先来个效果图 ^_^
微信支付功能,个人公众号是没有办法进行开发支付功能的,需要是使用非个人公众号进行注册(如:营业执照等,可以去淘宝购买一个也行 大概500左右)
公众平台的配置可以参考文档,这里主要是微信官网注册非个体公众号的否需代码操作。(也就是和我们码农相关的操作了)
支付的整个流程:当然和官方的操作 稍有不同
1. 先将订单信息交给后台存储,储存状态是未支付;
2. 通过云函数调用统一下单接口,返回支付前的必备数据;
3. 通过统一下单的接口返回的数据,打开微信的支付界面(支付界面的成功回调函数,不用和后台打交道,由回调函数操作,原因下面会讲到);
4. 用户输入完密码后,微信会将支付结果交给 回调地址 (该回调地址在统一下单接口中已经设置过了);
5. 在回调地址中将数据提交给后台服务器,后台将订单的支付状态更改为已支付即可。
1). 根目录下创建一个名为 cloud 的文件夹用于存放所有的云函数;
2). 对了 cloud 文件夹右击,选择 新建一个Node.js 云 的选项,命名为 pay ;
3). 此时还需要在小程序根目录中的 project.config.json 文件中添加如下代码:
"cloudfunctionRoot": "cloud/",
效果图图下:
4). 接着上传云函数(云函数每次修改都需要上传)
5). 在app.js文件中添加环境名称
App({
onLaunch:function(){
wx.cloud.init({
env:"yicai-p6gne"
})
},
...
...
...
env参数——>是指定环境名称;
如何查看环境名称:
编辑pay云函数中的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.goodName, //商品名称 或 商品描述
"outTradeNo": event.outTradeNoTo, //订单号
"spbillCreateIp": "127.0.0.1", //回调地址
"subMchId": "*********", // 微信支付商户号
"totalFee": event.totalFee, //商品支付金额 单位(分) 100代表一块钱
"envId": "yicai-p6gne", //云开发环境ID
"functionName": "pay_cb" //回调的云函数
})
return res
}
效果图如下:
js代码如下:(具体参数 根据自己的需求改动,注释很齐全都有说明)
//此处可以是点击事件
paydata: function (e) {
var that = this;
var outTradeNo = ""; //订单号
var jiaqian = 1; // 开发阶段先设置交易金额为0.01元
// var jiaqian = parseInt(that.data.filesM * 100); //获取真实付款金额
outTradeNo = Math.floor((Math.random() * 1000) + 1) + "1371" + new Date().getTime(); //生成订单号
that.setData({
outTradeNo: outTradeNo
})
//准备支付(先获取必要参数)
wx.cloud.callFunction({
name: 'pay', //调用微信得pay云函数
data: {
goodName: "农夫山泉", // 商品名称 或 商品描述
totalFee: jiaqian, // 需要支付的金额
outTradeNoTo: outTradeNo // 生成的订单号
},
success: res => {
console.log("获取字符参数成功", res); // 此处是通过pay微信云函数,有微信给我们生成支付前的必要参数
const payment = res.result.payment // 微信会返回支付需要的必备数据
wx.hideLoading()
//调起支付(获取必要参数后,开始真实调用微信支付窗口)
wx.requestPayment({
...payment,
success(res) { //如果支付成功了,进入success函数回调(成功后具体操作看实际业务需求)
console.log('支付成功', res)
wx.showLoading({
title: "付款成功"
})
setTimeout(function () {
wx.hideLoading()
that.upload(e); //将用户购买的数据 交给 后台
}, 700)
},
fail(res) {
console.error('支付失败', res)
wx.showLoading({
title: "支付失败"
})
setTimeout(function () {
wx.hideLoading()
}, 1600)
}
})
},
fail(res) {
console.log("获取支付参数失败", res);
}
})
},
js代码效果图:
注意在微信小程序开发工具中调起支付的界面如下:
注意在真实手机的小程序中进行支付的效果图如下:
但是还没有结束????
这种情况基本上可以使用,但是如何用户在手机上支付的时候,由于使用wx.requestPayment 的方法打开支付界面,需要用户手动点击确认按钮才会进入success 回调函数,如下图
只有用户点击完成的时候才会触发 wx.requestPayment 的成功回调函数,解决方法如下
上面是官网提供的流程图,(云函数的代码其实就是放在服务器上的代码)
在图中的最后一步,微信会将用户支付的信息回调给商户系统也就是回调给自己的后台服务器(而此时的微信回调事件是在用户输入完密码付款成功后,不需要用户点击完成按钮)。
也就是说我们在实际开发的时候 wx.requestPayment 的成功回调函数,我们基本不需要做任何和服务器有关的操作,微信服务器会监听到支付的结果给我们的回调云函数。所以特别注意 我们需要在支付前将订单信息提交给后台,进行存储到数据库,由微信回调地址到云函数,云函数再将数据交给后台。
所以在云函数 pay 中有一个参数是回调函数,
我们可以在云函数中等待微信给我们的回调数据,数据中有包含支付的结果信息。在下图代码11行中
此时我们要将响应的数据,获取订单号给后台,让后台更改数据库订单的状态为已支付状态即可。
但是此处需要安装node环境本机安装,需要使用nodejs发送get请求或者post请求 将订单号提交给后台,所以需要安装npm,上图的pay_modules文件夹,大家可以无视。
上图的16行即描述将订单号发送给服务器的地址
上述pay_cb云函数代码如下:
// 云函数入口文件
const rp = require('request-promise');
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
})
// 云函数入口函数
exports.main = async (event, context) => {
console.log('payment callback!', event)
if(event.resultCode == 'SUCCESS'){ //根据result_code查看业务结果成功进行提交数据告诉服务器
// const urlTmp = getApp().data.baseUrl ;
const urlTmp = "http://yczb.canurcster.xyz"
rp(urlTmp + '/home/supplier/notify?outTradeNo='+event.outTradeNo).then(function (e) {
console.log("响应数据:" + e)
})
}
}
基本上已经完成了,但是记住回调函数里面 需要加上return返回值(就是告诉微信后台,再回调函数中已经确认了收到了);如果不返回会造成DDS攻击。
支付结果回调的云函数必须返回如下一个对象,否则会视为回调不成功,云函数会收到重复的支付回调:
//更新云数据库数据
const res = {errcode:0,errmsg:''}//需要返回的字段,不返回该字段则一直回调
return res
上述操作基本上就搞定的差不多了,可以根据自己的业务需求进行响应的操作,凡事都有第一次,只要肯磨基本上花点事件都可以搞出来,重点是下面这个图很重要 一定要看懂
微信官网支付API手册:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_4&index=3
微信官方文档手册(可以进入上面的连接):https://developers.weixin.qq.com/miniprogram/dev/api/open-api/payment/wx.requestPayment.html