WalleoPay WalleoPay
EN
My account
Sign in Open an account Forgotten password Documentation

Opening an account is free. Your test keys are available straight away.

Security

What protects your customer, your money and your access.

A payment gateway is a target: money, phone numbers and identity documents pass through it. This page sets out the protections actually in place in WalleoPay, those you need to put in place on your side, and what we are not in a position to promise today.

We do not see what we have no need to see

The Mobile Money PIN is entered on the customer's phone, at the operator. Card numbers are entered on our card provider's hosted page. Neither one reaches our servers.

A notification is not proof

No incoming message on its own moves a payment to succeeded: it triggers an authenticated check with the operator, and it is that response which counts.

Every movement leaves a line

A merchant's balance is not recalculated on the fly: every credit and every debit is an entry, with the resulting balance, in a ledger we do not rewrite.

During payment

What protects your customer on the checkout page

This is the moment when a customer hesitates and an attacker has the most to gain. The checkout page is therefore the most locked-down part of the site: it loads nothing from outside, it never asks for a banking secret, and it only lives for a while.

The PIN does not go through us

With Mobile Money, the checkout page only asks for a phone number. The approval request then appears on the customer's phone, and it is at the operator that they enter their PIN. WalleoPay has no form capable of collecting that PIN — so there is nothing here to steal.

  • No PIN field, neither on the page nor in the API.
  • The operator is derived from the prefix: there is no choice for the customer to get wrong.
  • For card payments, entry takes place on our provider's hosted page: no card number reaches our servers.

A page that loads nothing from outside

All our HTML responses carry a strict content security policy. Scripts come from our domain alone, and the few inline scripts carry a token regenerated on every response: an injection elsewhere on the site would not be enough to display a fake checkout form.

Scripts
Our domain only, plus a single-use token per response.
Embedded content
Plugins and external objects are forbidden.
Form targets
Our domain and that of the operator concerned, nothing else.
Framing
The page cannot be framed by a third-party site.

A link that expires

Every payment has its own address, valid for 30 minutes. A link found later in a browsing history leads nowhere.

A watched rate

The checkout page accepts ten attempts per minute per IP address. A script trying numbers one after another is stopped before it becomes useful.

Automated probing blocked

Requests looking for a configuration file, a database backup or a WordPress panel get a 404 without ever touching the database, and leave a trace.

Headers applied to every response

The browser is not allowed to guess the type of a file we serve.

Framing restricted to our own domain.

Referrer sent only to encrypted same-origin destinations.

Camera, microphone, geolocation and the browser's payment interface disabled.

Window isolation: a third-party site opened from the page keeps no control over it.

In production and over HTTPS, an encrypted connection is enforced for one year, subdomains included.

Your money

What prevents a fake collection and a double charge

The two simplest frauds against a gateway are making it believe a payment has succeeded, or making it record the same operation twice. Both are handled by design, not by monitoring.

An operator notification decides nothing

Incoming operator notifications are accepted, logged, then treated as a mere signal: even when they announce a success, we go back through an authenticated query to the operator before changing the state of the payment. A forged message credits no one.

Replaying a request does not create a second payment

Every payment creation can carry an idempotency key. If the same request comes back, we return the original response instead of creating a second one. A key reused with different content is rejected. And if the first request dies in flight, the lock is released after 90 seconds so the order can be paid again.

An append-only ledger

Your balance is never recalculated from the list of payments: every movement is a dated entry, with its type, its direction, its amount and the resulting balance. Two payments settling in the same millisecond are serialised by a lock on your account row, never added up wrongly.

Signed notifications that keep trying

Every outgoing notification carries a signature computed over the timestamp and the body of the message, with the notification secret specific to your account. Signing the body alone would let a captured message be replayed indefinitely; signing the timestamp with it lets you reject it beyond your tolerance window.

X-WalleoPay-Signature: t=1737129600,v1=<hmac_sha256>

signature = hmac_sha256(horodatage . "." . corps, secret)
  • Up to 8 attempts per notification, spaced from 10 seconds to 6 hours apart.
  • Recommended timestamp tolerance: 5 minutes.
  • Every delivery keeps its response code and the beginning of the body returned by your server.
  • A delivery can be replayed by hand from your dashboard.

