Online payment in Morocco in 2026: how to get paid (methods, fees, steps)
3-D Secure cards, cash at agencies, payment links, subscriptions: what payment collection costs in Morocco, and the steps from the sandbox to production.
You sell to Moroccan customers and you want to be paid online, in dirhams, into an account in your company's name — without waiting for a settlement that drags on, without chasing the courier for cash. This guide covers the question from the merchant's side: which collection methods actually exist in Morocco, what they cost, which steps stand between you and a first transaction, and how to integrate them depending on whether you have a developer or not. It is long on purpose: it is the page to read once, before choosing.
Where things stand in 2026
Online payment in Morocco does not look like the version described in guides written elsewhere. Cards work, with 3-D Secure as the authentication standard. But a share of buyers has no card enabled for Internet use, or not enough trust in an unfamiliar site to type a number into it: cash on delivery remains a common reflex of Moroccan e-commerce, with its refused parcels and its cash riding around town. We quote no market share here; the figures in circulation are rarely sourceable, and your own refusal rate will tell you more than a national average.
Another local trait: the sale is often closed away from the site, on WhatsApp or Instagram, and payment follows the conversation rather than a cart. Finally, the international gateways developers are used to are not all open to Moroccan companies — we come back to that in the questions below. Collecting payments online in Morocco in 2026 means working with these three realities: the card, the cash, and the conversation.
The collection methods, compared
A payment gateway is chosen first by what it lets you collect, and how. The table below compares the five ways to collect from a Moroccan customer online: two payment methods — cards and cash — and three tools to put them to work — the payment link, the hosted checkout and the subscription. At ChariPay, all of them credit the same payment account, and all of them credit it instantly.
| Method | Who it is for | Funds available | What it takes technically | Watch out for |
|---|---|---|---|---|
| Online card payment (3-D Secure) | Any sale to a customer whose card is enabled for Internet use | Instantly in the payment account, as soon as the buyer's bank confirms | A hosted payment page, by link or by session; no card data passes through you | The payment is asynchronous: the webhook is the result of record, not the return page |
| Cash at an agency, by reference | Customers without a card, high baskets, orders you would rather not ship cash on delivery | Instantly in the payment account, as soon as the network confirms the deposit | The same hosted page: the customer chooses cash, receives a reference and deposits at an agency of the Chari network | The time between the order and the deposit depends on the customer: set an expiry and plan a reminder |
| Payment link | Shops without a developer, WhatsApp and Instagram sales, quotes, events | Instantly, as above | The portal — or POST /v1/payment-links; single or multiple use, sent by e-mail, QR code, poster | A multi-use link does not tell you who paid unless you read the notification: fill in metadata or externalId |
| Hosted checkout (sessions) | Sites and applications with a developer, a cart, a back office | Instantly, as above | POST /v1/payment-sessions with the amount in MAD, redirect to checkoutUrl, signed webhook | Idempotency on creation, webhook handling, orderId and externalId kept distinct |
| Subscription | Gyms, schools, software, boxes, rents — anything paid on a schedule | Instantly, at every instalment collected | A client (POST /v1/clients) then a subscription (POST /v1/subscriptions); first payment with 3-D Secure, then automatic charges | Customer consent, notice before each charge, retries at D+1, D+3 and D+7: test the full cycle in the sandbox |
Cards, with 3-D Secure
It is the method everyone expects, and the simplest to set up: your customer enters their card on a page hosted by ChariPay, their bank asks them for a 3-D Secure authentication, they come back — and the result reaches you by webhook. You never touch a card number, neither on your server nor in your browser: the PCI DSS Level 1 certification is ours, not yours, and your scope stays that of a merchant who never sees card data.
The point that surprises integrators: a card payment does not complete at the moment you call it. There is the bank, the authentication, the return. The confirmation page the buyer sees is only a redirect; the signed notification your server receives is the one source of truth. It is the first of the classic mistakes, further down. On what makes an authentication fail, 3-D Secure: what makes a payment fail goes into the detail.
Cash at an agency, by reference
ChariPay is the only payment gateway in Morocco that also collects cash at agencies. The principle fits in one sentence: on the same payment page, your customer chooses cash, receives a reference, and deposits the amount at an agency of the Chari network; you are notified the second the network confirms the deposit, and the amount is available in your payment account at that instant.
What it changes is the order of operations. An order paid on delivery ships first and gets paid afterwards — or does not. With the agency deposit, the order is paid before it ships, the money never travelled with a courier, and the collection shows up in the same statement as your card payments. The only delay is the time the customer takes to visit an agency; hence the value of a sensible expiry date on the reference and a reminder if the deposit is slow to come. We detailed the set-up in Taking cash without a till.
The payment link
The payment link is the tool of conversational selling and of the shop without a developer. You create it from the portal — amount, description, single or multiple use, expiry date — or through the API with POST /v1/payment-links, and you send it however you like: pasted into WhatsApp, e-mailed from ChariPay, printed as a QR code on a poster for a stand or a counter. The customer opens the page, chooses card or cash, pays.
A single-use link is consumed by the first successful payment; a multi-use link stays open and collects as many times as it is used — handy for a fixed price, a membership fee or an event. In that second case, it is the payment notification that tells you who paid and when: read it, or reconcile from the portal. To decide between a link and a full checkout, Payment link or checkout asks the right questions.
The hosted checkout, through payment sessions
As soon as you have a cart and a back office, the payment session replaces the link. Your server calls POST /v1/payment-sessions with the amount in MAD, your order reference and the buyer's details; the API returns a checkoutUrl to which you redirect the customer. The hosted page handles the card, the 3-D Secure authentication and the cash option; your server, for its part, waits for the webhook.
A session is single-use by default and expires on its own — seventy-two hours after creation if you specify nothing, or on the date you set. You can attach metadata to it, returned untouched in the notification, and your own externalId, whose effect the technical section further down explains.
The subscription
The subscription serves businesses that collect on a schedule: gym, school, software, rent, monthly box. You first create a client, then a subscription with its amount, its frequency and its start date. The first payment goes through the hosted checkout with 3-D Secure — that is where the customer gives their consent — and the following instalments are charged automatically, with a notice sent to the customer before each charge.
When a charge fails, ChariPay retries at D+1, D+3 and D+7 and sends the customer a fallback payment link; you are told by webhook and you keep control to suspend or cancel. As long as an instalment remains unpaid, no new period opens. The sandbox has an endpoint that forces the next due date: it is what lets you run a year of subscription in a minute, before touching a real customer. The product detail is on the Subscriptions page.
What payment collection costs in Morocco
Prices are compared last — we wrote it in Choosing a PSP in Morocco, and we stand by it. But they are compared, and for that you need to know what a quote is made of. In Morocco as elsewhere, the cost of collecting a payment online breaks down into five items, only two of which are printed in large type on the brochures.
The five items of a quote
- Activation. A one-off sum covering the review of your application, activation and support through go-live. Ask whether it is paid before or after activation.
- The commission. A percentage taken on each transaction, sometimes topped up with a fixed part. It generally depends on your line of business, your payment methods and your volumes. Two questions to ask: is it taken on successful transactions only, and is the percentage the same for every method?
- The security deposit. A guarantee held for the length of the relationship, meant to cover disputes and unpaid amounts. Its amount depends on the perceived risk of your business; ask how and when it is returned to you.
- Refunds. Refunding a customer is a normal act of trade, not an incident. Some providers keep the commission on the original transaction or charge for the operation: check what a full refund, then a partial one, actually costs you.
- Payouts. The most underestimated item. When does the money you collected reach an account you control? A settlement deferred by several days is a cash-flow cost you will never see on an invoice, and a transfer charged on every payout adds up fast.
Then there are the costs that appear on no quote: development time, manual reconciliation when the exports do not speak to your accounting, and the cash you keep handling on the side because the gateway does not collect it.
Our numbers
ChariPay's prices fit in a few lines, and the pricing page says nothing more.
- The sandbox is free, with no time limit and no commitment. You can build and test your whole integration before signing anything.
- The activation fee is MAD 6,000, VAT included, paid once, at go-live. Nothing before.
- The commission is a percentage per successful transaction. It is set once your application has been reviewed — your products, your payment methods, your volumes — and the security deposit with it. The proposal arrives with figures, before any commitment; we do not publish a generic percentage because it would be wrong for half our readers.
- Refunding a customer is free, in full or in part.
- Funds are available instantly in your payment account, an account with a RIB in your company's name. The payout to your bank is made by transfer on demand, or automatically every night once a settlement account is configured. From that account, you can also issue transfers, pay bills and buy mobile top-ups through the API — what you have just collected is already usable.
The steps: from the sandbox to production
There are two sets of steps, and they are nothing alike. The first asks nothing of anyone: it is the sandbox, which you open yourself. The second is administrative: enabling production, which requires a verified company.
The sandbox, in eight steps
The sandbox is free, has no time limit, and is self-serve: no sales meeting, no e-mail to support, no card required. Eight steps stand between a blank page and a first authenticated call, and the Getting started guide in the API documentation walks through them request by request.
- 1Sign up at portal-psp.charipay.ma/register with your work e-mail address.
- 2Activate your account from the link received by e-mail, and choose your password. The activation token exists only in that e-mail.
- 3Log in to the portal. Depending on your account's permissions, it may ask you to enrol a two-factor authentication app — keep your recovery codes.
- 4Select your company. It is this step, not the login, that opens your working session.
- 5Pass re-authentication. Creating an API key is a sensitive action: the portal issues a short-lived confirmation token, required at step 7.
- 6Look at the available permissions, and grant your key only what your integration actually calls.
- 7Create your key. It starts with
chari_sk_test_and is shown only once, at that moment: put it straight into a vault or an environment variable, never into page code (Protecting your API keys). - 8Check that everything holds with a
GET /v1/wallet: if the balance answers, you are authenticated.
A single test card exists in the sandbox: 4918914107195005, CVV 123, 3-D Secure code 555. It is enough to run a complete payment, authentication included, and to receive your first webhook. The base URL is the same as in production — https://api-psp.charipay.ma — because the key chooses the environment, not the address.
Enabling production
Production is enabled on your account once your company has been verified. Concretely, you send in your company file; the team reviews it, sets the commission and the security deposit, and sends you a proposal with figures. You then pay the activation fee — MAD 6,000, VAT included, once — and production is open.
Until it is, a chari_sk_live_ key gets an explicit 403 with the code PRODUCTION_ACCESS_NOT_ENABLED. That is not an integration bug, it is an administrative step that is not finished yet. Your developer can therefore prepare the production configuration without risk: it becomes active the day the file does.
On switch-over day, you change exactly one thing: the key. URLs, payloads and error codes are identical. The one known trap is the webhook signing secret, which differs between the sandbox and production; the integration that switches the key and keeps the old secret silently rejects every production notification. The full list of what to check before switching is in Sandbox to production: the go-live list.
Integration, depending on your situation
There is no one right integration, there are four, and yours depends on two questions: do you have a developer, and do you collect once or on a schedule?
Shop without a developer: payment links
Your shop runs on Shopify, on WooCommerce or on Instagram, and nobody on the team writes code. The circuit takes three moves: the order comes in, you create a payment link for the order amount from the portal, you send it to the customer — WhatsApp, e-mail, or a QR code on the delivery note. The customer pays by card or in cash at an agency; the portal shows it to you, and you mark the order as paid in your shop.
The portal is designed for a team, not a single person: it distinguishes the owner, manager, cashier and accountant roles, accepts several users, and exports your collections to CSV. The two platform guides — Getting paid on Shopify in Morocco and Getting paid on WooCommerce in Morocco — walk through this circuit step by step, then show when and how to move to the API.
Site with a developer: sessions and webhooks
With a developer, the integration comes down to two pieces: create a payment session for every order, and handle the notification that comes back. Creation looks like this:
curl -X POST https://api-psp.charipay.ma/v1/payment-sessions \
-H "X-CHARI-PAY-API-KEY: chari_sk_test_…" \
-H "Idempotency-Key: order-2026-0001" \
-H "Content-Type: application/json" \
-d '{
"amount": 250.00,
"orderId": "ORD-2026-0001",
"externalId": "order-2026-0001",
"config": {
"customer": {
"firstName": "Amine", "lastName": "Bennani",
"email": "amine@example.com", "phone": "+212600000000"
},
"urls": {
"accept": "https://votre-site.ma/merci",
"decline": "https://votre-site.ma/echec",
"notification": "https://votre-site.ma/webhooks/charipay"
}
}
}'The amount is in dirhams, with no currency field: the API works in MAD only. The response carries the checkoutUrl to which you redirect the buyer. The Idempotency-Key header, derived from your order reference, makes the call safe to replay; the externalId, unique per environment, means a second call for the same order returns the existing session with a 200 instead of creating a new one.
The second piece is your webhook endpoint. Every delivery carries X-CHARI-SIGNATURE, a hex-encoded HMAC-SHA256 computed over the string timestamp + "." + raw body, and X-CHARI-TIMESTAMP, the timestamp in milliseconds. Verification fits in a few lines:
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyChariSignature(rawBody, headers, secret) {
const timestamp = headers['x-chari-timestamp'];
const signature = headers['x-chari-signature'];
if (!timestamp || !signature) return false;
// Tolerance of ±5 minutes, matching the ChariPay side
if (Math.abs(Date.now() - Number(timestamp)) > 5 * 60 * 1000) return false;
const expected = createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
return expected.length === signature.length
&& timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}Four rules are enough after that. Verify against the raw body, before any parsing. Deduplicate on Chari-Event-Id: the same event can be delivered more than once, and that is a guarantee, not a defect. Answer 200 as soon as the event is written somewhere, and do the rest in the background. And if your server does not answer, don't worry: we retry at 1 min, 5 min, 30 min, 1 h, then every 6 h, up to 16 attempts over roughly 72 hours — and the portal's delivery log lets you replay any delivery in one click. Getting your webhook integration right details the five mistakes we see most often.
For the rest — clients, products and orders, refunds, transactions, exports — the API documentation covers 12 modules and 62 endpoints, with examples in four languages, a Postman collection, the OpenAPI contract and a pack ready to hand to your coding assistant.
Subscriptions
Integrating a subscription adds one step before the session: the client. You create it with POST /v1/clients, then open the subscription with POST /v1/subscriptions — amount, frequency, start date, notification channel, and your own externalId. The first collection goes through the hosted checkout with 3-D Secure and records the payment method; the following ones are automatic, announced to the customer by e-mail before the charge.
Your server receives a webhook at every due date, successful or not, with your externalId and your metadata: that is what lets you keep your own billing up to date without storing our references. Test the full cycle in the sandbox with the endpoint that forces the next due date — creation, three instalments, one failure, one cancellation — before opening production. It is the only way to find a recurring-billing bug before it reaches a real customer.
Marketplace and distribution
If you collect on behalf of a network — a marketplace, franchisees, points of sale — each entity can be declared as a sub-merchant, with its own wallet and its own identity check. A payment session then names, in config.settlement, the wallet to credit: the collection is attached to its point of sale at transaction time, instead of being untangled afterwards. Payouts, on the other hand, do not leave on their own: they go through a dual approval, where the requester is never the approver. The set-up is prepared with the integration team; the Distribution page gives the outline.
The classic mistakes
We see a lot of integrations go by. The same mistakes come back, and none of them is technical in the strict sense: they are shortcuts taken on day one and paid for in month three.
- Shipping on the return page. A buyer who closes the tab after paying will never see your confirmation page. If your order is only confirmed there, it never will be — while the money did arrive in your payment account. The rule is simple: the return page says thank you, the webhook ships.
- Forgetting idempotency. A network that drops between your call and our response, a user who double-clicks, a replayed job: without an
Idempotency-Keyon your creates and without a uniqueexternalId, you will end up creating two sessions for one order, or shipping twice. Never charge twice — idempotency explained explains how to derive these keys from your own references rather than drawing them at random. - Ignoring cash. The merchant who only accepts cards online keeps handling cash on delivery, outside any system, and does not count it as a cost. Offering the agency deposit on the same payment page brings that money back into the statement, before shipping.
- Reconciling by hand. Comparing a bank export with an order sheet at every month end is the symptom of an integration that did not use
externalIdandmetadata. These fields come back to you on every notification and in the CSV exports: reconciliation becomes a join, not a read-through. Reconciling your collections with your accounts shows the method. - Switching the key without switching the secret. On go-live day, the API key changes and so does the webhook signing secret. Forgetting the second gives the most baffling incident there is: payments go through, orders don't ship.
Frequently asked questions
Can you use Stripe in Morocco?
To date, Stripe's official list of supported countries does not include Morocco, and no timeline has been announced publicly. That is a fact of availability, nothing more. The workarounds that circulate — incorporating a company abroad, or going through a third party's account — have consequences that must be faced squarely: the funds are collected outside Morocco by a foreign entity, with the tax obligations of the country of incorporation; Moroccan foreign-exchange (Office des Changes) and VAT obligations apply when your customers are Moroccan; there is a risk of account closure, and going through a third party's account is contrary to the service's terms of use; finally, Moroccan cards are not always accepted. All of this is to be validated with your adviser before committing to anything. For a Moroccan company selling to Moroccan customers, the useful question is rather: which gateway licensed in Morocco collects in dirhams, into an account in my company's name? Stripe in Morocco covers the question in full.
Do you need a developer to collect payments online?
No. Payment links are created and sent from the portal, without a line of code, and are enough for a shop handling a few dozen orders a day. The developer becomes useful when volume calls for automation — a session created on every order, the order updated by webhook — or when you collect on a schedule.
How much does opening an account cost?
The sandbox is free and has no time limit. Going live costs an activation fee of MAD 6,000, VAT included, paid once. The commission per successful transaction and the security deposit are set once your application has been reviewed, and you know them before you commit. Refunding a customer is free.
When is the money available?
The instant the payment succeeds — by card, as soon as the buyer's bank confirms; in cash, as soon as the network confirms the deposit. The amount is available in your payment account, an account with a RIB in your company's name. To your bank, you pay out by transfer on demand, or automatically every night once a settlement account is configured.
What happens if my server is down when the payment completes?
Nothing is lost. Webhook delivery is retried at 1 min, 5 min, 30 min, 1 h, then every 6 h, up to 16 attempts over roughly 72 hours. The portal's delivery log shows every attempt and your server's response, and lets you replay a delivery in one click. Since every event carries the same Chari-Event-Id on every attempt, a handler that deduplicates stays correct however many times it is replayed.
How do I refund a customer?
Through POST /v1/refunds, identifying the payment by its operationId or by your externalId, with your own refundReference and a reason. The refund can be full or partial — refundAmount for a partial one — and the call answers 202 while the operation runs; replaying the same refundReference returns the existing refund, with a 200, without debiting twice. It is free.
Does card data pass through my site?
No. Entry happens on the payment page hosted by ChariPay, the 3-D Secure authentication at the buyer's bank, and your server receives only a signed notification. ChariPay is PCI DSS Level 1 certified, and data is processed within the framework of Law 09-08. Your compliance scope stays that of a merchant who never sees a card number; which self-assessment questionnaire applies to you is confirmed with your adviser or your acquirer.
Can I collect in a currency other than the dirham?
No. The API takes amounts in MAD and has no currency field; ChariPay is built for a Moroccan company collecting from customers in Morocco, into a Moroccan payment account.
Next step
If you have read this far, you know what you want to collect and how. What follows takes three moves.
- 1Open the sandbox at portal-psp.charipay.ma/register — eight steps, no meeting, no commitment — and make a first payment with the test card.
- 2Choose your integration: a link from the portal if you have no developer, a session and a webhook if you have one, a subscription if you collect on a schedule.
- 3Ask for your proposal once the integration holds in the sandbox: your application is reviewed, the commission and the security deposit are communicated to you, and production opens after the activation fee.
If you are still hesitating between several providers, the PSP in Morocco page explains what a licensed payment gateway is and how to read a quote, and Choosing a PSP in Morocco lists the eight questions to ask — of us as of anyone else.
Written by ChariPay team.