Skip to main content

Signature

All requests to GLODIPAY must include a signature field. All responses and IPN payloads from GLODIPAY include a signature field so you can verify authenticity.

Signatures use RSA with MD5 (md5WithRSAEncryption).

Your RSA Private Key and the RSA Public Key are both available from the API Keys page in the Merchant Dashboard.


Generating a Signature (Merchant → GLODIPAY)

Sign request payloads with your RSA Private Key (obtained from the Merchant Dashboard).

Steps:

  1. Filter Payload: Collect all request parameters except signature. Remove any keys with empty strings (""), null, or undefined values.
  2. Stringify Nested Data: If a field value is an object or array (e.g., metadata, browserDetails, transactionDocuments), convert it to a JSON string using your language's default encoder (no spaces).
  3. Sort Top-Level Keys: Sort the resulting keys in natural ascending order (case-sensitive). Use SORT_NATURAL in PHP or localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }) in JavaScript.
  4. Casting & Trimming:
    • Convert numbers to strings.
    • Convert booleans: true becomes "1", false becomes "".
    • Trim leading/trailing whitespace from all values.
  5. Canonicalization: Serialize the sorted object to a JSON string with all non-ASCII Unicode characters escaped to \uXXXX (RFC 8259). In PHP, json_encode($data) does this by default — do not use JSON_UNESCAPED_UNICODE. In Node.js, JSON.stringify() does not escape Unicode by default — apply the fix below.
    • Node.js — forward slashes: Apply .replace(/\//g, '\\/') to match PHP's default behavior.
    • Node.js — Unicode (RFC 8259): Apply .replace(/[\u0080-\uffff]/g, c => '\\u' + c.charCodeAt(0).toString(16).padStart(4, '0')) to escape all non-ASCII characters. This is required because JSON.stringify() keeps characters like á, đ, as raw UTF-8, while PHP escapes them to á, đ, . Without this fix, signatures will not match when the payload contains non-ASCII characters.
  6. Signing: Sign the canonical string with md5WithRSAEncryption.
  7. Encoding: Base64-encode the binary output and add it as the signature field.

Verifying a Signature (GLODIPAY → Merchant)

Verify GLODIPAY responses and webhooks with the RSA Public Key (available in the Portal).

Steps:

  1. Extract the signature value and remove the signature key from the payload.
  2. Follow the same Filtering, Stringifying, Sorting, and Trimming steps as described above.
  3. Verify the canonical string against the extracted signature using the RSA Public Key and md5WithRSAEncryption.

Code Examples

PHP

<?php

function generateSignature(array $data, string $privateKeyStr): string
{
unset($data['signature']);

// 1. Filter out empty/null values
$data = array_filter($data, function($v) {
return $v !== "" && $v !== null;
});

// 2. Stringify nested objects
foreach ($data as $k => $v) {
if (is_array($v)) $data[$k] = json_encode($v);
}

// 3. Sort keys
ksort($data, SORT_NATURAL);

// 4. Casting and trimming
array_walk_recursive($data, function (&$v) {
if (is_bool($v)) $v = $v ? "1" : "";
else $v = trim((string)$v);
});

// 5. Sign (PHP json_encode escapes '/' by default)
$key = openssl_pkey_get_private($privateKeyStr);
openssl_sign(json_encode($data), $signature, $key, 'md5WithRSAEncryption');

return base64_encode($signature);
}

Node.js

// Save as script.mjs and run: node script.mjs
import { createSign } from 'crypto';

function phpCast(v) {
if (typeof v === 'number') return String(v);
if (typeof v === 'boolean') return v ? '1' : '';
if (typeof v === 'string') return v.trim();
if (Array.isArray(v)) return v.map(phpCast);
if (v && typeof v === 'object') return Object.fromEntries(Object.entries(v).map(([k, val]) => [k, phpCast(val)]));
return v;
}

function generateSignature(data, privateKey) {
const sorted = {};
Object.keys(data)
.filter(k => k !== 'signature')
.sort((a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }))
.forEach(k => { sorted[k] = data[k]; });

const canonical = JSON.stringify(phpCast(sorted))
.replace(/\//g, '\\/')
.replace(/[\u0080-\uffff]/g, c => '\\u' + c.charCodeAt(0).toString(16).padStart(4, '0'));

const sign = createSign('md5WithRSAEncryption');
sign.update(canonical);
return sign.sign(privateKey, 'base64');
}

Bookmarks

No bookmarks yet.
Hover over a heading and click to save a section.