#!/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)  
 | 
  
 | 
  
 |