# How to Test Payment Integrations: Sandbox and Testing Guide

> A developer's guide to testing payment integrations - sandbox environments, test card numbers, edge case testing, and CI/CD workflows for payment flows.
- **Author**: Ayush Agarwal
- **Published**: 2026-04-13
- **Category**: Developer Guide
- **URL**: https://dodopayments.com/blogs/test-payment-integration-sandbox

---

Shipping a payment integration without thorough testing is a recipe for lost revenue, angry customers, and 3 AM incident pages. Payment flows have more failure modes than almost any other feature: declined cards, expired tokens, webhook delivery failures, currency conversion edge cases, race conditions on subscription renewals, and partial refunds that break your accounting.

Testing payments is uniquely challenging because you cannot use real credit cards in development, you need to simulate failures that rarely happen in production, and the payment provider is a third-party dependency you do not control. Sandbox environments solve the first problem. Systematic test planning solves the rest.

This guide covers how to test payment integrations from development through production, including sandbox setup, test scenarios, and CI/CD strategies.

## Sandbox vs Production Environments

Every serious payment provider offers two environments:

|            | Sandbox / Test               | Production / Live            |
| ---------- | ---------------------------- | ---------------------------- |
| Real money | No                           | Yes                          |
| Real cards | Test cards only              | Customer cards               |
| Webhooks   | Simulated events             | Real events                  |
| API keys   | Test keys (prefixed `test_`) | Live keys (prefixed `live_`) |
| Behavior   | Predictable, controllable    | Real-world variability       |

```mermaid
flowchart LR
    A[Development] -->|"Test API Keys"| B[Sandbox]
    B -->|"All tests pass"| C[Staging]
    C -->|"Integration tests"| D[Production]
    D -->|"Live API Keys"| E[Real Payments]
    B -->|"Simulate failures"| F[Error Handling Verified]
```

