feat: 微信分享钩子全页面接入 + 订阅信息结构化映射 + JWT 错误处理加强

- client: 全部页面接入 onShareAppMessage/onShareTimeline 分享钩子
- client: login 页增强、profile 订阅展示优化
- client/stores: 订阅字段扁平结构映射为 subInfo(plan/expiresAt/startDate)
- server: auth 路由 JWT 无效/过期统一返回 401 未授权响应
- server: models/tests 同步更新
This commit is contained in:
Yuzhiran Dev
2026-09-04 11:47:29 +08:00
parent de8ca9c420
commit 66de1dc396
37 changed files with 2138 additions and 1830 deletions
+51 -1
View File
@@ -146,7 +146,7 @@ class WeChatService {
out_trade_no: orderNo,
notify_url: this.notifyUrl,
amount: {
total: Math.round(amount * 100), // 转换为分
total: Math.round(amount), // 金额单位已为分
currency: 'CNY'
},
payer: {
@@ -184,6 +184,56 @@ class WeChatService {
}
}
/**
* 创建H5支付订单(微信H5支付/MWEB)
* @param {Object} orderData - { orderNo, body, amount, clientIp, appId }
*/
async createH5PaymentOrder(orderData) {
const { orderNo, body, amount, clientIp, appId } = orderData
const nonceStr = this.generateNonceStr()
const timestamp = Math.floor(Date.now() / 1000).toString()
// 1. 统一下单 (H5 / MWEB)
const url = '/v3/pay/transactions/h5'
const fullUrl = `https://api.mch.weixin.qq.com${url}`
const orderParams = {
appid: appId || this.appId,
mchid: this.mchId,
description: body,
out_trade_no: orderNo,
notify_url: this.notifyUrl,
amount: {
total: Math.round(amount), // 金额单位已为分
currency: 'CNY'
},
scene_info: {
h5_info: {
type: 'Wap',
client_ip: clientIp
}
}
}
// 模拟返回 h5_url (生产环境需调用真实微信支付接口)
// 实际生产调用示例:
// const sign = this.generateSign('POST', url, timestamp, nonceStr, JSON.stringify(orderParams))
// const response = await axios.post(fullUrl, orderParams, {
// headers: { 'Authorization': `WECHATPAY2-SHA256-RSA2048 ${sign}` }
// })
// const h5Url = response.data.h5_url
// 模拟 H5 支付链接(生产环境由微信返回真实 MWEB_URL)
const mockH5Url = `https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx_mock_${Date.now()}&package=mock_${Date.now()}`
return {
h5Url: mockH5Url,
orderNo,
amount: Math.round(amount)
}
}
/**
* 申请退款
*/