PaypalWebhookControllerTest.php 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. <?php
  2. namespace Webkul\BagistoApi\Tests\Unit\Payments;
  3. use Illuminate\Http\Request;
  4. use Mockery;
  5. use Tests\TestCase;
  6. use Webkul\Paypal\Http\Controllers\WebhookController;
  7. use Webkul\Paypal\Services\WebhookService;
  8. use Webkul\Paypal\Services\WebhookVerifier;
  9. class PaypalWebhookControllerTest extends TestCase
  10. {
  11. protected function tearDown(): void
  12. {
  13. Mockery::close();
  14. parent::tearDown();
  15. }
  16. private function request(array $event): Request
  17. {
  18. return Request::create(
  19. '/paypal/smart-button/webhook',
  20. 'POST',
  21. [],
  22. [],
  23. [],
  24. [
  25. 'CONTENT_TYPE' => 'application/json',
  26. 'HTTP_PAYPAL_AUTH_ALGO' => 'SHA256withRSA',
  27. 'HTTP_PAYPAL_CERT_URL' => 'https://api.paypal.com/cert.pem',
  28. 'HTTP_PAYPAL_TRANSMISSION_ID' => 'transmission-1',
  29. 'HTTP_PAYPAL_TRANSMISSION_SIG' => 'signature',
  30. 'HTTP_PAYPAL_TRANSMISSION_TIME' => '2026-08-10T08:00:00Z',
  31. ],
  32. json_encode($event, JSON_THROW_ON_ERROR),
  33. );
  34. }
  35. public function test_it_acknowledges_a_verified_unknown_event(): void
  36. {
  37. $verifier = Mockery::mock(WebhookVerifier::class);
  38. $verifier->shouldReceive('verify')->once()->andReturnTrue();
  39. $service = Mockery::mock(WebhookService::class);
  40. $service->shouldNotReceive('handleCaptureCompleted');
  41. $controller = new WebhookController($verifier, $service);
  42. $response = $controller->hook($this->request([
  43. 'id' => 'WH-EVENT-IGNORED',
  44. 'event_type' => 'CHECKOUT.ORDER.APPROVED',
  45. ]));
  46. $this->assertSame(200, $response->getStatusCode());
  47. $this->assertSame('ignored', $response->getData(true)['status']);
  48. }
  49. public function test_it_rejects_an_invalid_signature(): void
  50. {
  51. $verifier = Mockery::mock(WebhookVerifier::class);
  52. $verifier->shouldReceive('verify')->once()->andReturnFalse();
  53. $controller = new WebhookController(
  54. $verifier,
  55. Mockery::mock(WebhookService::class),
  56. );
  57. $response = $controller->hook($this->request([
  58. 'id' => 'WH-EVENT-BAD-SIGNATURE',
  59. 'event_type' => 'PAYMENT.CAPTURE.COMPLETED',
  60. ]));
  61. $this->assertSame(400, $response->getStatusCode());
  62. $this->assertSame('invalid_signature', $response->getData(true)['status']);
  63. }
  64. public function test_it_returns_a_retryable_error_when_processing_fails(): void
  65. {
  66. $verifier = Mockery::mock(WebhookVerifier::class);
  67. $verifier->shouldReceive('verify')->once()->andReturnTrue();
  68. $service = Mockery::mock(WebhookService::class);
  69. $service->shouldReceive('handleCaptureCompleted')
  70. ->once()
  71. ->andThrow(new \RuntimeException('temporary database failure'));
  72. $controller = new WebhookController($verifier, $service);
  73. $response = $controller->hook($this->request([
  74. 'id' => 'WH-EVENT-RETRY',
  75. 'event_type' => 'PAYMENT.CAPTURE.COMPLETED',
  76. 'resource' => [],
  77. ]));
  78. $this->assertSame(500, $response->getStatusCode());
  79. $this->assertSame('processing_failed', $response->getData(true)['status']);
  80. }
  81. }