首页 > 编程语言 >微信支付 Python

微信支付 Python

时间:2024-08-12 20:49:04浏览次数:7  
标签:xml code Python 微信 resp 支付 msg xmlresp

需求:

微信打开商品列表页面-> 点击商品后直接显示付款页面-> 点击付款调用微信支付

说明

微信支付需要你申请了公众号(appid, key - 用于签名), 商户号(mch_id, AppSecret - 用于获取openid, 获取code)
调起微信支付的页面需要配置授权, 如你的页面是http://www.shazuihuo.com/goods/index.html. 那么你需要配置为: http://www.shazuihuo.com/goods/ 即可, 这个是在商户号中配置
签名算法和校验工具

  1. 签名校验通过时还是提示签名错误, 可能时候商户号KEY配置的问题了, 重置一下KEY, 你可以继续使用原来的KEY来重置
  2. 公众号变更时记得修改后台和前台代码中的APPID

需要的ID和KEY

# 微信配置基础数据
WPC = {
    'APPID': 'wx53c1xxxxad626eb8',
    'APPSECRET': 'fdd177a7xxxxxxxxxxxxx856eeeb187c',
    'MCHID': '14222000000',
    'KEY': 'd7810713e1exxxxxxxxxxadc9617d0a6',
    'GOODDESC': '商户号中的公司简称或全称-无要求的商品名字',
    'NOTIFY_URL': 'https://www.xxxx.com/service/applesson/wechatordernotice', 
}

流程简介

  1. 网页内调起微信支付需要一个微信统一下单生成的订单号(prepay_id)
  2. 调用微信的统一下单接口需要一个用户在商户下的唯一标示(openid)
  3. 获取openid需要code参数加上AppID和AppSecret等,通过API换取access_token(openid)
  4. 其中code又需要通过页面跳转来获取, 需要appid和重定向url(可以带有你自己的参数, 会原样返回)
    那么开发思路便是一步步回朔了.

1. 获取code

用户点击按钮跳转到微信授权页, 微信处理完后重定向到redirect_uri, 并给我们加上code=xxx的参数, 这个code就是我们需要的

    $('#buy').click(function() {
        var param = {
            appid: 'wx53c1xxxxad626eb8',
            redirect_uri: 'https://www.xxxxx.com/wcpay/pay.html',
            response_type: 'code',
            scope: 'snsapi_base',
            state: '1'
        }
        window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?' + $.param(param);
    })

2. 获取openid

这个在后台完成, WPC中配置了你的APPSECRET, 这个不能泄露, 接口调用成功会拿到一个openid, 这里都不会有什么问题

    @classmethod
    def getOpenID(cls, kwargs):
        param = {
            'code': kwargs['code'],
            'appid': WPC['APPID'],
            'secret': WPC['APPSECRET'],
            'grant_type': 'authorization_code',
        }

        # 通过code获取access_token
        openIdUrl = 'https://api.weixin.qq.com/sns/oauth2/access_token'
        resp = requests.get(openIdUrl, params=param)
        # {openid, accss_token, refresh_token, openid, scope, expires_in}
        # openId = json.loads(resp.text)['openid']
        return resp.text

3. 微信统一下单

统一下单 时参数传递需要签名(微信用我们设定的密匙对参数进行MD5加密, 通过双方的签名判断请求是否被篡改)
签名算法

@classmethod
def getSign(cls, kwargs):

    # 计算签名
    keys, paras = sorted(kwargs), []
    paras = ['{}={}'.format(key, kwargs[key]) for key in keys if key != 'appkey']  # and kwargs[key] != '']
    stringA = '&'.join(paras)

    stringSignTemp = stringA + '&key=' + WPC['KEY']
    sign = MD5(stringSignTemp).upper()

    return sign

MD5函数

import hashlib

# 获取MD5
def MD5(str):
    md5 = hashlib.md5()
    md5.update(str.encode('utf-8'))
    return md5.hexdigest()

参数转xml

@classmethod
def getxml(cls, kwargs):
    
    kwargs['sign'] = Utility.getSign(kwargs)

    # 生成xml
    xml = ''
    for key, value in kwargs.items():
        xml += '<{0}>{1}</{0}>'.format(key, value)
    xml = '<xml>{0}</xml>'.format(xml)

    # print(xml)
    return xml

统一下单代码

code = self.POST.get('code')
openidresp = Utility.getOpenID({'code': code})
openid = json.loads(openidresp).get('openid')

