testApp = TransferApp::create([ 'keyname' => 'test_app', 'title' => '测试应用', 'description' => '用于API测试的应用', 'out_id' => 1001, 'currency_id' => 1, 'fund_id' => 1, 'exchange_rate' => 1.0000, 'is_enabled' => true, ]); // 创建OpenAPI应用(如果存在OpenAPI模块) if (class_exists(OpenApiApp::class)) { $this->apiApp = OpenApiApp::create([ 'name' => 'Test API App', 'app_id' => 'test_app_001', 'app_secret' => 'test_secret_123', 'scopes' => ['TRANSFER_IN', 'TRANSFER_OUT', 'TRANSFER_QUERY'], 'is_enabled' => true, ]); } } /** * 测试转入API */ public function testTransferInApi(): void { $data = [ 'business_id' => 'api_test_in_' . time(), 'user_id' => 1001, 'amount' => '100.50', 'out_user_id' => 'ext_user_123', 'remark' => 'API测试转入', 'callback_data' => ['test' => 'data'], ]; $response = $this->postJson('/api/transfer/in', $data, $this->getApiHeaders()); $response->assertStatus(200) ->assertJsonStructure([ 'code', 'message', 'data' => [ 'order_id', 'business_id', 'amount', 'internal_amount', 'exchange_rate', 'status', 'status_text', 'created_at' ] ]); // 验证数据库中的记录 $this->assertDatabaseHas('kku_transfer_orders', [ 'out_order_id' => $data['business_id'], 'user_id' => $data['user_id'], 'type' => TransferType::IN->value, 'status' => TransferStatus::CREATED->value, ]); } /** * 测试转出API */ public function testTransferOutApi(): void { $data = [ 'business_id' => 'api_test_out_' . time(), 'user_id' => 1001, 'amount' => '50.25', 'out_user_id' => 'ext_user_456', 'remark' => 'API测试转出', ]; $response = $this->postJson('/api/transfer/out', $data, $this->getApiHeaders()); $response->assertStatus(200) ->assertJsonStructure([ 'code', 'message', 'data' => [ 'order_id', 'business_id', 'amount', 'out_amount', 'exchange_rate', 'status', 'status_text', 'created_at' ] ]); // 验证数据库中的记录 $this->assertDatabaseHas('kku_transfer_orders', [ 'out_order_id' => $data['business_id'], 'user_id' => $data['user_id'], 'type' => TransferType::OUT->value, ]); } /** * 测试查询API - 通过业务ID查询 */ public function testTransferQueryByBusinessId(): void { // 先创建一个订单 $order = TransferOrder::create([ 'transfer_app_id' => $this->testApp->id, 'out_id' => $this->testApp->out_id, 'out_order_id' => 'query_test_' . time(), 'user_id' => 1001, 'currency_id' => 1, 'fund_id' => 1, 'type' => TransferType::IN, 'status' => TransferStatus::COMPLETED, 'out_amount' => 100, 'amount' => 100, 'exchange_rate' => 1.0000, ]); $response = $this->getJson('/api/transfer/order?business_id=' . $order->out_order_id, $this->getApiHeaders()); $response->assertStatus(200) ->assertJsonStructure([ 'code', 'message', 'data' => [ 'order_id', 'business_id', 'type', 'type_text', 'status', 'status_text', 'amount', 'out_amount', 'exchange_rate', 'user_id', 'created_at', ] ]); $responseData = $response->json('data'); $this->assertEquals($order->id, $responseData['order_id']); $this->assertEquals($order->out_order_id, $responseData['business_id']); } /** * 测试查询API - 通过订单ID查询 */ public function testTransferQueryByOrderId(): void { // 先创建一个订单 $order = TransferOrder::create([ 'transfer_app_id' => $this->testApp->id, 'out_id' => $this->testApp->out_id, 'out_order_id' => 'query_order_test_' . time(), 'user_id' => 1001, 'currency_id' => 1, 'fund_id' => 1, 'type' => TransferType::OUT, 'status' => TransferStatus::PROCESSING, 'out_amount' => 200, 'amount' => 200, 'exchange_rate' => 1.0000, ]); $response = $this->getJson('/api/transfer/order?order_id=' . $order->id, $this->getApiHeaders()); $response->assertStatus(200); $responseData = $response->json('data'); $this->assertEquals($order->id, $responseData['order_id']); $this->assertEquals(TransferType::OUT->value, $responseData['type']); $this->assertEquals(TransferStatus::PROCESSING->value, $responseData['status']); } /** * 测试API验证 - 缺少必填字段 */ public function testApiValidationMissingFields(): void { $data = [ // 缺少 business_id 'user_id' => 1001, 'amount' => '100.00', ]; $response = $this->postJson('/api/transfer/in', $data, $this->getApiHeaders()); $response->assertStatus(422) ->assertJsonStructure([ 'code', 'message', 'data' => [ 'business_id' ] ]); } /** * 测试API验证 - 无效金额 */ public function testApiValidationInvalidAmount(): void { $data = [ 'business_id' => 'invalid_amount_test_' . time(), 'user_id' => 1001, 'amount' => 'invalid_amount', ]; $response = $this->postJson('/api/transfer/in', $data, $this->getApiHeaders()); $response->assertStatus(422) ->assertJsonStructure([ 'code', 'message', 'data' => [ 'amount' ] ]); } /** * 测试API权限验证 */ public function testApiPermissionValidation(): void { $data = [ 'business_id' => 'permission_test_' . time(), 'user_id' => 1001, 'amount' => '100.00', ]; // 不提供认证头 $response = $this->postJson('/api/transfer/in', $data); $response->assertStatus(401); } /** * 测试重复业务ID */ public function testDuplicateBusinessId(): void { $businessId = 'duplicate_api_test_' . time(); $data = [ 'business_id' => $businessId, 'user_id' => 1001, 'amount' => '100.00', ]; // 第一次请求应该成功 $response1 = $this->postJson('/api/transfer/in', $data, $this->getApiHeaders()); $response1->assertStatus(200); // 第二次请求应该失败 $response2 = $this->postJson('/api/transfer/in', $data, $this->getApiHeaders()); $response2->assertStatus(400) ->assertJsonPath('message', '业务订单ID已存在'); } /** * 测试查询不存在的订单 */ public function testQueryNonExistentOrder(): void { $response = $this->getJson('/api/transfer/order?business_id=non_existent_order', $this->getApiHeaders()); $response->assertStatus(404) ->assertJsonPath('message', '订单不存在'); } /** * 测试汇率转换 */ public function testExchangeRateInApi(): void { // 设置汇率为2.0 $this->testApp->update(['exchange_rate' => 2.0000]); $data = [ 'business_id' => 'rate_test_' . time(), 'user_id' => 1001, 'amount' => '100.00', ]; $response = $this->postJson('/api/transfer/out', $data, $this->getApiHeaders()); $response->assertStatus(200); $responseData = $response->json('data'); $this->assertEquals('100.00', $responseData['amount']); // 内部金额 $this->assertEquals('200.00', $responseData['out_amount']); // 外部金额 $this->assertEquals('2.0000', $responseData['exchange_rate']); } /** * 获取API请求头 */ protected function getApiHeaders(): array { if (!isset($this->apiApp)) { return ['Accept' => 'application/json']; } return [ 'Accept' => 'application/json', 'Authorization' => 'Bearer ' . $this->generateApiToken(), 'X-App-Id' => $this->apiApp->app_id, ]; } /** * 生成API令牌(简化版) */ protected function generateApiToken(): string { return 'test_token_' . time(); } /** * 清理测试环境 */ protected function tearDown(): void { parent::tearDown(); } }