> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ozura.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing Guide

> Test your integration before going live with sandbox mode

Test your integration before going live.

## Testing Checklist

Run through this checklist before going live:

### 1. Create Session

* [ ] API call returns `success: true`
* [ ] You get a `checkoutUrl`

### 2. Checkout Page

* [ ] Your store name appears
* [ ] Correct amount displays
* [ ] Card form loads properly

### 3. Success Flow

* [ ] Enter card details, click "Pay Now"
* [ ] Customer redirected to your `successUrl`
* [ ] You receive `sessionId` and transaction parameters in URL

### 4. Cancel Flow

* [ ] Click "Cancel" on checkout
* [ ] Customer redirected to your `cancelUrl`

### 5. Verification

* [ ] Your server calls `GET /api/sessions/{sessionId}`
* [ ] Status returns `completed`

## Elavon Sandbox Testing

<Note>
  Make sure your checkout API calls are pointing at `https://sandbox-checkout.ozura.com`, not `https://checkout.ozura.com`.
</Note>

Ozura Checkout uses **Elavon** as the payment processor. Sandbox is self-serve and requires three things:

1. A **test vault key** (from a Test project at [ozuravault.com](https://www.ozuravault.com))
2. **Sandbox OzuraPay credentials** (merchant ID + PayAPI key) from the merchant dashboard's Sandbox toggle
3. Checkout API calls directed at `https://sandbox-checkout.ozura.com`

See the [Sandbox guide](/guides/sandbox) for the full setup walkthrough.

In sandbox, Elavon determines the transaction response based on the **amount**, not the card number.

### How It Works

| Amount Ends In | Result           |
| :------------- | :--------------- |
| `.00`          | **Approval**     |
| `.88`          | **Declined**     |
| `.13`          | **Amount Error** |

For example:

* `$25.00` → Approval
* `$25.88` → Declined
* `$25.13` → Amount Error

### Test Card Numbers

Ozura Checkout accepts card numbers of **13–19 digits** (Luhn-valid). Any of these test card numbers will work in sandbox mode. The **amount** determines success or failure:

| Card Type   | Number             |
| :---------- | :----------------- |
| Visa        | `4000000000000002` |
| Mastercard  | `5121212121212124` |
| Amex        | `370000000000002`  |
| Discover    | `6011000000000004` |
| Diners Club | `36111111111111`   |
| JCB         | `3566664444444445` |

**CVV:** Any 3 digits (4 digits for Amex)
**Expiry:** Any future date

## Important: Tax Affects the Final Amount

When testing, remember that **tax calculations can change the final amount** sent to Elavon.

Tax is calculated by the payment processor based on the customer's billing address. For example:

* Base amount: `$26.52`
* Customer enters zip code: `10001` (New York)
* Final amount might be `~$28.88` → triggers a decline!

### Tips for Predictable Testing

1. **Use round amounts** like `$25.00` or `$30.00` to ensure approvals
2. **Use `taxExempt: true`** when creating test sessions to skip tax calculation
3. **Use a tax-free zip code** in testing (some states have no sales tax)

**Example: Guaranteed Approval (Tax-Exempt)**

```json theme={null}
{
  "amount": "25.00",
  "taxExempt": true
}
```

Final amount to Elavon: `$25.00` → Approval

**Example: Testing Decline (Tax-Exempt)**

```json theme={null}
{
  "amount": "25.88",
  "taxExempt": true
}
```

Final amount to Elavon: `$25.88` → Declined

## Common Test Issues

### "Authentication failed" on submit

Checkout sessions expire after **30 minutes**. If you created the session and then waited more than 30 minutes before clicking **Pay Now**, the session will be expired. Create a new session and use the new checkout URL.

### "Session not found"

Sessions expire after 30 minutes. Create a new one.

### "Invalid API key"

Double-check your API keys match what's in your Ozura Dashboard.

### CORS errors

For popup/iframe modes, make sure `parentOrigin` exactly matches your website URL (including `https://`).

### Unexpected decline

Check if tax was applied. The total sent to Elavon might end in `.88` even if your base amount didn't.

## Ready for Production?

Going live means switching from sandbox credentials and URLs to their production equivalents:

1. **Get a production vault key.** Production vault applications are gated behind an approval step — apply via the [Ozura Vault](https://www.ozuravault.com) product UI or your Ozura representative. Test vault keys do not work in production.
2. **Switch to production OzuraPay credentials.** In the merchant dashboard, flip the **Sandbox/Production** toggle to Production and use the merchant ID + PayAPI key shown there.
3. **Point your checkout API calls at `https://checkout.ozura.com`** instead of `https://sandbox-checkout.ozura.com`.
4. Make a small real payment to verify the end-to-end flow before sending production traffic.
