Customer Payment Processing¶
Complete guide to customer-initiated appointment payment processing with automatic platform fee calculation and invoice generation.
Overview¶
The customer payment system provides secure payment processing for appointment bookings through Paper.id integration with:
- Invoice Generation - Professional PDF invoices for customer records
- Platform Fee Calculation - Automatic fee calculation based on subscription tier
- Wallet Integration - Optional wallet balance application to reduce payment
- Payment Gateway Integration - Unified Paper.id payment processing
- Webhook Automation - Automatic payment confirmation and status updates
- Multi-Method Support - Support for Indonesian payment methods (QRIS, E-Wallet, Bank Transfer, etc.)
Key Concepts:
- Base Amount = Service price (what the merchant receives minus platform fee)
- Platform Fee = Variable based on subscription tier (FREE: 8%, PRO: 5%, ENTERPRISE: 3%)
- Total Amount = Base Amount + Platform Fee (what customer pays)
- Wallet Application = Optional reduction from wallet balance (applied to base amount only)
- Invoice = Professional document with payment URL and PDF download
Subscription Plan Fee Tiers¶
Platform fees are automatically calculated based on the tenant's subscription plan:
| Subscription Plan | Platform Fee | Example on IDR 100,000 |
|---|---|---|
| FREE | 8% | IDR 8,000 fee → IDR 108,000 total |
| PRO | 5% | IDR 5,000 fee → IDR 105,000 total |
| ENTERPRISE | 3% | IDR 3,000 fee → IDR 103,000 total |
Fee Application:
- Fee is calculated on the base appointment amount
- Fee is added to the customer's payment amount
- Merchant receives base amount minus platform fee after payment
- Wallet balance (if used) reduces base amount before fee calculation
Example with Wallet Balance:
- Appointment base: IDR 100,000
- Wallet applied: IDR 20,000
- New base: IDR 80,000
- Platform fee (8% FREE tier): IDR 6,400
- Customer pays: IDR 86,400
- Wallet deducted: IDR 20,000
Process Appointment Payment¶
Initiate payment for a customer appointment with automatic fee calculation and invoice generation.
Endpoint¶
Authentication: Required (Customer JWT token)
Portal: 🟦 CUSTOMER (customer-only endpoint)
Request Body¶
Parameters:
appointment_id(required) - ID of the appointment to pay for (24-character ObjectId)payment_method(optional) - Payment method enum (defaults toQRISif not specified)- Options:
QRIS,BANK_TRANSFER,VIRTUAL_ACCOUNT,E_WALLET,CREDIT_CARD use_wallet_balance(optional) - Apply wallet balance if available (default:false)return_url(optional) - URL to redirect after payment completion
Response¶
{
"payment_id": "507f1f77bcf86cd799439012",
"status": "PENDING",
"payment_url": "https://payper.id/short456",
"invoice_url": "https://stg-v2.paper.id/abc123",
"invoice_pdf_url": "https://stg-v2.paper.id/pdf/xyz789",
"invoice_number": "INV-2025-001",
"amount": 108000.00,
"wallet_applied": null,
"expires_at": "2025-01-17T10:30:00Z",
"message": "Invoice created. Total: IDR 108,000.00 (Base: IDR 100,000.00 + Fee: IDR 8,000.00)"
}
Response Fields:
payment_id- Payment tracking record IDstatus- Payment status (PENDING,COMPLETED,FAILED,CANCELLED)payment_url- Paper.id payment URL for customer to complete paymentinvoice_url- Invoice payment page URLinvoice_pdf_url- Direct PDF invoice download URLinvoice_number- Invoice reference number (e.g.,INV-2025-001)amount- Total amount customer must pay (base + platform fee - wallet)wallet_applied- Amount deducted from wallet (if used)expires_at- Payment link expiration timestamp (24 hours)message- Detailed breakdown of payment amounts
Request Examples¶
Minimal Request (Recommended)¶
Simplest form - only appointment_id required. System defaults to QRIS payment method.
Use Case: Quick payment initiation without specifying payment method preferences.
With Wallet Balance¶
Apply customer wallet balance to reduce the payment amount.
Use Case: Customer wants to use stored wallet credits to partially or fully pay for appointment.
Full Request with All Options¶
Complete request with all optional parameters specified.
{
"appointment_id": "507f1f77bcf86cd799439011",
"payment_method": "CREDIT_CARD",
"use_wallet_balance": true,
"return_url": "https://app.example.com/payment-success"
}
Use Case: Advanced integration with specific payment method and return URL handling.
Payment Flow (10 Steps)¶
The payment process follows this complete sequence:
1. Validation¶
- Verify appointment exists and belongs to authenticated customer
- Check appointment status is
PENDINGorCONFIRMED - Ensure appointment hasn't been paid already
- Validate tenant Paper.id configuration is enabled
2. Platform Fee Calculation¶
- Retrieve tenant's subscription plan (FREE/PRO/ENTERPRISE)
- Calculate platform fee percentage:
- FREE: 8%
- PRO: 5%
- ENTERPRISE: 3%
- Calculate fee amount:
base_amount × fee_percentage
3. Wallet Balance Application (Optional)¶
- If
use_wallet_balance: true, retrieve customer wallet - Check wallet status is
ACTIVEand balance > 0 - Calculate wallet application:
min(wallet_balance, base_amount) - Deduct from wallet immediately (refunded if payment fails)
- Reduce base amount by wallet applied amount
4. Full Wallet Payment Shortcut¶
- If wallet covers full base amount, skip invoice generation
- Update appointment status to
CONFIRMEDimmediately - Mark payment as
COMPLETEDwithwallet_paymentID - Return success response without payment URL
5. Invoice Creation (Database)¶
- Create invoice record in database with type
APPOINTMENT - Generate unique invoice number (e.g.,
INV-2025-001) - Store line items for appointment services
- Add platform fee as separate line item
- Store metadata:
customer_initiated: true,payment_flow: customer_booking
6. Customer Partner Verification¶
- Ensure customer has Paper.id partner record
- Create partner record if doesn't exist
- Retrieve
partner_numberfor Paper.id integration
7. Paper.id Invoice Generation¶
- Create sales invoice in Paper.id using tenant credentials
- Include customer details (name, email, phone, address)
- Add appointment service line items
- Add platform fee line item with subscription plan metadata
- Configure callback webhook URL:
/api/v1/webhooks/paper-invoice/tenant/{tenant_id} - Receive Paper.id invoice ID, PDF URL, and payment URL
8. Link Paper.id Invoice¶
- Update database invoice with Paper.id references:
paper_invoice_id- Paper.id invoice IDpaper_invoice_url- Invoice page URLpaper_pdf_url- PDF download URLpaper_payment_url- Payment page URL
9. Create Payment Record¶
- Create payment record with status
PENDING - Link to appointment, customer, invoice, and tenant
- Store payment method (or default to
QRIS) - Store amount breakdown (base, fee, total)
- Generate reference ID:
APT-{appointment_id}-{timestamp} - Store metadata with
customer_initiated: true
10. Return Payment URL¶
- Return payment response with invoice URLs
- Customer redirects to
payment_urlto complete payment - System awaits webhook confirmation from Paper.id
- Webhook automatically updates payment and appointment status
Webhook Processing¶
After the customer completes payment on Paper.id, the webhook automatically processes the payment:
Webhook Endpoint¶
Automatic Actions on Payment Success¶
- Verify Payment Status - Validate
status: paidin webhook payload - Update Payment Record - Set payment status to
COMPLETED - Update Appointment - Set appointment status to
CONFIRMED - Update Invoice - Mark invoice as
PAIDwith payment date - Merchant Balance - Credit merchant account with base amount minus platform fee
- Customer Notification - Send booking confirmation email
- Staff Notification - Notify assigned staff of confirmed appointment
- Audit Log - Record payment event for compliance
Webhook Security¶
- Tenant Isolation - Webhook URL includes tenant_id for automatic routing
- Idempotency - Duplicate webhooks ignored based on invoice ID tracking
- Amount Verification - Payment amount validated against invoice total
- Invoice Validation - Invoice existence checked before processing
- Tenant Validation - Ensure invoice belongs to correct tenant
Payment Statuses¶
The payment can transition through the following statuses:
| Status | Description | Next Actions |
|---|---|---|
PENDING |
Payment initiated, awaiting completion | Customer must complete payment via payment_url |
PROCESSING |
Payment in progress at gateway | Wait for webhook confirmation |
COMPLETED |
Payment successful, appointment confirmed | Appointment ready, customer and staff notified |
FAILED |
Payment failed at gateway | Customer can retry with new payment request |
CANCELLED |
Payment cancelled by customer | Customer can create new payment request |
REFUNDED |
Payment refunded to customer | Refund processed, appointment cancelled |
Error Handling¶
Common Error Responses¶
400 Bad Request - Payment Gateway Not Configured¶
{
"detail": "Payment gateway not configured for this tenant. Please contact support or try alternative payment methods."
}
Cause: Tenant has not enabled or configured Paper.id integration Resolution: Contact tenant administrator to configure Paper.id credentials in tenant settings
403 Forbidden - Not Authorized¶
Cause: Appointment does not belong to authenticated customer Resolution: Verify customer is paying for their own appointment
404 Not Found - Appointment Not Found¶
Cause: Appointment ID does not exist or was deleted Resolution: Verify appointment ID is correct and appointment exists
409 Conflict - Already Paid¶
Cause: Appointment has existing completed payment Resolution: Check payment history, appointment is already confirmed
409 Conflict - Invalid Status¶
Cause: Appointment status is not PENDING or CONFIRMED
Resolution: Only pending or confirmed appointments can be paid
500 Internal Server Error - Invoice Creation Failed¶
Cause: Database error during invoice creation Resolution: Retry request, wallet automatically refunded if deducted
502 Bad Gateway - Paper.id API Error¶
Cause: Paper.id API unavailable or network error Resolution: Retry request, invoice and wallet automatically rolled back
Subscription Plan Limitations¶
The appointment payment system has no usage limits based on subscription plans. However, the platform fee percentage varies by plan:
Platform Fee by Plan¶
| Feature | FREE Plan | PRO Plan | ENTERPRISE Plan |
|---|---|---|---|
| Platform Fee | 8% | 5% | 3% |
| Fee on IDR 100k | IDR 8,000 | IDR 5,000 | IDR 3,000 |
| Appointment Payments | Unlimited | Unlimited | Unlimited |
| Invoice Generation | ✅ Included | ✅ Included | ✅ Included |
| PDF Invoices | ✅ Included | ✅ Included | ✅ Included |
| Wallet Integration | ✅ Included | ✅ Included | ✅ Included |
| Payment Methods | All methods | All methods | All methods |
Key Points:
- All plans support unlimited appointment payments
- Higher-tier plans reduce platform fees, increasing merchant profit margins
- No restrictions on payment volume or invoice generation
- All payment methods available on all plans
See Also:
- Subscription Management - Upgrade to reduce platform fees
- Payment History - View platform fee breakdown per payment
Integration with Other Features¶
Appointment Management¶
Reference: Appointment Management
- Payment links appointments to confirmed bookings
- Appointment status automatically updated to
CONFIRMEDon payment success - Unpaid appointments can be cancelled by customer or system
- Payment required before appointment is finalized
Invoice Management¶
Reference: Invoice Management
- Professional PDF invoice generated for every payment
- Invoice stored in database with Paper.id linkage
- Customers can download invoices from payment history
- Invoices include itemized service breakdown and platform fee
Customer Booking Flow¶
Reference: Customer Booking & Appointments
- Payment is final step in booking process
- Customer selects services → Staff → Time slot → Payment
- Booking not confirmed until payment completed
- Wallet balance can be applied during payment
Payment History¶
Reference: Payment History
- All payments tracked in customer payment history
- Platform fee and base amount displayed separately
- Downloadable invoices linked to payment records
- Filter by status, date range, payment type
Wallet Management¶
Reference: Customer Payments - Wallet Operations
- Wallet balance can reduce appointment payment amount
- Wallet deducted immediately, refunded if payment fails
- Wallet top-up requires separate payment with platform fee
- Wallet transactions tracked for audit
Subscription Plans¶
Reference: Subscription Management
- Subscription plan determines platform fee percentage
- Upgrading subscription reduces platform fees for customers
- Fee calculation automatic based on active subscription
- No manual configuration required
Best Practices¶
For Customers¶
✅ DO:
- Use wallet balance to reduce payment amounts when available
- Download and save PDF invoices for records
- Complete payment within 24 hours before link expires
- Contact support if payment fails to retry
❌ DON'T:
- Share payment URLs with others
- Attempt to pay for same appointment multiple times
- Ignore payment expiration deadlines
- Use expired or invalid payment methods
For Frontend Developers¶
✅ DO:
- Default to minimal request (only
appointment_id) for simplicity - Display platform fee breakdown transparently to customers
- Show wallet balance application option if customer has credits
- Provide invoice PDF download button in payment confirmation
- Handle payment URL redirect gracefully
- Implement webhook listener for real-time status updates
- Show payment expiration countdown timer
❌ DON'T:
- Require payment method selection upfront (QRIS is good default)
- Hide platform fee from customers (transparency required)
- Allow duplicate payment submissions
- Ignore
expires_attimestamp in UI - Cache payment URLs (they expire)
For Backend Developers¶
✅ DO:
- Always validate appointment ownership before payment
- Use PaymentProcessor service for automatic fee calculation
- Roll back wallet deduction if invoice creation fails
- Log all Paper.id API responses for debugging
- Implement idempotency checks in webhook handler
- Store complete fee breakdown in payment metadata
- Handle Paper.id API timeouts gracefully
❌ DON'T:
- Skip wallet refund on payment failure
- Trust client-provided fee calculations
- Process webhook without idempotency check
- Expose Paper.id credentials in logs
- Skip tenant validation in webhook processing
- Allow payment for cancelled appointments
Testing Payment Flow¶
Prerequisites¶
- Customer Account - Active customer with valid JWT token
- Appointment - Pending appointment belonging to customer
- Tenant Configuration - Paper.id credentials configured and enabled
- ngrok Setup - Expose local server for webhook testing
Test Scenario 1: Basic Payment (No Wallet)¶
Scenario: Customer pays for IDR 100,000 appointment on FREE plan
Step 1: Initiate Payment
curl -X POST http://localhost:8000/api/v1/customer/payments/process-appointment \
-H "Authorization: Bearer CUSTOMER_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"appointment_id": "507f1f77bcf86cd799439011"
}'
Expected Response:
{
"payment_id": "507f1f77bcf86cd799439012",
"status": "PENDING",
"payment_url": "https://payper.id/short456",
"invoice_url": "https://stg-v2.paper.id/abc123",
"invoice_pdf_url": "https://stg-v2.paper.id/pdf/xyz789",
"invoice_number": "INV-2025-001",
"amount": 108000.00,
"wallet_applied": null,
"expires_at": "2025-01-17T10:30:00Z",
"message": "Invoice created. Total: IDR 108,000.00 (Base: IDR 100,000.00 + Fee: IDR 8,000.00)"
}
Step 2: Complete Payment
- Open
payment_urlin browser - Select payment method (QRIS, E-Wallet, etc.)
- Complete payment using Paper.id test credentials
Step 3: Verify Webhook
- Check server logs for webhook received:
POST /api/v1/webhooks/paper-invoice/tenant/{tenant_id} - Verify payment status updated to
COMPLETED - Verify appointment status updated to
CONFIRMED
Step 4: Verify Results
curl -X GET http://localhost:8000/api/v1/customer/payments/history \
-H "Authorization: Bearer CUSTOMER_JWT_TOKEN"
Expected: Payment with status COMPLETED, invoice linked
Test Scenario 2: Payment with Wallet Balance¶
Scenario: Customer has IDR 30,000 wallet balance, pays for IDR 100,000 appointment
Step 1: Check Wallet Balance
curl -X GET http://localhost:8000/api/v1/customer/payments/wallet/balance \
-H "Authorization: Bearer CUSTOMER_JWT_TOKEN"
Expected Response:
Step 2: Initiate Payment with Wallet
curl -X POST http://localhost:8000/api/v1/customer/payments/process-appointment \
-H "Authorization: Bearer CUSTOMER_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"appointment_id": "507f1f77bcf86cd799439011",
"use_wallet_balance": true
}'
Expected Response:
{
"payment_id": "507f1f77bcf86cd799439012",
"status": "PENDING",
"amount": 75600.00,
"wallet_applied": 30000.00,
"message": "Invoice created. Total: IDR 75,600.00 (Base: IDR 70,000.00 + Fee: IDR 5,600.00) - Wallet: IDR 30,000.00"
}
Calculation Breakdown:
- Appointment base: IDR 100,000
- Wallet applied: IDR 30,000
- New base: IDR 70,000
- Platform fee (8%): IDR 5,600
- Customer pays: IDR 75,600
Step 3: Verify Wallet Deduction
curl -X GET http://localhost:8000/api/v1/customer/payments/wallet/balance \
-H "Authorization: Bearer CUSTOMER_JWT_TOKEN"
Expected: Balance reduced to IDR 0.00 immediately
Test Scenario 3: Full Wallet Payment¶
Scenario: Customer has IDR 150,000 wallet balance, pays for IDR 100,000 appointment
Step 1: Initiate Payment
curl -X POST http://localhost:8000/api/v1/customer/payments/process-appointment \
-H "Authorization: Bearer CUSTOMER_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"appointment_id": "507f1f77bcf86cd799439011",
"use_wallet_balance": true
}'
Expected Response:
{
"payment_id": "wallet_payment",
"status": "COMPLETED",
"payment_url": null,
"amount": 100000.00,
"wallet_applied": 100000.00,
"expires_at": null,
"message": "Paid with wallet balance: IDR 100,000.00"
}
Key Observations:
- No invoice generated (full wallet payment)
- No payment URL (already completed)
- Appointment status immediately
CONFIRMED - No platform fee charged (wallet already includes fee)
- Remaining wallet balance: IDR 50,000
Troubleshooting¶
Payment Link Expired¶
Symptoms: Customer tries to pay but link shows "Invoice expired"
Checks:
- Check
expires_attimestamp in payment response - Verify current time < expiry time (24 hours from creation)
Fix: - Create new payment request for same appointment - Previous payment automatically cancelled - New invoice and payment URL generated
Webhook Not Received¶
Symptoms: Payment completed but appointment still PENDING
Checks:
- Verify ngrok is running:
ngrok http 8000 - Check Paper.id webhook URL configuration includes tenant_id
- Review ngrok web interface:
http://localhost:4040for webhook requests - Check server logs for webhook processing errors
Fix:
- Manually trigger webhook from Paper.id dashboard (Resend Webhook button)
- Or manually update appointment and payment status via admin endpoint
Wallet Not Refunded on Failure¶
Symptoms: Payment failed but wallet balance not restored
Checks:
- Check wallet transaction history for refund transaction
- Verify payment status is
FAILEDorCANCELLED - Review server logs for rollback errors
Fix:
- Contact support to manually issue wallet refund
- Provide payment_id and customer_id for investigation
Platform Fee Incorrect¶
Symptoms: Fee amount doesn't match expected subscription tier rate
Checks:
- Verify tenant subscription plan:
GET /api/v1/subscriptions/current - Check subscription is
activestatus - Review payment metadata for
subscription_planfield
Fix:
- Ensure tenant subscription is active and not expired
- Upgrade subscription if fee tier needs adjustment
- Fee calculated at time of payment, not retroactively changed
API Reference Summary¶
| Field | Type | Required | Description |
|---|---|---|---|
appointment_id |
string | Yes | 24-character ObjectId of appointment |
payment_method |
enum | No | Payment method (default: QRIS) |
use_wallet_balance |
boolean | No | Apply wallet balance (default: false) |
return_url |
string | No | Redirect URL after payment |
Response Fields:
| Field | Type | Description |
|---|---|---|
payment_id |
string | Payment tracking ID |
status |
enum | Payment status |
payment_url |
string | Paper.id payment URL |
invoice_url |
string | Invoice page URL |
invoice_pdf_url |
string | PDF download URL |
invoice_number |
string | Invoice reference number |
amount |
decimal | Total payment amount |
wallet_applied |
decimal | Wallet balance used |
expires_at |
datetime | Payment link expiration |
message |
string | Payment breakdown message |
Related Documentation¶
- Subscription Management - Manage subscription plans and fees
- Appointment Management - Create and manage appointments
- Customer Booking & Appointments - Complete booking flow
- Payment History - View payment transaction history
- Invoice Management - Invoice generation and PDF access
- Webhook Integration - Webhook processing details
Next Steps:
- Create customer appointment: Customer Booking
- Initiate payment:
POST /api/v1/customer/payments/process-appointment - Customer completes payment via
payment_url - System automatically confirms appointment via webhook
- View payment history:
GET /api/v1/customer/payments/history - Download invoice PDF from payment record