Migrating from Card 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 using our /payment_methods endpoint, you should be able to send the stripe_id: paymentMethod.id instead of the stripe_token: token.token.

// 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

Currently, the Hint API /cards endpoint can accept either stripe_token or stripe_id to create Cards for patients, but moving forward, we will be deprecating /cards endpoint in favor for /payment_methods which will no longer accept stripe_token and only accepts stripe_id generating through PaymentMethod.

stripe_token is no longer being returned in the GET response.

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

In summary:

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

Additional Resources