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:
- A secret key (
kashu_sk_test_...) for your server. - A publishable key (
kashu_pk_test_...) for your page, made with the origins the form may appear on:
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.