Appearance
所有支付相关内容
- 游泳馆 办卡 微信支付
- 游泳馆 单次票 微信支付
- 羽毛球 办卡 微信支付
- 羽毛球 订场 一卡通支付
- 羽毛球 订场 会员卡支付
- 羽毛球 订场 微信支付
- 足球馆 办卡 微信支付
- 足球馆 订场 会员卡支付
- 足球馆 订场 微信支付
- 充值 一卡通 微信支付
- 充值 游泳卡 微信支付
- 充值 羽毛球卡 微信支付
- 充值 足球卡 微信支付
- 体测机 获取报告 微信支付
- 赛事活动 报名费 微信支付
关于微信支付
后端返回的 微信支付格式一致,皆为
ts
export interface IResPay {
appId: string //'wxa9462c49dd468b45'
nonceStr: string //'gYAObidSwEi7DYsx'
packageValue: string //'prepay_id=wx0410242604233355fef688a2db13730001'
paySign: string //'DCCCF08E293FCEF18D980F2C6B885612'
signType: string //'MD5'
timeStamp: string //'1730687066'
}在此基础上,经过多次思考,最终是把微信支付进行统一封装
微信支付的唤起方式
ts
interface IMpWxPay {
/**
* 公众号ID,由商户传入
*/
appId: string
/**
* 时间戳
*/
timeStamp: string
/**
* 随机串
*/
nonceStr: string
/**
* prepay_id
*/
package: string
/**
* 微信签名方式,如 RSA
*/
signType: string
/**
* 微信签名
*/
paySign: string
}
export const wxMpPay = (wxPay: IMpWxPay) => {
// package 为 js 关键字,不能为变量名
const { appId, timeStamp, nonceStr, package: pg, signType, paySign } = wxPay
if (!appId) return Promise.reject('缺少appId')
if (!timeStamp) return Promise.reject('缺少timeStamp')
if (!nonceStr) return Promise.reject('缺少nonceStr')
if (!pg) return Promise.reject('缺少package')
if (!signType) return Promise.reject('缺少signType')
if (!paySign) return Promise.reject('缺少paySign')
const param = {
appId, //公众号ID,由商户传入
timeStamp, //时间戳,自1970年以来的秒数
nonceStr, //随机串
package: pg,
signType, //微信签名方式:
paySign //微信签名
}
// console.log('微信支付 WeixinJSBridge.invoke 参数 > ', param)
return new Promise((resolve, reject) => {
if (!WeixinJSBridge) return reject('WeixinJSBridge 不存在')
// @ts-ignore
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
param,
// @ts-ignore
function (res) {
const isPaySuccess = res.err_msg === 'get_brand_wcpay_request:ok'
// console.log('微信支付结果', isPaySuccess, res)
if (isPaySuccess) {
resolve(res)
} else {
reject(res)
}
}
)
})
}针对微航后端进一步的封装
ts
import type { IResPay } from '@/api/type'
import { wxMpPay } from '@/util/weixin'
import { ref } from 'vue'
// ----------------------------------------------------------------
// 微信支付 Hooks
// ----------------------------------------------------------------
// 这个type的意义是:支付结果为多状态设计
// 1. 是否 可以支付
// 2. 是否 支付成功
// 3. 如果有需求变动,可以增加其他
export interface IWxPayResult {
message: string
/**
* 是否 可以支付
*
* 因为 server 提供给的支付参数并不一定有
*/
isCanPaid: boolean
/**
* 是否 支付成功
*/
isPaySuccess: boolean
}
export const useWxPay = () => {
const payDate = ref<IPayDataV2>(createWxPayV2Data())
/**
* 是否有支付缓存
*
* 微信支付 参数可以 多次使用,如果存在缓存可以直接支付
*/
const hasPayCache = () => payDataCheck(payDate.value)
const invokePay = async (data?: IResPay): Promise<IWxPayResult> => {
let myData: IPayDataV2 | undefined = undefined
// 如果 传入 data,将 支付数据记录下来
if (data) {
const { packageValue, ...other } = data
myData = {
...other,
package: packageValue
}
if (payDataCheck(myData)) {
payDate.value = myData
}
}
const payConf: IPayDataV2 = myData || payDate.value
const result: IWxPayResult = {
message: 'default value',
isCanPaid: false,
isPaySuccess: false
}
if (!payDataCheck(payConf)) {
result.message = 'API返回支付参数异常'
return result
}
try {
result.isCanPaid = true
// const res =
await wxMpPay(payConf)
result.isPaySuccess = true
result.message = '支付成功'
return result
} catch (error: any) {
// get_brand_wcpay_request:cancel
if (error.err_msg === 'get_brand_wcpay_request:cancel') {
result.message = '取消支付'
} else {
result.message = '支付失败:' + error?.message || error.err_msg
}
return result
}
}
return {
payDate,
hasPayCache,
invokePay
}
}
/**
* 微信支付 v2 数据
*
*/
export interface IPayDataV2 {
appId: string
timeStamp: string
nonceStr: string
package: string
signType: string
paySign: string
}
/**
* 创建一个value为空的 微信支付 数据
*/
export function createWxPayV2Data(): IPayDataV2 {
return {
appId: '', //公众号ID,由商户传入
timeStamp: '', //时间戳,自1970年以来的秒数
nonceStr: '', //随机串
package: '',
signType: '', //微信签名方式:
paySign: ''
}
}
/**
* 检查 支付信息 是否有效
*/
function payDataCheck(data: IPayDataV2) {
if (!data || typeof data !== 'object') return false
const { appId, timeStamp, nonceStr, package: pack, signType, paySign } = data
return appId && timeStamp && nonceStr && pack && signType && paySign
}最终效果:
ts
import { useWxPay } from '@/hook/useWxPay'
const { hasPayCache, invokePay } = useWxPay()
// 现目前没有使用
// 重复支付在用户修改了订单信息有问题,所以设计了,但是没有使用
if (hasPayCache()) {
return invokePay()
}
reqPlayTicket({
couponId: selectCoupon.value?.id,
couponMoney: selectCoupon.value?.amount,
originalPrice: amount.value,
priceTotal: total.value,
num: order.singleUserInputInfo.count,
ticketId,
venueId
})
.then((res) => invokePay(res.data))
.then(({ message, isCanPaid, isPaySuccess }) => {
if (!isCanPaid || !isPaySuccess) return showError(message)
toResultPage()
})
.catch((e) => {
console.error(e)
showError(e.message || '获取支付信息失败')
})关于 重新支付/微信支付
ts
/**
* 重新支付
*/
export const useRePay = () => {
const { invokePay } = useWxPay()
const rePay = async (order: IOrder): Promise<IWxPayResult> => {
if (!order.raw) throw new Error('订单数据异常')
const { tradeType, orderType, orderStatus } = order.raw
console.log('重新支付')
console.log('tradeType 交易类型 1体测机 2赛事活动 3一卡通 4羽毛球 5足球馆 6游泳馆')
console.log({ tradeType, orderType })
const payFunc = (res: IResPayOrder) => {
if (res.code !== 200) throw new Error(res.msg)
return invokePay(res.data)
}
// 体测机
if (tradeType === 1) {
return rePayCheckup(order.raw).then(payFunc)
}
// 赛事活动报名
if (tradeType === 2) {
return rePayActivity(order.raw).then(payFunc)
}
// 一卡通
if (tradeType === 3) {
return rePayOneCard(order.raw).then(payFunc)
}
// 羽毛球
if (tradeType === 4) {
console.log('羽毛球 orderType 1=线下订场,2=办卡,3=充值,4=延期,5=锁场,6=微信订场')
// 办卡
if (orderType === 2) {
return rePayBadmintonApplyCard(order.raw).then(payFunc)
}
// 充值
if (orderType === 3) {
return rePayRechargeBadminton(order.raw).then(payFunc)
}
// 微信订场
if (orderType === 6) {
return rePayBadminton(order.raw).then(payFunc)
}
}
// 游泳馆
if (tradeType === 6) {
console.log('游泳馆 orderType 订单类型(1售票,2办卡,3续卡,4退卡,5转卡,6冻卡,7解冻,8延期)')
// 1 售票
if (orderType === 1) {
return rePaySwimBuyTicket(order.raw).then(payFunc)
}
// 2 办卡
if (orderType === 2) {
return rePaySwimCard(order.raw).then(payFunc)
}
// 3 续卡
if (orderType === 3) {
return rePayRenewSwimCard(order.raw).then(payFunc)
}
}
// 足球馆
if (tradeType === 5) {
console.log('足球馆 orderType 订单类型(1售票,2办卡,3充值)')
// 定场
if (orderType === 1) {
return rePayFootball(order.raw)
.then((res) => {
return { ...res, data: res.data.data }
})
.then(payFunc)
}
// 办卡
if (orderType === 2) {
return rePayFootballCard(order.raw)
.then((res) => {
return { ...res, data: res.data.data }
})
.then(payFunc)
}
// 充值
if (orderType === 3) {
return rePayRechargeFootballCard(order.raw).then(payFunc)
}
}
throw new Error('未知类型:' + tradeType + ',orderType:' + orderType)
}
return { rePay }
}具体 看 代码,这里提供一下具体的请求参数
ts
// 活动报名
function rePayActivity(order: IResOrderListRows) {
const { orderNo } = order
const wxStore = useWeixinStore()
return reqActivityRePay({
orderNo,
openId: wxStore.openId
})
}
// 一卡通 重新支付
function rePayOneCard(order: IResOrderListRows) {
const { orderNo } = order
const wxStore = useWeixinStore()
return reqRePayOneCard({
orderNo,
openId: wxStore.openId,
amount: order.payAmount
})
}
function rePayCheckup(order: IResOrderListRows) {
const { orderNo, payAmount } = order
const wxStore = useWeixinStore()
return reqRePayCheckup({
orderNo,
openId: wxStore.openId,
amount: payAmount
})
}
// 羽毛球 定场 重新支付
function rePayBadminton(order: IResOrderListRows) {
const { orderNo, payAmount } = order
const wxStore = useWeixinStore()
const param = {
orderNo,
realityMoney: payAmount,
payType: 3 as 3,
openId: wxStore.openId
}
return reqBadmintonPayOrder(param)
}
// 羽毛球 办卡 重新支付
function rePayBadmintonApplyCard(order: IResOrderListRows) {
const { orderNo, payAmount } = order
const wxStore = useWeixinStore()
return reqRePayBadmintonApplyCard({
orderNo,
openId: wxStore.openId,
realityMoney: payAmount
})
}
// 羽毛球 会员卡充值 重新支付
function rePayRechargeBadminton(order: IResOrderListRows) {
const { orderNo, payAmount } = order
const wxStore = useWeixinStore()
return reqRePayRechargeBadminton({
orderNo,
openId: wxStore.openId,
amount: payAmount
})
}
function rePaySwimBuyTicket(order: IResOrderListRows) {
const { orderNo, payAmount } = order
const wxStore = useWeixinStore()
return reqRePaySwimBuyTicket({
orderNo,
openId: wxStore.openId,
priceTotal: payAmount
})
}
function rePaySwimCard(order: IResOrderListRows) {
const { orderNo, payAmount } = order
const wxStore = useWeixinStore()
return reqRePaySwimBuyCard({
orderNo,
openId: wxStore.openId,
payAmount
})
}
// 游泳卡 充值
function rePayRenewSwimCard(order: IResOrderListRows) {
const { orderNo, payAmount } = order
const wxStore = useWeixinStore()
return reqRePayRechargeSwim({
orderNo,
openId: wxStore.openId,
amount: payAmount
})
}
// 足球馆 定场 重新支付
function rePayFootball(order: IResOrderListRows) {
const { orderNo, payAmount } = order
const wxStore = useWeixinStore()
return reqRePayFootball({
orderNo,
openId: wxStore.openId,
price: payAmount
})
}
function rePayFootballCard(order: IResOrderListRows) {
const { orderNo, payAmount } = order
const wxStore = useWeixinStore()
return reqRePayFootballCard({
orderNo,
openId: wxStore.openId,
payAmount
})
}
function rePayRechargeFootballCard(order: IResOrderListRows) {
const { orderNo, payAmount } = order
const wxStore = useWeixinStore()
return reqRePayRechargeFootball({
orderNo,
openId: wxStore.openId,
amount: payAmount
})
}