一、uni.app支付

uni.requestPayment是一个统一各平台的客户端支付API,不管是在某家小程序还是在App中,客户端均使用本API调用支付。
uni.requestPayment运行在各端时,会自动转换为各端的原生支付调用API。

  1. 注意支付不仅仅需要客户端的开发,还需要服务端开发。虽然客户端API统一了,但各平台的支付申请开通、配置回填仍然需要看各个平台本身的支付文档。
  2. 比如微信有App支付、小程序支付、H5支付等不同的申请入口和使用流程,对应到uni-app,在App端要申请微信的App支付,而小程序端则申请微信的小程序支付。

1.uni.requestPayment参数说明

参数名 类型 必填 说明 平台差异说明
provider String 服务提供商,通过 uni.getProvider 获取。
orderInfo String/Object 订单数据, App、支付宝小程序、百度小程序、抖音小程序
timeStamp String 微信小程序必填 时间戳从1970年1月1日至今的秒数,即当前的时间。 微信小程序
nonceStr String 微信小程序必填 随机字符串,长度为32个字符以下。 微信小程序
package String 微信小程序必填 统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=xx。 微信小程序
signType String 微信小程序必填 签名算法,应与后台下单时的值一致 微信小程序
paySign String 微信小程序必填 签名 具体签名方案参见 微信小程序支付文档 微信小程序
bannedChannels Array<String> 需要隐藏的支付方式 百度小程序
service Number 抖音小程序必填 固定值:5(拉起小程序收银台)开发者如果不希望使用抖音小程序收银台,service设置为3/4时,可以直接拉起微信/支付宝进行支付:service=3: 微信API支付,不拉起小程序收银台;service=4: 支付宝API支付,不拉起小程序收银台。其中service=3、4,仅在1.35.0.1+基础库(头条743+)支持 抖音小程序
_debug Number 仅限调试用,上线前去掉该参数。_debug=1时,微信支付期间可以看到中间报错信息,方便调试 抖音小程序
getOrderStatus Function 抖音小程序必填 商户前端实现的查询支付订单状态方法(该方法需要返回个Promise对象)。 service=3、4时不需要传。 抖音小程序
success Function 接口调用成功的回调
fail Function 接口调用失败的回调函数
complete Function 接口调用结束的回调函数(调用成功、失败都会执行)
  1. signType 说明
    合法值 说明
    MD5 仅在 v2 版本接口适用
    HMAC-SHA256 仅在 v2 版本接口适用
    RSA 仅在 v3 版本接口适用
  2. signType 注意事项
    • APP端,如果你的应用在用户完成支付后;立即给支付的用户push消息通知。会与前端支付回调相互冲突,请延迟执行推送。
    • 抖音小程序支付接口调整使用时请注意 头条支付
  3. orderInfo 注意事项
    • 百度小程序的 orderInfo 为 Object 类型,详细的数据结构,参考:百度收银台支付
    • 支付宝小程序的 orderInfo(支付宝的规范为 tradeNO) 为 String 类型,表示支付宝交易号。
    • 抖音小程序的 orderInfo 为 Object 类型,详见:头条支付
    • App端,支付宝支付 orderInfo 为 String 类型。
    • App端,微信支付 orderInfo 为 Object 类型。
    • App端,苹果应用内支付 orderInfo 为Object 类型,{productid: ‘productid’}。

二、微信小程序支付

1.微信小程序支付时序图

在这里插入图片描述
商户系统和微信支付系统主要交互:
1. 小程序内调用登录接口,获取到用户的openid
2. 商户server调用支付统一下单,
3. 商户server调用再次签名,
4. 商户server接收支付通知,
5. 商户server查询支付结果,如未收到支付通知的情况,商户后台系统可调用 查询订单API
6. 商户小程序内使用小程序调起支付API(uni.requestPayment)发起微信支付,

2.示例

// 仅作为示例,非真实参数信息。
uni.requestPayment({
    provider: 'wxpay',
	timeStamp: String(Date.now()),
	nonceStr: 'A1B2C3D4E5',
	package: 'prepay_id=wx20180101abcdefg',
	signType: 'MD5',
	paySign: '',
	success: function (res) {
		console.log('success:' + JSON.stringify(res));
	},
	fail: function (err) {
		console.log('fail:' + JSON.stringify(err));
	}
});

