Benjamin

静以修身,俭以养德,非澹薄无以明志,非宁静无以致远。
随笔 - 296, 文章 - 0, 评论 - 196, 引用 - 0
数据加载中……

python服务器 实现app微信支付:支付异步通知

# -*- coding: utf-8 -*-
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import pymysql
import json
import xmltodict
from hashlib import md5
from tornado.options import define, options
####################微信支付异步回调消息########################
WEIXIN_KEY = '8mdRLb1yeesYssfasdfsadfassdaV'
def generate_sign(params):
    """
    生成md5签名的参数
    """
    if 'sign' in params:
        params.pop('sign')
    src = '&'.join(['%s=%s' % (k, v) for k, v in sorted(params.items())]) + '&key=%s' % WEIXIN_KEY
    return md5(src.encode('utf-8')).hexdigest().upper()
def validate_sign(resp_dict):
    """
    验证微信返回的签名
    """
    if 'sign' not in resp_dict:
        return False
    wx_sign = resp_dict['sign']
    sign = generate_sign(resp_dict)
    if sign == wx_sign:
        return True
    return False
def handle_wx_response_xml(params):
    """
    处理微信支付返回的xml格式数据
    """
    try:
        resp_dict = xmltodict.parse(params)['xml']
        if not resp_dict or len(resp_dict) < 1:
            print('resp_dict is zero+++++++++')
            return None
        return_code = resp_dict.get('return_code')
        if return_code == 'SUCCESS':  # 仅仅判断通信标识成功,非交易标识成功,交易需判断result_code
            if validate_sign(resp_dict):
                print('验证成功!!!')
                return resp_dict
       
    except Exception as e:
        print(e)
        return None
    return None
def weixinpay_call_back(request):
    """
    微信支付回调
    :param request: 回调参数
    :return:
    """
    args = str(request.body,'utf-8')
    if args is None:
        return None
    print(args)
    # 验证平台签名
    resp_dict = handle_wx_response_xml(args)
    if resp_dict is None:
        print('签名验证失败!!!')
        return None
    return resp_dict
def weixinpay_response_xml(params):
    """
    生成交易成功返回信息
    """
    def generate_response_data(resp_dict):
        """
        字典转xml
        """
        return xmltodict.unparse({'xml': resp_dict}, pretty=True, full_document=False).encode('utf-8')
    return_info = {
        'return_code': params,
        'return_msg': 'OK'
    }
    return generate_response_data(return_info)
def weixinpay_sucess_db(dicts):
    """微信支付成功后数据库日志操作"""
    if isinstance(dicts,dict):
        trade_status = dicts['result_code']  # 业务结果  SUCCESS/FAIL
        trade_no = dicts['out_trade_no']  # 商户订单号
        if trade_status == "SUCCESS":
            appid = dicts['appid']  # 应用ID
            bank_type = dicts['bank_type']  # 付款银行
            cash_fee = dicts['cash_fee']  # 现金支付金额(分)
            device_info = dicts['device_info']  # 微信支付分配的终端设备号
            fee_type = dicts['fee_type']  # 货币种类
            gmt_create = dicts['time_end']  # 支付完成时间
            total_amount = int(dicts['total_fee']) / 100  # 总金额(单位由分转元)
            trade_type = dicts['trade_type']  # 交易类型
            out_trade_no = dicts['transaction_id']  # 微信支付订单号
            seller_id = dicts['mch_id']  # 商户号
            openid = dicts['openid']  # 用户标识
            update_sql = ''' update weixin_trade set trade_status='{trade_status}', appid='{appid}', ''' + \
            '''seller_id='{seller_id}', openid='{openid}', total_amount='{total_amount}',''' +  \
            '''out_trade_no='{out_trade_no}', gmt_create='{gmt_create}', '''+ \
            '''device_info='{device_info}', trade_type='{trade_type}', bank_type='{bank_type}', ''' + \
            '''fee_type='{fee_type}', cash_fee='{cash_fee}' where trade_no='{trade_no}' '''
            update_sql = update_sql.format(
                trade_status=trade_status,
                appid=appid,
                seller_id=seller_id,
                openid=openid,
                total_amount=total_amount,
                out_trade_no=out_trade_no,
                gmt_create=gmt_create,
                device_info=device_info,
                trade_type=trade_type,
                bank_type=bank_type,
                fee_type=fee_type,
                cash_fee=cash_fee,
                trade_no=trade_no)
            print(update_sql)
            #写数据库
            
def weixin_rollback(request):
    """
    【API】: 微信宝支付结果回调接口,供微信服务端调用
    """
    try:
        # 支付异步回调验证
        data = weixinpay_call_back(request)
        if data:
            print('微信支付返回====={0}'.format(data))
            res = "success"
            trade_status = data['result_code']  # 业务结果  SUCCESS/FAIL
            out_trade_no = data['out_trade_no']  # 商户订单号
            if trade_status == "SUCCESS":
                weixinpay_sucess_db(data)
                device_info = data['device_info']  # 微信支付分配的终端设备号
                # 如果状态是支付成功则发放物品
                hall = KBEngine.globalData["Halls"]
                if hall:
                    player_data = hall.GetPlayerByDbId(int(device_info))
                    if player_data:
                        player = player_data.entityCall
                        if player:
                            print('微信发放奖品到客户端,订单号======%s' % out_trade_no)
                            player.GmBkCmd({'cmd':'PayReward','Order_id':out_trade_no})
                        else:
                            print('找不到玩家++++++++')
            else:
                res = "error: pay failed! "
                status = 0
                err_code = data['err_code']  # 错误代码
                err_code_des = data['err_code_des']  # 错误代码描述
        else:
            res = "error: verify failed! "
    except Exception as e:
        print(e)
        res='err:exception==='
    finally:
        return weixinpay_response_xml(res)
class WeChatPayNotify(tornado.web.RequestHandler):
    """微信支付回调"""
    def post(self):
        """
        【API】: 微信宝支付结果回调接口,供微信服务端调用
        """
        self.write(weixin_rollback(self.request))
class WeChatPay(tornado.web.RequestHandler):
    def post(self):
        to_client={}
        for k,v in self.request.arguments.items():
            to_client[k] = str(v[0],encoding='utf-8')
        pid = to_client.pop('pid')
        if isinstance(pid,str):
            pid = int(pid)
        self.write('')

posted on 2020-12-05 15:34 Benjamin 阅读(92) 评论(0)  编辑 收藏 引用 所属分类: python


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理