微信小程序免输卡号绑定银行卡(前端流程及代码)

微信跳转小程序实现免输卡号绑定银行卡

微信免输绑卡在 项目启动前,银行会与微信官方对接,会有一个技术支持的群,正在做免输绑卡功能或者已经做过免输绑卡功能的朋友,肯定知道群里技术助手回答问题的效率有多高,一般一天1~2句话,很影响进度;而且技术助手大多数会让你参照文档,对于已经做过的,可能感觉不难,对于正在做的,难在不懂整个流程;我这里简单总结下,也希望对后面做免输绑卡功能的朋友有帮助。


需要实现的效果图:
在这里插入图片描述
首先,我先说下我在做免输绑卡时遇到的比较迷茫的几个问题?
1、从微信到小程序,微信和小程序如何做交互,小程序如何获取微信参数?
微信打开小程序前所有功能,都是微信自带的,不需要开发;微信跳转小程序后,可以在小程序onload中接收参数,拿到参数(银行三要素)调后端接口进行解密,获取银行卡号。
2、小程序免输绑卡插件,使用时有几种场景,银行卡列表使用插件和银行卡列表不使用插件,是自己画页面,还是使用插件带的样式?
银行官方人员会建议你全使用插件的页面,这样容易审核通过,所以作为前端人员,一个页面不用画,我是是画了一大堆页面,结果后面全部改成了使用插件带的页面。
3、验短信页面是不是免输绑卡插件带的,短信接口怎么处理?
验短信页面是插件带的,只需要拉起验短api,短信页面自带的有,接口前端也不用处理。
免输卡号产品简介、接入流程、开发指引:
https://pay.weixin.qq.com/wiki/doc/apiv3/Offline/open/chapter1_1_1.shtml
免输卡号绑卡小程序插件简介:
https://mp.weixin.qq.com/wxopen/plugindevdoc?appid=wx1bf7bb903143fa2c&token=1244483084〈=zh_CN

流程

1、在onload中接收微信传来的参数,调接口获取openid,校验银行侧的openid和微信传来的openid是否一致;
2、拿到微信传来的参数,引入sha1加密方式,按照免输绑卡文档的拼接方式进行加密,再将加密后的结果与微信传来的paysign做对比,如果一致,则通过;
3、使用微信侧传来的三要素,调后端接口查询银行卡信息,使用插件,展示查询的银行卡信息;
4、在插件的用户点击同意的方法事件中,先调后端的绑卡的接口;绑卡接口成功不代表绑卡成功,需要在绑卡接口成功的回调中再拉起验短api,按照验短api需要送的字段(验短api需要送字段拼接的加密paysign;验短api传的时间戳随机数,只能是9位,要截取)

注:在使用插件前,需要在pages.json页面中配置使用插件,可以在小程序公众平台查看插件的appid
在这里插入图片描述

在这里插入图片描述

后面附带了我的代码,希望对后面的前端朋友有帮助

代码:

<template>
</template>