UnifieOrderRequest = {
    'appid': 'wx53c1xxxxad626eb8',  # 公众账号ID
    'body': '公司名称-商品',  # 商品描述
    'mch_id': '1397xxxxxx8',  # 商户号:深圳市泽慧文化传播有限公司
    'nonce_str': '',  # 随机字符串
    'notify_url': 'https://service.xxxx.com/service/applesson/wechatordernotice',  # 微信支付结果异步通知地址
    'openid': '',  # trade_type为JSAPI时,openid为必填参数!此参数为微信用户在商户对应appid下的唯一标识, 统一支付接口中,缺少必填参数openid!
    'out_trade_no': '',  # 商户订单号
    'spbill_create_ip': '',  # 终端IP
    'total_fee': '',  # 标价金额
    'trade_type': 'JSAPI',  # 交易类型
}
UnifieOrderRequest['nonce_str'] = Utility.getnoncestr()
UnifieOrderRequest['openid'] = openid
UnifieOrderRequest['out_trade_no'] = UnifieOrderRequest['mch_id'] + str(order.id)  # 内部订单号码
UnifieOrderRequest['spbill_create_ip'] = self.request.remote_ip
UnifieOrderRequest['total_fee'] = int(lesson.price * 100)
# 签名并生成xml
xml = Utility.getxml(UnifieOrderRequest)

resp = requests.post("https://api.mch.weixin.qq.com/pay/unifiedorder", data=xml.encode('utf-8'), headers={'Content-Type': 'text/xml'})
msg = resp.text.encode('ISO-8859-1').decode('utf-8')
xmlresp = xmltodict.parse(msg)
prepay_id = ''

if xmlresp['xml']['return_code'] == 'SUCCESS':
    if xmlresp['xml']['result_code'] == 'SUCCESS':
        prepay_id = xmlresp['xml']['prepay_id']
        timestamp = str(int(time.time()))
        data = {
            "appId": xmlresp['xml']['appid'],
            "nonceStr": Utility.getnoncestr(),
            "package": "prepay_id=" + xmlresp['xml']['prepay_id'],
            "signType": "MD5",
            "timeStamp": timestamp
        }
        data['paySign'] = Utility.getSign(data)
        data['orderid'] = order.id  # 付款后操作的订单
        # 签名后返回给前端做支付参数
        return JsonResponse(self, '000', data=data)
    else:
        msg = xmlresp['xml']['err_code_des']
        return JsonResponse(self, '002', msg=msg)
else:
    msg = xmlresp['xml']['return_msg']
    return JsonResponse(self, '002', msg=msg)

统一下单成功返回后直接调用微信支付, 显示支付界面, 其中的paySign是我们自己的签名

try {
    // statements
    // 微信统一订单, 返回预支付信息
    var code = query('code'),
        origin = query('groupid');
        // alert(code);

        $.post({
            url: orderurl,
            data: {
                origin: origin,
                mobile: phone,
                code: code
            }
        }).then(function(resp) {
            if (resp.code && resp.code == "000") {
                // 后台返回订单信息
                var wepaydata = {
                    appId: resp.data.appId,
                    nonceStr: resp.data.nonceStr,
                    package: resp.data.package,
                    paySign: resp.data.paySign,
                    signType: "MD5",
                    timeStamp: resp.data.timeStamp
                };
                var orderid = resp.data.orderid || 0;

                window.jsApiCall = function() {
                    WeixinJSBridge.invoke(
                        'getBrandWCPayRequest',
                        wepaydata,
                        function(res) {
                            WeixinJSBridge.log(res.err_msg);
                            // alert(res.err_code + res.err_desc + res.err_msg);
                            // alert(res.err_msg)
                            if (res.err_msg == 'get_brand_wcpay_request:ok') {
                                $.get(orderurl, { orderid: orderid }, function(resp) {
                                    if (resp.code == '000') {
                                        window.location.href = window.location.href.replace('pay.html', 'success.html');
                                    } else {
                                        alert(resp.msg);
                                        // 一个code只能请求一次, 重新进入index
                                        if (resp.code == '002') {
                                            window.location.href = window.location.href.replace('pay.html', 'index.html');
                                        }
                                    }
                                });
                            } else {
                                // 其他支付异常微信有显示消息
                                // alert(res.err_msg);
                            }
                        }
                    );
                }

                window.callpay = function() {
                    if (typeof WeixinJSBridge == "undefined") {
                        if (document.addEventListener) {
                            document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
                        } else if (document.attachEvent) {
                            document.attachEvent('WeixinJSBridgeReady', jsApiCall);
                            document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
                        }
                    } else {
                        jsApiCall();
                    }

                }

                // 发起支付
                window.callpay();

            } else {
                alert(resp.msg);
                // alert(JSON.stringify(resp) + resp.msg);
            }
        }, function(resp) {
            alert(resp)
            alert(JSON.stringify(resp))

            // alert('请求失败, 请重试');
        });
} catch (e) {
    // statements
    alert(e)
}

4. 订单查询

订单查询 是为了确认我们的支付是成功的

# 查询微信付款情况
orderid = self.GET.get('orderid')
orderquery = {
    'appid': WPC['APPID'],
    'mch_id': WPC['MCHID'],
    'nonce_str': Utility.getnoncestr(),
    'out_trade_no': WPC['MCHID'] + orderid
}
xml = Utility.getxml(orderquery)
print(xml)

resp = requests.post("https://api.mch.weixin.qq.com/pay/orderquery", data=xml.encode('utf-8'), headers={'Content-Type': 'text/xml'})
msg = resp.text.encode('ISO-8859-1').decode('utf-8')
xmlresp = xmltodict.parse(msg)
print(xmlresp)

