mirror of
https://gitee.com/liuxioabin/fengketrade.git
synced 2026-04-17 12:57:32 +08:00
修复
This commit is contained in:
parent
70b1d415de
commit
cfee7fe12f
@ -22,11 +22,7 @@ if (file_exists($envFile)) {
|
||||
|
||||
return [
|
||||
// API基础地址 (生产环境)
|
||||
'api_base_url' => 'https://yunbusiness.ccb.com/tp_service/txCtrl/server',
|
||||
|
||||
// 收银台地址 (生产环境)
|
||||
'cashier_url' => 'https://yunbusiness.ccb.com/clp_service/txCtrl',
|
||||
|
||||
'api_base_url' => 'https://yunbusiness.ccb.com/tp_service/server',
|
||||
// 交易代码映射
|
||||
'tx_codes' => [
|
||||
'order_push' => 'A3341TP01', // 订单推送
|
||||
|
||||
@ -1,527 +0,0 @@
|
||||
<?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'],
|
||||
'加密方式' => 'RSA(使用服务方私钥解密)',
|
||||
'模拟数据' => $testParams
|
||||
];
|
||||
} else {
|
||||
// 尝试解密(使用服务方私钥)
|
||||
$decryptedParams = CcbUrlDecrypt::decrypt($ccbParamSJ, $config['private_key']);
|
||||
|
||||
$result = [
|
||||
'解密结果' => $decryptedParams ? '成功' : '失败',
|
||||
'原始参数' => $ccbParamSJ,
|
||||
'解密数据' => $decryptedParams,
|
||||
'服务方编号' => $config['service_id'],
|
||||
'加密方式' => 'RSA'
|
||||
];
|
||||
}
|
||||
|
||||
$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 '✗ 格式异常';
|
||||
}
|
||||
}
|
||||
@ -222,9 +222,6 @@ class CcbPaymentService
|
||||
'updatetime' => time()
|
||||
]);
|
||||
|
||||
// 构建完整的支付URL
|
||||
$paymentUrl = $this->config['cashier_url'] . '?' . $finalPaymentString;
|
||||
|
||||
// 记录支付请求
|
||||
$this->recordPaymentRequest($orderId, [
|
||||
'payment_string' => $finalPaymentString,
|
||||
@ -242,7 +239,6 @@ class CcbPaymentService
|
||||
'data' => [
|
||||
'payment_string' => $finalPaymentString,
|
||||
'mac' => $mac,
|
||||
'payment_url' => $paymentUrl,
|
||||
'order_sn' => $order['order_sn'],
|
||||
'pay_flow_id' => $payFlowId,
|
||||
'amount' => number_format($order['pay_fee'], 2, '.', ''),
|
||||
@ -561,26 +557,6 @@ class CcbPaymentService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建支付URL
|
||||
*
|
||||
* @param array $params 支付参数
|
||||
* @param string $mac 签名
|
||||
* @return string
|
||||
*/
|
||||
private function buildPaymentUrl($params, $mac)
|
||||
{
|
||||
// 添加必要参数
|
||||
$params['MAC'] = $mac;
|
||||
$params['REMARK2'] = $this->config['service_id']; // 服务方编号
|
||||
|
||||
// 生成查询字符串
|
||||
$queryString = http_build_query($params);
|
||||
|
||||
// 返回完整URL(实际使用时通过JSBridge调用,不直接访问)
|
||||
return $this->config['cashier_url'] . '?' . $queryString;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新订单支付状态
|
||||
*
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user