6 min read

Test Stripe Subscriptions

This guide explains how to test your Stripe integration thoroughly using test mode.

Test Mode Setup

  1. Switch to test mode in Stripe Dashboard
  2. Use test API keys:
    const iaptic = new IapticStripe({
      stripePublicKey: 'pk_test_...',
      appName: 'com.example.app',
      apiKey: 'your_test_api_key'
    });
    

Test Cards

Successful Payments

// Always succeeds
const CARD_SUCCESS = '4242 4242 4242 4242';

// Requires authentication (3D Secure)
const CARD_3DS = '4000 0000 0000 3220';

Failed Payments

// Generic decline
const CARD_DECLINE = '4000 0000 0000 0002';

// Insufficient funds
const CARD_INSUFFICIENT = '4000 0000 0000 9995';

// Expired card
const CARD_EXPIRED = '4000 0000 0000 0069';

Test Scenarios

1. Basic Subscription

// 1. Create checkout
const response = await iaptic.createStripeCheckout({
  offerId: 'stripe:prod_xyz#price_xyz',
  applicationUsername: 'test_user',
  successUrl: 'https://example.com/success',
  cancelUrl: 'https://example.com/cancel'
});

// 2. Complete checkout with test card
// Use card: 4242 4242 4242 4242

// 3. Verify subscription
const { purchases } = await iaptic.getPurchases();
console.assert(purchases[0].renewalIntent === 'Renew');

2. Failed Payment

// Use card: 4000 0000 0000 0002
// Verify webhook events
const subscription = await iaptic.getPurchases();
console.assert(subscription.isBillingRetryPeriod === true);

3. Plan Change

// 1. Start with basic plan
// 2. Upgrade to premium
await iaptic.changePlan({
  offerId: 'stripe:prod_premium#price_xyz'
});

// 3. Verify proration
const { purchases } = await iaptic.getPurchases();
console.assert(purchases[0].productId.includes('premium'));

4. Cancellation

// 1. Create subscription
// 2. Cancel through portal
await iaptic.redirectToCustomerPortal({
  returnUrl: 'https://example.com/account'
});

// 3. Verify status
const { purchases } = await iaptic.getPurchases();
console.assert(purchases[0].renewalIntent === 'Cancel');

Test Webhook Events

Use Stripe CLI to simulate events:

# Install Stripe CLI
brew install stripe/stripe-cli/stripe

# Login
stripe login

# Listen to webhooks
stripe listen --forward-to localhost:3000/webhook

# Trigger specific events
stripe trigger customer.subscription.created
stripe trigger customer.subscription.updated
stripe trigger invoice.payment_failed

Test Access Keys

// 1. Store access key
const accessKey = response.accessKey;
localStorage.setItem('stripe_access_key', accessKey);

// 2. Test expiration
const { new_access_keys } = await iaptic.getPurchases(
  'sub_xyz',
  'expired_key_123'
);

// 3. Verify rotation
console.assert(new_access_keys?.['sub_xyz'] !== undefined);

Common Test Cases

Subscription Lifecycle

  • [x] Initial subscription
  • [x] Successful renewal
  • [x] Failed payment
  • [x] Payment retry
  • [x] Cancellation
  • [x] Reactivation

Plan Changes

  • [x] Upgrade
  • [x] Downgrade
  • [x] Proration
  • [x] Failed change

User Management

  • [x] New user
  • [x] Transfer subscription
  • [x] Multiple users
  • [x] Access revocation

Error Handling

  • [x] Invalid cards
  • [x] Network errors
  • [x] Webhook failures
  • [x] Access key rotation

Test Environment

class TestEnvironment {
  constructor() {
    this.iaptic = new IapticStripe({
      stripePublicKey: 'pk_test_...',
      appName: 'test.app',
      apiKey: 'test_key'
    });
  }

  async createTestSubscription(card = '4242424242424242') {
    const response = await this.iaptic.createStripeCheckout({
      offerId: this.getTestOfferId(),
      applicationUsername: 'test_user',
      successUrl: 'http://localhost:3000/success',
      cancelUrl: 'http://localhost:3000/cancel'
    });

    // Simulate checkout completion
    await this.simulateCheckout(response.sessionId, card);
    
    return response;
  }

  async simulateCheckout(sessionId, card) {
    // Implement checkout simulation
  }

  getTestOfferId() {
    return 'stripe:prod_test#price_test';
  }

  async cleanup() {
    // Clean up test data
  }
}

Best Practices

  1. Test Data

    • Use clear test identifiers
    • Clean up after tests
    • Isolate test environments
    • Use fresh sessions
  2. Automation

    • Automate common flows
    • Test edge cases
    • Verify webhooks
    • Monitor test coverage
  3. Verification

    • Check subscription status
    • Verify metadata
    • Validate access keys
    • Monitor webhooks