Migrating from Stripe Tokens to Payment Methods

As of April 2020, our payment service has been updated to leverage Stripe's Payment Methods instead of Tokens using Card Sources. The following guide details the change and subsequent steps to update your code.

🚧

This is a technical document

This abides by the best practices recommended in the latest release of the Stripe API. This tutorial is intended for those with a working understanding of our current behavior and can make the necessary changes.

Background

PaymentMethod objects represent your customer's payment instruments. They can be used with PaymentIntents to collect payments or saved to Customer objects to store instrument details for future payments.

Key Attributes

  • id (string): Unique identifier for the object
  • card (hash): Card information containing the user card details
  • billing_details: Billing information associated with the PaymentMethod that may be used or required by particular types of payment methods.

Updating your code

Use createPaymentMethod instead of createToken. This will return an object with a paymentMethod property instead of token, with almost the same properties. The primary difference is that while token contains a token, payment methods have an id.

When attaching a card to a Patient with our /cards endpoint, you should be able to send the stripe_id: paymentMethod.id instead of the stripe_token: token.token and expect the same response.

// Stripe Production Public Key: 'pk_live_ImPWqYGkbMfjwg22MiAmB6u4'
// Stripe Test Public Key: 'pk_test_Y7byiIyWmjqy4Xy7fjArJdPl'
// Test card/bank numbers: https://stripe.com/docs/testing#cards
// Code Example Adapted From: https://stripe.com/docs/payments/cards/collecting/web
// https://stripe.com/payments/elements
// https://stripe.dev/elements-examples/

// BEFORE 

stripeClient.createToken(
  cardElement, extraParams
).then({ error, token }) {
  if (error) {
    deferred.reject({ data: { message: error.message }});
  } else {
    deferred.resolve(token);
  }
});

translateCardToken(stripeToken) => {
  return {
    stripe_token: stripeToken.id,
    last_four:    stripeToken.card.last4,
    card_type:    stripeToken.card.brand,
    exp_month:    stripeToken.card.exp_month,
    exp_year:     stripeToken.card.exp_year,
  };
}

// AFTER

stripeClient.createPaymentMethod(
    // Billing Details hash is optional - https://stripe.com/docs/api/payment_methods/create#create_payment_method-billing_details
    { type: "card", card: cardElement, billing_details: extraParams }
).then(({ error, paymentMethod }) => {
  if (error) {
    // Display error.message in your UI.
    deferred.reject({ data: { message: error.message }});
  } else {
    // The payment has succeeded
    // Display a success message
    deferred.resolve(paymentMethod);
  }
});

translatePaymentMethod(paymentMethod) => {
  return {
    stripe_id: paymentMethod.id,
    last_four: paymentMethod.card.last4,
    card_type: paymentMethod.card.brand,
    exp_month: paymentMethod.card.exp_month,
    exp_year:  paymentMethod.card.exp_year,
  };
}

❗️

Deprecations for stripe_token and shared attributes

Currently, the Hint API can accept either stripe_token or stripe_id to create Cards for patients, but moving forward, we will be deprecating use of stripe_token in favor of stripe_id generating through PaymentMethod. We recommend passing stripe_id for POST on /cards.

For the time being, we will be returning stripe_token in the GET response, but this will also be deprecated in the coming months.

The shared attribute, which previously indicates if you are creating it with the Hint Stripe publishable key, on Card will also be deprecated. As long as you're using the Stripe publishable key as noted in the example above to create your Stripe PaymentMethods, you do not need to pass the shared: true attribute to our cards endpoint to attach the resulting PaymentMethod to the Patient.

We advise prioritizing the changes to your application to ensure no disruption in connectivity.

In summary:

  • /cards POST:
    • use stripe_id instead of stripe_token
    • removal of shared
  • /cards GET: removal of stripe_token

Additional Resources