PaymentOrderRejectTest.php 4.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. <?php
  2. namespace Tests\Integration;
  3. use App\Http\Controllers\admin\PaymentOrder as PaymentOrderController;
  4. use App\Models\PaymentOrder;
  5. use App\Services\PaymentOrderService;
  6. use Illuminate\Config\Repository;
  7. use Illuminate\Database\Capsule\Manager;
  8. use Illuminate\Database\Schema\Blueprint;
  9. use Illuminate\Foundation\Application;
  10. use Illuminate\Http\Request;
  11. use Illuminate\Support\Facades\DB;
  12. use Illuminate\Support\Facades\Facade;
  13. use PHPUnit\Framework\TestCase;
  14. /** 后台在线充值拒绝:未完成订单直接失败,之后迟到的成功回调不再入账。 */
  15. class PaymentOrderRejectTest extends TestCase
  16. {
  17. private Application $app;
  18. protected function setUp(): void
  19. {
  20. parent::setUp();
  21. Facade::clearResolvedInstances();
  22. $this->app = $app = new Application(dirname(__DIR__, 2));
  23. $app->instance('config', new Repository(['app' => ['timezone' => 'Asia/Shanghai'], 'admin_realtime' => ['enabled' => false]]));
  24. $app->instance('files', new \Illuminate\Filesystem\Filesystem());
  25. $app->instance('path.lang', dirname(__DIR__, 2) . '/lang');
  26. $app->register(\Illuminate\Translation\TranslationServiceProvider::class);
  27. $app->register(\Illuminate\Validation\ValidationServiceProvider::class);
  28. $app->instance(\Illuminate\Contracts\Routing\ResponseFactory::class, (new \ReflectionClass(\Illuminate\Routing\ResponseFactory::class))->newInstanceWithoutConstructor());
  29. Request::macro('validate', function (array $rules) { return validator()->validate($this->all(), $rules); });
  30. Facade::setFacadeApplication($app);
  31. $db = new Manager($app);
  32. $db->addConnection(['driver' => 'sqlite', 'database' => ':memory:', 'prefix' => 'bot_']);
  33. $db->setAsGlobal();
  34. $db->bootEloquent();
  35. $app->instance('db', $db->getDatabaseManager());
  36. $db->schema()->create('payment_orders', function (Blueprint $t) {
  37. $t->id(); $t->string('member_id'); $t->integer('type'); $t->integer('status'); $t->string('state')->nullable();
  38. $t->text('callback_data')->nullable(); $t->string('remark')->nullable(); $t->decimal('amount', 24, 10); $t->timestamps();
  39. });
  40. foreach ([[1, 1], [1, 7], [1, 2], [3, 1], [1, 0]] as [$type, $status]) {
  41. DB::table('payment_orders')->insert(['member_id' => 'm1', 'type' => $type, 'status' => $status, 'amount' => 10]);
  42. }
  43. }
  44. protected function tearDown(): void
  45. {
  46. DB::disconnect();
  47. Facade::clearResolvedInstances();
  48. parent::tearDown();
  49. }
  50. private function reject(array $input): array
  51. {
  52. $this->app->instance('request', Request::create('/admin/paymentOrder/reject', 'POST', $input));
  53. $resp = (new PaymentOrderController())->reject();
  54. return json_decode($resp->getContent(), true);
  55. }
  56. private function orderStatus(int $id): int
  57. {
  58. return (int)DB::table('payment_orders')->where('id', $id)->value('status');
  59. }
  60. public function test_open_orders_become_failed_with_remark(): void
  61. {
  62. $r = $this->reject(['id' => 1, 'remark' => '未付款']); $this->assertSame(0, $r['code'], $r['msg']);
  63. $this->assertSame(0, $this->reject(['id' => 2])['code']);
  64. $this->assertSame(0, $this->reject(['id' => 5])['code']);
  65. $this->assertSame([3, 3, 3], [$this->orderStatus(1), $this->orderStatus(2), $this->orderStatus(5)]);
  66. $this->assertSame('未付款', DB::table('payment_orders')->where('id', 1)->value('remark'));
  67. $this->assertSame('后台拒绝', DB::table('payment_orders')->where('id', 2)->value('remark'));
  68. }
  69. public function test_finished_or_other_type_orders_are_refused(): void
  70. {
  71. $this->assertNotSame(0, $this->reject(['id' => 3])['code']);
  72. $this->assertNotSame(0, $this->reject(['id' => 4])['code']);
  73. $this->assertSame([2, 1], [$this->orderStatus(3), $this->orderStatus(4)]);
  74. }
  75. public function test_late_success_callback_is_ignored_after_reject(): void
  76. {
  77. $this->reject(['id' => 1]);
  78. $apply = new \ReflectionMethod(PaymentOrderService::class, 'applyPayCallback');
  79. $this->assertFalse($apply->invoke(null, PaymentOrder::find(1), '10', '2', '2', '3', []));
  80. $this->assertSame(PaymentOrderService::STATUS_FAIL, $this->orderStatus(1));
  81. }
  82. }