|
|
@@ -0,0 +1,73 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace Tests\Integration;
|
|
|
+
|
|
|
+use App\Console\Commands\PaymentPayTimeout;
|
|
|
+use App\Models\PaymentOrder;
|
|
|
+use App\Services\PaymentOrderService;
|
|
|
+use Illuminate\Config\Repository;
|
|
|
+use Illuminate\Database\Capsule\Manager;
|
|
|
+use Illuminate\Database\Schema\Blueprint;
|
|
|
+use Illuminate\Foundation\Application;
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
+use Illuminate\Support\Facades\Facade;
|
|
|
+use PHPUnit\Framework\TestCase;
|
|
|
+
|
|
|
+/** 在线充值超时:定时任务把处理中超过30分钟的订单标记为7超时,迟到的回调仍会处理。 */
|
|
|
+class PaymentPayTimeoutTest extends TestCase
|
|
|
+{
|
|
|
+ protected function setUp(): void
|
|
|
+ {
|
|
|
+ parent::setUp();
|
|
|
+ Facade::clearResolvedInstances();
|
|
|
+ $app = new Application(dirname(__DIR__, 2));
|
|
|
+ $app->instance('config', new Repository(['app' => ['timezone' => 'Asia/Shanghai'], 'admin_realtime' => ['enabled' => false]]));
|
|
|
+ Facade::setFacadeApplication($app);
|
|
|
+ $db = new Manager($app);
|
|
|
+ $db->addConnection(['driver' => 'sqlite', 'database' => ':memory:', 'prefix' => 'bot_']);
|
|
|
+ $db->setAsGlobal();
|
|
|
+ $db->bootEloquent();
|
|
|
+ $app->instance('db', $db->getDatabaseManager());
|
|
|
+ $db->schema()->create('payment_orders', function (Blueprint $t) {
|
|
|
+ $t->id(); $t->string('member_id'); $t->integer('type'); $t->integer('status'); $t->string('state')->nullable();
|
|
|
+ $t->text('callback_data')->nullable(); $t->decimal('amount', 24, 10); $t->timestamps();
|
|
|
+ });
|
|
|
+ $old = date('Y-m-d H:i:s', strtotime('-2 hours'));
|
|
|
+ $fresh = date('Y-m-d H:i:s', strtotime('-5 minutes'));
|
|
|
+ foreach ([
|
|
|
+ [1, 1, $old], // 1 → 超时
|
|
|
+ [1, 1, $fresh], // 2 未到时限,仍处理中
|
|
|
+ [1, 2, $old], // 3 已成功不动
|
|
|
+ [3, 1, $old], // 4 人工充值不受影响
|
|
|
+ ] as [$type, $status, $at]) {
|
|
|
+ DB::table('payment_orders')->insert(['member_id' => 'm1', 'type' => $type, 'status' => $status,
|
|
|
+ 'amount' => 10, 'created_at' => $at, 'updated_at' => $at]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function tearDown(): void
|
|
|
+ {
|
|
|
+ DB::disconnect();
|
|
|
+ Facade::clearResolvedInstances();
|
|
|
+ parent::tearDown();
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_command_marks_only_overdue_online_pay_orders_as_timeout(): void
|
|
|
+ {
|
|
|
+ (new PaymentPayTimeout())->handle();
|
|
|
+
|
|
|
+ $this->assertSame([1 => 7, 2 => 1, 3 => 2, 4 => 1],
|
|
|
+ DB::table('payment_orders')->orderBy('id')->pluck('status', 'id')->map(fn($s) => (int)$s)->all());
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_late_callback_is_still_applied_to_timeout_order(): void
|
|
|
+ {
|
|
|
+ (new PaymentPayTimeout())->handle();
|
|
|
+ $apply = new \ReflectionMethod(PaymentOrderService::class, 'applyPayCallback');
|
|
|
+
|
|
|
+ $processed = $apply->invoke(null, PaymentOrder::find(1), '10', '2', '3', '2', []);
|
|
|
+
|
|
|
+ $this->assertTrue($processed);
|
|
|
+ $this->assertSame(PaymentOrderService::STATUS_FAIL, (int)DB::table('payment_orders')->where('id', 1)->value('status'));
|
|
|
+ }
|
|
|
+}
|