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
|
|||
|
|
}
|