Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2
3declare(strict_types=1);
4
5namespace App\Domain\Stripe\Service;
6
7use App\Domain\Stripe\Data\PaymentChargeData;
8use App\Domain\Stripe\Data\PaymentMethodData;
9use App\Domain\Stripe\Data\SetupIntentData;
10use App\Domain\Stripe\Data\StripeCustomerData;
11use App\Domain\Stripe\Data\WebhookEventData;
12use App\Domain\Stripe\Exception\WebhookSignatureException;
13
14/**
15 * Domain-shaped Stripe client.
16 *
17 * Each concrete operation FlowState performs against Stripe goes through one
18 * method here. Implementations:
19 *   - {@see StripeService}             — real SDK wrapper, used in non-test envs
20 *   - {@see \App\Test\Fake\FakeStripeClient} — in-memory, used by integration tests
21 *
22 * The interface grows as later PRs in the FSC-92 rollout need more
23 * operations (SetupIntents, PaymentIntents, PaymentMethods, etc.).
24 */
25interface StripeClientInterface
26{
27    /**
28     * Create a new Customer in Stripe.
29     *
30     * @param ?string $email Optional billing email (recommended for receipts)
31     * @param ?string $name  Optional display name
32     * @param array<string, string> $metadata Arbitrary key-value tags stored on the Customer
33     */
34    public function createCustomer(
35        ?string $email = null,
36        ?string $name = null,
37        array $metadata = [],
38    ): StripeCustomerData;
39
40    /**
41     * Retrieve a Customer by ID. Returns null when the Customer does not
42     * exist (Stripe's resource_missing) — any other error bubbles.
43     * @param string $customerId
44     */
45    public function findCustomer(string $customerId): ?StripeCustomerData;
46
47    /**
48     * Create a SetupIntent for the given Customer. The returned client_secret
49     * is handed to the frontend so Stripe.js can confirm against Stripe and
50     * attach the resulting PaymentMethod to the Customer.
51     * @param string $customerId
52     */
53    public function createSetupIntent(string $customerId): SetupIntentData;
54
55    /**
56     * List card-type PaymentMethods attached to a Customer. The default
57     * PaymentMethod (per Stripe's invoice_settings) is flagged via
58     * {@see PaymentMethodData::$isDefault}.
59     *
60     * @param string $customerId
61     * @return list<PaymentMethodData>
62     */
63    public function listPaymentMethods(string $customerId): array;
64
65    /**
66     * Detach a PaymentMethod from its Customer. The PM is no longer usable
67     * after this; FlowState never re-attaches the same one.
68     * @param string $paymentMethodId
69     */
70    public function detachPaymentMethod(string $paymentMethodId): void;
71
72    /**
73     * Set the Customer's default PaymentMethod (used for off-session charges
74     * like loan payments). Stripe stores this on
75     * `invoice_settings.default_payment_method`.
76     * @param string $customerId
77     * @param string $paymentMethodId
78     */
79    public function setDefaultPaymentMethod(string $customerId, string $paymentMethodId): void;
80
81    /**
82     * Charge a stored PaymentMethod off-session (the user is not present to
83     * complete a 3DS challenge). Creates a PaymentIntent with
84     * `confirm: true`, `off_session: true`, and the given amount in cents.
85     *
86     * @param int    $amountCents Amount in the smallest currency unit (cents for USD)
87     * @param string $description Human-readable description (shows on Stripe dashboard + receipts)
88     * @param array<string, string> $metadata Tags stored on the PaymentIntent (e.g. loan_id, payment_id)
89     * @param string $customerId
90     * @param string $paymentMethodId
91     */
92    public function chargePaymentMethod(
93        string $customerId,
94        string $paymentMethodId,
95        int $amountCents,
96        string $description,
97        array $metadata = [],
98    ): PaymentChargeData;
99
100    /**
101     * Verify and parse an inbound Stripe webhook payload. Signature
102     * verification uses the configured webhook_secret; mismatch throws
103     * {@see WebhookSignatureException} (which the action translates to 400).
104     *
105     * @param string $payload   Raw request body, exactly as Stripe sent it
106     * @param string $signature Value of the `Stripe-Signature` header
107     *
108     * @throws WebhookSignatureException
109     */
110    public function parseWebhookEvent(string $payload, string $signature): WebhookEventData;
111}