hch
2018-10-18 0a70259aa5a019920767b43fc23374ebf30b9b85
fix:新增微信商城,注意兑换码不能用多线程有可能发生复用bug
6个文件已修改
521 ■■■■ 已修改文件
Tool/WebCenter/Coupon/CouponDB.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/WebCenter/Coupon/config.ini 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/WebCenter/Coupon/webapp.py 373 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/WebCenter/CouponCode/CouponDB.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/WebCenter/CouponCode/main.py 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/WebCenter/CouponCode/webapp.py 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tool/WebCenter/Coupon/CouponDB.py
@@ -21,6 +21,8 @@
g_dbController = None
CouponWXColName = "tagCouponWXSC"   # 微信商城
CouponBatchColName = "tagCouponBatch"
CouponCodeColName = "tagCouponCode"
ModuleName = "CouponDB"
Tool/WebCenter/Coupon/config.ini
@@ -23,8 +23,16 @@
;CommonCards = ["zj98u2j0ud1"]
CommonCards = []
;微信商城购物key
zyxh_wxkey = dcdce6dj
;苹果appid充值key
key_424064855 = 3ecd1
key_815035927 = b552a
;只允许配置IOS的APPID,如自由星河下有多个苹果appid共用则都要配置
appid_dict = {"zyxh":["424064855", "815035927"]}
;----------------------------------------------------------------------------------------------------
;公共固定码,所有人用同一个码,每个人只能领取一次
;[zj98u2j0ud1]
Tool/WebCenter/Coupon/webapp.py
@@ -211,42 +211,6 @@
    
    return json.dumps({"success":couponid}, ensure_ascii=False)
#/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)
# 查询卡使用情况
@myapp.route('/Coupon/QueryCouponCode.php')
@@ -271,219 +235,6 @@
    
    return json.dumps(data, ensure_ascii=False)
# 卡类型 开头字母做标识如 g1~999代表此卡只能使用一次 h1~999卡可以重复使用 z开头代表固定码
# 玩家使用卡号 参数 平台 区服 账号 区服链接(GM用)卡号
# http://center.xxx.com:53003/Coupon/CouponCode.php?channel=appid&code=XXX&accid=YYY&sid=222&pushurl=s222.xxx.com
@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
    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, agentName, 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)
    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:
@@ -494,3 +245,127 @@
    
    return
    
#=================游戏服务器记录==========================================================
# $arrayInsert=array( '_id'=>$orderID, 'ServerID'=>$getServer_id,
#                    'AccID'=>$qid, 'OrderAmount'=>$nOrderAmount,
#                    'OrderID'=>$orderID, 'Sign'=>$recvSign,
#                    'BeginOrderTime'=>date("Y-m-d H:i:s"), 'EndOrderTime'=>0,
#                    'IsProcess'=>0, "OrderInfo"=>$DataArray['OrderInfo']);
#===========================================================================
#=================后台数据记录==========================================================
# appid    是    string    微信商城用户选择的平台appid
# regionid    是    string    区服ID:  s8001
# orderid    是    string    微信商城订单号不能与充值订单重复
# passport    是    string    玩家游戏帐号
# roleid    是    string    角色名称
# ordertitle    是    string    订单标题,例如:  128元礼包
# orderinfo    是    string    订单信息, 例如:  snxxz.18
# money    是    float    付款数保留两位小数
# ip    是    string    玩家IP,可空值
# level    是    string    等级
# viplevel    是    string    VIP等级
# time    是    string    充值时间戳 例如: 1539447585
# sign    是    string    签名
#===========================================================================
#http://center.2460web.com:53002/Coupon/CouponWXBill.php
#微信商城 参数 ordertitle orderinfo orderid count money(保留两位小数)sign ip time(补发不更新时间)
@myapp.route('/Coupon/CouponWXBill.php', method='POST')
def CouponWXBill():
    dataDict = request.POST
    for key, value in dataDict.items():
        mylog.debug("key:%s  value:%s"%(key, value))
    channel = "zyxh"  # 需支持多个appid,一个订单一个激活码
    orderID = dataDict.get("orderid", "")    # 订单,根据数量分支出多个订单对应一个激活码
    if not orderID:
        return json.dumps({"error":"param orderid"}, ensure_ascii=False)
    orderInfo = dataDict.get("orderinfo", "")    # 商品编号
    if not orderInfo:
        return json.dumps({"error":"param orderInfo"}, ensure_ascii=False)
    count = int(dataDict.get("count", 0))     # 礼包数量
    if count <= 0:
        return json.dumps({"error":"param count"}, ensure_ascii=False)
    money = float(dataDict.get("money", 0))     # 价格
    if money <= 0:
        return json.dumps({"error":"param money"}, ensure_ascii=False)
    timeStr = dataDict.get("time", "")     # 充值时间,补发不更新时间
    if not timeStr:
        return json.dumps({"error":"param time"}, ensure_ascii=False)
    sign = dataDict.get("sign", "")     # 充值时间,补发不更新时间
    if not sign:
        return json.dumps({"error":"param sign"}, ensure_ascii=False)
    key = ConfigIO.GetValue("Coupon", channel + "_wxkey")
    calcSign = md5.md5(str(count) + orderID + timeStr + key).hexdigest()
    if calcSign != sign:
        mylog.debug("error sign=%s"%calcSign)
        return json.dumps({"error":"sign"}, ensure_ascii=False)
    dbController = CouponDB.GetDBEventCon()
    if not dbController:
        # 无法获取数据库
        mylog.debug("no dbController")
        return json.dumps({"error":"db"}, ensure_ascii=False)
    # 验证是否重复订单
    result = dbController.find(CouponDB.CouponWXColName, {"realorderid":orderID})
    if result[1]:
        codeList = []
        for cardInfo in result[1]:
            codeList.append(cardInfo['code'])
        #return json.dumps({"error":"orderid repeat"}, ensure_ascii=False)
        mylog.debug("orderid repeat")
        return json.dumps({orderID:codeList}, ensure_ascii=False)
    #批量插入卡号
    tmpCodeList = []    # 卡信息
    codeList = []   # 卡号
    for i in xrange(count):
        tmpCodeDoc = {}
        # 前3位为类型标识
        tmpCodeDoc['code'] = "wx" + md5.md5( channel + str(i) + orderID + timeStr + str(i) + \
                                     str(random.randint(1000, 2000000))).hexdigest()[5:17] + \
                                     random.choice('1234567890abcdefghijklmnopqrstuvwxyz') +\
                                     random.choice('1234567890abcdefghijklmnopqrstuvwxyz')
        tmpCodeDoc['operateid'] = channel   # appid组合标识 一家运营商可能有多个appid
        tmpCodeDoc['status'] = 0
        tmpCodeDoc['usetime'] = ""
        tmpCodeDoc['count'] = count
        tmpCodeDoc['appid'] = ""    # 记录用
        tmpCodeDoc['serverid'] = ""    # 记录用
        tmpCodeDoc['realorderid'] = orderID    # 购物的orderID,会根据数量拆解
        tmpCodeDoc['orderid'] = orderID + "_" + str(i+1)    # 拆解的orderID,会根据数量拆解
        tmpCodeDoc['accid'] = ""
        tmpCodeDoc['roleid'] = ""
        tmpCodeDoc['ordertitle'] = dataDict.get("ordertitle", "")
        tmpCodeDoc['orderinfo'] = orderInfo
        tmpCodeDoc['money'] = money
        tmpCodeDoc['ip'] = dataDict.get("ip", "")
        tmpCodeDoc['level'] = ""
        tmpCodeDoc['viplevel'] = ""
        tmpCodeDoc['createtime'] = timeStr
        tmpCodeList.append(tmpCodeDoc)
        codeList.append(tmpCodeDoc['code'])
    result = dbController.insert(CouponDB.CouponWXColName, tmpCodeList)
    if not result:
        return json.dumps({"error":"insert card"}, ensure_ascii=False)
    mylog.debug("插入成功%s"%tmpCodeList)
    return json.dumps({orderID:codeList}, ensure_ascii=False)
