Crownline Global — Payment API Integration Guide

Welcome! This guide explains how to integrate your platform with Crownline Global's payment system to accept payments from your customers.


1. Overview

Crownline Global handles the full payment process for you — from generating payment instructions for your customers to confirming when funds have arrived. You only need to talk to our API, using the API key we provide you.

Base URL (production):

https://api.crownlineglobal.co.uk

All requests must be sent over HTTPS. Requests over plain HTTP will be rejected.


2. Authentication

Every API request must include your API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Your API key is issued when your merchant account is created, and is visible (masked, with a "Show" option) in your Merchant Dashboard.

Keep your API key secret. Anyone with your API key can create payments on your behalf. If you believe your key has been compromised, regenerate it immediately from your dashboard under API Key → Regenerate.

⚠️ Regenerating your key immediately invalidates the old one. Update your integration with the new key right away, or your payment requests will start failing with 401 Unauthorized.


3. Creating a Payment

You have two integration options, depending on whether you want to build your own checkout page or use ours.

Option A — API Endpoint (you build your own checkout UI)

Use this if you want full control over how the payment method (bank transfer code, QR code, etc.) is displayed to your customer.

Endpoint:

POST /api/payments/create

Request body:

Field Type Required Description
merchantOrderId string Yes Your own unique order ID (must be unique per request)
amount number Yes Payment amount
countryCode string Yes e.g. IDN, VN, BR, COL, IN, BD, KR
currency string Yes e.g. Rp, VND, BRL, COP, INR, BDT, KRW
language string Yes e.g. EN, ID
paymentMethodCode string Yes The payment method to use (we'll provide the list of available codes for your target country)
notificationUrl string Yes Your own webhook URL — we will POST payment status updates here (see Section 5)
customerName string Yes Customer's full name
customerEmail string Yes Customer's email address
customerPhone string Yes Customer's phone number
customerPersonalId string Conditional Customer's national ID / personal identification number. Required for some countries (e.g. Vietnam, Brazil, India) — check with us for your target country. Omit if not required.
productName string Yes Description of what's being purchased

Example request:

curl -X POST https://api.crownlineglobal.co.uk/api/payments/create \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "merchantOrderId": "ORDER-1001",
    "amount": 150000,
    "countryCode": "IDN",
    "currency": "Rp",
    "language": "ID",
    "paymentMethodCode": "BNIVA",
    "notificationUrl": "https://yourshop.com/webhooks/payment",
    "customerName": "Jane Doe",
    "customerEmail": "jane@example.com",
    "customerPhone": "081234567890",
    "productName": "Order #1001"
  }'

Response:

{
  "code": "SUCCESS",
  "status": "PENDING",
  "platformOrderId": "2026080600100001",
  "paymentInfo": {
    "type": "code",
    "content": "8330600001522451",
    "expiredTime": "20260806141616"
  }
}

The paymentInfo.content field is what you show your customer — its meaning depends on paymentInfo.type:

type Meaning
code A virtual account number / payment code for the customer to use
url A link to redirect the customer to for payment
html Raw HTML content to render on your page
json A nested JSON object (e.g. QR code data + a fallback link)

Option B — Hosted Payment Page (we host the checkout)

Use this if you'd rather not build a payment UI yourself. Same request format, different endpoint:

POST /api/payments/create-h5

The response's paymentInfo.content will be a URL — redirect your customer's browser there to complete payment. Once done, they'll be redirected back automatically.


4. Checking Payment Status

You can check the status of any order at any time:

GET /api/payments/status?merchantOrderId=ORDER-1001
curl "https://api.crownlineglobal.co.uk/api/payments/status?merchantOrderId=ORDER-1001" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response:

{
  "code": "SUCCESS",
  "status": "SUCCESS",
  "amount": 150000,
  "paidAmount": "150000",
  "currency": "Rp"
}

Important: amount is the amount requested. paidAmount is the amount actually paid by the customer — these can differ. Always use paidAmount to confirm whether an order was paid in full, not amount.

Possible status values: PENDING, SUCCESS, FAILED.


5. Webhook Notifications

When a payment's status changes (typically when it succeeds), we send a POST request to the notificationUrl you provided when creating the payment.

What we send:

{
  "merchantOrderId": "ORDER-1001",
  "status": "SUCCESS",
  "amount": 150000,
  "paidAmount": "150000",
  "currency": "Rp"
}

Headers:

Header Description
Content-Type application/json
X-Payfac-Signature HMAC-SHA256 signature of the raw request body, signed with your API key (hex-encoded)

Verifying the signature

To confirm a webhook genuinely came from us (and not an impersonator), recompute the signature yourself and compare:

Pseudocode:

expected_signature = HMAC_SHA256(key = your_api_key, message = raw_request_body)
if expected_signature != X-Payfac-Signature header:
    reject the request

Node.js example:

const crypto = require('crypto');

function verifyWebhook(rawBody, signatureHeader, apiKey) {
  const expected = crypto
    .createHmac('sha256', apiKey)
    .update(rawBody)
    .digest('hex');
  return expected === signatureHeader;
}

PHP example:

function verifyWebhook($rawBody, $signatureHeader, $apiKey) {
    $expected = hash_hmac('sha256', $rawBody, $apiKey);
    return hash_equals($expected, $signatureHeader);
}

Always compute the signature over the raw, unparsed request body — not a re-serialized version of the JSON, as formatting differences will cause the signature check to fail.

Responding to our webhook

Return an HTTP 200 status code to acknowledge receipt. If we don't receive a 200, we currently do not automatically retry — we recommend checking payment status via the API (Section 4) as a backup if you suspect a webhook was missed.


6. Error Handling

All error responses follow this shape:

{
  "error": "description of what went wrong"
}

Common HTTP status codes:

Status Meaning
200 Success
400 Invalid request (missing/malformed fields)
401 Missing or invalid API key
403 Your merchant account has been suspended — contact us
502 We couldn't process the request — retry shortly

7. Testing

Before going live, we can provide you with a test/sandbox API key so you can validate your integration end-to-end without moving real funds. Contact us to request sandbox access.


8. Security Checklist


9. Support

If you run into issues integrating, or need the list of paymentMethodCode values available for your target country, please reach out to your Crownline Global account contact.


10. Additional Resources