2025-10-18 15:47:25 +08:00

526 lines
17 KiB
PHP
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.

<?php
namespace addons\shopro\controller;
use addons\shopro\controller\Common;
use addons\shopro\library\ccblife\CcbRSA;
use addons\shopro\library\ccblife\CcbMD5;
use addons\shopro\library\ccblife\CcbUrlDecrypt;
use addons\shopro\library\ccblife\CcbHttpClient;
use addons\shopro\library\ccblife\CcbOrderService;
use addons\shopro\library\ccblife\CcbPaymentService;
use app\admin\model\shopro\order\Order as OrderModel;
use think\Db;
use think\Exception;
/**
* 建行生活测试控制器
*
* 用于测试和验证各个功能模块是否正常工作
*
* @author Billy
* @date 2025-01-17
*/
class Ccbtest extends Common
{
/**
* 不需要登录的方法
* @var array
*/
protected $noNeedLogin = ['*'];
/**
* 不需要权限的方法
* @var array
*/
protected $noNeedRight = ['*'];
/**
* 测试主页
* 展示所有可用的测试接口
*/
public function index()
{
$baseUrl = $this->request->domain() . '/addons/shopro/ccbtest';
$tests = [
'基础功能测试' => [
[
'name' => '测试RSA加密解密',
'url' => $baseUrl . '/testRsa',
'method' => 'GET',
'desc' => '测试RSA加密和解密功能是否正常'
],
[
'name' => '测试MD5签名',
'url' => $baseUrl . '/testMd5',
'method' => 'GET',
'desc' => '测试MD5签名生成功能'
],
[
'name' => '测试URL参数解密',
'url' => $baseUrl . '/testUrlDecrypt',
'method' => 'GET',
'desc' => '测试建行URL参数解密功能'
],
],
'订单功能测试' => [
[
'name' => '测试订单推送',
'url' => $baseUrl . '/testOrderPush?order_id=1',
'method' => 'GET',
'desc' => '测试推送订单到建行需要提供order_id'
],
[
'name' => '测试订单查询',
'url' => $baseUrl . '/testOrderQuery?order_sn=ORDER123',
'method' => 'GET',
'desc' => '测试查询建行订单状态需要提供order_sn'
],
[
'name' => '测试批量同步',
'url' => $baseUrl . '/testBatchSync',
'method' => 'GET',
'desc' => '测试批量同步未同步的订单'
],
],
'支付功能测试' => [
[
'name' => '测试生成支付串',
'url' => $baseUrl . '/testPaymentString?order_id=1',
'method' => 'GET',
'desc' => '测试生成建行支付串需要提供order_id'
],
[
'name' => '测试支付验证',
'url' => $baseUrl . '/testVerifyPayment?order_sn=ORDER123',
'method' => 'GET',
'desc' => '测试验证支付结果需要提供order_sn'
],
],
'用户功能测试' => [
[
'name' => '模拟用户登录',
'url' => $baseUrl . '/testUserLogin',
'method' => 'POST',
'desc' => '模拟建行用户登录流程',
'params' => [
'ccb_user_id' => 'ccb_test_user_001',
'mobile' => '13800138000'
]
],
],
'环境检查' => [
[
'name' => '检查配置',
'url' => $baseUrl . '/checkConfig',
'method' => 'GET',
'desc' => '检查建行配置是否正确'
],
[
'name' => '检查数据库',
'url' => $baseUrl . '/checkDatabase',
'method' => 'GET',
'desc' => '检查数据库表结构是否正确'
],
]
];
$this->success('建行生活接口测试', $tests);
}
/**
* 测试RSA加密解密
*/
public function testRsa()
{
try {
$config = config('ccblife');
// 测试数据
$testData = '这是一个测试字符串用于验证RSA加密解密功能是否正常工作。包含中文、English、数字123456和特殊字符!@#$%^&*()';
// 加密
$encrypted = CcbRSA::encrypt($testData, $config['public_key']);
// 解密
$decrypted = CcbRSA::decrypt($encrypted, $config['private_key']);
// 验证
$isSuccess = ($decrypted === $testData);
$result = [
'测试结果' => $isSuccess ? '成功' : '失败',
'原始数据' => $testData,
'加密后数据BASE64' => substr($encrypted, 0, 100) . '...',
'加密后长度' => strlen($encrypted),
'解密后数据' => $decrypted,
'数据一致性' => $isSuccess ? '✓ 一致' : '✗ 不一致'
];
$this->success('RSA加密解密测试完成', $result);
} catch (Exception $e) {
$this->error('RSA测试失败' . $e->getMessage());
}
}
/**
* 测试MD5签名
*/
public function testMd5()
{
try {
$config = config('ccblife');
// 测试API消息签名
$apiMessage = '{"TX_CODE":"A3341TP01","USER_ID":"test_user"}';
$apiSign = CcbMD5::signApiMessage($apiMessage, $config['private_key']);
// 测试支付串签名
$paymentResult = CcbMD5::generatePaymentSignature(
$config['merchant_id'],
$config['pos_id'],
$config['branch_id'],
'TEST_ORDER_' . time(),
'100.00',
$config['private_key'],
'01',
'530550'
);
$result = [
'API消息签名' => [
'原始消息' => $apiMessage,
'签名结果' => $apiSign,
'签名长度' => strlen($apiSign)
],
'支付串签名' => [
'支付串' => $paymentResult['payment_string'],
'MAC签名' => $paymentResult['mac'],
'参数列表' => $paymentResult['params']
]
];
$this->success('MD5签名测试完成', $result);
} catch (Exception $e) {
$this->error('MD5测试失败' . $e->getMessage());
}
}
/**
* 测试URL参数解密
*/
public function testUrlDecrypt()
{
try {
$config = config('ccblife');
// 模拟建行传递的加密参数
// 注意这里需要真实的ccbParamSJ参数才能测试
$ccbParamSJ = $this->request->get('ccbParamSJ', '');
if (empty($ccbParamSJ)) {
// 如果没有提供参数,生成一个测试用的
$testParams = [
'userid' => 'test_ccb_user_001',
'mobile' => '13800138000',
'openid' => 'test_openid_001'
];
$result = [
'提示' => '未提供ccbParamSJ参数无法进行实际解密测试',
'说明' => '请从建行App跳转时携带ccbParamSJ参数',
'服务方编号' => $config['service_id'],
'DES密钥前8位' => substr($config['service_id'], 0, 8),
'模拟数据' => $testParams
];
} else {
// 尝试解密
$decryptedParams = CcbUrlDecrypt::decrypt($ccbParamSJ, $config['service_id']);
$result = [
'解密结果' => $decryptedParams ? '成功' : '失败',
'原始参数' => $ccbParamSJ,
'解密数据' => $decryptedParams,
'服务方编号' => $config['service_id']
];
}
$this->success('URL参数解密测试', $result);
} catch (Exception $e) {
$this->error('URL解密测试失败' . $e->getMessage());
}
}
/**
* 测试订单推送
*/
public function testOrderPush()
{
try {
$orderId = $this->request->get('order_id', 1);
$orderService = new CcbOrderService();
$result = $orderService->pushOrder($orderId);
$this->success('订单推送测试完成', $result);
} catch (Exception $e) {
$this->error('订单推送失败:' . $e->getMessage());
}
}
/**
* 测试订单查询
*/
public function testOrderQuery()
{
try {
$orderSn = $this->request->get('order_sn', '');
if (empty($orderSn)) {
$this->error('请提供订单号参数 order_sn');
}
$orderService = new CcbOrderService();
$result = $orderService->queryOrder($orderSn);
$this->success('订单查询测试完成', $result);
} catch (Exception $e) {
$this->error('订单查询失败:' . $e->getMessage());
}
}
/**
* 测试批量同步
*/
public function testBatchSync()
{
try {
$orderService = new CcbOrderService();
$result = $orderService->batchSync(5); // 同步5个订单
$this->success('批量同步测试完成', $result);
} catch (Exception $e) {
$this->error('批量同步失败:' . $e->getMessage());
}
}
/**
* 测试生成支付串
*/
public function testPaymentString()
{
try {
$orderId = $this->request->get('order_id', 1);
$paymentService = new CcbPaymentService();
$result = $paymentService->generatePaymentString($orderId);
$this->success('支付串生成测试完成', $result);
} catch (Exception $e) {
$this->error('支付串生成失败:' . $e->getMessage());
}
}
/**
* 测试支付验证
*/
public function testVerifyPayment()
{
try {
$orderSn = $this->request->get('order_sn', '');
if (empty($orderSn)) {
$this->error('请提供订单号参数 order_sn');
}
$paymentService = new CcbPaymentService();
$isSuccess = $paymentService->verifyPayment($orderSn);
$result = [
'订单号' => $orderSn,
'支付状态' => $isSuccess ? '已支付' : '未支付',
'验证结果' => $isSuccess
];
$this->success('支付验证测试完成', $result);
} catch (Exception $e) {
$this->error('支付验证失败:' . $e->getMessage());
}
}
/**
* 模拟用户登录
*/
public function testUserLogin()
{
try {
$ccbUserId = $this->request->post('ccb_user_id', 'ccb_test_user_001');
$mobile = $this->request->post('mobile', '13800138000');
// 查询或创建用户
$user = Db::name('user')->where('ccb_user_id', $ccbUserId)->find();
if (!$user) {
// 创建测试用户
$userData = [
'ccb_user_id' => $ccbUserId,
'username' => 'test_' . substr(md5($ccbUserId), 0, 8),
'nickname' => '测试用户' . substr($ccbUserId, -4),
'mobile' => $mobile,
'avatar' => '/assets/img/avatar.png',
'status' => 'normal',
'salt' => \fast\Random::alnum(),
'password' => '',
'joinip' => $this->request->ip(),
'jointime' => time(),
'logintime' => time(),
'loginip' => $this->request->ip(),
'createtime' => time(),
'updatetime' => time()
];
// 设置随机密码
$userData['password'] = md5(md5(\fast\Random::alnum(32)) . $userData['salt']);
$userId = Db::name('user')->insertGetId($userData);
$user = Db::name('user')->where('id', $userId)->find();
}
// 生成Token
$this->auth->direct($user['id']);
$token = $this->auth->getToken();
$result = [
'用户ID' => $user['id'],
'建行用户ID' => $ccbUserId,
'手机号' => $mobile,
'Token' => $token,
'是否新用户' => !isset($userId) ? '否' : '是'
];
$this->success('用户登录测试成功', $result);
} catch (Exception $e) {
$this->error('用户登录测试失败:' . $e->getMessage());
}
}
/**
* 检查配置
*/
public function checkConfig()
{
try {
$config = config('ccblife');
$checks = [
'基础配置' => [
'收银台地址' => $config['cashier_url'] ?? '未配置',
'服务方编号' => $config['service_id'] ?? '未配置',
],
'商户信息' => [
'商户号' => $config['merchant_id'] ?? '未配置',
'POS号' => $config['pos_id'] ?? '未配置',
'分行号' => $config['branch_id'] ?? '未配置',
],
'密钥配置' => [
'私钥长度' => strlen($config['private_key'] ?? '') . ' 字符',
'公钥长度' => strlen($config['public_key'] ?? '') . ' 字符',
'私钥格式' => $this->validateKey($config['private_key'] ?? ''),
'公钥格式' => $this->validateKey($config['public_key'] ?? ''),
],
'交易代码' => $config['tx_codes'] ?? [],
'HTTP配置' => $config['http'] ?? [],
'安全配置' => $config['security'] ?? []
];
$this->success('配置检查完成', $checks);
} catch (Exception $e) {
$this->error('配置检查失败:' . $e->getMessage());
}
}
/**
* 检查数据库
*/
public function checkDatabase()
{
try {
$checks = [];
// 检查用户表
$userColumns = Db::query("SHOW COLUMNS FROM fa_user LIKE 'ccb_user_id'");
$checks['用户表(fa_user)'] = [
'ccb_user_id字段' => !empty($userColumns) ? '✓ 存在' : '✗ 不存在'
];
// 检查订单表
$orderColumns = Db::query("SHOW COLUMNS FROM fa_shopro_order WHERE Field IN ('ccb_user_id', 'ccb_pay_flow_id', 'ccb_sync_status', 'ccb_sync_time')");
$orderFields = array_column($orderColumns, 'Field');
$checks['订单表(fa_shopro_order)'] = [
'ccb_user_id字段' => in_array('ccb_user_id', $orderFields) ? '✓ 存在' : '✗ 不存在',
'ccb_pay_flow_id字段' => in_array('ccb_pay_flow_id', $orderFields) ? '✓ 存在' : '✗ 不存在',
'ccb_sync_status字段' => in_array('ccb_sync_status', $orderFields) ? '✓ 存在' : '✗ 不存在',
'ccb_sync_time字段' => in_array('ccb_sync_time', $orderFields) ? '✓ 存在' : '✗ 不存在',
];
// 检查支付日志表
$paymentLogExists = Db::query("SHOW TABLES LIKE 'fa_ccb_payment_log'");
$checks['支付日志表(fa_ccb_payment_log)'] = [
'表是否存在' => !empty($paymentLogExists) ? '✓ 存在' : '✗ 不存在'
];
// 检查同步日志表
$syncLogExists = Db::query("SHOW TABLES LIKE 'fa_ccb_sync_log'");
$checks['同步日志表(fa_ccb_sync_log)'] = [
'表是否存在' => !empty($syncLogExists) ? '✓ 存在' : '✗ 不存在'
];
// 统计数据
if (!empty($syncLogExists)) {
$syncStats = Db::name('ccb_sync_log')
->field('sync_status, COUNT(*) as count')
->group('sync_status')
->select();
$checks['同步统计'] = [];
foreach ($syncStats as $stat) {
$status = $stat['sync_status'] == 1 ? '成功' : '失败';
$checks['同步统计'][$status] = $stat['count'] . ' 条';
}
}
$this->success('数据库检查完成', $checks);
} catch (Exception $e) {
$this->error('数据库检查失败:' . $e->getMessage());
}
}
/**
* 验证密钥格式
*/
private function validateKey($key)
{
if (empty($key)) {
return '✗ 未配置';
}
// 检查是否为BASE64格式
if (base64_encode(base64_decode($key)) === $key) {
return '✓ BASE64格式';
}
return '✗ 格式异常';
}
}