Payments API
Complete guide to payment processing in Jiffoo Mall
Payments API
Process payments securely using multiple payment methods including credit cards, digital wallets, and bank transfers.
Payment Flow
sequenceDiagram
Client->>API: POST /payments/initiate
API->>Payment Provider: Create payment intent
Payment Provider->>API: Return payment details
API->>Client: Return payment session
Client->>Payment Provider: Complete payment
Payment Provider->>API: POST /payments/webhooks (webhook)
API->>API: Update order status
API->>Payment Provider: Acknowledge webhook
Client->>API: GET /payments/:id (check status)
API->>Client: Return payment statusEndpoints
Initiate Payment
Create a new payment session for an order.
Endpoint: POST /payments/initiate
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Request Body:
{
"orderId": "order_abc123",
"paymentMethodId": "pm_card_visa",
"amount": 185.97,
"currency": "USD",
"returnUrl": "https://example.com/payment/success",
"cancelUrl": "https://example.com/payment/cancel"
}Response: 201 Created
{
"success": true,
"message": "Payment initiated",
"data": {
"paymentId": "pay_xyz789",
"orderId": "order_abc123",
"status": "pending",
"amount": 185.97,
"currency": "USD",
"paymentMethod": {
"id": "pm_card_visa",
"type": "card",
"brand": "visa",
"last4": "4242"
},
"clientSecret": "pi_secret_abc123xyz789",
"paymentUrl": "https://payment-provider.com/checkout/xyz789",
"expiresAt": "2024-01-01T01:00:00.000Z",
"createdAt": "2024-01-01T00:00:00.000Z"
}
}Error Response: 400 Bad Request
{
"success": false,
"error": {
"code": "INVALID_ORDER",
"message": "Order not found or already paid"
}
}Validation Rules:
orderId: Required, must be a valid unpaid orderpaymentMethodId: Required, must be a valid payment methodamount: Required, must match order totalcurrency: Required, ISO 4217 currency codereturnUrl: Required, valid URLcancelUrl: Required, valid URL
Get Payment Details
Retrieve information about a specific payment.
Endpoint: GET /payments/:id
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Path Parameters:
id: Payment ID
Response: 200 OK
{
"success": true,
"data": {
"id": "pay_xyz789",
"orderId": "order_abc123",
"status": "succeeded",
"amount": 185.97,
"currency": "USD",
"paymentMethod": {
"id": "pm_card_visa",
"type": "card",
"brand": "visa",
"last4": "4242"
},
"transactionId": "txn_abc123xyz789",
"receiptUrl": "https://payment-provider.com/receipts/xyz789",
"refunded": false,
"refundedAmount": 0,
"metadata": {
"customerIp": "192.168.1.1",
"userAgent": "Mozilla/5.0..."
},
"createdAt": "2024-01-01T00:00:00.000Z",
"completedAt": "2024-01-01T00:05:00.000Z"
}
}Error Response: 404 Not Found
{
"success": false,
"error": {
"code": "PAYMENT_NOT_FOUND",
"message": "Payment not found"
}
}Confirm Payment
Confirm a payment after user authorization.
Endpoint: POST /payments/:id/confirm
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Path Parameters:
id: Payment ID
Request Body:
{
"paymentIntentId": "pi_abc123xyz789",
"paymentMethodDetails": {
"type": "card",
"cardToken": "tok_visa_4242"
}
}Response: 200 OK
{
"success": true,
"message": "Payment confirmed",
"data": {
"id": "pay_xyz789",
"orderId": "order_abc123",
"status": "succeeded",
"amount": 185.97,
"currency": "USD",
"transactionId": "txn_abc123xyz789",
"receiptUrl": "https://payment-provider.com/receipts/xyz789",
"completedAt": "2024-01-01T00:05:00.000Z"
}
}Error Response: 400 Bad Request
{
"success": false,
"error": {
"code": "PAYMENT_FAILED",
"message": "Payment declined by card issuer",
"details": {
"declineCode": "insufficient_funds",
"declineMessage": "Insufficient funds"
}
}
}Get Payment Methods
Retrieve available payment methods for the user.
Endpoint: GET /payments/methods
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Response: 200 OK
{
"success": true,
"data": {
"methods": [
{
"id": "pm_card_visa_1",
"type": "card",
"brand": "visa",
"last4": "4242",
"expiryMonth": 12,
"expiryYear": 2025,
"isDefault": true,
"billingAddress": {
"name": "John Doe",
"city": "New York",
"country": "US",
"zipCode": "10001"
}
},
{
"id": "pm_card_mastercard_1",
"type": "card",
"brand": "mastercard",
"last4": "5555",
"expiryMonth": 6,
"expiryYear": 2026,
"isDefault": false
},
{
"id": "pm_wallet_paypal",
"type": "digital_wallet",
"provider": "paypal",
"email": "[email protected]",
"isDefault": false
}
],
"availableTypes": [
{
"type": "card",
"name": "Credit/Debit Card",
"brands": ["visa", "mastercard", "amex", "discover"]
},
{
"type": "digital_wallet",
"name": "Digital Wallet",
"providers": ["paypal", "apple_pay", "google_pay"]
},
{
"type": "bank_transfer",
"name": "Bank Transfer",
"providers": ["ach", "wire"]
}
]
}
}Add Payment Method
Add a new payment method to the user's account.
Endpoint: POST /payments/methods
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Request Body:
{
"type": "card",
"cardToken": "tok_visa_4242",
"billingAddress": {
"name": "John Doe",
"street": "123 Main St",
"city": "New York",
"state": "NY",
"zipCode": "10001",
"country": "US"
},
"setAsDefault": true
}Response: 201 Created
{
"success": true,
"message": "Payment method added",
"data": {
"id": "pm_card_visa_2",
"type": "card",
"brand": "visa",
"last4": "4242",
"expiryMonth": 12,
"expiryYear": 2025,
"isDefault": true,
"billingAddress": {
"name": "John Doe",
"street": "123 Main St",
"city": "New York",
"state": "NY",
"zipCode": "10001",
"country": "US"
},
"createdAt": "2024-01-01T00:00:00.000Z"
}
}Error Response: 400 Bad Request
{
"success": false,
"error": {
"code": "INVALID_PAYMENT_METHOD",
"message": "Invalid card token or card details"
}
}Delete Payment Method
Remove a payment method from the user's account.
Endpoint: DELETE /payments/methods/:id
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Path Parameters:
id: Payment method ID
Response: 200 OK
{
"success": true,
"message": "Payment method removed"
}Error Response: 404 Not Found
{
"success": false,
"error": {
"code": "PAYMENT_METHOD_NOT_FOUND",
"message": "Payment method not found"
}
}Refund Payment
Initiate a refund for a completed payment.
Endpoint: POST /payments/:id/refund
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Path Parameters:
id: Payment ID
Request Body:
{
"amount": 185.97,
"reason": "customer_request",
"notes": "Customer requested refund due to wrong item"
}Response: 200 OK
{
"success": true,
"message": "Refund initiated",
"data": {
"refundId": "ref_abc123",
"paymentId": "pay_xyz789",
"orderId": "order_abc123",
"status": "pending",
"amount": 185.97,
"currency": "USD",
"reason": "customer_request",
"estimatedArrival": "2024-01-08T00:00:00.000Z",
"createdAt": "2024-01-01T00:00:00.000Z"
}
}Error Response: 400 Bad Request
{
"success": false,
"error": {
"code": "REFUND_FAILED",
"message": "Payment cannot be refunded (already refunded or too old)"
}
}Validation Rules:
amount: Optional, defaults to full payment amount, cannot exceed original amountreason: Required, must be one of:customer_request,fraudulent,duplicate,wrong_item- Payment must be in
succeededstatus - Refunds must be initiated within 90 days of payment
Payment Webhooks
Receive payment status updates from payment providers. This endpoint is called by the payment provider, not by clients.
Endpoint: POST /payments/webhooks
Headers:
X-Webhook-Signature: sha256=abc123xyz789...
Content-Type: application/jsonRequest Body:
{
"event": "payment.succeeded",
"paymentId": "pay_xyz789",
"orderId": "order_abc123",
"transactionId": "txn_abc123xyz789",
"amount": 185.97,
"currency": "USD",
"timestamp": "2024-01-01T00:05:00.000Z"
}Response: 200 OK
{
"success": true,
"message": "Webhook processed"
}Webhook Events:
payment.initiated: Payment session createdpayment.succeeded: Payment completed successfullypayment.failed: Payment failedpayment.canceled: Payment canceled by userrefund.created: Refund initiatedrefund.succeeded: Refund completedrefund.failed: Refund failed
Security:
- All webhooks are signed with HMAC-SHA256
- Verify the
X-Webhook-Signatureheader before processing - Webhooks have a 5-minute tolerance for timestamp validation
Payment Status
| Status | Description |
|---|---|
pending | Payment initiated, awaiting completion |
processing | Payment being processed by provider |
succeeded | Payment completed successfully |
failed | Payment failed |
canceled | Payment canceled by user |
refunded | Payment fully refunded |
partially_refunded | Payment partially refunded |
Error Codes
| Code | Description |
|---|---|
UNAUTHORIZED | Authentication required or token invalid |
PAYMENT_NOT_FOUND | Payment not found |
INVALID_ORDER | Order not found or already paid |
INVALID_PAYMENT_METHOD | Payment method invalid or expired |
PAYMENT_FAILED | Payment declined by provider |
INSUFFICIENT_FUNDS | Insufficient funds in account |
REFUND_FAILED | Refund cannot be processed |
WEBHOOK_VERIFICATION_FAILED | Webhook signature verification failed |
Best Practices
- Always verify webhook signatures to prevent fraud
- Handle idempotency - use the same payment ID for retries
- Store payment receipts for customer records
- Implement payment retry logic with exponential backoff
- Use PCI-compliant payment providers - never store card details directly
- Monitor failed payments and provide clear error messages
- Handle 3D Secure (3DS) for card payments when required
- Set appropriate timeout values for payment confirmations (typically 30 seconds)
Security
- All payment data is encrypted in transit using TLS 1.3
- Card details are tokenized and never stored on servers
- PCI DSS Level 1 compliant payment processing
- 3D Secure 2.0 (3DS2) supported for card payments
- Fraud detection and prevention built-in
- Regular security audits and penetration testing
Rate Limits
- Payment initiation: 20 requests per minute per user
- Payment confirmation: 10 requests per minute per user
- Payment method management: 30 requests per minute per user
- Webhooks: No rate limit (verified by signature)
Exceeding rate limits will result in a 429 Too Many Requests response.