微信小程序:用户点击跳转付款码界面

最近工作中遇到一个需求是用户点击活动领取的微信代金券后跳转到微信付款码界面,于是乎,一顿翻文档,说实话,微信小程序的文档翻起来真的…一言难尽。
很快找到了一个wx.requestPayment(Object object),可是仔细一看,这个接口是发起支付的,会弹出付款界面,就是让你输入密码那个,继续找,无果,转战百度,果然搜到了,原来这并不是一个开放的接口,而是需要单独去向微信申请的,并且也没有公开文档。也对,毕竟是跳到付款码界面,比较敏感 。
好申请完成后,开始开发!

前置条件

API介绍

wx.openOfflinePayView(OBJECT)

参数类型必填实例值说明
appIdStringwxd678efh567hg6787公众平台 appid,需与 mch_id 有绑定关系
timeStampString1631604636时间戳;商户生成从 1970 年 1 月 1 日 00: 00:00 至今的秒数,即当前的时间
nonceStrStringnjqn50kxbl随机字符串;商户生成的随机字符串;取 值范围:长度为 32 个字符以下。
packageStringmch_id=1289343489mch_id=****,微信支付商户号,需与 appid 有绑定关系
signTypeStringMD5签名类型,目前支持 MD5、 HMAC-SHA256。该字段需参与签名。
paySignString97A991A68892C3A0668E4DE80F24F782签名结果,该方法需要加入签名的参数为 appId、timeStamp、nonceStr、package、 key、signType,请注意这里的参数有大 小写,签名的时候不要转为小写
successFunctionsuccessHandler调用成功回调
failFunctionfailHandler调用失败回调
completeFunctioncomplatehandler调用完成回调

签名字符串示例

appId=wxa66666d6d5c4bf4b&nonceStr=y6683ha9i6a&package=mch_id=164888850&signType=MD5&timeStamp=1631605839&key=apiKey12355yesuis

最终请求示例

wx.openOfflinePayView(
{ 
	'appId': 'wxa66666d6d5c4bf4b',
 	'timeStamp': '1631605839',
  	'nonceStr': 'y6683ha9i6a', 
  	'package': 'mch_id=164888850', 
  	'signType': 'MD5', 
  	'paySign': '64355B5427BAF57459BA2A3214AF1883EBB2B519F4789B7D616CC8B8F2CE8ED5',
  	'success':function(res){}, 
  	'fail':function(res){}, 
  	'complete':function(res){} 
 }
)

代码

官方签名规则及签名生成算法

签名生成

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

注意以下规则:

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

  • 加密参数排序拼接方法
obj2str(args) => {
  //获取参数对象的参数名集合
  var keys = Object.keys(args) 
  //参数名ASCII码从小到大排序(字典序)
  keys = keys.sort() 
  // 用于接收排序并过滤空值后的属性及值
  var newArgs = {} 
  // 遍历赋值存储
  keys.forEach(function (key) {
    if (args[key] != "" && args[key] != 'undefined') {  //如果参数的值为空不参与签名;
      newArgs[key] = args[key]  //参数名区分大小写;
    }
  })
  //用于接收拼接的字符串
  var string = ''
  for (var k in newArgs) {
    string += '&' + k + '=' + newArgs[k]
  }
  // 截取字符串,只取第一个&符号后面的值
  string = string.substr(1)
  // 返回字符串,用于下一步加密
  return string
}
  • 生成随机数方法
    用于保证签名不可预测。推荐生成随机数算法如下:调用随机数函数生成,将得到的值转换为字符串
creatNonceStr(radix=36){
	// 将0-1随机小数,转换为radix进制,去掉0.,保留余下部分(这里可以自由发挥)
	return Math.random().toString(radix).substr(2, 15)
}
  1. stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue注意:密钥的长度为32个字节。

我这里使用的是MD5加密,是从网上找的现成的,引入小程序直接使用

key设置路径:微信商户平台(pay.weixin.qq.com)–>账户设置–>API安全–>密钥设置

 	let params = {
        appId: 'wxa66666d6d5c4bf4b',
	 	timeStamp: parseInt(new Date().getTime() / 1000) + '',
	  	nonceStr: this.creatNonceStr(), 
	  	package: 'mch_id=164888850', 
	  	signType: 'MD5', ,
      }
      // 商户后台api Key
      let mchKey = 'apiKey12355yesuis'
      // 在拼接的参数后追加上api key
      let objStr = this.obj2str(params)+`&key=${mchKey}`
      // 进行MD5加密并转为大写
      let paySign =  md5.hex_md5(objStr).toUpperCase()

注意

  • package的值是mch_id=商户号,我第一次就没看清文档写错了
  • key是将appId、timeStamp、nonceStr、package、 key、signType排序拼接后追加在最后的
  • key用的是商户后台的API秘钥而不是APIv3秘钥
  • 最后记得将加密后的结果转为大写
  1. 调用API
  wx.openOfflinePayView({
        ...params,
        paySign,
        success(res){
          console.log('成功',res)
        },
        fail(err){
          console.log('失败',err)
        },
        complete(e){
          console.log('结束',e)
        }
      })

在这里插入图片描述

如果你觉得文章对你有帮助,可以关注我的个人公众号 ,感谢你的支持!!
在这里插入图片描述

posted @   Silence_1018  阅读(145)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示