微信小程序运营支付规范


微信官方针对有虚拟支付功能的小程序下发了整改通知.截至5月8号,平台将对账号屏蔽iOS系统的支付接口调用.我去查了<<微信小程序运营规则>>,如上图.发现小程序的支付规范中已经做了明示.
这次整改主要含2方面内容:
1.虚拟支付
不是所有提供支付功能的小程序都要整改,仅仅只有涉及”虚拟支付”的小程序需要调整.什么是虚拟支付呢?说白了就是购买非实物,摸不到的物品.比如:VIP会员,充值,在线课程,虚拟物品等等.
2.iOS系统
本次整改,只涉及iOS系统内运行的小程序,安卓系统不受影响,开发者们依然可以在安卓版本内调用微信支付.另外小游戏内的安卓购功能,也不受影响.
针对规则,开发者们可以如何绕过呢?我整理后发现主要有4种方式.
1.小程序跳转APP或者引导用户去APP支付(例如得到小程序)
2.引导至公众号支付或者利用公众号支付(例如乐乐国学)
3.将虚拟变成实体
4.收费变免费
最后公司决定选用第二种支付逻辑,也就是利用公众号支付来实现绕过小程序支付.
前端操作流程如下图:其本质还是利用公众号支付来实现支付功能

接下来我们来一步一步看代码是如何实现这套流程的.


第一步:现在WXML中引入按钮组和苹果支付的组件

    <!-- 屏幕下方的功能按钮  拼团 原价购买 集赞   --><course_actionBtn id="course-actionBtn" bindDialogEvent="onDialogEvent" bindApplePayEvent="onApplePayEvent" bindAndroidPayEvent="onAndroidPayEvent" bindPriseEvent="onPriseEvent" data-mode="{{data}}"> </course_actionBtn>
<!--苹果手机支付验证框  -->
<payment-dialog id="payment-dialog" data-mode="{{isGroup}}" payArgumentStr="{{payArgumentStr}}"></payment-dialog>

第二步:在页面的js里在点击拼团按钮的triggerEvent方法里弹出苹果支付的组件,因为专栏详情页下方的入口按钮组也封装成了组件,为了减少专栏详情页的代码数量.也是基于面向对象的考虑,单独的业务逻辑抽取出来,方便其他页面如果使用类似代码的话,方便移植.比如产品新加入的集赞入口,这样就可以直接修改按钮组组件的逻辑就好,不需要大范围的修改专栏详情页的代码逻辑.又比如将来如果有一个新的业务功能也需要这套按钮入口,直接引入组件就可以了.利于扩展.可以看到这里按钮组是一个组件,当点击拼团支付或者原价购买时,因为区分了苹果支付和安卓支付,我在这里将苹果支付也抽成了一个组件.这样可以在安卓系统上走小程序原生支付,在苹果系统上走我们特殊处理的苹果支付.目的也是为了将来方便扩展.这里有一个隐藏的坑.这里记录下来防止遗忘.

官方给的tip:
注意:必须在两个组件定义中都加入relations定义,否则不会生效。下图是官方文档给出的relations支持的type类型.

综上,我的理解是微信目前只支持类似这种包含关系的组件嵌套组件.它必须满足的是一种UI层面的嵌套,而我现在实现的是一种逻辑意义上的嵌套,所以不满足.这里我选用了第二套方案.利用组件的事件机制,将所有的组件都引入page对象中,然后监听每个组件的点击事件,并将触发结果从子组件中全部传到page对象中进行回调处理.

