Files
yshop-pro-uniapp/utils/paymentUtils.js
2023-11-15 19:59:37 +08:00

286 lines
9.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @name: 支付工具方法
* @author: kahu4
* @date: 2023-11-07 11:42
* @description支付工具方法 请使用try catch抓取异常或者.catch抓取异常
* @update: 2023-11-07 11:42
* */
import { useInterface } from "@/hooks/useInterface";
import { createMessage, h5InWeChat } from "@/utils/index";
import { wechatPay } from "@/api/order";
import { CacheKey } from "@/utils/config";
const {loading, hideLoading} = useInterface()
// 微信支付的provider
export const WechatProvider = 'wxpay'
// 支付类型(后端用)
export const ServiceFrom = {
'h5': 'weixin_h5', // H5微信内h5、微信外H5
'weixin': 'weixin_applet', // 微信小程序
'app': 'weixin_app' // 微信APP
}
export const ServicePayType = {
'h5': 'weixin_h5', // H5微信内h5、微信外H5
'weixin': 'weixin_applet', // 微信小程序
'app': 'weixin_app' // 微信APP
}
// 支付类型(前端用)
export const PayType = {
0: 'wechat', // 微信支付
1: 'balance', // 余额支付
2: 'alipay', // 支付宝支付
}
// 微信支付环境类型(前端用)
export const WechatPayEnvType = {
0: 'app', // APP
1: 'miniProgram', // 小程序
2: 'h5InWechat', // 微信内H5
3: 'h5OutWechat' // 微信外H5
}
/**
* 获取当前环境
* @returns {*} WechatPayEnvType
*/
export function getEnvType() {
let envType; // 0.APP 1.微信小程序 2.微信内H5 3.微信外H5 WechatPayEnvType
// #ifdef APP-PLUS
envType = WechatPayEnvType["0"]
// #endif
// #ifdef MP-WEIXIN
envType = WechatPayEnvType["1"]
// #endif
// #ifdef H5
if (h5InWeChat()) {
envType = WechatPayEnvType["2"]
} else {
envType = WechatPayEnvType["3"]
}
// #endif
return envType
}
/**
* @name: 支付
* @param options {{ type:any, payInfo:any }}
* type PayType
* payInfo 结算信息
*/
export async function doPayment(options) {
loading({title: '支付中...'})
const res = await _chooseEnvToPayment(options)
hideLoading()
return res
}
/**
* 区别环境调用支付
* @param options
* @returns {Promise<{msg: *, data: *}>}
* @private
*/
async function _chooseEnvToPayment(options) {
const {type, payInfo} = options
let res;
if (type === PayType[0]) {
// 微信支付
switch (getEnvType()) {
case WechatPayEnvType["0"]:
res = await _appWechatPay(payInfo)
break;
case WechatPayEnvType["1"]:
res = await _miniProgramPay(payInfo)
break;
case WechatPayEnvType["2"]:
res = await _h5InWechatPay(payInfo)
break;
case WechatPayEnvType["3"]:
res = await _h5OutWechatPay(payInfo)
break;
}
}
if (type === PayType["1"]) {
// 余额支付
}
if (type === PayType["2"]) {
// 支付宝
res = await _aliPay(payInfo)
}
return res
}
/**
* APP微信支付
* @param payInfo
* @private
* @docs https://pay.weixin.qq.com/docs/merchant/apis/in-app-payment/app-transfer-payment.html
*/
function _appWechatPay(payInfo) {
return new Promise(async (resolve, reject) => {
const payData = {
from: ServiceFrom['app'],
paytype: ServicePayType['app'],
uni: payInfo.orderId
}
// 请求线上获取 res:{ appId,timeStamp,nonceStr,paySign,package,signType,mwebUrl,codeUrl,merchant_id,out_trade_no }
const res = await _doWechatPayRequest(payData)
// 兼容性写法:防止电脑端用户支付后马上关闭支付弹窗导致失败
uni.setStorageSync(CacheKey.PAY_INFO, JSON.stringify(payData))
const orderInfo = {
appid: res.appId, // 微信开放平台审核通过的移动应用AppID 。
prepayid: res.merchant_id, // 请填写商户号mchid对应的值。
timestamp: res.timeStamp, // 时间
sign: res.paySign, // 签名使用字段AppID、timeStamp、nonceStr、prepayid计算得出的签名值 注意取值RSA格式
partnerid: res.out_trade_no, // 微信返回的支付交易会话ID该值有效期为2小时。
noncestr: res.nonceStr, // 随机字符串不长于32位。推荐随机数生成算法。
package: 'Sign=WXPay', // 暂填写固定值Sign=WXPay
}
uni.requestPayment({
provider: WechatProvider,
orderInfo,
success: (res) => resolve(createMessage('用户支付成功', res)),
fail: (error) => reject(createMessage('用户支付失败', error))
})
})
}
/**
* 微信小程序支付
* @param payInfo
* @private
* @docs https://pay.weixin.qq.com/docs/merchant/apis/h5-payment/h5-transfer-payment.html
*/
function _miniProgramPay(payInfo) {
return new Promise(async (resolve, reject) => {
const payData = {
from: ServiceFrom['weixin'],
paytype: ServiceFrom['weixin'],
uni: payInfo.orderId
}
// 请求线上获取 res:{ appId,timeStamp,nonceStr,paySign,package,signType,mwebUrl,codeUrl,merchant_id,out_trade_no }
const res = await _doWechatPayRequest(payData)
// 兼容性写法:防止电脑端用户支付后马上关闭支付弹窗导致失败
uni.setStorageSync(CacheKey.PAY_INFO, JSON.stringify(payData))
uni.requestPayment({
timeStamp: res.timeStamp,
nonceStr: res.nonceStr,
signType: res.signType,
paySign: res.paySign,
package: res.package,
provider: WechatProvider,
success: (res) => resolve(createMessage('用户支付成功', res)),
fail: (error) => reject(createMessage('用户支付失败', error))
})
})
}
/**
* 微信内H5支付
* @param payInfo
* @private
* @docs https://pay.weixin.qq.com/docs/merchant/apis/h5-payment/h5-transfer-payment.html
*/
async function _h5InWechatPay(payInfo) {
return new Promise(async (resolve, reject) => {
const payData = {
from: ServiceFrom['h5'],
paytype: ServicePayType['h5'],
uni: payInfo.orderId
}
// 请求线上获取 res:{ appId,timeStamp,nonceStr,paySign,package,signType,mwebUrl,codeUrl,merchant_id,out_trade_no }
const res = await _doWechatPayRequest(payData)
/** 注册JS SDK */
jweixin.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来若要查看传入的参数可以在pc端打开参数信息会通过log打出仅在pc端时才会打印。
appId: res.appId, // 必填,公众号的唯一标识
timestamp: res.timeStamp, // 必填,生成签名的时间戳
nonceStr: res.nonceStr, // 必填,生成签名的随机串
signature: res.paySign, // 必填签名见附录1
jsApiList: ['chooseWXPay'] // 必填需要使用的JS接口列表所有JS接口列表见附录2
});
/** JS SDK 可使用状态 */
jweixin.ready(() => {
/** 检查JS SDK API是否可用 */
jweixin.checkJsApi({
jsApiList: ['chooseWXPay'], // 需要检测的JS接口列表所有JS接口列表见附录2,
success: () => {
},
fail: (error) => {
return reject(createMessage('微信版本过低,请升级微信版本', error))
}
});
uni.setStorageSync(CacheKey.PAY_INFO, JSON.stringify(payData))
/** 去拉起微信支付 */
jweixin.chooseWXPay({
timestamp: res.timeStamp, // 支付签名时间戳注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: res.nonceStr, // 支付签名随机串,不长于 32 位
package: res.package, // 统一支付接口返回的prepay_id参数值提交格式如prepay_id=***
signType: res.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: res.paySign, // 支付签名
success: (res) => {
// 支付成功后的回调函数
return resolve(createMessage('用户支付成功', res))
},
cancel: (r) => {
return reject(createMessage('用户取消支付', {}))
},
fail: (error) => {
return reject(createMessage('跳转微信支付失败', error))
}
});
});
/** JS SDK发生错误 */
jweixin.error((error) => {
return reject(createMessage('JS-SDK加载错误', error))
});
})
}
/**
* 微信外H5支付
* @param payInfo
* @private
*/
async function _h5OutWechatPay(payInfo) {
const payData = {
from: ServiceFrom['h5'],
paytype: ServicePayType['h5'],
uni: payInfo.orderId
}
const res = await _doWechatPayRequest(payData)
if (res && res.mwebUrl) {
// 缓存支付订单数据
uni.setStorageSync(CacheKey.PAY_INFO, JSON.stringify(payData))
location.replace(res.mwebUrl)
return Promise.resolve(createMessage('用户支付成功', {type: 'h5'}))
} else {
return Promise.reject(createMessage('服务端拉起支付失败', {type: 'h5', error: res}))
}
}
/**
* 支付宝支付
* @param payInfo
*/
function _aliPay(payInfo) {
return Promise.reject("暂不支持支付宝支付")
}
/**
* 请求服务端获取支付信息
* @param data {{from:string, paytype: string, uni: string }}
* @returns {Promise<*>}
* @private
*/
async function _doWechatPayRequest(data) {
return await wechatPay(data)
}