fengketrade/public/ccblife-demo.html
2025-10-20 08:54:02 +08:00

553 lines
18 KiB
HTML
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.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>建行生活 H5 集成示例</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background: #f5f5f5;
padding: 20px;
}
.container {
max-width: 600px;
margin: 0 auto;
background: #fff;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
font-size: 24px;
margin-bottom: 20px;
color: #333;
text-align: center;
}
.info-section {
background: #f8f9fa;
border-radius: 4px;
padding: 15px;
margin-bottom: 20px;
}
.info-item {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
font-size: 14px;
}
.info-item:last-child {
margin-bottom: 0;
}
.label {
color: #666;
}
.value {
color: #333;
font-weight: 500;
}
.btn {
display: block;
width: 100%;
padding: 12px 20px;
background: #0066cc;
color: #fff;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
margin-bottom: 15px;
transition: background 0.3s;
}
.btn:hover {
background: #0052a3;
}
.btn:disabled {
background: #ccc;
cursor: not-allowed;
}
.btn-secondary {
background: #6c757d;
}
.btn-secondary:hover {
background: #545b62;
}
.btn-success {
background: #28a745;
}
.btn-success:hover {
background: #218838;
}
.result {
background: #f0f8ff;
border: 1px solid #b6d4fe;
border-radius: 4px;
padding: 15px;
margin-top: 20px;
white-space: pre-wrap;
font-family: monospace;
font-size: 12px;
max-height: 300px;
overflow-y: auto;
}
.status {
display: inline-block;
padding: 4px 8px;
border-radius: 3px;
font-size: 12px;
margin-left: 10px;
}
.status-success {
background: #d4edda;
color: #155724;
}
.status-error {
background: #f8d7da;
color: #721c24;
}
.status-warning {
background: #fff3cd;
color: #856404;
}
.loading {
display: none;
text-align: center;
padding: 20px;
}
.loading.active {
display: block;
}
.spinner {
border: 3px solid #f3f3f3;
border-top: 3px solid #0066cc;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
margin: 0 auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.divider {
height: 1px;
background: #e9ecef;
margin: 20px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>建行生活 H5 集成示例</h1>
<!-- 环境信息 -->
<div class="info-section">
<h3>环境信息</h3>
<div class="info-item">
<span class="label">当前环境:</span>
<span class="value" id="env-status">检测中...</span>
</div>
<div class="info-item">
<span class="label">设备类型:</span>
<span class="value" id="device-type">-</span>
</div>
<div class="info-item">
<span class="label">JSBridge 状态:</span>
<span class="value" id="bridge-status">未就绪</span>
</div>
<div class="info-item">
<span class="label">Bridge 对象:</span>
<span class="value" id="bridge-object">检测中...</span>
</div>
<div class="info-item">
<span class="label">登录状态:</span>
<span class="value" id="login-status">未登录</span>
</div>
<div class="info-item">
<span class="label">建行用户ID</span>
<span class="value" id="ccb-user-id">-</span>
</div>
<div class="info-item">
<span class="label">建行参数:</span>
<span class="value" id="ccb-param"></span>
</div>
</div>
<div class="divider"></div>
<!-- 功能测试 -->
<h3 style="margin-bottom: 15px;">功能测试</h3>
<button class="btn" onclick="refreshEnv()">🔄 刷新环境检测</button>
<button class="btn" onclick="decryptCcbParam()">🔓 解密建行参数</button>
<button class="btn" onclick="getUserInfo()">获取建行用户信息</button>
<button class="btn btn-secondary" onclick="doAutoLogin()">执行自动登录</button>
<button class="btn btn-success" onclick="testPayment()">测试支付功能</button>
<div class="divider"></div>
<!-- 调试功能 -->
<h3 style="margin-bottom: 15px;">调试功能</h3>
<button class="btn btn-secondary" onclick="checkUrlParams()">检查 URL 参数</button>
<button class="btn btn-secondary" onclick="showUserAgent()">显示 User-Agent</button>
<button class="btn btn-secondary" onclick="checkBridgeObjects()">检查 Bridge 对象</button>
<button class="btn btn-secondary" onclick="clearCache()">清除缓存</button>
<button class="btn btn-secondary" onclick="toggleDebug()">切换调试模式</button>
<!-- 加载状态 -->
<div class="loading" id="loading">
<div class="spinner"></div>
<p style="margin-top: 10px;">处理中...</p>
</div>
<!-- 结果显示 -->
<div class="result" id="result" style="display: none;"></div>
</div>
<!-- 引入 JSBridge -->
<script src="/assets/js/ccblife-bridge.js"></script>
<script>
// 初始化配置
window.onload = function() {
// 初始化 CcbLifeBridge
CcbLifeBridge.init({
debug: true,
apiBaseUrl: '/addons/shopro'
});
// 更新环境状态
updateEnvStatus();
// 监听登录成功事件
window.addEventListener('ccb:login:success', function(e) {
console.log('登录成功事件:', e.detail);
updateLoginStatus(e.detail);
});
// 监听 Bridge 就绪
CcbLifeBridge.ready(function() {
document.getElementById('bridge-status').innerHTML =
'<span class="status status-success">已就绪</span>';
});
};
// 更新环境状态
function updateEnvStatus() {
var isInApp = CcbLifeBridge.isInCcbApp();
var envEl = document.getElementById('env-status');
if (isInApp) {
envEl.innerHTML = '<span class="status status-success">建行生活 App 内</span>';
} else {
envEl.innerHTML = '<span class="status status-warning">普通浏览器</span>';
}
// 设备类型
var deviceType = CcbLifeBridge.isIOS() ? 'iOS' : 'Android';
document.getElementById('device-type').textContent = deviceType;
// 检查 Bridge 对象
checkBridgeObjectsStatus();
// 检查建行参数
var params = CcbLifeBridge.getUrlParams();
if (params.ccbParamSJ) {
document.getElementById('ccb-param').innerHTML =
'<span class="status status-warning">已加密(点击解密按钮)</span>';
} else {
document.getElementById('ccb-param').textContent = '无';
}
// 检查登录状态
var token = localStorage.getItem('ccb_token');
var userInfo = localStorage.getItem('ccb_user_info');
if (token && userInfo) {
try {
var user = JSON.parse(userInfo);
updateLoginStatus({ userInfo: user });
} catch(e) {
console.error('解析用户信息失败', e);
}
}
}
// 检查 Bridge 对象状态
function checkBridgeObjectsStatus() {
var bridgeObjects = [];
if (window.WebViewJavascriptBridge) {
bridgeObjects.push('WebViewJavascriptBridge');
}
if (window.mbspay) {
bridgeObjects.push('mbspay');
}
var bridgeEl = document.getElementById('bridge-object');
if (bridgeObjects.length > 0) {
bridgeEl.innerHTML = '<span class="status status-success">' +
bridgeObjects.join(', ') + '</span>';
} else {
bridgeEl.innerHTML = '<span class="status status-error">未检测到</span>';
}
}
// 刷新环境检测
function refreshEnv() {
updateEnvStatus();
// 重新检查 Bridge 就绪状态
if (CcbLifeBridge.isReady) {
document.getElementById('bridge-status').innerHTML =
'<span class="status status-success">已就绪</span>';
} else {
document.getElementById('bridge-status').innerHTML =
'<span class="status status-error">未就绪</span>';
// 等待 3 秒后重新检查
setTimeout(function() {
if (CcbLifeBridge.isReady) {
document.getElementById('bridge-status').innerHTML =
'<span class="status status-success">已就绪</span>';
}
}, 3000);
}
showResult('环境信息已刷新');
}
// 更新登录状态
function updateLoginStatus(data) {
document.getElementById('login-status').innerHTML =
'<span class="status status-success">已登录</span>';
if (data.userInfo && data.userInfo.ccb_user_id) {
document.getElementById('ccb-user-id').textContent = data.userInfo.ccb_user_id;
}
}
// 获取用户信息
function getUserInfo() {
showLoading(true);
CcbLifeBridge.getUserInfo(function(result) {
showLoading(false);
if (result.success) {
showResult('获取用户信息成功:\n' + JSON.stringify(result.data, null, 2));
} else {
showResult('获取用户信息失败:' + result.error);
}
});
}
// 执行自动登录
function doAutoLogin() {
if (!CcbLifeBridge.isInCcbApp()) {
showResult('错误:不在建行生活 App 内,无法执行自动登录');
return;
}
showLoading(true);
CcbLifeBridge.getUserInfo(function(result) {
if (result.success) {
CcbLifeBridge.doLogin(result.data);
showLoading(false);
showResult('正在登录...\n用户信息' + JSON.stringify(result.data, null, 2));
} else {
showLoading(false);
showResult('获取用户信息失败:' + result.error);
}
});
}
// 测试支付功能
function testPayment() {
// 这里需要先调用后端接口生成支付串
var orderId = prompt('请输入订单ID测试用', '1');
if (!orderId) {
return;
}
showLoading(true);
// 模拟调用后端生成支付串
fetch('/addons/shopro/ccbpayment/createPayment', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'token': localStorage.getItem('ccb_token') || ''
},
body: JSON.stringify({
order_id: orderId
})
})
.then(response => response.json())
.then(data => {
showLoading(false);
if (data.code === 1) {
// 调起支付
CcbLifeBridge.payment({
payment_string: data.data.payment_string
}, function(result) {
if (result.success) {
showResult('支付调起成功,请在建行 App 内完成支付');
} else {
showResult('支付调起失败:' + result.error);
}
});
} else {
showResult('生成支付串失败:' + data.msg);
}
})
.catch(error => {
showLoading(false);
showResult('请求失败:' + error.message);
});
}
// 解密建行参数
function decryptCcbParam() {
var params = CcbLifeBridge.getUrlParams();
if (!params.ccbParamSJ) {
showResult('错误URL 中没有 ccbParamSJ 参数');
return;
}
showLoading(true);
// 调用后端接口解密
fetch('/addons/shopro/ccblife/decryptParam', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
ccbParamSJ: params.ccbParamSJ
})
})
.then(response => response.json())
.then(data => {
showLoading(false);
if (data.code === 1) {
var decrypted = data.data;
showResult('解密成功:\n' + JSON.stringify(decrypted, null, 2));
// 更新显示
document.getElementById('ccb-param').innerHTML =
'<span class="status status-success">已解密</span>';
// 如果有用户ID显示出来
if (decrypted.userid) {
document.getElementById('ccb-user-id').textContent = decrypted.userid;
}
} else {
showResult('解密失败:' + data.msg);
}
})
.catch(error => {
showLoading(false);
showResult('请求失败:' + error.message);
});
}
// 检查 URL 参数
function checkUrlParams() {
var params = CcbLifeBridge.getUrlParams();
showResult('URL 参数:\n' + JSON.stringify(params, null, 2));
}
// 显示 User-Agent
function showUserAgent() {
var ua = navigator.userAgent;
showResult('User-Agent\n' + ua);
}
// 检查 Bridge 对象
function checkBridgeObjects() {
var info = {
WebViewJavascriptBridge: typeof window.WebViewJavascriptBridge !== 'undefined',
mbspay: typeof window.mbspay !== 'undefined',
bridgeReady: CcbLifeBridge.isReady,
isIOS: CcbLifeBridge.isIOS(),
isInCcbApp: CcbLifeBridge.isInCcbApp()
};
showResult('Bridge 对象检测:\n' + JSON.stringify(info, null, 2));
}
// 清除缓存
function clearCache() {
localStorage.removeItem('ccb_token');
localStorage.removeItem('ccb_user_info');
document.getElementById('login-status').innerHTML =
'<span class="status status-warning">未登录</span>';
document.getElementById('ccb-user-id').textContent = '-';
showResult('缓存已清除');
}
// 切换调试模式
function toggleDebug() {
CcbLifeBridge.config.debug = !CcbLifeBridge.config.debug;
showResult('调试模式:' + (CcbLifeBridge.config.debug ? '开启' : '关闭'));
}
// 显示加载状态
function showLoading(show) {
var loading = document.getElementById('loading');
if (show) {
loading.classList.add('active');
} else {
loading.classList.remove('active');
}
}
// 显示结果
function showResult(message) {
var resultEl = document.getElementById('result');
resultEl.style.display = 'block';
resultEl.textContent = message;
}
</script>
</body>
</html>