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