# Subscription & Payment Gateway Contract

## Model
`Business Subscription -> Subscription Invoice -> Payment Attempt -> Gateway Transaction -> Refund (optional)`

Payment failure never destroys the invoice. A verified successful payment settles an invoice and advances/activates the subscription inside one DB transaction.

## Subscription states
`TRIALING`, `ACTIVE`, `PAST_DUE`, `GRACE`, `SUSPENDED`, `CANCELED`, `EXPIRED`.

Plan entitlement is data-driven by feature key and value; application code must not scatter checks such as `if plan == BUSINESS`.

## Gateway interface
```php
interface PaymentGatewayInterface
{
    public function key(): string;
    public function capabilities(): GatewayCapabilities;
    public function createPayment(GatewayCreatePaymentRequest $request): GatewayCreatePaymentResult;
    public function checkStatus(GatewayStatusRequest $request): GatewayStatusResult;
    public function verifyWebhook(array $headers, string $rawBody): GatewayWebhookResult;
}
```

Refund creation is an optional separate capability because provider APIs differ.

## ShasPay implementation
- Use HMAC Signed mode for every server-to-server API call.
- Keep API key, API secret and webhook secret only on the PHP server.
- Flutter calls ShasPOS Pro; it never calls privileged ShasPay APIs directly.
- `reference_type`: `shaspos_subscription_invoice`.
- `reference_id`: internal invoice ID used only server-to-server.
- Metadata carries the public invoice number.
- Payment attempt idempotency key: `shaspos-subinv-<invoice-public-id>-attempt-<n>`.
- Return/cancel pages are informational only; they never activate a subscription.

Webhook process:
1. Read exact raw body.
2. Verify HMAC signature with separate webhook secret.
3. Deduplicate using gateway + event ID.
4. For `payment.approved`, lock invoice/subscription, verify reference/amount/currency, record transaction, mark invoice paid, activate/extend subscription, audit, commit.
5. Rejected/refund/reversal events update immutable payment history and appropriate subscription state; never erase the original transaction.

## Future providers
KNET, bKash, Stripe or other gateways implement the same interface. Each driver declares capabilities such as hosted checkout, status inquiry, webhook, recurring billing, saved method, refund creation/partial refund, countries and currencies.
