记录一次微信jsapi支付调起用的签名
主要场景是在微信内打开链接进行支付。使用md5签名,rsa签名没成功,真tm服了。
首先已经成功创建了预支付订单,也就是得到了prepay_id了,如果还没有到这一步本文的内容暂时还无关哈。
构建签名字符串
此处需要注意一定要在最后加商户平台设置的密钥key,加在构建的字符串后面,不然会显示签名验证失败,去tm的!!!代码如下
import hashlib
import six
def _cal_pay_sign(self, app_id, timestamp, nonceStr, prepay_id):
data = {
'appId': app_id, # 公众号appid
'timeStamp': timestamp, # 创建预订单时的时间戳(10位)
'nonceStr': nonceStr, # 创建预订单时随机字符
'signType': 'MD5', # 签名方式
'package': f'prepay_id={prepay_id}', # prepay_id是预订单获取到的预订单字符串
}
# 进行排序并构建一个列表,方便后续构建签名字符串,_to_binary在下面有
sign_data = [_to_binary('{0}={1}'.format(k, data[k])) for k in sorted(data) if data[k]]
# api_key 为商户平台设置的密钥key
sign_data.append(_to_binary('key={0}'.format(api_key)))
# 构建签名字符串
sign_str = b'&'.join(sign_data)
# 签名
pay_sign = _to_text(hashlib.md5(sign_str).hexdigest().upper())
return pay_sign
# 上面用到的函数,主要作用是进行编码,可以自己看情况写不需要我那么麻烦
def _to_text(value, encoding='utf-8'):
"""将值转换为unicode,默认编码为utf-8
:param value: 要转换的值
:param encoding: 期望的编码
"""
if not value:
return ''
if isinstance(value, six.text_type):
return value
if isinstance(value, six.binary_type):
return value.decode(encoding)
return six.text_type(value)
def _to_binary(value, encoding='utf-8'):
"""将值转换为二进制字符串,默认编码为utf-8
:param value: 要转换的值
:param encoding: 期望的编码
"""
if not value:
return b''
if isinstance(value, six.binary_type):
return value
if isinstance(value, six.text_type):
return value.encode(encoding)
return _to_text(value).encode(encoding)
前端页面调起支付
因为是在微信内使用的网页,直接使用WeixinJSBridge,只有在微信内使用有效, 此处是使用的django的render返回的网页,所以返回的变量直接放在了网页中, 按自己情况返回对应数据即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>微信支付</title>
</script>
</head>
<body>
<h1>微信支付</h1>
<button id="payButton">支付</button>
<script>
// 从服务器返回签名等数据
// 公众号appid
var appId = '{{ appid }}';
// 请求预订单时间戳
var timestamp = '{{ timestamp }}';
// 请求预订单随机字符串
var nonceStr = '{{ nonceStr }}';
// prepay_id='***'这部分
var package = '{{ package }}';
// 签名方式 MD5
var signType = '{{ signType }}';
// 签名字符串
var paySign = '{{ paySign }}';
function onBridgeReady() {
WeixinJSBridge.invoke('getBrandWCPayRequest', {
"appId": appId, //公众号ID
"timeStamp": timestamp, //时间戳
"nonceStr": nonceStr, //随机串
"package": package,
"signType": signType, //微信签名方式
"paySign": paySign // 微信签名
},
function(res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
// 支付成功
alert("支付成功");
} else {
// 支付失败
document.getElementById("openid").innerText = "支付失败: " + res.err_msg;
alert(res.err_msg);
}
});
}
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
} else {
onBridgeReady();
}
</script>
</body>
</html>
以上,来自 lee 记录,希望对你有帮助