Guides

Encrypt Card Payments Across Multiple Payment Processors

This guide will help you build an app that processes encrypted card payments with multiple payment providers: to see what it looks like, watch this demo. Clone this GitHub repo or use the Replit to follow along.

If you're a developer building payments into your application, you may be considering Payment Card Industry Data Security Standard (PCI DSS) compliance. One way to reduce the scope of your compliance burden is to ensure that your app never touches credit card data in plaintext. This can be challenging if you need to integrate multiple payment processors and pass sensitive data to their APIs, but it's possible with Evervault's Inputs UI Component and Outbound Relay.

Check out the PCI DSS for Developers and Evervault Input documentation for more information.

This guide will walk you through building a card payments app using the Inputs UI Component (which we will refer to as Inputs from now on). Inputs encrypts customer card data and keeps it encrypted as it moves from your client to your server. You can then pass the encrypted card data to multiple payment processors, such as Checkout.com and Stripe, where Outbound Relay automatically decrypts the card details. You can add additional payment processors as needed.


Prerequisites

To run the code, you will need the following accounts:

Setting up your payments app

Clone this examples repo and open it in your favourite code editor. Navigate to the working directory.

Next, install the dependencies, which includes the Evervault, Stripe, and Checkout SDKs to encrypt and send payments. Other dependencies required are the Node Fetch module to use the Fetch API and the dotenv module to load environment variables. Then run the code.

If you don't have an Evervault app yet, you'll create one in the next step.

Create an Evervault app

You’ll need an Evervault App dedicated to this project, so let’s set that up first. Go to Evervault, and in your dashboard, click Create App.

Once you’ve created your App, click on App Settings. This will give you access to your App ID and API Key, which you will need later on to add as environment variables. You can also access your Team ID and App ID from the URL of the page you are currently on: app.evervault.com/[team_team-id]/[app_app-id]/settings.

You’re officially set up with Evervault! Now you can add Inputs.

Initialize Inputs

You’ll use Inputs to create the form that collects cardholder data. When you use Inputs, it will be served within an iFrame that is hosted on Evervault’s PCI-compliant infrastructure, so all actions on card data (like validity checks and encryption operations) only occur within an Evervault context.

Open up public/index.html, and initialize the SDK by adding your Team ID and App ID which you created in the previous section.

Now if you go to localhost:8080 in your browser, you should see the following:

Screenshot of input form

Next, you'll add in details required to use Stripe.

Add Stripe

Before you can send any payments from the server, you’re going to need a Stripe API key which you’ll store in a .env file. An example file called .env.example is included as part of the starter app, so rename it to.env.

Next, go to your Stripe API keys dashboard. You should see a Publishable key and a Secret key. Copy the Secret key.

Screenshot of Stripe dashboard

Add the STRIPE_API_KEY to the .env file. It should look like STRIPE_API_KEY="sk_test_YOUR-SECRET-KEY".

To see where you are passing data to Stripe, navigate to the paymentProviders directory and open stripe.js. You should see this at the top of the file:

This will create an instance of the Stripe object, which is your entry point to the rest of the Stripe.js SDK. You will also declare a PROVIDER_NAME of ‘Stripe’ for the logic you will add in later on to differentiate between providers.

The makePayment() method is what will send your payment to Stripe:

The Stripe paymentMethod object is part of the Payment Method API and will allow you to create a payment type of “card,” but you could also utilise this for other forms of payment such as Buy Now Pay Later, direct debit via a bank, or a digital wallet.

You then pass the ID of the paymentMethod to the paymentIntent, which will be used to initialise the payment flow within Stripe.

Now, you can finally test out the payment. Stripe has a number of test card numbers available to use. For testing purposes, let’s use:

If you try to input the test card data and click checkout, you will see in your terminal that you’re getting a 402 error. This is because the card number is currently being sent in its encrypted form, but it’s not decrypting when it reaches the Stripe API.

If you check your terminal, you should be able to see the card object printed out. You’ll notice the encrypted strings as values for both the card number and the cvc:

