clean and refine product docs structure
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Integration Notes & Schema Touchpoints — Balinyaar docs</title>
|
||||
<link rel="stylesheet" href="../assets/doc.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="layout">
|
||||
<aside class="sidebar">
|
||||
<a class="brand" href="../index.html"><span class="dot"></span> Balinyaar docs</a>
|
||||
<p class="tagline">Trust-first home-nursing marketplace · Iran</p>
|
||||
<nav><div class="group"><div class="label">Start here</div><ul><li><a href="../index.html">Docs home</a></li><li><a href="../overview/platform-summary.html">Platform summary & ground truths</a></li></ul></div><div class="group"><div class="label">Business requirements</div><ul><li><a href="../business/index.html">Overview & MVP scope</a></li><li><a href="../business/01-actors-and-onboarding.html">1. Actors & onboarding</a></li><li><a href="../business/02-nurse-verification.html">2. Nurse verification</a></li><li><a href="../business/03-service-catalog-and-pricing.html">3. Service catalog & pricing</a></li><li><a href="../business/04-search-and-matching.html">4. Search & matching</a></li><li><a href="../business/05-booking-and-scheduling.html">5. Booking & scheduling</a></li><li><a href="../business/06-evv-and-service-delivery.html">6. EVV / service delivery</a></li><li><a href="../business/07-cancellation-and-refunds.html">7. Cancellation & refunds</a></li><li><a href="../business/08-payments-and-escrow.html">8. Payments & escrow</a></li><li><a href="../business/09-installments-bnpl.html">9. Installments / BNPL</a></li><li><a href="../business/10-payouts.html">10. Payouts to nurses</a></li><li><a href="../business/11-reviews-trust-and-safety.html">11. Reviews, trust & safety</a></li><li><a href="../business/12-messaging-and-emergencies.html">12. Messaging & emergencies</a></li><li><a href="../business/13-tax-invoicing-and-legal.html">13. Tax, invoicing & legal</a></li><li><a href="../business/14-notifications-and-admin.html">14. Notifications & admin</a></li></ul></div><div class="group"><div class="label">Database model</div><ul><li><a href="../data-model/index.html">Overview & decisions</a></li><li><a href="../data-model/diagrams.html">Diagrams</a></li><li><a href="../data-model/01-identity-and-access.html">1. Identity & access</a></li><li><a href="../data-model/02-geography.html">2. Geography</a></li><li><a href="../data-model/03-services-and-pricing.html">3. Services & pricing</a></li><li><a href="../data-model/04-verification-and-credentials.html">4. Verification & credentials</a></li><li><a href="../data-model/05-booking-and-scheduling.html">5. Booking & scheduling</a></li><li><a href="../data-model/06-payments-ledger-and-refunds.html">6. Payments, ledger & refunds</a></li><li><a href="../data-model/07-payouts.html">7. Payouts</a></li><li><a href="../data-model/08-bnpl.html">8. BNPL / installments</a></li><li><a href="../data-model/09-messaging.html">9. Messaging</a></li><li><a href="../data-model/10-reviews-and-records.html">10. Reviews & records</a></li><li><a href="../data-model/11-notifications.html">11. Notifications</a></li><li><a href="../data-model/12-audit-config-and-reference.html">12. Audit, config & reference</a></li><li><a href="../data-model/13-partner-centers-and-future.html">13. Partner centers & future</a></li></ul></div><div class="group"><div class="label">Payments deep-dive</div><ul><li><a href="index.html">Overview & exec summary</a></li><li><a href="iranian-payment-reality.html">Iranian payment reality</a></li><li><a href="escrow-ledger.html">Escrow as a ledger</a></li><li><a href="bnpl-landscape.html">BNPL landscape & finding</a></li><li><a href="cancellation-and-payout.html">Cancellation & nurse payout</a></li><li><a class="active" href="integration-notes.html">Integration & schema touchpoints</a></li><li><a href="sources.html">Recommendations & sources</a></li></ul></div><div class="group"><div class="label">Research & strategy</div><ul><li><a href="../research/index.html">Overview & exec summary</a></li><li><a href="../research/market-and-competitors.html">Market & competitors</a></li><li><a href="../research/problems-and-risks.html">Problems & risks</a></li><li><a href="../research/verification.html">Verification (research)</a></li><li><a href="../research/legal-landscape.html">Legal landscape</a></li><li><a href="../research/go-to-market.html">Go-to-market & sources</a></li></ul></div><div class="group"><div class="label">Notes & more</div><ul><li><a href="../notes/open-questions.html">Open questions</a></li><li><a href="../notes/future-ideas.html">Future ideas</a></li><li><a href="../wireframes/index.html">Wireframes</a></li><li><a href="../fa/index.html">Farsi documents</a></li></ul></div></nav>
|
||||
</aside>
|
||||
<main class="main"><div class="content">
|
||||
<div class="topbar"><button class="theme-toggle" type="button" onclick="__t()">theme</button></div>
|
||||
<p><a href="index.html">← Payments overview</a></p>
|
||||
<h1 id="integration-notes-schema-touchpoints">Integration Notes & Schema Touchpoints</h1>
|
||||
<h2 id="8-integration-notes">8. Integration notes <a class="anchor" href="#8-integration-notes" aria-hidden="true">#</a></h2>
|
||||
<h3 id="81-snapppay-اسنپپی-primary">8.1 SnappPay (اسنپپی) — primary <a class="anchor" href="#81-snapppay-اسنپپی-primary" aria-hidden="true">#</a></h3>
|
||||
<p>API-based with an IPG redirect. Endpoint paths are <strong>VERIFIED</strong> against the open-source Laravel package and match exactly:</p>
|
||||
<pre><code>POST api/online/v1/oauth/token → OAuth bearer token
|
||||
GET api/online/offer/v1/eligible → eligibility / credit check on the customer
|
||||
POST api/online/payment/v1/token → payment token → redirect customer to SnappPay
|
||||
POST api/online/payment/v1/verify → verify after callback
|
||||
POST api/online/payment/v1/settle → settle (capture the merchant lump)
|
||||
POST api/online/payment/v1/revert → full reversal
|
||||
POST api/online/payment/v1/cancel → cancel
|
||||
POST api/online/payment/v1/update → partial (new amount strictly lower)
|
||||
GET api/online/payment/v1/status → status</code></pre>
|
||||
<p>Credentials issued only after a signed contract + business-license review: <code>user_name</code>, <code>password</code>, <code>client_id</code>, <code>client_secret</code>, merchant/customer number, security code, <code>base_url</code>. Sandbox availability is plausible (issued by sales) but <strong>TO BE CONFIRMED</strong> — the public package does not evidence it.</p>
|
||||
<blockquote><p><strong>WARNING:</strong> the <code>SnapPayInc/open-api-java-sdk</code> GitHub repo is the <strong>unrelated CANADIAN SnapPay</strong> (snappay.ca, CAD) — <strong>do NOT use it</strong>. Likewise, English searches for "digipay split payment" return <strong>DigiPay.Guru</strong>, an unrelated white-label vendor — not the Iranian Digipay.</p>
|
||||
</blockquote>
|
||||
<h3 id="82-digipay-دیجیپی-secondary-fallback">8.2 Digipay (دیجیپی) — secondary / fallback <a class="anchor" href="#82-digipay-دیجیپی-secondary-fallback" aria-hidden="true">#</a></h3>
|
||||
<p>Unified <strong>UPG</strong> gateway, server-side + hosted redirect:</p>
|
||||
<pre><code>POST /digipay/api/tickets/business?type=… → ticket + redirectUrl (type MUST match product)
|
||||
(callback to merchant)
|
||||
POST /digipay/api/purchases/verify → verify (re-check amount + providerId before trusting)
|
||||
POST /digipay/api/purchases/deliver?type=… → delivery confirmation (Credit=5 / BNPL=13) — GATE ON EVV CHECK-OUT
|
||||
POST /digipay/api/refunds?type=… → refund (providerId, amount, saleTrackingCode)
|
||||
GET /digipay/api/refunds/{InquiryId} → poll refund status
|
||||
POST /digipay/api/reverse → manual reverse (~25 min, IPG/DPG only)</code></pre>
|
||||
<p><strong>Type codes (VERIFIED, first-party):</strong> IPG=0, Wallet=11, Credit=5, BNPL=13, Credit-Card=24 — <strong>persist the gateway type per transaction</strong>; deliver/refund calls must carry the matching code. Each purchase supports <strong>EITHER refund OR manual reverse, not both</strong> — store a mutually-exclusive reversal-mode flag. For a <em>service</em>, the "delivery" is the completed visit, so <strong>gate <code>deliver</code> on the nurse's EVV check-out.</strong> A BNPL refund returns to the customer's Digipay credit/wallet (or bank/SHEBA), <strong>not</strong> the original card.</p>
|
||||
<h3 id="83-cross-cutting-integration-rules">8.3 Cross-cutting integration rules <a class="anchor" href="#83-cross-cutting-integration-rules" aria-hidden="true">#</a></h3>
|
||||
<ul>
|
||||
<li><strong>Webhook idempotency:</strong> every PSP/BNPL callback is at-least-once and retried. Upsert into <strong><code>payment_webhook_events</code></strong> keyed <code>UNIQUE(external_event_id)</code> <strong>first</strong>, inside the same transaction that mutates money state, and <strong>no-op on duplicate</strong> — prevents double-confirm / double-settle / double-refund.</li>
|
||||
<li><strong>Never trust the callback alone</strong> — always <code>verify</code> server-side and re-check <code>amount</code> + <code>providerId</code>/reference before treating funds as captured.</li>
|
||||
<li><strong>Amounts in IRR Rials as <code>BIGINT</code></strong> everywhere; SnappPay/Digipay quote in <strong>Toman</strong> at the API boundary — store a <code>currency</code> field on the BNPL row and <strong>convert only at the boundary, never internally.</strong></li>
|
||||
<li><strong>State-machine guard</strong> on BNPL status transitions (<code>eligible → token_issued → verified → settled → reverted</code>) so callbacks/retries cannot double-settle or double-refund.</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<h2 id="9-schema-touchpoints">9. Schema touchpoints <a class="anchor" href="#9-schema-touchpoints" aria-hidden="true">#</a></h2>
|
||||
<p>Final, aligned table/field names (these supersede <code>installment_plans</code> / <code>installment_entries</code>). The canonical entity definitions live in the data model: <a href="../data-model/06-payments-ledger-and-refunds.html">payments, ledger & refunds</a> and <a href="../data-model/08-bnpl.html">BNPL</a>.</p>
|
||||
<ul>
|
||||
<li><strong><code>bnpl_transactions</code></strong> (new, <strong>replaces <code>installment_plans</code></strong>; <code>installment_entries</code> <strong>CUT</strong>) — 1:1 with a <code>payment_transaction</code>. Fields: <code>payment_transaction_id</code> FK UNIQUE, <code>provider_code</code>, <code>merchant_of_record</code>, <code>external_payment_token</code>, <code>external_transaction_id</code>, <code>eligibility_status</code>, <code>order_amount_irr</code>, <code>settled_amount_irr</code> (net of provider commission), <code>bnpl_commission_irr</code>, <code>currency</code> (<code>IRR</code>/<code>TOMAN</code>), <code>status</code> (<code>eligible</code>/<code>token_issued</code>/<code>verified</code>/<code>settled</code>/<code>reverted</code>/<code>cancelled</code>/<code>failed</code>), <code>installment_count</code> (default 4, informational only), <code>settled_at</code>, <code>revert_transaction_id</code>, <code>reverted_amount_irr</code>, <code>reverted_at</code>, <code>refund_channel</code>, <code>callback_payload_json</code>.</li>
|
||||
<li><strong><code>payment_transactions</code></strong> — keep full gateway response + Shaparak reference; <strong>ADD</strong> a filtered <code>UNIQUE(gateway_reference_code) WHERE NOT NULL</code> and a filtered <code>UNIQUE(booking_id) WHERE status='succeeded'</code> (single capture per booking; idempotent retries).</li>
|
||||
<li><strong><code>payment_webhook_events</code></strong> (new) — <code>provider_code</code>, <code>event_type</code>, <code>external_event_id UNIQUE</code>, <code>payload_json</code>, <code>signature_valid</code>, <code>processing_status</code> (<code>received</code>/<code>processed</code>/<code>failed</code>/<code>ignored</code>), <code>related_payment_transaction_id</code> NULL, <code>received_at</code>, <code>processed_at</code>.</li>
|
||||
<li><strong><code>refunds</code></strong> — <strong>1:N</strong> per <code>payment_transaction</code> (the original "1:1" claim is wrong); <strong>ADD</strong> <code>platform_fee_refunded_irr</code>, <code>nurse_payout_refunded_irr</code> (fee-leg decomposition), <code>refund_channel</code> (<code>psp_card</code>/<code>bnpl_revert</code>/<code>manual_bank</code>), <code>external_revert_reference</code>, <code>expected_customer_refund_eta</code>; app invariant <code>Σ refunded ≤ captured</code>.</li>
|
||||
<li><strong><code>ledger_entries</code></strong> (new) — <code>transaction_group_id</code>, <code>account_type</code> (<code>escrow_held</code>/<code>platform_revenue</code>/<code>nurse_payable</code>/<code>refund_payable</code>/<code>bnpl_fee_expense</code>/<code>nurse_clawback_receivable</code>), <code>nurse_id</code> NULL, <code>direction</code>, <code>amount_irr</code>, <code>booking_id</code> NULL, <code>source_ref_type</code>, <code>source_ref_id</code>, <code>memo</code>, <code>created_at</code>. Append-only; balanced per group.</li>
|
||||
<li><strong><code>nurse_clawbacks</code></strong> (new) — <code>nurse_id</code>, <code>booking_id</code>, <code>refund_id</code>, <code>amount_irr</code>, <code>status</code> (<code>pending</code>/<code>recovered</code>/<code>written_off</code>), <code>recovered_in_payout_id</code> NULL, <code>created_at</code>, <code>resolved_at</code>.</li>
|
||||
<li><strong><code>payment_gateways</code></strong> — encrypted provider config in <code>config_json</code> / secrets: SnappPay <code>client_id</code>, <code>client_secret</code>/<code>username</code>+<code>password</code>, merchant number, security code, <code>base_url</code>, <code>sandbox</code> flag. <strong>Never</strong> store credentials per-transaction.</li>
|
||||
</ul>
|
||||
<p><strong>Supporting changes:</strong> <code>bookings</code> gets the three-way split (<code>gross_price_irr</code>, <code>balinyaar_commission_irr</code>, <code>nurse_payout_amount</code>) and <code>dispute_window_ends_at</code>; <code>payout_released</code> BIT is <strong>CUT</strong> (derive from <code>nurse_payout_booking_links</code> + ledger). <code>nurse_payouts</code> gets <code>gross_earnings_irr</code>, <code>clawback_applied_irr</code>, <code>net_amount_irr</code>. An <strong><code>invoices</code></strong> table (minimal) captures the commission VAT line.</p>
|
||||
<a class="back-to-top" href="#">↑ Back to top</a>
|
||||
</div></main>
|
||||
</div>
|
||||
<script>
|
||||
(function(){var k='balinyaar-docs-theme';var s=localStorage.getItem(k);
|
||||
if(s)document.documentElement.setAttribute('data-theme',s);
|
||||
else if(matchMedia('(prefers-color-scheme: dark)').matches)document.documentElement.setAttribute('data-theme','dark');})();
|
||||
function __t(){var d=document.documentElement;var n=d.getAttribute('data-theme')==='dark'?'light':'dark';
|
||||
d.setAttribute('data-theme',n);localStorage.setItem('balinyaar-docs-theme',n);}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user