Spaces:
Runtime error
Runtime error
| namespace Tests\Unit; | |
| use App\Domain\Payments\Gateways\StripeGateway; | |
| use Illuminate\Support\Facades\Http; | |
| use Tests\TestCase; | |
| class StripeGatewayTest extends TestCase | |
| { | |
| public function test_card_checkout_session_is_created(): void | |
| { | |
| config(['payments.stripe.secret_key' => 'sk_test_fake']); | |
| Http::fake([ | |
| 'https://api.stripe.com/v1/checkout/sessions' => Http::response([ | |
| 'id' => 'cs_test_card', | |
| 'url' => 'https://checkout.stripe.com/c/pay_card', | |
| 'payment_intent' => 'pi_card', | |
| ], 200), | |
| ]); | |
| $intent = (new StripeGateway())->createIntent($this->invoice(), [ | |
| 'payment_id' => 'pay_123', | |
| 'payment_method' => 'card', | |
| 'customer_email' => 'applicant@example.com', | |
| 'return_url' => 'https://example.com/return', | |
| 'cancel_url' => 'https://example.com/cancel', | |
| ], 'PAY-123'); | |
| $this->assertSame('cs_test_card', $intent['gateway_reference']); | |
| $this->assertSame('pi_card', $intent['external_reference']); | |
| $this->assertSame('https://checkout.stripe.com/c/pay_card', $intent['checkout_url']); | |
| Http::assertSent(fn ($request) => $request->url() === 'https://api.stripe.com/v1/checkout/sessions' | |
| && $request['payment_method_types'][0] === 'card' | |
| && $request['client_reference_id'] === 'PAY-123' | |
| && $request['line_items'][0]['price_data']['product_data']['name'] === 'Application Fee'); | |
| } | |
| public function test_bank_transfer_checkout_session_creates_customer(): void | |
| { | |
| config([ | |
| 'payments.stripe.secret_key' => 'sk_test_fake', | |
| 'payments.stripe.bank_transfer_type' => 'us_bank_transfer', | |
| ]); | |
| Http::fake([ | |
| 'https://api.stripe.com/v1/customers' => Http::response(['id' => 'cus_bank'], 200), | |
| 'https://api.stripe.com/v1/checkout/sessions' => Http::response([ | |
| 'id' => 'cs_test_bank', | |
| 'url' => 'https://checkout.stripe.com/c/pay_bank', | |
| 'payment_intent' => null, | |
| 'customer' => 'cus_bank', | |
| ], 200), | |
| ]); | |
| $intent = (new StripeGateway())->createIntent($this->invoice(), [ | |
| 'payment_id' => 'pay_456', | |
| 'payment_method' => 'bank_transfer', | |
| 'customer_email' => 'applicant@example.com', | |
| 'return_url' => 'https://example.com/return', | |
| 'cancel_url' => 'https://example.com/cancel', | |
| ], 'PAY-456'); | |
| $this->assertSame('cs_test_bank', $intent['gateway_reference']); | |
| $this->assertSame('cus_bank', $intent['metadata']['stripe_customer_id']); | |
| Http::assertSent(fn ($request) => $request->url() === 'https://api.stripe.com/v1/customers'); | |
| Http::assertSent(fn ($request) => $request->url() === 'https://api.stripe.com/v1/checkout/sessions' | |
| && $request['payment_method_types'][0] === 'customer_balance' | |
| && $request['payment_method_options']['customer_balance']['funding_type'] === 'bank_transfer'); | |
| } | |
| public function test_webhook_signature_is_verified(): void | |
| { | |
| config(['payments.stripe.webhook_secret' => 'whsec_fake']); | |
| $payload = json_encode(['id' => 'evt_123', 'type' => 'checkout.session.completed'], JSON_THROW_ON_ERROR); | |
| $timestamp = time(); | |
| $signature = hash_hmac('sha256', $timestamp.'.'.$payload, 'whsec_fake'); | |
| $verified = (new StripeGateway())->verifyWebhook($payload, [ | |
| 'stripe-signature' => ['t='.$timestamp.',v1='.$signature], | |
| ]); | |
| $this->assertTrue($verified['verified']); | |
| $this->assertSame('evt_123', $verified['event_id']); | |
| } | |
| public function test_checkout_session_uses_invoice_fee_type_name(): void | |
| { | |
| config(['payments.stripe.secret_key' => 'sk_test_fake']); | |
| Http::fake([ | |
| 'https://api.stripe.com/v1/checkout/sessions' => Http::response([ | |
| 'id' => 'cs_test_membership', | |
| 'url' => 'https://checkout.stripe.com/c/pay_membership', | |
| 'payment_intent' => 'pi_membership', | |
| ], 200), | |
| ]); | |
| $invoice = $this->invoice(); | |
| $invoice->fee_type_code = 'ANNUAL_MEMBERSHIP_FEE'; | |
| (new StripeGateway())->createIntent($invoice, [ | |
| 'payment_id' => 'pay_789', | |
| 'payment_method' => 'card', | |
| 'customer_email' => 'applicant@example.com', | |
| 'return_url' => 'https://example.com/return', | |
| 'cancel_url' => 'https://example.com/cancel', | |
| ], 'PAY-789'); | |
| Http::assertSent(fn ($request) => $request->url() === 'https://api.stripe.com/v1/checkout/sessions' | |
| && $request['line_items'][0]['price_data']['product_data']['name'] === 'Annual Membership Fee'); | |
| } | |
| public function test_webhook_signature_accepts_multiple_v1_values(): void | |
| { | |
| config(['payments.stripe.webhook_secret' => 'whsec_fake']); | |
| $payload = json_encode(['id' => 'evt_456', 'type' => 'checkout.session.completed'], JSON_THROW_ON_ERROR); | |
| $timestamp = time(); | |
| $validSignature = hash_hmac('sha256', $timestamp.'.'.$payload, 'whsec_fake'); | |
| $verified = (new StripeGateway())->verifyWebhook($payload, [ | |
| 'stripe-signature' => ['t='.$timestamp.',v1=invalidsignature,v1='.$validSignature], | |
| ]); | |
| $this->assertTrue($verified['verified']); | |
| $this->assertSame('evt_456', $verified['event_id']); | |
| } | |
| private function invoice(): object | |
| { | |
| return (object) [ | |
| 'id' => 'inv_123', | |
| 'application_id' => 'app_123', | |
| 'fee_type_code' => 'APPLICATION_FEE', | |
| 'amount_due' => 20, | |
| 'currency' => 'USD', | |
| ]; | |
| } | |
| } | |