Accept Bizum inside Stripe's Custom Payment Methods (CPM) Payment Element, processed by MONEI under its own Bizum acquiring licence, and reported back to Stripe's Payment Records API for unified reporting.
This is the runnable reference for the guide at https://docs.monei.com/guides/stripe-bizum-cpm — it mirrors that contract exactly.
1. Customer selects Bizum in the Stripe Payment Element
2. Your CPM handler -> POST /pay
3. /pay creates a Stripe custom PaymentMethod (pm_) + a MONEI Bizum payment
4. Browser redirects to the MONEI hosted page; customer confirms in their bank app
5. MONEI redirects the customer to /return (?id=&status=) — branch on status
6. MONEI POSTs the full Payment object to /monei/callback (authoritative)
7. /monei/callback maps the status to a Stripe Payment Records call (idempotent)
The customer UX rides the redirect; the Stripe report is server-to-server reconciliation that runs a few seconds later. Treat the callback, not the redirect, as the authoritative outcome.
cp .env.example .env # fill in the values
npm install
npm start| Env var | What |
|---|---|
MONEI_API_KEY |
MONEI Dashboard → Settings → API Access |
STRIPE_SECRET_KEY |
Stripe secret key (test mode sk_test_…) |
STRIPE_CPMT_ID |
Bizum custom-payment-method-type id (cpmt_…), created in the Stripe Dashboard |
BASE_URL |
Public URL of this app (use a tunnel like ngrok so MONEI can reach /monei/callback) |
Prerequisites: a MONEI account with Bizum enabled, and the Bizum custom
payment method type created in the Stripe Dashboard (Settings → Custom payment
methods → cpmt_…).
| Route | Purpose |
|---|---|
POST /pay |
Create the Stripe custom PaymentMethod (pm_) + the MONEI Bizum payment; returns { redirectUrl } for the hosted page. Body: { amount?, phoneNumber?, orderId? } (amount in minor units, 1000 = €10). |
GET /return |
Customer return page for both outcomes; branches on the uppercase status query param. |
POST /monei/callback |
Verifies MONEI-Signature, maps status → Stripe Payment Records (idempotent on the MONEI payment id). |
POST /refund |
Refund through MONEI. Body: { paymentId, amount? } (omit amount for a full refund). |
MONEI status |
Stripe call |
|---|---|
SUCCEEDED |
report_payment outcome: guaranteed |
FAILED / CANCELED / EXPIRED |
report_payment outcome: failed |
PENDING / AUTHORIZED |
report_payment initiated (no terminal outcome) |
REFUNDED / PARTIALLY_REFUNDED |
report_refund on the existing Payment Record |
report_payment creates the Payment Record; the report_payment_attempt_*
endpoints update an existing one. Since a Bizum payment delivers a single terminal
callback, report the terminal state in one report_payment call. The idempotency
key is the MONEI payment id (processor_details.custom.payment_reference).
Note: Stripe's Payment Records API is in preview. MONEI supports both full and partial Bizum refunds.
- The MONEI payment id is stored in Stripe as
processor_details.custom.payment_reference, and the MONEI auth code asmetadata.monei_authorization_code— so the two systems cross-reference. /monei/callbackneeds the raw body for signature verification (this app usesexpress.raw).- No OAuth, no MONEI-hosted connector — you call both APIs with your own keys.
MIT