End-to-End Flow: From Merchant Signup to Settlement
- Phase 1: Merchant Onboarding
- Phase 2: Customer Makes Purchase
- Phase 3: FluxaPay Processes Payment Request
- Phase 4: Customer Completes Payment
- Phase 5: FluxaPay Detects & Verifies Payment
- Phase 6: Notify Merchant
- Phase 7: Fund Sweeping
- Phase 8: Settlement to Merchant
- Complete Flow Summary
-
Merchant visits
fluxapay.com/signup -
Fills registration form:
- Business name: "Cool Shop"
- Email: merchant@coolshop.com
- Country: Nigeria
- Settlement currency: NGN
- Bank details: (for fiat settlements)
-
Submits form → FluxaPay Backend
Backend Process:
-
Generate unique
merchant_id:"merch_abc123" -
Store merchant profile in database:
{
"merchant_id": "merch_abc123",
"business_name": "Cool Shop",
"email": "merchant@coolshop.com",
"country": "NG",
"settlement_currency": "NGN",
"bank_account": {...},
"api_key": "sk_live_xyz789",
"webhook_url": null,
"status": "active",
"created_at": "timestamp"
}- Register merchant in Merchant Registry Contract (Stellar):
register_merchant(
merchant_id: "merch_abc123",
business_name: "Cool Shop",
settlement_currency: "NGN"
)- Send welcome email with:
- API credentials
- Dashboard login
- Integration docs
Merchant Dashboard:
-
Logs into
dashboard.fluxapay.com -
Configures settings:
- Sets webhook URL:
https://coolshop.com/webhooks/fluxapay - Generates API keys
- Reviews settlement schedule (daily/weekly)
- Sets webhook URL:
-
Integrates FluxaPay into their website
- Adds payment button
- Implements API calls
Customer Journey:
-
Customer (Alice) browses
coolshop.com -
Adds items to cart:
- Wireless Headphones: $45
- Phone Case: $5
- Total: $50
-
Proceeds to checkout
-
Selects payment method:
- ○ Credit Card
- ○ Bank Transfer
- ● Pay with Crypto (USDC) ✓
-
Clicks "Pay with Crypto"
Cool Shop Backend API Call:
POST https://api.fluxapay.com/v1/payments
Authorization: Bearer sk_live_xyz789
Content-Type: application/json{
"amount": 50,
"currency": "USDC",
"customer_email": "alice@email.com",
"order_id": "order_12345",
"metadata": {
"customer_name": "Alice",
"items": ["Headphones", "Phone Case"]
},
"success_url": "https://coolshop.com/order/success",
"cancel_url": "https://coolshop.com/cart"
}FluxaPay Backend Process:
-
Receive payment creation request
-
Generate unique
payment_id:"pay_xyz789" -
Derive unique Stellar address using HD Wallet:
HD Wallet Derivation: - Master Seed: [SECURED_MASTER_SEED] - Derivation path: master_seed → merch_abc123 → pay_xyz789 - Generated Keypair: * Public Key (address): GPAY_XYZ789...AAA * Secret Key: SPAY_SECRET...BBB (stored encrypted) -
Create Stellar account for this payment:
- Check if
GPAY_XYZ789...AAAexists on Stellar - If not, create account:
- Send 0.5 XLM from FluxaPay's funding account
- Establish trustline for USDC
- Check if
-
Store payment in Payment Contract (Stellar):
create_payment(
payment_id: "pay_xyz789",
merchant_id: "merch_abc123",
amount: 50,
currency: "USDC",
deposit_address: "GPAY_XYZ789...AAA",
status: "pending",
customer_email: "alice@email.com",
order_id: "order_12345",
metadata: {...},
expires_at: now + 30 minutes
)- Store in PostgreSQL database:
INSERT INTO payments (
payment_id, merchant_id, amount, currency,
deposit_address, status, created_at, expires_at
) VALUES (
'pay_xyz789', 'merch_abc123', 50, 'USDC',
'GPAY_XYZ789...AAA', 'pending', NOW(), NOW() + INTERVAL '30 minutes'
)- Emit webhook:
payment.created
POST https://coolshop.com/webhooks/fluxapay{
"event": "payment.created",
"payment_id": "pay_xyz789",
"status": "pending",
"amount": 50,
"currency": "USDC"
}- Return response to Cool Shop:
{
"payment_id": "pay_xyz789",
"deposit_address": "GPAY_XYZ789...AAA",
"amount": 50,
"currency": "USDC",
"status": "pending",
"expires_at": "2026-01-20T15:30:00Z",
"checkout_url": "https://pay.fluxapay.com/pay_xyz789"
}Cool Shop Backend:
-
Receives FluxaPay response
-
Redirects Alice to:
https://pay.fluxapay.com/pay_xyz789OR embeds FluxaPay checkout widget on their page
FluxaPay Checkout Page (pay.fluxapay.com/pay_xyz789):
┌──────────────────────────────────────────────────┐
│ 🔒 Secure Payment - FluxaPay │
├──────────────────────────────────────────────────┤
│ │
│ Pay Cool Shop │
│ Order #12345 │
│ │
│ Amount: 50 USDC │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ Send USDC on Stellar Network to: │ │
│ │ │ │
│ │ GPAY_XYZ789...AAA │ │
│ │ [Copy Address] [Show QR Code] │ │
│ └────────────────────────────────────────────┘ │
│ │
│ ⏱️ Payment expires in: 28:45 │
│ │
│ 💡 How to pay: │
│ 1. Open your Stellar wallet (Lobstr, etc.) │
│ 2. Send exactly 50 USDC to the address above │
│ 3. Wait for confirmation │
│ │
│ Status: ⏳ Waiting for payment... │
│ [Checking blockchain...] │
│ │
└──────────────────────────────────────────────────┘
Page auto-refreshes every 5 seconds to check payment status
Alice's Actions:
-
Opens Stellar wallet app (e.g., Lobstr)
-
Clicks "Send"
-
Enters:
- Recipient:
GPAY_XYZ789...AAA(copies from FluxaPay page) - Amount: 50 USDC
- Asset: USDC
- Recipient:
-
Reviews transaction
-
Confirms and signs transaction
-
Transaction submitted to Stellar network
- Transaction Hash:
TXN_HASH_ABC123...
- Transaction Hash:
-
Stellar network processes (3-5 seconds)
-
✅ Transaction confirmed on blockchain
FluxaPay Oracle Service (runs continuously):
Every 3 seconds:
- Query database for active pending payments:
SELECT * FROM payments
WHERE status = 'pending'
AND expires_at > NOW()Results: [..., pay_xyz789, ...]
- For each pending payment, check Stellar blockchain:
GET https://horizon.stellar.org/accounts/GPAY_XYZ789...AAA/transactions- Oracle sees new transaction:
{
"hash": "TXN_HASH_ABC123...",
"source_account": "GALICE_WALLET...XYZ",
"created_at": "2026-01-20T15:05:30Z",
"operations": [
{
"type": "payment",
"from": "GALICE_WALLET...XYZ",
"to": "GPAY_XYZ789...AAA",
"asset_code": "USDC",
"amount": "50.0000000"
}
]
}-
Oracle validates:
- ✓ Destination address matches
- ✓ Asset is USDC
- ✓ Amount matches expected (50 USDC)
- ✓ Payment hasn't expired
- ✓ Payment status is still "pending"
- ✓ Transaction hash not already processed
-
✅ Validation successful → Proceed to verification
Oracle → Payment Contract (Stellar):
verify_payment(
payment_id: "pay_xyz789",
transaction_hash: "TXN_HASH_ABC123...",
payer_address: "GALICE_WALLET...XYZ",
amount_received: 50
)Smart Contract Execution:
-
Load payment data from contract state:
payment = get_payment("pay_xyz789")
-
Verify conditions:
payment.status == "pending"✓payment.amount == 50✓transaction_hash not in processed_transactions✓payment.expires_at > current_time✓
-
Update payment state:
payment.status = "confirmed" payment.confirmed_at = current_timestamp payment.transaction_hash = "TXN_HASH_ABC123..." payment.payer_address = "GALICE_WALLET...XYZ"
-
Add transaction to processed list:
processed_transactions.push("TXN_HASH_ABC123...")
-
Save to contract storage
-
Emit event:
PaymentConfirmed { payment_id: "pay_xyz789", merchant_id: "merch_abc123", amount: 50, transaction_hash: "TXN_HASH_ABC123..." }
-
Return success to Oracle
Oracle → PostgreSQL:
UPDATE payments
SET
status = 'confirmed',
confirmed_at = NOW(),
transaction_hash = 'TXN_HASH_ABC123...',
payer_address = 'GALICE_WALLET...XYZ'
WHERE payment_id = 'pay_xyz789'FluxaPay Webhook Service:
-
Listens for
PaymentConfirmedevent from contract -
Event received for
payment_id:"pay_xyz789" -
Fetch full payment details from database
-
Construct webhook payload:
{
"event": "payment.confirmed",
"payment_id": "pay_xyz789",
"merchant_id": "merch_abc123",
"order_id": "order_12345",
"amount": 50,
"currency": "USDC",
"status": "confirmed",
"transaction_hash": "TXN_HASH_ABC123...",
"payer_address": "GALICE_WALLET...XYZ",
"confirmed_at": "2026-01-20T15:05:35Z",
"metadata": {
"customer_name": "Alice",
"items": ["Headphones", "Phone Case"]
}
}-
Sign payload with merchant's webhook secret. Compute an HMAC-SHA256 over the ISO timestamp and the JSON body joined by a dot (
${timestamp}.${payload}) and use the merchant'swebhook_secretas the HMAC key. Include the timestamp in a header so receivers can enforce a freshness window and detect replay attacks. -
Send webhook:
POST https://coolshop.com/webhooks/fluxapay
X-FluxaPay-Signature: [HMAC_SIGNATURE]
X-FluxaPay-Timestamp: 2026-02-26T12:00:00.000Z-
Retry logic:
- If fails, retry with exponential backoff
- Attempt 1: immediate
- Attempt 2: after 5 seconds
- Attempt 3: after 25 seconds
- Attempt 4: after 2 minutes
- Max 5 attempts
-
Log webhook delivery status
Cool Shop Backend (webhook handler):
-
Receives webhook at
/webhooks/fluxapay -
Validates signature:
- Verify
X-FluxaPay-Signatureheader - Prevents spoofing
- Verify
-
Validates event:
if (payload.event === 'payment.confirmed' &&
payload.payment_id === 'pay_xyz789') {
// Find order in database
order = db.orders.find({ id: 'order_12345' })
// Update order status
order.status = 'paid'
order.payment_confirmed_at = payload.confirmed_at
order.save()
// Trigger fulfillment
fulfillmentService.processOrder(order)
// Send confirmation email to customer
emailService.send({
to: 'alice@email.com',
subject: 'Order Confirmed!',
body: 'Your payment was successful...'
})
}- Return
200 OKto FluxaPay (acknowledge webhook)
FluxaPay Checkout Page (WebSocket/polling update):
┌──────────────────────────────────────────────────┐
│ 🔒 Secure Payment - FluxaPay │
├──────────────────────────────────────────────────┤
│ │
│ ✅ Payment Confirmed! │
│ │
│ Amount: 50 USDC │
│ Transaction: TXN_HASH_ABC123... │
│ Confirmed at: 2026-01-20 15:05:35 UTC │
│ │
│ Redirecting to Cool Shop... │
│ │
└──────────────────────────────────────────────────┘
Auto-redirect to: https://coolshop.com/order/success?payment_id=pay_xyz789
Customer sees order confirmation on Cool Shop ✅
FluxaPay Sweep Service (runs every 5 minutes):
- Query database for confirmed but unswept payments:
SELECT * FROM payments
WHERE status = 'confirmed'
AND swept = falseResults: [pay_xyz789, pay_abc456, ...]
-
For each payment to sweep:
Payment:
pay_xyz789a) Retrieve encrypted secret key from database
b) Decrypt secret key:
secret_key = decrypt(encrypted_key) keypair = Keypair.fromSecret(secret_key) // Result: keypair for GPAY_XYZ789...AAA
c) Build sweep transaction:
transaction = new TransactionBuilder(account, { fee: BASE_FEE, networkPassphrase: Networks.PUBLIC }) .addOperation(Operation.payment({ destination: 'GFLUXAPAY_TREASURY...XYZ', // FluxaPay main wallet asset: new Asset('USDC', USDC_ISSUER), amount: '50.0000000' })) .addMemo(Memo.text('pay_xyz789')) // Track which payment .setTimeout(30) .build()
d) Sign transaction:
transaction.sign(keypair)
e) Submit to Stellar network:
response = await horizon.submitTransaction(transaction)
Sweep Transaction Hash:
SWEEP_TXN_ABC...f) Update database:
UPDATE payments SET swept = true, swept_at = NOW(), sweep_transaction_hash = 'SWEEP_TXN_ABC...' WHERE payment_id = 'pay_xyz789'
g) (Optional) Merge payment account to reclaim XLM:
- Reduces ongoing costs
- Sends remaining XLM back to funding account
-
Repeat for all confirmed payments
-
FluxaPay Treasury now holds:
- Previous balance + 50 USDC from
pay_xyz789 - Accumulates USDC from all merchants
- Previous balance + 50 USDC from
FluxaPay Settlement Service (runs daily at 00:00 UTC):
- Calculate settlements per merchant:
SELECT merchant_id, SUM(amount) as total_usdc
FROM payments
WHERE status = 'confirmed'
AND swept = true
AND settled = false
GROUP BY merchant_idResults:
merch_abc123(Cool Shop): 450 USDC (9 payments)merch_def456(Tech Store): 1200 USDC (15 payments)- ...
-
For each merchant settlement:
Merchant:
merch_abc123(Cool Shop)
Total USDC: 450
Settlement Currency: NGNa) Fetch merchant details:
merchant = db.merchants.find('merch_abc123') bank_account = merchant.bank_account settlement_currency = merchant.settlement_currency // NGN
b) Convert USDC to NGN:
- Current rate: 1 USDC = 1,500 NGN
- 450 USDC × 1,500 = 675,000 NGN
- Minus FluxaPay fee (2%): 675,000 - 13,500 = 661,500 NGN
c) Process bank transfer:
- Use payment partner (Paystack, Flutterwave, etc.)
- Transfer 661,500 NGN to merchant's bank account
- Transfer Reference:
SETTLE_XYZ123
d) Update Settlement Coordinator Contract:
mark_settled( merchant_id: "merch_abc123", payment_ids: [pay_xyz789, pay_abc456, ...], usdc_amount: 450, fiat_currency: "NGN", fiat_amount: 661500, settlement_reference: "SETTLE_XYZ123" )
e) Update database:
UPDATE payments SET settled = true, settled_at = NOW(), settlement_reference = 'SETTLE_XYZ123', settlement_fiat_amount = 661500, settlement_fiat_currency = 'NGN' WHERE payment_id IN (pay_xyz789, pay_abc456, ...)
f) Send webhook to merchant:
{ "event": "settlement.completed", "merchant_id": "merch_abc123", "payment_ids": ["pay_xyz789", "pay_abc456", ...], "total_payments": 9, "usdc_amount": 450, "settlement_currency": "NGN", "settlement_amount": 661500, "settlement_fee": 13500, "bank_reference": "SETTLE_XYZ123", "settled_at": "2026-01-21T00:15:00Z" }g) Send settlement notification email to merchant
Cool Shop:
-
Receives webhook:
settlement.completed -
Updates accounting system:
- Record revenue: 661,500 NGN
- Record FluxaPay fees: 13,500 NGN
-
Receives bank transfer:
- Bank account credited: 661,500 NGN
- Reference:
SETTLE_XYZ123
-
Can view details in FluxaPay dashboard:
- Transaction history
- Settlement reports
- Download invoices
graph TD
A[1. MERCHANT ONBOARDING<br/>Merchant signs up → Get API keys → Integrate] --> B
B[2. CUSTOMER CHECKOUT<br/>Customer adds to cart → Clicks Pay with Crypto] --> C
C[3. PAYMENT CREATION<br/>Merchant API call → FluxaPay generates unique<br/>payment address HD wallet → Returns checkout URL] --> D
D[4. CUSTOMER PAYS<br/>Customer sees payment page → Sends USDC from wallet<br/>to unique address → Transaction on Stellar] --> E
E[5. DETECTION & VERIFICATION<br/>Oracle monitors address → Detects payment →<br/>Verifies on smart contract → Updates status] --> F
F[6. MERCHANT NOTIFICATION<br/>Webhook sent to merchant → Merchant fulfills order<br/>→ Customer receives confirmation] --> G
G[7. FUND SWEEPING<br/>Auto-sweep USDC from payment address → FluxaPay<br/>treasury → Accumulate funds] --> H
H[8. SETTLEMENT<br/>Batch payments by merchant → Convert USDC to fiat →<br/>Bank transfer to merchant → Settlement complete]
┌─────────────────────────────────────────────────────────┐
│ 1. MERCHANT ONBOARDING │
│ Merchant signs up → Get API keys → Integrate │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 2. CUSTOMER CHECKOUT │
│ Customer adds to cart → Clicks "Pay with Crypto" │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 3. PAYMENT CREATION │
│ Merchant API call → FluxaPay generates unique │
│ payment address (HD wallet) → Returns checkout URL │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 4. CUSTOMER PAYS │
│ Customer sees payment page → Sends USDC from wallet │
│ to unique address → Transaction on Stellar │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 5. DETECTION & VERIFICATION │
│ Oracle monitors address → Detects payment → │
│ Verifies on smart contract → Updates status │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 6. MERCHANT NOTIFICATION │
│ Webhook sent to merchant → Merchant fulfills order │
│ → Customer receives confirmation │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 7. FUND SWEEPING │
│ Auto-sweep USDC from payment address → FluxaPay │
│ treasury → Accumulate funds │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 8. SETTLEMENT │
│ Batch payments by merchant → Convert USDC to fiat → │
│ Bank transfer to merchant → Settlement complete │
└─────────────────────────────────────────────────────────┘
FluxaPay System:
├── Master Seed: [HIGHLY SECURED]
│ └── Used to derive all payment addresses
│
├── Treasury Wallet: GFLUXAPAY_TREASURY...XYZ
│ └── Receives swept USDC from all payments
│
├── Funding Wallet: GFLUXAPAY_FUNDING...ABC
│ └── Funds new payment addresses with XLM
│
└── Per-Payment Addresses (derived):
├── GPAY_XYZ789...AAA (for pay_xyz789)
├── GPAY_ABC456...BBB (for pay_abc456)
└── ... (one per payment, deterministically derived)
Merchant:
└── Cool Shop (merch_abc123)
└── No Stellar address needed
└── Receives NGN in bank account
- ✅ Unique address per payment - No payment ambiguity
- ✅ Automated detection - Oracle monitors blockchain
- ✅ Smart contract verification - On-chain proof
- ✅ Instant notifications - Real-time webhooks
- ✅ Automatic sweeping - Secure fund management
- ✅ Batch settlements - Cost-efficient fiat conversion
- ✅ Multi-currency support - Settle in local currencies
This is the complete end-to-end flow! Each payment gets its own unique address, no ambiguity, and fully automated settlement. 🚀