完成该功能的前提是要先搞明白纯签约是怎么回事,微信小程序的纯签约其实和公众号的纯签约执行过程是一致的,只是实现方式不通,他是指用户和所签公司之间的一个约定协议,公司实现这个功能是值他所申请的微信小程序和他申请的直连商户进行开通纯签约的功能,可以满足先签约后扣费的一个操作,本篇文章会结合微信小程序纯签约的官网文档以及对应代码的解释和一些可能存在的坑进行记录,希望可以帮助一些准备或者已经对接的人解疑答惑。
搞明白小程序的纯签约流程对于我们后面理解代码有很大的帮助,微信小程序纯签约是在我们拿到纯签约参数的时候调wx.navigateToMiniProgram这个方法跳转到其他小程序中进行签约的,这里的wx.navigateToMiniProgram方法也很简单就是官方的从一个小程序跳转到另一个小程序的方法,那么具体跳转到哪一个小程序呢?官方也有明确说明就是appid 为wxbd687630cd02ce1d的小程序,那么这里就比较好解释为什么拉起纯签约的时候会有两个 appid 了,最外层的那个是固定的就是wxbd687630cd02ce1d,内部extraData里面的 appid 才是你自己公司需要执行纯签约的小程序的 appid,这是第一个疑惑,第二个是外部的一个path 是不是也是写死的,是的,这里的 path 也是我们需要跳转到官网纯签约小程序的时候的默认路径,和你的小程序没有任何关系,直接写死pages/index/index即可,那么这里就可以理解了,微信小程序的纯签约其实就是从你的小程序拉起跳转到官方的小程序中进行签约,之后签约结束又从官方的签约小程序跳回你自己的小程序的一个过程,所以本质的过程是两个小程序之间的来回跳转
/**
* @function contractSigning 小程序纯签约
* @param data 签约入参 [参数说明:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_3.shtml]
* @param successCb 支付成功回调函数
* @param failCb 支付失败回调函数
*/
export const contractSigning = (data, successCb, failCb) => {
const { appId, path, extraData } = data
wx.navigateToMiniProgram({
appId,
path,
extraData,
success(res) {
// TODO: 成功跳转到签约小程序
console.log('签约成功回参:', res)
successCb(res)
},
fail(errMsg) {
// TODO: 未成功跳转到签约小程序
console.log('签约失败回参:', errMsg)
failCb(errMsg)
},
complete: function (com) {
console.log('执行结束:', com)
}
})
}
上面这段代码其实就是官网提供的例子,我只是封装到的自己的项目中,所以这里没必要纠结我具体封装的时候传入的参数,看了微信小程序纯签约流程这步之后相信你对上面的参数是有一部分理解了。
看微信小程序纯签约流程这步骤的解释,appid 就是签约的官方小程序的 appid 写死的wxbd687630cd02ce1d,path 就是默认进去官方签约小程序之后的默认路径,写死的pages/index/index
这里extraData里面的参数和正常的支付是一样的,我们的支付就是后端对接了统一下单的接口之后返回了一系列参数之后前端执行官方的uni.requestPayment方法,那么签约也是一样的,后端对接了统一下单接口之后返回我们执行wx.navigateToMiniProgram的方法需要的参数即可,这个后端对接统一下单理解即可。
onShow(res) {
// 场景值1038:从被打开的小程序返回
if (res.scene === 1038) {
const { appId, extraData } = res.referrerInfo
if (appId == 'wxbd687630cd02ce1d') { // appId为wxbd687630cd02ce1d:从签约小程序跳转回来
if (typeof extraData == 'undefined'){
// TODO
// 客户端小程序不确定签约结果,需要向商户侧后台请求确定签约结果
return;
}
if(extraData.return_code == 'SUCCESS'){
// TODO
// 客户端小程序签约成功,需要向商户侧后台请求确认签约结果
var contract_id = extraData.contract_id
return;
} else {
// TODO
// 签约失败
return;
}
}
}
}
上面这段代码是微信用来判断当前签约状态的,写到 App.vue 中,这个签约状态指的是用户是不是点击了同意且输入了密码之后会到一个点击确定的页面,页面是微信官方的,这个时候用户点击了确定,就会到extraData.return_code == 'SUCCESS’的判断条件里面,你可以在这里进行跳转到你自定义的结果页面,比如我的代码是这样的
onShow((res) => {
console.log('场景值:', res)
if (res && res.scene === 1038) {
// 场景值1038:从被打开的小程序返回
const { appId, extraData } = res.referrerInfo
if (appId == 'wxbd687630cd02ce1d') {
// appId为wxbd687630cd02ce1d:从签约小程序跳转回来
// TODO: 是不是签约成功 到中转页面进行判断 不需要使用微信的签约状态进行判断
const { orderNo, tenantId, businessTradeNo } = uni.getStorageSync('queryContractParams')
uni.navigateTo({
url: `/pages/tabPages/transfer/index${uni.$u.queryParams({
orderNo,
tenantId,
businessTradeNo,
isOpen: true
})}`
})
}
}
})
为什么我的代码并没有进行在具体点击确定成功之后才进行回调呢?这个和我们具体的技术设计有关系,我是跳转到了一个中转页面,页面里面我会请求接口查询一下是不是真的签约成功了,所以对我来说用户是不是真的点击了并不重要,我只需要到中转页重新请求接口看一下是不是签约了就可以了,后面决定跳转到哪个页面,是成功页面还是失败的页面,所以这里根据自己的实际需求和技术方案进行适当的调整即可。
这个要看你的 onShow 这段代码是不是写到了 App.vue中了,如果不是,是拿不到对应的 sence 的
前面解释过,纯签约的过程是两个小程序之间的跳转,那么从不同的小程序跳转的场景值就是 1038
因为appId == ‘wxbd687630cd02ce1d’ 就是官方的纯签约小程序的 appid,所以保证你是从纯签约小程序回来的,而不是别的小程序回来的
记得引入一下:import { onShow } from ‘@dcloudio/uni-app’
我们可以看到第一段代码中其实有一个成功/失败/完成的回调函数,后面 App.vue 中也有一堆判断的回调,到底是指什么,首先第一段代码的回调是在你执行wx.navigateToMiniProgram的时候就会执行的,也就是说哪怕是用户没有拉起来纯签约,但是只要执行了wx.navigateToMiniProgram这个方法,那么那个回调就会执行,所以在这里判断是不是签约成功显然是不合理的,那么这里存在的意义是什么呢?这里我们在签约之前需要的参数进行在这里缓存,后面 App.vue中跳转页面的时候用到的就是缓存的最新的数据。这里是比较容易绕的,如果实在不太理解,你就可以不使用这个回调函数,也是可以完成功能的,你可以理解为这个回调其实就是微信以这个方法是不是被成功拉起作为参考来的,只要成功拉起了该方法,就是成功的回调,起来失败了,比如你的参数有问题,拉不起来,那么就是执行失败的回调,和是不是签约成功没有关系,而后面的 App.vue 才是判断是不是真的签约成功了 可以参考我的代码
// TODO: 设置拉起微信纯签约的参数 / 执行纯签约
contractSigning(setWechatcontractParams(getParamByUrl(payData.redirect_url)), resultSuccessCb, resultCb)
// TODO: 设置拉起微信纯签约的参数
const setWechatcontractParams = (params) => {
const signParams = params
const { appid, contract_code, contract_display_account, mch_id, notify_url, outerid, plan_id, request_serial, return_web, sign, timestamp, version } = signParams
const appletContractParams = {
appId: 'wxbd687630cd02ce1d',
path: 'pages/index/index',
extraData: {
appid,
contract_code,
contract_display_account,
mch_id,
notify_url,
plan_id,
request_serial,
timestamp,
sign
}
}
return appletContractParams
}
// TODO: 拉起微信纯签约之前的回调
const resultSuccessCb = () => {
const { orderNo, tenantId, businessTradeNo } = callBackParams
uni.setStorageSync('queryContractParams', callBackParams) // TODO: 存储签约结束需要的查询订单的参数
uni.navigateTo({
url: `/pages/tabPages/transfer/index${uni.$u.queryParams({ orderNo, tenantId, businessTradeNo })}`
})
}
说明这个 openID 已经开通了一个,这里需要先解绑,具体的操作步骤是:微信-我的-服务-钱包-支付设置-自动续费-找到那条你开通的地方,点击-关闭自动续费服务即可
这里如果正常的直连商户,其他的一些属性参数都是很容易获取的,只有一个 sign 的签名容易出问题,可以联系你们的后端使用签名校验工具进行生成对应的签名给到前端,前端模拟是不是成功跳转,只要可以跳转就说明是正常的。
这个问题只有安卓手机存在,因为安卓手机关闭屏幕之后重新进去小程序会重新执行上一次的场景值,也就是说如果你签约结束到了结果成功页,那么你关闭屏幕再打开,他会重新到签约结束到的中转页,再到结果页,这个问题苹果手机没有,解决方案是在你中转页的地方添加一个全局属性或者缓存,再 app.vue 中的 onShow 的地方判断条件判断这个缓存是不是存在的,因为签约的之后这个页面跳转到中转页了,app.vue 的 onUnload将缓存清空,这样下次进来的之后因为缓存没有了,所以就不会再到中转页面了。
以上就是关于微信小程序纯签约的代码逻辑过程分析,相信可以解答很多人的疑惑,如果你看完之后还对微信小程序的纯签约有疑惑的话,可以下方留言,也可以直接 QQ 群联系或者直接联系我,看到了都会进行解答的!
1.用户从商户小程序发起签约请求 (商户需确认委托代扣权限已开通,模板已审批通过,小程序APPID与商户号已绑定)。
2.商户将签约请求参数按照规则拼接之后,通过小程序跳转,向签约小程序发起签约请求。
3.用户在微信签约小程序选择支付方式完成签约。
4.微信将签约结果返回给商户。