diff --git a/api/auth.ts b/api/auth.ts index b29bd5b..2215adf 100644 --- a/api/auth.ts +++ b/api/auth.ts @@ -1,5 +1,6 @@ import { APP_CONFIG } from '@/config'; import { HttpStatusError, httpRequest, toFormUrlEncoded } from '@/utils/http'; +import { postForm } from '@/utils/request'; export interface LoginResponse { code: number | string; @@ -53,30 +54,25 @@ export const loginByCode = async (code: string) => { /** @deprecated 使用 loginByCode */ export const loginByWechatCode = loginByCode; -export interface MobileAuthBindResponse { +export interface BindMobileResponse { code: number | string; msg?: string; - data?: unknown; + data?: { + code?: string; + msg?: string; + mobile?: string; + }; } -/** 小程序授权绑定手机号(微信/支付宝) */ -export const mobileAuthBind = async (code: string) => { - const response = await httpRequest({ - url: `${APP_CONFIG.API_BASE_URL}/user/v1/mobile.auth.bind`, - method: 'POST', - data: toFormUrlEncoded({ - code, - app_id: APP_CONFIG.APP_ID, - platform: resolveLoginPlatform() - }), - header: { - 'content-type': 'application/x-www-form-urlencoded' - } +/** + * 支付宝手机号绑定。 + * encryptedData = my.getPhoneNumber 成功回调里 response.response(解密密文) + * 需登录态:走 postForm,自动带 Authorization: Bearer + */ +export const bindMobile = (encryptedData: string) => { + return postForm('user/v1/bind.mobile', { + encryptedData, + app_id: APP_CONFIG.APP_ID, + platform: resolveLoginPlatform() }); - - if (response.statusCode < 200 || response.statusCode >= 300) { - throw new HttpStatusError('手机号绑定失败', response.statusCode, response.data); - } - - return response.data; }; diff --git a/pages/pay/pay.vue b/pages/pay/pay.vue index c59fe12..d3d191c 100644 --- a/pages/pay/pay.vue +++ b/pages/pay/pay.vue @@ -189,7 +189,7 @@ import { computed, ref } from 'vue'; import { onLoad, onShow } from '@dcloudio/uni-app'; import { bindMerchantByUrl, cancelTrade, changeMerchant, merchantListByUrl, supplierByUrl } from '@/api/cashier'; import type { MerchantListItem } from '@/api/cashier'; -import { mobileAuthBind, resolveLoginPlatform } from '@/api/auth'; +import { bindMobile, resolveLoginPlatform } from '@/api/auth'; import { postForm } from '@/utils/request'; import { DEFAULT_MERCHANT, APP_CONFIG, PROPERTY_APP } from '@/config'; import { @@ -680,13 +680,46 @@ const refreshPropertyAfterPhoneBind = async () => { alipayPropertyUnbound.value = true; }; -const extractAlipayPhoneCode = (phoneRes: any) => { - const response = phoneRes?.response; - if (typeof response === 'string') return response; - if (response && typeof response === 'object') { - return response.response || response.code || ''; +const tryParseJson = (value: any) => { + if (typeof value !== 'string') return value; + const text = value.trim(); + if (!text || (text[0] !== '{' && text[0] !== '[')) return value; + try { + return JSON.parse(text); + } catch { + return value; } - return phoneRes?.code || ''; +}; + +/** 调试日志用:把嵌套 JSON 字符串展开成可展开对象 */ +const toLogObject = (value: any, depth = 0): any => { + if (value == null || depth > 4) return value; + const parsed = tryParseJson(value); + if (Array.isArray(parsed)) { + return parsed.map((item) => toLogObject(item, depth + 1)); + } + if (parsed && typeof parsed === 'object') { + const result: Record = {}; + Object.keys(parsed).forEach((key) => { + result[key] = toLogObject(parsed[key], depth + 1); + }); + return result; + } + return parsed; +}; + +const logPhoneAuth = (label: string, payload?: any) => { + console.log(`[收银台][手机号授权] ${label}`, payload === undefined ? undefined : toLogObject(payload)); +}; + +/** 取 getPhoneNumber 密文:response.response */ +const extractAlipayEncryptedData = (phoneRes: any) => { + const parsed = tryParseJson(phoneRes?.response); + if (parsed && typeof parsed === 'object') { + const encrypted = parsed.response; + return typeof encrypted === 'string' ? encrypted.trim() : ''; + } + return typeof phoneRes?.response === 'string' ? phoneRes.response.trim() : ''; }; const requestAlipayPhoneNumber = () => @@ -708,36 +741,35 @@ const requestAlipayPhoneNumber = () => }); const handleAlipayPhoneAuthTap = () => { - console.log('[收银台][手机号授权] 按钮点击'); + logPhoneAuth('按钮点击'); }; const handleAlipayPhoneAuthError = (event?: any) => { - console.log('[收银台][手机号授权] error 回调', event); + logPhoneAuth('error 回调', event); }; const handleAlipayPhoneAuthorize = async (event?: any) => { - console.log('[收银台][手机号授权] getAuthorize 回调', event); + logPhoneAuth('getAuthorize 回调', event); if (paying.value || bindingPhone.value) return; bindingPhone.value = true; try { const phoneRes = await requestAlipayPhoneNumber(); - console.log('[收银台][手机号授权] getPhoneNumber 成功', phoneRes); + logPhoneAuth('getPhoneNumber 成功', phoneRes); - const code = extractAlipayPhoneCode(phoneRes); - console.log('[收银台][手机号授权] 解析 code', { - code, - response: phoneRes?.response, - phoneCode: phoneRes?.code + const encryptedData = extractAlipayEncryptedData(phoneRes); + logPhoneAuth('解析 encryptedData', { + encryptedData, + response: tryParseJson(phoneRes?.response) }); - if (!code) { + if (!encryptedData) { throw new Error('手机号授权失败'); } - const response = await mobileAuthBind(code); - console.log('[收银台][手机号授权] mobileAuthBind 响应', response); + const response = await bindMobile(encryptedData); + logPhoneAuth('bind.mobile 响应', response); if (Number(response?.code) !== 200) { throw new Error(response?.msg || '手机号绑定失败'); @@ -745,7 +777,7 @@ const handleAlipayPhoneAuthorize = async (event?: any) => { await refreshPropertyAfterPhoneBind(); } catch (error: any) { - console.log('[收银台][手机号授权] 授权失败', error); + logPhoneAuth('授权失败', error); const errMsg = error?.errMsg || error?.message || ''; if (errMsg.includes('cancel') || errMsg.includes('拒绝')) return; uni.showToast({