| #!/usr/bin/python  | 
| # -*- coding: utf-8 -*-  | 
| #  | 
| ##@package  | 
| #  | 
| # @todo: 激活码  | 
| #  | 
| # @author: Alee  | 
| # @date 2018-5-4 22:10:51  | 
| # @version 1.0  | 
| #  | 
| # @note: 中文必须传utf8,收到的为urlencode内容  .decode('gbk').encode('utf8')  | 
| # 1.使用礼包卡号  | 
| #---------------------------------------------------------------------  | 
|   | 
| from bottle import Bottle, request, static_file  | 
| import md5  | 
| import CouponDB  | 
| import datetime  | 
| from lib import ReadConfig  | 
| import json  | 
| import urllib2  | 
| import urllib  | 
| from lib import mylog, CommFunc  | 
| import os.path  | 
| import zipfile  | 
| import time  | 
|   | 
| # get: request.query.username request.GET.get('username','')  | 
| # post: request.forms.get('username')  request.POST.get('username')  | 
| #===============================================================================  | 
| # @myapp.route('/cool/kk/:name3/:count#\\d+#')  | 
| # def maybe(name3, count):  | 
| # client_ip = request.environ.get('REMOTE_ADDR')  | 
| # client_ip = request.environ.get('HTTP_X_FORWARDED_FOR') or request.environ.get('REMOTE_ADDR')  | 
| #===============================================================================  | 
|   | 
| ConfigIO = ReadConfig.ReadConfig(os.getcwd() + "\\..\\Coupon\\config.ini")  | 
|   | 
| # 应用端口  | 
| CenterPort = ConfigIO.GetValue("Coupon", "CenterPort")  | 
| #mobiletest.173on.com:55000  | 
| Def_ExportUrl = ConfigIO.GetValue("Coupon", "exporturl") + "/Coupon/CouponLoad.php?couponid=%s&channel=%s"  | 
|   | 
| # GM端口  | 
| PushPort = ConfigIO.GetValue("Coupon", "PushPort")  | 
| PushKey = ConfigIO.GetValue("Coupon", "PushKey")  | 
| CommonCards = eval(ConfigIO.GetValue("Coupon", "CommonCards"))  | 
|                   | 
|           | 
| Def_CardMsg = {  | 
|                0:"CodeRewardSys2", #  兑换码无效  | 
|                1: "CodeRewardSys1", #   兑换卡奖励已发至邮件  | 
|                2:"CodeRewardSys3", #  兑换码已使用过  | 
|                3:"CodeRewardSys4",  # 同类型兑换码只能使用一次  | 
|          }  | 
|                   | 
|                   | 
|                   | 
| myapp = Bottle()  | 
|   | 
|   | 
|   | 
| #/api/Coupon/index.php?couponBatchId=%s&agentName=%s"  | 
| # 下载指定礼包批次   | 
| @myapp.route('/Coupon/CouponLoad.php')  | 
| def LoadCouponBatch():  | 
|     dataDict = request.GET  | 
|     appid = dataDict.get("channel", "")     # 运营提供的APPID,即渠道  | 
|     if not appid:  | 
|         mylog.debug("no appid")  | 
|         return json.dumps({"error":"param appid"}, ensure_ascii=False)  | 
|     couponid = dataDict.get("couponid", "")  | 
|     if not couponid:  | 
|         return json.dumps({"error":"param couponid"}, ensure_ascii=False)  | 
|       | 
|     downFile = r".\download\%s.zip"%couponid  | 
|     if os.path.isfile(downFile):  | 
|         return static_file("%s.zip"%couponid, r".\download", download=True)  | 
|       | 
|     dbController = CouponDB.GetDBEventCon()  | 
|     if not dbController:  | 
|         # 无法获取数据库  | 
|         mylog.debug("no dbController")  | 
|         return json.dumps({"error":"db"}, ensure_ascii=False)  | 
|     result, data = dbController.find(CouponDB.CouponCodeColName + "_" + appid, {'channel':appid, 'couponid':couponid})  | 
|     if not data:  | 
|         return json.dumps({"error":"no couponid"}, ensure_ascii=False)  | 
|       | 
|     fileIO = open(r".\download\%s.txt"%couponid, 'w')  | 
|   | 
|     for codeInfo in data:  | 
|         fileIO.write(codeInfo["code"] + "\n")  | 
|     fileIO.close()   | 
|       | 
|     f = zipfile.ZipFile(downFile, 'w', zipfile.ZIP_DEFLATED)  | 
|     f.write(r".\download\%s.txt"%couponid)  | 
|     f.close()  | 
|     return static_file("%s.zip"%couponid, r".\download", download=True)  | 
|   | 
|   | 
| #================客户端请求参数===============================================================  | 
| # channel    是    string    Appid 如jsgameios  | 
| # code    是    string    兑换码  | 
| # accid    是    string    账号  | 
| # spid    是    string    运营商ID,研发自己配置的,如jisu代表极速平台  | 
| # sid    是    int    服务器ID 数字  | 
| # pushurl    是    string    域名链接s222.xxx.com  | 
| # roleid    是    string    玩家游戏名  | 
| # level    是    int    玩家等级  | 
| # viplevel    是    Int    玩家VIP等级  | 
| #===============================================================================  | 
|   | 
| #2018.10.10 混服支持导致账号拼接逻辑变更需要spid  | 
| # 卡类型 开头字母做标识如 g1~999代表此卡只能使用一次 h1~999卡可以重复使用 z开头代表固定码 wx开头代表微信商店  | 
| # 玩家使用卡号 参数 平台 区服 账号 区服链接(GM用)卡号  | 
| # http://center.xxx.com:53003/Coupon/CouponCode.php  | 
| @myapp.route('/Coupon/CouponCode.php')  | 
| def CouponCode():  | 
|     dataDict = request.GET  | 
|       | 
|     for key, value in dataDict.items():  | 
|         mylog.debug("CouponCode key:%s  value:%s"%(key, value))  | 
|       | 
|     agentName = dataDict.get("channel", "")     # 运营提供的APPID,即渠道  | 
|     if not agentName:  | 
|         mylog.debug("no appid")  | 
|         return  | 
|     codeStr = dataDict.get("code", "")  | 
|     if not codeStr:  | 
|         return  | 
|       | 
|     spID = dataDict.get("spid", "")  | 
|     if not spID:  | 
|         tdict = {"jisugame":"jisu", 'spxjgame':'sipu', 'mrgame':'maoer',  | 
|                  "jisugameios":"jisu", 'spyxxjios':'sipu', 'mrgameios':'maoer'}  | 
|           | 
|         # 没传的话默认和appid一样  | 
|         spID = tdict.get(agentName, agentName)  | 
|           | 
|     accid = dataDict.get("accid", "")  | 
|     if not accid:  | 
|         return  | 
|       | 
|     sid = CommFunc.ToIntDef(dataDict.get("sid", 0), 0)  | 
|     if not sid:  | 
|         return  | 
|     pushurl = dataDict.get("pushurl", "")  | 
|     if not pushurl:  | 
|         return  | 
|       | 
|     # 转化为游戏账号   | 
|     accid = "%s@%s@s%s"%(accid.lower(), spID, sid)  | 
|       | 
|     dbController = CouponDB.GetDBEventCon()  | 
|     if not dbController:  | 
|         # 无法获取数据库  | 
|         mylog.debug("no dbController")  | 
|         return  | 
|   | 
|     #通过GM接口告知玩家使用情况  | 
|     gmresult = {'accID':accid, 'sid':sid, 'channel':agentName}  | 
|   | 
|     #-----------统一固定码处理----------------------  | 
|     if codeStr in CommonCards:  | 
|         # 不同固定码各自只能领一次  | 
|         result, commondata = dbController.find_one(CouponDB.CouponCodeColName + "_Common", {"code":codeStr, "accid":accid})  | 
|         if commondata:  | 
|             # 已使用  | 
|             gmresult['status'] = 2  | 
|             mylog.debug("common status=2")  | 
|             return SendGm(gmresult, pushurl)  | 
|           | 
|         gmresult['status'] = 1  | 
|         gmresult['code'] = codeStr  | 
|         gmresult['coupontype'] = codeStr  # 统一格式,服务器不一定有用,固定码根据 codeStr 发奖励  | 
|           | 
|         dbController.insert(CouponDB.CouponCodeColName + "_Common", {"code":codeStr, "accid":accid})  | 
|         mylog.debug("common ok")  | 
|         return SendGm(gmresult, pushurl)  | 
|   | 
|     #-----------微信商城----------------------  | 
|     if codeStr.startswith('wx'):  | 
|         operateID = GetOperateID(agentName)  | 
|         if not operateID:  | 
|             mylog.debug("wx no appid  = %s"%agentName)  | 
|             return  | 
|         result, wxdata = dbController.find_one(CouponDB.CouponWXColName, {"code":codeStr, "operateid":operateID})  | 
|         if not wxdata:  | 
|             return  | 
|           | 
|         if int(wxdata['status']) == 1:  | 
|             gmresult['status'] = 2  | 
|             mylog.debug("wxcard used!")  | 
|             return SendGm(gmresult, pushurl)  | 
|           | 
|         wxdata['status'] = 1  | 
|         wxdata['accid'] = dataDict.get("accid", "")     # 此处用原始账号  | 
|         wxdata['usetime'] = str(datetime.datetime.today()).split(".")[0]  | 
|           | 
|         wxdata['appid'] = agentName  | 
|         wxdata['serverid'] = 's%s'%sid  | 
|         wxdata['roleid'] = dataDict.get("roleid", "")  | 
|         wxdata['level'] = dataDict.get("level", "")  | 
|         wxdata['viplevel'] = dataDict.get("viplevel", "")  | 
|         if SendWXBill(wxdata, pushurl):  | 
|             # 充值成功  | 
|             dbController.update(CouponDB.CouponWXColName, {"code":codeStr, "operateid":operateID}, wxdata)  | 
|             # 通知后台记录  | 
|             SendDataCollectorBillInfo(wxdata, pushurl, operateID)  | 
|         return   | 
|       | 
|       | 
|     #-----------批量兑换码处理----------------------  | 
|     result, data = dbController.find_one(CouponDB.CouponCodeColName + "_" + agentName, {"code":codeStr, "channel":agentName})  | 
|   | 
|     if not data:  | 
|         #无此卡  | 
|         gmresult['status'] = 0  | 
|         mylog.debug("no card")  | 
|         return SendGm(gmresult, pushurl)  | 
|     if int(data['status']) == 1:  | 
|         #已使用,同卡号记录默认可用,避免断线发送失败的情况(未返回结果验证情况下)  | 
|         gmresult['status'] = 2  | 
|         mylog.debug("card used!")  | 
|         return SendGm(gmresult, pushurl)  | 
|       | 
|     result, data2 = dbController.find_one(CouponDB.CouponBatchColName, {"couponid":data["couponid"]})  | 
|     if not data2:  | 
|         #此批次卡已删除  | 
|         gmresult['status'] = 0  | 
|         mylog.debug("no couponid")  | 
|         return SendGm(gmresult, pushurl)  | 
|     if int(data2['status']) == 1:  | 
|         #暂停使用该批次卡  | 
|         gmresult['status'] = 0  | 
|         mylog.debug("couponid frozed")  | 
|         return SendGm(gmresult, pushurl)  | 
|     if (data2["minserverno"] != 0 and data2["maxserverno"] != 0):  | 
|         if int(data2["minserverno"]) > sid or int(data2["maxserverno"]) < sid:  | 
|             #不在指定区  | 
|             gmresult['status'] = 0  | 
|             mylog.debug("no sid")  | 
|             return SendGm(gmresult, pushurl)  | 
|     if data2["expiretime"] != "" and datetime.datetime.today() > GetDateTimeByStr(data2["expiretime"]):  | 
|         #已过期  | 
|         gmresult['status'] = 0  | 
|         mylog.debug("time pass")  | 
|         return SendGm(gmresult, pushurl)  | 
|     #再查一次是否用过此批次的其他卡,   | 
|     result, data3 = dbController.find_one(CouponDB.CouponCodeColName + "_" + agentName, \  | 
|                                           {"couponid":data["couponid"], "accid":accid})  | 
|     if data3:  | 
|         #用过同类卡,已记录过不再做新记录  | 
|         gmresult['status'] = 3  | 
|         gmresult['coupontype'] = data["coupontype"]  | 
|         gmresult['code'] = codeStr  | 
|         mylog.debug("use again")  | 
|         return SendGm(gmresult, pushurl)  | 
|       | 
|     data['status'] = 1  | 
|     data['accid'] = accid  | 
|     data['usetime'] = str(datetime.datetime.today())  | 
|       | 
|     dbController.update(CouponDB.CouponCodeColName + "_" + agentName, {"code":codeStr, "channel":agentName}, data)  | 
|     # 0 不可用,1.可用发放奖励 ,2.已使用 3.同类型卡不能使用两次  | 
|     gmresult['status'] = 1  | 
|     gmresult['code'] = codeStr  | 
|     gmresult['coupontype'] = data["coupontype"]  | 
|       | 
|     mylog.debug("card ok!")  | 
|     return SendGm(gmresult, pushurl)  | 
|   | 
|   | 
|   | 
| def SendGm(gmresult, pushurl):  | 
|     try:  | 
|         # GM推送地址  | 
|         #GMToolPage = http://s1.yhlz.09ge.com:30001/Server/Tool.php  | 
|         gmurl = "http://%s:%s/Server/Tool.php"%(pushurl, PushPort)  | 
|         gmkey = PushKey  | 
|         if not gmkey or not gmurl:  | 
|             return  | 
|           | 
|         useStatus = gmresult['status']  | 
|           | 
|         gmresult['notifyMsg'] = Def_CardMsg.get(useStatus, "CodeRewardSys2")  | 
|           | 
|           | 
|         if useStatus != 1:  | 
|             #失败系统提示  | 
|             pack_data = {};  | 
|             pack_data["queryType"] = "accID"  | 
|             pack_data["playerFind"] = gmresult["accID"]  | 
|             pack_data["pack_type"] = "GMT_MediaCard"  | 
|             pack_data["notifyMsg"] = gmresult['notifyMsg']  | 
|           | 
|             pack_data["key"] = gmkey;  | 
|             pack_data['coding'] = "utf8";  | 
|           | 
|             #使用key加密  | 
|             pack_data_dict = json.dumps(pack_data)  | 
|             sign = md5.md5(pack_data_dict+gmkey).hexdigest()  | 
|             post = {}  | 
|             post['pack'] = pack_data_dict;  | 
|             post['sign'] = sign;  | 
|             urllib2.urlopen(gmurl, urllib.urlencode(post), 3)  | 
|             return  | 
|           | 
|         mylog.debug("SendGm:%s"%gmurl)  | 
|         pack_data = {};  | 
|         pack_data["queryType"] = "accID"  | 
|         pack_data["playerList"] = gmresult["accID"]  | 
|         pack_data["Title"] = ConfigIO.GetValue(gmresult["coupontype"], "MailTitle").decode("gbk")  | 
|         pack_data["Text"] = ConfigIO.GetValue(gmresult["coupontype"], "MailText").decode("gbk")  | 
|         pack_data["EndTime"] = str(datetime.datetime.today() + datetime.timedelta(days=15)).split('.')[0]  | 
|         pack_data["Sender"] = ConfigIO.GetValue(gmresult["coupontype"], "MailSender").decode("gbk")  | 
|   | 
|           | 
|         Items =  eval(ConfigIO.GetValue(gmresult["coupontype"], "Items"))  | 
|         pack_data["itemNums"] = ','.join([str(i) for i in range(len(Items))])  | 
|         i = 0  | 
|         for itemList in Items:  | 
|             pack_data["ItemID%s"%i] = str(itemList[0])  | 
|             pack_data["ItemCnt%s"%i] = str(itemList[1])  | 
|             pack_data["IsBind%s"%i] = '1'  | 
|             i += 1  | 
|               | 
|         pack_data["pack_type"] = "GMT_AddPersonalCompensation"  | 
|         pack_data["Detail"] = "cardCode:" + gmresult["code"]  | 
|   | 
|         pack_data["key"] = gmkey;  | 
|         pack_data['coding'] = "utf8";  | 
|       | 
|         #使用key加密  | 
|         pack_data_dict = json.dumps(pack_data)  | 
|         sign = md5.md5(pack_data_dict+gmkey).hexdigest()  | 
|         post = {}  | 
|         post['pack'] = pack_data_dict;  | 
|         post['sign'] = sign;  | 
|         result = urllib2.urlopen(gmurl, urllib.urlencode(post), 10)  | 
|   | 
|         content = result.read()  | 
|         result.close()  | 
|           | 
|         # 成功提示  | 
|         pack_data = {};  | 
|         pack_data["queryType"] = "accID"  | 
|         pack_data["playerFind"] = gmresult["accID"]  | 
|         pack_data["pack_type"] = "GMT_MediaCard"  | 
|         pack_data["notifyMsg"] = gmresult['notifyMsg']  | 
|       | 
|         pack_data["key"] = gmkey;  | 
|         pack_data['coding'] = "utf8";  | 
|       | 
|         #使用key加密  | 
|         pack_data_dict = json.dumps(pack_data)  | 
|         sign = md5.md5(pack_data_dict+gmkey).hexdigest()  | 
|         post = {}  | 
|         post['pack'] = pack_data_dict;  | 
|         post['sign'] = sign;  | 
|         urllib2.urlopen(gmurl, urllib.urlencode(post), 3)  | 
|           | 
|         return content  | 
|     except Exception, e:  | 
|         mylog.debug("gm error %s"%e)  | 
|     return  | 
|       | 
|       | 
| def GetDateTimeByStr(timeStr, timeFomat="%Y-%m-%d"):  | 
|     try:  | 
|         return datetime.datetime.strptime(timeStr, timeFomat)  | 
|       | 
|     except:  | 
|         mylog.debug("GetDateTimeByStr error %s"%timeStr)  | 
|       | 
|     return  | 
|       | 
|   | 
| # 通过appid找到运营商  | 
| def GetOperateID(appid):  | 
|     appidDict = eval(ConfigIO.GetValue("Coupon", "appid_dict"))  | 
|     for key, value in appidDict.items():  | 
|         if appid in value:  | 
|             return key  | 
|     return ""  | 
|   | 
|   | 
|   | 
| # 微信入口充值  | 
| def SendWXBill(wxdata, pushurl):  | 
|     try:  | 
|         billurl = "http://%s/api/exchange/index.php"%pushurl  | 
|   | 
|         post = {}  | 
|         post['AccountID'] = wxdata['accid']  | 
|         post['RegionName'] = wxdata['serverid']   | 
|         post['OrderAmount'] = wxdata['money']   | 
|         post['BillNO'] = wxdata['orderid']   | 
|         post['OrderInfo'] = wxdata['orderinfo']   | 
|         post['OperatorID'] = wxdata['appid']   | 
|           | 
|         key = ConfigIO.GetValue("Coupon", "key_%s"%post['OperatorID'])  | 
|         # $sign=md5($AccountID.$OrderAmount.$BillNO.$RegionName.$key)  | 
|         mylog.debug("appid = %s  key = %s"%(post['OperatorID'], key))  | 
|           | 
|         sign = md5.md5(post['AccountID'] + str(post['OrderAmount']) + post['BillNO'] + post['RegionName'] + key).hexdigest()  | 
|           | 
|         post['Sign'] = sign  | 
|         result = urllib2.urlopen(billurl, urllib.urlencode(post), 3)  | 
|         resultDict = json.loads(result.read())  | 
|           | 
|         mylog.debug("resultDict = %s "%(resultDict))  | 
|   | 
|         if int(resultDict["errorcode"]) > 0:  | 
|             return True  | 
|     except Exception, e:  | 
|         mylog.info("SendWXBill error %s"%e)  | 
|     return False  | 
|   | 
| # 通知后台数据中心记录  | 
| def SendDataCollectorBillInfo(wxdata, pushurl, operateID):  | 
|     try:  | 
|         billurl = "http://recharge.game.2460web.com:12000/api/notify/swwx"  | 
|       | 
|         post = {}  | 
|         post['appid'] = wxdata['appid']  | 
|         post['regionid'] = wxdata['serverid']   | 
|         post['orderid'] = wxdata['orderid']   | 
|         post['passport'] = wxdata['accid']   | 
|         post['roleid'] =  wxdata['roleid']  | 
|         post['ordertitle'] = wxdata['ordertitle'].encode("UTF8")  | 
|         post['orderinfo'] = wxdata['orderinfo']  | 
|         post['money'] = wxdata['money']   | 
|         post['ip'] = wxdata['ip']   | 
|         post['level'] = wxdata['level']   | 
|         post['viplevel'] = wxdata['viplevel']   | 
|         post['time'] = int(time.time())  | 
|           | 
|         key = ConfigIO.GetValue("Coupon", "key_%s"%post['appid'])  | 
|         #md5(appid=$appid®ionid=$regionid&passport=$passport&&money=$money&time=$time$app_secret)   | 
|         signStr = "appid=%s®ionid=%s&passport=%s&money=%s&time=%s%s"%(\  | 
|                     post['appid'], post['regionid'], post['passport'], post['money'], post['time'], key)  | 
|         sign = md5.md5(signStr).hexdigest()  | 
|         #mylog.debug("SendDataCollectorBillInfo  %s-%s-%s-%s"%(signStr, sign, key, post))  | 
|         post['sign'] = sign  | 
|         result = urllib2.urlopen(billurl +"?" + urllib.urlencode(post), timeout =3)  | 
|         #mylog.debug("SendDataCollectorBillInfo result %s"%result.read())  | 
|   | 
|     except Exception, e:  | 
|         mylog.debug("SendDataCollectorBillInfo error %s"%e)  | 
|   | 
|   |