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 Yassir API never accepts raw card numbers, expiry dates, or CVC. Card entry happens on a Yassir-hosted page that securely captures the card, so the sensitive card data never passes through your systems. This keeps your PCI DSS scope to the minimum (SAQ A).

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#

FlowWhen to useWhat the buyer enters
New cardThe 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 cardThe 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

When you charge a saved card, Yassir does not collect or re-prompt for the CVV/CVC. You charge the stored card with just its 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.

Loading diagram...
  1. Create a payment intentPOST /payments/intents with the amount and currency. You get back a paymentId and a clientSecret.
  2. Proceed with the card methodPOST /payments/intents/:id/proceed with the card paymentMethodCode and a redirectUrl (where the buyer should land after paying). The response has statusCode: 12, require3DS: true, and a payUrl in metadata.
  3. Redirect the buyer to payUrl — this is the Yassir-hosted card page. The buyer enters their card and completes any 3D Secure challenge there.
  4. Finalization is automatic — once the card is confirmed, the hosted page finalizes the payment with Yassir for you. You do not call anything here.
  5. Buyer is redirected back — on success, the hosted page sends the buyer to your redirectUrl with ?status=success&paymentId=<paymentId> appended.
  6. Confirm the result — call GET /payments/intents/:id/check or rely on the webhook. A statusCode of 2 means the payment succeeded.
New card — proceed then redirect
// 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#

OutcomeWhat happens
SuccessThe buyer is redirected to <redirectUrl>?status=success&paymentId=<paymentId>. paymentId is the Yassir payment intent ID.
Failure / card declinedThe 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.
Handling the 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)

Always verify server-side

The redirect only fires on success, and its query parameters are for showing the buyer the right page — not proof of payment. Because a failed payment produces no redirect, you must confirm every card payment with the Check endpoint or a webhook before fulfilling the order.

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.

Loading diagram...
  1. 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".
  2. Proceed with the saved cardPOST /payments/intents/:id/proceed with the card paymentMethodCode and the cardId of the chosen card.
  3. Handle the result — if the card is charged directly you get statusCode: 2. If the issuer requires re-authentication, you get statusCode: 12 with a payUrl; redirect the buyer there to complete 3D Secure.
Saved card — proceed with cardId
// 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:

CodeCurrency
DZDAlgerian Dinar
MADMoroccan Dirham
TNDTunisian Dinar
EGPEgyptian Pound
SARSaudi Riyal
AEDUAE Dirham
USDUS Dollar
EUREuro
GBPPound Sterling
CADCanadian Dollar

Two-decimal currencies only

Amounts are handled as two-decimal currencies (this covers all the currencies above, including EUR and USD). Zero-decimal currencies (for example JPY) are not handled correctly today. Confirm the exact set of currencies enabled for your service with your Yassir contact before going live.

Status codes and retries#

Card payments use the same numeric status codes as every other method. The ones you will see most often:

statusCodeMeaningWhat to do
2SucceededFulfill the order.
12Requires authenticationRedirect the buyer to payUrl (card entry or 3D Secure).
3RejectedCard declined. Show an error and let the buyer try another card.
4 / 14Refunded / auto-refundedA refund was processed on the payment.

The Status Codes reference lists every code.

Retries and idempotency#

  • Retrying proceed is safe. Retrying proceed for 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/check or 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 /check as 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

Card payments emit the same webhook payload as other methods. Use remoteStatusCode for your logic. For card payments the webhook's orderId is the card payment reference. See the Webhooks guide for the full payload.