2025-10-17 17:34:36 +08:00

440 lines
8.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 建行生活平台集成模块
*
* @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,
// JSBridge 对象
bridge: null,
// 就绪状态
isReady: false,
// 就绪回调队列
readyCallbacks: [],
/**
* 初始化
*/
init() {
// 检测环境
this.detectEnvironment();
// 如果在建行App内初始化JSBridge
if (this.isInCcbApp) {
this.setupBridge();
// 自动登录
this.autoLogin();
}
console.log('[CcbLife] 初始化完成, 是否在建行App内:', this.isInCcbApp);
},
/**
* 检测运行环境
*/
detectEnvironment() {
// #ifdef H5
const ua = navigator.userAgent.toLowerCase();
// 检查User-Agent
if (ua.indexOf('ccblife') > -1 || ua.indexOf('ccb') > -1) {
this.isInCcbApp = true;
return;
}
// 检查URL参数
const urlParams = this.getUrlParams();
if (urlParams.ccbParamSJ || urlParams.from === 'ccblife') {
this.isInCcbApp = true;
return;
}
// 检查JSBridge
if (window.WebViewJavascriptBridge || window.mbspay) {
this.isInCcbApp = true;
return;
}
// #endif
// #ifdef APP-PLUS
// 在APP中也可能通过插件方式集成建行SDK
// TODO: 检测建行SDK插件
// #endif
// #ifdef MP-WEIXIN
// 小程序环境不支持建行生活
this.isInCcbApp = false;
// #endif
},
/**
* 设置JSBridge
*/
setupBridge() {
// #ifdef H5
const self = this;
// iOS WebViewJavascriptBridge
if (window.WebViewJavascriptBridge) {
self.bridge = window.WebViewJavascriptBridge;
self.onBridgeReady();
} else {
document.addEventListener('WebViewJavascriptBridgeReady', function() {
self.bridge = window.WebViewJavascriptBridge;
self.onBridgeReady();
}, false);
}
// Android 直接通过window对象
if (window.mbspay && !self.bridge) {
self.bridge = window.mbspay;
self.onBridgeReady();
}
// 设置超时检查
setTimeout(() => {
if (!self.isReady) {
console.warn('[CcbLife] JSBridge 未就绪');
}
}, 3000);
// #endif
},
/**
* Bridge就绪回调
*/
onBridgeReady() {
this.isReady = true;
console.log('[CcbLife] JSBridge 已就绪');
// 执行所有等待的回调
this.readyCallbacks.forEach(callback => callback());
this.readyCallbacks = [];
},
/**
* 等待Bridge就绪
*/
ready(callback) {
if (this.isReady) {
callback();
} else {
this.readyCallbacks.push(callback);
}
},
/**
* 获取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;
},
/**
* 获取建行用户信息
*/
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: '获取用户信息失败'
});
}
});
});
});
},
/**
* 自动登录
*/
async autoLogin() {
try {
// 检查是否已登录
const token = uni.getStorageSync('token');
if (token) {
console.log('[CcbLife] 用户已登录');
return;
}
// 获取用户信息
const userResult = await this.getUserInfo();
if (userResult.code !== 0) {
throw new Error(userResult.msg);
}
// 调用后端登录接口
const loginResult = await ccbApi.autoLogin(userResult.data);
if (loginResult.code === 1) {
// 保存Token和用户信息
uni.setStorageSync('token', loginResult.data.token);
uni.setStorageSync('userInfo', loginResult.data.userInfo);
// 更新Shopro用户状态
sheep.$store('user').getInfo();
console.log('[CcbLife] 自动登录成功');
// 触发登录成功事件
uni.$emit('ccb:login:success', loginResult.data);
} else {
throw new Error(loginResult.msg);
}
} catch (error) {
console.error('[CcbLife] 自动登录失败:', error);
}
},
/**
* 调起建行支付
*/
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
// 区分iOS和Android
if (this.isIOS()) {
// iOS使用URL Scheme
this.paymentForIOS(options, resolve, reject);
} else {
// Android使用JSBridge
this.paymentForAndroid(options, resolve, reject);
}
// #endif
// #ifdef APP-PLUS
// APP中调用原生插件
this.paymentForApp(options, resolve, reject);
// #endif
});
});
},
/**
* iOS支付
*/
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
},
/**
* Android支付
*/
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 : '支付失败'
});
}
});
},
/**
* APP支付
*/
paymentForApp(options, resolve, reject) {
// #ifdef APP-PLUS
// TODO: 调用建行SDK插件
uni.showToast({
title: 'APP支付暂未实现',
icon: 'none'
});
reject({
code: -1,
msg: 'APP支付暂未实现'
});
// #endif
},
/**
* 调用原生方法
*/
callNative(method, params, callback) {
// #ifdef H5
try {
if (this.isIOS() && this.bridge && this.bridge.callHandler) {
// iOS WebViewJavascriptBridge
this.bridge.callHandler(method, params, callback);
} else if (window.mbspay && window.mbspay[method]) {
// Android直接调用
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
},
/**
* 判断是否iOS
*/
isIOS() {
// #ifdef H5
return /iPhone|iPad|iPod/i.test(navigator.userAgent);
// #endif
// #ifndef H5
return uni.getSystemInfoSync().platform === 'ios';
// #endif
},
/**
* 处理URL跳转登录
*/
async handleUrlLogin() {
const params = this.getUrlParams();
// 如果有ccbParamSJ参数说明是从建行跳转过来的
if (params.ccbParamSJ) {
try {
// 调用后端解密并登录
const result = await ccbApi.login(params);
if (result.code === 1) {
// 保存Token和用户信息
uni.setStorageSync('token', result.data.token);
uni.setStorageSync('userInfo', result.data.user_info);
// 更新用户状态
sheep.$store('user').getInfo();
// 跳转到指定页面
const redirectUrl = result.data.redirect_url || '/pages/index/index';
uni.reLaunch({
url: redirectUrl
});
} else {
uni.showToast({
title: result.msg || '登录失败',
icon: 'none'
});
}
} catch (error) {
console.error('[CcbLife] URL登录失败:', error);
uni.showToast({
title: '登录失败',
icon: 'none'
});
}
}
}
};
// 导出平台对象
export default CcbLifePlatform;