mpac-pgw API Authentication Guide
This guide explains how to authenticate with the mpac-pgw API.
Overview
mpac-pgw uses two authentication methods:
| Method | Use Case | Endpoints |
|---|---|---|
| HMAC-SHA256 | Server-to-server calls | Create, List, Capture, Sync |
| payment_token | Client/SDK calls | Retrieve, Confirm, Cancel |
API Keys
Each Organization receives API credentials:
api_key(client_id): Public identifier, e.g.,pk_test_abc123...secret_key: Private key for signing, e.g.,sk_test_xyz789...
Security: Never expose your
secret_keyin client-side code. It should only be used on your backend servers.
HMAC-SHA256 Authentication
Used for server-to-server API calls that require organization-level authentication.
Header Format
Authorization: HMAC-SHA256 <api_key>:<timestamp>:<signature>Signature Calculation
1. Build the message:
MESSAGE = METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + SHA256(BODY)
2. Hash the secret key:
SECRET_KEY_HASH = SHA256(secret_key)
3. Calculate signature:
SIGNATURE = HMAC-SHA256(SECRET_KEY_HASH, MESSAGE)Parameters
| Parameter | Description | Example |
|---|---|---|
METHOD | HTTP method (uppercase) | POST |
PATH | Request path (without query string) | /v1/payment_intents |
TIMESTAMP | Unix timestamp (seconds) | 1702123456 |
BODY | Request body (empty string if no body) | {"amount": 1000} |
Code Examples
JavaScript/Node.js
javascript
const crypto = require('crypto');
function generateHMACAuth(apiKey, secretKey, method, path, body = '') {
const timestamp = Math.floor(Date.now() / 1000).toString();
// Hash the body
const bodyHash = crypto.createHash('sha256')
.update(body)
.digest('hex');
// Build message
const message = `${method}\n${path}\n${timestamp}\n${bodyHash}`;
// Hash the secret key
const secretKeyHash = crypto.createHash('sha256')
.update(secretKey)
.digest('hex');
// Calculate HMAC signature
const signature = crypto.createHmac('sha256', secretKeyHash)
.update(message)
.digest('hex');
return `HMAC-SHA256 ${apiKey}:${timestamp}:${signature}`;
}
// Usage
const authHeader = generateHMACAuth(
'pk_test_abc123',
'sk_test_xyz789',
'POST',
'/v1/payment_intents',
JSON.stringify({ merchant_id: '...', store_id: '...', amount: 1000 })
);
fetch('https://api.example.com/v1/payment_intents', {
method: 'POST',
headers: {
'Authorization': authHeader,
'Content-Type': 'application/json'
},
body: JSON.stringify({ merchant_id: '...', store_id: '...', amount: 1000 })
});Python
python
import hashlib
import hmac
import time
import json
import requests
def generate_hmac_auth(api_key: str, secret_key: str, method: str, path: str, body: str = '') -> str:
timestamp = str(int(time.time()))
# Hash the body
body_hash = hashlib.sha256(body.encode()).hexdigest()
# Build message
message = f"{method}\n{path}\n{timestamp}\n{body_hash}"
# Hash the secret key
secret_key_hash = hashlib.sha256(secret_key.encode()).hexdigest()
# Calculate HMAC signature
signature = hmac.new(
secret_key_hash.encode(),
message.encode(),
hashlib.sha256
).hexdigest()
return f"HMAC-SHA256 {api_key}:{timestamp}:{signature}"
# Usage
body = json.dumps({"merchant_id": "...", "store_id": "...", "amount": 1000})
auth_header = generate_hmac_auth(
'pk_test_abc123',
'sk_test_xyz789',
'POST',
'/v1/payment_intents',
body
)
response = requests.post(
'https://api.example.com/v1/payment_intents',
headers={
'Authorization': auth_header,
'Content-Type': 'application/json'
},
data=body
)Go
go
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"strconv"
"time"
)
func generateHMACAuth(apiKey, secretKey, method, path, body string) string {
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
// Hash the body
bodyHashBytes := sha256.Sum256([]byte(body))
bodyHash := hex.EncodeToString(bodyHashBytes[:])
// Build message
message := method + "\n" + path + "\n" + timestamp + "\n" + bodyHash
// Hash the secret key
secretKeyHashBytes := sha256.Sum256([]byte(secretKey))
secretKeyHash := hex.EncodeToString(secretKeyHashBytes[:])
// Calculate HMAC signature
mac := hmac.New(sha256.New, []byte(secretKeyHash))
mac.Write([]byte(message))
signature := hex.EncodeToString(mac.Sum(nil))
return fmt.Sprintf("HMAC-SHA256 %s:%s:%s", apiKey, timestamp, signature)
}Timestamp Tolerance
The server accepts timestamps within 5 minutes of server time. Requests with older timestamps will be rejected with expired_signature error.
Common Errors
| Error Code | Description | Solution |
|---|---|---|
invalid_signature | Signature doesn't match | Check your signing logic |
expired_signature | Timestamp too old | Use current Unix timestamp |
client_not_found | Invalid API key | Verify your api_key |
client_suspended | Organization is suspended | Contact support |
Payment Token Authentication
Used for client-side SDK calls after a PaymentIntent is created.
How It Works
- Your backend creates a PaymentIntent (using HMAC auth)
- Backend receives
payment_tokenin response - Backend passes
payment_tokento client/SDK - Client uses
payment_tokenfor subsequent operations
Usage
GET requests: Pass as query parameter
GET /v1/payment_intents/{id}?payment_token=pi_xxx_secret_yyyPOST requests: Include in request body
json
POST /v1/payment_intents/{id}/confirm
{
"payment_token": "pi_xxx_secret_yyy",
"payment_method_type": "qr_mpm",
"provider": "PAYPAY"
}Security Notes
payment_tokenis tied to a specific PaymentIntent- It expires when the PaymentIntent expires (default: 30 minutes)
- It can only be used for operations on its associated PaymentIntent
- Token format:
{payment_intent_id}_secret_{random_hex}
Best Practices
- Store secrets securely: Use environment variables or secret managers
- Never log secrets: Avoid logging full API keys or signatures
- Use HTTPS: Always use TLS in production
- Rotate keys: Periodically rotate API keys (you can have multiple active keys)
- Separate environments: Use different API keys for test/staging/production
Testing with Postman
- Import
postman/mpac-pgw.postman_collection.json - Import
postman/mpac-pgw-Test.postman_environment.json - Set environment variables:
client_id: Your API key (e.g.,pk_test_...)secret_key: Your secret key (e.g.,sk_test_...)merchant_id: Merchant IDstore_id: Store ID
- The collection includes a pre-request script that auto-generates HMAC signatures
Quick Reference
Endpoints by Authentication Type
| Endpoint | Method | Auth Type |
|---|---|---|
/v1/payment_intents | POST | HMAC |
/v1/payment_intents | GET | HMAC |
/v1/payment_intents/{id} | GET | payment_token |
/v1/payment_intents/{id}/confirm | POST | payment_token |
/v1/payment_intents/{id}/cancel | POST | payment_token |
/v1/payment_intents/{id}/capture | POST | HMAC |
/v1/payment_intents/{id}/transactions | GET | payment_token |
/v1/transactions/{id} | GET | HMAC |
/v1/sync/merchants | POST | HMAC |