<script>
	import {
		accountNoFormat
	} from '@/utils/util.js';
	import {
		showModal
	} from '@/core/app.js';
	// 引入sha1算法
	import sha1 from 'sha1';
	export default {
		data() {
			return {
				param: {}, //接收微信传来的参数
				noncestr: '', //生成随机不到32位字符串
				paysign: '', //生成签名
				openid: '', //用于银行校验
				sessionKey: '',
				timestamp: '', // 随机数
				data: {
					pluginData: { // 银行向插件传的数据
						appId: '', // 银行小程序的appid
						bankCardLists: []
					}
				},

				// 绑卡接口需要送的字段
				phone: '', // 手机号
				sgntrPrsnIdentTp: '', // 证件类型
				sgntrAcctNm: '', // 签约人账户名称
				sgntrPrsnIdentNo: '', // 证件号
			}
		},
		onLoad(option) {
			// 调用一个loading
			wx.showLoading({
				title: '加载中'
			})
			// 生成随机32位字符
			this.randomStr();
			if (option != undefined && option != null && option != '') {
				this.param = option
				this.data.pluginData.appId = option.appid
				// wx签名校验
				this.compareWXPaysign();
			};
		},

		methods: {
			// 获取Code
			getCode() {
				var that = this
				uni.login({
					// timeout: 10000,
					provider: 'weixin',
					success: function(data) {
						//获取临时登录凭证code
						that.getUserEnter(data.code)
					},
					fail: function(err) {
						console.log("loginerr", err);
					}
				})
			},
			// 获取用户openid 
			getUserEnter(jsCode) {
				this.$api.getUserOpenid(jsCode).then(res => {
						if (res.code == 'MOP000000') {
							this.openid = res.data.data.openid
							this.sessionKey = res.data.data.session_key
							this.compareOpenid(this.openid)
						}
					})
					.catch(error => {});
			},
			// 校验微信传来的openid
			compareOpenid(id) {
				const openid = this.param.openid
				// 校验不通过,进入无卡绑定页面
				if (openid == id) {
					this.getCardInfo()
				} else {
					if(this.checkingVersion()) {
					      this.goPlugin();
					 }
				}
			},
			// 查询银行卡信息
			getCardInfo() {
				const encbankelem = this.param.enc_bankelem;
				let data = {
					threeElements: encbankelem,
				};
				this.$api.queryCard(data).then(res => {
					if(res.code == 'MOP000000'){
						this.phone = res.data.phone; // 手机号
						this.sgntrPrsnIdentTp = res.data.cre_type; //证件类型
						this.sgntrAcctNm = res.data.true_name; //签约人账户名称
						this.sgntrPrsnIdentNo = res.data.cre_id; // 证件号
						// 给储蓄卡数组赋值
						let debitCardList = [];
						debitCardList = res.data.AcctInfoList;
						if (debitCardList.length != '0') {
							debitCardList.forEach((item) => {
								item.cardNumber = accountNoFormat(item.acctNo);
								item.accTCardType = 'XX银行 储蓄卡';
								item.sgntrPrsnAcctTp = '00';
								item.cardType = 'DEBIT';
							})
						}
						// 给信用卡数组赋值
						let creditCardList = [];
						creditCardList = res.data.AccountInfoList;
						if (creditCardList.length != '0') {
							creditCardList.forEach((item) => {
								item.cardNumber = accountNoFormat(item.cardNbr);
								item.acctNo = item.cardNbr;
								item.accTCardType = 'XX银行 信用卡';
								item.sgntrPrsnAcctTp = '01';
								item.cardType = 'CREDIT';
							})
						}
						this.data.pluginData.bankCardLists = [
							...debitCardList,
							...creditCardList
						]
						if(this.checkingVersion()) {
						      this.goPlugin();
							  wx.hideLoading();
						 }
					} else{
						if(this.checkingVersion()) {
						      this.goPlugin();
							  wx.hideLoading();
						 }
					}
				})
			},
			// 进入页面微信侧数据生成签名并做校验
			compareWXPaysign() {
				const appid = this.param.appid
				const appkey = 银行小程序申请的appkey 
				const bind_tail = this.param.bind_tail
				const enc_bankelem = this.param.enc_bankelem
				const noncestr = this.param.noncestr
				const openid = this.param.openid
				const sessionid = this.param.sessionid
				const timestamp = this.param.timestamp
				const paysign =
					`appid=${appid}&appkey=${appkey}&bind_tail=${bind_tail}&enc_bankelem=${enc_bankelem}&noncestr=${noncestr}&openid=${openid}&sessionid=${sessionid}&timestamp=${timestamp}`
				const paysign1 = this.param.paysign
				// 将拼接的字符进行sha1加密生成签名
				// 校验生成的签名与微信传来的签名是否一致
				if (sha1(paysign) == paysign1) {
					this.getCode()
				} else {
					if(this.checkingVersion()) {
					      this.goPlugin();
						  wx.hideLoading();
					 }
				}
			},
			// 生成随机字符串
			randomStr() {
				/*默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1*/
				var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
				var maxPo = $chars.length;
				var randomNum = '';
				for (var i = 0; i < 32; i++) {
					randomNum += $chars.charAt(Math.floor(Math.random() * maxPo));
				}
				this.noncestr = randomNum;
			},
			// 调用蒙层插件
			goPlugin() {
				const that = this
				wx.navigateTo({
					url: 'plugin://myPlugin/plugin-index',
					events: {
						// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
						agreeBtnClick: function(data) { // 用户点击了协议蒙层的“同意”按钮
							const appid = that.param.appid
							const appkey = 银行小程序申请的appkey 
							const noncestr = that.noncestr
							const package1 = `bank_type=NCBCB_${data.selectedCard.item.cardType}`
							const sessionid = that.param.sessionid
							const timestamp = Date.now().toString().substring(0, 10)
							const paysign =
								`appid=${appid}&appkey=${appkey}&noncestr=${noncestr}&package=${package1}&sessionid=${sessionid}&timestamp=${timestamp}`
							// sha1加密,并存入paysign
							const paysignSuccess = sha1(paysign)
							var encodsndBackURL = encodeURIComponent(`bind_scene=NO_CARD_BIND&sessionid=${that.param.sessionid}`)
							// 调用一个loading
							wx.showLoading({
								title: '加载中'
							})
							const param = {
								sndBackURL: encodsndBackURL, // 回跳地址
								tranTpCd: "0207", // 交易类型码 固定填写“0207”(协议签约受理)
								acptInstNo: "1", // 受理机构号 写死
								acptInstIndID: "Z2004944000010", // 受理机构标识 写死
								rsrvMblNo: that.phone, //手机号
								sgntrPrsnIdentNo: that.sgntrPrsnIdentNo, // 证件号
								sgntrPrsnIdentTp: that.sgntrPrsnIdentTp, // 证件类型
								sgntrAcctNm: that.sgntrAcctNm, // 签约人账户名称
								sgntrBnkAcctNo: data.selectedCard.item.acctNo, // 卡号
								sgntrPrsnAcctTp: data.selectedCard.item.sgntrPrsnAcctTp, // 动态判断
								acctInstIndNo: "C1050331000044", // 账户机构标识号 
								pymtCnlTp: "EPCC" // 
							}
							that.$api.oneclkBindcardToacct(param).then(res => {
								if(res.code == 'MOP000000'){
									// 调起微信验短页面的数据
									wx.phoneBindCardVerifySms({
										timestamp: timestamp,
										noncestr: that.noncestr,
										package: package1,
										paysign: paysignSuccess,
										sessionid: that.param.sessionid,
										signtype: 'sha1',
										appid: that.param.appid,
										success(res) {
											wx.hideLoading();
										},
										fail(res) {
											wx.hideLoading();
										}
									})
								}
							})
						},
						disagreeBtnClick: function() { // 用户点击了协议蒙层的“不同意”按钮
							console.log('用户点击了协议蒙层的“不同意”按钮');
						},
						openUserProtocol: function(data) {
							console.log('用户点击了某个协议,协议信息为:', data.protocolInfo);
						},
						noCardsStatusBtnClick: function() { // 当前没有任何银行卡,展示“无卡,空列表”页面,用户点击“知道了”按钮,退出小程序,回到微信支付选择银行的“银行列表页”
							console.log('没有银行卡场景,用户点击了知道了按钮');
						},
					},
					success: (res) => {
						// 通过eventChannel向被打开页面传送数据
						res.eventChannel.emit('bankListDataSend', {
							bankData: that.data.pluginData
						});
					},
					fail: (res) => {
						console.log('跳转插件失败', res);
					}
				})
			},
			checkingVersion() {
				if (this.getOpenerEventChannel) {
					// 当前版本支持
					return true;
				}
				wx.showModal({
					title: '更新提示',
					content: '当前版本过低,请更新微信到最新版本。',
					showCancel: false,
					confirmText: '知道了'
				});
				return false;
			},
		}
	}
</script>

<style>
</style>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

smileAgain-lg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值