import { get } from '@af-mobile-client-vue3/services/restTools' import { detectEnvironment } from '@af-mobile-client-vue3/utils/environment' import wx from 'weixin-js-sdk' // 微信JS-SDK配置接口 export interface WechatConfig { debug: boolean appId: string timestamp: number nonceStr: string signature: string jsApiList: wx.ApiMethod[] } // 微信扫码配置 export interface WechatScanConfig { needResult: 0 | 1 scanType: wx.scanType[] } // 微信扫码结果 export interface WechatScanResult { resultStr: string } // 检查是否在微信环境中 export function isWechatBrowser(): boolean { const env = detectEnvironment() return env.isWechat } // 检查是否在小程序环境中 export function isMiniprogram(): boolean { const env = detectEnvironment() return env.isMiniprogram } // 配置微信JS-SDK export function configWechatSDK(config: WechatConfig): Promise { return new Promise((resolve, reject) => { if (!isWechatBrowser()) { reject(new Error('非微信环境,无法使用微信JS-SDK')) return } wx.config({ debug: config.debug, appId: config.appId, timestamp: config.timestamp, nonceStr: config.nonceStr, signature: config.signature, jsApiList: config.jsApiList, }) wx.ready(() => { console.log('微信JS-SDK配置成功') resolve() }) wx.error((res: any) => { console.error('微信JS-SDK配置失败:', res) reject(new Error(`微信JS-SDK配置失败: ${res.errMsg}`)) }) }) } // 微信扫码 export function scanQRCode(config: WechatScanConfig): Promise { return new Promise((resolve, reject) => { if (!isWechatBrowser()) { reject(new Error('非微信环境,无法使用微信扫码')) return } wx.scanQRCode({ needResult: config.needResult, scanType: config.scanType, success: (res: WechatScanResult) => { console.log('微信扫码成功:', res) resolve(res) }, fail: (res: any) => { console.error('微信扫码失败:', res) reject(new Error(`微信扫码失败: ${res.errMsg}`)) }, cancel: () => { reject(new Error('用户取消扫码')) }, }) }) } // 获取微信签名(模拟) export async function getWechatSignature(url: string): Promise<{ appId: string timestamp: number nonceStr: string signature: string }> { // 这里应该调用后端接口获取微信签名 // 现在使用模拟数据 return new Promise((resolve) => { get(`/af-wechat/weixin/getJsSdk?path=${url}`).then((res) => { resolve({ appId: res.appId, timestamp: res.timeStamp, nonceStr: res.nonceStr, signature: res.sign, }) }) }) } // 初始化微信环境 export async function initWechatEnvironment(): Promise { if (!isWechatBrowser()) { console.log('非微信环境,跳过微信初始化') return } try { const currentUrl = window.location.href.split('#')[0] const signatureData = await getWechatSignature(currentUrl) await configWechatSDK({ debug: false, appId: signatureData.appId, timestamp: signatureData.timestamp, nonceStr: signatureData.nonceStr, signature: signatureData.signature, jsApiList: [ 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'onVoicePlayEnd', 'uploadVoice', 'downloadVoice', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'translateVoice', 'getNetworkType', 'openLocation', 'getLocation', 'hideOptionMenu', 'showOptionMenu', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'closeWindow', 'scanQRCode', 'chooseWXPay', 'openProductSpecificView', 'addCard', 'chooseCard', 'openCard', ], }) console.log('微信环境初始化成功') } catch (error) { console.error('微信环境初始化失败:', error) } } // 小程序扫码(在小程序环境中) export function miniprogramScanCode(): Promise { return new Promise((resolve, reject) => { if (!isMiniprogram()) { reject(new Error('非小程序环境,无法使用小程序扫码')) return } // 在小程序环境中,通过 postMessage 与小程序通信 const mp = (window as any).wx && (window as any).wx.miniProgram const sendMessage = (payload: any) => { if (mp && typeof mp.postMessage === 'function') { mp.postMessage({ data: payload }) } else if (window.parent && window.parent !== window) { window.parent.postMessage(payload, '*') } else { throw new Error('无法与小程序通信') } } try { sendMessage({ type: 'scanCode', data: {} }) // 监听小程序返回的扫码结果 const handleMessage = (event: MessageEvent) => { const raw = (event as any).data const msg = raw && typeof raw === 'object' && 'data' in raw ? (raw as any).data : raw if (msg && msg.type === 'scanCodeResult') { window.removeEventListener('message', handleMessage) if (msg.success) { resolve(msg.result) } else { reject(new Error(msg.error || '扫码失败')) } } } window.addEventListener('message', handleMessage) // 设置超时 setTimeout(() => { window.removeEventListener('message', handleMessage) reject(new Error('扫码超时')) }, 30000) } catch (err) { reject(err) } }) } // 小程序NFC读取(在小程序环境中) export function miniprogramNfcRead(): Promise { return new Promise((resolve, reject) => { if (!isMiniprogram()) { reject(new Error('非小程序环境,无法使用小程序NFC')) return } const mp = (window as any).wx && (window as any).wx.miniProgram const sendMessage = (payload: any) => { if (mp && typeof mp.postMessage === 'function') { mp.postMessage({ data: payload }) } else if (window.parent && window.parent !== window) { window.parent.postMessage(payload, '*') } else { throw new Error('无法与小程序通信') } } try { sendMessage({ type: 'nfcRead', data: {} }) const handleMessage = (event: MessageEvent) => { const raw = (event as any).data const msg = raw && typeof raw === 'object' && 'data' in raw ? (raw as any).data : raw if (msg && msg.type === 'nfcResult') { window.removeEventListener('message', handleMessage) if (msg.success) { resolve(msg.result || '') } else { reject(new Error(msg.error || 'NFC读取失败')) } } } window.addEventListener('message', handleMessage) setTimeout(() => { window.removeEventListener('message', handleMessage) reject(new Error('NFC读取超时')) }, 30000) } catch (err) { reject(err) } }) } // H5:仅监听小程序主动回传 export function waitAuthFromMiniProgram(timeout = 15000) { return new Promise<{ token: string, resources?: any, expireTime?: number }>((resolve, reject) => { const handle = (event: MessageEvent) => { const raw = (event as any).data const msg = raw && typeof raw === 'object' && 'data' in raw ? (raw as any).data : raw if (msg && msg.type === 'auth') { window.removeEventListener('message', handle) return msg ? resolve(msg) : reject(new Error('未获取到授权信息')) } } window.addEventListener('message', handle) setTimeout(() => { window.removeEventListener('message', handle) reject(new Error('获取授权信息超时')) }, timeout) }) }