Collecting payment information [NEW as of 2024]

Hint supports 2 ways to gather payment information: manual entry of card and bank information, or verifying bank information with bank login data. In order to collect payment information you will use Stripe Payment Elements & Setup Intents. It will create the input fields and/or login to the bank, tokenize the information and return it via javascript.

πŸ“˜

At a high level

You will need to use our setup endpoint in order to create SetupIntents. The setup intent response will return a client secret, which you can use to instantiate the Stripe Elements form. You can then have your customers fill out their credit card or bank account details directly with Stripe, and Stripe returns a stripe_id after the payment method is created and the setup intent is confirmed successfully. This stripe_id is needed to create a PaymentMethod in Hint.

We will walk through each of these individual steps below.

Step 1: Creating a Setup Intent using Hint's setup endpoint

Full documentation: POST /setup

The /setup endpoint is a POST that accepts the following required attributes:

accepts_bank boolean

  • true will allow the elements iframe to show the option of adding bank account
  • false will only show the card option in the iframe

user_is_owner boolean

  • true should be used if the patient is the primary user of the form, since they will be given the option to log in to their bank directly.
  • false used when filling the elements iframe form on behalf of the patient

You will need to use the stripe_client_secret returned in the response for the following steps.

Step 2: Using the StripeClientSecret from the SetupIntent to instantiate the Stripe Elements form and confirm the SetupIntent created in Step 1

The goal here is to provide a UI form for your customers to enter their credit card or bank account information directly to Stripe. Stripe offers a customizable form using their Payment Elements embeddable UI component. A form example can be viewed here: https://stripe.com/docs/payments/payment-element

After you create the SetupIntent, attach a payment method and confirm it to collect any required permissions to charge the payment method later.

We have provided a sample example of how we use it on the Hint platform below:

πŸ‘

Use Hint's Public Keys

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/payment-element#create-a-payment-element
// https://stripe.com/docs/payments/payment-element
// https://stripe.com/docs/payments/quickstart
// https://github.com/stripe-samples/accept-a-payment/tree/main/payment-element


// Create a Stripe client.
const stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx');

// customization
const appearance = { /* appearance */ };
const options = { /* options */ };

// Create an instance of Elements.
// https://stripe.com/docs/js/elements_object/create
const elements = stripe.elements({ clientSecret, appearance });

// Create an instance of the payment element.
// https://stripe.com/docs/js/elements_object/create_payment_element
const paymentElement = elements.create('payment', options);

// Add an instance of the payment element into the `payment-element` <div>.
paymentElement.mount('#payment-element');

// Handle form submission.
// https://stripe.com/docs/js/setup_intents/confirm_setup
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
  event.preventDefault();
  
  stripe.confirmSetup({
     elements,
     confirmParams: {
        // Return URL where the customer should be redirected after the SetupIntent is confirmed.
        return_url: 'https://example.com',
     }, 
     redirect: "if_required", // only redirect if needed for 3d secure
  }).then(({ error, setupIntent }) => {
     if (error) {
        // Handle the error
     } else {
        // From the setupIntent object, obtain the "payment_method" attribute, 
        // which will be the ID of the payment method used with this SetupIntent 
        // (see Stripe Documentation here: https://stripe.com/docs/api/setup_intents/object#setup_intent_object-payment_method
     }
  });
});

Step 3: Save the payment method to the Hint patient

❗️

Do Not Send Hint Sensitive Payment Details

Sensitive payment details like card numbers and bank account numbers should never be sent to Hint. If you are collecting payment details, they should always be sent to Stripe first, so they can be tokenized, and then you send the token to Hint.

Unless you are PCI compliant, you probably don't want card/bank numbers to hit your servers either, which is why the Stripe Elements library sends this information from the user's client directly to Stripe (more detail here: https://stripe.com/docs/security)

Full documentation: POST /payment_method

You must attach this payment information to a patient and you can do this through the POST /payment_method endpoint. You are required to send the payment_method returned in step 2 after confirming the SetupIntent as stripe_id to the POST request. The payment_method object should look something like pm_abc123de546789.

This creates a payment method in Hint. Hint will return the newly created payment method information with the following response:

// BankAccount
{
  "id": "bnk-ab12C345DeF6",
  "default": true,
  "last_four": "4123",
  "name": "Bank of America NA",
  "type": "bank_account",
  "bank_account": {
    "id": "bnk-ab12C345DeF6",
    "last_four": "4123",
    "name": "Bank of America NA",
    "stripe_token": "tok_1234",
    "type": "BankAccount"
  },
  "card": null
}


// Card
{
  "id": "card-ab12C345DeF6",
    "default": false,
    "last_four": "4123",
    "name": "Visa",
    "type": "card",
    "bank_account": null,
    "card": {
      "id": "card-ab12C345DeF6",
      "card_type": "visa",
      "exp_month": 7,
      "exp_year": 2017,
      "last_four": "4123",
      "name": "Visa",
      "type": "Card"
    }
}

All Done :tada:

After you've created the payment method on the Hint patient and received the successful response, no further action is needed.

πŸ“˜

Important Note

We send an email notification to the patient email address on file when a new bank account is added to their Hint account. This is a requirement from Stripe based on their interpretation of NACHA guidelines.

Testing Cards

You can use anything for the zip code and cvc check. Expiration dates can be any future date.

4242424242424242 Visa - Successful
5200828282828210 Mastercard (debit) - Successful
378282246310005 American Express - Successful

4000000000000002 Charge is declined with a card_declined code.
4000000000000127 Charge is declined with an incorrect_cvc code.

Testing Bank Accounts / ACH

You can mimic successful and failed ACH charges using the following bank routing and account numbers:

  • Routing number: 110000000
  • Account number:
    • 000123456789 (success)
    • 000111111116 (failure upon use)
    • 000111111113 (account closed)
    • 000222222227 (NSF/insufficient funds)
    • 000333333335 (debit not authorized)
    • 000444444440 (invalid currency)