orderPaid = 0
if xmlresp['xml']['return_code'] == 'SUCCESS':
    if xmlresp['xml']['result_code'] == 'SUCCESS':
        if xmlresp['xml']['trade_state'] == 'SUCCESS':
            orderPaid = 1
        else:
            msg = xmlresp['xml']['trade_state_desc']
            return JsonResponse(self, '001', msg=smg)
    else:
        msg = xmlresp['xml']['err_code_des']
        return JsonResponse(self, '001', msg=msg)
else:
    msg = xmlresp['xml']['return_msg']
    return JsonResponse(self, '001', msg=msg)

官方Demo

SDK与DEMO下载, 用python就需要自己码代码, 当时看的是PHP的

标签:xml,code,Python,微信,resp,支付,msg,xmlresp
From: https://www.cnblogs.com/596014054-yangdongsheng/p/10719967.html

相关文章

  • OpenCv学习-python
    一.OpenCv介绍简介OpenCV(OpenSourceComputerVisionLibrary:opencv官网地址)是一个开源的基于BSD许可的库,它包括数百种计算机视觉算法。文档OpenCV2.xAPI描述的是C++API,相对还有一个基于C语言的OpenCV1.xAPI,后者的描述在文档opencv1.x.pdf中。OpenCV具有模块化结......
  • python-xlsxwriter的基本使用
    安装xlsxwriter:pipinstallXlsxWriter简单实例:#coding:utf-8importxlsxwriterworkbook=xlsxwriter.Workbook('demo1.xlsx')#创建一个Excel文件worksheet=workbook.add_worksheet()#创建一个工作表对象worksheet.set_column('A:A',20)#设定第一列(A)宽度为20像素bold=......
  • mysql数据库:使用Python操作MySQL
    mysql数据库:使用Python操作MySQL安装第三方模块pymysqlpipinstallpymysql操作MySQLimportpymysql#创建连接#需要传入一些参数:#hostmysql所在的主机名或者是域名或者是ip地址#portmysql运行的端口号#ps-aux|grepmysql找到MySQL运行的进程......
  • 2024华为OD笔试机试 - 模拟目录管理功能 (python/c++/java D卷C卷真题算法)
    华为OD机试(C卷+D卷)2024真题目录(Java&c++&python)题目描述实现一个模拟目录管理功能的软件,输入一个命令序列,输出最后一条命令运行结果。支持命令:创建目录命令:mkdir目录名称,如mkdirabc为在当前目录创建abc目录,如果已存在同名目录则不执行任何操作。此命令无输出......
  • Python运行不报错又无任何结果输出
    Python运行不报错又无任何结果输出在Python编程中,遇到程序既不报错也没有任何结果输出的情形,往往让开发者感到困惑。这类问题可能源于多种原因,包括但不限于代码逻辑错误、环境配置问题、或是输入数据的问题。本文将深入探讨这一问题,并提供解决思路、方法、常见场景......
  • 代码质量的守护者:Python静态代码分析工具的集成之道
    标题:代码质量的守护者:Python静态代码分析工具的集成之道在软件开发过程中,代码质量是至关重要的一环。Python作为一种流行的编程语言,拥有众多的静态代码分析工具,它们能够在代码运行之前检测潜在的错误和代码风格问题。本文将深入探讨如何将这些工具集成到Python开发流程中,从......
  • 124. 项目74:简易句子结构分析器——《跟老吕学Python·新手》
    124.项目74:简易句子结构分析器——《跟老吕学Python·新手》124.项目74:简易句子结构分析器124.1目标124.2功能124.3设计124.4实现步骤124.5代码实现124.6测试124.7注意事项124.8小结124.项目74:简易句子结构分析器124.1目标开发一个......
  • 微信 PC版v3.9 防撤回 可多开
    版本特色:1、看到对方撤回的消息2、多账号可正常登录修改原理,如下图:使用说明:解压后,双击open_Wechat.exe来运行软件下载地址:Wechat防撤回多开版v3.9解压密码:helloh下载时可能会有广告,忽略,等下载结束即可部分杀软会因该版本软件未购买签名证书(如下图)而阻止运行,可通过暂......
  • Java微信公众号推送模版消息的方法示例
    要在Java中向微信公众号推送模板消息,首先需要确保我们已经有了微信公众号,并且已经设置了模板消息权限和模板ID。模板消息是一种向用户发送通知的服务,广泛用于订单状态更新、服务提醒等场景。下面,我将详细介绍如何使用Java结合微信官方提供的API来实现模板消息的推送。这通常涉及......
  • 智慧农业信息化服务平台小程序/基于微信小程序的农业信息管理系统的设计与实现/基于微
    摘要随着信息技术互联网和小程序的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的微信小程序应运而生,各行各业相继进入信息管理时代,其中智慧农业信息化服务平台小程序就是信息时代变革中的产物之一。任何......