云开发支付流程闭环

extends

微信小程序--使用云开发完成支付闭环

在上述文章中,我们对支付结果的处理更多依赖于小程序端的操作

  1. 订单号存储在小程序端
  2. 支付结果采用小程序端定时触发器轮询

现在我对该流程进行了优化处理

1.流程介绍

2.小程序端

  1. 请求统一下单云函数
  2. 调用支付接口
  3. 侦听器获取支付结果
// pages/index/details.js
const app = getApp();
const db = wx.cloud.database();
var watcher = null
Page({ /**
* 页面的初始数据
*/
data: { },
//付费解锁
payUnlock() {
var that = this; this.setData({
vis: true
})
//用户ID 即为OPENID
let userid = this.data.selfcard._id;
wx.cloud.callFunction({
name: 'userpay',
data: {
fee: 1,
paydata: {
userid
}
},
success: res => {
console.log(res)
//统一下单云函数中需要返回侦听器 需要的记录id
that.payWatcher(res.result.docid);
that.setData({
vis: false
})
//根据统一下单参数 请求支付接口
const payment = res.result.payment
wx.requestPayment({
...payment,
success(ans) {
console.log(ans)
},
fail(ans) {
that.setData({
errMsg: '调用支付失败'
})
}
})
}
})
},
payWatcher(docid){
var that = this;
//为用户支付记录表设置侦听器,侦听docid信息的变动
this.watcher = db.collection('USERPAYLOG').doc(docid).watch({
onChange: async function (snapshot) {
//只打印变动的信息
// console.log(snapshot)
if (snapshot.docChanges.length != 0) {
console.log(snapshot.docChanges)
let paydoc = snapshot.docChanges[0].doc;
//侦听到支付成功
if(paydoc.paystatus == 1){
that.setData({
succMsg:'支付成功',
locked:false,
bottom:0
})
}
// await that.watcher.close();
}
},
onError: function (err) {
console.error('the watch closed because of error', err)
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) { },
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
try {
this.watcher.close();
} catch (error) {
console.log('暂未启动支付侦听器')
}
}
})

3.云函数端

userpay

  1. 云调用统一下单【CloudPay.unifiedOrder】
  2. 数据库中存入订单记录并设置为未支付状态

需要配置商户(云开发控制台)

const cloud = require('wx-server-sdk')
//需要在此处修改你的云环境ID
cloud.init({
env: ''
})
const db = cloud.database();
const _ = db.command;
// 云函数入口函数
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
var openid = event.openid || wxContext.OPENID
//获取统一下单金额
var fee = parseInt(event.fee);
let paydata = event.paydata;
//生成订单号
let tradeno = GetTradeNo();
//调用统一下单接口
const res = await cloud.cloudPay.unifiedOrder({
//填写你的商户主体信息 例如 xx商贸
"body": "",
"outTradeNo": tradeno,
"spbillCreateIp": "127.0.0.1",
//填写你的商户ID -- 可在云开发控制台中绑定获得(上图所示)
"subMchId": "",
"totalFee": fee,
//填写你的云环境ID
"envId": "",
//填写你的回调函数名称
"functionName": "userpaynotify"
})
console.log(res)
res.outTradeNo = tradeno
res.totalFee = fee
//支付状态 0 为未支付
paydata.tradeno = tradeno
paydata.paystatus = 0
paydata.totalfee = fee
paydata.openid = openid
paydata.paytime = TimeCode()
//统一下单shuju
paydata.uniOrder = res
//拦截处理 为保持数据库字段一致性
if (res.returnCode == 'SUCCESS' && res.resultCode == 'SUCCESS') {
//在云数据库中写入未支付的订单信息
let tdata = await db.collection('USERPAYLOG').add({
data: paydata
})
console.log(tdata)
//将该记录ID携带返回给小程序端
res.docid = tdata._id;
return res;
}else{
return res;
}
} function GetTradeNo() {
var outTradeNo = ""; //订单号
for (var i = 0; i < 6; i++) //6位随机数,用以加在时间戳后面。
{
outTradeNo += Math.floor(Math.random() * 10);
}
outTradeNo = "COP" + new Date().getTime() + outTradeNo; //时间戳,用来生成订单号。
return outTradeNo;
} function TimeCode() {
var date = new Date();
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate() var hour = date.getHours()
var minute = date.getMinutes()
var second = date.getSeconds() return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':')
} function formatNumber(n) {
n = n.toString()
return n[1] ? n : '0' + n
}

