iVendNextDevelopers Request a sandbox

Your own card or mobile-money connector — the recipe

A payment connector lets a shop take money through a payment provider we do not connect ourselves: a card terminal's cloud service, mobile money, or pay-later. You build it on your own server. The shop's payments app calls it over HTTPS on the gateway contract paygw/1, revision 1.0, and nothing of yours runs inside the shop.

Reference implementation: contracts/paygw/partner_stub.py, the payments team's own stand-in connector, copied unchanged. It is the connector their tests, their conformance kit and their walk on a real till ran against. Its "provider" is a toy ledger in memory, so it shows what your connector owes the shop and leaves out the provider call that you write. The contract: contracts/pages/paygw.md, the kit's copy of revision 1.0.

When to use it. The customer wants a card terminal or a mobile-money or pay-later provider that our own payment apps do not cover. If the shop wants its own balance spent at the till (store credit, cash back), that is a wallet instead: A partner wallet at the till. If one of our payment apps already covers the provider, use it (chapter 11).

Pick your profile

A connector serves one way of paying. If you serve two, you publish two connectors.

Profile What the customer does Rail in your declaration How your connector answers take this payment
Card taps or inserts a card at a terminal the provider runs from its cloud card_present approved or declined, while the cashier waits (up to 60 seconds)
Push: mobile money approves the payment on their own phone mobile_money pending at once with your own handle; you tell the shop when it finishes
Push: pay-later approves on their own phone, online card_not_present the same as mobile money

The stand-in has one profile for each: card_cloud, momo and bnpl (its other two, card_agent and wallet, are a counter-wired terminal, which comes in a second phase, and a wallet, which has its own recipe).

What the shop asks your connector

The shop asks You answer
Take this payment (authorise) approved with the amount actually taken and your approval code, declined with a reason, or (push) pending with your own handle. The same reference asked twice is one charge, answered the same way.
What happened to this reference? (status) the answer about exactly that payment. Never the answer about another one, and never received only when you never sent it to the provider.
Give it all back (reverse) approved with the amount given back. Asking twice is safe and answers approved again.

A card refund is still made on the provider's own machine and recorded at the till; on this contract only a wallet answers refund. When a push finishes, your connector calls the shop back; the shop also asks status on its own, so a lost callback slows the answer down but does not lose the payment.

Steps

All of this is done on your own sandbox, on its screens, as the site's administrator. Ask CitiXsys to install the remote gateway payments app on your sandbox site (the one the wallet uses; a new sandbox site does not carry it) and to switch on its payments test mode, without which the sandbox refuses a sandbox certificate (step 3).

  1. Run the stand-in first. IVN_POINT_SECRET=<a secret you choose> python3 contracts/paygw/partner_stub.py --profile card_cloud --port 8443 --no-tls, behind any public HTTPS address: the shop refuses plain http and private addresses. It listens on 127.0.0.1, which suits a tunnel on the same machine; on a small host add --host 0.0.0.0 behind a proxy that terminates HTTPS. Use --profile momo for a push. It knows two merchant references, M-STUB-1 and M-STUB-2; a card payment that carries none is still taken. Going through the steps below with it before you write a line tells you the shop's side works.
  2. Write your connector. Copy the stand-in's signed route and its answers. Keep what it gets right: it keys every lookup on (site, reference), puts site and currency in every answer, answers a repeated reference with its first answer, and refuses a body whose verb is not the route it came in on. ⚠ One thing the stand-in cannot show you: its ledger is its provider, so it has no provider call to lose. Yours has. Store our reference in your own record before you call the provider, and if the provider's reply is lost, answer that reference unknown for ever, ⛔ never never received: an absence for a payment the provider may have taken lets the shop cancel a real charge (the contract's §2).
  3. Sign your sandbox certificate with the sandbox certificate tool: your declaration, your partner name and the connector's name. Start from the stand-in's declaration for your profile (DECLARATIONS near the top of the file) and change its markets: they must include the two-letter country of each shop company that will take the payment, or going live refuses (the sandbox's shop is a US company). can_prove_absence: true is a promise that you can tell never received from lost: make it only if your provider can.
  4. Remote Connector → New. Paste the certificate, your service's bare address (https://<service>: the shop adds /paygw/1/<verb> itself, so an address ending in /paygw/1 doubles it and every call answers 404) and the secret: the same secret your connector checks signatures with (for the stand-in, its IVN_POINT_SECRET). Save. The form shows the site id.
  5. Give your connector the secret and the site id, and restart it. Your connector binds the two and refuses another site's calls; the stand-in has no setting for this (it answers whatever site calls it), so with the stand-in this step is only the secret.
  6. Payment Account (a display name, the company, provider: your connector, environment test, the shop's currency, and the Merchant reference at the partner: the reference your connector knows this merchant by).
  7. Card only: Payment Device. A label, the account, the till (POS Profile) it serves, transport cloud, and the Terminal: your name for the terminal, which reaches your connector as device on every take this payment. A push connector has no device.
  8. Payment Connection (the company, the rail from your declaration, your connector, the account; Certification required: not required on a sandbox) → Test connection. It must pass: the shop asks your connector about a reference that never existed, with the merchant reference, so a merchant you do not hold fails it.
  9. Go live. The payments app makes your connector's payment method and binds a card device's till. Put the payment method on each till's POS Profile; where that POS Profile links a payment template, add it there too.
  10. Push only: a contact for the customer. A push declares payer_required: true, so the till refuses it for a customer with no mobile number or email on record, and nothing is taken (walked with a wallet that declares it; not yet with a push).

When your connector does not answer

The till never charges twice on a guess. A card payment with no answer in time is held as not sure: the cashier is told not to charge the customer again, and the shop asks status until it knows. A payment that was taken but should not stand (the sale was cancelled, or you took more than was asked) is reversed by the shop, up to five times, and then a person is told. Make reverse safe to repeat and finish it within those tries.

Certification and going live

On your sandbox, the Run the conformance kit button on the Payment Connection drives test payments through your connector and gives you a sealed report to download. Your sandbox copy must answer the kit's two test verbs, induce and settle (the stand-in does, unless started with --live); without them the report reads INCOMPLETE, which does not qualify. Your live connector refuses both with 403.

When the kit reads CERTIFIED and SEALED, send the downloaded report, unchanged, to https://library.ivendnext.app/v1/payment-certificate (POST). Paste the certificate you get back into the Remote Connector on the customer's site. No one at CitiXsys needs to act, and no pilot store is required. Your partner code is bound to the site you first certify from. The customer's site needs our remote gateway app at 2.1.0 or later.

What is proven, and what is not

Technical notes

Needs this serves

This page in the kit