Payment Processing
Part of: MPAC SmartPOS Cloud Platform - Product RequirementsVersion: 2.0 Last Updated: 2026-01-28
Overview
The Payment Processing domain handles all payment-related operations in the SmartPOS system, supporting multiple payment methods (QR codes, credit cards, cash, e-money) with different processing modes. It orchestrates payment flows between the terminal, backend services, and the Payment Gateway (mpac-pgw), ensuring secure transaction processing, proper state management, idempotency, and comprehensive refund capabilities. This domain is critical for completing customer transactions and maintaining financial integrity across the platform.
Table of Contents
- Payment Methods
- Payment Flow Architecture
- Payment Entity
- Refund Processing
- Idempotency & Duplicate Prevention
Payment Methods
Supported Payment Types:
| Method | Type | Provider Examples | Processing Mode |
|---|---|---|---|
| QR (MPM) | Digital | PayPay, LINE Pay, au PAY | pgw_processed |
| QR (CPM) | Digital | PayPay, Rakuten Pay | pgw_processed |
| Credit Card | Card | Via SP-NET processor | external |
| Cash | Physical | Direct | manual |
| E-Money | Digital | Suica, PASMO, nanaco | external |
Processing Modes:
pgw_processed- Payment Gateway handles directly (QR payments)external- External app processes (Credit Card via Intent)manual- Staff confirms manually (Cash)
Payment Flow Architecture
QR Payment Flow (pgw_processed)
1. Customer selects PayPay
└─ Device: POST /payments {bill_id, amount, payment_method}
2. svc-smarttab creates payment record
└─ Call PGW: POST /v1/payment_intents
Request: {
merchant_ref_id: "unique_per_merchant",
amount: 100000,
currency: "JPY",
order_id: "POS-ORDER-123",
payment_method_type: "qr_mpm",
processing_mode: "pgw_processed"
}
Response: PaymentIntent {
id: "pi_01HXYZ",
status: "requires_payment_method",
payment_token: "tok_abc123"
}
3. Frontend (WebView) receives payment_token
└─ SDK: POST /v1/payment_intents/{id}/confirm
└─ PGW generates QR code
└─ Display QR to customer
4. Customer scans with PayPay app
└─ PayPay processes payment
└─ Webhook: POST /v1/webhooks/paypay
└─ PGW updates: status = "succeeded"
5. Frontend polls: GET /v1/payment_intents/{id}
└─ Receives: status = "succeeded"
6. svc-smarttab updates payment
└─ Payment status: completed
└─ Bill status: paid
└─ Generate receiptCredit Card Flow (external)
1. Customer selects Credit Card
└─ Device: POST /payments {bill_id, amount, payment_method: CREDIT_CARD}
2. svc-smarttab creates payment
└─ Call PGW: POST /v1/payment_intents
processing_mode: "external"
status: "requires_action"
3. Frontend launches Credit Card App via Intent
Intent Extras: {
"corr_id": "CORR-36-1730188800000",
"amount": 100000,
"classificationCode": 5,
"authorizationID": "AUTH01"
}
4. Credit Card App processes
└─ Communicates with SP-NET processor
└─ Card reader processes payment
└─ Returns via ActivityResult: {
approval_code: "123456",
card_slip_number: "00123",
card_last_4: "1234",
status: "success"
}
5. Business App receives result
└─ PATCH /payments/{id}
{approval_code, card_document_number}
└─ Status: completed
6. svc-smarttab updates
└─ Call PGW: POST /v1/payment_intents/{id}/capture
└─ Bill status: paidCash Flow (manual)
1. Customer pays cash
└─ Device: POST /payments {
bill_id,
amount,
payment_method: CASH,
cash_received: 150000
}
2. svc-smarttab creates payment
└─ Calculate change: 150000 - 100000 = 50000
└─ Display change to staff
└─ Staff confirms cash received
└─ Payment status: completed
└─ Bill status: paidPayment Entity
{
"id": "payment_uuid",
"merchant_id": 1,
"store_id": 2,
"bill_id": "bill_uuid",
"split_id": "split_uuid" (optional),
"payment_provider_method_id": 1,
"amount": 100000,
"tip_amount": 10000,
"total_amount": 110000,
"payment_method": {
"type": "CREDIT_CARD",
"provider": "VISA"
},
"status": "pending|processing|completed|failed|refunded",
"transaction_id": "pi_01HXYZ",
"payment_token": "tok_abc123",
"approval_code": "123456",
"card_document_number": "00123",
"card_last_4": "1234",
"card_brand": "VISA",
"card_arn": "ARN123...",
"cash_received": 150000 (if CASH),
"change_amount": 50000 (if CASH),
"refund_amount": 0,
"refund_reason": null,
"created_at": "2026-01-28T11:00:00Z",
"completed_at": "2026-01-28T11:01:00Z"
}Payment States:
pending- Created, awaiting processingprocessing- Being processed by providercompleted- Successfully completedfailed- Payment failedrefunded- Payment refunded
Refund Processing
Purpose: Reverse completed payments with proper audit trail.
Refund Types:
- Full refund - Return entire payment amount
- Partial refund - Return portion of payment amount
Refund Flow:
Staff initiates refund
└─ POST /payments/{id}/refund
Request: {
refund_amount: 50000,
reason: "Item not available",
staff_code: "STAFF001"
}
For Credit Card:
└─ Retrieve: card_document_number, approval_code
└─ Launch Credit Card App with refund params
└─ App processes refund via SP-NET
└─ Receive refund approval
└─ Update payment: status=refunded, refund_amount
For QR:
└─ Call PGW: POST /v1/payment_intents/{id}/refund
└─ PGW calls provider (PayPay) refund API
└─ Provider refunds to customer account
└─ Update payment: status=refunded
Update Bill:
└─ If full refund and only payment: Bill status=cancelled
└─ If partial: Adjust bill paid_amountRefund Constraints:
- Must be completed payment
- Refund amount ≤ original payment amount
- Requires staff authorization
- Cannot refund already refunded payment
- Audit trail records all refund operations
API Endpoints:
POST /payments/{id}/refund- Initiate refundGET /payments/{id}/refund-status- Check refund status
Idempotency & Duplicate Prevention
Purpose: Prevent duplicate charges when requests are retried.
Idempotency Key:
- Header:
Idempotency-Key: <uuid> - Unique per transaction per merchant
- 24-hour cache retention in Redis
- Database constraint on merchant_ref_id
Behavior:
Request 1: POST /payments {Idempotency-Key: abc-123}
→ Creates payment, caches response
→ Returns: Payment {id: pay_001, status: completed}
Request 2 (retry): POST /payments {Idempotency-Key: abc-123}
→ Detects duplicate key in cache
→ Returns: Same cached response {id: pay_001, status: completed}
→ No duplicate charge createdSee Also
Related Domains:
- Order & Bill - Order lifecycle and bill management that precedes payment
- Payment Gateway - Payment Gateway service (mpac-pgw) implementation and provider integrations
- Settlement - Post-payment settlement and reconciliation processes
Technical Implementation:
- Database Architecture - Payment and refund data model and schema design
- Business Logic - Payment state machine and validation rules
API Reference:
- API Endpoints - Complete API specification for payment operations
Navigation: ← Previous: Order & Bill | ↑ Back to Domain Catalog | Next: Payment Gateway →