美文网首页
微信支付 - JSAPI(Python)

微信支付 - JSAPI(Python)

作者: 伤心的小码码 | 来源:发表于2019-09-25 19:02 被阅读0次

微信支付最核心的两个功能就是 微信支付支付回调通知

1.准备

  • 配置信息

    1. appid
      进入微信公众号里面的 开发>基本配置 就有

      appid.jpg
    2. mch_id
      商户的id

    3. mch_key
      商户的密钥

    4. notify_url
      这个支付结束后的回调 URL。

    5. openid
      这个是用户的openid,获取这个方式根据不同的业务获取。公众号业务的可以参考 微信公众号网页授权

  • 添加支付配置目录

添加服务器的域名

dhsj

2.业务流程

请求统一支付接口,封装数据,返回给客户端进行调用支付功能,然后等待支付结果回调。

2.1.H5 微信支付

微信支付参考链接:统一下单微信内H5调起支付

2.1.1.辅助工具

辅助工具主要是为了方便一些复杂流程

  • 32位的随机字符串
def nonce_str():
  # 生成字符串
  return random_number(32)

def random_number(iterate, value=""):
  # 构建一个字符集
  strs = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
             "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
             "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
             "U", "V", "W", "X", "Y", "Z"
  ]

  if iterate == 0:
    return value
  
  # 递归方式生成字符串
  return value + random_number(iterate - 1, random.choice(strs))

  • 签名
"""
    签名验证地址: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1
"""
def sign(sign_key_value, key):
  # key = mch_key
  # 拼接参数
  string_sign_temp = ""

  for k, v in [(k, sign_key_value[k]) for k in sorted(sign_key_value.keys())]:
    if v is not None or v != "":
      string_sign_temp += "{}={}&".format(k, v if v else str(v))

  # MD5加密
  import hashlib
  _md5_obj = hashlib.md5()
  _pre_sign = string_sign_temp + "key={}".format(key)

  _md5_obj.update(_pre_sign.encode(encoding='utf-8'))
  _sign = _md5_obj.hexdigest().upper()
  
  return _sign


辅助工具实现参考来源:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3

2.1.2.统一下单必须参数

# 封装必要的数据

{  
  'appid': appid,  
  'mch_id': mch_id,
  'device_info': "WEB",
  'nonce_str': nonce_str,
  'body': body,
  'out_trade_no': out_trade_no,
  'total_fee': total_fee,
  'spbill_create_ip': spbill_create_ip,
  'notify_url': notify_url,
  'trade_type': trade_type,
  'openid': openid,
  # 其他需要的字段
}

这个数据作为一下的 params

2.1.3.构建请求的xml

def json2xml(params):
  # params 是 `2.1.2` 所需要的数据
  # params 是需要进行转换的 dict
  import xmltojson  # pip install xmltojson
  return xmltodict.unparse(str, pretty=True)

def params_exchanging(params):
  # 生成签名之后,拼接并转换成 xml
  _sign = sign(params)
  
  params['sign'] = _sign
  return json2xml(params)
  

这个返回的数据用于下面统一下单的 data_xml

2.1.4.统一下单

参考文档:统一下单

def unified_ordering(data_xml):
  import requests  # pip install requests
  import xmltojson
  import json

  _unified_url = "https://api.mch.weixin.qq.com/pay/unifiedorder"

  _res = requests.post(_unified_url, data=data_xml)
  
  # 返回一个 dict 对象,讲 返回的 xml 转换成方便操作的 json
  return json.loads(json.dumps(xmltodict.parse(wx_msg), indent=1))

返回的数据可以直接使用,但是为了进一步方便前端的工作,我们需要封装成直接让前端调起H5支付的功能。

2.1.4.处理统一下单数据

参考文档: 微信内H5调起支付

# 处理数据之前需要判断数据的可用性哦,看统一下单的文档有解释
#
#  unified_order_result 格式如下:
#     {
#         "xml": {
#             "appid": "dasdasdsad",
#             ...
#          }
#    }
# 
def jsapi_resolve(unified_order_result, mch_key):
  import datetime

  _dict = {
    "appId": unified_order_result['xml']['appid'],
    "timeStamp": str(datetime.datetime.now().timestamp())[0:10],
    "nonceStr": unified_order_result['xml']['nonce_str'],
    "package": "prepay_id={}".format(unified_order_result['xml']['prepay_id']),
    "signType": "MD5"
  }

  _sign = sign(_dict, mch_key)
  _dict['paySign'] = _sign
  
  return _dict

到这里,返回的数据就可以提供微信支付了。

2.2.支付回调通知处理

文档参考:支付结果通知

支付回调通知需要是 Post 的请求API,并且不能有任何参数要求。

2.2.1.解析数据

使用 Flask 作为后台

from flask import request, Flask, jsonify  # pip install flask
from flask_core import CORS  # pip install flask_core

app = Flask(__name__)

@app.route("/api/wx/payment/callback")
def payment_callback():
  # 微信传过来的数据
  _data_recv = request.data
  
  import xmltojson
  import logging
  
  # 微信需要返回一个固定的数据,在没有问题下,一般都写死了。
  try:
    _json_data = json.loads(json.dumps(xmltodict.parse(_data_recv), indent=1))
  
    logging.warning("{}".format(_json_data))

    # TODO 业务逻辑处理...

  except Exception as err:
    logging.exception(err)
  
  finaly:
    return """
    <xml>
      <return_code><![CDATA[SUCCESS]]></return_code>
      <return_msg><![CDATA[OK]]></return_msg>
    </xml>
     """

3.总结

  1. 微信的文档确实很难过;
  2. 微信支付的错误返回确实很难过,很多问题返回同一个错误信息;
  3. 很多时候,需要做一个笔记,毕竟微信支付的功能被用好多次,但是每次都得重新再来,不想了;
  4. 微信的文档挺多的,但是感觉没有一个统一的感觉;
    5.微信公众号支付文档

相关文章

网友评论

      本文标题:微信支付 - JSAPI(Python)

      本文链接:https://www.haomeiwen.com/subject/kueeuctx.html