The sandbox mimics the production API exactly but never processes real charges. Use test API keys from your [Dodo Payments dashboard](https://dodopayments.com) or your payment provider to access it.

### Setting Up the Sandbox

With Dodo Payments, the setup is straightforward:

1. Get your test API key from the dashboard
2. Use it in your [SDK initialization](https://docs.dodopayments.com/developer-resources/dodo-payments-sdks)
3. All API calls now hit the sandbox

```javascript
import DodoPayments from "dodopayments";

const client = new DodoPayments({
  bearerToken: process.env.DODO_TEST_API_KEY, // test_ prefixed key
});

// This creates a test payment - no real charge
const payment = await client.payments.create({
  payment_link: true,
  billing: {
    city: "SF",
    country: "US",
    state: "CA",
    street: "123 Test St",
    zipcode: 94105,
  },
  customer: { email: "test@example.com", name: "Test Customer" },
  product_cart: [{ product_id: "pdt_test_product", quantity: 1 }],
});
```

Refer to the [integration guide](https://docs.dodopayments.com/developer-resources/integration-guide) for detailed sandbox configuration and the [API reference](https://docs.dodopayments.com/api-reference/introduction) for available endpoints.

## Test Card Numbers

Payment providers supply specific card numbers that trigger predictable outcomes. Common test cards:

| Card Number         | Behavior            |
| ------------------- | ------------------- |
| 4242 4242 4242 4242 | Successful payment  |
| 4000 0000 0000 0002 | Generic decline     |
| 4000 0000 0000 9995 | Insufficient funds  |
| 4000 0000 0000 0069 | Expired card        |
| 4000 0000 0000 0127 | Incorrect CVC       |
| 4000 0025 0000 3155 | Requires 3D Secure  |
| 4000 0000 0000 3220 | 3DS2 authentication |

For all test cards:

- Use any future expiration date (e.g., 12/30)
- Use any 3-digit CVC (e.g., 123)
- Use any billing ZIP code

> Test cards are your most important debugging tool. Before you write a single line of error handling, run each failure test card through your checkout flow and see what actually happens. Most developers are surprised by what their UI does when a payment fails.
>
> - Ayush Agarwal, Co-founder & CPTO at Dodo Payments

## Essential Test Scenarios

### Happy Path Tests

- One-time payment succeeds
- Subscription creation succeeds
- Subscription renewal succeeds
- Upgrade from one plan to another
- Downgrade with prorated credit
- Payment with coupon/discount applied

### Failure Tests

- Card declined (generic, insufficient funds, expired)
- 3D Secure authentication required and completed
- 3D Secure authentication required but abandoned
- Network timeout during payment
- Duplicate payment submission (double-click)
- Payment with invalid card number format

### Webhook Tests

- Successful payment webhook received and processed
- Failed payment webhook triggers [dunning flow](https://dodopayments.com/blogs/dunning-management)
- Subscription cancelled webhook revokes access
- Refund webhook updates customer records
- Webhook with invalid signature rejected
- Duplicate webhook (idempotency check)
- Webhook received out of order

### Edge Case Tests

- Currency conversion for [international payments](https://dodopayments.com/blogs/multi-currency-pricing-global-saas)
- Zero-amount authorization (card validation)
- Very large amounts (test upper limits)
- Very small amounts (below minimum threshold)
- Partial refund followed by full refund
- Subscription with trial period ending
- Customer updating payment method mid-cycle

### Checkout UI Tests

- [Overlay checkout](https://docs.dodopayments.com/developer-resources/overlay-checkout) opens and closes correctly
- [Inline checkout](https://docs.dodopayments.com/developer-resources/inline-checkout) renders in container
- Mobile responsive checkout experience
- Loading states during payment processing
- Error messages display correctly for each decline type
- Success redirect after payment

## Automated Testing Strategies

### Unit Tests for Payment Logic

Test your business logic independent of the payment provider:

```javascript
describe("Subscription Activation", () => {
  it("should activate subscription on payment.succeeded", async () => {
    const event = createMockEvent("payment.succeeded", {
      customer_id: "cust_123",
      product_id: "pdt_pro_plan",
    });

    await handleWebhook(event);

    const sub = await db.subscriptions.findOne({ customerId: "cust_123" });
    expect(sub.status).toBe("active");
    expect(sub.planId).toBe("pdt_pro_plan");
  });

  it("should not double-activate on duplicate webhook", async () => {
    const event = createMockEvent("payment.succeeded", {
      customer_id: "cust_123",
      product_id: "pdt_pro_plan",
    });

    await handleWebhook(event);
    await handleWebhook(event); // duplicate

    const subs = await db.subscriptions.find({ customerId: "cust_123" });
    expect(subs.length).toBe(1); // only one subscription created
  });
});
```

### Integration Tests Against Sandbox

Run integration tests against the sandbox API in your CI/CD pipeline:

```yaml
# GitHub Actions example
payment-tests:
  runs-on: ubuntu-latest
  env:
    DODO_API_KEY: ${{ secrets.DODO_TEST_API_KEY }}
  steps:
    - uses: actions/checkout@v4
    - run: npm install
    - run: npm run test:payments
```

### End-to-End Tests

Use Playwright or Cypress to test the complete checkout flow:

1. Navigate to your pricing page
2. Select a plan
3. Fill in test card details
4. Submit payment
5. Verify redirect to success page
6. Verify subscription activated in database

## Pre-Launch Checklist

Before switching from test to live API keys:

- [ ] All happy path scenarios pass
- [ ] All failure scenarios handled gracefully with user-friendly error messages
- [ ] Webhook endpoint verified with signature checking
- [ ] Idempotency implemented for webhook processing
- [ ] Logging captures payment events for debugging
- [ ] Error monitoring alerts set up for payment failures
- [ ] Refund flow tested end-to-end
- [ ] [Subscription lifecycle](https://docs.dodopayments.com/features/subscription) tested (create, renew, cancel, upgrade, downgrade)
- [ ] [License key delivery](https://docs.dodopayments.com/features/license-keys) verified (if applicable)
- [ ] Currency display correct for [international customers](https://dodopayments.com/blogs/global-billing)
- [ ] [Checkout widget](https://docs.dodopayments.com/developer-resources/overlay-checkout) renders correctly on all target devices
- [ ] Revenue numbers reconcile between your database and provider dashboard

## Monitoring in Production

After launch, monitor these metrics:

- **Payment success rate**: Should be 85%+ for cards, higher for bank transfers
- **Webhook delivery rate**: Should be 99%+
- **Average payment processing time**: Should be under 3 seconds
- **Refund processing time**: Track SLA compliance
- **Error rates by type**: Identify systematic issues early

Set up alerts for anomalies. A sudden spike in decline rates could indicate a processor outage, a broken checkout flow, or a fraud attack. Catching these early prevents significant [revenue leakage](https://dodopayments.com/blogs/revenue-leakage-saas).

For more on building robust payment infrastructure, read our guides on [payment gateway integration](https://dodopayments.com/blogs/payment-gateway-integration-guide), [payment APIs](https://dodopayments.com/blogs/payment-api-guide), and the [developer experience at Dodo Payments](https://dodopayments.com/blogs/developer-experience-dodo-payments).

## FAQ

### Can I use real credit cards in a sandbox environment?

No. Sandbox environments only accept test card numbers provided by the payment provider. Submitting real card numbers to the sandbox will result in an error. This is by design to prevent accidental charges during development and testing.

### How do I test webhooks locally if my server is not publicly accessible?

Use a tunneling service like ngrok to expose your local server. Run `ngrok http 3000` to get a public URL, then register that URL as your webhook endpoint in the payment provider's test dashboard. Some providers also offer CLI tools that forward test events to localhost directly.

### Should I run payment tests in CI/CD pipelines?

Yes. Run unit tests and integration tests against the sandbox API in every CI/CD run. This catches regressions in payment logic before they reach production. Use your test API key as a CI secret and run the payment test suite as part of your standard test job.

### What is the difference between test mode and live mode?

Test mode uses sandbox API keys and processes simulated transactions with test card numbers. No real money moves. Live mode uses production API keys and processes real charges against real customer cards. The API interface is identical, only the keys and card validation differ.

### How do I simulate a 3D Secure authentication flow in testing?

Most payment providers have specific test card numbers that trigger 3D Secure. For example, 4000002500003155 typically triggers a 3DS challenge. The sandbox simulates the authentication popup so you can test both successful and failed authentication scenarios.

## Final Thoughts

Testing payments properly takes time upfront but prevents costly production incidents. Use the sandbox exhaustively, automate what you can, and run through the full checklist before going live.

For a payment platform with developer-friendly testing tools and comprehensive SDKs, check out [Dodo Payments](https://dodopayments.com) and see the [pricing](https://dodopayments.com/pricing).
---
- [More Developer Guide articles](https://dodopayments.com/blogs/category/developer-guide)
- [All articles](https://dodopayments.com/blogs)