git / moonbite-network / templates/merchant.html · raw

{% extends "base.html" %}{% block body_class %}mb-v2{% endblock %}{% block title %}Accept MBITE Payments - MoonBite Merchants{% endblock %}{% block nav_active %}merchants{% endblock %}{% block content %}<div class="main-content">    <section class="hero">        <h2>Accept MoonBite Payments</h2>        <p>Non-custodial invoicing: customers pay your own address, wallet to wallet. The server only observes the chain.</p>    </section>    <div class="cards-grid">        <div class="card">            <div class="card-header">Self-Custody</div>            <div class="card-body">                <p>Payments land directly on an address you control. MoonBite never holds coins, keys, or balances on your behalf.</p>            </div>        </div>        <div class="card">            <div class="card-header">No Platform Fee</div>            <div class="card-body">                <p>There is no merchant fee. The only cost is the ordinary network transaction fee the payer attaches to their transaction.</p>            </div>        </div>        <div class="card">            <div class="card-header">Chain-Verified</div>            <div class="card-body">                <p>An invoice is marked paid only when a new inbound payment of at least the invoiced amount is observed on chain above the balance snapshot taken when the invoice was raised.</p>            </div>        </div>        <div class="card">            <div class="card-header">Token-Gated</div>            <div class="card-body">                <p>Registering returns a manage token once. Only that token can raise invoices against your address or read your ledger.</p>            </div>        </div>    </div>    <div class="card card-full">        <div class="card-header">How It Works</div>        <div class="card-body">            <ol class="info-list" style="list-style-type: decimal;">                <li><strong>Get a receive address</strong> from your own MoonBite wallet. Use a dedicated address for invoicing and do not spend from it while invoices are open.</li>                <li><strong>Register once</strong> with <code>POST /api/merchants</code>. The response includes <code>manage_token</code> exactly once. Store it like a password; it is never shown again.</li>                <li><strong>Create an invoice</strong> with <code>POST /api/merchant/invoice</code>, sending your merchant id and the token in the <code>X-Merchant-Token</code> header.</li>                <li><strong>Show the customer</strong> the returned <code>pay_uri</code> or the QR at <code>/api/merchant/invoice/&lt;id&gt;/qr.svg</code>. They pay from their wallet.</li>                <li><strong>Confirm payment</strong> by polling <code>GET /api/merchant/invoice/&lt;id&gt;</code> until <code>status</code> is <code>paid</code>, or sweep all open invoices with <code>POST /api/merchant/invoices/poll</code>.</li>            </ol>            <p style="margin-top: 1rem; color: var(--text-secondary);">                Invoices expire after one hour if unpaid. While network hashrate is low, wait for a comfortable number of confirmations before releasing high-value goods.            </p>        </div>    </div>    <div class="card card-full">        <div class="card-header">1. Register a Merchant</div>        <div class="card-body">            <pre class="code-block"><code>POST /api/merchantsContent-Type: application/json{  "name": "Your Shop",  "category": "goods",  "mbite_address": "&lt;your MoonBite receive address&gt;",  "url": "https://example.com",  "blurb": "What you sell"}201 Created{  "status": "success",  "merchant": {    "id": "&lt;merchant_id&gt;",    "name": "Your Shop",    "mbite_address": "&lt;your MoonBite receive address&gt;",    "manage_token": "&lt;shown once, store it securely&gt;"  }}</code></pre>            <p style="color: var(--text-secondary);">Categories: goods, services, food, digital, donation, other. The token is not recoverable; if it is lost, register again.</p>        </div>    </div>    <div class="card card-full">        <div class="card-header">2. Create an Invoice</div>        <div class="card-body">            <pre class="code-block"><code>POST /api/merchant/invoiceContent-Type: application/jsonX-Merchant-Token: &lt;manage_token&gt;{  "merchant_id": "&lt;merchant_id&gt;",  "amount": "12.5",  "memo": "Order 1042"}201 Created{  "status": "success",  "invoice": {    "id": "&lt;invoice_id&gt;",    "address": "&lt;your MoonBite receive address&gt;",    "amount": "12.5",    "status": "pending",    "seconds_left": 3600,    "pay_uri": "moonbite:&lt;address&gt;?amount=12.5&amp;label=Order%201042"  }}</code></pre>            <p style="color: var(--text-secondary);">                The invoice is always raised against your registered address. Requests without a valid token, or naming any other address, are refused. Rate limit: 30 per minute per client.            </p>        </div>    </div>    <div class="card card-full">        <div class="card-header">3. Check Payment</div>        <div class="card-body">            <pre class="code-block"><code>GET /api/merchant/invoice/&lt;invoice_id&gt;200 OK{  "status": "success",  "invoice": {    "id": "&lt;invoice_id&gt;",    "status": "paid",    "paid_units": 1250000000,    "paid_at": 1760000000  }}GET /api/merchant/invoice/&lt;invoice_id&gt;/qr.svgimage/svg+xml encoding the pay_uri</code></pre>            <p style="color: var(--text-secondary);">                Status is one of pending, paid, expired. Anyone holding the invoice id may poll it, so share ids only with the paying customer. Each poll may trigger a chain scan; polls are rate-limited and share a global scan budget, so a 503 with Retry-After means try again shortly.            </p>        </div>    </div>    <div class="card card-full">        <div class="card-header">4. Ledger and Sweep (authenticated)</div>        <div class="card-body">            <pre class="code-block"><code>GET /api/merchant/invoices?merchant_id=&lt;merchant_id&gt;X-Merchant-Token: &lt;manage_token&gt;POST /api/merchant/invoices/pollContent-Type: application/jsonX-Merchant-Token: &lt;manage_token&gt;{ "merchant_id": "&lt;merchant_id&gt;" }200 OK{ "status": "success", "checked": 3, "paid": ["..."], "expired": [], "addresses_scanned": 1 }</code></pre>            <p style="color: var(--text-secondary);">                Send the token only in the header, never in the URL. Both calls return only your own merchant's invoices.            </p>        </div>    </div>    <div class="card card-full">        <div class="card-header">Directory</div>        <div class="card-body">            <p>Registered merchants are listed publicly at <code>GET /api/merchants</code> (optionally <code>?category=food</code>). Manage tokens are never included in directory reads.</p>        </div>    </div></div>{% endblock %}