Photo by Christian Wiediger on Unsplash

Tips for Amazon Pay. How to Add Amazon Pay with React.js and Node.js Using v2.

Here is how to implement version 2 of Amazon Pay on your website, explaining both one-time and recurring payments.

Ryohei Arai
7 min readJun 6, 2022

--

Nowadays, integrating a payment system into an application has become a lot easier than ever before. Thanks to constantly evolving technologies.

In this article, I would like to introduce how to add Amazon Pay of version 2 to your application. I previously implemented Google Pay and Apple Pay with Stripe so I expected that the implementation of Amazon Pay would be the same as Google Pay and Apple Pay with Stripe, but it was quite different and a bit confusing to me.

So let me put down and share what I learned through the Amazon Pay implementation here.

Prerequisite

The technologies used in this article are;

  1. TypeScript
  2. React.js / Node.js
  3. Amazon Pay SDK

Introduction

Amazon Pay offers two ways of payment integration: one-time and recurring. The difference between them is explained, followed by the actual implementation.

*Please note that for this article I only explain One-Time payment implementation. In the future, an article on recurring payment may be written.

How It Works

First, let me briefly explain the mechanism of Amazon Pay.

Amazon Developer Intro to Amazon Pay | Amazon Pay

When a customer clicks an Amazon Pay button on a website, it redirects the customer to Amazon’s hosted website to start a checkout session.

Within the checkout session, the customer can edit customer information and make a payment.

After selecting the address and card, the customer data becomes accessible via the checkout session object on your website.

Then, you can complete the payment.

Having said that, now let me break down the difference between one-time and recurring slicing it into two sections.

One-Time

When an Amazon Pay button is pressed, a checkout session gests started. As long as the checkout session does not expire, the session id is valid meaning it is in a purchasable state.

Neither credit card nor address is necessary to be stored in the database for future use as redirecting to Amazon’s hosted website is always necessary to make a payment. You can obtain personal data at the same time.

Going through the checkout session flow is required every time a customer purchases a product.

After payment goes successful, completed transaction data becomes accessible using ChargePermissionId which is included in the completed session object. The permission id is unique to every checkout session.

When payment does not need to be captured instantly after a credit card is authorized, the permission id can be used to capture the authorized funds later. Keep the permission id somewhere in your database if so.

Recurring

By contrast, recurring payment does not require you to follow the flow every time a customer purchases a product. However, the initial payment flow must be completed via the checkout session flow.

After the initial transaction successfully completes, similarly, a unique ChargePermissionId is generated. But what is different from one-time payment is that all payments can be done at any arbitrary time on your server with the permission id.

Payments can be done at any arbitrary time.

However, if customer information used for the current checkout is changed, completing the checkout session again is required to issue a new fresh permission id.

In addition, Amazon does not automatically handle recurring payments. If you are familiar with payment providers such as Stripe and Square, please note that there is no concept of Webhook so you need to implement your own subscription system.

Implementation

Now let’s implement Amazon Pay.

Amazon has its detailed integration documentation, so please refer to its documentation as well as mine. I hope my article can illustrate a practical example and extend some explanations that the doc does not include.

Generate Signature

With Cloud Functions I am using, credential data should be accessed via the config because private data must not be disclosed. For the store id and public id, please open your Seller Central Manager account. Copy and paste them.

The above code generates a signature. Without a valid signature set to an Amazon Pay button, the initial redirect to Amazon’s hosted page to start a checkout session fails — a checkout session cannot begin.

For the webCheckoutDetails, please specify URLs for each returning destination URL that Amazon automatically redirects to.

Scopes define what access you want to obtain from a customer. The logged-in customer data gets accessible from a checkout session object. You can use “buyer ID” to access the data anytime if the customer is already logged in via the Amazon Pay button.

Also, note that the signature and the payload are passed to the front end from the server because the Amazon Pay button requires the same configuration objects in both the front and back ends.

A slight setup difference triggers an error so please be careful about the setup implementation. Of course, the same configuration objects can be set separately, but I think it is better to manage it from one single place.

