From 94e1e05fdf67abd9392c2dff94fc17451217730b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Sat, 25 Apr 2026 12:59:59 +0800 Subject: [PATCH] =?UTF-8?q?fix(payment):=20=E4=BF=AE=E5=A4=8D=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E6=94=AF=E4=BB=98=E6=97=B6openid=E7=BB=91=E5=AE=9A?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增确保支付前openid正确绑定的方法,解决支付账号不一致问题 - 在创建微信支付订单前强制刷新openid,防止旧微信账号导致支付失败 - 在自动登录后补充openid绑定步骤,确保支付所需的openid存在 - 设计为非阻塞流程,避免网络异常导致支付阻塞 - 仅针对微信支付触发,其他支付方式不受影响 --- .workbuddy/memory/2026-04-25.md | 16 +++++++ src/hooks/useUser.ts | 20 ++++++++- src/utils/payment.ts | 75 +++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 .workbuddy/memory/2026-04-25.md diff --git a/.workbuddy/memory/2026-04-25.md b/.workbuddy/memory/2026-04-25.md new file mode 100644 index 0000000..bd9f085 --- /dev/null +++ b/.workbuddy/memory/2026-04-25.md @@ -0,0 +1,16 @@ +# 2026-04-25 工作日志 + +## 微信支付"下单账号与支付账号不一致"问题修复 + +**问题**:用户支付时微信提示「下单账号与支付账号不一致,请核实后再支付」 + +**根因**:下单时后端使用的 openid 与当前实际支付的微信用户 openid 不匹配。前端在创建订单前没有刷新 openid,依赖登录/注册时的旧绑定。 + +**修改文件**: +1. `src/utils/payment.ts` — 新增 `ensureOpenIdBeforePay()` 方法,在 `pay()` 方法中、微信支付创建订单前强制调用 `Taro.login()` + `getWxOpenId()` 刷新绑定当前用户的 openid +2. `src/hooks/useUser.ts` — 在 `autoLoginByOpenId()` 登录成功后补充 openid 绑定逻辑(之前只调了 loginByOpenId 没有调 getWxOpenId) + +**方案特点**: +- 非阻塞设计:openid 刷新失败不阻止支付(网络波动时兼容) +- 仅微信支付触发:余额支付/支付宝不受影响 +- 兼容已有 openid 的场景:即使已有 openid 也会刷新(防止切号) diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts index df5c040..d1e42da 100644 --- a/src/hooks/useUser.ts +++ b/src/hooks/useUser.ts @@ -1,7 +1,7 @@ import { useState, useEffect } from 'react'; import Taro from '@tarojs/taro'; import { User } from '@/api/system/user/model'; -import { getUserInfo, updateUserInfo, loginByOpenId } from '@/api/layout'; +import { getUserInfo, updateUserInfo, loginByOpenId, getWxOpenId } from '@/api/layout'; import { TenantId } from '@/config/app'; import { handleInviteRelation } from '@/utils/invite'; @@ -27,6 +27,24 @@ export const useUser = () => { setUser(data.user); setIsLoggedIn(true); + // 自动登录成功后,补齐 openid(JSAPI 微信支付必需) + // 防止后续支付时报"下单账号与支付账号不一致" + if (!data.user?.openid) { + try { + const freshCode = await new Promise((resolve, reject) => { + Taro.login({ + success: (r) => resolve(r.code as string), + fail: () => resolve(undefined), + }); + }); + if (freshCode) { + await getWxOpenId({ code: freshCode }); + } + } catch (_e) { + console.warn('自动登录后绑定 openid 失败'); + } + } + // 处理邀请关系 if (data.user?.userId) { try { diff --git a/src/utils/payment.ts b/src/utils/payment.ts index 4444070..5183aad 100644 --- a/src/utils/payment.ts +++ b/src/utils/payment.ts @@ -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(); 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 { + 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((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); // 创建订单