Tool/WebCenter/CouponCode/CouponDB.py
@@ -21,6 +21,8 @@
g_dbController = None
CouponWXColName = "tagCouponWXSC"   # 微信商城
CouponBatchColName = "tagCouponBatch"
CouponCodeColName = "tagCouponCode"
ModuleName = "CouponDB"
Tool/WebCenter/CouponCode/main.py
@@ -33,7 +33,8 @@
    
    CenterPort = int(ReadConfig.ReadConfig(os.getcwd() + "\\..\\Coupon\\config.ini").GetValue("Coupon", "CodePort", 53003))
    
    run(host='0.0.0.0', port=CenterPort, app=webapp.myapp, server='waitress')
    # 此处不要用多线程,不然会导致同时间复用的情况,造成刷单
    run(host='0.0.0.0', port=CenterPort, app=webapp.myapp)
    return
if __name__ == '__main__':
Tool/WebCenter/CouponCode/webapp.py
@@ -97,10 +97,23 @@
    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开头代表固定码
# 卡类型 开头字母做标识如 g1~999代表此卡只能使用一次 h1~999卡可以重复使用 z开头代表固定码 wx开头代表微信商店
# 玩家使用卡号 参数 平台 区服 账号 区服链接(GM用)卡号
# http://center.xxx.com:53003/Coupon/CouponCode.php?channel=appid&code=XXX&accid=YYY&sid=222&pushurl=s222.xxx.com&spid=jisu
# http://center.xxx.com:53003/Coupon/CouponCode.php
@myapp.route('/Coupon/CouponCode.php')
def CouponCode():
    dataDict = request.GET
@@ -118,9 +131,12 @@
    
    spID = dataDict.get("spid", "")
    if not spID:
        mylog.debug("no spid")
        return
        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
@@ -162,6 +178,39 @@
        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())
        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:
@@ -326,3 +375,77 @@
    
    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'] = wxdata['usetime']
        key = ConfigIO.GetValue("Coupon", "%s_wxkey"%operateID)
        #md5(appid=$appid&regionid=$regionid&passport=$passport&&money=$money&time=$time$app_secret)
        sign = md5.md5("appid=%s&regionid=%s&passport=%s&money=%s&time=%s%s"%(\
                    post['appid'], post['regionid'], post['passport'], post['money'], post['time'], key)).hexdigest()
        post['Sign'] = sign
        result = urllib2.urlopen(billurl, urllib.urlencode(post), 3)
        mylog.debug("SendDataCollectorBillInfo result %s"%result.read())
    except Exception, e:
        mylog.debug("SendDataCollectorBillInfo error %s"%e)