Amazon Checkout API

Amazon’s Checkout Javascript API needs to be loaded first using the script tag below. Please add the line replacing the region at the root HTML page.

<script src="https://static-{YOUR REGION HERE}.payments-amazon.com/checkout.js"></script>

It currently supports regions for US, EU/UK, and JP; na, eu, and fe respectively.

Render Amazon Pay

Please callrenderButton method of the Checkout API to display Amazon Pay. After the window and amazon pay objects appear, you can use the custom hook I created below.

And use this hook on your review page to check if renderButton is shown.

You need to create a div with an ID that is the same as the ID of renderButton method on the same page. I named it “#AmazonPayButton” but you can call it whatever id you prefer.

After the response data containing the signature and payload is fetched from the server, then put in the dependency list to trigger a useEffect function to render the renderAmazonButton so that your Amazon Pay button should be visible on your website.

After you are taken to the Amazon’s hosted website and a new checkout session starts, you are automatically redirected back to the checkoutReviewReturnUrl set in the configuration explained above.

The URL will contain amazonCheckoutSessionId so please parse it to extract the session id.

Render Edit Buttons

Likewise, address and payment editing buttons are renderable calling BindChangeAction method. As you did in the previous step above, please create divs again that share the same IDs with respective “bindChangeAction”s so that changes can be made on Amazon’s hosted website.

Now, let’s finalize the checkout with a few more steps 💰💰💰

Set up Payment Intent

Make sure that the session object has valid “Payment Details” when executing a payment. Otherwise, Amazon throws an error. So what you need to do is to update your session data to fulfill the requirement with the required values.

As I have explained in the above section, if you want to authorize a card and capture funds at the same time, you can use AuthorizeWithCapture payment intent. If you want to only authorize a card and capture funds later, then Authorize. Or, Confirm if you want to authorize and capture them later. As a side note, Confirm can be useful if your service offers a free trial period feature.

When the checkout session state gets updated, AmazonPayredirectUrl should be passed via the session data. The URL is only provided by Amazon.

Customers must redirect to the URL page right after updating transaction details such as charge amount, payment intent, and others that are required fields in the “paymentDetails”.

Amazon does not automatically trigger any redirect to the Amazon pay redirect URL. Without the redirect, calling completeCheckoutSession back-end function to finalize the payment fails. Please be careful about this!

Validation

Also, please pay attention to constraints in the session’s object. It must be empty when a payment is executed.

You can validate it from session data. To get your session data, you can call getCheckoutSession. For example, if the charge amount is not set or it is set to zero, the constraints will include “ChargeAmountNotSet”.

Please validate each constraint in the array before you call the complete checkout session method.

If the constraints array is empty, it means you are now ready to make a payment!

Finalize Payment

To complete the checkout session, please collect the session id, the charge amount, and the currency code. And then execute the payment.

*Again, ensure that a customer is taken to AmazonPayredirectUrl before finalizing the checkout. Otherwise, it throws an error.

Additionally, after the payment is executed, please confirm that the status is “Completed”. If it is not, a charge has yet to be captured.

There are multiple error cases provided for this when the status is not completed. It includes “BuyerCanceled”, “Expired”, “AmazonCanceled”, and “Declined”.

As I mentioned in the payment type difference section above,

As long as the checkout session does not expire, you can make a purchase with the session id.

So, for example, if the payment is attempted while a checkout session expires, the status is “Expired”. In this case, recreate a new checkout session and use the new session id for the payment.

Please keep in mind that there are multiple error cases after executing the payment so it s important to handle them accordingly.

If your payment status is Completed, congratulations, you have successfully completed integrating Amazon Pay v2 into your website!

And here is the Amazon Pay Node API class I made.

That’s it!

I am in the middle of writing other articles related to e-commerce and payment right now as well, so please feel free to follow me to get notified instantly when my future articles are ready.

--

--

Ryohei Arai

I like startup / fintech / commerce / productivity