2025-10-17 17:34:36 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 建行生活平台集成模块
|
|
|
|
|
|
*
|
|
|
|
|
|
* @author Billy
|
|
|
|
|
|
* @date 2025-01-17
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
import sheep from '@/sheep';
|
|
|
|
|
|
import ccbApi from './api';
|
|
|
|
|
|
|
|
|
|
|
|
// 建行生活配置
|
|
|
|
|
|
const config = {
|
|
|
|
|
|
// 是否开启调试
|
|
|
|
|
|
debug: true,
|
|
|
|
|
|
// API基础路径
|
|
|
|
|
|
apiBaseUrl: '/addons/shopro',
|
|
|
|
|
|
// 超时时间
|
|
|
|
|
|
timeout: 10000,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 建行生活平台对象
|
|
|
|
|
|
const CcbLifePlatform = {
|
|
|
|
|
|
// 平台标识
|
|
|
|
|
|
platform: 'ccblife',
|
|
|
|
|
|
|
|
|
|
|
|
// 平台名称
|
|
|
|
|
|
name: '建行生活',
|
|
|
|
|
|
|
|
|
|
|
|
// 是否在建行生活环境中
|
|
|
|
|
|
isInCcbApp: false,
|
|
|
|
|
|
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// JSBridge 对象(已禁用)
|
|
|
|
|
|
// bridge: null,
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// 就绪状态(已禁用)
|
|
|
|
|
|
// isReady: false,
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// 就绪回调队列(已禁用)
|
|
|
|
|
|
// readyCallbacks: [],
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 初始化
|
|
|
|
|
|
*/
|
|
|
|
|
|
init() {
|
2025-10-21 17:33:05 +08:00
|
|
|
|
console.log('[CcbLife] ========== 建行生活平台初始化 ==========');
|
|
|
|
|
|
|
2025-10-17 17:34:36 +08:00
|
|
|
|
// 检测环境
|
|
|
|
|
|
this.detectEnvironment();
|
|
|
|
|
|
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// ⚠️ JSBridge 已禁用,目前不需要
|
|
|
|
|
|
// if (this.isInCcbApp) {
|
|
|
|
|
|
// this.setupBridge();
|
|
|
|
|
|
// }
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
2025-10-21 17:33:05 +08:00
|
|
|
|
console.log('[CcbLife] ✅ 初始化完成');
|
|
|
|
|
|
console.log('[CcbLife] 是否在建行App内:', this.isInCcbApp);
|
|
|
|
|
|
console.log('[CcbLife] 平台标识:', this.platform);
|
|
|
|
|
|
console.log('[CcbLife] ===========================================');
|
2025-10-17 17:34:36 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检测运行环境
|
|
|
|
|
|
*/
|
|
|
|
|
|
detectEnvironment() {
|
2025-10-21 17:33:05 +08:00
|
|
|
|
console.log('[CcbLife] 开始检测运行环境...');
|
|
|
|
|
|
|
2025-10-17 17:34:36 +08:00
|
|
|
|
// #ifdef H5
|
|
|
|
|
|
const ua = navigator.userAgent.toLowerCase();
|
2025-10-21 17:33:05 +08:00
|
|
|
|
console.log('[CcbLife] User-Agent:', ua);
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
|
|
|
|
|
// 检查User-Agent
|
|
|
|
|
|
if (ua.indexOf('ccblife') > -1 || ua.indexOf('ccb') > -1) {
|
2025-10-21 17:33:05 +08:00
|
|
|
|
console.log('[CcbLife] ✅ 通过UA检测到建行App');
|
2025-10-17 17:34:36 +08:00
|
|
|
|
this.isInCcbApp = true;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查URL参数
|
|
|
|
|
|
const urlParams = this.getUrlParams();
|
2025-10-21 17:33:05 +08:00
|
|
|
|
console.log('[CcbLife] URL参数:', urlParams);
|
|
|
|
|
|
|
2025-10-17 17:34:36 +08:00
|
|
|
|
if (urlParams.ccbParamSJ || urlParams.from === 'ccblife') {
|
2025-10-21 17:33:05 +08:00
|
|
|
|
console.log('[CcbLife] ✅ 通过URL参数检测到建行App');
|
|
|
|
|
|
console.log('[CcbLife] ccbParamSJ:', urlParams.ccbParamSJ ? '存在' : '不存在');
|
|
|
|
|
|
console.log('[CcbLife] from:', urlParams.from);
|
2025-10-17 17:34:36 +08:00
|
|
|
|
this.isInCcbApp = true;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-21 17:33:05 +08:00
|
|
|
|
console.log('[CcbLife] ❌ 未检测到建行App环境');
|
|
|
|
|
|
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// ⚠️ 已移除 JSBridge 检查(目前不需要)
|
|
|
|
|
|
// if (window.WebViewJavascriptBridge || window.mbspay) {
|
|
|
|
|
|
// this.isInCcbApp = true;
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
2025-10-17 17:34:36 +08:00
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
|
|
|
|
// #ifdef APP-PLUS
|
|
|
|
|
|
// 在APP中也可能通过插件方式集成建行SDK
|
|
|
|
|
|
// TODO: 检测建行SDK插件
|
2025-10-21 17:33:05 +08:00
|
|
|
|
console.log('[CcbLife] App环境,检测建行SDK插件...');
|
2025-10-17 17:34:36 +08:00
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
|
|
|
|
// 小程序环境不支持建行生活
|
2025-10-21 17:33:05 +08:00
|
|
|
|
console.log('[CcbLife] 小程序环境,不支持建行生活');
|
2025-10-17 17:34:36 +08:00
|
|
|
|
this.isInCcbApp = false;
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-10-21 14:56:48 +08:00
|
|
|
|
* 设置JSBridge(已禁用 - 目前不需要)
|
2025-10-17 17:34:36 +08:00
|
|
|
|
*/
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// setupBridge() {
|
|
|
|
|
|
// // #ifdef H5
|
|
|
|
|
|
// const self = this;
|
|
|
|
|
|
// let bridgeCheckCount = 0;
|
|
|
|
|
|
// const MAX_BRIDGE_CHECK = 20;
|
|
|
|
|
|
// const BRIDGE_CHECK_INTERVAL = 500;
|
|
|
|
|
|
//
|
|
|
|
|
|
// // iOS WebViewJavascriptBridge
|
|
|
|
|
|
// if (window.WebViewJavascriptBridge) {
|
|
|
|
|
|
// self.bridge = window.WebViewJavascriptBridge;
|
|
|
|
|
|
// self.onBridgeReady();
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// // 监听iOS Bridge就绪事件
|
|
|
|
|
|
// document.addEventListener('WebViewJavascriptBridgeReady', function() {
|
|
|
|
|
|
// self.bridge = window.WebViewJavascriptBridge;
|
|
|
|
|
|
// self.onBridgeReady();
|
|
|
|
|
|
// }, false);
|
|
|
|
|
|
//
|
|
|
|
|
|
// // Android 直接通过window对象
|
|
|
|
|
|
// if (window.mbspay) {
|
|
|
|
|
|
// self.bridge = window.mbspay;
|
|
|
|
|
|
// self.onBridgeReady();
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// // 轮询检查Bridge是否已加载
|
|
|
|
|
|
// const bridgeCheckInterval = setInterval(() => {
|
|
|
|
|
|
// bridgeCheckCount++;
|
|
|
|
|
|
//
|
|
|
|
|
|
// if (window.WebViewJavascriptBridge && !self.isReady) {
|
|
|
|
|
|
// clearInterval(bridgeCheckInterval);
|
|
|
|
|
|
// self.bridge = window.WebViewJavascriptBridge;
|
|
|
|
|
|
// self.onBridgeReady();
|
|
|
|
|
|
// console.log(`[CcbLife] iOS Bridge 已就绪(检查${bridgeCheckCount}次)`);
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// if (window.mbspay && !self.isReady) {
|
|
|
|
|
|
// clearInterval(bridgeCheckInterval);
|
|
|
|
|
|
// self.bridge = window.mbspay;
|
|
|
|
|
|
// self.onBridgeReady();
|
|
|
|
|
|
// console.log(`[CcbLife] Android Bridge 已就绪(检查${bridgeCheckCount}次)`);
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// if (bridgeCheckCount >= MAX_BRIDGE_CHECK) {
|
|
|
|
|
|
// clearInterval(bridgeCheckInterval);
|
|
|
|
|
|
// console.error('[CcbLife] ⚠️ JSBridge 初始化超时');
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }, BRIDGE_CHECK_INTERVAL);
|
|
|
|
|
|
// // #endif
|
|
|
|
|
|
// },
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2025-10-21 14:56:48 +08:00
|
|
|
|
* Bridge就绪回调(已禁用)
|
2025-10-17 17:34:36 +08:00
|
|
|
|
*/
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// onBridgeReady() {
|
|
|
|
|
|
// this.isReady = true;
|
|
|
|
|
|
// console.log('[CcbLife] JSBridge 已就绪');
|
|
|
|
|
|
// this.readyCallbacks.forEach(callback => callback());
|
|
|
|
|
|
// this.readyCallbacks = [];
|
|
|
|
|
|
// },
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2025-10-21 14:56:48 +08:00
|
|
|
|
* 等待Bridge就绪(已禁用)
|
2025-10-17 17:34:36 +08:00
|
|
|
|
*/
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// ready(callback) {
|
|
|
|
|
|
// if (this.isReady) {
|
|
|
|
|
|
// callback();
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// this.readyCallbacks.push(callback);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// },
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取URL参数
|
|
|
|
|
|
*/
|
|
|
|
|
|
getUrlParams() {
|
|
|
|
|
|
const params = {};
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
|
const search = window.location.search.substring(1);
|
|
|
|
|
|
if (search) {
|
|
|
|
|
|
const pairs = search.split('&');
|
|
|
|
|
|
pairs.forEach(pair => {
|
|
|
|
|
|
const parts = pair.split('=');
|
|
|
|
|
|
if (parts.length === 2) {
|
|
|
|
|
|
params[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
return params;
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-10-21 14:56:48 +08:00
|
|
|
|
* 获取建行用户信息(已禁用 - 依赖JSBridge)
|
2025-10-17 17:34:36 +08:00
|
|
|
|
*/
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// async getUserInfo() {
|
|
|
|
|
|
// return new Promise((resolve, reject) => {
|
|
|
|
|
|
// if (!this.isInCcbApp) {
|
|
|
|
|
|
// reject({
|
|
|
|
|
|
// code: -1,
|
|
|
|
|
|
// msg: '不在建行生活App内'
|
|
|
|
|
|
// });
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// this.ready(() => {
|
|
|
|
|
|
// this.callNative('getUserInfo', {}, (result) => {
|
|
|
|
|
|
// if (result && result.userid) {
|
|
|
|
|
|
// resolve({
|
|
|
|
|
|
// code: 0,
|
|
|
|
|
|
// data: {
|
|
|
|
|
|
// ccb_user_id: result.userid,
|
|
|
|
|
|
// mobile: result.mobile || '',
|
|
|
|
|
|
// nickname: result.nickname || '',
|
|
|
|
|
|
// avatar: result.avatar || ''
|
|
|
|
|
|
// }
|
|
|
|
|
|
// });
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// reject({
|
|
|
|
|
|
// code: -1,
|
|
|
|
|
|
// msg: '获取用户信息失败'
|
|
|
|
|
|
// });
|
|
|
|
|
|
// }
|
|
|
|
|
|
// });
|
|
|
|
|
|
// });
|
|
|
|
|
|
// });
|
|
|
|
|
|
// },
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2025-10-21 14:56:48 +08:00
|
|
|
|
* 自动登录(已禁用 - 依赖JSBridge的getUserInfo)
|
|
|
|
|
|
* 目前改用App.vue中的checkCCBLogin统一处理URL参数登录
|
2025-10-20 14:09:00 +08:00
|
|
|
|
* @param {Number} retryCount - 重试次数
|
2025-10-17 17:34:36 +08:00
|
|
|
|
*/
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// async autoLogin(retryCount = 0) {
|
|
|
|
|
|
// const MAX_RETRY = 2;
|
|
|
|
|
|
// const RETRY_DELAY = 2000;
|
|
|
|
|
|
//
|
|
|
|
|
|
// try {
|
|
|
|
|
|
// const token = uni.getStorageSync('token');
|
|
|
|
|
|
// if (token) {
|
|
|
|
|
|
// console.log('[CcbLife] 用户已登录,跳过自动登录');
|
|
|
|
|
|
// try {
|
|
|
|
|
|
// await sheep.$store('user').getInfo();
|
|
|
|
|
|
// console.log('[CcbLife] Token有效');
|
|
|
|
|
|
// return { success: true, cached: true };
|
|
|
|
|
|
// } catch (e) {
|
|
|
|
|
|
// console.warn('[CcbLife] Token已失效,清除并重新登录');
|
|
|
|
|
|
// uni.removeStorageSync('token');
|
|
|
|
|
|
// uni.removeStorageSync('userInfo');
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// console.log('[CcbLife] 开始自动登录...');
|
|
|
|
|
|
//
|
|
|
|
|
|
// // 获取用户信息
|
|
|
|
|
|
// const userResult = await this.getUserInfo();
|
|
|
|
|
|
// if (userResult.code !== 0) {
|
|
|
|
|
|
// throw new Error(userResult.msg || '获取建行用户信息失败');
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// console.log('[CcbLife] 建行用户信息获取成功:', userResult.data);
|
|
|
|
|
|
//
|
|
|
|
|
|
// // 调用后端登录接口
|
|
|
|
|
|
// const loginResult = await ccbApi.autoLogin(userResult.data);
|
|
|
|
|
|
//
|
|
|
|
|
|
// if (loginResult.code === 1) {
|
|
|
|
|
|
// sheep.$store('user').setToken(loginResult.data.token);
|
|
|
|
|
|
// uni.setStorageSync('userInfo', loginResult.data.user_info || loginResult.data.userInfo);
|
|
|
|
|
|
// console.log('[CcbLife] ✅ 自动登录成功');
|
|
|
|
|
|
// uni.$emit('ccb:login:success', loginResult.data);
|
|
|
|
|
|
// uni.showToast({
|
|
|
|
|
|
// title: '欢迎回来',
|
|
|
|
|
|
// icon: 'success',
|
|
|
|
|
|
// duration: 1500
|
|
|
|
|
|
// });
|
|
|
|
|
|
// return { success: true, data: loginResult.data };
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// throw new Error(loginResult.msg || '登录接口返回失败');
|
|
|
|
|
|
// }
|
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
|
// console.error(`[CcbLife] ❌ 自动登录失败(第${retryCount + 1}次):`, error.message || error);
|
|
|
|
|
|
//
|
|
|
|
|
|
// if (retryCount < MAX_RETRY) {
|
|
|
|
|
|
// console.log(`[CcbLife] ${RETRY_DELAY / 1000}秒后进行第${retryCount + 2}次尝试...`);
|
|
|
|
|
|
// return new Promise((resolve) => {
|
|
|
|
|
|
// setTimeout(() => {
|
|
|
|
|
|
// resolve(this.autoLogin(retryCount + 1));
|
|
|
|
|
|
// }, RETRY_DELAY);
|
|
|
|
|
|
// });
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// console.error('[CcbLife] 自动登录失败,已达最大重试次数');
|
|
|
|
|
|
// uni.showModal({
|
|
|
|
|
|
// title: '登录提示',
|
|
|
|
|
|
// content: '自动登录失败,请点击登录按钮手动登录',
|
|
|
|
|
|
// showCancel: false,
|
|
|
|
|
|
// confirmText: '知道了'
|
|
|
|
|
|
// });
|
|
|
|
|
|
// return { success: false, error: error.message || '未知错误' };
|
|
|
|
|
|
// }
|
|
|
|
|
|
// },
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2025-10-21 14:56:48 +08:00
|
|
|
|
* 调起建行支付(已禁用 - 依赖JSBridge)
|
2025-10-17 17:34:36 +08:00
|
|
|
|
*/
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// async payment(options) {
|
|
|
|
|
|
// return new Promise((resolve, reject) => {
|
|
|
|
|
|
// if (!this.isInCcbApp) {
|
|
|
|
|
|
// reject({
|
|
|
|
|
|
// code: -1,
|
|
|
|
|
|
// msg: '不在建行生活App内'
|
|
|
|
|
|
// });
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// if (!options.payment_string) {
|
|
|
|
|
|
// reject({
|
|
|
|
|
|
// code: -1,
|
|
|
|
|
|
// msg: '缺少支付串参数'
|
|
|
|
|
|
// });
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// this.ready(() => {
|
|
|
|
|
|
// // #ifdef H5
|
|
|
|
|
|
// if (this.isIOS()) {
|
|
|
|
|
|
// this.paymentForIOS(options, resolve, reject);
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// this.paymentForAndroid(options, resolve, reject);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// // #endif
|
|
|
|
|
|
//
|
|
|
|
|
|
// // #ifdef APP-PLUS
|
|
|
|
|
|
// this.paymentForApp(options, resolve, reject);
|
|
|
|
|
|
// // #endif
|
|
|
|
|
|
// });
|
|
|
|
|
|
// });
|
|
|
|
|
|
// },
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2025-10-21 14:56:48 +08:00
|
|
|
|
* iOS支付(已禁用)
|
2025-10-17 17:34:36 +08:00
|
|
|
|
*/
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// paymentForIOS(options, resolve, reject) {
|
|
|
|
|
|
// // #ifdef H5
|
|
|
|
|
|
// const paymentUrl = 'comccbpay://pay?' + options.payment_string;
|
|
|
|
|
|
// window.location.href = paymentUrl;
|
|
|
|
|
|
// setTimeout(() => {
|
|
|
|
|
|
// resolve({
|
|
|
|
|
|
// code: 0,
|
|
|
|
|
|
// msg: '已调起支付,请在建行App内完成支付'
|
|
|
|
|
|
// });
|
|
|
|
|
|
// }, 1000);
|
|
|
|
|
|
// // #endif
|
|
|
|
|
|
// },
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2025-10-21 14:56:48 +08:00
|
|
|
|
* Android支付(已禁用 - 依赖JSBridge)
|
2025-10-17 17:34:36 +08:00
|
|
|
|
*/
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// paymentForAndroid(options, resolve, reject) {
|
|
|
|
|
|
// this.callNative('payment', {
|
|
|
|
|
|
// payment_string: options.payment_string
|
|
|
|
|
|
// }, (result) => {
|
|
|
|
|
|
// if (result && result.success) {
|
|
|
|
|
|
// resolve({
|
|
|
|
|
|
// code: 0,
|
|
|
|
|
|
// data: result
|
|
|
|
|
|
// });
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// reject({
|
|
|
|
|
|
// code: -1,
|
|
|
|
|
|
// msg: result ? result.error : '支付失败'
|
|
|
|
|
|
// });
|
|
|
|
|
|
// }
|
|
|
|
|
|
// });
|
|
|
|
|
|
// },
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2025-10-21 14:56:48 +08:00
|
|
|
|
* APP支付(已禁用)
|
2025-10-17 17:34:36 +08:00
|
|
|
|
*/
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// paymentForApp(options, resolve, reject) {
|
|
|
|
|
|
// // #ifdef APP-PLUS
|
|
|
|
|
|
// uni.showToast({
|
|
|
|
|
|
// title: 'APP支付暂未实现',
|
|
|
|
|
|
// icon: 'none'
|
|
|
|
|
|
// });
|
|
|
|
|
|
// reject({
|
|
|
|
|
|
// code: -1,
|
|
|
|
|
|
// msg: 'APP支付暂未实现'
|
|
|
|
|
|
// });
|
|
|
|
|
|
// // #endif
|
|
|
|
|
|
// },
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2025-10-21 14:56:48 +08:00
|
|
|
|
* 调用原生方法(已禁用 - JSBridge相关)
|
2025-10-17 17:34:36 +08:00
|
|
|
|
*/
|
2025-10-21 14:56:48 +08:00
|
|
|
|
// callNative(method, params, callback) {
|
|
|
|
|
|
// // #ifdef H5
|
|
|
|
|
|
// try {
|
|
|
|
|
|
// if (this.isIOS() && this.bridge && this.bridge.callHandler) {
|
|
|
|
|
|
// this.bridge.callHandler(method, params, callback);
|
|
|
|
|
|
// } else if (window.mbspay && window.mbspay[method]) {
|
|
|
|
|
|
// const result = window.mbspay[method](JSON.stringify(params));
|
|
|
|
|
|
// if (callback) {
|
|
|
|
|
|
// callback(typeof result === 'string' ? JSON.parse(result) : result);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// console.warn('[CcbLife] 原生方法不存在:', method);
|
|
|
|
|
|
// if (callback) {
|
|
|
|
|
|
// callback({
|
|
|
|
|
|
// success: false,
|
|
|
|
|
|
// error: '原生方法不存在'
|
|
|
|
|
|
// });
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// } catch (e) {
|
|
|
|
|
|
// console.error('[CcbLife] 调用原生方法失败:', e);
|
|
|
|
|
|
// if (callback) {
|
|
|
|
|
|
// callback({
|
|
|
|
|
|
// success: false,
|
|
|
|
|
|
// error: e.message
|
|
|
|
|
|
// });
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// // #endif
|
|
|
|
|
|
// },
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
2025-10-21 17:33:05 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 调起建行收银台
|
|
|
|
|
|
* 根据建行App服务方接入文档,使用支付串调起收银台
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} options - 支付参数
|
|
|
|
|
|
* @param {String} options.payment_string - 支付串
|
|
|
|
|
|
* @param {Number} options.order_id - 订单ID
|
|
|
|
|
|
* @param {String} options.order_sn - 订单号
|
|
|
|
|
|
* @returns {Promise<Object>} - 返回支付结果
|
|
|
|
|
|
*/
|
|
|
|
|
|
async payment(options) {
|
|
|
|
|
|
console.log('[建行收银台] ========== 调起建行收银台 ==========');
|
|
|
|
|
|
console.log('[建行收银台] 参数:', {
|
|
|
|
|
|
order_id: options.order_id,
|
|
|
|
|
|
order_sn: options.order_sn,
|
|
|
|
|
|
payment_string_length: options.payment_string?.length
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
if (!this.isInCcbApp) {
|
|
|
|
|
|
console.error('[建行收银台] ❌ 不在建行生活App内');
|
|
|
|
|
|
reject({
|
|
|
|
|
|
code: -1,
|
|
|
|
|
|
msg: '不在建行生活App内'
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!options.payment_string) {
|
|
|
|
|
|
console.error('[建行收银台] ❌ 缺少支付串参数');
|
|
|
|
|
|
reject({
|
|
|
|
|
|
code: -1,
|
|
|
|
|
|
msg: '缺少支付串参数'
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log('[建行收银台] 支付串前100字符:', options.payment_string.substring(0, 100));
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
|
const isIOS = this.isIOS();
|
2025-10-28 17:25:31 +08:00
|
|
|
|
console.log('[建行收银台] 设备:', isIOS ? 'iOS' : 'Android');
|
2025-10-21 17:33:05 +08:00
|
|
|
|
|
|
|
|
|
|
if (isIOS) {
|
2025-10-28 17:25:31 +08:00
|
|
|
|
this._callIOSCashier(options.payment_string, resolve, reject);
|
2025-10-21 17:33:05 +08:00
|
|
|
|
} else {
|
2025-10-28 17:25:31 +08:00
|
|
|
|
this._callAndroidCashier(options.payment_string, resolve, reject);
|
2025-10-21 17:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
|
|
|
|
// #ifndef H5
|
2025-10-28 17:25:31 +08:00
|
|
|
|
reject({ code: -1, msg: '仅支持H5环境' });
|
2025-10-21 17:33:05 +08:00
|
|
|
|
// #endif
|
|
|
|
|
|
} catch (error) {
|
2025-10-28 17:25:31 +08:00
|
|
|
|
console.error('[建行收银台] ❌ 调起异常:', error.message);
|
|
|
|
|
|
reject({ code: -1, msg: error.message || '调起支付失败' });
|
2025-10-21 17:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log('[建行收银台] ===========================================');
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-10-28 17:25:31 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* iOS收银台调起(内部方法)
|
|
|
|
|
|
* 使用旧版 mbspay://direct
|
|
|
|
|
|
*/
|
|
|
|
|
|
_callIOSCashier(paymentString, resolve, reject) {
|
|
|
|
|
|
console.log('[iOS收银台] 支付串长度:', paymentString.length);
|
|
|
|
|
|
|
|
|
|
|
|
// ⭐ iOS使用旧版URL Scheme(实测更稳定)
|
|
|
|
|
|
const payUrl = 'mbspay://direct?' + paymentString;
|
|
|
|
|
|
console.log('[iOS收银台] URL长度:', payUrl.length);
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 方式1: window.location.href
|
|
|
|
|
|
window.location.href = payUrl;
|
|
|
|
|
|
console.log('[iOS收银台] window.location.href已设置');
|
|
|
|
|
|
|
|
|
|
|
|
// 方式2: iframe降级(100ms后)
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
const iframe = document.createElement('iframe');
|
|
|
|
|
|
iframe.style.display = 'none';
|
|
|
|
|
|
iframe.src = payUrl;
|
|
|
|
|
|
document.body.appendChild(iframe);
|
|
|
|
|
|
setTimeout(() => document.body.removeChild(iframe), 1000);
|
|
|
|
|
|
}, 100);
|
|
|
|
|
|
|
|
|
|
|
|
// 认为调起成功
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
console.log('[iOS收银台] ✅ 已调起');
|
|
|
|
|
|
resolve({ code: 0, msg: '已调起建行支付' });
|
|
|
|
|
|
}, 500);
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('[iOS收银台] ❌ 调起失败:', error.message);
|
|
|
|
|
|
reject({ code: -1, msg: error.message });
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Android收银台调起(内部方法)
|
|
|
|
|
|
*/
|
|
|
|
|
|
_callAndroidCashier(paymentString, resolve, reject) {
|
|
|
|
|
|
console.log('[Android收银台] 支付串长度:', paymentString.length);
|
|
|
|
|
|
|
|
|
|
|
|
// 方式1: 新版 CCBAndroid.callCashier
|
|
|
|
|
|
if (window.CCBAndroid?.callCashier) {
|
|
|
|
|
|
console.log('[Android收银台] 使用 CCBAndroid.callCashier');
|
|
|
|
|
|
window.CCBAndroid.callCashier(paymentString);
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
console.log('[Android收银台] ✅ 已调起');
|
|
|
|
|
|
resolve({ code: 0, msg: '已调起建行支付' });
|
|
|
|
|
|
}, 500);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 方式2: 旧版 mbspay.directpay
|
|
|
|
|
|
if (window.mbspay?.directpay) {
|
|
|
|
|
|
console.log('[Android收银台] 使用 mbspay.directpay(旧版)');
|
|
|
|
|
|
window.mbspay.directpay(paymentString);
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
console.log('[Android收银台] ✅ 已调起');
|
|
|
|
|
|
resolve({ code: 0, msg: '已调起建行支付' });
|
|
|
|
|
|
}, 500);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 无可用方法
|
|
|
|
|
|
console.error('[Android收银台] ❌ 无可用调起方法');
|
|
|
|
|
|
console.error('[Android收银台] window对象:', Object.keys(window).filter(k =>
|
|
|
|
|
|
k.toLowerCase().includes('ccb') || k.toLowerCase().includes('pay')
|
|
|
|
|
|
));
|
|
|
|
|
|
reject({ code: -1, msg: '建行支付环境异常,请更新App' });
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-10-17 17:34:36 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 判断是否iOS
|
|
|
|
|
|
*/
|
|
|
|
|
|
isIOS() {
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
|
return /iPhone|iPad|iPod/i.test(navigator.userAgent);
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
// #ifndef H5
|
|
|
|
|
|
return uni.getSystemInfoSync().platform === 'ios';
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 处理URL跳转登录
|
2025-10-20 14:09:00 +08:00
|
|
|
|
* 建行App通过URL携带加密参数跳转到H5时调用
|
2025-10-20 22:41:56 +08:00
|
|
|
|
*
|
|
|
|
|
|
* ⚠️ 注意:此方法已禁用,改用App.vue中的checkCCBLogin统一处理
|
|
|
|
|
|
* 原因:App.vue实现了更完善的逻辑(ccbParamSJ比较、用户切换、防重复调用)
|
2025-10-17 17:34:36 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async handleUrlLogin() {
|
2025-10-20 22:41:56 +08:00
|
|
|
|
console.log('[CcbLife] handleUrlLogin被调用,但已禁用(改用App.vue统一处理)');
|
|
|
|
|
|
return; // 🔒 禁用此方法,避免与App.vue重复调用
|
|
|
|
|
|
|
2025-10-17 17:34:36 +08:00
|
|
|
|
const params = this.getUrlParams();
|
|
|
|
|
|
|
2025-10-20 14:09:00 +08:00
|
|
|
|
// 如果有ccbParamSJ参数,说明是从建行跳转过来的
|
2025-10-17 17:34:36 +08:00
|
|
|
|
if (params.ccbParamSJ) {
|
2025-10-20 14:09:00 +08:00
|
|
|
|
console.log('[CcbLife] 检测到URL登录参数,开始处理...');
|
|
|
|
|
|
|
|
|
|
|
|
// 显示加载提示
|
|
|
|
|
|
uni.showLoading({
|
|
|
|
|
|
title: '登录中...',
|
|
|
|
|
|
mask: true
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-10-17 17:34:36 +08:00
|
|
|
|
try {
|
2025-10-20 14:09:00 +08:00
|
|
|
|
// 检查是否已经登录过(避免重复登录)
|
|
|
|
|
|
const existingToken = uni.getStorageSync('token');
|
|
|
|
|
|
const loginTimestamp = uni.getStorageSync('ccb_url_login_timestamp');
|
|
|
|
|
|
const now = Date.now();
|
|
|
|
|
|
|
|
|
|
|
|
// 如果5分钟内已经用同样的参数登录过,跳过
|
|
|
|
|
|
if (existingToken && loginTimestamp && (now - loginTimestamp) < 5 * 60 * 1000) {
|
|
|
|
|
|
console.log('[CcbLife] 检测到最近已登录,跳过URL登录');
|
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
|
|
|
|
|
|
|
// 直接跳转
|
|
|
|
|
|
const redirectUrl = params.redirect_url || '/pages/index/index';
|
|
|
|
|
|
uni.reLaunch({ url: redirectUrl });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-17 17:34:36 +08:00
|
|
|
|
// 调用后端解密并登录
|
|
|
|
|
|
const result = await ccbApi.login(params);
|
|
|
|
|
|
|
2025-10-20 14:09:00 +08:00
|
|
|
|
uni.hideLoading();
|
|
|
|
|
|
|
2025-10-17 17:34:36 +08:00
|
|
|
|
if (result.code === 1) {
|
2025-10-20 14:09:00 +08:00
|
|
|
|
// 🔑 使用setToken方法更新登录状态(关键!)
|
|
|
|
|
|
sheep.$store('user').setToken(result.data.token);
|
|
|
|
|
|
|
|
|
|
|
|
// 保存用户信息和登录时间戳
|
2025-10-17 17:34:36 +08:00
|
|
|
|
uni.setStorageSync('userInfo', result.data.user_info);
|
2025-10-20 14:09:00 +08:00
|
|
|
|
uni.setStorageSync('ccb_url_login_timestamp', Date.now());
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
2025-10-20 14:09:00 +08:00
|
|
|
|
console.log('[CcbLife] ✅ URL登录成功');
|
2025-10-17 17:34:36 +08:00
|
|
|
|
|
2025-10-20 14:09:00 +08:00
|
|
|
|
// 触发登录成功事件
|
|
|
|
|
|
uni.$emit('ccb:login:success', result.data);
|
|
|
|
|
|
|
|
|
|
|
|
// 显示欢迎提示
|
2025-10-17 17:34:36 +08:00
|
|
|
|
uni.showToast({
|
2025-10-20 14:09:00 +08:00
|
|
|
|
title: `欢迎${result.data.user_info?.nickname || ''}`,
|
|
|
|
|
|
icon: 'success',
|
|
|
|
|
|
duration: 1500
|
2025-10-17 17:34:36 +08:00
|
|
|
|
});
|
2025-10-20 14:09:00 +08:00
|
|
|
|
|
|
|
|
|
|
// 延迟跳转,让用户看到提示
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
const redirectUrl = result.data.redirect_url || '/pages/index/index';
|
|
|
|
|
|
uni.reLaunch({
|
|
|
|
|
|
url: redirectUrl
|
|
|
|
|
|
});
|
|
|
|
|
|
}, 1500);
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new Error(result.msg || '登录失败');
|
2025-10-17 17:34:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2025-10-20 14:09:00 +08:00
|
|
|
|
console.error('[CcbLife] ❌ URL登录失败:', error);
|
|
|
|
|
|
|
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
|
|
|
|
|
|
|
// 显示详细错误
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: 'URL登录失败',
|
|
|
|
|
|
content: error.message || error.msg || '参数解密失败,请重新进入',
|
|
|
|
|
|
showCancel: true,
|
|
|
|
|
|
cancelText: '返回',
|
|
|
|
|
|
confirmText: '重试',
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
if (res.confirm) {
|
|
|
|
|
|
// 重试
|
|
|
|
|
|
this.handleUrlLogin();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 返回建行或首页
|
|
|
|
|
|
uni.reLaunch({
|
|
|
|
|
|
url: '/pages/index/index'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-17 17:34:36 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 导出平台对象
|
|
|
|
|
|
export default CcbLifePlatform;
|