Skip to content

mpac-pgw Integration Guide

This guide explains how to integrate with the MPAC Payment Gateway using the available SDKs.

Overview

mpac-pgw uses a two-step payment flow inspired by Stripe's PaymentIntent pattern:

  1. Backend creates a PaymentIntent (server-to-server, HMAC-authenticated)
  2. Frontend confirms the payment (client SDK, payment_token-authenticated)
  Backend (HMAC-SHA256)          mpac-pgw                Frontend (payment_token)
  ─────────────────────         ─────────               ──────────────────────────
         │                          │                            │
         │ POST /v1/payment_intents │                            │
         │ ────────────────────────>│                            │
         │                          │                            │
         │ { id, payment_token }    │                            │
         │ <────────────────────────│                            │
         │                          │                            │
         │        pass payment_token to frontend                 │
         │ ──────────────────────────────────────────────────>   │
         │                          │                            │
         │                          │ GET /v1/payment_intents/:id│
         │                          │ <──────────────────────────│
         │                          │                            │
         │                          │ POST .../confirm           │
         │                          │ <──────────────────────────│
         │                          │                            │
         │                          │ { qr_content, status }     │
         │                          │ ──────────────────────────>│

Authentication

Server-to-Server (HMAC-SHA256)

All backend API calls use HMAC-SHA256 authentication:

Authorization: HMAC-SHA256 <api_key>:<timestamp>:<signature>

Message   = METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + HEX(SHA256(BODY))
Key       = bytes(HEX(SHA256(secret_key)))
Signature = HEX(HMAC-SHA256(Key, Message))

Note: The HMAC key is the byte representation of the hex-encoded SHA-256 of the secret key (64 ASCII bytes), matching the secret_key_hash column in the database.

The timestamp must be within a 5-minute window of the server's clock.

Client/Frontend (payment_token)

Frontend SDKs authenticate using a payment_token returned when creating a PaymentIntent:

  • GET requests: Token is sent as a query parameter ?payment_token=...
  • POST requests: Token is included in the request body { "payment_token": "..." }

Payment tokens are single-use, time-limited (5 minutes), and scoped to a single PaymentIntent.

Integration Steps

1. Backend Setup

Install the server-side SDK for your language:

Go:

bash
go get github.com/mp-solution-inc/mpac-pgw/sdks/sdk-go

Python:

bash
pip install mpac-pgw[http]

2. Create a PaymentIntent

Go:

go
client := mpspgw.NewClient(mpspgw.ClientConfig{
    BaseURL:   "https://pgw.example.com",
    APIKey:    "ak_01JXXXXXXXXXXXXXXXXXXXXXX",
    SecretKey: "sk_live_xxxxxxxxxxxxxxxxxxxxxxxx",
})

intent, err := client.CreatePaymentIntent(ctx, mpspgw.CreatePaymentIntentRequest{
    Amount:             1000,
    Currency:           "JPY",
    PaymentMethodTypes: []string{"qr_mpm"},
    MerchantRefID:      "order_12345",
    MerchantStoreID:    "store_001",
})
// Pass intent.PaymentToken to the frontend

Python:

python
from mpac_pgw import Client, ClientConfig, CreatePaymentIntentRequest

client = Client(ClientConfig(
    base_url="https://pgw.example.com",
    api_key="ak_01JXXXXXXXXXXXXXXXXXXXXXX",
    secret_key="sk_live_xxxxxxxxxxxxxxxxxxxxxxxx",
))

intent = client.create_payment_intent(CreatePaymentIntentRequest(
    amount=1000,
    currency="JPY",
    payment_method_types=["qr_mpm"],
    merchant_ref_id="order_12345",
    merchant_store_id="store_001",
))
# Pass intent.payment_token to the frontend

3. Frontend Payment Confirmation

JavaScript/TypeScript:

typescript
import { MPACGateway } from '@cloudsky/mpac-pgw-sdk-js';

const mps = new MPACGateway({
  publicKey: 'pk_test_xxx',
  environment: 'sandbox',
});

// Load the PaymentIntent with the token from your backend
const intent = await mps.retrievePaymentIntent(paymentToken);

// Confirm QR payment
const qr = await mps.confirmQRPayment('PAYPAY');

// Render qr.qr_content as a QR code for the customer to scan

// Listen for completion
mps.on('payment_success', (data) => {
  // Payment completed successfully
});

mps.on('payment_failed', (data) => {
  // Payment failed
});

// Clean up when done
mps.destroy();

4. Webhook Handling (Optional)

PGW sends webhooks for asynchronous payment events. Configure your webhook URL when setting up your organization.

Webhook payloads include the PaymentIntent ID and the updated status. Always verify the webhook signature before processing.

Payment Processing Modes

ModeMethodsDescription
pgw_processedQR (MPM/CPM)PGW processes the payment directly via provider APIs
externalCredit Card, E-MoneyPGW records the intent; processing happens via external apps
manualCashPGW records the intent; staff confirms payment received

Merchant/Store Sync

Before processing payments, merchant and store data must be synced from the upstream system:

go
err := client.SyncMerchants(ctx, mpspgw.SyncMerchantsRequest{
    Merchants: []mpspgw.SyncMerchant{
        {
            ID:   "merchant_001",
            Name: "Example Restaurant",
            Stores: []mpspgw.SyncStore{
                {
                    ID:   "store_001",
                    Name: "Tokyo Branch",
                    PaymentProcessorConfigs: []mpspgw.PaymentProcessorConfig{
                        {
                            Provider:    "PAYPAY",
                            IsActive:    true,
                            Credentials: map[string]interface{}{
                                "merchant_id": "paypay_merchant_123",
                            },
                        },
                    },
                },
            },
        },
    },
})

PaymentIntent Lifecycle

requires_payment_method --> requires_action --> processing --> succeeded
                                                          \--> failed
                                                          \--> cancelled
StatusDescription
requires_payment_methodInitial state after creation
requires_actionAwaiting user action (e.g., 3DS challenge)
processingPayment is being processed by the provider
succeededPayment completed successfully
failedPayment failed
cancelledPayment was cancelled

Error Handling

All SDKs return structured errors with a code and message:

CodeDescription
invalid_tokenPayment token is invalid or expired
invalid_requestRequest validation failed
provider_not_supportedQR provider is not yet supported
provider_errorError from the payment provider
rate_limit_exceededToo many requests (1000/min per merchant)
idempotency_conflictConflicting idempotent request

Rate Limits

  • Per merchant: 1,000 requests/minute
  • Global: 10,000 requests/minute
  • Rate limit headers are included in all responses

MPAC — MP-Solution Advanced Cloud Service