- E-learning
- Payments
- Morocco
- Next.js
How to sell courses online in Morocco: CMI, Stripe and bank transfer
To sell courses online in Morocco you need more than Stripe: Moroccan cards through CMI, foreign cards through Stripe, and agency or bank-transfer payments approved by staff. How each one works.

· 6 min read

Key takeaways
- 1To sell courses online in Morocco, offer three routes: Moroccan cards through CMI, foreign cards through Stripe, and agency or bank-transfer payments.
- 2CMI uses a signed form to a hosted payment page and a server callback; Stripe uses a card form on your page and a webhook.
- 3Offline payments need a reference, an instructions PDF, a receipt upload and staff approval; an AI check can turn away files that aren't receipts.
- 4Confirm card payments from both the redirect and the server callback, fulfil each order once, and check the amount and currency on the server.
To sell courses online in Morocco, one payment method isn't enough. On the platforms I've built for Moroccan academies, three routes come up: Moroccan cards through CMI, foreign cards through Stripe, and an offline route for learners who pay at an agency or by bank transfer. Schoolaris offers all three in one checkout, and they all end in the same enrolment, dashboard and receipt. Here's how each one works, and the mistakes that cost you sales.

Why one payment method isn't enough in Morocco#
A course business in France can add Stripe and be done. In Morocco, your learners don't all pay the same way. Some have a Moroccan bank card. Some live abroad and pay in euros or dollars. And some would rather pay in cash at a Wafacash or Cash Plus agency, or send a bank transfer, than type a card number into a website.
If the checkout only fits one of those groups, the others leave, and you sell courses online in Morocco to a fraction of the people who wanted to buy. So every platform I've built for this market (Schoolaris, UpSkills and CCL) takes cards and offline payments, and staff see both in the same back office. Schoolaris adds CMI for Moroccan cards.
| Method | Who it's for | How the payment is confirmed | Money arrives |
|---|---|---|---|
| Card via CMI | Learners with a Moroccan card | CMI calls your server back | Automatically |
| Card via Stripe | Learners with a foreign card | Stripe webhook | Automatically |
| Agency or transfer | Learners who prefer cash or a bank transfer | Receipt uploaded, staff approve | After a person checks it |

Accepting Moroccan cards with CMI#
CMI (Centre Monétique Interbancaire) processes card payments in Morocco, including Visa and Mastercard, and you get a merchant account through your bank. The integration is a hosted payment page, which works like this:
- Your server creates a pending order and builds a form with the amount, the order number and the return URLs.
- The form is signed: the parameters are sorted, joined, and hashed with SHA-512 using your store key, so nobody can change the amount on the way.
- The browser posts the form to CMI's payment page, where the learner pays in dirhams with 3-D Secure. The page can be shown in Arabic, French or English.
- CMI calls your server back directly. You check the signature and the amount, then mark the order paid.
- The learner is sent back to your site: to their dashboard if it worked, to the checkout with a clear message if it didn't.
On Schoolaris, the checkout picks the tab for the learner: a Moroccan learner sees CMI first, everyone else sees the card form. If a learner leaves and comes back, a recent unpaid CMI order is reused instead of creating a duplicate, and an older one is closed.
Accepting foreign cards with Stripe#
For learners abroad, Stripe gives you a card form that stays on your own page, with 3-D Secure running inside it. One catch: Stripe doesn't open accounts for companies based in Morocco (check its list of supported countries), so you need a company registered in a country it supports to use it.
On the technical side, I create a PaymentIntent on the server with the amount in cents, confirm it in the browser, and listen for the payment_intent.succeeded webhook. The price, the currency and the tax always come from the server. The browser never sends them, because a changed request could otherwise pay 100 rupiah for a 100-euro course.
Bank transfer and cash agencies for Moroccan learners#
The offline route needs the most care, because a person has to check each payment. A good one looks like this:
- A payment reference the learner quotes when paying, so staff can match the money to the order.
- A PDF with the instructions: the agency or bank details, the amount and the reference, sent by email and downloadable again from the dashboard.
- A receipt upload from the learner's payments page, which moves the order to "awaiting validation".
- Staff approval in the back office, limited to people with the right permission. Approving it activates the enrolment and emails a receipt.
The agencies depend on your audience. The platforms I've built list options such as Wafacash, Cash Plus, Barid Cash, Western Union and bank transfer, plus mobile money such as Orange Money and Wave for learners elsewhere in Africa. Show each one with its logo: learners recognise the brand before they read the name.
Two details I'd copy. On CCL, an AI check looks at each uploaded file first and turns away anything that isn't a receipt: selfies, ID cards, and a mistake learners really make, CCL's own payment-instructions PDF uploaded back. A person still verifies every receipt; the check only saves them from opening the wrong files. And on Schoolaris and UpSkills, the offline route now starts with a WhatsApp message to the learner's adviser, who records the payment and activates the enrolment.
Confirming payments without losing a sale#

