Testing Billing

    Learn how to test your billing integration.

    Check out some common scenarios to help you thoroughly test your billing integration before taking it live. You should also make use of our general testing doc, particularly its list of test credit card numbers.

    Testing subscription trial periods

    A common need is to test how your integration handles trial periods without waiting a full trial period to see the results. There’s a quick solution here: create a new subscription with a trial_end value only a few minutes in the future.

    Using this approach, you won’t see a customer.subscription.trial_will_end event notification (which occurs three days before a trial ends), but in all other ways the logic is the same as a subscription with a longer trial period.

    Testing subscription webhook notifications

    Proper use of subscriptions relies heavily on using webhooks. You can test webhooks by triggering fake event notifications via the Dashboard. However, when you do so, the received event contains only fake data that doesn’t correlate to real or test subscription information.

    Using fake event notifications may suffice but the most reliable way to test webhook notifications is to create actual test subscriptions and handle the corresponding events.

    Testing payment failures

    We’ve identified specific test credit card numbers to trigger payment failures, and these are usable on subscriptions and invoices as well.

    One catch to be aware of is that if a subscription requires an immediate payment and that payment fails, the subscription is not created. In order to test how a payment failure affects an active subscription, attach the 4000 0000 0000 0341 credit card to a customer as the payment source but use a trial period to defer the charge. A period of a few seconds or minutes is sufficient. Depending upon your subscription settings, you will have to wait a day or more to see the first retry attempt. If desired, you can use that period to update the customer’s payment source to a working test card to see what happens with a successful retry.

    Testing ACH credit transfer payments of invoices

    Most of Stripe’s functionality is designed to behave the same in both test and live modes. With manual ACH credit transfer payments of invoices, the main difference is that in test mode we send the invoice.sent webhook event according to the schedule in your settings, but the emails are not actually sent. If you wish to send a test mode invoice, you can click the Send button when you view the invoice in the Dashboard:

    To test manual payments on invoices via ACH credit transfers:

    1. Create the subscription, using send_invoice for the billing parameter (or using the Dashboard).
    2. After the invoice is created, find it in the Dashboard and click Send to send the email.
    3. Identify the newly created ach_credit_transfer source on the Customer object (or customer in the Dashboard).
    4. Update the owner email on the created source to amount_XXXX@any_domain.com, where XXXX is an integer representing the amount of money you want to simulate pushing (e.g., an invoice for $149.35 matches an owner email value of amount_14935@example.com).

    The second step is not required, but only non-editable invoices will be reconciled automatically. Sending an invoice will convert it to a non-editable state.

    Step four is represented by this code:

    curl https://api.stripe.com/v1/sources/src_19Q3AILlRB0eXbMt81RVDnM9 \
       -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
       -d owner[email]="amount_1000@example.com"
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    Stripe::Source.update('src_19Q3AILlRB0eXbMt81RVDnM9', {
      owner: {email: 'amount_1000@example.com'},
    })
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    stripe.Source.modify('src_19Q3AILlRB0eXbMt81RVDnM9',
      owner={'email': 'amount_1000@example.com'},
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    \Stripe\Source::update('src_19Q3AILlRB0eXbMt81RVDnM9', [
        'owner' => ['email' => 'amount_1000@example.com'],
    ]);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Source source = Source.retrieve("src_19Q3AILlRB0eXbMt81RVDnM9");
    Map<String, Object> ownerParams = new HashMap<>();
    ownerParams.put("email", "amount_1000@example.com");
    Map<String, Object> params = new HashMap<>();
    params.put("owner", ownerParams);
    source.update(params);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    stripe.sources.update('src_19Q3AILlRB0eXbMt81RVDnM9', {
      owner: {
        email: 'amount_1000@example.com',
      },
    });
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.SourceObjectParams{
      Owner: &stripe.SourceOwnerParams{
        Email: stripe.String("amount_1000@example.com"),
      },
    }
    src, _ := source.Update("src_19Q3AILlRB0eXbMt81RVDnM9", params)
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    StripeConfiguration.SetApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    var options = new StripeSourceUpdateOptions {
        Owner = new StripeSourceOwner {
            Email = "amount_1000@example.com",
        }
    };
    var service = new StripeSourceService();
    StripeSource source = service.Update("src_19Q3AILlRB0eXbMt81RVDnM9", options);
    

    A few moments after performing the update request, the receiver will be updated automatically. Retrieve the receiver with:

    curl https://api.stripe.com/v1/sources/src_19Q3AILlRB0eXbMt81RVDnM9 \
       -u sk_test_4eC39HqLyjWDarjtT1zdp7dc:
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    source = Stripe::Source.retrieve('src_19Q3AILlRB0eXbMt81RVDnM9')
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    source = stripe.Source.retrieve('src_19Q3AILlRB0eXbMt81RVDnM9')
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    $source = \Stripe\Source::retrieve('src_19Q3AILlRB0eXbMt81RVDnM9');
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Source source = Source.retrieve("src_19Q3AILlRB0eXbMt81RVDnM9");
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    const source = stripe.sources.retrieve('src_19Q3AILlRB0eXbMt81RVDnM9');
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.SourceObjectParams{}
    src, _ := source.Get("src_19Q3AILlRB0eXbMt81RVDnM9", params)
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    StripeConfiguration.SetApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    var service = new StripeSourceService();
    StripeSource source = service.Get("src_19Q3AILlRB0eXbMt81RVDnM9");
    

    A funded receiver will have a populated amount_received field:

    {
      "object": "list",
      "data": [
        {
          "id": "src_19Q3AILlRB0eXbMt81RVDnM9",
          "object": "source",
          "amount": null,
          "client_secret": "src_client_secret_Z0zPIgnR0BVafiMLaJcxI3HS",
          "created": 1481585102,
          "currency": "usd",
          "customer": "cus_9jWC3097MQwYwF",
          "flow": "receiver",
          "livemode": false,
          "metadata": {},
          "owner": {
            "address": null,
            "email": "amount_1000@test.com",
            "name": null,
            "phone": null,
            "verified_address": null,
            "verified_email": null,
            "verified_name": null,
            "verified_phone": null
          },
          "receiver": {
            "address": "110000000-test_12e2b7d44ea6",
            "amount_charged": 1000,
            "amount_received": 1000,
            "amount_returned": 0,
            "refund_attributes_method": "email",
    See all 45 lines "refund_attributes_status": "missing" }, "status": "chargeable", "type": "ach_credit_transfer", "usage": "reusable", "ach_credit_transfer": { "account_number": "test_12e2b7d44ea6", "fingerprint": "3eoX8Ufbxh0oVDim", "routing_number": 110000000 } } ], "has_more": false, "url": "/v1/customers/cus_9jWC3097MQwYwF/sources" }

    If the amount funded matches a non-editable (sent) invoice, the invoice will automatically transition to paid, with a corresponding Payment object containing the payment details appearing in your account.

    Questions?

    We're always happy to help with code or other questions you might have! Search our documentation, contact support, or connect with our sales team. You can also chat live with other developers in #stripe on freenode.

    Was this page helpful? Yes No

    Send

    Thank you for helping improve Stripe's documentation. If you need help or have any questions, please consider contacting support.