One-click test payment
Creates a real payment intent on the router, then opens the hosted checkout.
Same checkout the landing-page demo uses — this page just exposes the raw API and test cards.
Use 4242 4242 4242 4242, any future expiry, any CVC.
Test credentials
Publishable keys are safe in the browser. Secret keys never leave our server.
- Publishable key
loading…- API base
loading…- Checkout SDK
loading…- Create intent
POST /api/checkout-init
Test cards
Every card below is handled by the Qershi test connector. Click any number to copy it, then paste it into the checkout. Expiry: any future date. CVC: any 3 digits.
| Card number | Result | What it simulates |
|---|---|---|
| succeeds | Payment completes and is captured. | |
| succeeds | Visa-style success. | |
| succeeds | Mastercard-style success. | |
| succeeds | Amex-style success. | |
| declined | Card declined. | |
| declined | Card declined. | |
| declined | Lost card. | |
| declined | Stolen card. | |
| 3-D Secure | Authenticates, then succeeds. |
Any other number is rejected as unsupported.
Copy-paste integration
1 · Create the payment (server)
Your backend calls Qershi with the secret key. Returns a client secret.
curl -sS -X POST https://qershi.com.et/api/checkout-init \
-H 'Content-Type: application/json' \
-d '{"amount":2500,"currency":"ETB"}'
2 · Mount the checkout (browser)
Load the SDK, mount the payment element, then submit with confirmPayment().
const cfg = await (await fetch('/api/checkout-init', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ amount: 2500, currency: 'ETB' })
})).json()
await new Promise((ok, no) => {
const s = document.createElement('script')
s.src = cfg.sdk_url; s.onload = ok; s.onerror = no
document.head.appendChild(s)
})
const hyper = window.Hyper(cfg.publishable_key,
{ customBackendUrl: cfg.backend_url })
const elements = hyper.elements({ clientSecret: cfg.client_secret })
elements.create('payment', { layout: 'tabs' }).mount('#checkout')
// The payment element renders the form but has NO submit button --
// submitting is the merchant's job. Render your own and call confirmPayment().
document.querySelector('#pay-now').addEventListener('click', async () => {
const res = await hyper.confirmPayment({
elements,
confirmParams: { return_url: location.href },
redirect: 'if_required'
})
if (res.status === 'succeeded') location.replace('/thanks')
})