爱链笔记-微信支付

一曲冷凌霜 提交于 2019-12-27 09:26:45

本来以为微信支付是几行代码的事儿,没想到还要前后端配合,有点深。所以我还是记下来吧。(python环境下)

具体的业务流程就从百度上copy一下咯。

 

首先就要在公众平台申请微信支付,具体做法见https://jingyan.baidu.com/article/ad310e80f7a5c01849f49e9b.html,搞好了就进行下一步。

获取openid,步骤见上一篇。

之后就是生成商户订单了,来获取prepayid了,具体要求见官方说明https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3:

第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

有几个规则很重要:

  1. ◆ 参数名ASCII码从小到大排序(字典序);
  2. ◆ 如果参数的值为空不参与签名;
  3. ◆ 参数名区分大小写;
  4. ◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
  5. ◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段

这里我需要发送的数据集合M如下;

 data = {

        'appid':env_dist['appid'],

        'mch_id':env_dist['mch'],

         'nonce_str': get_nonce_str(), #自己写的一个随机字符串,防止重放攻击。

         'body': '上链费用',  # 商品描述

         'out_trade_no': str(int(time.time())),  # 商户订单号

         'spbill_create_ip': '127.0.0.1',  # APP和网页支付提交用户端ipNative支付填调用微信支付API的机器IP

         'notify_url': ' http://www.weixin.qq.com/wxpay/pay.php',  # 异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数

         'trade_type': 'JSAPI',

         'total_fee': '1', #支付费用,单位为分。

         'openid' : openid,

     }

用如下语句进行排序拼接: stringA = '&'.join(["{0}={1}".format(k, data.get(k)) for k in sorted(data)])

其中生成随机字符串函数:

def get_nonce_str():

     string=[]

     for i in range(32):

         x = random.randint(1, 2)

         if x == 1:

             y = str(random.randint(0, 9))

         else:

             y = chr(random.randint(97, 122))

         string += y

        string = ''.join(string)

        return string

接下来将stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。merchant_key到 https://pay.weixin.qq.com -->账户中心-->API安全-->设置API密钥
自行设置一个32位的密钥

  stringSignTemp = '{0}&key={1}'.format(stringA, merchant_key)

  stringSignTemp = stringSignTemp.encode("utf8") #utf-8编码很重要

  sign = hashlib.md5(stringSignTemp).hexdigest().upper()

  data['sign'] = sign

 将data变为xml格式,为发送到微信后台做准备。

data = trans_dict_to_xml(data).encode('utf-8') #utf-8编码,很重要。

将字典变为xml的方法如下:

def trans_dict_to_xml(data):

     xml = []

     for k in data.keys():

         v = data.get(k)

         if k == 'detail' and not v.startswith('<![CDATA['):

             v = '<![CDATA[{}]]>'.format(v)

         xml.append('<{key}>{value}</{key}>'.format(key=k, value=v))

    return '<xml>{}</xml>'.format(''.join(xml))

 然后使用post方法将数据传输到后台换取prepayid。

 url = 'https://api.mch.weixin.qq.com/pay/unifiedorder' #换取的url

  req = urllib.request.Request(url=url, data=data, method='POST', headers={'Content-Type': 'application/xml'})

得到返回值: result = result.decode('utf-8'),返回的数据大致如下:

<xml>
   <return_code><![CDATA[SUCCESS]]></return_code>
   <return_msg><![CDATA[OK]]></return_msg>
   <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
   <mch_id><![CDATA[10000100]]></mch_id>
   <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
   <openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid>
   <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
   <result_code><![CDATA[SUCCESS]]></result_code>
   <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
   <trade_type><![CDATA[JSAPI]]></trade_type>
</xml>

这里我只需要得到prepayid,所以使用了正则,不过使用dom解析xml是更加通用的做法,代码如下:

 result = re.findall(r"<prepay_id><!\[CDATA\[(.*)]]></prepay_id>", result)

获得perpayid后进行第二次签名。

首先定义需要传输的数据包,包括:

package="prepay_id="+prepay_id

 t = time.time()

 

data2={

      'appId': 'wx04c066bae099852d',

      'timeStamp': int(t), #时间戳,为整数秒

      'nonceStr': get_nonce_str(),

      'package': package,

      'signType':'MD5',

 }

获得数据包后和上面步骤一样进行签名。获得paysign,和data2一并传到前端。

 stringB = '&'.join(["{0}={1}".format(k, data2.get(k))for k in sorted(data2)])

 stringB = '{0}&key={1}'.format(stringB, merchant_key)stringB=stringB.encode("utf8")

 paySign = hashlib.md5(stringB).hexdigest().upper()#获得paysign

 data2['paySign']=paySign#将paysign加入到data2中

前端得到以上的参数,调用wx.requestPayment就实现了微信支付,具体的前端代码等到写前端时再写。

最后有几个官方的关于微信支付的文档可以看看,上面的应该是最简单的一个应用了,剩下的还是要靠自己继续发掘了。

微信支付统一下单接口文档:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=9_1

微信支付签名算法:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=4_3

微信支付开发教程:https://mp.weixin.qq.com/paymch/readtemplate?t=mp/business/course3_tmpl&lang=zh_CN

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!