A verifiable audit trail, payment by payment

Every payment keeps the sequence of its events: state change, origin of the change, operator error message, content received. In a dispute, the question is not who remembers what, but reading the line back.

  • Dated history of every transition, with the starting state and the ending state.
  • Origin of the event: system, operator, merchant or administrator.
  • Amounts handled in whole francs, with no sub-unit and no floating-point rounding.
  • Accounting ledger exportable from your space, for your bookkeeping.
  • A payout that fails at the operator automatically credits your balance back.

Your access

API keys, team, passwords

Most incidents on a gateway do not come from a vulnerability, but from a key left in a public repository or from access left with someone who has gone. Here is what the platform does to limit the damage.

A secret we cannot give back to you

When a key is issued, the secret is shown to you once. We keep only a SHA-256 fingerprint and the last four characters for display. So no one here can read your key or send it to you by email — and read access to our database would not reveal it either.

  • The secret presented is compared to the stored fingerprint, never to a plaintext value.
  • A key is revoked, not deleted: its history stays readable.
  • Immediate renewal from the dashboard, with no ticket and no delay.
  • A rejected key is logged with the IP address and the prefix presented.
  • Separate keys per service: one compromised module does not expose the others.

The mode follows from the key, never from a parameter

A test key cannot collect real money, whatever request is sent. Conversely, a live key stays rejected as long as your verification file has not been approved, or as long as the service concerned is not approved. A configuration oversight does not turn into a real transaction.

Account not activated

Live keys are rejected with an explicit message; test keys keep working.

File under review

Same handling: you integrate and you test, you do not collect yet.

Service not approved

Its live key is rejected even when the account itself is active.

Three roles, distinct powers

A shop is not run by one person alone. Each member of your team is given a role, and that role decides what they can trigger.

Role What they can do
Owner The only one to manage the team, the API keys and the account settings.
Manager Manages the services and the day-to-day work, without touching access.
Read only Views the payments and the ledger; triggers nothing that touches money.

Invitations use a single-use random token, expire after seven days and can be cancelled before they are accepted. A member is removed from the team in one click, and their role is changed without reinviting them.

Passwords and account recovery

  • In production, ten characters minimum, letters and digits required.
  • A password that has already appeared in a known public breach is rejected at sign-up as well as at change.
  • Passwords are hashed, never stored in plaintext and never reversible.
  • The forgotten password form answers exactly the same thing whether the address exists or not: it cannot be used to find out who is a customer of ours.
  • The reset link expires and works only once; using it also renews the remembered session token.

Enforced rate limits

Sign in 5 attempts per minute per address + IP pair, 20 per minute per IP
Merchant API 120 requests per minute per key, 300 per minute per IP
Checkout page 10 attempts per minute per IP
Sign up 5 account creations per hour per IP
Contact form 5 messages per hour per IP

The login limit applies to the address + IP pair: a dictionary attack against one account does not block access for other merchants.

Your data

Identity documents, operator credentials, uploaded files

Opening a merchant account means entrusting us with a trade register or an identity document. Connecting your own operator accounts means entrusting us with credentials. These two deposits are handled separately from the rest.

The documents in your file

  • Stored outside the public directory: no web address leads directly to a file.
  • Viewing restricted to your authenticated space and to the internal review of the file.
  • Filename entirely regenerated: the original name is only used for display and never touches the file system.
  • The real type is read from the content of the file, not from its extension: an executable renamed as an image is rejected.
  • Accepted formats: JPG, PNG, WEBP and PDF, five megabytes maximum.
  • SHA-256 fingerprint kept to detect any later alteration.

Operator credentials

The MTN, Orange and card credentials stored in the platform are encrypted at rest. Once entered, they are never displayed again: the interface only shows whether a field is filled or empty, with the last four characters for secrets.

  • Encryption at rest for credentials and configuration secrets.
  • No secret appears in an API response or in an export.
  • Test and live modes configured separately, never mixed.
  • Downloadable modules are served from an allow-list: an unknown module name never reaches the file system.

The details of what we collect, why and for how long are in the privacy policy.

Your side of the work

Five rules that keep your account safe

