> For the complete documentation index, see [llms.txt](https://docs.payr.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.payr.com/payment-interface/payr-sdk/payment-flow.md).

# Payment Flow

This page explains how to trigger payments using `PAYR.pay()` after initializing the SDK.

The payment flow is designed to be simple: all payment data (amount, reference, features) is configured in `PAYR.init()`, so triggering a payment requires no arguments. The SDK automatically routes to the appropriate payment method based on what the user selected (card, APM, or wallet).

***

### PAYR.pay()

The `PAYR.pay()` method creates a payment using the current SDK state. **All payment data** (amount, currency, reference) comes from the `PAYR.init()` configuration - **no arguments are required**.

#### How It Works

**For Card Payments:**

* SDK displays saved payment methods in your container at init
* User selects a card and enters CVC
* You call `PAYR.pay()` to process the payment

**For Wallet Payments (Apple Pay / Google Pay):**

* When `features.applePay` or `features.googlePay` is enabled, wallet buttons appear in the SDK UI
* User taps the wallet button directly
* **You do NOT call `PAYR.pay()`** for wallet flows — the SDK handles it automatically
* Amount is sourced from `pure_amount` in init (or live amount input when `isAmountEditable: true`)

**For Alternative Payment Methods (APMs):**

* When `features.apms: true` is set, a "Payment type" selector appears (Card, Alipay, WeChat Pay, UnionPay)
* For APMs, SDK hides the card dropdown and CVC input
* You call `PAYR.pay()` to process the APM payment

**For Recurring Payments:**

* When `features.recurring: true` is set, SDK loads recurring payment logic
* First payment requires 3DS authentication
* Subsequent payments are automated

***

### Signature

```typescript
PAYR.pay(): Promise<void>
```

* **No arguments** — All payment data is sourced from `PAYR.init()` configuration
* **Returns:** Promise that resolves to `undefined` on success
* **Rejects:** On validation errors, user cancellation, payment failures, or API errors

***

### Prerequisites

Before calling `PAYR.pay()`, ensure:

1. **`PAYR.init()`** has completed successfully
2. **You have not called `PAYR.destroy()`**
3. **For card payments:** User has selected a saved card and entered CVC
4. **When `isAmountEditable: true`:** User has entered a valid amount in the SDK input

If prerequisites are not met, `pay()` throws `PayrError`:

* Code `INIT_FAILED` — SDK not initialized or already destroyed
* Code `VALIDATION_ERROR` — Invalid or missing required data (e.g., empty amount input)

***

### Callbacks vs await

**On Success:**

* SDK calls `onSuccess` callback from `PAYR.init()` with the payment result
* `pay()` promise **also resolves**
* You can use `await PAYR.pay()`, `onSuccess`, or both

**On Failure:**

* SDK calls `onError` callback from `PAYR.init()` with the error
* `pay()` promise **also rejects** with the same error

```javascript
// Using await
try {
  await PAYR.pay();
  console.log('Payment completed');
} catch (error) {
  console.error('Payment failed:', error);
}

// Using callbacks (set in init)
PAYR.init({
  // ... config
  onSuccess: (result) => {
    console.log('Payment successful:', result);
    window.location.href = '/payment-success';
  },
  onError: (error) => {
    console.error('Payment failed:', error);
    alert('Payment failed: ' + error.message);
  }
});

// Later, trigger payment
await PAYR.pay();
```

***

### Payment Routing

When you call `PAYR.pay()`:

1. **Resolves amount** — From live input (if `isAmountEditable: true`) or `pure_amount` from init
2. **Inspects payment type** — Checks what the user selected in the SDK UI
3. **Routes payment:**
   * If APM is selected → Runs APM payment flow (redirect or QR code)
   * Otherwise → Runs card payment flow (3DS if required)

The payment breakdown block shows:

* Amount
* Payment Execution Fee
* Total

The amount + fee breakdown updates in real-time when `isAmountEditable: true`.

***

### Example: Basic Usage

```javascript
// Initialize SDK with fixed amount
await PAYR.init({
  apiBaseUrl: 'https://sandbox-api.mypayr.co.uk',
  authToken: token,
  container: '#payr-payment-form',
  pure_amount: 850.00,
  reference: 'rent-jan-2024',
  environment: 'sandbox',
  features: {
    addPaymentMethod: true,
    apms: true,
    recurring: true
  },
  onSuccess: (result) => {
    console.log('Payment successful:', result);
  },
  onError: (error) => {
    console.error('Payment failed:', error);
  }
});

// Trigger payment when user clicks pay button
document.getElementById('pay-button').addEventListener('click', async () => {
  try {
    await PAYR.pay();  // No arguments needed
    // Success handled by onSuccess callback
  } catch (error) {
    // Error handled by onError callback
    console.error('Payment error:', error);
  }
});
```

***

### Example: Editable Amount

```javascript
// Initialize SDK with editable amount
await PAYR.init({
  apiBaseUrl: 'https://sandbox-api.mypayr.co.uk',
  authToken: token,
  container: '#payr-payment-form',
  isAmountEditable: true,      // User can enter amount
  pure_amount: 850.00,         // Optional pre-fill
  environment: 'sandbox',
  onSuccess: (result) => {
    console.log('Payment successful:', result);
  },
  onError: (error) => {
    console.error('Payment failed:', error);
  }
});

// Trigger payment
document.getElementById('pay-button').addEventListener('click', async () => {
  try {
    await PAYR.pay();  // Uses amount from SDK input
  } catch (error) {
    // Validation error if amount input is empty or invalid
    console.error('Payment error:', error);
  }
});
```

***

### Next Steps

* [**Customization**](/payment-interface/payr-sdk/customization.md) - Customize colors, fonts, and styling
* [**Error Handling**](/error-handling.md) - Handle payment errors
* [**Testing**](/testing.md) - Test the SDK in your sandbox environment

***

### Support

Need help with payment flow? Contact **<support@mypayr.co.uk>**
