testApp = TransferApp::create([ 'keyname' => 'test_app', 'title' => '测试应用', 'description' => '用于单元测试的应用', 'out_id' => 1001, 'currency_id' => 1, 'fund_id' => 1, 'exchange_rate' => 1.0000, 'is_enabled' => true, ]); } /** * 测试创建转出订单 */ public function testCreateTransferOut(): void { $data = [ 'transfer_app_id' => $this->testApp->id, 'out_order_id' => 'test_out_' . time(), 'user_id' => 1001, 'amount' => '100.00', 'remark' => '测试转出', ]; $order = TransferLogic::createTransferOutFromArray($data); $this->assertInstanceOf(TransferOrder::class, $order); $this->assertEquals(TransferType::OUT, $order->type); $this->assertEquals(TransferStatus::CREATED, $order->status); $this->assertEquals('100.00', $order->amount); $this->assertEquals('100.00', $order->out_amount); $this->assertEquals(1.0000, $order->exchange_rate); } /** * 测试创建转入订单 */ public function testCreateTransferIn(): void { $data = [ 'transfer_app_id' => $this->testApp->id, 'out_order_id' => 'test_in_' . time(), 'user_id' => 1001, 'amount' => '200.00', 'remark' => '测试转入', ]; $order = TransferLogic::createTransferInFromArray($data); $this->assertInstanceOf(TransferOrder::class, $order); $this->assertEquals(TransferType::IN, $order->type); $this->assertEquals(TransferStatus::CREATED, $order->status); $this->assertEquals('200.00', $order->out_amount); $this->assertEquals('200.00', $order->amount); $this->assertEquals(1.0000, $order->exchange_rate); } /** * 测试汇率转换 */ public function testExchangeRateConversion(): void { // 设置汇率为2.0 $this->testApp->update([ 'exchange_rate' => 2.0000 ]); $data = [ 'transfer_app_id' => $this->testApp->id, 'out_order_id' => 'test_rate_' . time(), 'user_id' => 1001, 'amount' => '100.00', ]; // 测试转出(内部金额转外部金额) $outOrder = TransferLogic::createTransferOutFromArray($data); $this->assertEquals('100.00', $outOrder->amount); $this->assertEquals('200.00', $outOrder->out_amount); // 测试转入(外部金额转内部金额) $data['out_order_id'] = 'test_rate_in_' . time(); $inOrder = TransferLogic::createTransferInFromArray($data); $this->assertEquals('100.00', $inOrder->out_amount); $this->assertEquals('50.00', $inOrder->amount); } /** * 测试业务ID唯一性 */ public function testBusinessIdUniqueness(): void { $businessId = 'unique_test_' . time(); $data = [ 'transfer_app_id' => $this->testApp->id, 'out_order_id' => $businessId, 'user_id' => 1001, 'amount' => '100.00', ]; // 第一次创建应该成功 $order1 = TransferLogic::createTransferOutFromArray($data); $this->assertInstanceOf(TransferOrder::class, $order1); // 第二次创建相同业务ID应该抛出异常 $this->expectException(\Exception::class); $this->expectExceptionMessage('业务订单ID已存在'); TransferLogic::createTransferOutFromArray($data); } /** * 测试应用不存在的情况 */ public function testAppNotFound(): void { $data = [ 'transfer_app_id' => 99999, // 不存在的应用ID 'out_order_id' => 'test_not_found_' . time(), 'user_id' => 1001, 'amount' => '100.00', ]; $this->expectException(\Exception::class); $this->expectExceptionMessage('划转应用不存在'); TransferLogic::createTransferOutFromArray($data); } /** * 测试应用已禁用的情况 */ public function testAppDisabled(): void { // 禁用应用 $this->testApp->update([ 'is_enabled' => false ]); $data = [ 'transfer_app_id' => $this->testApp->id, 'out_order_id' => 'test_disabled_' . time(), 'user_id' => 1001, 'amount' => '100.00', ]; $this->expectException(\Exception::class); $this->expectExceptionMessage('划转应用已禁用'); TransferLogic::createTransferOutFromArray($data); } /** * 测试金额验证 */ public function testAmountValidation(): void { $data = [ 'transfer_app_id' => $this->testApp->id, 'out_order_id' => 'test_amount_' . time(), 'user_id' => 1001, 'amount' => '0', // 无效金额 ]; $this->expectException(\Exception::class); $this->expectExceptionMessage('金额必须大于0'); TransferLogic::createTransferOutFromArray($data); } /** * 测试内部模式处理 */ public function testInternalMode(): void { // 创建内部模式应用(所有API URL为空) $internalApp = TransferApp::create([ 'keyname' => 'internal_app', 'title' => '内部应用', 'out_id' => 1002, 'currency_id' => 1, 'fund_id' => 1, 'exchange_rate' => 1.0000, 'is_enabled' => true, // 所有API URL都为空,表示内部模式 ]); $data = [ 'transfer_app_id' => $internalApp->id, 'out_order_id' => 'test_internal_' . time(), 'user_id' => 1001, 'amount' => '100.00', ]; $order = TransferLogic::createTransferOutFromArray($data); // 内部模式应该直接完成 $this->assertEquals(TransferStatus::COMPLETED, $order->status); } /** * 测试外部模式处理 */ public function testExternalMode(): void { // 设置外部API URL $this->testApp->update([ 'order_out_create_url' => 'https://api.example.com/transfer/out', 'order_callback_url' => 'https://api.example.com/callback', ]); $data = [ 'transfer_app_id' => $this->testApp->id, 'out_order_id' => 'test_external_' . time(), 'user_id' => 1001, 'amount' => '100.00', ]; $order = TransferLogic::createTransferOutFromArray($data); // 外部模式应该是处理中状态 $this->assertEquals(TransferStatus::PROCESSING, $order->status); } /** * 测试回调数据处理 */ public function testCallbackDataHandling(): void { $callbackData = [ 'custom_field' => 'test_value', 'user_info' => [ 'name' => 'Test User' ], ]; $data = [ 'transfer_app_id' => $this->testApp->id, 'out_order_id' => 'test_callback_' . time(), 'user_id' => 1001, 'amount' => '100.00', 'callback_data' => $callbackData, ]; $order = TransferLogic::createTransferOutFromArray($data); $this->assertEquals($callbackData, $order->callback_data); } /** * 测试新的参数化API - 转出订单 */ public function testNewParameterizedCreateTransferOut(): void { // 使用新的明确参数API $order = TransferLogic::createTransferOut( transferAppId: $this->testApp->id, userId: 1001, amount: '150.75', password: 'test_password', googleCode: '123456', outUserId: 'ext_user_123', remark: '新API测试转出', callbackData: [ 'test' => 'new_api' ] ); $this->assertInstanceOf(TransferOrder::class, $order); $this->assertEquals($this->testApp->id, $order->transfer_app_id); $this->assertEquals(1001, $order->user_id); $this->assertEquals('150.75', $order->out_amount); $this->assertEquals('150.75', $order->amount); $this->assertEquals(TransferType::OUT, $order->type); $this->assertEquals('ext_user_123', $order->out_user_id); $this->assertEquals('新API测试转出', $order->remark); $this->assertEquals([ 'test' => 'new_api' ], $order->callback_data); } /** * 测试新的参数化API - 转入订单 */ public function testNewParameterizedCreateTransferIn(): void { // 使用新的明确参数API $order = TransferLogic::createTransferIn( transferAppId: $this->testApp->id, userId: 1001, out_order_id: 'NEW_API_' . time(), amount: '250.25', outUserId: 'ext_user_456', remark: '新API测试转入', callbackData: [ 'source' => 'new_api_test' ] ); $this->assertInstanceOf(TransferOrder::class, $order); $this->assertEquals($this->testApp->id, $order->transfer_app_id); $this->assertEquals(1001, $order->user_id); $this->assertEquals('250.25', $order->out_amount); $this->assertEquals('250.25', $order->amount); $this->assertEquals(TransferType::IN, $order->type); $this->assertEquals('ext_user_456', $order->out_user_id); $this->assertEquals('新API测试转入', $order->remark); $this->assertEquals([ 'source' => 'new_api_test' ], $order->callback_data); } /** * 测试新API的可选参数 */ public function testNewApiOptionalParameters(): void { // 只使用必需参数 $order = TransferLogic::createTransferOut( transferAppId: $this->testApp->id, userId: 1001, amount: '100.00', password: 'test_password' ); $this->assertInstanceOf(TransferOrder::class, $order); $this->assertNull($order->out_user_id); $this->assertNull($order->remark); $this->assertEquals([], $order->callback_data); } /** * 清理测试环境 */ protected function tearDown(): void { parent::tearDown(); } }