fix(payment): 修复微信支付时openid绑定问题

- 新增确保支付前openid正确绑定的方法,解决支付账号不一致问题
- 在创建微信支付订单前强制刷新openid,防止旧微信账号导致支付失败
- 在自动登录后补充openid绑定步骤,确保支付所需的openid存在
- 设计为非阻塞流程,避免网络异常导致支付阻塞
- 仅针对微信支付触发,其他支付方式不受影响
This commit is contained in:
2026-04-25 12:59:59 +08:00
parent 4d96ca4569
commit 94e1e05fdf
3 changed files with 110 additions and 1 deletions

View File

@@ -5,6 +5,7 @@ import { getSelectedStoreFromStorage, getSelectedStoreIdFromStorage } from '@/ut
import type { ShopStoreRider } from '@/api/shop/shopStoreRider/model';
import type { ShopStoreWarehouse } from '@/api/shop/shopStoreWarehouse/model';
import request from '@/utils/request';
import { getWxOpenId, getUserInfo } from '@/api/layout';
/**
* 支付类型枚举
@@ -33,6 +34,74 @@ export class PaymentHandler {
private static storeRidersCache = new Map<number, ShopStoreRider[]>();
private static warehousesCache: ShopStoreWarehouse[] | null = null;
/**
* 【关键修复】支付前确保当前微信用户的 openid 已正确绑定到后端
*
* 问题场景:
* 1. 用户通过手机号注册 → openid 未绑定 → 后端用空 openid 创建预支付单 → 支付时报"账号不一致"
* 2. 用户切换了微信账号 → 本地缓存的用户信息是旧账号的 → openid 与当前支付人不匹配
* 3. 自动登录(loginByOpenId)未触发 getWxOpenId 绑定流程
*
* 解决方案:每次微信支付前,重新获取 wx.login code 并调用 getWxOpenId 绑定,
* 确保后端记录的 openid = 当前实际支付人的 openid
*/
private static async ensureOpenIdBeforePay(): Promise<void> {
try {
// 非微信环境跳过(如 H5 开发调试)
let isWeapp = false;
try {
isWeapp = Taro.getEnv() === Taro.ENV_TYPE.WEAPP;
} catch (_e) {
isWeapp = process.env.TARO_ENV === 'weapp';
}
if (!isWeapp) return;
// 获取当前登录用户的最新信息(检查是否已有 openid
let currentUser = null;
try {
currentUser = await getUserInfo();
} catch (_e) {
// getUserInfo 失败时不阻塞支付(可能是 token 过期等),让后续接口自行报错
console.warn('[ensureOpenId] 获取用户信息失败,跳过 openid 校验');
return;
}
// 如果用户已有 openid仍然需要刷新因为用户可能切换了微信账号
// 每次都重新获取 code + 绑定,确保 openid 是当前微信会话的
const code = await new Promise<string | undefined>((resolve, reject) => {
Taro.login({
success: (res) => resolve(res.code as string),
fail: (e) => reject(e),
timeout: 5000, // 5秒超时
});
});
if (!code) {
console.warn('[ensureOpenId] wx.login 未返回 code');
return;
}
// 调用后端绑定/更新 openid
await getWxOpenId({ code });
console.log('[ensureOpenId] openid 刷新/绑定成功');
// 同步本地 User 缓存,确保后续逻辑能读到最新 openid
try {
const freshUser = await getUserInfo();
if (freshUser) {
Taro.setStorageSync('User', freshUser);
}
} catch (_e) {
// ignore: 服务端已更新 openid本地缓存不同步也不影响本次支付
}
} catch (error) {
// openid 刷新失败不阻塞支付流程(可能网络波动),
// 但记录日志方便排查;若确实不一致,微信支付侧会报错
console.warn('[ensureOpenId] openid 刷新失败(非阻塞):', error);
}
}
/**
* 执行支付
* @param orderData 订单数据
@@ -80,6 +149,12 @@ export class PaymentHandler {
// 设置支付类型
orderData.payType = paymentType;
// 【关键修复】微信支付前,强制刷新/绑定当前微信用户的 openid
// 防止"下单账号与支付账号不一致"错误
if (paymentType === PaymentType.WECHAT) {
await this.ensureOpenIdBeforePay();
}
console.log('创建订单请求:', orderData);
// 创建订单