PaypalWebhookVerifierTest.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. <?php
  2. namespace Webkul\BagistoApi\Tests\Unit\Payments;
  3. use Illuminate\Http\Client\Request;
  4. use Illuminate\Support\Facades\Http;
  5. use Tests\TestCase;
  6. use Webkul\Paypal\Services\WebhookVerifier;
  7. class PaypalWebhookVerifierTest extends TestCase
  8. {
  9. private function verifier(array $config): WebhookVerifier
  10. {
  11. return new class($config) extends WebhookVerifier
  12. {
  13. public function __construct(protected array $config) {}
  14. protected function getConfigData(string $key): mixed
  15. {
  16. return $this->config[$key] ?? null;
  17. }
  18. };
  19. }
  20. private function headers(): array
  21. {
  22. return [
  23. 'PayPal-Auth-Algo' => 'SHA256withRSA',
  24. 'PayPal-Cert-Url' => 'https://api.paypal.com/cert.pem',
  25. 'PayPal-Transmission-Id' => 'transmission-1',
  26. 'PayPal-Transmission-Sig' => 'signature',
  27. 'PayPal-Transmission-Time' => '2026-08-10T08:00:00Z',
  28. ];
  29. }
  30. public function test_it_verifies_a_sandbox_webhook_with_oauth(): void
  31. {
  32. Http::fake([
  33. 'https://api-m.sandbox.paypal.com/v1/oauth2/token' => Http::response([
  34. 'access_token' => 'access-token',
  35. ]),
  36. 'https://api-m.sandbox.paypal.com/v1/notifications/verify-webhook-signature' => Http::response([
  37. 'verification_status' => 'SUCCESS',
  38. ]),
  39. ]);
  40. $verifier = $this->verifier([
  41. 'client_id' => 'client-id',
  42. 'client_secret' => 'client-secret',
  43. 'webhook_id' => 'WH-123',
  44. 'sandbox' => true,
  45. ]);
  46. $event = ['id' => 'WH-EVENT-1', 'event_type' => 'PAYMENT.CAPTURE.COMPLETED'];
  47. $this->assertTrue($verifier->verify($this->headers(), $event));
  48. Http::assertSentCount(2);
  49. Http::assertSent(function (Request $request) use ($event) {
  50. return $request->url() === 'https://api-m.sandbox.paypal.com/v1/notifications/verify-webhook-signature'
  51. && $request['webhook_id'] === 'WH-123'
  52. && $request['transmission_id'] === 'transmission-1'
  53. && $request['webhook_event'] === $event
  54. && $request->hasHeader('Authorization', 'Bearer access-token');
  55. });
  56. }
  57. public function test_it_uses_the_live_api_when_sandbox_is_disabled(): void
  58. {
  59. Http::fake([
  60. 'https://api-m.paypal.com/v1/oauth2/token' => Http::response(['access_token' => 'live-token']),
  61. 'https://api-m.paypal.com/v1/notifications/verify-webhook-signature' => Http::response([
  62. 'verification_status' => 'FAILURE',
  63. ]),
  64. ]);
  65. $verifier = $this->verifier([
  66. 'client_id' => 'client-id',
  67. 'client_secret' => 'client-secret',
  68. 'webhook_id' => 'WH-LIVE',
  69. 'sandbox' => false,
  70. ]);
  71. $this->assertFalse($verifier->verify($this->headers(), ['id' => 'WH-EVENT-2']));
  72. Http::assertSent(fn (Request $request) => str_starts_with($request->url(), 'https://api-m.paypal.com/'));
  73. }
  74. public function test_it_rejects_missing_signature_headers_without_calling_paypal(): void
  75. {
  76. Http::fake();
  77. $verifier = $this->verifier([
  78. 'client_id' => 'client-id',
  79. 'client_secret' => 'client-secret',
  80. 'webhook_id' => 'WH-123',
  81. 'sandbox' => true,
  82. ]);
  83. $headers = $this->headers();
  84. unset($headers['PayPal-Transmission-Sig']);
  85. $this->expectException(\InvalidArgumentException::class);
  86. try {
  87. $verifier->verify($headers, ['id' => 'WH-EVENT-3']);
  88. } finally {
  89. Http::assertNothingSent();
  90. }
  91. }
  92. }