# Taking payment with Elements

> The pay button, your own button with confirmPayment(), gateways that open their own window, returnUrl, edit() and test mode.

Source: https://shopfa.st/docs/elements/payments

## 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:

```js
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](https://shopfa.st/docs/elements/styling) can hide or change that amount.

## Your own button

```js
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.

1. **Free orders** (a gift card or a 100% discount) are paid on the spot.
2. **Test mode**: the payment element shows the test card and the result is immediate. See [Test mode](#test-mode).
3. **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:

```text
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 the `payButton` or
> `checkout` element 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:

```js
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.
