Pārlūkot izejas kodu

fix: 接入 getuserdetail 获取手机号并展示调试参数

内部成员授权后优先调用 getuserdetail 并用 mobile 回填访客缓存,缺失时回退 user/get。首页调试弹窗改为展示 getuserdetail 返回,并单独显示 user_ticket 与 access_token 参数。

Made-with: Cursor
haifeng.zhang 1 nedēļu atpakaļ
vecāks
revīzija
207cf4052d
3 mainītis faili ar 56 papildinājumiem un 4 dzēšanām
  1. 37 2
      src/api/wecom/index.ts
  2. 11 0
      src/api/wecom/types.ts
  3. 8 2
      src/pages/home/index.vue

+ 37 - 2
src/api/wecom/index.ts

@@ -10,6 +10,7 @@ import type {
   WecomGroupChatResponse,
   WecomInternalUserResponse,
   WecomTokenResponse,
+  WecomUserDetailResponse,
   WecomVisitorProfile,
 } from './types'
 
@@ -36,6 +37,7 @@ const TOKEN_EXPIRED_ERRCODES = new Set([40014, 42001])
 const wecomActionText: Record<string, string> = {
   gettoken: '企业微信凭证获取失败',
   getuserinfo: '身份获取失败',
+  getuserdetail: '成员敏感信息获取失败',
   userGet: '成员信息获取失败',
   externalcontactGet: '外部联系人信息获取失败',
   groupchatGet: '客户群信息获取失败',
@@ -173,6 +175,20 @@ export function getWecomInternalUser(userid: string) {
   )
 }
 
+export function getWecomUserDetail(userTicket: string) {
+  return requestWithAccessToken<WecomUserDetailResponse>(
+    (accessToken) => ({
+      url: '/cgi-bin/auth/getuserdetail',
+      method: 'POST',
+      data: {
+        access_token: accessToken,
+        user_ticket: userTicket,
+      },
+    }),
+    'getuserdetail',
+  )
+}
+
 export function getWecomExternalContact(externalUserId: string) {
   return requestWithAccessToken<WecomExternalContactResponse>(
     (accessToken) => ({
@@ -316,15 +332,30 @@ export async function syncExternalVisitorProfile(code: string) {
       userInfo,
       externalContact,
       internalUserRaw: undefined,
+      userTicket: undefined,
+      debugAccessToken: undefined,
     }
   }
 
   const memberUserId = pickMemberUserId(userInfo)
   if (memberUserId) {
     const internal = await getWecomInternalUser(memberUserId)
+    let detailRaw: WecomUserDetailResponse | undefined
+    let detailMobile = ''
+    let debugAccessToken = ''
+    if (userInfo.user_ticket) {
+      try {
+        const detail = await getWecomUserDetail(userInfo.user_ticket)
+        detailRaw = detail
+        detailMobile = (detail.mobile || '').trim()
+        debugAccessToken = getCachedAccessToken()
+      } catch {
+        detailMobile = ''
+      }
+    }
     const profile: WecomVisitorProfile = {
       name: internal.name || '',
-      mobile: (internal.mobile || internal.telephone || '').trim(),
+      mobile: detailMobile || (internal.mobile || internal.telephone || '').trim(),
       unionid: '',
       internalUserid: memberUserId,
     }
@@ -334,7 +365,9 @@ export async function syncExternalVisitorProfile(code: string) {
       profile,
       userInfo,
       externalContact: null,
-      internalUserRaw: internal,
+      internalUserRaw: detailRaw,
+      userTicket: userInfo.user_ticket || '',
+      debugAccessToken,
     }
   }
 
@@ -344,5 +377,7 @@ export async function syncExternalVisitorProfile(code: string) {
     userInfo,
     externalContact: null,
     internalUserRaw: undefined,
+    userTicket: undefined,
+    debugAccessToken: undefined,
   }
 }

+ 11 - 0
src/api/wecom/types.ts

@@ -27,6 +27,17 @@ export interface WecomInternalUserResponse extends WecomBaseResponse {
   position?: string
 }
 
+export interface WecomUserDetailResponse extends WecomBaseResponse {
+  userid?: string
+  gender?: string | number
+  avatar?: string
+  qr_code?: string
+  mobile?: string
+  email?: string
+  biz_mail?: string
+  address?: string
+}
+
 export interface WecomExternalContactResponse extends WecomBaseResponse {
   external_contact?: {
     name?: string

+ 8 - 2
src/pages/home/index.vue

@@ -87,7 +87,13 @@ const bootstrapWithCode = async (code: string) => {
   }
   applyVisitorFromSyncResult(result)
   if (result.internalUserRaw) {
-    internalUserGetJsonText.value = JSON.stringify(result.internalUserRaw, null, 2)
+    internalUserGetJsonText.value = JSON.stringify({
+      authParams: {
+        user_ticket: result.userTicket || '',
+        access_token: result.debugAccessToken || '',
+      },
+      getuserdetail: result.internalUserRaw,
+    }, null, 2)
     internalUserGetPopupVisible.value = true
   }
 }
@@ -159,7 +165,7 @@ const getQuestionPage = () => {
     <img class="box_bg_bottom" src="@/assets/bg_bottom.png" alt="" srcset="">
 
     <van-popup v-model:show="internalUserGetPopupVisible" round closeable class="user-get-popup">
-      <view class="user-get-popup__header">user/get 返回</view>
+      <view class="user-get-popup__header">getuserdetail 返回</view>
       <scroll-view scroll-y class="user-get-popup__content">
         <text selectable class="user-get-popup__json">{{ internalUserGetJsonText }}</text>
       </scroll-view>