虽互不曾谋面,但希望能和您成为笔尖下的朋友

以读书,技术,生活为主,偶尔撒点鸡汤

不作,不敷衍,意在真诚吐露,用心分享

点击左上方,可关注本刊

标星公众号(ID:itclanCoder)

如果不知道如何操作

点击这里,标星不迷路

━━━━━━

前言

对于支付下单在小程序当中是一个非常重要的功能,在未接入云支付之前,想要实现一个支付下单的功能,借助微信官方提供的wx.requestPayment()这个接口,发起微信支付

需要获取小程序的openId,然后调起数据签名(timeStamp,nonceStr,package,signType,paySign),这些字段参数处理起来仍是有些麻烦的

但接入了云支付之后,实现一个支付功能,就相当简单容易了,免签名,直接获取小程序wx.requestPayment的所需参数

开发者无需关心证书、签名、也无需依赖第三方模块,免去了泄漏证书,支付等敏感信息的风险;还支持云函数作为微信支付进行支付和退款的回调地址,不再需要定时轮询,更加高效

您将在本文中学习到:

  • 随机生成商品订单号,订单号不能重复

  • 实现云支付的功能

01

前提条件

资质:小程序主体开通微信支付(微信支付不支持个人小程序,需要企业账户才可以)的能力,并且已绑定商户号(绑定开通商户号)的小程序

02

开通 

开通微信支付云调用,在云控制台 -> 设置 -> 全局设置中开通,如下所示

点击添加商户号后进行账号绑定,这时候绑定了微信支付的商户号管理员的微信会收到一条授权确认的模板消息

点击模板消息会弹出服务商助手小程序,确认授权之后就可以在云开发控制台看到绑定状态为“已绑定”,而JS API权限也会显示“已授权”

03

微信支付流程 

  1. 在小程序端:用户在小程序端点击支付时,使用wx.cloud.callFunction调用云函数(例如:支付云函数名为questionPay),并将商品描述(body),商品订单号outTradeNo,子商户号subMchId,总金额totalFee等信息参数传递给questionPay云函数

  2. 在云函数端: 在questionPay云函数中调用统一下单接口cloud.cloudPay.unifiedOrder(),该函数接收一对象,包含的参数有,商品描述(body),商品订单号(outTradeNo),云坏境的 Id,以及需要填写结果通知回调函数(如:wechatpay),它是用来接收异步支付的结果,questionPay云函数会返回成功结果的对象中会包含payment字段(包含:appId,nonceStr,package,paySign,signType(MD5),timeStamp)参数,会唤起微信支付的界面

  3. 在小程序端wx.cloudFunctionsuccess回调函数(即调用questionPay云函数返回的对象)里调用wx.requestPayment接口发起支付请求,而从questionPay云函数返回的payment对象,参数,包含这个接口所需要的所有信息(参数),会弹出微信支付的界面

  4. 用户在小程序端支付成功,questionPay就会接收到异步的支付结果

04

微信云支付-小程序端代码 

以下是小程序端的示例代码

