KashuDocs

Take card payments in your page

Kashu.js puts Kashu's card form in your checkout page. The buyer types their card into the form, which sits in a frame served by Kashu, so the card number never touches your page or your servers. You get back either a paid checkout session or a card token you can charge from your server.

Before you start

You need two keys from the same mode:

curl https://api.kashupay.com/v1/api_keys \
  -H "Authorization: Bearer $KASHU_SECRET_KEY" -H "Content-Type: application/json" \
  -d '{"type":"publishable","allowed_origins":["https://shop.example.com"]}'

An origin is a scheme, host and port, with no path: https://shop.example.com, or https://shop.example.com:8443. A test key may also name http://localhost or http://127.0.0.1, with a port, while you build. The form refuses to load on any other page. To add an origin, make a new publishable key with the full list and revoke the old one; rolling a key keeps its origins.

Option 1: take payment for a checkout session

Your server makes a session for the amount due and hands its client secret to the page. Kashu's form shows the amount, takes the card and pays the session:

<div id="card"></div>
<script src="https://api.kashupay.com/v1/kashu.js"></script>
<script>
  var kashu = Kashu("kashu_pk_test_...");
  kashu.mount("#card", { clientSecret: session.client_secret });
</script>

Once the session is paid, Kashu.js sends the buyer to your success_url. Pass onComplete to stay on the page instead: kashu.mount("#card", { clientSecret: session.client_secret, onComplete: function (result) { ... } }), where result holds session, paymentStatus and returnUrl.

Checkout sessions covers making a session, its statuses and how to fulfil the order.

Option 2: a card token for your own flow

Mount the form without a client secret, and ask it for a token when the buyer submits your own form:

<form id="order">
  <div id="card"></div>
  <button type="submit">Place order</button>
</form>
<script src="https://api.kashupay.com/v1/kashu.js"></script>
<script>
  var kashu = Kashu("kashu_pk_test_...");
  kashu.mount("#card");
  document.getElementById("order").addEventListener("submit", async function (event) {
    event.preventDefault();
    try {
      var token = await kashu.createToken();
      await fetch("/orders", { method: "POST", body: JSON.stringify({ card: token.id }) });
    } catch (error) {
      // error.code is card_invalid when the card as typed cannot be used; ask the buyer to check it.
    }
  });
</script>

A card token (tok_...) can be used once, within 15 minutes. Spend it from your server, either to charge it:

curl https://api.kashupay.com/v1/payments \
  -H "Authorization: Bearer $KASHU_SECRET_KEY" -H "Idempotency-Key: order-1001-charge" -H "Content-Type: application/json" \
  -d '{"amount":4999,"currency":"USD","customer":"cu_...","token":"tok_..."}'

or to save the card for the customer and charge it later with its pm_ id:

curl https://api.kashupay.com/v1/payment_methods \
  -H "Authorization: Bearer $KASHU_SECRET_KEY" -H "Idempotency-Key: order-1001-card" -H "Content-Type: application/json" \
  -d '{"customer":"cu_...","token":"tok_..."}'

The customer needs an email. A charge with a token saves the card for the customer too, so the payment names a payment_method you can charge again. A token used twice is token_already_used, an old one token_expired, and a token of another account or mode is resource_missing. Retry a request with the same Idempotency-Key and you get the same object back; a token is spent once whatever the retries.

Kashu.js reference

Call What it does
Kashu(publishableKey) Starts Kashu.js with your publishable key.
kashu.mount(target, options) Puts the card form in target (a selector or an element). options.clientSecret takes payment for a session; options.onComplete replaces the redirect. Mounting again replaces the form. Returns the form.
kashu.createToken() Resolves { id: "tok_..." }, or rejects with an error whose code says why.
form.on("ready" | "complete" | "error", handler) Runs handler when the form loads, when a session is paid, or when the form reports a problem.
form.unmount() Takes the form out of the page.

Kashu.js talks to the form only on Kashu's own origin, and takes a message only from the frame it made. The form answers only the page origin it was opened on, and only when that origin is one of your key's allowed origins.