我们重新回到苹果支付这里.弹出苹果支付的组件后(就是流程图的第一幅图).
//弹出苹果支付

  onApplePayEvent: function (e) {var isGroup = e.detail.isGroupvar payArgumentStr = e.detail.payArgumentStrthis.setData({ isGroup: isGroup, payArgumentStr: payArgumentStr})this.paymentDialog.showPopup()},
  // 三人拼团tapPuzzle: function(e) {var result = this.dataset.modevar courseID = result.idvar that = this//防止按钮重复点击if (util.isReClick() || this.data.clickStatus == 1) return//前置验证是否需要弹出收集手机号的验证弹框util.checkoutShowMessageCodeDialog(this, function(e) {if (e == 1) {that.setData({clickStatus: 1})pm = new PayManager()pm.groupBuyPayment(courseID, {iosCallback: res => {var payArgumentStr = res//调起iOS支付逻辑, payArgumentStr也是在这里通过组件事件给传递到page对象里面,PayManager()是项目里我封装的支付管理类,一种es6的写法------------这里最重要that.triggerEvent("ApplePayEvent", {isGroup: 1,payArgumentStr: payArgumentStr})that.setData({clickStatus: 0})},androidCallback: res => {var code = res.codevar result = res.dataif (code == -1) {that.setData({clickStatus: 0})console.log("调起拼团接口失败");util.toast(result)} else if (code == -2) {that.setData({clickStatus: 0})console.log("拼团调起微信支付失败");// util.toast(result.errMsg)} else if (code == 0) {that.setData({clickStatus: 0})console.log("拼团调起微信支付成功");var result = pm.getGroupResult();//跳转到拼团详情页面wx.navigateTo({url: '../group-payment/group-payment?groupBuyId=' + result.groupBuyId,})}}})} else if (e == -1) {console.log("手机号验证失败")} else if (e == 2) {that.triggerEvent("DialogEvent")}})},

下面这段代码是支付管理类里关于拼团购买的实现

  //拼团购买groupBuyPayment(courseId, callBack) {var that = this//获取当前用户手机类型var isIOS = util.isIOSPlatform(app.data)if (isIOS == true) {//组装sessionFrom,带到客服会话列表里面if (courseId) {var object = {};object.courseId = courseId;object.isGroupBuy = "1";//1是拼团购买 0是原价购买object.groupBuyId = "";//groupBuyId如果有值就是参与拼团 没有值是发起拼团var argument = JSON.stringify(object);} else {console.log("courseId为空")}//这里这个argument就是上面那个payArgumentStrcallBack.iosCallback(argument)} else {//安卓支付var courseID = courseId;//1.发起拼团,获取支付的前置信息获取network.POST("/groupBuy/startGroupBuy", {params: { courseId: courseID },success: function (result) {// successvar r = result.data.data;that.groupResult = rvar groupId = r.groupBuyId;var timestamp = r.timestamp;var nonceStr = r.nonceStr;var pack = r.package;var paysign = r.paySign;//2.调起微信支付util.requestWXPayment(timestamp, nonceStr, pack, paysign, function (res) {callBack.androidCallback({ code: 0, data: res })}, function (res) {callBack.androidCallback({ code: -2, data: res })})},fail: function (error) {console.log("error:")console.log(error)callBack.androidCallback({ code: -1, data: error })}})}}

第三步:

 <button class='popup_ok' open-type='contact' session-from='{{payArgumentStr}}'>确定</button>



打开客服消息时,将这个payArgumentStr传给后台.它是怎么传给后台的呢?看上图,是我在小程序API中截取的图片.我们先看第一幅图红框位置.它的意思就是当用户在小程序中点击一个openType=”contact”的按钮时就会产生一个数据包,这个数据包里有一个SessionFrom字段.我们的payArgumentStr就是通过这个字段传给后台的.在看第二副图,就是微信服务器会将消息(或事件)的数据包(JSON或者XML格式)POST请求开发者填写的URL。开发者收到请求后可以使用发送客服消息接口进行异步回复。简单解释就是从用户点击客服会话按钮,就会产生第一个数据包,可以利用这个数据包从外面带一些自定义的参数到会话列表中,这个数据包会先发到微信服务器,微信服务器收到这个数据包后,会将这个数据包发给我们自己的服务器,因为小程序后台配置的开发者URL就是我们自己的服务器地址,服务器收到微信服务器的请求后获取到这个payArgumentStr,也就是拿到了订单信息.再根据这些信息生成支付链接,当监听到用户发送客服消息时将支付链接回调回去.显示在客服会话列表中.
现在我们再来看看这个payArgumentStr到底是什么?它其实是我和后台约定好的一个json对象转成的字符串.这个json对象会带一些必要信息到后台,让后台知道我当前发起的什么样的支付请求,是原价购买,是我要拼团,还是参与拼团.如果是我要拼团,需要课程ID,如果是参与拼团的话,需要拼团ID.这些参数都是我在打开客服列表会话时,传给后台,将来后台拿到这些参数,处理后,把这些信息拼在支付链接后面返回给我.就是流程图第3幅图里面的点击立即购买,它其实后台返回的一条带有订单信息的支付url链接.(这里是有安全隐患的).这个url链接是我自己写的并发布好的一个web页面,在这个页面里我会先拿到订单信息,然后调起公众号支付完成对该订单的付款.后台监听到这个单子付过款后,就会更新相关字段,这样我跳回小程序后,来到专栏详情页就可以去服务器更新专栏课程的最新状态,就专栏解锁.

