Payment Processing API
This guide provides comprehensive documentation for the Payment API, enabling direct payment processing with multiple payment methods, advanced features, and best practices for production deployment.
Overview
The Payment API enables direct payment processing without escrow terms, supporting various payment methods including mobile money, cards, and Piaxis wallet transactions. It’s ideal for immediate payment scenarios like retail purchases, service payments, and subscription billing.
Key Features: - Multiple payment methods (MTN, Airtel, Visa/Mastercard, Piaxis wallet) - Real-time payment processing - Comprehensive webhook notifications - Refund and dispute management - Recurring payment support - Advanced fraud protection
Use Cases: - E-commerce checkout - Service payments - Subscription billing - Marketplace transactions - Digital content purchases - Utility payments
Supported Payment Methods
Method |
Description |
Countries |
Processing Time |
|---|---|---|---|
|
|
MTN Mobile Money |
Uganda, Rwanda, Ghana |
30-60 seconds |
|
|
Airtel Money |
Uganda, Kenya, Tanzania |
30-60 seconds |
|
|
Visa/Mastercard |
All supported countries |
5-10 seconds |
|
|
External Piaxis Wallet |
All supported countries |
5-15 seconds |
Authentication Requirements
Payment Method |
Required Authentication |
Additional Requirements |
|---|---|---|
|
|
API Key only |
Valid phone number |
|
|
API Key only |
Valid phone number |
|
|
API Key only |
PCI compliance recommended |
|
|
API Key only |
Same merchant account |
|
|
OAuth2 Access Token |
User authorization required |
Creating Payments
Basic Payment Creation
- POST /api/payments/create
-
Create a direct payment transaction.
- JSON Parameters:
-
-
amount (number) – Payment amount (required)
-
currency (string) – Currency code (UGX, USD, etc.) (required)
-
payment_method (string) – Payment method identifier (required)
-
user_info (object) – Customer information (required for most methods)
-
reference (string) – Unique reference for the payment (optional)
-
description (string) – Payment description (optional)
-
metadata (object) – Additional custom data (optional)
-
products (array) – Product information for piaxis_external (conditional)
-
card_info (object) – Card details for card payments (conditional)
-
callback_url (string) – URL to redirect after payment (optional)
-
send_sms (boolean) – Send SMS notification to customer (optional)
-
send_email (boolean) – Send email receipt to customer (optional)
-
Example 1: MTN Mobile Money Payment
POST /api/payments/create HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json
{
"amount": 50000,
"currency": "UGX",
"payment_method": "mtn",
"reference": "INV-2024-001",
"description": "Product purchase - Electronics",
"user_info": {
"email": "[email protected]",
"phone_number": "+256700000000",
"name": "John Doe"
},
"metadata": {
"order_id": "ORD-789123",
"customer_type": "premium",
"source": "mobile_app"
},
"send_sms": true,
"send_email": true
}
Response:
{
"status": "success",
"data": {
"payment_id": "f530533e-3761-4cde-9c9d-88c5be6493bb",
"amount": "50000.00",
"currency": "UGX",
"status": "pending",
"payment_method": "mtn",
"reference": "INV-2024-001",
"description": "Product purchase - Electronics",
"customer": {
"email": "[email protected]",
"phone_number": "+256700000000",
"name": "John Doe"
},
"created_at": "2024-02-10T10:30:00Z",
"expires_at": "2024-02-10T10:45:00Z",
"payment_url": "https://payments.gopiaxis.com/pay/f530533e-3761-4cde-9c9d-88c5be6493bb",
"qr_code_url": "https://api.gopiaxis.com/payments/f530533e-3761-4cde-9c9d-88c5be6493bb/qr",
"metadata": {
"order_id": "ORD-789123",
"customer_type": "premium",
"source": "mobile_app"
}
}
}
Example 2: Airtel Money Payment
POST /api/payments/create HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json
{
"amount": 25000,
"currency": "UGX",
"payment_method": "airtel",
"reference": "BILL-2024-456",
"description": "Utility bill payment",
"user_info": {
"email": "[email protected]",
"phone_number": "+256750000000",
"name": "Jane Smith"
},
"callback_url": "https://yourapp.com/payment/callback"
}
Example 3: Card Payment
POST /api/payments/create HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json
{
"amount": 100000,
"currency": "UGX",
"payment_method": "card",
"reference": "SUB-2024-789",
"description": "Monthly subscription",
"user_info": {
"email": "[email protected]",
"name": "Alice Johnson"
},
"card_info": {
"save_card": true,
"card_holder_name": "Alice Johnson"
},
"metadata": {
"subscription_id": "sub_123456",
"plan": "premium"
}
}
Example 4: Piaxis External Payment (Requires OAuth2)
POST /api/payments/create HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
{
"amount": 75000,
"currency": "UGX",
"payment_method": "piaxis_external",
"reference": "PROD-2024-123",
"description": "Product purchase from marketplace",
"products": [
{
"product_id": "7c8b7cbe-4d52-4097-9fb2-858be26f5338",
"name": "Wireless Headphones",
"quantity": 1,
"unit_price": 75000
}
],
"metadata": {
"marketplace_order": "MP-789123",
"seller_id": "seller_456"
}
}
Example 5: Piaxis Internal Payment (Same Account)
POST /api/payments/create HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json
{
"amount": 15000,
"currency": "UGX",
"payment_method": "piaxis_external",
"reference": "TRANSFER-2024-001",
"description": "Internal account transfer"
}
Advanced Payment Features
Recurring Payments
POST /api/payments/create HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json
{
"amount": 50000,
"currency": "UGX",
"payment_method": "card",
"reference": "RECURRING-2024-001",
"description": "Monthly subscription payment",
"user_info": {
"email": "[email protected]",
"name": "Bob Wilson"
},
"recurring": {
"enabled": true,
"frequency": "monthly",
"start_date": "2024-02-15",
"end_date": "2024-12-15",
"max_cycles": 10
},
"card_info": {
"save_card": true
}
}
Split Payments
POST /api/payments/create HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json
{
"amount": 100000,
"currency": "UGX",
"payment_method": "mtn",
"reference": "SPLIT-2024-001",
"description": "Marketplace transaction",
"user_info": {
"email": "[email protected]",
"phone_number": "+256700000000"
},
"split_config": [
{
"recipient_id": "seller_123",
"amount": 85000,
"description": "Product sale"
},
{
"recipient_id": "platform_fee",
"amount": 15000,
"description": "Platform commission"
}
]
}
Payment Status & Tracking
Getting Payment Status
- GET /api/payments/{payment_id}
-
Get detailed information about a specific payment.
- Parameters:
-
-
payment_id – UUID of the payment
-
Example Request:
GET /api/payments/f530533e-3761-4cde-9c9d-88c5be6493bb HTTP/1.1 Host: api.gopiaxis.com api-key: YOUR_API_KEY
Response:
{ "status": "success", "data": { "payment_id": "f530533e-3761-4cde-9c9d-88c5be6493bb", "amount": "50000.00", "currency": "UGX", "status": "completed", "payment_method": "mtn", "reference": "INV-2024-001", "description": "Product purchase - Electronics", "customer": { "email": "[email protected]", "phone_number": "+256700000000", "name": "John Doe" }, "transaction_id": "TXN-MTN-123456789", "provider_reference": "MP240210.1030.A12345", "created_at": "2024-02-10T10:30:00Z", "completed_at": "2024-02-10T10:32:15Z", "fees": { "piaxis_fee": "1500.00", "provider_fee": "500.00", "total_fees": "2000.00" }, "metadata": { "order_id": "ORD-789123", "customer_type": "premium", "source": "mobile_app" } } }
Listing Payments
- GET /api/payments
-
List payments with filtering and pagination options.
- Query Parameters:
-
-
limit (int) – Number of payments to return (default: 20, max: 100)
-
offset (int) – Number of payments to skip (default: 0)
-
status (string) – Filter by payment status
-
payment_method (string) – Filter by payment method
-
start_date (string) – Filter payments after this date (ISO 8601)
-
end_date (string) – Filter payments before this date (ISO 8601)
-
reference (string) – Filter by payment reference
-
customer_email (string) – Filter by customer email
-
Example Request:
GET /api/payments?limit=50&status=completed&payment_method=mtn&start_date=2024-02-01T00:00:00Z HTTP/1.1 Host: api.gopiaxis.com api-key: YOUR_API_KEY
Response:
{ "status": "success", "data": { "payments": [ { "payment_id": "f530533e-3761-4cde-9c9d-88c5be6493bb", "amount": "50000.00", "currency": "UGX", "status": "completed", "payment_method": "mtn", "reference": "INV-2024-001", "created_at": "2024-02-10T10:30:00Z", "completed_at": "2024-02-10T10:32:15Z" } ], "pagination": { "total": 150, "limit": 50, "offset": 0, "has_more": true } } }
Payment Status Flow
Status |
Description |
Next Possible States |
|---|---|---|
|
|
Payment initiated, awaiting customer action |
|
|
|
Payment being processed by provider |
|
|
|
Payment successfully completed |
|
|
|
Payment failed |
|
|
|
Payment request expired |
None |
|
|
Payment cancelled by user or system |
None |
|
|
Payment has been refunded |
None |
|
|
Payment is under dispute |
|
Refunds & Reversals
Creating Refunds
- POST /api/payments/{payment_id}/refund
-
Create a refund for a completed payment.
- Parameters:
-
-
payment_id – UUID of the payment to refund
-
- JSON Parameters:
-
-
amount (number) – Refund amount (optional, defaults to full amount)
-
reason (string) – Reason for refund (optional)
-
metadata (object) – Additional refund data (optional)
-
Example Request:
POST /api/payments/f530533e-3761-4cde-9c9d-88c5be6493bb/refund HTTP/1.1 Host: api.gopiaxis.com api-key: YOUR_API_KEY Content-Type: application/json { "amount": 25000, "reason": "Partial refund for damaged item", "metadata": { "refund_type": "partial", "damaged_item_id": "item_123" } }
Response:
{ "status": "success", "data": { "refund_id": "ref_1234567890abcdef", "payment_id": "f530533e-3761-4cde-9c9d-88c5be6493bb", "amount": "25000.00", "currency": "UGX", "status": "processing", "reason": "Partial refund for damaged item", "created_at": "2024-02-10T15:00:00Z", "estimated_completion": "2024-02-12T15:00:00Z" } }
Refund Status Tracking
- GET /api/refunds/{refund_id}
-
Get refund status and details.
Example Response:
{ "status": "success", "data": { "refund_id": "ref_1234567890abcdef", "payment_id": "f530533e-3761-4cde-9c9d-88c5be6493bb", "amount": "25000.00", "currency": "UGX", "status": "completed", "reason": "Partial refund for damaged item", "refund_method": "original_payment_method", "created_at": "2024-02-10T15:00:00Z", "completed_at": "2024-02-12T14:30:00Z", "provider_reference": "REF-MTN-789456123" } }
Error Handling
Common Error Codes
Error Code |
HTTP Status |
Description |
|---|---|---|
|
|
400 |
Amount is invalid or exceeds limits |
|
|
400 |
Currency not supported |
|
|
400 |
Payment method not supported or invalid |
|
|
402 |
Customer has insufficient funds |
|
|
400 |
Payment request has expired |
|
|
409 |
Reference already exists |
|
|
400 |
Phone number format is invalid |
|
|
502 |
Payment provider returned an error |
|
|
402 |
Card payment was declined |
|
|
401 |
OAuth2 token required for this payment method |
Example Error Response:
{
"error": {
"code": "INSUFFICIENT_FUNDS",
"message": "The customer does not have sufficient funds for this transaction",
"details": {
"payment_id": "f530533e-3761-4cde-9c9d-88c5be6493bb",
"provider_code": "MW001",
"provider_message": "Your account balance is too low to complete this transaction",
"retry_possible": false,
"suggested_actions": [
"Ask customer to top up their account",
"Try a different payment method"
]
},
"timestamp": "2024-02-10T10:35:00Z",
"request_id": "req_1234567890abcdef"
}
}
Error Recovery Strategies
Retry Logic for Transient Errors:
import time
import requests
from typing import Dict, Any
def create_payment_with_retry(payment_data: Dict[str, Any], max_retries: int = 3) -> Dict[str, Any]:
retryable_errors = ['PROVIDER_ERROR', 'NETWORK_ERROR', 'TIMEOUT']
for attempt in range(max_retries):
try:
response = requests.post(
'https://api.gopiaxis.com/api/payments/create',
json=payment_data,
headers={'api-key': 'YOUR_API_KEY'}
)
if response.status_code == 200:
return response.json()
error_data = response.json()
error_code = error_data.get('error', {}).get('code')
if error_code not in retryable_errors or attempt == max_retries - 1:
raise Exception(f"Payment failed: {error_data}")
# Exponential backoff
wait_time = (2 ** attempt) + 1
time.sleep(wait_time)
except requests.RequestException as e:
if attempt == max_retries - 1:
raise Exception(f"Network error: {e}")
time.sleep((2 ** attempt) + 1)
Handling Specific Error Scenarios:
def handle_payment_error(error_code: str, error_data: Dict[str, Any]) -> str:
"""Return appropriate action based on error code"""
error_handlers = {
'INSUFFICIENT_FUNDS': 'Show customer balance error, suggest top-up',
'INVALID_PHONE_NUMBER': 'Ask customer to verify phone number',
'CARD_DECLINED': 'Suggest different card or payment method',
'EXPIRED_PAYMENT': 'Create new payment request',
'DUPLICATE_REFERENCE': 'Generate new unique reference',
'PROVIDER_ERROR': 'Retry with exponential backoff'
}
return error_handlers.get(error_code, 'Contact support for assistance')
Integration Examples
Python Integration
import requests
import json
import os
from datetime import datetime
from typing import Dict, Any, Optional
class PiaxisPayments:
def __init__(self, api_key: str, base_url: str = 'https://api.gopiaxis.com'):
self.api_key = api_key
self.base_url = base_url
self.headers = {
'api-key': api_key,
'Content-Type': 'application/json'
}
def create_payment(self, amount: float, currency: str, payment_method: str,
user_info: Dict[str, str], **kwargs) -> Dict[str, Any]:
"""Create a new payment"""
payment_data = {
'amount': amount,
'currency': currency,
'payment_method': payment_method,
'user_info': user_info,
**kwargs
}
response = requests.post(
f"{self.base_url}/api/payments/create",
json=payment_data,
headers=self.headers
)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"Payment creation failed: {response.text}")
def get_payment(self, payment_id: str) -> Dict[str, Any]:
"""Get payment details"""
response = requests.get(
f"{self.base_url}/api/payments/{payment_id}",
headers=self.headers
)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"Failed to get payment: {response.text}")
def list_payments(self, **filters) -> Dict[str, Any]:
"""List payments with optional filters"""
params = {k: v for k, v in filters.items() if v is not None}
response = requests.get(
f"{self.base_url}/api/payments",
params=params,
headers=self.headers
)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"Failed to list payments: {response.text}")
def refund_payment(self, payment_id: str, amount: Optional[float] = None,
reason: Optional[str] = None) -> Dict[str, Any]:
"""Create a refund for a payment"""
refund_data = {}
if amount is not None:
refund_data['amount'] = amount
if reason is not None:
refund_data['reason'] = reason
response = requests.post(
f"{self.base_url}/api/payments/{payment_id}/refund",
json=refund_data,
headers=self.headers
)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"Refund creation failed: {response.text}")
# Usage example
if __name__ == "__main__":
# Initialize client
piaxis = PiaxisPayments(api_key=os.getenv('piaxis_API_KEY'))
# Create MTN payment
try:
payment = piaxis.create_payment(
amount=50000,
currency='UGX',
payment_method='mtn',
user_info={
'email': '[email protected]',
'phone_number': '+256700000000',
'name': 'John Doe'
},
reference=f"ORDER-{datetime.now().strftime('%Y%m%d-%H%M%S')}",
description='Product purchase',
metadata={'order_id': 'ORD-123'}
)
print(f"Payment created: {payment['data']['payment_id']}")
print(f"Payment URL: {payment['data']['payment_url']}")
# Check payment status
status = piaxis.get_payment(payment['data']['payment_id'])
print(f"Payment status: {status['data']['status']}")
except Exception as e:
print(f"Error: {e}")
Node.js Integration
const axios = require('axios');
class PiaxisPayments {
constructor(apiKey, baseUrl = 'https://api.gopiaxis.com') {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
this.headers = {
'api-key': apiKey,
'Content-Type': 'application/json'
};
}
async createPayment(amount, currency, paymentMethod, userInfo, options = {}) {
const paymentData = {
amount,
currency,
payment_method: paymentMethod,
user_info: userInfo,
...options
};
try {
const response = await axios.post(
`${this.baseUrl}/api/payments/create`,
paymentData,
{ headers: this.headers }
);
return response.data;
} catch (error) {
throw new Error(`Payment creation failed: ${error.response?.data || error.message}`);
}
}
async getPayment(paymentId) {
try {
const response = await axios.get(
`${this.baseUrl}/api/payments/${paymentId}`,
{ headers: this.headers }
);
return response.data;
} catch (error) {
throw new Error(`Failed to get payment: ${error.response?.data || error.message}`);
}
}
async listPayments(filters = {}) {
try {
const response = await axios.get(
`${this.baseUrl}/api/payments`,
{
headers: this.headers,
params: filters
}
);
return response.data;
} catch (error) {
throw new Error(`Failed to list payments: ${error.response?.data || error.message}`);
}
}
async refundPayment(paymentId, amount = null, reason = null) {
const refundData = {};
if (amount !== null) refundData.amount = amount;
if (reason !== null) refundData.reason = reason;
try {
const response = await axios.post(
`${this.baseUrl}/api/payments/${paymentId}/refund`,
refundData,
{ headers: this.headers }
);
return response.data;
} catch (error) {
throw new Error(`Refund creation failed: ${error.response?.data || error.message}`);
}
}
async waitForPaymentCompletion(paymentId, maxWaitMinutes = 10) {
const maxAttempts = maxWaitMinutes * 2; // Check every 30 seconds
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const payment = await this.getPayment(paymentId);
const status = payment.data.status;
if (['completed', 'failed', 'expired', 'cancelled'].includes(status)) {
return payment;
}
// Wait 30 seconds before next check
await new Promise(resolve => setTimeout(resolve, 30000));
}
throw new Error(`Payment ${paymentId} did not complete within ${maxWaitMinutes} minutes`);
}
}
// Usage example
async function processPayment() {
const piaxis = new PiaxisPayments(process.env.piaxis_API_KEY);
try {
// Create card payment
const payment = await piaxis.createPayment(
100000,
'UGX',
'card',
{
email: '[email protected]',
name: 'Alice Johnson'
},
{
reference: `ORDER-${Date.now()}`,
description: 'Subscription payment',
callback_url: 'https://yourapp.com/payment/callback',
metadata: {
subscription_id: 'sub_123',
plan: 'premium'
}
}
);
console.log('Payment created:', payment.data.payment_id);
console.log('Payment URL:', payment.data.payment_url);
// Wait for completion (optional)
const completedPayment = await piaxis.waitForPaymentCompletion(
payment.data.payment_id,
5 // Wait up to 5 minutes
);
console.log('Payment completed:', completedPayment.data.status);
} catch (error) {
console.error('Error:', error.message);
}
}
// Run the example
processPayment();
Production Best Practices
Security Considerations
-
API Key Protection - Store API keys in environment variables - Use different keys for different environments - Rotate keys regularly - Never expose keys in client-side code
-
Request Validation - Validate all input data before sending to API - Implement proper error handling - Use HTTPS for all communications - Implement request signing for additional security
-
PCI Compliance (for card payments) - Never store card details on your servers - Use tokenization for recurring payments - Implement proper access controls - Regular security audits
Performance Optimization
-
Connection Pooling - Use HTTP connection pooling - Implement request queuing for high volumes - Set appropriate timeouts
-
Caching Strategy - Cache payment method configurations - Cache exchange rates if applicable - Implement smart refresh strategies
-
Monitoring & Alerting - Monitor payment success rates - Alert on high failure rates - Track payment processing times - Monitor API response times
# Example monitoring setup
import logging
import time
from functools import wraps
def monitor_payment_api(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
try:
result = func(*args, **kwargs)
duration = time.time() - start_time
logging.info(f"Payment API call successful: {func.__name__} took {duration:.2f}s")
return result
except Exception as e:
duration = time.time() - start_time
logging.error(f"Payment API call failed: {func.__name__} took {duration:.2f}s, error: {e}")
raise
return wrapper
Webhook Integration
Set up webhooks to handle payment status changes:
from flask import Flask, request, jsonify
import hmac
import hashlib
app = Flask(__name__)
@app.route('/webhooks/payments', methods=['POST'])
def handle_payment_webhook():
# Verify webhook signature
signature = request.headers.get('X-Piaxis-Signature')
if not verify_signature(request.data, signature):
return jsonify({'error': 'Invalid signature'}), 401
event_data = request.get_json()
event_type = event_data.get('event')
if event_type == 'payment.completed':
# Handle successful payment
payment_data = event_data['data']
update_order_status(payment_data['reference'], 'paid')
send_confirmation_email(payment_data['customer']['email'])
elif event_type == 'payment.failed':
# Handle failed payment
payment_data = event_data['data']
update_order_status(payment_data['reference'], 'payment_failed')
send_failure_notification(payment_data['customer']['email'])
return jsonify({'status': 'processed'}), 200
Testing & Debugging
Test Environment
Use Piaxis sandbox environment for testing:
# Sandbox configuration
SANDBOX_API_KEY = 'pk_test_1234567890abcdef'
SANDBOX_BASE_URL = 'https://sandbox-api.gopiaxis.com'
# Test payment
piaxis_test = PiaxisPayments(SANDBOX_API_KEY, SANDBOX_BASE_URL)
Test Data:
-
Test Phone Numbers: +256700000000 - +256700000099
-
Test Cards: 4111111111111111 (Visa), 5555555555554444 (Mastercard)
-
Test Amounts: Use specific amounts to trigger different scenarios
Test Scenarios:
# Test different payment scenarios
test_scenarios = [
{'amount': 1000, 'expected': 'completed'}, # Success
{'amount': 1001, 'expected': 'failed'}, # Failure
{'amount': 1002, 'expected': 'insufficient'}, # Insufficient funds
{'amount': 1003, 'expected': 'expired'}, # Expiry
]
Debugging Tools
Request/Response Logging:
import logging
import json
def log_api_call(method, url, request_data, response_data, status_code):
log_entry = {
'method': method,
'url': url,
'request': request_data,
'response': response_data,
'status_code': status_code,
'timestamp': datetime.now().isoformat()
}
if status_code >= 400:
logging.error(f"API Error: {json.dumps(log_entry)}")
else:
logging.info(f"API Success: {json.dumps(log_entry)}")
Common Debugging Steps:
Check API key validity
-
Verify request format and required fields
Check payment method availability
-
Validate phone numbers and email addresses
Review webhook delivery logs
Test with smaller amounts first
Support & Resources
Documentation: - API Reference: https://docs.gopiaxis.com/api/payments/ - Integration Guides: https://docs.gopiaxis.com/guides/payments/ - SDKs: https://github.com/piaxis/sdks/
Support Channels: - Email: payments-support@piaxis.com - Developer Forum: https://forum.gopiaxis.com/ - Status Page: https://status.gopiaxis.com/
Testing Tools: - Sandbox Dashboard: https://sandbox-dashboard.gopiaxis.com/ - Webhook Testing: https://dashboard.gopiaxis.com/webhooks/test - API Explorer: https://docs.gopiaxis.com/api/explorer/
Emergency Support: For critical payment issues: emergency@piaxis.com (include merchant ID and payment ID)