| #!/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  | 
| import traceback  | 
|   | 
| # 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")  | 
| PushTimeout = ConfigIO.GetInt("Coupon", "PushTimeout", 5)  | 
| CommonCards = eval(ConfigIO.GetValue("Coupon", "CommonCards"))  | 
|   | 
| # 发放奖励邮件内容json,utf8编码  | 
| f = open(os.getcwd() + "\\..\\Coupon\\CodeMail.json", "r")  | 
| MailJson = eval(f.read())  | 
| f.close()  | 
|   | 
| # 礼包使用返回结果码定义  | 
| ErrCode_OK = 0 # 成功,非0的码均代表错误  | 
| ErrCode_Invalid = 1 # 兑换码无效  | 
| ErrCode_Used = 2 # 礼包码已被使用  | 
| ErrCode_TypeUsed = 3 # 已经使用过同类型的礼包码  | 
| ErrCode_LVLimit = 4 # 等级不足  | 
| ErrCode_VIPLVLimit = 5 # VIP等级不足  | 
| ErrCode_ParamErr = 97 # 参数错误  | 
| ErrCode_FrequentRequest = 98 # 频繁请求  | 
| ErrCode_OtherErr = 99 # 其他错误,比如运行错误等  | 
|   | 
| # 礼包码处理结果码信息 {code:["码信息说明", "给玩家的系统提示key"], ...}  | 
| ErrCodeMsgInfo = {  | 
|                   ErrCode_OK:["OK", "CodeRewardSys1"],  | 
|                   ErrCode_Invalid:["code invalid", "CodeRewardSys2"],  | 
|                   ErrCode_Used:["code has been used", "CodeRewardSys3"],  | 
|                   ErrCode_TypeUsed:["You has been used this Giftcode type", "CodeRewardSys4"],  | 
|                   ErrCode_LVLimit:["level limit", "LvErr"],  | 
|                   ErrCode_VIPLVLimit:["vip level limit", "VipLevel"],  | 
|                   ErrCode_ParamErr:["parameter error", ""],  | 
|                   ErrCode_FrequentRequest:["frequent request", ""],  | 
|                   ErrCode_OtherErr:["other error", ""],  | 
|                   }  | 
|   | 
| def CouponCodeResponse(errcode, msgEx=""):  | 
|     errmsg = ""  | 
|     if errcode in ErrCodeMsgInfo:  | 
|         errmsg = ErrCodeMsgInfo[errcode][0]  | 
|     if msgEx:  | 
|         errmsg = "%s : %s" % (errmsg, msgEx)  | 
|     resData = {"errcode":errcode, "errmsg":errmsg}  | 
|     if errcode != ErrCode_OK:  | 
|         mylog.error("resError: %s" % str(resData))  | 
|     else:  | 
|         mylog.debug("resData: %s" % str(resData))  | 
|         #mylog.info("resData: %s" % str(resData))  | 
|     return json.dumps(resData, ensure_ascii=False)  | 
|   | 
|                   | 
| myapp = Bottle()  | 
|   | 
| # 防止短时间内的多次无效访问 accid:time  | 
| AccID_Cache_Dict = {}  | 
|   | 
| def CleanAccID():  | 
|     global AccID_Cache_Dict  | 
|       | 
|     if len(AccID_Cache_Dict) < 100:  | 
|         return   | 
|     AccID_Cache_Dict = {}  | 
|   | 
|   | 
| #/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():  | 
|     global AccID_Cache_Dict  | 
|     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:  | 
|         return CouponCodeResponse(ErrCode_ParamErr, "no channel appid")  | 
|     codeStr = dataDict.get("code", "")  | 
|     if not codeStr:  | 
|         return CouponCodeResponse(ErrCode_ParamErr, "no code")  | 
|     codeStr = codeStr.strip()  | 
|     #只是用来拼接账号  | 
|     spID = dataDict.get("spid", "")  | 
|     if not spID:  | 
|         return CouponCodeResponse(ErrCode_ParamErr, "no spid")  | 
|       | 
|     accid = dataDict.get("accid", "")  | 
|     if not accid:  | 
|         return CouponCodeResponse(ErrCode_ParamErr, "no accid")  | 
|       | 
|     sid = CommFunc.ToIntDef(dataDict.get("sid", 0), 0)  | 
|     if not sid:  | 
|         return CouponCodeResponse(ErrCode_ParamErr, "no sid")  | 
|     pushurl = dataDict.get("pushurl", "")  | 
|     if not pushurl:  | 
|         return CouponCodeResponse(ErrCode_ParamErr, "no pushurl")  | 
|       | 
|     # 转化为游戏账号   | 
|     accid = "%s@%s@s%s" % (accid.lower(), spID, sid)  | 
|       | 
|     try:  | 
|         CleanAccID()  | 
|         #mylog.debug("AccID_Cache_Dict : %s"%str(AccID_Cache_Dict))  | 
|         if accid not in AccID_Cache_Dict:  | 
|             AccID_Cache_Dict[accid] = int(time.time())  | 
|         elif time.time() - AccID_Cache_Dict[accid] < 2:  | 
|             mylog.debug("==========bad: fast click  %s" % accid)  | 
|             return CouponCodeResponse(ErrCode_FrequentRequest)  | 
|               | 
|         AccID_Cache_Dict[accid] = int(time.time())  | 
|     except:  | 
|         pass  | 
|       | 
|       | 
|     dbController = CouponDB.GetDBEventCon()  | 
|     if not dbController:  | 
|         # 无法获取数据库  | 
|         return CouponCodeResponse(ErrCode_OtherErr, "no dbController")  | 
|       | 
|     #通过GM接口告知玩家使用情况  | 
|     gmresult = {'accID':accid, 'sid':sid, 'channel':agentName}  | 
|       | 
|     #-----------统一固定码处理----------------------  | 
|     CommonCardsList = CommonCards.get(agentName, [])  | 
|     if codeStr in CommonCardsList:  | 
|         # 不同固定码各自只能领一次  | 
|         result, commondata = dbController.find_one(CouponDB.CouponCodeColName + "_Common", {"code":codeStr, "accid":accid})  | 
|         if commondata:  | 
|             # 已使用  | 
|             return SendGm(ErrCode_Used, gmresult, pushurl)[1]  | 
|           | 
|         commCheckStatus = CommCheck(dataDict, codeStr)  | 
|         if commCheckStatus != None:  | 
|             return SendGm(commCheckStatus, gmresult, pushurl)[1]  | 
|           | 
|         gmresult['code'] = codeStr  | 
|         gmresult['coupontype'] = codeStr  # 统一格式,服务器不一定有用,固定码根据 codeStr 发奖励  | 
|           | 
|         retCode, retMsg = SendGm(ErrCode_OK, gmresult, pushurl)  | 
|         if retCode == ErrCode_OK:  | 
|             dbController.insert(CouponDB.CouponCodeColName + "_Common", {"code":codeStr, "accid":accid})  | 
|             mylog.debug("common ok")  | 
|         return retMsg  | 
|       | 
|     #-----------微信商城----------------------  | 
|     if codeStr.startswith('wx'):  | 
|         operateID = GetOperateID(agentName)  | 
|         if not operateID:  | 
|             return CouponCodeResponse(ErrCode_OtherErr, "wx no appid  = %s" % agentName)  | 
|         result, wxdata = dbController.find_one(CouponDB.CouponWXColName, {"code":codeStr, "operateid":operateID})  | 
|         if not wxdata:  | 
|             return CouponCodeResponse(ErrCode_OtherErr, "not wxdata code(%s) operateID(%s)" % (codeStr, operateID))  | 
|           | 
|         if int(wxdata['status']) == 1:  | 
|             mylog.debug("wxcard used!")  | 
|             return SendGm(ErrCode_Used, gmresult, pushurl)[1]  | 
|           | 
|         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 CouponCodeResponse(ErrCode_OK)  | 
|         return CouponCodeResponse(ErrCode_OtherErr, "SendWXBill error")  | 
|       | 
|     #-----------批量兑换码处理,同类型只领取一次----------------------  | 
|     result, data = dbController.find_one(CouponDB.CouponCodeColName + "_" + agentName, {"code":codeStr, "channel":agentName})  | 
|       | 
|     if not data:  | 
|         #无此卡  | 
|         mylog.debug("no card")  | 
|         return SendGm(ErrCode_Invalid, gmresult, pushurl)[1]  | 
|     if int(data['status']) == 1:  | 
|         #已使用,同卡号记录默认可用,避免断线发送失败的情况(未返回结果验证情况下)  | 
|         mylog.debug("card used!")  | 
|         return SendGm(ErrCode_Used, gmresult, pushurl)[1]  | 
|           | 
|     couponType = data["coupontype"]  | 
|     commCheckStatus = CommCheck(dataDict, data["coupontype"])  | 
|     if commCheckStatus != None:  | 
|         return SendGm(commCheckStatus, gmresult, pushurl)[1]  | 
|       | 
|     result, data2 = dbController.find_one(CouponDB.CouponBatchColName, {"couponid":data["couponid"]})  | 
|     if not data2:  | 
|         #此批次卡已删除  | 
|         mylog.debug("no couponid")  | 
|         return SendGm(ErrCode_Invalid, gmresult, pushurl)[1]  | 
|     if int(data2['status']) == 1:  | 
|         #暂停使用该批次卡  | 
|         mylog.debug("couponid frozed")  | 
|         return SendGm(ErrCode_Invalid, gmresult, pushurl)[1]  | 
|     if (data2["minserverno"] != 0 and data2["maxserverno"] != 0):  | 
|         if int(data2["minserverno"]) > sid or int(data2["maxserverno"]) < sid:  | 
|             #不在指定区  | 
|             mylog.debug("no sid")  | 
|             return SendGm(ErrCode_Invalid, gmresult, pushurl)[1]  | 
|     if data2["expiretime"] != "" and datetime.datetime.today() > GetDateTimeByStr(data2["expiretime"]):  | 
|         #已过期  | 
|         mylog.debug("time pass")  | 
|         return SendGm(ErrCode_Invalid, gmresult, pushurl)[1]  | 
|       | 
|     prefix = "" # 固定前缀  | 
|     if couponType in MailJson:  | 
|         mailInfo = MailJson[couponType]  | 
|         prefix = mailInfo.get("Prefix", "")  | 
|     elif ConfigIO.HasSection(couponType):  | 
|         if ConfigIO.HasOption(couponType, "Prefix"):  | 
|             prefix = ConfigIO.GetValue(couponType, "Prefix")  | 
|               | 
|     # h 开头的卡类型可重复使用  | 
|     if not codeStr.startswith(prefix + 'h'):  | 
|         #再查一次是否用过此批次的其他卡,   | 
|         result, data3 = dbController.find_one(CouponDB.CouponCodeColName + "_" + agentName, \  | 
|                                               {"coupontype":data["coupontype"], "accid":accid})  | 
|         if data3:  | 
|             #用过同类卡,已记录过不再做新记录  | 
|             gmresult['coupontype'] = data["coupontype"]  | 
|             gmresult['code'] = codeStr  | 
|             mylog.debug("use again")  | 
|             return SendGm(ErrCode_TypeUsed, gmresult, pushurl)[1]  | 
|           | 
|     data['status'] = 1  | 
|     data['accid'] = accid  | 
|     data['usetime'] = str(datetime.datetime.today())  | 
|       | 
|     gmresult['code'] = codeStr  | 
|     gmresult['coupontype'] = data["coupontype"]  | 
|       | 
|     retCode, retMsg = SendGm(ErrCode_OK, gmresult, pushurl)  | 
|     if retCode == ErrCode_OK:  | 
|         dbController.update(CouponDB.CouponCodeColName + "_" + agentName, {"code":codeStr, "channel":agentName}, data)  | 
|         mylog.debug("card ok!")  | 
|     return retMsg  | 
|   | 
| def CommCheck(dataDict, coupontype):  | 
|     ## 通用常规检查  | 
|       | 
|     if coupontype in MailJson:  | 
|         mailInfo = MailJson[coupontype]  | 
|         lvLimit = mailInfo.get("LV", 0)  | 
|         vipLVLimit = mailInfo.get("VIPLV", 0)  | 
|     else:  | 
|         lvLimit = ConfigIO.GetInt(coupontype, "LV")  | 
|         vipLVLimit = ConfigIO.GetInt(coupontype, "VIPLV")  | 
|           | 
|     # 使用等级  | 
|     playerLV = CommFunc.ToIntDef(dataDict.get("level", 0))  | 
|     if lvLimit > 0 and playerLV < lvLimit:  | 
|         mylog.debug("playerLV(%s) < lvLimit(%s)" % (playerLV, lvLimit))  | 
|         return ErrCode_LVLimit  | 
|       | 
|     # vip等级相关  | 
|     playerVIPLV = CommFunc.ToIntDef(dataDict.get("viplevel", 0))  | 
|     if vipLVLimit > 0 and playerVIPLV < vipLVLimit:  | 
|         mylog.debug("playerVIPLV(%s) < vipLVLimit(%s)" % (playerVIPLV, vipLVLimit))  | 
|         return ErrCode_VIPLVLimit  | 
|       | 
|     return  | 
|   | 
| def SendGm(errcode, gmresult, pushurl):  | 
|     try:  | 
|         # GM推送地址  | 
|         #GMToolPage = http://s1.yhlz.09ge.com:30001/Server/Tool.php  | 
|         # 兼容两种入口,一种客户端只发服务器域名的,一种GM工具直接读取的服务器GM工具地址  | 
|         if pushurl.endswith("Tool.php"):  | 
|             gmurl = pushurl  | 
|         else:  | 
|             gmurl = "http://%s:%s/Server/Tool.php" % (pushurl, PushPort)              | 
|         gmkey = PushKey  | 
|         if not gmkey or not PushPort:  | 
|             return ErrCode_OtherErr, CouponCodeResponse(ErrCode_OtherErr, "no PushKey or not PushPort")  | 
|         mylog.debug("SendGm:%s" % gmurl)  | 
|           | 
|         notifyMsg = ""  | 
|         if errcode in ErrCodeMsgInfo:  | 
|             notifyMsg = ErrCodeMsgInfo[errcode][1]  | 
|         if not notifyMsg:  | 
|             notifyMsg = "CodeRewardSys2"  | 
|               | 
|         if notifyMsg:  | 
|             gmtData = {"queryType":"accID", "playerFind":gmresult["accID"], "notifyMsg":notifyMsg}  | 
|             SendGMTCMD(gmurl, gmtData, gmkey, "GMT_MediaCard")  | 
|               | 
|         if errcode != ErrCode_OK:  | 
|             return errcode, CouponCodeResponse(errcode)  | 
|           | 
|         coupontype = gmresult["coupontype"]  | 
|         if coupontype in MailJson:  | 
|             mailInfo = MailJson[coupontype]  | 
|             mailTitle = mailInfo.get("MailTitle", "MailTitle")  | 
|             mailText = mailInfo.get("MailText", "")  | 
|             mailSender = mailInfo.get("MailSender", "System")  | 
|             mailItems = mailInfo.get("Items", [])  | 
|         else:  | 
|             mailTitle = ConfigIO.GetValue(gmresult["coupontype"], "MailTitle").decode("gbk")  | 
|             mailText = ConfigIO.GetValue(gmresult["coupontype"], "MailText").decode("gbk")  | 
|             mailSender = ConfigIO.GetValue(gmresult["coupontype"], "MailSender").decode("gbk")  | 
|             mailItems = eval(ConfigIO.GetValue(gmresult["coupontype"], "Items"))  | 
|         pack_data = {}  | 
|         pack_data["queryType"] = "accID"  | 
|         pack_data["playerList"] = gmresult["accID"]  | 
|         pack_data["Title"] = mailTitle  | 
|         pack_data["Text"] = mailText  | 
|         pack_data["EndTime"] = str(datetime.datetime.today() + datetime.timedelta(days=15)).split('.')[0]  | 
|         pack_data["Sender"] = mailSender  | 
|           | 
|         Items = mailItems  | 
|         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] = str(itemList[2] if len(itemList) > 2 else 0)  | 
|             i += 1  | 
|               | 
|         pack_data["Detail"] = "cardCode:" + gmresult["code"]  | 
|           | 
|         ResultType = SendGMTCMD(gmurl, pack_data, gmkey, "GMT_AddPersonalCompensation")  | 
|         if ResultType == 0:  | 
|             return ErrCode_OK, CouponCodeResponse(ErrCode_OK)  | 
|         else:  | 
|             return ErrCode_OtherErr, CouponCodeResponse(ErrCode_OtherErr, "ResultType error is %s" % ResultType)  | 
|     except BaseException:  | 
|         mylog.error("SendGm error %s" % traceback.format_exc())  | 
|     return ErrCode_OtherErr, CouponCodeResponse(ErrCode_OtherErr, "gm error")  | 
|   | 
| def SendGMTCMD(gmurl, gmtData, gmkey, pack_type):  | 
|     ## 发送GM工具命令  | 
|     pack_data = {}  | 
|     if gmtData and isinstance(gmtData, dict):  | 
|         pack_data.update(gmtData)  | 
|     pack_data["pack_type"] = pack_type  | 
|     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), PushTimeout)  | 
|     retContent = result.read()  | 
|     resultDict = json.loads(retContent)  | 
|     result.close()  | 
|     ResultType = resultDict.get("ResultType", 5) # 5未知错误  | 
|     return ResultType  | 
|   | 
|       | 
| 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)  | 
|   | 
|   | 
| # 查询审核时间  | 
| @myapp.route('/auditdate.php')  | 
| def QueryAuditdate():  | 
|     return "2021-06-22 11:30:00"  |