Accept a payment
The end-to-end flow for charging a diner at a venue: tokenize in the browser, charge on the server, settle on the webhook.
The flow
- The diner enters their card in
yusker.jshosted fields → you get a single-use token. - Your backend exchanges the token for a Payment Instrument.
- Your backend creates a Transfer against the venue's merchant with your platform fee.
- Yusker sends a webhook when the transfer settles — you close the check and reconcile.
1 · Collect the card (browser)
<div id="card"></div>
<script src="https://js.yusker.com/v1"></script>
<script>
const form = Yusker.tokenizationForm({ container: "#card", environment: "sandbox" });
document.querySelector("#pay").onclick = async () => {
const { token } = await form.submit(); // "TKxxxx"
await fetch("/api/checkout", {
method: "POST",
body: JSON.stringify({ token, check_id: "4823" }),
});
};
</script>2 & 3 · Exchange + charge (server)
// POST /api/checkout
const { token, check_id } = req.body;
const auth = { Authorization: "Basic " + Buffer.from(process.env.YUSKER_KEY).toString("base64") };
// exchange the token for a reusable instrument
const pi = await api("/payment_instruments", { type: "TOKEN", token, identity: buyerId });
// charge: fee computed on the full amount (bill + tip + tax)
const transfer = await api("/transfers", {
merchant: venue.merchant_id,
source: pi.id,
amount: 5000, // $50.00
fee: 175, // 2.90% + $0.30
currency: "CAD",
idempotency_id: `check_${check_id}`,
tags: { check_id },
});
// transfer.state === "SUCCEEDED"Settle on the webhook, not the response
The API response tells you the transfer was accepted. The webhook is the authoritative settlement signal. Mark the check paid when you receive
transfer.succeeded — and make it idempotent, since webhooks can be redelivered.4 · Settle (webhook)
// POST /webhooks/yusker
app.post("/webhooks/yusker", (req, res) => {
if (!verifyYuskerSignature(req)) return res.sendStatus(401);
for (const event of req.body.events) {
if (event.type === "transfer.succeeded") {
closeCheck(event.transfer.tags.check_id); // idempotent
}
}
res.sendStatus(200);
});See Webhooks for signature verification and the full event list, and Testing for sandbox test cards that force each outcome.