iVendNextDevelopers Request a sandbox

S46 — Payment method rules (pp_pmr): which payment methods each customer group may use

The shop decides which payment methods each group of its customers may use at the till: customers who order through a delivery platform pay only by that platform's method, only account customers may buy on account, a group that settles in dollars pays only in dollars. When the cashier presses Pay, the app leaves every other method off that sale's payment screen, dimmed, with the shop's reason beside it.

When to use it: a rule about the sale's customer decides which payment methods the till may take, and the shop keeps the rule itself, in Desk.

What happens

When What the cashier sees
A sale for a customer whose group's rule leaves methods out The payment screen opens with those methods dimmed: "Not for this sale: Talabat customers pay with Talabat." The cashier takes one that is not
A rule that leaves out every method this till offers "This sale can't be paid" and "Customers in Talabat can't pay at this till: use one with Talabat."
No rule for the customer's group, or for any group above it The payment screen opens as always
A refund, the returned items of an exchange, a return rung without its sale Not judged: the refund choices open as always
An exchange's new items Judged as a sale. An exchange pays them with store credit: an Only these rule that does not list the store-credit method stops that group's exchanges
The service down, or the shop's records unreadable The check's down answer: the sale goes on with every method and is flagged on Sales to review

Which rule decides. One rule per customer group, either Only these payment methods or Every payment method but these. A customer takes their own group's rule; a group with no rule takes the rule of the nearest group above it in the shop's customer group tree. A group's own rule replaces the rule above it entirely: a method the rule above leaves out comes back unless the group's own rule leaves it out too. So two rules cover on-account credit for account customers only:

Customer group Rule Methods
All Customer Groups Every payment method but these On Account
Account customers Only these payment methods Cash, Credit Card, On Account

A customer in Retail (under All Customer Groups) cannot buy on account; a customer in Account customers, or a group below it, can.

What the shop does

  1. Install the app from the App library (or paste its manifest into Retail Extension Package in Desk), read what it will do and consent. The install adds the record type PP PMR Rule, the role PP PMR Integration, the check and the feed registration, the check switched off. Nothing changes at the till yet.
  2. Make the app's integration user (the integration user recipe): tick Is Desk User, give it the role PP PMR Integration alone and generate its API key. In Role Permissions, give that role read on Customer Group (the service reads the group tree). Choose the user on the feed registration PP PMR Rules feed, then press Connect again on the app's record, which sends that user's key to the service.
  3. Write the rules in PP PMR Rule: one per customer group that needs one. The payment methods are the shop's own Mode of Payment records, as the till offers them (Cash, Credit Card, On Account). Words the cashier reads is optional: blank, the app writes "Customers in ⟨group⟩ pay with ⟨methods⟩." or "Not for customers in ⟨group⟩."
  4. Switch the check on: open Payment method rules in Retail Extension Subscription, read what is sent, tick the consent, choose the POS Profiles, and switch it on.

Where it shows. The rules are Desk records the shop keeps (its System Manager, or a role the shop gives the rights to in Role Permissions: that role also needs Select on Customer Group and Mode of Payment, or the rule's lookups answer nothing). At the till the cashier meets them at Pay: the methods left out are dimmed with the rule's words.

What leaves the shop. At Pay, and before each refund the till pays, the priced basket goes to the service's address: each line's item, group, quantity and amounts, the totals, the store, till, POS day and terminal, the cashier's user, the customer and their customer group, the coupons, the sale details the cashier captured and the payment methods offered; never a card. The service reads the shop's rule records and its customer group tree with the integration user's key, keeps them one minute, and keeps nothing of a sale. It writes nothing. A hosted copy holds each shop's check secret and its user's API key from Connect again until the shop removes the app. Say so on your card.

The files

File What it is
manifest.json the record type PP PMR Rule (one per customer group, named by it) and its table PP PMR Rule Method, a feed registration (it names the app's one integration user), a help address, and one check, installed switched off; when the service is down the sale goes on, flagged
payrules.py the pure core: the signature check (verify), the shape check, the shop's rules (rules_of) and tree (tree_of), the rule that decides (deciding) and the answer (on_check)
service/app.py the service, standard library only: POST /pmr/check, GET /health, and the app template's handshake for many shops; one handle answers the web server and the function entry (lambda_handler) alike
Dockerfile · app.json the settings file for hosting ("runs": "function": on CitiXsys hosting it is a function, paid per call) and an image for your own server (built from the kit's root)
tests/ the rules, the service over the wire with signed calls (one shop and many), the shop's reads against a stand-in shop, every answer against the published contract, the manifest; canaries.py breaks each guarded rule and expects its test to fail

Run it

python3 -m unittest discover -s samples/s46_payment_method_rules/tests -p 'test_*.py'
python3 samples/s46_payment_method_rules/tests/canaries.py
python3 samples/s46_payment_method_rules/service/app.py samples/s46_payment_method_rules/service/.env.local

Settings, one shop (service/.env.local, never committed): IVN_CHECK_SECRET (handed back at install as pp_pmr:sub:methods), IVN_SHOP_URL, IVN_SHOP_KEY (<api key>:<api secret> of the integration user), PORT. PMR_PREFIX names the rule record type (default PP PMR).

Many shops, hosted

The service is the app template's shape: set IVN_LIBRARY_APP and a store (IVN_SHOPS_TABLE on CitiXsys hosting, else IVN_SHOPS_FILE). Each shop connects itself after its install and hands over the check's secret; Connect again hands over its integration user's key. Until the key arrives the service answers 503 and the down answer applies. Every call names its shop (X-iVendNext-Site), and each shop is answered from its own rules with its own key.

Make it your own

What a partner usually changes:

Before you copy it

Technical notes

Why it is built this way

Option Cost Verdict
Do nothing: one POS Profile per kind of customer, each with its own methods 0 a delivery platform's customers need their own till, and an account customer at an ordinary till is still offered On account
A manifest only: a field on Customer Group naming its methods ~½ day nothing reads it at the till; a manifest cannot answer a check
A check before payment, answered by a function that leaves methods out ~1 day picked: the rule holds at every door that takes money, on every till the shop switches it on for, in the shop's own words; S32's service shape and S44's group-tree walk reused

The answer, exactly

Bounds, stated

Needs this serves

This page in the kit