Taking payment with Elements
The pay button, your own button with confirmPayment(), gateways that open their own window, returnUrl, edit() and test mode.
The pay button
The checkout element has its own pay button and runs the whole payment. With split elements, mount payButton
where you want it:
elements.create("payButton").mount("#pay");
It shows the total your store worked out (“Pay $24.00”, in your checkout’s own words), and nothing in Styling can hide or change that amount.
Your own button
document.querySelector("#buy").addEventListener("click", async () => {
const result = await shopfast.confirmPayment({ elements, returnUrl: "https://yourshop.com/thanks" });
if (result.error) return showError(result.error.message);
showThanks(result.order.number);
});
confirmPayment checks what the buyer filled in, starts the order on your store and resolves when it is paid
({ order }) or stops ({ error }). Call it inside the click handler, before any await: gateways that need their own
window can only open one during a click.
What happens when the buyer pays
Every payment goes through your store’s own checkout: the same Fraud Shield checks, sanctions, tax, discounts, gift cards, order limits and ways to pay as on your store. Elements never decide a price.
- Free orders (a gift card or a 100% discount) are paid on the spot.
- Test mode: the payment element shows the test card and the result is immediate. See Test mode.
- Gateways with their own page (PayPal, Stripe’s card step, crypto, manual methods): Elements open a small
payment window from your store during the click, then send it to the gateway. Your page fires
navigate, the elements show “Finish paying in the new window”, and they update by themselves when the payment goes through. The window shows the buyer’s order page at the end.
If the browser blocks the window, the payment element shows an Open payment window button (a click the browser
allows). With returnUrl, the whole tab goes to pay instead and comes back to your page:
https://yourshop.com/thanks?shopfast_checkout=…
Load Elements on that page as usual: the script reads shopfast_checkout, removes it from the address bar, and
fires complete once the store confirms the payment. returnUrl must be on the same site as the page that started
the payment.
Note When your own button calls
confirmPayment()for a gateway with its own window, your page opens that window and holds its address for a moment, a one-time link that expires in 15 minutes. Use thepayButtonorcheckoutelement if you would rather your page never sees it.
The EU and UK box
Buyers in the EU, the EEA and the UK must ask for immediate delivery and acknowledge that their 14-day right to cancel
ends once it starts. The consent and checkout elements show the box exactly as your store’s checkout does: for the
country picked, and always for buyers connecting from those countries. Your store refuses the payment without it, so
mount one of them. The waiver event tells you when the box shows or becomes required.
Letting the buyer change their mind
Once a payment has started the cart is locked, so a buyer who spots a typo is not stuck:
elements.edit(); // unlocks the form and goes back to it
The payment element offers the same with Change details while the payment window is open. If the buyer still pays
in the old window, complete fires as usual.
Test mode
While your store is in test mode (turn on Test mode in Money → Payments for 1, 24 or 72 hours), every checkout runs on simulated payments and is marked as a test, and any website may show your elements.
The payment element shows a test card instead of card fields:
| Card number | Expiry | CVC |
|---|---|---|
4242 4242 4242 4242 |
12 / 34 |
123 |
and lets you pick what the simulated processor answers:
| Test outcome | Result |
|---|---|
| Approve | Paid: complete fires with test: true |
| Decline | error with payment_declined |
| Provider error, Outage | error with payment_failed |
| Risk decline | error with payment_declined |
Test orders are recorded as tests: keys are TEST- placeholders and nothing is paid out.