212 lines
4.9 KiB
JavaScript
212 lines
4.9 KiB
JavaScript
// miniprogram/utils/payment.js
|
||
// 微信支付工具类
|
||
|
||
const app = getApp()
|
||
|
||
/**
|
||
* 发起微信支付
|
||
* @param {Object} options - 支付选项
|
||
* @param {String} options.orderId - 订单ID
|
||
* @param {Number} options.amount - 支付金额(元)
|
||
* @param {String} options.description - 商品描述
|
||
* @param {Function} options.success - 成功回调
|
||
* @param {Function} options.fail - 失败回调
|
||
*/
|
||
function wxPay(options) {
|
||
const { orderId, amount, description, success, fail } = options
|
||
|
||
wx.showLoading({
|
||
title: '正在支付...',
|
||
mask: true
|
||
})
|
||
|
||
// 1. 调用后端创建支付订单
|
||
wx.request({
|
||
url: `${app.globalData.apiBase}/payment/create`,
|
||
method: 'POST',
|
||
header: {
|
||
'Authorization': `Bearer ${wx.getStorageSync('token')}`
|
||
},
|
||
data: {
|
||
orderId,
|
||
amount,
|
||
description,
|
||
paymentMethod: 'wechat'
|
||
},
|
||
success: (res) => {
|
||
wx.hideLoading()
|
||
|
||
if (res.statusCode === 200) {
|
||
const paymentData = res.data
|
||
|
||
// 2. 调起微信支付
|
||
wx.requestPayment({
|
||
timeStamp: paymentData.timeStamp,
|
||
nonceStr: paymentData.nonceStr,
|
||
package: paymentData.package,
|
||
signType: paymentData.signType || 'RSA',
|
||
paySign: paymentData.paySign,
|
||
success: (payRes) => {
|
||
console.log('支付成功', payRes)
|
||
|
||
// 3. 通知后端支付成功
|
||
notifyPaymentSuccess(orderId, paymentData.prepayId)
|
||
|
||
wx.showToast({
|
||
title: '支付成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
})
|
||
|
||
success && success(payRes)
|
||
},
|
||
fail: (payErr) => {
|
||
console.error('支付失败', payErr)
|
||
|
||
if (payErr.errMsg.indexOf('cancel') !== -1) {
|
||
wx.showToast({
|
||
title: '支付已取消',
|
||
icon: 'none'
|
||
})
|
||
} else {
|
||
wx.showToast({
|
||
title: '支付失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
|
||
fail && fail(payErr)
|
||
}
|
||
})
|
||
} else {
|
||
wx.showToast({
|
||
title: res.data.message || '创建订单失败',
|
||
icon: 'none'
|
||
})
|
||
fail && fail(res)
|
||
}
|
||
},
|
||
fail: (err) => {
|
||
wx.hideLoading()
|
||
console.error('请求失败', err)
|
||
|
||
wx.showToast({
|
||
title: '网络请求失败',
|
||
icon: 'none'
|
||
})
|
||
|
||
fail && fail(err)
|
||
}
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 通知后端支付成功
|
||
* @param {String} orderId
|
||
* @param {String} prepayId
|
||
*/
|
||
function notifyPaymentSuccess(orderId, prepayId) {
|
||
wx.request({
|
||
url: `${app.globalData.apiBase}/payment/notify`,
|
||
method: 'POST',
|
||
header: {
|
||
'Authorization': `Bearer ${wx.getStorageSync('token')}`
|
||
},
|
||
data: {
|
||
orderId,
|
||
prepayId,
|
||
status: 'success'
|
||
},
|
||
success: (res) => {
|
||
console.log('支付通知成功', res)
|
||
},
|
||
fail: (err) => {
|
||
console.error('支付通知失败', err)
|
||
}
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 查询订单状态
|
||
* @param {String} orderId
|
||
* @param {Function} callback
|
||
*/
|
||
function queryOrderStatus(orderId, callback) {
|
||
wx.request({
|
||
url: `${app.globalData.apiBase}/payment/query`,
|
||
method: 'GET',
|
||
header: {
|
||
'Authorization': `Bearer ${wx.getStorageSync('token')}`
|
||
},
|
||
data: { orderId },
|
||
success: (res) => {
|
||
if (res.statusCode === 200) {
|
||
callback && callback(true, res.data)
|
||
} else {
|
||
callback && callback(false, null)
|
||
}
|
||
},
|
||
fail: () => {
|
||
callback && callback(false, null)
|
||
}
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 购买完整电子书
|
||
* @param {Function} success
|
||
* @param {Function} fail
|
||
*/
|
||
function purchaseFullBook(success, fail) {
|
||
// 计算动态价格:9.9 + (天数 * 1元)
|
||
const basePrice = 9.9
|
||
const startDate = new Date('2025-01-01') // 书籍上架日期
|
||
const today = new Date()
|
||
const daysPassed = Math.floor((today - startDate) / (1000 * 60 * 60 * 24))
|
||
const currentPrice = basePrice + daysPassed
|
||
|
||
const orderId = `ORDER_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
||
|
||
wxPay({
|
||
orderId,
|
||
amount: currentPrice,
|
||
description: 'Soul派对·创业实验 完整版',
|
||
success: (res) => {
|
||
// 更新本地购买状态
|
||
updatePurchaseStatus(true)
|
||
success && success(res)
|
||
},
|
||
fail
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 更新购买状态
|
||
* @param {Boolean} isPurchased
|
||
*/
|
||
function updatePurchaseStatus(isPurchased) {
|
||
const userInfo = app.getUserInfo()
|
||
if (userInfo) {
|
||
userInfo.isPurchased = isPurchased
|
||
wx.setStorageSync('userInfo', userInfo)
|
||
app.globalData.userInfo = userInfo
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查是否已购买
|
||
* @returns {Boolean}
|
||
*/
|
||
function checkPurchaseStatus() {
|
||
const userInfo = app.getUserInfo()
|
||
return userInfo ? userInfo.isPurchased : false
|
||
}
|
||
|
||
module.exports = {
|
||
wxPay,
|
||
queryOrderStatus,
|
||
purchaseFullBook,
|
||
checkPurchaseStatus,
|
||
updatePurchaseStatus
|
||
}
|