# Live merchant checkout integration This is a **separate, initially disabled** production integration, not an upgrade of the existing sandbox SDKs or store plugins. The separately named `woocommerce-live` and `opencart-live` candidates use this protocol. Each has its own supported host versions and limitations; native host-install and bounded authorized payment tests are still required separately for each candidate. Neither is enabled by a code deployment. Never put a provider password or a live merchant key in browser code, a URL, a Git repository, a support message or a log. ## Merchant setup 1. Complete business review, email verification, MFA and reviewed website origin. 2. Submit the merchant's beneficiary record through `/app/splits`. Staff send the required private information to AsanPardakht and record the genuine approval reference. Submission is **not approval**. This code does not send paperwork to the provider automatically or invent evidence. 3. Normal Asan production/domain/IP/amount gates, invoice issuance, the approved split capability and exact `settlementPortions` wire confirmation must pass. The owner must separately authorize `ASAN_IPG_MERCHANT_API_ENABLED=1`. 4. From `/app/gateway`, issue a new live key using the account password and MFA. The raw key appears once. Save it privately on the store server. It is bound to one owned beneficiary approval revision and the reviewed website origin. This first checkout allocates **100%** of each transaction to that approved beneficiary. No company fee, affiliate share, refund, wallet credit or arbitrary bank transfer is inferred or deducted. A future commercial fee needs an explicit, approved allocation and separate accounting evidence; never treat the PSP's fee as Sayapay-earned revenue. ## Server API Send `Authorization: Bearer `. Test keys and browser Origin/Sec-Fetch-Site requests are refused. Use IRR integer amounts, not tomans. - `POST /api/ipg/merchant/payments`: JSON `{order_id,title,amount,return_url}` and a persisted `Idempotency-Key` header (8–128 ASCII letters/digits/`._:-`). `return_url` must be HTTPS on the merchant's exact reviewed origin. - `GET /api/ipg/merchant/payments/`: read the saved authoritative status, scoped to the authenticated merchant. - `POST /api/ipg/merchant/payments//verify` with `{}`: the same saved evidence, **not** an instruction to replay a bank verification. The merchant must load title, amount and order ID from its own database; never forward the buyer's untrusted totals. Save the returned payment ID and checkout URL against that order before redirecting the buyer. The checkout URL is always on `https://saya-pay.com/ipg/pay/...`. The buyer returns from Shaparak to Sayapay's existing signed/capability-bound callback. Inquiry, exact amount/order matching, Verify and Settlement stay in that existing server-side state machine. The receipt provides a separate “return to store” link to the frozen reviewed URL; **that navigation is not proof of payment**. There is no unverified `paid=true` callback and no automatic server-to-server notification in this milestone. After the customer returns, the store server reads status using the saved payment ID and matches ID/order ID/IRR amount. Fulfil only when `payment_verified` is true and `state` is `settlement_requested` or `settled`. `merchant-live-client.mjs` provides `createMerchantClient` and `merchantOrderPaid` for this policy. Neither Settlement nor that fulfilment policy proves final credit in the bank account: `bank_credit_status` remains `not_reconciled`. ## Retry and revocation A timeout is unknown, not failed. Do not generate another order or idempotency key. Reuse the original request/key, inspect its saved result and ask support if needed. An uncertain Token/Verify/Settlement is never replayed by this API. Key revocation, changed approval/origin or issuance pause stops new Token and redirect issuance. Already-attempted bank operations can still reconcile without that key; a valid replacement key for the same merchant can read historical receipts. Existing test keys, sandbox financial history and balances are untouched. ## Release boundary Migration `024_ipg_merchant_checkout.sql`, reviewed runtime grants, candidate tests and a separately authorized release are required. Keep new issuance disabled until actual beneficiary approval and a bounded merchant checkout test succeed. Local mocked tests are not proof of a production payment or bank-account credit. For platform-specific setup and limitations, see the standalone candidate's guide: - `woocommerce-live/README-fa.md`: WooCommerce classic checkout and CPT only; HPOS and external persistent object caches are refused by this candidate. - `opencart-live/README-fa.md`: OpenCart 3 only, not OpenCart 4; the separate live extension must remain disabled until its own host acceptance is complete. Neither candidate converts existing sandbox orders or keys. The six original sandbox downloads remain sandbox-only; changing their key prefix does not upgrade them to this protocol. Local host doubles, a downloadable ZIP or a successful build are not proof of a native host installation or a real payment.