function wxConfig() {//通过config接口注入权限验证设置$.ajax({type: 'GET',url: app.url.config_url + 'wechat-js-config/xcx',data: {url: window.location.href //window.location.href指的永远是访问该网页时用的URL. },success:function (msg,req) {if(req == 'success') {console.log("=====获取成功======");var data = msg.data.js_config;wx.config({debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。appId: data.appid, // 必填,企业号的唯一标识,此处填写企业号corpidtimestamp:data.timestamp , // 必填,生成签名的时间戳nonceStr: data.nonceStr, // 必填,生成签名的随机串signature: data.signature,// 必填,签名,见附录1jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2});// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后wx.ready(function(){//获取页面URL链接的查询参数var args = app.getQueryStringArgs();console.log(args);//1.获取支付类型var paymentType = args.isGroupBuy;var courseId = args.courseId;var groupBuyId = args.groupBuyId;if (paymentType == 1) {if (groupBuyId != "null") {//参团人获取拼团预付单信息joinGroupBuy(groupBuyId);}else {//拼团发起人获取拼团预付单信息startGroupBuy(courseId);}}else {//原价购买的预付单信息    unlockCourse(courseId);}});}else {app.showTip('请求超时');}},error:function (msg) {app.showTip(JSON.stringify(msg));}})
}

//支付成功后跳转到公众号文章页面,就是流程图中第6幅图.这个页面是在公众号后台配置生成的公众号文章,在编辑的时候,可以在文章里面关联小程序的图文消息.这样就可以通过点击公众号里的小程序图文消息实现从公众号向小程序的跳转,完成闭环.这里有个小坑,就是生成的文章链接是一个临时链接,是有时效的,可以百度一下如何获取公众号文章的永久链接拿到永久链接,很简单,这里就不给传送门了.这里还有一个小需求,就是在web页面调起支付后,如果取消支付,就关闭当前页面,回到客服会话列表.我的思路是在支付的封装方法里,监听到支付取消后跳回处理.

//跳转到公众号文章页面
function nextArticePage() {window.open("https://mp.weixin.qq.com/s/IxGJRB5oUtE8sP292KATOw");
}
if(res.errMsg == "chooseWXPay:cancel" ) {WeixinJSBridge.call('closeWindow');}

综上,就是我前端的整体实现逻辑,可能会有很多不准确的地方,感兴趣的朋友看到后可以给我指出来.提前谢谢了.
参考连接:
2小时后,小程序“虚拟支付”更改规则,这有4种“曲线救国”的方式!