Everything above happens on our side. The rest depends on how you integrate the platform. These five points cover nearly all the incidents we can anticipate.

Keep the secret key on your server

A live key grants the right to create payments and request payouts in your name. It has no place in page JavaScript, in a mobile app shipped to your customers, or in a Git repository. If someone else could merely have read it, renew it: it is immediate and free.

Re-check every payment through the API before you deliver

The only source that counts is the API response to an authenticated request on the payment identifier. Neither the return URL in the customer's browser nor the content of a notification should trigger a delivery on its own: one can be forged in the address bar, the other can arrive twice, out of order, or come from elsewhere.

Verify the signature of every notification

Recompute the fingerprint over the timestamp and the body received, compare it in constant time, and reject any message whose timestamp falls outside your tolerance window. Then answer in under ten seconds: long processing goes into a queue, it does not happen while we are waiting for your response.

Keep your team up to date

Give the weakest role that allows the work to be done, keep the owner role restricted, remove without delay the access of a colleague who leaves and cancel invitations that have not been accepted. A forgotten team account is an account nobody is watching.

Report an incident straight away

A key published by mistake, a notification received from an unexpected source, a gap between your ledger and ours, unexplained behaviour on the checkout page: write to us before trying to work it out alone. We would rather have an alert for nothing than an alert that comes late.

The right order, once and for all

  1. 1 You create the payment from your server, with an idempotency key.
  2. 2 The customer pays on the hosted page; you touch nothing.
  3. 3 You receive a signed notification, you verify it, and you treat it as a signal: go and check.
  4. 4 You query the API on the payment identifier, with your secret key.
  5. 5 The API confirms the state and the amount: you deliver, and you mark the order as paid on your side.

The details of the calls, the fields and the verification code are in the documentation.

Straight talk

What we do not promise

A security page that announces nothing but good news does not help you decide. Here are the limits we know about, written down before you have to discover them.

No external audit to date

The platform is young. No independent firm has yet carried out a code review or a penetration test on WalleoPay. What you read on this page describes what is implemented, not what has been validated by a third party. The day an audit takes place, we will publish its scope and its date.

No PCI-DSS certification, and that is deliberate

We handle no card number: entry takes place entirely on our card provider's hosted page, which carries that compliance for what it processes. So we do not claim to be PCI-DSS certified — we have organised the service so that we do not have to be.

Funds pass through the operators

MTN Mobile Money and Orange Money remain the custodians of the money until payout. An outage on their platform, a block on an account or a delay on their side is not up to us. We can tell you precisely where an operation stands; we cannot force an operator to settle it.

No uptime figure announced

We do not display an uptime rate and we do not sign a numbered service level agreement: we do not yet have the operating history that would let us keep to one. Announcing an unverifiable figure would be the first thing not to believe on this page.

No two-factor authentication yet

Signing in to your space rests today on a password, protected by strength rules, a refusal of passwords that have already leaked and a limit on attempts. Adding a second factor is work under way, not an available feature.

We do not keep your money

An aggregator is not meant to hold its merchants' funds for long. The available balance is made to be paid out, and we follow a retention cap of 7 days so that we can warn you. Do not use us as a savings account.

The corresponding contractual commitments are written in black and white in our security policy and in the terms and conditions.

Reporting

You have found something

Whether you are a merchant, a developer or just a visitor, write to us. We would rather receive ten reports that lead nowhere than learn about a problem from an unhappy customer. No reward is planned at this stage, and we say so rather than let you believe otherwise.

By email

support@walleopay.com

Put "security" in the subject for priority handling.

Response time

Within one working day

For an incident in progress on a merchant account, put "incident" in the subject.

What to send us

  • The exact address of the page or the name of the API call concerned.
  • The approximate date and time, with your time zone.
  • The steps that reproduce the problem, even roughly.
  • The payment identifier if there is one, never your secret key.

Never attach a secret key, a password or a Mobile Money PIN to a report. If a key has leaked, renew it first from your dashboard, then tell us.

Open the contact form

Start in test mode, with no commitment

Test keys arrive as soon as you sign up. You connect your shop, you check that your code really does re-check through the API, and you only go live once your file has been approved.