NATURAL_API_KEY to your Sandbox API key and call https://api.sandbox.natural.com. Before you take real payments, add your site.
Create the intent
Create the intent on your server withPOST /payment-intents.
data.attributes.clientSecret. Store data.id with the order, and send the secret to the browser. Treat it like a password. Don’t log it or put it in a URL.
Add the form to your page
clientSecret Promise once, outside render. A new clientSecret or theme mounts a new form. PaymentForm removes the form when it unmounts. It works with server rendering, Strict Mode, and the Next.js app router.
Confirm the payment
When the payer is done,onComplete gets { paymentIntentId, status }. It fires once. If the intent had already finished when the form mounted, it fires right away, so a payer who presses Back to your checkout page sees your confirmation again.
Show your confirmation on
onComplete. Don’t ship the order from there. Ship it when the paymentIntent.completed webhook arrives on your server. The webhook arrives even if the payer closes the page.
A processing payment can still fail. If it does, you get a cardPayment.failed webhook and the intent goes back to open. The form keeps showing “Payment processing”. To let the payer try again, render PaymentForm with a new key.
Handle errors
WhenonError fires, the form is done. It can’t take a payment anymore. To try again, render PaymentForm with a new key.
An error is a plain { code, message } object. Match on code. We never rename or remove a code, but we do add new ones, so handle a code you don’t know. The message is for your logs. Its wording can change.
A problem the payer can fix, like a declined card, shows inside the form. It doesn’t call onError.
Show the order on your page
The form shows the total, your business name, and your policies. Make sure your page shows:- Each item, any tax or fee, and the total with its currency, matching the intent’s
amount - Your country, and an email address or phone number for support
- Your delivery policy, if you ship goods
Match your page
The form has no background of its own. Its Pay button uses the brand color from your Natural account. On a dark page, passtheme="dark":
Place the form
- The form grows to fit what it shows. Don’t give
PaymentFormor its parents a fixed height withoverflow: hidden. - Size and position the form with
classNameonPaymentForm.natural.jssets the size of its own frames. - Popups, such as a 3-D Secure challenge or a sign-in code, open over your whole page.
- Serve your page over HTTPS. The form doesn’t load on plain
http, except onlocalhostin Sandbox.
Test in Sandbox
Your page code doesn’t change between Sandbox and live. The secret tells the form which one it’s in. Pay with the test cards. When the form asks for a code, to save a card or to sign in, enter000000.
Sandbox skips the 3-D Secure challenge popup, Apple Pay, Google Pay, and the receipt email.
Go live
Create the intent with your production API key athttps://api.natural.com. Then list every site that shows the form. Open Developers, then API keys, and add them under Checkout domains.
A site is a scheme, host, and port, like https://shop.example.com. Browsers treat example.com and www.example.com as two sites, so list both if you use both. If you’re a platform, your sites cover the intents you create for your merchants. On a site you haven’t listed, onError gets domain_not_allowed.
Content Security Policy
If your page sets a Content Security Policy, allow Natural’s checkout origin inscript-src and frame-src:
natural.js makes no network requests from your page and adds no styles. PaymentForm adds the natural.js script tag without a nonce. If your policy uses nonces, keep the source above or add 'strict-dynamic'. If your page enforces Trusted Types, allow the one policy PaymentForm creates:
Browser support
The form opens no popup windows, so it works in webviews and in-app browsers. Apple Pay and Google Pay may not appear there.