Callback penerimaan

The merchant server is called only after a pay-in completes successfully; the callback status is always completed.

Only final payment results are sent. Any HTTP 2xx response stops delivery immediately. After the first failure, the platform retries in 1 minute; after another failure, it makes a final retry in 5 minutes, for up to 3 attempts total. Callback business times use Beijing time in YYYY/MM/DD HH:mm:ss format.

POSTnotifyUrl dari permintaan pembuatan pesanan pembayaran body

Header

KolomTipeWajibDeskripsi
content-typeapplication/jsonYaSelalu aplikasi/json.
x-callback-timestampstringYaPanggilan balik timestamp dalam milidetik.
x-callback-noncestringYaPanggilan balik nonce.
x-callback-signaturestringYaHMAC-SHA256(apiKey, timestamp + "." + nonce + "." + rawBody)。
x-callback-signature-algorithmstringYaSelalu HMAC-SHA256.
x-callback-signature-versionstringYaSelalu v1.

Parameter

KolomTipeWajibDeskripsi
merchantUidstringYaMerchant UID.
orderNostringYaNomor pesanan platform.
merchantOrderNostring | nullYaNomor pesanan pedagang.
bindKeystring | nullYaKunci pengikatan untuk isi ulang anggota. Biasanya kosong untuk pesanan pembayaran bersama.
chainCodestring | nullYaJaringan pesanan.
tokenSymbolstring | nullYaToken pesanan.
txHashstring | nullYaHash transaksi yang cocok; null sebelum terdeteksi.
expectedAmountstring | nullYaJumlah pesanan.
paidAmountstringYaJumlah pembayaran sebenarnya.
fromAddressstring | nullYaAlamat pengirim.
statusstringYaFinal successful pay-in status; always completed.
modestringYaMode: shared atau exclusive.
businessTypestringYaJenis bisnis pesanan.
serviceFeeUsdstringTIDAKBiaya layanan penerimaan ini.
feeBalanceAfterUsdstringTIDAKSaldo akun biaya setelah pemotongan.
payerRiskStatusstringYaStatus penilaian risiko pembayar.
payerRiskLabelstring | nullYaLabel penilaian risiko pembayar.

Contoh permintaan

{
  "merchantUid": "880001",
  "orderNo": "PI1776193200123ABCD1234",
  "merchantOrderNo": "M202604150001",
  "bindKey": null,
  "expectedAmount": "100.000000",
  "paidAmount": "100.000000",
  "chainCode": "TRON",
  "tokenSymbol": "USDT",
  "txHash": "f7f17891f52c35d0c93170f0d12bb347ac16ab34853b4bc8dcf7fd0a8c9aa321",
  "fromAddress": "TS7b7iD8G2PaPqK1TqSmLJ9nrrYH4oKX1S",
  "status": "completed",
  "mode": "shared",
  "businessType": "fixed",
  "serviceFeeUsd": "0.000000",
  "feeBalanceAfterUsd": "10.000000",
  "payerRiskStatus": "low_risk",
  "payerRiskLabel": "低风险"
}

Kolom respons

KolomTipeWajibDeskripsi
HTTP Status200-299YaSetiap respons 2xx dianggap sukses.
Response Bodystring | jsonTIDAKRespons body dapat disesuaikan.

Contoh respons

HTTP/1.1 200 OK
Content-Type: application/json

{
  "ok": true
}

Contoh kode

Menjalankan: simpan Java sebagai UUGateExample.java (UUGateCallback.java untuk callback), lalu gunakan java nama file; PHP: php example.php; Go: go run example.go; Node.js: node example.mjs. Verifikasi callback membaca isi asli dari input standar.

import { createHmac, timingSafeEqual } from 'node:crypto';

function required(name) {
  const value = process.env[name]?.trim();
  if (!value) throw new Error(name + ' is required');
  return value;
}
const key = required('UUGATE_API_KEY');
const timestamp = required('UUGATE_CALLBACK_TIMESTAMP'), nonce = required('UUGATE_CALLBACK_NONCE');
const signature = required('UUGATE_CALLBACK_SIGNATURE');
const chunks = [];
for await (const chunk of process.stdin) chunks.push(chunk);
const rawBody = Buffer.concat(chunks);
const expected = createHmac('sha256', key).update(timestamp + '.' + nonce + '.', 'utf8').update(rawBody).digest();
const actual = Buffer.from(signature, 'hex');
if (!/^[a-fA-F0-9]{64}$/.test(signature) || actual.length !== expected.length || !timingSafeEqual(expected, actual))
  throw new Error('Invalid callback signature');
console.log('VERIFIED');

Catatan

  • Verifikasi panggilan balik menggunakan apiKey, bukan header permintaan tanda tangan x OpenAPI.
  • Setelah verifikasi, cocokkan merchant, pesanan, aset, jaringan, dan jumlah. Simpan pembayaran serta hasil secara transaksional dan idempoten berdasarkan nomor platform sebelum merespons 2xx; notifikasi berulang tidak boleh menggandakan kredit atau pengiriman.
  • Untuk isi ulang anggota, gunakan bindKey secara langsung sebagai pengenal anggota sehingga Anda tidak memerlukan tabel pemetaan orderNo-ke-anggota tambahan.
  • Kode ini hanya memverifikasi callback. Kirim isi asli ke input standar dan petakan header ke UUGATE_CALLBACK_TIMESTAMP, UUGATE_CALLBACK_NONCE, UUGATE_CALLBACK_SIGNATURE. UUGATE_API_KEY harus sama dengan key saat membuat pesanan. Selanjutnya periksa pesanan dan simpan secara idempoten dalam transaksi sebelum mengembalikan HTTP 2xx.