GLODIPAY REFUND API SPECIFICATION
VERSION 2.0.0
Table of Contents
- Introduction
- Endpoints
- Signature
- REFUND API
- REFUND QUERY
- REFUND NOTIFICATION
- Appendix
- Refund Status Values
- Status Codes
- Code Examples
- PHP
- Node.js
Introduction
This document describes the GLODIPAY Refund API v2, which allows merchants to initiate refunds for completed transactions, query refund status, and receive refund notifications via IPN.
Key points:
- Refunds can be full or partial (subject to per-provider constraints -- some providers only support full-amount refunds).
- Refunds may be auto-processed immediately or held for manual approval, depending on merchant configuration.
- The
notificationUrlfrom the original transaction is used for refund IPN notifications. - The maximum refundable amount per refund is:
paidAmountminus the total already refunded for the transaction.
Endpoints
| Test | Get it from the API Keys page of the Sandbox Merchant Dashboard |
| Production | Get it from the API Keys page of the Merchant Dashboard |
Signature
All requests and responses are signed using RSA with MD5 (signature version 2.1).
Sending a request (Merchant -> GLODIPAY)
Put the request fields listed below in a JSON string, sign that exact string with your RSA Private Key, and send three fields:
| Field | Value |
|---|---|
signVersion | "2.1" |
payload | The request fields as a JSON string, e.g. JSON.stringify(fields) |
signature | Base64 of the md5WithRSAEncryption signature of payload |
Verifying what GLODIPAY sends (GLODIPAY -> Merchant)
Responses, redirects and webhooks use the same signVersion / payload / signature shape. Verify signature against the payload string with the GLODIPAY RSA Public Key, then parse payload as JSON.
Full details and code: Signature.
Requests without
signVersionare verified with the 2.0 rules. See Signature 2.0.
REFUND API
Initiate a refund for a completed transaction.
Endpoint: POST /v2/refund
Method: POST
Content-Type: application/json
Request
| transactionId | String (ULID) | M | The transactionId received from the checkout IPN or transaction query |
| amount | Float | M | Refund amount. Minimum: 0.10. Maximum: remaining refundable amount (paidAmount minus already refunded) |
| reason | String(max:1000) | O | Short description of the refund reason |
| signVersion | String | O | 2.1: send the other fields as a JSON string in payload (see Signature). Omit to use the 2.0 rules |
| signature | String(max:750) | M | RSA-MD5 signature |
Note: Certain providers (e.g. PayAgency, SmartPay, ClisaPay, FinvyPay, WPay) only support full-amount refunds. The system enforces the minimum refund amount accordingly.
Response
Content-Type: application/json
| status | String | success |
| message | String | Human-readable message |
| data | JSON | Refund details. See data object below |
data object:
| refundId | String (ULID) | GLODIPAY refund ID |
| refundNumber | String | GLODIPAY human-readable refund number |
Refund created and processed immediately (auto-refund enabled):
{
"status": "success",
"message": null,
"data": {
"refundId": "01jzabk09xc4pbgwe8hyg4cwbf",
"refundNumber": "2507-1751420414"
}
}
Refund created and pending manual approval:
{
"status": "success",
"message": "Refund created and waiting for approval.",
"data": {
"refundId": "01jzabk09xc4pbgwe8hyg4cwbf",
"refundNumber": "2507-1751420414"
}
}
Validation error (HTTP 422):
{
"status": "error",
"message": "Invalid request data.",
"errors": [
{
"field": "amount",
"message": ["The amount must be between 0.1 and 100."]
}
]
}
REFUND QUERY
Query the latest status of a refund.
Endpoint: POST /v2/refund/query
Method: POST
Content-Type: application/json
Request
| refundId | String (ULID) | M | GLODIPAY refund ID (from Refund API response or Refund IPN) |
| signVersion | String | O | 2.1: send the other fields as a JSON string in payload (see Signature). Omit to use the 2.0 rules |
| signature | String(max:750) | M | RSA-MD5 signature |
Response
Content-Type: application/json
| status | String | success |
| message | String | Human-readable message |
| data | JSON | Refund details object. See fields below |
data object fields:
| transactionId | String | GLODIPAY original transaction ID |
| ref | String | Merchant's orderRef |
| refundId | String | GLODIPAY refund ID |
| currency | String | ISO 4217 currency code |
| refundAmount | Float | Refund amount |
| status | String | Refund status. See Refund Status Values |
| statusCode | Number | Numeric status code. See Status Codes |
| metadata | JSON | Key-value pairs from the original checkout session |
| reason | String | Refund reason |
| message | String | Human-readable status message |
| originalRefundCreatedAt | ISO 8601 datetime | Refund creation time at the PSP |
| refundCreatedAt | ISO 8601 datetime | Refund creation time in GLODIPAY system |
| transactionCreatedAt | ISO 8601 datetime | Original transaction creation time |
| signature | String | RSA-MD5 signature -- verify with GLODIPAY public key |
Example:
{
"status": "success",
"message": "",
"data": {
"transactionId": "01jza90dy6w82dfrrqvadn5vs4",
"ref": "ORDER-001",
"refundId": "01jzabk09xc4pbgwe8hyg4cwbf",
"currency": "USD",
"refundAmount": 50.00,
"status": "refund_successful",
"statusCode": 11,
"metadata": { "orderId": "12345" },
"reason": "Customer request",
"message": null,
"originalRefundCreatedAt": "2026-04-14T11:00:00+00:00",
"refundCreatedAt": "2026-04-14T11:00:01+00:00",
"transactionCreatedAt": "2026-04-14T10:00:00+00:00"
}
}
2.1 accounts receive these fields as a JSON string in
payload, alongsidesignVersionandsignature; 2.0 accounts receive them flat withsignature. See Signature.
REFUND NOTIFICATION
GLODIPAY sends an HTTP POST to the notificationUrl of the original transaction when a refund status changes.
Method: POST
Content-Type: application/json
Retry policy: If your server does not return {"returnCode":"100"} within 30 seconds, GLODIPAY will retry delivery.
Payload
| transactionId | String | M | GLODIPAY original transaction ID |
| ref | String | M | Merchant's orderRef |
| refundId | String | M | GLODIPAY refund ID |
| currency | String | M | ISO 4217 currency code |
| refundAmount | Float | M | Refund amount |
| status | String | M | Refund status. See Refund Status Values |
| statusCode | Number | M | Numeric status code. See Status Codes |
| metadata | JSON | O | Key-value pairs from the original checkout session |
| reason | String | O | Refund reason |
| message | String | O | Human-readable status message |
| originalRefundCreatedAt | ISO 8601 datetime | M | Refund creation time at the PSP |
| refundCreatedAt | ISO 8601 datetime | M | Refund creation time in GLODIPAY system |
| transactionCreatedAt | ISO 8601 datetime | M | Original transaction creation time |
| signature | String | M | RSA-MD5 signature -- verify with GLODIPAY public key |
Example IPN Payload:
{
"transactionId": "01jza90dy6w82dfrrqvadn5vs4",
"ref": "ORDER-001",
"refundId": "01jzabk09xc4pbgwe8hyg4cwbf",
"currency": "USD",
"refundAmount": 50.00,
"status": "refund_successful",
"statusCode": 11,
"metadata": { "orderId": "12345" },
"reason": "Customer request",
"message": null,
"originalRefundCreatedAt": "2026-04-14T11:00:00+00:00",
"refundCreatedAt": "2026-04-14T11:00:01+00:00",
"transactionCreatedAt": "2026-04-14T10:00:00+00:00"
}
2.1 accounts receive these fields as a JSON string in
payload, alongsidesignVersionandsignature; 2.0 accounts receive them flat withsignature. See Signature.
Response (Merchant -> GLODIPAY)
Your server must respond within 30 seconds:
{
"returnCode": "100",
"description": "Received"
}
| returnCode | String | R | Must be "100" to acknowledge receipt |
| description | String(1,1500) | O | Optional description |
Appendix
Refund Status Values
String values returned in the status field of refund IPN payloads and refund query responses.
| refund_initiated | Refund request initiated |
| refund_under_review | Refund under review |
| refund_successful | Refund completed successfully |
| refund_failed | Refund failed |
| refund_partially_successful | Partial refund completed |
| refund_partially_failed | Partial refund failed |
| void_initiated | Void initiated |
| void_under_review | Void under review |
| void_successful | Void completed successfully |
| void_failed | Void failed |
| void_partially_successful | Partial void completed |
| void_partially_failed | Partial void failed |
Status Codes
Numeric code in the statusCode field of refund IPN payloads and refund query responses.
| 8 | refund_initiated | Refund initiated |
| 9 | refund_failed | Refund failed |
| 10 | refund_under_review | Refund under review |
| 11 | refund_successful | Refund successful |
| 12 | refund_partially_failed | Partial refund failed |
| 13 | refund_partially_successful | Partial refund successful |
| 18 | void_initiated | Void initiated |
| 19 | void_under_review | Void under review |
| 20 | void_successful | Void successful |
| 21 | void_failed | Void failed |
| 22 | void_partially_successful | Partial void successful |
| 23 | void_partially_failed | Partial void failed |
Code Examples
PHP
<?php
const PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----
YOUR_PRIVATE_KEY_HERE
-----END PRIVATE KEY-----
";
const GLODIPAY_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----
YOUR_GLODIPAY_PUBLIC_KEY_HERE
-----END PUBLIC KEY-----
";
function signPayload(array $fields, string $privateKeyPem): array
{
$payload = json_encode($fields);
openssl_sign($payload, $signature, openssl_pkey_get_private($privateKeyPem), 'md5WithRSAEncryption');
return ['signVersion' => '2.1', 'payload' => $payload, 'signature' => base64_encode($signature)];
}
function verifyBody(array $body, string $publicKeyPem): bool
{
return openssl_verify($body['payload'], base64_decode($body['signature']), openssl_pkey_get_public($publicKeyPem), 'md5WithRSAEncryption') === 1;
}
// Example: create a refund
$payload = [
'transactionId' => '01jza90dy6w82dfrrqvadn5vs4',
'amount' => '50.00',
'reason' => 'Customer request',
];
$body = signPayload($payload, PRIVATE_KEY);
$ch = curl_init('https://payment-sandbox.gpayprocessing.com/v2/refund');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
echo 'Refund ID: ' . $result['data']['refundId'];
Node.js
// Save as script.mjs and run: node script.mjs
import { createSign, createVerify } from 'crypto';
import https from 'https';
const PRIVATE_KEY = `-----BEGIN PRIVATE KEY-----
YOUR_PRIVATE_KEY_HERE
-----END PRIVATE KEY-----`;
const GLODIPAY_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
YOUR_GLODIPAY_PUBLIC_KEY_HERE
-----END PUBLIC KEY-----`;
function signPayload(fields, privateKeyPem) {
const payload = JSON.stringify(fields);
const signature = createSign('md5WithRSAEncryption').update(payload).sign(privateKeyPem, 'base64');
return { signVersion: '2.1', payload, signature };
}
function verifyBody(body, publicKeyPem) {
return createVerify('md5WithRSAEncryption').update(body.payload).verify(publicKeyPem, body.signature, 'base64');
}
// Example: create a refund
const payload = {
transactionId: '01jza90dy6w82dfrrqvadn5vs4',
amount: '50.00',
reason: 'Customer request',
};
const body = signPayload(payload, PRIVATE_KEY);
const postData = JSON.stringify(body);
const options = {
hostname: 'payment-sandbox.gpayprocessing.com',
path: '/v2/refund',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData),
},
};
const req = https.request(options, (res) => {
let body = '';
res.on('data', chunk => body += chunk);
res.on('end', () => {
const result = JSON.parse(body);
console.log('Refund ID:', result.data.refundId);
});
});
req.on('error', console.error);
req.write(postData);
req.end();