3.案例

  1. 前端项目代码

    // 获取openid
    async getOpenidHandler() {
    	let { code } = await uni.login(); // 这个 api 支持 Promise 方式调用
    	console.log("code: ", code);
    	// 请求后端的接口,获取 openid
    	let url = `https://baidu.com/xcx/openid?code=${code}`;
    	uni.request({
    		url,
    		success: (response) => {
    			console.log("response: ", response);
    			/* 
    			{
    				"code": 0,
    				"msg": "success",
    				"data": {
    					"session_key": "xxxxxx====",
    					"openid": "oZpya5S6Mk6cccccccccccccccccccc"
    				}
    			} 
    			 */
    		}
    	})
    }
    
    payHandler() {
    	// 获取支付信息
    	let url = `https://baidu.com/xcx/buy`;
    	uni.request({
    		url,
    		success: (response) => {
    			console.log("response: ",response);
    			/* 
    			 appId: "wx1cxxxxxxxx"
    			 nonceStr: "xxxxxxxxxxxx"
    			 package: "prepay_id=wx182045498482360e7cccccccccccccc"
    			 paySign: "9A8226D2424cccccccccccccccccccc"
    			 signType: "MD5"
    			 timeStamp: "1681821949"
    			 */
    			
    			// package 是 js 里面的保留字
    			let {timeStamp, nonceStr, package: packageParam, signType, paySign } = response.data.data;
    			
    			wx.requestPayment({
    				timeStamp,
    				nonceStr,
    				package: packageParam,
    				signType,
    				paySign,
    				success(res) {
    					console.log("res: ", res);
    			 },
    				fail(res) {
    					console.log('error', res);
    				}
    			})
    			
    			
    		}
    	})
    	
    
    	// 调用微信支付的 api
    	/*  */
    }
    
  2. node.js Sever项目代码

const express = require('express')
const tenpay = require('tenpay');
const siteConfig = require('./payConfig.js');
const path = require('path');
const md5 = require('md5');
const axios = require('axios')
const app = express()
const port = 8001

app.use(express.static('public'))

app.engine('html', require('express-art-template'));
app.set('view options', {
    debug: process.env.NODE_ENV !== 'production'
});
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');

const config = {
    // appid: siteConfig.appid,
    appid: siteConfig.xcxid,

    mchid: siteConfig.mchid,
    partnerKey: siteConfig.partnerKey,
    notify_url: 'https://api.52kfw.cn/notify', // 买家成功支付后,微信系统通知商户后台系统的url地址 一般在这个里面去更改用户的订单的状态为 已支付
    spbill_create_ip: '106.52.75.114'
};

// 调试模式(传入第二个参数为true, 可在控制台输出数据)
const api = new tenpay(config, true);
/**
 * 根据小程序的 code 换取用户的 openid
 *
 */
app.get('/xcx/openid', async (req, res) => {
    // 客户端要传递一个 code
    let code = req.query.code;
    if (!code) {
        res.json({
            code: -1,
            msg: 'code必传'
        });
        return;
    }
    let appid = siteConfig.xcxid;
    let secret = siteConfig.xcxsecret;
    // 使用code 换取openid
    let codeToOpenidUrl = `https://api.weixin.qq.com/sns/jscode2session?appid=${appid}&secret=${secret}&js_code=${code}&grant_type=authorization_code `;

    try {
        const response = await axios.get(codeToOpenidUrl);

        res.json({
            code: 0,
            msg: 'success',
            data: response.data
        })
    } catch (e) {
        res.json({
            code: -1,
            msg: 'failure',
            data: null
        })
    }


})
app.get('/xcx/buy', async (req, res) => {
    let goodsId = Date.now().toString();
    let trade_no = md5(Math.random() + goodsId);
    let openid = 'oZpya5S6Mk6ufOWW84eIYksSsJUc';
    // appid和openid不匹配 tenpay 其他的 支付方式(pc h5 公众号 使用的服务号的 appid ,但是如果要做小程序支付,则要使用小程序的 appid)
    let result = await api.getPayParams({
        out_trade_no: trade_no,
        body: '微信小程序支付测试',
        total_fee: '1',
        openid: openid, // 微信小程序支付则和微信公众号里面网页支付一样,需要一个openid
        // openid 是什么? 当前微信小程序使用者的唯一身份标识符,在做支付的时候需要这个 openid
        // 知道这个 openid 就知道是哪个微信用户在付钱?

        // 如何获取到 openid
        // wx.login api 是小程序提供的一个登录 api 返回一个 code, 然后我们可以通过这个code换取到用户的openid
        // 如何换?
    });
    console.log(result);

    res.json({
        code: 0,
        msg: 'success',
        data: result
    })

})
app.listen(port, () => {
    console.log(`pay app listening on port ${port}`)
})

三、总结

  1. 小程序不能通过拉起H5页面做jsapi支付,小程序内只能使用小程序支付
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