A card payment can be confirmed two ways: the learner's browser returns to your site, or the payment provider calls your server. Use both, and send both through the same step:
- Never rely on the redirect alone. People close the tab after paying. The server callback arrives anyway.
- Fulfil once. Callbacks can arrive twice, or at the same time as the redirect. Key the enrolment on the payment ID, and stop if it's already paid.
- Check the amount and currency against the order, and treat a missing amount as a mismatch.
- Ask for a retry when something breaks. If your server fails while handling a callback, answer with an error so the provider tries again. On one project, a bug made the callback answer "OK" even when it had failed, so the payment was never retried and learners who closed the tab paid without getting access. Retries only fix temporary errors: a wrong amount goes to a person for review.
Instalments, reminders and receipts#
For longer programmes, CCL lets learners spread the payment: they choose to pay in full, in two instalments or in three, with a bigger discount for paying in full. The remaining balance is paid later from the dashboard, by card or through an agency, and the amount can never go above what's still owed.
On Schoolaris, every dashboard page shows a banner while money is owed, and a quieter "receipt under review" note once a receipt is uploaded. Receipts are generated as PDFs, and there they come in French, English and Arabic, with right-to-left layout for Arabic.
Which payment methods to start with when you sell courses online in Morocco#
If most of your learners live in Morocco, start with CMI and the offline route: that covers people with a local card and people who prefer cash. Add Stripe when you sell to learners abroad. Instalments come next if your programmes are expensive. Payments are one of the smaller modules in what an e-learning platform costs, but they decide whether the other modules ever get paid for.
On a custom platform, each of these routes follows your own rules. If you're comparing that with a hosted course platform, why CCL left LearnWorlds covers the trade-offs.
Want local payments on your platform?#
If you sell courses online in Morocco and your checkout loses learners who don't pay by foreign card, tell me how your learners pay today. You can also look at the platforms I've built with CMI, Stripe and agency payments.
Frequently asked questions
How do you accept Moroccan bank cards on a course website?+
Through CMI, Morocco's card processor, with a merchant account from your bank. Your site sends a signed form to CMI's payment page, the learner pays in dirhams with 3-D Secure, and CMI calls your server back to confirm.
Can a Moroccan company use Stripe?+
Stripe doesn't open accounts for companies based in Morocco, so you need a company registered in a supported country. Stripe is still useful for learners abroad paying with foreign cards.
How do bank transfer payments work on an e-learning platform?+
The learner gets a payment reference and a PDF with the bank or agency details, pays, and uploads the receipt. Staff check it in the back office, and approving it activates the enrolment and sends a receipt.
Can learners pay for a course in instalments?+
Yes, if the platform supports it. On CCL, learners can pay in full or in two or three instalments, and pay the remaining balance later from their dashboard by card or through an agency.

Written by
Full Stack Developer & Web Marketer · Marrakech, Morocco
I build modern, scalable web applications end to end, from frontend to backend, with a focus on performance, clean code and user experience.