419 lines
15 KiB
PHP
419 lines
15 KiB
PHP
<?php
|
||
/**
|
||
* 华为支付模型测试类
|
||
*/
|
||
|
||
// 设置错误报告
|
||
ini_set('display_errors', 1);
|
||
ini_set('display_startup_errors', 1);
|
||
error_reporting(E_ALL);
|
||
|
||
// 添加自动加载路径
|
||
$root_path = dirname(__DIR__, 3);
|
||
require_once $root_path . '/vendor/autoload.php';
|
||
|
||
// 定义常量
|
||
if (!defined('ROOT_PATH')) {
|
||
define('ROOT_PATH', $root_path . '/');
|
||
}
|
||
|
||
// 模拟app()函数,解决框架依赖问题
|
||
function app() {
|
||
return new class {
|
||
public function getRootPath() {
|
||
return dirname(__DIR__, 3) . '\\';
|
||
}
|
||
};
|
||
}
|
||
|
||
class PayModelTest
|
||
{
|
||
protected $config = [];
|
||
protected $pay_model = null;
|
||
|
||
/**
|
||
* 构造函数
|
||
*/
|
||
public function __construct()
|
||
{
|
||
// 加载测试配置
|
||
$this->config = $this->parseYamlFile(__DIR__ . '/mock/data.yml');
|
||
echo "配置加载完成\n";
|
||
// print_r($this->config);
|
||
}
|
||
|
||
/**
|
||
* 解析YAML文件
|
||
* @param string $file_path YAML文件路径
|
||
* @return array
|
||
*/
|
||
protected function parseYamlFile($file_path)
|
||
{
|
||
if (!file_exists($file_path)) {
|
||
throw new Exception("YAML文件不存在: {$file_path}");
|
||
}
|
||
|
||
$yaml_content = file_get_contents($file_path);
|
||
if ($yaml_content === false) {
|
||
throw new Exception("读取YAML文件失败: {$file_path}");
|
||
}
|
||
|
||
// 使用正则替换YAML中的\n为实际换行符
|
||
$yaml_content = preg_replace_callback('/\\\\n/', function($matches) {
|
||
return "\n";
|
||
}, $yaml_content);
|
||
|
||
// 简单的YAML解析(仅支持当前测试文件的格式)
|
||
$config = [];
|
||
$lines = explode("\n", $yaml_content);
|
||
$current_key = '';
|
||
$in_block = false;
|
||
$block_content = '';
|
||
|
||
foreach ($lines as $line) {
|
||
$line = trim($line);
|
||
if (empty($line) || strpos($line, '#') === 0) {
|
||
continue;
|
||
}
|
||
|
||
if ($in_block) {
|
||
if (strpos($line, '---') === 0) {
|
||
continue;
|
||
}
|
||
if (preg_match('/^\w+:/', $line)) {
|
||
$config[$current_key] = $block_content;
|
||
$in_block = false;
|
||
$block_content = '';
|
||
} else {
|
||
$block_content .= $line . "\n";
|
||
continue;
|
||
}
|
||
}
|
||
|
||
if (strpos($line, ':') !== false) {
|
||
list($key, $value) = explode(':', $line, 2);
|
||
$key = trim($key);
|
||
$value = trim($value);
|
||
|
||
if (strpos($value, '|') !== false) {
|
||
$in_block = true;
|
||
$current_key = $key;
|
||
continue;
|
||
}
|
||
|
||
if (!empty($value)) {
|
||
$config[$key] = $value;
|
||
}
|
||
}
|
||
}
|
||
|
||
if ($in_block && !empty($current_key)) {
|
||
$config[$current_key] = $block_content;
|
||
}
|
||
|
||
return $config;
|
||
}
|
||
|
||
/**
|
||
* 运行测试
|
||
*/
|
||
public function runTests()
|
||
{
|
||
echo "开始运行华为支付模型测试...\n";
|
||
|
||
try {
|
||
// 1. 测试支付方法
|
||
echo "1. 测试支付方法...\n";
|
||
$this->testPayMethod();
|
||
echo "1. 支付方法测试通过\n";
|
||
|
||
// 2. 测试关闭订单方法
|
||
echo "2. 测试关闭订单方法...\n";
|
||
$this->testCloseOrderMethod();
|
||
echo "2. 关闭订单方法测试通过\n";
|
||
|
||
// 3. 测试退款方法
|
||
echo "3. 测试退款方法...\n";
|
||
$this->testRefundMethod();
|
||
echo "3. 退款方法测试通过\n";
|
||
|
||
// 4. 测试查询订单方法
|
||
echo "4. 测试查询订单方法...\n";
|
||
$this->testQueryOrderMethod();
|
||
echo "4. 查询订单方法测试通过\n";
|
||
|
||
// 5. 测试回调验证方法
|
||
echo "5. 测试回调验证方法...\n";
|
||
$this->testCallbackVerification();
|
||
echo "5. 回调验证方法测试通过\n";
|
||
|
||
echo "\n所有测试通过!\n";
|
||
} catch (Exception $e) {
|
||
echo "\n测试失败:" . $e->getMessage() . "\n";
|
||
echo "错误堆栈:" . $e->getTraceAsString() . "\n";
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 测试支付方法
|
||
*/
|
||
protected function testPayMethod()
|
||
{
|
||
// 创建支付模型实例
|
||
require_once dirname(__DIR__) . '/model/Pay.php';
|
||
require_once dirname(__DIR__) . '/data/sdk/utils.php';
|
||
require_once dirname(__DIR__) . '/data/sdk/HuaweiPayClient.php';
|
||
|
||
// 添加必要的配置
|
||
$site_id = '1';
|
||
$config_data = $this->config;
|
||
$config_data['site_id'] = $site_id;
|
||
// 使用文本模式的密钥,而不是证书文件
|
||
unset($config_data['private_key']);
|
||
unset($config_data['huawei_public_key']);
|
||
|
||
try {
|
||
// 创建实际的华为支付客户端实例
|
||
$project_root = dirname(__DIR__, 4); // 获取项目根目录
|
||
$huawei_pay_client = new \addon\huaweipay\data\sdk\HuaweiPayClient($config_data, $project_root);
|
||
echo " - 华为支付客户端实例创建成功\n";
|
||
|
||
// 测试H5支付
|
||
$h5_params = [
|
||
'out_trade_no' => 'TEST_H5_' . time(),
|
||
'subject' => '测试H5支付商品',
|
||
'body' => '测试H5支付商品描述',
|
||
'total_amount' => 0.01,
|
||
'client_ip' => '127.0.0.1'
|
||
];
|
||
|
||
// 调用真实的H5支付方法
|
||
$h5_result = $huawei_pay_client->h5Pay($h5_params, $config_data['returnUrl'], $config_data['notifyUrl']);
|
||
echo " - H5支付方法调用成功\n";
|
||
echo " 结果: " . json_encode($h5_result, JSON_UNESCAPED_UNICODE) . "\n";
|
||
|
||
// 测试APP支付
|
||
$app_params = [
|
||
'out_trade_no' => 'TEST_APP_' . time(),
|
||
'subject' => '测试APP支付商品',
|
||
'body' => '测试APP支付商品描述',
|
||
'total_amount' => 0.01
|
||
];
|
||
|
||
// 调用真实的APP支付方法
|
||
$app_result = $huawei_pay_client->appPay($app_params, $config_data['notifyUrl']);
|
||
echo " - APP支付方法调用成功\n";
|
||
echo " 结果: " . json_encode($app_result, JSON_UNESCAPED_UNICODE) . "\n";
|
||
|
||
} catch (Exception $e) {
|
||
echo " - 支付测试失败: " . $e->getMessage() . "\n";
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 测试关闭订单方法
|
||
*/
|
||
protected function testCloseOrderMethod()
|
||
{
|
||
require_once dirname(__DIR__) . '/data/sdk/utils.php';
|
||
require_once dirname(__DIR__) . '/data/sdk/HuaweiPayClient.php';
|
||
|
||
// 添加必要的配置
|
||
$site_id = '1';
|
||
$config_data = $this->config;
|
||
$config_data['site_id'] = $site_id;
|
||
// 使用文本模式的密钥,而不是证书文件
|
||
unset($config_data['private_key']);
|
||
unset($config_data['huawei_public_key']);
|
||
|
||
try {
|
||
// 创建实际的华为支付客户端实例
|
||
$project_root = dirname(__DIR__, 4); // 获取项目根目录
|
||
$huawei_pay_client = new \addon\huaweipay\data\sdk\HuaweiPayClient($config_data, $project_root);
|
||
echo " - 华为支付客户端实例创建成功\n";
|
||
|
||
// 测试关闭订单
|
||
$params = [
|
||
'out_trade_no' => 'TEST_CLOSE_' . time()
|
||
];
|
||
|
||
// 调用真实的关闭订单方法
|
||
$close_result = $huawei_pay_client->closeOrder($params);
|
||
echo " - 关闭订单方法调用成功\n";
|
||
echo " 结果: " . json_encode($close_result, JSON_UNESCAPED_UNICODE) . "\n";
|
||
|
||
} catch (Exception $e) {
|
||
echo " - 关闭订单测试失败: " . $e->getMessage() . "\n";
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 测试退款方法
|
||
*/
|
||
protected function testRefundMethod()
|
||
{
|
||
require_once dirname(__DIR__) . '/data/sdk/utils.php';
|
||
require_once dirname(__DIR__) . '/data/sdk/HuaweiPayClient.php';
|
||
|
||
// 添加必要的配置
|
||
$site_id = '1';
|
||
$config_data = $this->config;
|
||
$config_data['site_id'] = $site_id;
|
||
// 使用文本模式的密钥,而不是证书文件
|
||
unset($config_data['private_key']);
|
||
unset($config_data['huawei_public_key']);
|
||
|
||
try {
|
||
// 创建实际的华为支付客户端实例
|
||
$project_root = dirname(__DIR__, 4); // 获取项目根目录
|
||
$huawei_pay_client = new \addon\huaweipay\data\sdk\HuaweiPayClient($config_data, $project_root);
|
||
echo " - 华为支付客户端实例创建成功\n";
|
||
|
||
// 测试退款
|
||
$params = [
|
||
'out_trade_no' => 'TEST_REFUND_' . time(),
|
||
'out_request_no' => 'REFUND_' . time(),
|
||
'refund_amount' => 0.01,
|
||
'refund_reason' => '测试退款'
|
||
];
|
||
|
||
// 调用真实的退款方法
|
||
$refund_result = $huawei_pay_client->refund($params);
|
||
echo " - 退款方法调用成功\n";
|
||
echo " 结果: " . json_encode($refund_result, JSON_UNESCAPED_UNICODE) . "\n";
|
||
|
||
} catch (Exception $e) {
|
||
echo " - 退款测试失败: " . $e->getMessage() . "\n";
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 测试查询订单方法
|
||
*/
|
||
protected function testQueryOrderMethod()
|
||
{
|
||
require_once dirname(__DIR__) . '/data/sdk/utils.php';
|
||
require_once dirname(__DIR__) . '/data/sdk/HuaweiPayClient.php';
|
||
|
||
// 添加必要的配置
|
||
$site_id = '1';
|
||
$config_data = $this->config;
|
||
$config_data['site_id'] = $site_id;
|
||
// 使用文本模式的密钥,而不是证书文件
|
||
unset($config_data['private_key']);
|
||
unset($config_data['huawei_public_key']);
|
||
|
||
try {
|
||
// 创建实际的华为支付客户端实例
|
||
$project_root = dirname(__DIR__, 4); // 获取项目根目录
|
||
$huawei_pay_client = new \addon\huaweipay\data\sdk\HuaweiPayClient($config_data, $project_root);
|
||
echo " - 华为支付客户端实例创建成功\n";
|
||
|
||
// 测试查询订单
|
||
$params = [
|
||
'out_trade_no' => 'TEST_QUERY_' . time()
|
||
];
|
||
|
||
// 调用真实的查询订单方法
|
||
$query_result = $huawei_pay_client->queryOrder($params);
|
||
echo " - 查询订单方法调用成功\n";
|
||
echo " 结果: " . json_encode($query_result, JSON_UNESCAPED_UNICODE) . "\n";
|
||
|
||
} catch (Exception $e) {
|
||
echo " - 查询订单测试失败: " . $e->getMessage() . "\n";
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 测试回调验证方法
|
||
*/
|
||
protected function testCallbackVerification()
|
||
{
|
||
require_once dirname(__DIR__) . '/data/sdk/utils.php';
|
||
require_once dirname(__DIR__) . '/data/sdk/HuaweiPayClient.php';
|
||
|
||
// 添加必要的配置
|
||
$site_id = '1';
|
||
$config_data = $this->config;
|
||
$config_data['site_id'] = $site_id;
|
||
// 使用文本模式的密钥,而不是证书文件
|
||
unset($config_data['private_key']);
|
||
unset($config_data['huawei_public_key']);
|
||
|
||
try {
|
||
// 创建实际的华为支付客户端实例
|
||
$project_root = dirname(__DIR__, 4); // 获取项目根目录
|
||
$huawei_pay_client = new \addon\huaweipay\data\sdk\HuaweiPayClient($config_data, $project_root);
|
||
echo " - 华为支付客户端实例创建成功\n";
|
||
|
||
// 生成模拟回调参数并签名
|
||
$timestamp = date('Y-m-d H:i:s');
|
||
$callback_params = [
|
||
'out_trade_no' => 'TEST_CALLBACK_' . time(),
|
||
'trade_no' => 'HWPAY_' . time(),
|
||
'total_amount' => '0.01',
|
||
'trade_status' => 'SUCCESS',
|
||
'timestamp' => $timestamp,
|
||
'app_id' => $config_data['app_id'],
|
||
'merc_no' => $config_data['merc_no'],
|
||
'sign_type' => 'RSA2'
|
||
];
|
||
|
||
// 生成签名
|
||
$sign = '';
|
||
$signParams = $callback_params;
|
||
unset($signParams['sign']);
|
||
unset($signParams['sign_type']);
|
||
ksort($signParams);
|
||
|
||
$stringToSign = '';
|
||
foreach ($signParams as $key => $value) {
|
||
$stringToSign .= $key . '=' . $value . '&';
|
||
}
|
||
$stringToSign = rtrim($stringToSign, '&');
|
||
|
||
// 使用文本模式的私钥生成签名
|
||
$private_key_content = $config_data['private_key_text'];
|
||
|
||
// 对私钥进行格式化,确保openssl_sign能够正确处理
|
||
$cleanContent = preg_replace('/\s+/', '', $private_key_content);
|
||
$cleanContent = preg_replace('/-----BEGIN.*?-----/', '', $cleanContent);
|
||
$cleanContent = preg_replace('/-----END.*?-----/', '', $cleanContent);
|
||
$formattedKey = "-----BEGIN PRIVATE KEY-----\n";
|
||
$length = strlen($cleanContent);
|
||
for ($i = 0; $i < $length; $i += 64) {
|
||
$formattedKey .= substr($cleanContent, $i, 64) . "\n";
|
||
}
|
||
$formattedKey .= "-----END PRIVATE KEY-----";
|
||
|
||
openssl_sign($stringToSign, $sign, $formattedKey, OPENSSL_ALGO_SHA256);
|
||
$callback_params['sign'] = base64_encode($sign);
|
||
|
||
// 使用华为支付客户端验证签名
|
||
$verify_result = $huawei_pay_client->verifySign($callback_params);
|
||
|
||
if ($verify_result) {
|
||
echo " - 回调签名验证通过\n";
|
||
echo " - 回调参数:" . json_encode($callback_params, JSON_UNESCAPED_UNICODE) . "\n";
|
||
echo " - 交易状态:{$callback_params['trade_status']}\n";
|
||
} else {
|
||
throw new Exception("回调签名验证失败");
|
||
}
|
||
|
||
} catch (Exception $e) {
|
||
echo " - 回调验证测试失败: " . $e->getMessage() . "\n";
|
||
throw $e;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 运行测试
|
||
$test = new PayModelTest();
|
||
$test->runTests(); |