支付成功后触发云环境中该回调函数

回调函数携带的请求信息请在参考文档中查看

userpaynotify

  1. 修改数据库中订单状态

  2. 返回给回调请求SUCCESS数据【Cloud.paymentCallback】

    订单在支付成功时会触发该回调函数

    该回调函数必须有返回值,且必须是固定格式

    根据回调函数携带的订单号,修改对应订单号的订单状态,并且返回对应格式的返回信息

    字段名 变量名 必填 类型 描述
    错误码 errcode Number 0
    错误信息 errmsg String
const cloud = require('wx-server-sdk')
//填写你的云环境ID
cloud.init({
env: ''
})
const db = cloud.database();
const _ = db.command;
// 云函数入口函数
exports.main = async (event, context) => { console.log('支付成功回调函数触发')
console.log(event)
let tradeno = event.outTradeNo;
try {
//修改数据库中订单状态 为已支付
db.collection('USERPAYLOG').where({
tradeno:tradeno
}).update({
data:{
paystatus:1
}
})
} catch (error) {
return {
errmsg: 'SERVER_ERROR',
errcode: -1
}
}
return {
errmsg: 'SUCCESS',
errcode: 0
}
}

参考文档

  1. 云开发文档 Cloud.CloudPay | 微信开放文档 (qq.com)

  2. 回调函数请求携带参数

{
appid: '', bankType: 'OTHERS', cashFee: 1, feeType: 'CNY', isSubscribe: 'N', mchId: '', nonceStr: '', openid: '', outTradeNo: '', resultCode: 'SUCCESS', returnCode: 'SUCCESS', subAppid: '', subIsSubscribe: 'N', subMchId: '', subOpenid: '', timeEnd: '', totalFee: 1, tradeType: 'JSAPI', transactionId: '', userInfo: {
appId: '', openId: ''
}
}