微信小程序 iOS支付相关推荐

  1. ios微信小程序虚拟支付解决办法

    ios微信小程序虚拟支付整理介绍 目前iOS端暂不支持虚拟支付,微信小程序虚拟支付仅涉及到ios端,安卓端不受影响. 小程序支付规范 https://developers.weixin.qq.com/ ...

  2. 微信小程序篇(微信小程序的支付)

    微信小程序的支付和微信公众号的支付是类似的,对比起来还比公众号支付简单了一些,我们只需要调用微信的统一下单接口获取prepay_id之后我们在调用微信的支付即可. 今天我们来封装一般node的支付接口 ...

  3. ios 上传图片失败 小程序_微信小程序ios端 使用ajaxSubmit上传图片失败,android没问题...

    微信小程序ios端 使用ajaxSubmit上传图片失败,android没问题 微信小程序开发上传图片,使用ajaxsubmit,post请求,form设置multipart/form-data, a ...

  4. 微信小程序服务器支付sdk,微信小程序之支付后如何调用SDK的异步通知

    微信小程序之支付后如何调用SDK的异步通知 发布时间:2021-07-05 10:47:33 来源:亿速云 阅读:57 作者:小新 这篇文章主要介绍微信小程序之支付后如何调用SDK的异步通知,文中介绍 ...

  5. 解决微信小程序IOS中使用picker弹出内容和手机软键盘重叠的问题

    解决微信小程序IOS中使用picker弹出内容和手机软键盘重叠的问题 项目需求: 一个信息提交页面:有input输入框,有picker选择器 遇到的问题: 点击input输入框时,手机自动弹出键盘,但 ...

  6. 微信小程序调用支付接口支付(tp5、小程序)

    微信小程序调用支付接口支付 今天记录一下学习的小程序调用微信支付接口 一.先理清一下调起微信支付的整个流程. 1.就是先调用微信的支付统一下单api获取到prepay_id 2.然后后端再将这个pre ...

  7. 微信小程序ios端唤醒不了拨打电话或者部分电话拨打不了解决方案

    目录 简介 技术 问题 解决方案 简介 主要解决微信小程序ios端唤醒不了拨打电话或者部分电话拨打不了问题,使用安卓手机就可以轻松的唤醒拨打电话. 技术 uni-app前端小程序框架 问题 在调试微信 ...

  8. 解决微信小程序ios端滚动卡顿的问题

    解决微信小程序ios端滚动卡顿的问题 参考文章: (1)解决微信小程序ios端滚动卡顿的问题 (2)https://www.cnblogs.com/goloving/p/10563472.html 备 ...

  9. 微信小程序—微信小程序端支付代码

    只有微信小程序端的代码,如下 Page({data: {},onLoad: function (options) {// 页面初始化 options为页面跳转所带来的参数var that = this ...

最新文章

  1. 不敢相信,居然用Java写了个“天天酷跑”!
  2. [java]OutOfMemoryError 原因及解决办法
  3. [转]C#操作XML方法详解
  4. linux系统调用sysconf(获取系统信息)
  5. 抽象工厂模式java_抽象工厂模式
  6. python excel转xml
  7. 如何在 FaceTime 通话中共享您的屏幕?
  8. 【PLSQL】PLSQL安装、破解以及汉化教程
  9. MCU_ZigBee协议栈相关函数总结
  10. Android 8.0正式版彩蛋,炸了!微信8.0竟然有18个彩蛋更新!
  11. 远程访问SOAP协议接口
  12. JAVA_OPTS(JVM相关运行参数的变量)设置
  13. android厨房的使用方法,懒人生活的福音:Android在厨房_软件资讯技巧应用-中关村在线...
  14. php微信 api,PHP微信API接口类
  15. 关于3分频电路的讨论
  16. 【备战蓝桥杯】USACo-- airpro【改变策略】
  17. vue 一个动态链接url转成二维码
  18. 漏洞复现----11、GlassFish任意文件读取
  19. kdj值应用口诀_KDJ应用口诀,一文教你巧妙利用KDJ买卖股票
  20. jsp高校活动管理系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

热门文章

  1. centos mysql 连接_centos支持远程mysql连接
  2. 软件架构--入门导读--欲穷千里目,更上一层楼
  3. 【BI应用案例】大都会人寿活跃分析经济时代的秘密武器
  4. python_接口自动化测试框架
  5. MFC中UpdateData函数的使用解释
  6. BurpSuite之Intruder
  7. FinalShell SSH工具 优秀国产xshell替代,ssh客户端,ssh工具
  8. Webmin -- Webmin Users
  9. HTML <head> 元素
  10. 100个变态的软件测试面试题及答案!——看完变态面试官对你竖起大拇指!