To fix this issue, you’ll need to enable Outbound Relay, which will decrypt the sensitive fields during the request to Stripe.

Enable Outbound Relay

To encrypt data in transit as it passes to third-party APIs, you’ll use Outbound Relay.

First add your Evervault App ID (Evervault Dashboard > Team Settings) and your Evervault API Key to the .env. This can be a key scoped specifically for Outbound Relay or can have multiple permissions as long as Outbound Relay is included.

To see where Outbound Relay is enabled in your code, open up the index.js file, and you will notice it below the PaymentProviders object:

This will enable Outbound Relay, so your card data will be decrypted (but only when it reaches the Stripe API).

The last step is to add api.stripe.com as an outbound destination in your Evervault dashboard. In your dashboard, under Outbound Relay, click Add Destination and add api.stripe.com. It should look like the below. Then, click Add Outbound Destination.

Setting up Outbound Relay

Let’s test it out to see if it works!

Try out a successful payment

Go back to http://localhost:8080/ and try sending the payment again using the card details you used previously. This time, the payment should be successful.

If you go to your Stripe payments dashboard, you will see that the payment was successfully received by Stripe.

Successful payment in the Stripe dashboard

You will also see the activity logged in your Evervault Outbound Relay dashboard for the api.stripe.com destination. If there was an error, you could see more details about what might have happened. A common error is improperly setting the host destination, so if you’re not seeing any activity in the logs, make sure the destination is defined correctly.

Outbound Relay activity log

Well done; your app should now work. If you’re interested in adding an additional payment provider, you can keep going with the guide to add Checkout.com as an additional outbound destination.

This guide does not cover implementing 3D Secure (3DS), a fraud protection measure that requires customers to complete an additional verification step with a card issuer during the payment process. This may be required for your business. Check your provider's documentation to learn more about 3DS and setup options.

Add Checkout.com

To access the checkout.com API, you will need a secret key, a public key, and a channel ID. Log in to your Checkout test account and go to the Developer Overview. Click Create a new key.

Checkout.com developer dashboard

First, create a public API key. Then paste it into your .env. It should look like CHECKOUT_COM_PUBLIC_KEY="pk_sbox_XXXXXXXXXXX”.

When you create the key, you will be given the option to allow any processing channel, or choose specific channels. For the sake of this demo, you can leave it set to “Allow any processing channel.” Find the processing channel ID next to the channel checkbox (looks like pc_XXXXXXXXX) and add it to the .env file.

Checkout.com api key creation

Repeat the process to create a secret API key. It will look like sk_sbox_XXXXXXX. Be sure to set it as an environment variable as soon as it’s displayed; you won’t be able to access it again.

Now you have everything you need to connect to the Checkout API. If you open the PaymentProviders directory and open the checkoutcom.js file you will see the code used to send a payment to Checkout.com. For additional details on the Checkout.com API, you can see the documentation for Payments here.

Nearly there! The last step is to set *.checkout.com as a destination in the Outbound Relay section of your Evervault dashboard.

Set Checkout.com as a destination in Outbound Relay

This step will look familiar. Open your Evervault dashboard again and go to Outbound Relay. Enable *.checkout.com as a destination. Note that you will use the wildcard here to select requests made to any subdomains of Checkout.com. This is because there is a slight difference between the sandbox and production domains of Checkout.com, but if we use this configuration, it will handle both.

If you have multiple Evervault apps, be sure you are in the one you set up at the beginning of the guide.

Make a test payment using the same credit card number 4242424242424242. This time, it should route to Checkout.com. If you check your Checkout.com payments dashboard, you will see the transaction went through.

Checkout.com successful payment

You now have a feature that processes encrypted payments across multiple payment service providers!

Conclusion

In this guide, you built a fully encrypted card payments feature across multiple payment processors using Evervault Inputs and Outbound Relay, Stripe, and Checkout.com. If you ran into an issue or have any questions about this guide, feel free to raise them on GitHub. Happy Encrypting!