Files
shop-platform/src/addon/huaweipay/tests/HuaweiPayClientTest.php
2025-12-02 15:36:42 +08:00

295 lines
8.6 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 addon\huaweipay\tests;
use addon\huaweipay\data\sdk\HuaweiPayClient;
use think\facade\Log;
class HuaweiPayClientTest
{
/**
* 测试配置
* @var array
*/
protected $testConfig = [
'app_id' => 'test_app_id',
'merc_no' => 'test_merc_no',
'private_key' => 'tests/mock/cert/merchant_private_key.pem',
'huawei_public_key' => 'tests/mock/cert/huawei_public_key.pem',
'sandbox' => true
];
/**
* 运行所有测试
*/
public function runTests()
{
echo "开始测试华为支付客户端...\n";
try {
$this->testConstructSuccess();
$this->testConstructMissingConfig();
$this->testGenerateSign();
$this->testH5Pay();
$this->testOrderQuery();
$this->testRefund();
$this->testVerifySign();
echo "\n✅ 所有测试通过!\n";
return true;
} catch (\Exception $e) {
echo "\n❌ 测试失败:" . $e->getMessage() . "\n";
echo "错误位置:" . $e->getFile() . "" . $e->getLine() . "\n";
return false;
}
}
/**
* 测试构造函数 - 成功场景
*/
public function testConstructSuccess()
{
echo "测试构造函数成功场景...";
// 模拟证书文件
$this->createMockCertFiles();
try {
$client = new HuaweiPayClient($this->testConfig);
echo " ✅ 通过\n";
} catch (\Exception $e) {
throw new \Exception("构造函数测试失败: " . $e->getMessage());
}
}
/**
* 测试构造函数 - 缺少必要配置
*/
public function testConstructMissingConfig()
{
echo "测试构造函数缺少配置...";
// 测试缺少app_id
try {
$config = $this->testConfig;
unset($config['app_id']);
new HuaweiPayClient($config);
throw new \Exception("应该抛出缺少app_id的异常");
} catch (\Exception $e) {
if (strpos($e->getMessage(), '缺少必要配置app_id') === false) {
throw new \Exception("异常信息不正确: " . $e->getMessage());
}
}
echo " ✅ 通过\n";
}
/**
* 测试生成签名
*/
public function testGenerateSign()
{
echo "测试生成签名...";
$this->createMockCertFiles();
$client = new HuaweiPayClient($this->testConfig);
// 使用反射调用私有方法
$reflection = new \ReflectionClass($client);
$method = $reflection->getMethod('generateSign');
$method->setAccessible(true);
$params = [
'app_id' => 'test_app_id',
'merc_no' => 'test_merc_no',
'order_id' => 'test_order_001',
'amount' => 100,
'sign' => 'ignored'
];
// 测试签名不应该失败
try {
$sign = $method->invoke($client, $params);
$this->assertEquals(true, is_string($sign), "签名应该是字符串");
echo " ✅ 通过\n";
} catch (\Exception $e) {
throw new \Exception("签名生成测试失败: " . $e->getMessage());
}
}
/**
* 测试H5支付
*/
public function testH5Pay()
{
echo "测试H5支付...";
$this->createMockCertFiles();
// 模拟HTTP请求
$this->mockHttpRequest();
$client = new HuaweiPayClient($this->testConfig);
$params = [
'order_id' => 'test_order_001',
'amount' => 100,
'subject' => '测试商品',
'notify_url' => 'https://example.com/notify',
'return_url' => 'https://example.com/return'
];
// 由于无法真正发送HTTP请求这里只测试参数验证
try {
// 尝试调用实际环境可能需要模拟curl
$result = $client->h5Pay($params);
echo " ⚠️ 跳过实际HTTP请求测试\n";
} catch (\Exception $e) {
// 预期可能会有curl错误这里只检查是否因为参数问题
if (strpos($e->getMessage(), '缺少必要参数') !== false) {
throw new \Exception("H5支付参数测试失败: " . $e->getMessage());
}
echo " ⚠️ 跳过实际HTTP请求测试\n";
}
}
/**
* 测试订单查询
*/
public function testOrderQuery()
{
echo "测试订单查询...";
$this->createMockCertFiles();
$client = new HuaweiPayClient($this->testConfig);
$params = [
'order_id' => 'test_order_001'
];
try {
// 尝试调用实际环境可能需要模拟curl
$result = $client->orderQuery($params);
echo " ⚠️ 跳过实际HTTP请求测试\n";
} catch (\Exception $e) {
if (strpos($e->getMessage(), '缺少必要参数') !== false) {
throw new \Exception("订单查询参数测试失败: " . $e->getMessage());
}
echo " ⚠️ 跳过实际HTTP请求测试\n";
}
}
/**
* 测试退款
*/
public function testRefund()
{
echo "测试退款...";
$this->createMockCertFiles();
$client = new HuaweiPayClient($this->testConfig);
$params = [
'order_id' => 'test_order_001',
'refund_order_id' => 'refund_001',
'refund_amount' => 100
];
try {
// 尝试调用实际环境可能需要模拟curl
$result = $client->refund($params);
echo " ⚠️ 跳过实际HTTP请求测试\n";
} catch (\Exception $e) {
if (strpos($e->getMessage(), '缺少必要参数') !== false) {
throw new \Exception("退款参数测试失败: " . $e->getMessage());
}
echo " ⚠️ 跳过实际HTTP请求测试\n";
}
}
/**
* 测试签名验证
*/
public function testVerifySign()
{
echo "测试签名验证...";
$this->createMockCertFiles();
$client = new HuaweiPayClient($this->testConfig);
// 使用反射调用私有方法
$reflection = new \ReflectionClass($client);
$method = $reflection->getMethod('verifySign');
$method->setAccessible(true);
$params = [
'app_id' => 'test_app_id',
'merc_no' => 'test_merc_no',
'order_id' => 'test_order_001',
'amount' => 100
];
// 由于无法真正验证签名,这里只测试方法是否存在
try {
// 传入空签名,预期会失败
$verified = $method->invoke($client, $params, '');
echo " ⚠️ 跳过实际签名验证测试\n";
} catch (\Exception $e) {
echo " ⚠️ 跳过实际签名验证测试\n";
}
}
/**
* 创建模拟证书文件
*/
private function createMockCertFiles()
{
// 确保mock证书目录存在
$certDir = __DIR__ . '/mock/cert/';
if (!is_dir($certDir)) {
mkdir($certDir, 0755, true);
}
// 创建模拟证书文件
$privateKeyPath = $certDir . 'merchant_private_key.pem';
$publicKeyPath = $certDir . 'huawei_public_key.pem';
if (!file_exists($privateKeyPath)) {
file_put_contents($privateKeyPath, '-----BEGIN PRIVATE KEY-----\nMOCK_PRIVATE_KEY_CONTENT\n-----END PRIVATE KEY-----');
}
if (!file_exists($publicKeyPath)) {
file_put_contents($publicKeyPath, '-----BEGIN PUBLIC KEY-----\nMOCK_PUBLIC_KEY_CONTENT\n-----END PUBLIC KEY-----');
}
}
/**
* 模拟HTTP请求
*/
private function mockHttpRequest()
{
// 在实际测试中,可以使用更高级的模拟技术
// 这里仅提供基础框架
}
/**
* 断言相等
*/
private function assertEquals($expected, $actual, $message = '')
{
if ($expected !== $actual) {
throw new \Exception($message ?: "断言失败: 期望 {$expected},实际得到 {$actual}");
}
}
}
// 如果直接运行此文件,则执行测试
if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])) {
$test = new HuaweiPayClientTest();
$test->runTests();
}