微信小程序--云开发支付闭环的更多相关文章

  1. 技本功丨收藏!斜杠青年与你共探微信小程序云开发(下篇)

    2019年2月26日,人们为了一个杯子疯了一天. 星巴克猫爪杯,一场已经与猫无关了的“圣杯战争“.网上的倒卖价格,已炒至近千元! 求而不得,舍而不能,得而不惜.这是人最大的悲哀... 所以,请珍惜以下 ...

  2. 微信小程序-云开发(手记)

    微信小程序-云开发(手记) 1.创建data.json文件 注意以下几点要求: 入门示例: init方法的env:默认环境配置,传入字符串形式的环境 ID(理解为数据库)可以指定所有服务的默认环境(意 ...

  3. 第六章 “我要点爆”微信小程序云开发实例之爆文详情页制作

    爆文详情页制作 从首页中数据列表打开相应详情页面的方法: 给数据列表中每个数据项加一个点击事件,同时将当前数据项的id暂时记录在本地,然后跳转到详情页面detail goopen: function ...

  4. 第一章 “我要点爆”微信小程序云开发之项目建立与我的页面功能实现

    第一章 “我要点爆”微信小程序云开发之项目建立与我的页面功能实现 开发环境搭建 使用自己的AppID新建小程序项目,后端服务选择小程序·云开发,点击新建,完成项目新建. 新建成功后跳转到开发者工具界面 ...

  5. “我要点爆”微信小程序云开发实例

    使用云开发进行微信小程序“我要点爆”的制作 下一章:“我要点爆”微信小程序云开发之项目建立与我的页面功能实现 接下来我将对“我要点爆”微信小程序进行完整的开源介绍 小程序名称: 我要点爆 查看方式:从 ...

  6. 微信小程序云开发-从0打造云音乐全栈小程序

    第1章 首门小程序“云开发”课程,你值得学习本章主要介绍什么是小程序云开发以及学习云开发的重要性,并介绍项目的整体架构,真机演示项目功能,详细介绍整体课程安排.课程适用人群以及需要掌握的前置知识.通过 ...

  7. 微信小程序云开发不完全指北

    微信小程序云开发不完全指北 首先必须说明云开发的"云"并不是类似云玩家里的云的意思,而是微信小程序真的提供了云开发的接口以及一个简单的提供存储.数据库服务的虚拟后台(对于一些轻量小 ...

  8. 微信小程序云开发如何上手

    简要介绍 微信小程序云开发,是基于 Serverless 的一站式后端云服务,涵盖函数.数据库.存储.CDN等服务,免后端运维.基于云开发可以免鉴权调用微信所有开放能力. 前提准备 微信开发者工具 创 ...

  9. 微信小程序-云开发实战教程

    微信小程序-云开发实战教程 云函数,云存储,云数据库,云调用 https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/gettin ...

  10. 微信小程序-云开发-实战项目

    微信小程序-云开发-实战项目 微信小程序 微信小程序平台服务条款 https://developers.weixin.qq.com/miniprogram/product/service.html h ...

随机推荐

  1. SpringBoot 整合模板引擎 jetbrick-template

    添加依赖 <dependency> <groupId>com.github.subchen</groupId> <artifactId>jetbrick ...

  2. KubeCube 用户管理与身份认证

    前言 KubeCube (https://kubecube.io) 是由网易数帆近期开源的一个轻量化的企业级容器平台,为企业提供 kubernetes 资源可视化管理以及统一的多集群多租户管理功能.K ...

  3. [oeasy]python0021_宝剑镶宝石_爱之石中剑_批量替换_特殊字符_特殊颜色

    继续运行 回忆上次内容 上次 运行了 game.py 分析了 game.py 也大致读懂了 game.py       添加图片注释,不超过 140 字(可选)   这个 程序 可以进一步 进行修改吗 ...

  4. [oeasy]python0127_中文系统_gbk_BIG5_南极星_内码转化

    中文系统bgk 回忆上次内容 汉字字形通过 点阵式打字机 像素级寻址的屏幕 进入了计算机的世界   ​   添加图片注释,不超过 140 字(可选)   在海峡对岸的台湾同胞 也进入了汉字时代   他 ...

  5. oeasy 教您玩转linux 之 010209 装酷利器 hollywood

    我们来回顾一下 上一部分我们都讲了什么? 屏幕故障风格的软件包bb 可以设置音频 这次装一个酷 下个hollywood软件包 apt show hollywood apt search hollywo ...

  6. CF1929B Sasha and the Drawing 题解

    CF1929B 题意 给定一个 \(n\times n\) 的正方形,已知正方形最多有 \(4\times n-2\) 条对角线,要求要有至少 \(k\) 条对角线经过至少一块黑色方格,求至少要将几条 ...

  7. OI-Wiki 学习笔记

    算法基础 \(\text{Update: 2024 - 07 - 22}\) 复杂度 定义 衡量一个算法的快慢,一定要考虑数据规模的大小. 一般来说,数据规模越大,算法的用时就越长. 而在算法竞赛中, ...

  8. centos7更换aliyun软件源一键脚本

    centos7更换aliyun软件源 centos7更换aliyun软件源一键脚本 curl -O https://raw.githubusercontent.com/Yogoshiteyo/aliy ...

  9. 【Hibernate】Re01.5 API

    1.Session单表的CRUD操作 1.增加或者修改,使用同一个方法,或者下面的两个也行: 感觉多此一举... 2.删除方法,硬删除: 3.获取方法提供了两种,Get & Load get方 ...

  10. 【Vue】06 Webpack Part2 打包命令配置

    Webpack 配置: 入口 & 出口: 就是我们使用的打包命令: 一个是对什么文件执行,这就是入口 一个是输出到什么文件,这就是出口 每一次打包使用这个命令都必须指定这两个必要的参数 所以将 ...