feat: 小程序真实微信支付功能
新增: 1. /api/miniprogram/pay - 创建预支付订单API 2. /api/miniprogram/pay/notify - 支付回调处理 3. /api/miniprogram/login - 小程序登录获取openId 配置: - 小程序AppID: wxb8bbb2b10dec74aa - 商户号: 1318592501 - 回调地址: https://soul.cunbao.net/api/miniprogram/pay/notify 更新: - app.js: 添加getOpenId方法,支付前获取openId - read.js: processPayment调用真实支付接口 - 支持API不可用时回退到测试模式
This commit is contained in:
@@ -361,65 +361,96 @@ ${id === 'preface' || id === 'epilogue' || id.startsWith('appendix') || id === '
|
||||
await this.processPayment('fullbook', null, this.data.fullBookPrice)
|
||||
},
|
||||
|
||||
// 处理支付
|
||||
// 处理支付 - 调用真实微信支付接口
|
||||
async processPayment(type, sectionId, amount) {
|
||||
this.setData({ isPaying: true })
|
||||
|
||||
try {
|
||||
// 创建订单
|
||||
// 1. 先获取openId (支付必需)
|
||||
let openId = app.globalData.openId || wx.getStorageSync('openId')
|
||||
|
||||
if (!openId) {
|
||||
console.log('[Pay] 需要先获取openId')
|
||||
openId = await app.getOpenId()
|
||||
|
||||
if (!openId) {
|
||||
wx.showModal({
|
||||
title: '提示',
|
||||
content: '需要登录后才能支付,请先登录',
|
||||
showCancel: false
|
||||
})
|
||||
this.setData({ showLoginModal: true, isPaying: false })
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[Pay] 开始创建订单:', { type, sectionId, amount, openId: openId.slice(0, 10) + '...' })
|
||||
|
||||
// 2. 调用后端创建预支付订单
|
||||
let paymentData = null
|
||||
|
||||
try {
|
||||
const res = await app.request('/api/payment/create-order', {
|
||||
const res = await app.request('/api/miniprogram/pay', {
|
||||
method: 'POST',
|
||||
data: { type, sectionId, amount }
|
||||
data: {
|
||||
openId,
|
||||
productType: type,
|
||||
productId: sectionId,
|
||||
amount,
|
||||
description: type === 'fullbook' ? '《一场Soul的创业实验》全书' : `章节-${sectionId}`,
|
||||
userId: app.globalData.userInfo?.id || ''
|
||||
}
|
||||
})
|
||||
|
||||
if (res.success && res.data) {
|
||||
paymentData = res.data
|
||||
console.log('[Pay] 创建订单响应:', res)
|
||||
|
||||
if (res.success && res.data?.payParams) {
|
||||
paymentData = res.data.payParams
|
||||
console.log('[Pay] 获取支付参数成功')
|
||||
} else {
|
||||
throw new Error(res.error || '创建订单失败')
|
||||
}
|
||||
} catch (apiError) {
|
||||
console.log('API创建订单失败,使用模拟支付')
|
||||
}
|
||||
|
||||
// 如果API不可用,使用模拟支付
|
||||
if (!paymentData) {
|
||||
paymentData = {
|
||||
isMock: true,
|
||||
orderId: 'mock_' + Date.now()
|
||||
}
|
||||
}
|
||||
|
||||
// 调用微信支付或模拟支付
|
||||
if (paymentData.isMock) {
|
||||
// 模拟支付确认
|
||||
const confirmRes = await new Promise((resolve) => {
|
||||
console.log('[Pay] API创建订单失败:', apiError.message)
|
||||
|
||||
// 开发环境:API不可用时使用模拟支付
|
||||
const useMock = await new Promise((resolve) => {
|
||||
wx.showModal({
|
||||
title: '确认支付',
|
||||
content: `支付 ¥${amount} 购买${type === 'section' ? '本章' : '全书'}?\n(测试环境模拟支付)`,
|
||||
title: '支付服务暂不可用',
|
||||
content: '是否使用测试模式完成购买?',
|
||||
confirmText: '测试购买',
|
||||
cancelText: '取消',
|
||||
success: (res) => resolve(res.confirm)
|
||||
})
|
||||
})
|
||||
|
||||
if (confirmRes) {
|
||||
// 模拟支付成功,更新本地数据
|
||||
if (useMock) {
|
||||
this.mockPaymentSuccess(type, sectionId)
|
||||
wx.showToast({ title: '购买成功', icon: 'success' })
|
||||
wx.showToast({ title: '测试购买成功', icon: 'success' })
|
||||
this.initSection(this.data.sectionId)
|
||||
}
|
||||
} else {
|
||||
// 真实微信支付
|
||||
await this.callWechatPay(paymentData)
|
||||
wx.showToast({ title: '购买成功', icon: 'success' })
|
||||
this.setData({ isPaying: false })
|
||||
return
|
||||
}
|
||||
|
||||
// 刷新页面
|
||||
// 3. 调用微信支付
|
||||
console.log('[Pay] 调起微信支付')
|
||||
await this.callWechatPay(paymentData)
|
||||
|
||||
// 4. 支付成功,更新本地数据
|
||||
this.mockPaymentSuccess(type, sectionId)
|
||||
wx.showToast({ title: '购买成功', icon: 'success' })
|
||||
|
||||
// 5. 刷新页面
|
||||
this.initSection(this.data.sectionId)
|
||||
|
||||
} catch (e) {
|
||||
console.error('[Pay] 支付失败:', e)
|
||||
|
||||
if (e.errMsg && e.errMsg.includes('cancel')) {
|
||||
wx.showToast({ title: '已取消支付', icon: 'none' })
|
||||
} else {
|
||||
wx.showToast({ title: '支付失败', icon: 'none' })
|
||||
wx.showToast({ title: e.errMsg || '支付失败', icon: 'none' })
|
||||
}
|
||||
} finally {
|
||||
this.setData({ isPaying: false })
|
||||
|
||||
Reference in New Issue
Block a user