diff --git a/pages/p2p/authorizeWechat.vue b/pages/p2p/authorizeWechat.vue index 6d3c9bd..a87155f 100644 --- a/pages/p2p/authorizeWechat.vue +++ b/pages/p2p/authorizeWechat.vue @@ -11,15 +11,27 @@ 您已授权 - 您已拒绝授权,请去设置中 - - 打开语音、视频通话提醒开关 + + 授权失败 + 请保证设备一直处于在线状态 + + 重试 + - - 打开设置 + + 您已拒绝授权,请去设置中 + + 打开语音、视频通话提醒开关 + + + 打开设置 + @@ -52,57 +64,76 @@ const pending = ref(false) - onShow(() => { + const weChatTicketsFlag = ref(false) + + onShow(async () => { uni.showLoading({ title: '加载中...' }) - wx.getDeviceVoIPList({ - async success(res) { - list.value = res.list - if (res.list.length > 0) { - const result = await getInfo() - if (result.code === 0) { - const data = list.value.find(item => item.sn === result.data.WXIoTDeviceInfo.SN) - if (data) { - if (data.status === 1) { - if (reject.value) { - passthrough({ - request_method: 'POST', - request_uri: '/api/v1/tencentYun/reportWechatAuthSuccess', - post_args: { - lockId: $bluetooth.currentLockInfo.lockId, - wxOpenid: getStorage('openid'), - wxDeviceSn: result.data.WXIoTDeviceInfo.SNTicket - } - }) - } - reject.value = false - } else if (data.status === 0) { - reject.value = true - } - isAuthorized.value = true - requestFinish.value = true - uni.hideLoading() - } else { - requestFinish.value = true - uni.hideLoading() - } - } else { - uni.showToast({ - title: result.message, - icon: 'none' - }) - requestFinish.value = true - uni.hideLoading() - } - } else { - requestFinish.value = true - uni.hideLoading() - } + + const resultList = await Promise.all([getDeviceVoIPList(), getAuthResult()]) + + list.value = resultList[0] + const authResult = resultList[1] + + const data = list.value.find(item => item.sn === authResult.data.wxDeviceSn) + + if (authResult?.code === 0 && authResult?.data?.wxOpenid === getStorage('openid') && data) { + isAuthorized.value = true + requestFinish.value = true + if (data.status === 1) { + reject.value = false + } else if (data.status === 0) { + reject.value = true + weChatTicketsFlag.value = true } - }) + uni.hideLoading() + } else { + requestFinish.value = true + uni.hideLoading() + } }) + const getDeviceVoIPList = async () => { + return new Promise(resolve => { + wx.getDeviceVoIPList({ + success: res => { + resolve(res.list) + } + }) + }) + } + + const retry = async () => { + if (pending.value) return + uni.showLoading({ + title: '授权中...' + }) + pending.value = true + const ticketsResult = await weChatTickets() + + pending.value = false + if (ticketsResult?.code === 0) { + passthrough({ + request_method: 'POST', + request_uri: '/api/v1/tencentYun/reportWechatAuthSuccess', + post_args: { + lockId: $bluetooth.currentLockInfo.lockId, + wxOpenid: getStorage('openid'), + wxDeviceSn: ticketsResult.data.wxDeviceSn + } + }) + uni.hideLoading() + isAuthorized.value = true + } else { + uni.hideLoading() + uni.showToast({ + title: '授权失败', + icon: 'none' + }) + } + } + const openSetting = () => { uni.openSetting({ success: res => { @@ -111,6 +142,18 @@ }) } + const getAuthResult = async () => { + const result = await passthrough({ + request_method: 'GET', + request_uri: '/api/v1/tencentYun/checkWechatAuth', + post_args: { + lockId: $bluetooth.currentLockInfo.lockId, + wxOpenid: getStorage('openid') + } + }) + return result + } + const getInfo = async () => { const result = await passthrough({ request_method: 'GET', @@ -122,6 +165,29 @@ return result } + const weChatTickets = async (snTicket, sn) => { + let ticket = snTicket + let snResult = sn + if (!snTicket) { + const result = await getInfo() + ticket = result.data.WXIoTDeviceInfo.SNTicket + snResult = result.data.WXIoTDeviceInfo.SN + } + const result = await $bluetooth.weChatTickets({ + keyId: $bluetooth.currentLockInfo.keyId.toString(), + uid: $bluetooth.currentLockInfo.uid.toString(), + openId: getStorage('openid'), + snTicket: ticket + }) + + return { + code: result.code, + data: { + wxDeviceSn: snResult + } + } + } + const handleAuthorize = async () => { if (pending.value) return pending.value = true @@ -136,22 +202,39 @@ modelId: result.data.WXIoTDeviceInfo.ModelId, deviceName: await env[await getApp().globalData.getEnvConfig()].appName, async success() { - isAuthorized.value = true - uni.hideLoading() - pending.value = false - passthrough({ - request_method: 'POST', - request_uri: '/api/v1/tencentYun/reportWechatAuthSuccess', - post_args: { - lockId: $bluetooth.currentLockInfo.lockId, - wxOpenid: getStorage('openid'), - wxDeviceSn: result.data.WXIoTDeviceInfo.SNTicket - } - }) - uni.showToast({ - title: '授权成功', - icon: 'none' - }) + const ticketsResult = await weChatTickets( + result.data.WXIoTDeviceInfo.SNTicket, + result.data.WXIoTDeviceInfo.SN + ) + + if (ticketsResult?.code === 0) { + isAuthorized.value = true + uni.hideLoading() + pending.value = false + passthrough({ + request_method: 'POST', + request_uri: '/api/v1/tencentYun/reportWechatAuthSuccess', + post_args: { + lockId: $bluetooth.currentLockInfo.lockId, + wxOpenid: getStorage('openid'), + wxDeviceSn: result.data.WXIoTDeviceInfo.SN + } + }) + uni.showToast({ + title: '授权成功', + icon: 'none' + }) + } else { + isAuthorized.value = true + uni.hideLoading() + pending.value = false + reject.value = true + weChatTicketsFlag.value = true + uni.showToast({ + title: '授权失败', + icon: 'none' + }) + } }, fail() { isAuthorized.value = true diff --git a/stores/bluetooth.js b/stores/bluetooth.js index 4484d7a..dad8566 100644 --- a/stores/bluetooth.js +++ b/stores/bluetooth.js @@ -116,7 +116,9 @@ const subCmdIds = { // 修改设置 updateSetting: 70, // 修改设置带参数 - updateSettingWithParams: 72 + updateSettingWithParams: 72, + // 微信票据 + weChatTickets: 55 } export const useBluetoothStore = defineStore('ble', { @@ -482,6 +484,21 @@ export const useBluetoothStore = defineStore('ble', { } }) break + case subCmdIds.weChatTickets: + that.updateCurrentLockInfo({ + ...that.currentLockInfo, + token: decrypted.slice(5, 9) + }) + if (decrypted[2] === 0) { + characteristicValueCallback({ + code: decrypted[9] + }) + } else { + characteristicValueCallback({ + code: decrypted[2] + }) + } + break case subCmdIds.registerCard: case subCmdIds.registerRemote: case subCmdIds.registerPalmVein: @@ -2861,6 +2878,107 @@ export const useBluetoothStore = defineStore('ble', { return this.getResult(this.setLockPassword, data) }, + // 微信票据 + async weChatTickets(data) { + // 确认蓝牙状态正常 + if ( + this.bluetoothStatus !== 0 && + this.currentLockInfo.transportType !== transportType.TRANSPORT_TENCENT_YUN + ) { + console.log('写入未执行', this.bluetoothStatus) + this.getBluetoothStatus() + return { + code: -1 + } + } + + // 确认设备连接正常 + if ( + !this.currentLockInfo.connected && + this.currentLockInfo.transportType !== transportType.TRANSPORT_TENCENT_YUN + ) { + const searchResult = await this.searchAndConnectDevice() + if (searchResult.code !== 0) { + return searchResult + } + this.updateCurrentLockInfo({ + ...this.currentLockInfo, + deviceId: searchResult.data.deviceId + }) + console.log('设备ID:', this.currentLockInfo.deviceId) + const result = await this.connectBluetoothDevice() + console.log('连接结果', result) + if (!result) { + return { + code: -1 + } + } + } + + // 检查是否已添加为用户 + const checkResult = await this.checkLockUser() + if (!checkResult) { + return { + code: -1 + } + } + + const { keyId, uid, openId, snTicket } = data + const length = 2 + 1 + 1 + 40 + 20 + 4 + 2 + openId.length + 2 + snTicket.length + 1 + 16 + const headArray = this.createPackageHeader(3, length) + const contentArray = new Uint8Array(length) + + contentArray[0] = cmdIds.expandCmd / 256 + contentArray[1] = cmdIds.expandCmd % 256 + + contentArray[2] = subCmdIds.weChatTickets + + contentArray[3] = length - 3 + + for (let i = 0; i < keyId.length; i++) { + contentArray[i + 4] = keyId.charCodeAt(i) + } + for (let i = 0; i < uid.length; i++) { + contentArray[i + 44] = uid.charCodeAt(i) + } + + contentArray.set(this.currentLockInfo.token || new Uint8Array([0, 0, 0, 0]), 64) + + contentArray[68] = openId.length / 256 + contentArray[69] = openId.length % 256 + + for (let i = 0; i < openId.length; i++) { + contentArray[i + 70] = openId.charCodeAt(i) + } + + contentArray[70 + openId.length] = snTicket.length / 256 + contentArray[71 + openId.length] = snTicket.length % 256 + + for (let i = 0; i < snTicket.length; i++) { + contentArray[i + 72 + openId.length] = snTicket.charCodeAt(i) + } + + contentArray[72 + openId.length + snTicket.length] = 16 + + const md5Array = this.md5Encrypte( + keyId + uid, + this.currentLockInfo.token || new Uint8Array([0, 0, 0, 0]), + this.currentLockInfo.signKey + ) + + contentArray.set(md5Array, 73 + openId.length + snTicket.length) + + const cebArray = sm4.encrypt(contentArray, this.currentLockInfo.commKey, { + mode: 'ecb', + output: 'array' + }) + + const packageArray = this.createPackageEnd(headArray, cebArray) + + this.transportMessage(packageArray) + + return this.getResult(this.weChatTickets, data) + }, parseTimeToList(timeString) { let timeList = [0, 0, 0, 0]