Page({/*** 页面的初始数据*/data: {slideVal: 5, // slide滑块默认初始值showSlide: false, // slide滑块默认显示showInput: true, // input表单默认隐藏onOff: true, // 其他金额切换开关},/*** 生命周期函数--监听页面加载*/onLoad: function(options) {},// 滑动滑块sliderChange(event) {const slideVal = event.detail.value;this.setData({slideVal,});},// 点击其他金额进行切换onOtherPayTap() {const onOff = this.data.onOff;if (onOff) {this.toggleChange(false, true);} else {this.toggleChange(true, false);}this.setData({onOff: !onOff,});},toggleChange(showSlide, showInput) {this.setData({showSlide,showInput,});},// 点击支付按钮,发起支付questionPay(event) {const { sliderVal, value } = event.detail.value;const showSlide = this.data.showSlide;const goodsnum = this._getGoodsRandomNumber();const subMchId = '1594460621'; // 子商户号,微信支付商户号,必填const body = '解锁探秘';const sliderPayVal = sliderVal * 100;const inputPayVal = value * 100;if (showSlide === false) {this._callQuestionPay(body, goodsnum, subMchId, sliderPayVal);} else {if (value) {this._callQuestionPay(body, goodsnum, subMchId, inputPayVal);} else {wx.showToast({icon: 'none',title: '亲,您没有输入任何数额,无法解锁哦',duration: 2000,});}}},// 请求questionPay云函数,调用支付能力_callQuestionPay(body, goodsnum, subMchId, payVal) {wx.cloud.callFunction({name: 'questionPay',data: {// 需要将data里面的参数传给questionPay云函数body,goodsnum, // 商品订单号不能重复subMchId, // 子商户号,微信支付商户号,必填payVal, // 这里必须整数,不能是小数,而且类型是number,否则就会报错},}).then((res) => {console.log(res);const payment = res.result.payment;console.log(payment); // 里面包含appId,nonceStr,package,paySign,signType,timeStamp这些支付参数wx.requestPayment({// 根据获取到的参数调用支付 API 发起支付...payment, // 解构参数appId,nonceStr,package,paySign,signType,timeStampsuccess: (res) => {console.log('支付成功', res);},fail: (err) => {console.error('支付失败', err);},});}).catch((err) => {console.error(err);});},// 随机生成商品订单号,订单号不能重复_getGoodsRandomNumber() {const date = new Date(); // 当前时间let Year = `${date.getFullYear()}`; // 获取年份let Month = `${date.getMonth() + 1 < 10 ? `0${date.getMonth() + 1}` : date.getMonth() + 1}`; // 获取月let Day = `${date.getDate() < 10 ? `0${date.getDate()}` : date.getDate()}`; // 获取天let hour = `${date.getHours() < 10 ? `0${date.getHours()}` : date.getHours()}`; // 获取小时let min = `${date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes()}`; // 获取分钟let sec = `${date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds()}`; // 获取秒let formateDate = `${Year}${Month}${Day}${hour}${min}${sec}`; // 时间return `${Math.round(Math.random() * 1000)}${formateDate +Math.round(Math.random() * 89 + 100).toString()}`;},
});

wxml代码

<view class="wrap"><form bindsubmit="questionPay"><view hidden="{{showSlide}}"><sliderbindchange="sliderChange"block-size="15"activeColor="#34bfa3"value="5"min="5"name="sliderVal"max="200"block-color="#34bfa3"show-value="{{false}}"/><view>¥<text>{{slideVal}}</text></view></view><view class="show-input-wrap" hidden="{{ showInput }}"><text>¥</text><inputclass="show-input"placeholder="1.00-200.00元"maxlength="3"type="number"focus="{{true}}"confirm-hold="{{true}}"name="value"value=""/></view><view class="other-pay-count" bindtap="onOtherPayTap"><text>{{showSlide === false? "其他金额": "取消"}}</text></view><button class="pay-btn" form-type="submit">支付</button></form>
</view>

wxss代码

/* miniprogram/pages/testpay/testpay.wxss */
.wrap {height: auto;background: #fff;text-align: center;font-size: 32rpx;
}.show-input-wrap {display: flex;justify-content: center;margin-top: 40rpx;
}.other-pay-count {font-size: 30rpx;color: #34bfa3;margin: 40rpx 0;
}.pay-btn {outline: none;border: none;background: #d43c33;color: #fff;font-size: 32rpx;border-radius: 0;
}

上面完成了在小程序端的支付的功能,触发支付操作,请求云函数,并且携带一些参数给该云函数,在云函数返回成功的结果中,拿到返回的参数,然后调用wx.requestPayment唤起微信支付.

注意

  • subMchId:子商户号,微信支付商户号,必填

  • body: 商品描述信息也必须填

  • inputPayVal: 支付默认金额值是0.01,所以需要做一下转化,必须是整型(int),不能是小数

  • goodsnum: 随机生成商品订单号,订单号不能重复(主要解决支付第一次后,无法在重复支付的问题,将订单号,设置为随机数就可以了的)

上面的...payment,其实是对象的解构,包含了如下参数,你不用解构也是可以的,挨个的取到对象value,传入wx.requestPayment中也是可以的

{appId: 'wx9fbad659d5dfgdc9bc'; // 是以你自己小程序appId为准nonceStr: 'nWQePZDsUCaKgNvP';package: 'prepay_id=wx30090731253190aa666629200';paySign: 'BFB4834C7969F661962dgdf96E1C37';signType: 'MD5';timeStamp: '1596071251';
}

...payment

wx.requestPayment({// 根据获取到的参数调用支付 API 发起支付...payment, // 解构参数appId,nonceStr,package,paySign,ignType,timeStampsuccess: (res) => {console.log('支付成功', res);},fail: (err) => {console.error('支付失败', err);},
});

等价于

const payment = res.result.payment;
const { appId, nonceStr, paySign, signType, timeStamp } = payment;
wx.requestPayment({// 根据获取到的参数调用支付 API 发起支付// ...payment,       // 等价于下面appId,nonceStr,package: payment.package, // 这个package无法解构,真是醉了的paySign,signType,timeStamp,success: (res) => {console.log('支付成功', res);},fail: (err) => {console.error('支付失败', err);},
});

05

云函数端支付代码 

在云函数根目录文件夹cloudfunctions右键,选择“新建 Nodejs 云函数”,新建一个云函数questionPay,然后再在index.js里输入以下代码,然后进行一些修改(注意参数名称是固定的,大小写也要原样写)

// 云函数入口文件
const cloud = require('wx-server-sdk');cloud.init({env: cloud.DYNAMIC_CURRENT_ENV,
});// 云函数入口函数
exports.main = async (event, context) => {const res = await cloud.cloudPay.unifiedOrder({body: event.body, // 商品描述,必填outTradeNo: event.goodsnum, // 商户订单号,必填,不能重复spbillCreateIp: '127.0.0.1', // 终端IP,必填subMchId: event.subMchId, // 子商户号,微信支付商户号,必填totalFee: event.payVal, // 总金额,必填envId: 'xxxxx', // 结果通知回调云函数环境,你自己小程序的坏境idfunctionName: 'wechatpay', // 结果通知回调云函数名,非必填参数,即使为空,也不影响支付,但是官方文档里写的是必填参数,表示已醉});return res;
};

利用了cloud.cloudPay.unifiedOrder云支付接口,接收小程序端请求该云函数的参数,最终将结果返回

注意

  • body为你的商家名(店名)-销售商品的类名

  • outTradeNo: 是商户订单号,32 个字符内,只能是数字、大小写字母_-,代码中是用时间戳随机数解决的

  • subMchId:你的商户 ID 或子商户 ID,填写云开发控制台- 设置- 全局设置- 微信支付配置里的商户号也可以

  • totalFee: 是支付的金额,单位是分,注意在小程序要做一下单位转化

  • envId: 是你的结果通知回调云函数所在的环境 ID

  • functionName: 结果通知云函数的名称(可以自定义)

修改完之后,点击questionPay云函数目录下的index.js,然后右键选择“云函数增量上传:更新文件”或右键云函数根目录文件夹 cloudfunctions,选择“上传并部署:云端安装依赖(不上传 Node_modules)”

最后就可以在开发者工具的模拟器里点击"发起支付"的按钮了,这时会弹出支付的二维码,扫码支付就可以了;也可以使用预览或真机调试

06

结语

你会发现用云开发的云支付实现微信支付功能,非常便捷,没有几行代码,你只需要专注自己的业务逻辑开发就可以了的,无需关心证书、签名、也无需依赖第三方模块,免去了泄漏证书,支付等敏感信息的风险

简直是太方便了的


公众号(ID:itclanCoder)

码能让您早脱菜籍,文能让您洗净铅华

可能您还想看更多:

表单输入框聚焦效果

微信小程序中 setData 详解

小程序-云开发-多图片内容安全检测

喜欢就点个在看再走吧

小程序-云开发-实现微信云支付功能相关推荐

  1. 微信小程序——传统开发模式与云开发模式对比

    目  录 1.传统开发模式与云开发模式的对比图 2.云开发技术能力说明 3.云开发技术特点 1.传统开发模式与云开发模式的对比图 通过传统开发模式与云开发模式的对比图可以看出传统开发模式需要开发者关注 ...

  2. 微信小程序红包开发思路 微信红包小程序开发思路讲解

    之前公司开发小程序红包,将自己在开发的过程中遇到的一些坑分享到了博客里.不少人看了以后,还是不明白怎么开发.也加了我微信咨询.所以今天,我就特意再写一篇文章,这次就不谈我开发中遇到的坑了.就主要给大家 ...

  3. 分享微信点餐小程序搭建步骤_微信点餐功能怎么做

    线下餐饮实体店都开始摸索发展网上订餐服务.最多人选择的是入驻外卖平台,但抽成高,推广还要另买流量等问题,也让不少商家入不敷出.在这种情况下,建立自己的微信订餐小程序,做自己的私域流量是另一种捷径.那么 ...

  4. 微信小程序/校园社区论坛/微信云开发/云函数

    # 一.框架来源 1.非常非常感谢B站up主"[梦千的曾哥哥](https://space.bilibili.com/404417254)"的开源框架. 没有他就没有这个小程序.如 ...

  5. 微信小程序php开发实例,微信小程序教程之demo:猫眼电影实例

    一.目录结构 采用的开发工具是Egret Wing,主要目录说明: 从目录可知整体结构简单,主要就是三个界面:首页homepage.电影详情页moviedetail.影院列表页cinema. 二.首页 ...

  6. 微信小程序api调起微信提供的功能-网络、媒体、文件、数据存储、位置、设备、界面、开发接口

    微信小程序-API 框架提供丰富的微信原生API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等. 说明: wx.on 开头的 API 是监听某个事件发生的API接口,接受一个 C ...

  7. 【微信小程序企业级开发教程】订阅消息功能

    文章目录 1 功能介绍 2 使用说明 1 功能介绍 消息能力是小程序能力中的重要组成,我们为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验. 订阅消息推送位置:服务通知 订阅消息下发条件:用 ...

  8. 最新版2023免费设计艺术签名多种模式微信小程序源码 支持微信流量主功能

    某交易网站上卖500元的源码,免费设计艺术签名,支持微信流量主 下载链接 网盘源码   密码:3lev 背景 近年来,微信小程序已经成为了移动互联网领域中的一个重要平台,它可以帮助开发者轻松地开发和发 ...

  9. 【微信授权登录】uniapp开发小程序,实现获取微信授权登录功能

    一.解题思路: 微信授权登录(获取用户信息) 1.先获取用户信息--用户授权允许后,通过调用uni.login 可以获取到code. 2.拿着获取到的code去调用--登录接口,可以获取到token. ...

  10. 微信小程序后台开发详解

    微信小程序后台开发 前言 开发环境 开发流程 项目整体结构 接口开发 项目部署 ip映射 Nginx反向代理 gunicorn+super多进程开启服务+进程监控 ssl证书 小程序常用功能 微信支付 ...

最新文章

  1. 【TPAMI2020】目标检测中的不平衡问题:综述论文,34页pdf
  2. 基于贝叶斯算法实现简单的分类(java)
  3. 【机器学习】机器学习概述
  4. (原創) 如何讀取/寫入文字檔? (IC Design) (Verilog)
  5. flash builder 4.7 debug via usb device iPhone 4s - device not found
  6. 记事本和textarea中的换行
  7. 在matlab中使用spm8,在matlab中同时使用spm2,spm5,spm8
  8. mqtt 发送消息过多_阿里云MQTT服务端注解式消息处理分发与同步调用实践小结
  9. SpringMVC注解HelloWorld
  10. 质因数分解(洛谷P1075题题解,Java语言描述)
  11. 20145212 《信息安全系统设计基础》第3周学习总结
  12. 永别了!2200元,老外眼中的2200元神机缺货数月后下架
  13. sql crud_SQL Server中的CRUD操作
  14. 要做网络营销 这样的讲座不能错过
  15. Google Python 编程风格指南
  16. 确定你的电脑是否支持安装64位操作系统
  17. 气溶胶反演输入转化错误_暗目标法的Himawari-8静止卫星数据气溶胶反演
  18. mysql 1114_mysql 解决 ERROR 1114 (HY000): The table 'XXX' is full
  19. 【YOLOX 论文+源码解读】YOLOX: Exceeding YOLO Series in 2021
  20. Pdf 插入图片 | 指定位置插入图片 不改变原格式 直接操作 pdf

热门文章

  1. powerbi嵌入到HTML5,如何把Power BI嵌入到Web应用中
  2. 中国矿业大学本科毕业设计Latex模板cumtthesis
  3. mysql版本查询命令
  4. 营业收费系统 建立报表库服务器,浅谈计算机在自来水收费系统的重要应用
  5. (MTT)连续能量函数最小化方法
  6. 录制计算机课,ClassIn怎么录制视频 录课操作步骤
  7. iTextSharp 添加图片
  8. 腾讯推出移动端动画组件PAG,释放设计生产力!
  9. 2D虚拟试衣——服装变形
  10. 农业银行联行号怎么查询_中国农业银行大额联行号12位是什么,怎么查找