Card Payments (Visa / Mastercard)
Accept Visa and Mastercard payments
Overview#
Yassir Payment accepts Visa and Mastercard card payments. Card payments reuse the same endpoints as every other payment method: you create a payment intent, proceed with the card payment method, and check the result. The only card-specific piece is where the card details are entered.
Card details never touch your servers
The card payment method#
The card payment method has its own code, which you use as paymentMethodCode when you proceed with a payment. To get the exact value for your service and country, call List Payment Methods and read the code of the card option rather than hard-coding it.
Two ways to pay by card#
| Flow | When to use | What the buyer enters |
|---|---|---|
| New card | The buyer is paying with a card that is not saved to their account. | Full card details on the Yassir-hosted page (number, expiry, CVC), plus any 3D Secure challenge. |
| Saved card | The buyer previously paid with a card and it was saved to their account. | Nothing, in most cases — you charge the saved card by its cardId. The issuer may still require a 3D Secure step. |
There is no “saved card + CVV only” step
cardId. If the card's issuer requires re-authentication, the response carries a payUrl for a 3D Secure challenge (statusCode 12) — not a CVV field.New card flow#
Use this flow when the buyer enters a card for the first time. You never handle the raw card details — Yassir hosts the card-entry page.
- Create a payment intent —
POST /payments/intentswith the amount and currency. You get back apaymentIdand aclientSecret. - Proceed with the card method —
POST /payments/intents/:id/proceedwith the cardpaymentMethodCodeand aredirectUrl(where the buyer should land after paying). The response hasstatusCode: 12,require3DS: true, and apayUrlinmetadata. - Redirect the buyer to
payUrl— this is the Yassir-hosted card page. The buyer enters their card and completes any 3D Secure challenge there. - Finalization is automatic — once the card is confirmed, the hosted page finalizes the payment with Yassir for you. You do not call anything here.
- Buyer is redirected back — on success, the hosted page sends the buyer to your
redirectUrlwith?status=success&paymentId=<paymentId>appended. - Confirm the result — call
GET /payments/intents/:id/checkor rely on the webhook. AstatusCodeof2means the payment succeeded.
// 2. Proceed with the card method
POST /api/v1/payments/intents/{paymentId}/proceed
Headers:
Authorization: Bearer base64(client_id:client_secret)
x-client-secret: pa_{id}_secret_{hex}
x-service: YOUR_SERVICE
x-platform: API
Body:
{
"paymentMethodCode": "STRIPE", // the card method code from List Payment Methods
"redirectUrl": "https://yourapp.com/checkout/return"
}
// Response — buyer must be redirected to the hosted card page
{
"data": {
"require3DS": true,
"statusCode": 12,
"status": "Require card details",
"metadata": {
"payUrl": "https://<yassir-hosted-card-page>/..."
}
},
"message": "payment proceeded successfully"
}
// 3. Redirect the buyer
window.location.href = response.data.metadata.payUrl;// 2. Proceed with the card method
POST /api/v1/payments/intents/{paymentId}/proceed
Headers:
Authorization: Bearer base64(client_id:client_secret)
x-client-secret: pa_{id}_secret_{hex}
x-service: YOUR_SERVICE
x-platform: API
Body:
{
"paymentMethodCode": "STRIPE", // the card method code from List Payment Methods
"redirectUrl": "https://yourapp.com/checkout/return"
}
// Response — buyer must be redirected to the hosted card page
{
"data": {
"require3DS": true,
"statusCode": 12,
"status": "Require card details",
"metadata": {
"payUrl": "https://<yassir-hosted-card-page>/..."
}
},
"message": "payment proceeded successfully"
}
// 3. Redirect the buyer
window.location.href = response.data.metadata.payUrl;Setting the redirect URL#
Pass a redirectUrl in the proceed request body. It is where the buyer's browser is sent after they finish on the hosted card page. It must be an http or https URL. If you omit it, Yassir falls back to the deep link configured for your service.
What comes back on the redirect URL#
| Outcome | What happens |
|---|---|
| Success | The buyer is redirected to <redirectUrl>?status=success&paymentId=<paymentId>. paymentId is the Yassir payment intent ID. |
| Failure / card declined | The buyer is not redirected. The hosted page shows an inline error and lets them retry on the same page. There is no status=failed redirect. |
// Successful payment redirect:
https://yourapp.com/checkout/return?status=success&paymentId=123e4567-e89b-12d3-a456-426614174000
// Your handler:
const params = new URLSearchParams(window.location.search);
const paymentId = params.get('paymentId');
// The redirect is a UX signal only. Always confirm server-side
// before fulfilling the order:
GET /api/v1/payments/intents/{paymentId}/check
// → statusCode: 2 (succeeded)// Successful payment redirect:
https://yourapp.com/checkout/return?status=success&paymentId=123e4567-e89b-12d3-a456-426614174000
// Your handler:
const params = new URLSearchParams(window.location.search);
const paymentId = params.get('paymentId');
// The redirect is a UX signal only. Always confirm server-side
// before fulfilling the order:
GET /api/v1/payments/intents/{paymentId}/check
// → statusCode: 2 (succeeded)Always verify server-side
Saved cards#
When a buyer pays with a new card, that card is saved to their account automatically for future payments (Yassir keeps a reference with the brand and last four digits — never the full number or CVV). You can then charge it again without the buyer re-entering anything.
- List the buyer's saved cards — call GET /payment-methods (with user context) or GET /cards. Saved cards appear as items with
paymentOptionType: "card"and a display name like"visa *** 3456". - Proceed with the saved card —
POST /payments/intents/:id/proceedwith the cardpaymentMethodCodeand thecardIdof the chosen card. - Handle the result — if the card is charged directly you get
statusCode: 2. If the issuer requires re-authentication, you getstatusCode: 12with apayUrl; redirect the buyer there to complete 3D Secure.
// Charge a saved card — no card details, no CVV
POST /api/v1/payments/intents/{paymentId}/proceed
{
"paymentMethodCode": "STRIPE", // the card method code from List Payment Methods
"cardId": "d290f1ee-6c54-4b01-90e6-d701748f0851"
}
// Success — charged directly
{
"data": { "statusCode": 2, "status": "The amount was deposited successfully" },
"message": "payment proceeded successfully"
}
// Issuer requires 3D Secure — redirect the buyer to payUrl
{
"data": { "statusCode": 12, "metaData": { "payUrl": "https://..." } },
"message": "payment proceeded successfully"
}// Charge a saved card — no card details, no CVV
POST /api/v1/payments/intents/{paymentId}/proceed
{
"paymentMethodCode": "STRIPE", // the card method code from List Payment Methods
"cardId": "d290f1ee-6c54-4b01-90e6-d701748f0851"
}
// Success — charged directly
{
"data": { "statusCode": 2, "status": "The amount was deposited successfully" },
"message": "payment proceeded successfully"
}
// Issuer requires 3D Secure — redirect the buyer to payUrl
{
"data": { "statusCode": 12, "metaData": { "payUrl": "https://..." } },
"message": "payment proceeded successfully"
}Saved cards can be listed with GET /cards and removed with DELETE /cards/:id. See the Cards API reference for details.
Supported currencies#
A payment's currency must be a currency that is enabled for your service in the target country. The currency you pass as actionCurrencyCode is validated against the currencies configured for your service and country.
The currencies with built-in handling today are:
| Code | Currency |
|---|---|
DZD | Algerian Dinar |
MAD | Moroccan Dirham |
TND | Tunisian Dinar |
EGP | Egyptian Pound |
SAR | Saudi Riyal |
AED | UAE Dirham |
USD | US Dollar |
EUR | Euro |
GBP | Pound Sterling |
CAD | Canadian Dollar |
Two-decimal currencies only
Status codes and retries#
Card payments use the same numeric status codes as every other method. The ones you will see most often:
| statusCode | Meaning | What to do |
|---|---|---|
2 | Succeeded | Fulfill the order. |
12 | Requires authentication | Redirect the buyer to payUrl (card entry or 3D Secure). |
3 | Rejected | Card declined. Show an error and let the buyer try another card. |
4 / 14 | Refunded / auto-refunded | A refund was processed on the payment. |
The Status Codes reference lists every code.
Retries and idempotency#
- Retrying proceed is safe. Retrying
proceedfor the same payment reuses the same underlying card payment — it will not double-charge the buyer. - Poll or wait for the webhook. There is no automatic client-side retry. To learn the final result, poll
GET /intents/:id/checkor handle the webhook. The final status always reconciles even if the buyer closes the browser before returning. - Webhooks are delivered once, without a retry. Yassir sends the outbound webhook to your registered URL once per state change and does not retry it, so also treat
GET /checkas your source of truth. See the Webhooks guide. - Refund retry is not yet available. Automatic re-attempt of a failed refund is planned but not yet implemented. For now, if a refund request fails, retry it yourself.
Webhooks for card payments
remoteStatusCode for your logic. For card payments the webhook's orderId is the card payment reference. See the Webhooks guide for the full payload.