# How payments work

Who does what in a payment, from checkout to the webhook, for each kind of channel. The numbers in each diagram are the order things happen in.

## Who’s involved

| Who | What they do |
| --- | --- |
| **Payer** | Your customer. Pays with a QR Ph app, an e-wallet, a card or cash at a counter. |
| **Your server** | Creates the payment with your API key, shows the payer what to do next, and fulfills the order when the webhook arrives. Your app or website talks to your server, never to Weav with your key. |
| **Weav** | Sets the payment up with the provider, tracks its status, credits your balance and sends you signed webhooks. |
| **Provider** | Where the money moves: the payer’s bank or e-wallet through QR Ph, GCash, Maya, the card network, or a Pay & Go, Palawan or Bayad counter. |

## Payment link (the default)

Send the payer to Weav’s payment page. Nothing is set up with the provider until they open it; then the page shows the QR code, the counter code or the way to the provider’s page, with how-to-pay steps and a live status.

```mermaid
sequenceDiagram
    autonumber
    actor Payer
    participant Server as Your server
    participant Weav
    participant Provider
    Payer->>Server: Checks out
    Server->>Weav: POST /v1/payments
    Weav-->>Server: 201 PENDING<br/>next_action.checkout_url
    Server-->>Payer: Sends them to checkout_url
    Payer->>Weav: Opens Weav's payment page
    Weav->>Provider: Sets up the payment
    Weav-->>Payer: QR code, counter code or the<br/>provider's page, with steps
    Payer->>Provider: Pays
    Provider->>Weav: Confirms the payment
    Note over Weav: COMPLETED<br/>your balance is credited
    Weav-->>Payer: The page shows it as paid
    Weav->>Server: PAYMENT_COMPLETED<br/>webhook, signed
    Server-->>Weav: 2xx within 10 seconds
    Note over Server: Verify X-Signature,<br/>then fulfill the order once
```

The link lasts 24 hours unopened. Once the payer opens it, `expires_at` becomes the provider’s window, for example 15 minutes for a QR Ph code.

## QR Ph, shown by you

With `"next_action_format": "DIRECT"` you get the raw QR string and show it yourself. Any QR Ph bank or e-wallet app can pay it.

```mermaid
sequenceDiagram
    autonumber
    actor Payer
    participant Server as Your server
    participant Weav
    participant Provider as Payer's bank<br/>or e-wallet
    Payer->>Server: Checks out
    Server->>Weav: POST /v1/payments<br/>QR_PH, DIRECT
    Weav->>Provider: Sets up the QR Ph code
    Weav-->>Server: 201 PENDING, DISPLAY_QR<br/>qr_string, instructions
    Server-->>Payer: Shows the QR code and the steps
    alt Paid before expires_at
        Payer->>Provider: Scans the code<br/>in their app and pays
        Provider->>Weav: Confirms the payment
        Weav->>Server: PAYMENT_COMPLETED<br/>webhook
    else Not paid in time
        Weav->>Server: PAYMENT_FAILED webhook<br/>failure.code EXPIRED
    end
```

A payment that failed or was canceled can still complete if the provider confirms the money arrived late. Act on the latest status. See [Statuses](https://docs.weavpayments.com/statuses).

## Redirect: GCash, Maya and cards

The payer pays on the provider’s own page. With `"next_action_format": "DIRECT"`, `checkout_url` is that page, as below; with a payment link, Weav’s page sends them there. Where their browser lands afterward only decides what they see; it never confirms the payment.

```mermaid
sequenceDiagram
    autonumber
    actor Payer
    participant Server as Your server
    participant Weav
    participant Provider as GCash, Maya<br/>or card checkout
    Payer->>Server: Checks out
    Server->>Weav: POST /v1/payments<br/>GCASH, MAYA or CARD, DIRECT,<br/>success_url, cancel_url
    Weav->>Provider: Creates the checkout
    Weav-->>Server: 201 PENDING<br/>REDIRECT: checkout_url
    Server-->>Payer: Redirects to checkout_url
    Payer->>Provider: Pays, or cancels
    Provider-->>Payer: Sends them back through Weav
    Payer->>Weav: Returns
    Weav->>Provider: Checks the result
    Weav-->>Payer: Redirects to<br/>success_url or cancel_url
    Note over Payer,Server: Landing on success_url<br/>is not proof of payment
    Provider->>Weav: Confirms the payment
    Weav->>Server: PAYMENT_COMPLETED<br/>webhook
```

If the provider is still confirming, the payer sees a Weav page that updates by itself before the redirect. The provider’s confirmation can come before or after the payer returns.

## Over the counter: Pay & Go, PalawanPay and Bayad

The payer gets a payment code and pays cash to **Eplayment** at a kiosk or counter. With `"next_action_format": "DIRECT"` you get the code and give it to them, as below; with a payment link, Weav’s page shows it.

```mermaid
sequenceDiagram
    autonumber
    actor Payer
    participant Server as Your server
    participant Weav
    participant Provider as Kiosk or counter
    Payer->>Server: Checks out
    Server->>Weav: POST /v1/payments<br/>PAY_AND_GO, PALAWANPAY or BAYAD,<br/>DIRECT
    Weav-->>Server: 201 PENDING<br/>PAY_AT_COUNTER: payment_code
    Server-->>Payer: Gives them the payment code
    alt Paid within 48 hours
        Payer->>Provider: Pays cash to Eplayment<br/>with the code
        Provider->>Weav: Confirms the payment
        Weav->>Server: PAYMENT_COMPLETED<br/>webhook
    else Not paid in time
        Weav->>Server: PAYMENT_FAILED webhook<br/>failure.code EXPIRED
    end
```

## Webhook delivery

Every status change reaches your server as a signed webhook. Answer within 10 seconds, do the work in a queue, and handle each event once: the same event can arrive twice, and events can arrive out of order.

```mermaid
sequenceDiagram
    autonumber
    participant Weav
    participant Server as Your server
    Weav->>Server: POST to your webhook URL (X-Signature)
    alt 2xx within 10 seconds
        Note over Weav: Delivered
    else Anything else: 4xx, 5xx, timeout,<br/>TLS error or redirect
        loop Up to 18 attempts over about 7 days
            Weav->>Server: Retries, freshly signed each time
        end
        Note over Weav: Still failing: waits in the<br/>dashboard for you to repost
    end
    Server->>Weav: GET /v1/payments/{reference_id}<br/>at any time
    Weav-->>Server: The payment's latest status
```

See [Event types](https://docs.weavpayments.com/webhooks/event-types) for the retry schedule and [Verifying signatures](https://docs.weavpayments.com/webhooks/verifying-signatures) for the check.
