Buat dan Validasi Signature

Safe Acceptance API menggunakan komunikasi klien ke server dan bukan server ke server. Untuk menjaga keamanan transaksi, pengguna diharapkan membuat signature dan validasi pesan untuk menjaga keaslian pesan atau transaksi yang berjalan.

API menggunakan signature sebagai validator untuk request dan respon yang sesuai. signature dibuat dari body request dan respon dengan melakukan hashing dengan kunci rahasia bersama yang hanya diketahui oleh merchant dan Xendit.

Jika Anda melakukan verifikasi signature dalam tanggapan Xendit dan tidak cocok dengan body request Anda, kemungkinan respon tersebut telah dirusak dan berpotensi terkena penipuan. Respon harus ditolak dalam situasi itu.

Secara singkat, langkah-langkah yang diperlukan adalah sebagai berikut:

  1. Membuat shared secret dari secret API key Anda
  2. Membuat representasi string dari body request transaksi Anda
  3. Tanda tangani (signing) string dengan shared secret Anda
  4. Tambahkan signature dan signed_fields ke body request yang akan di-POST ke API safe acceptance

Di bawah ini adalah penjelasan secara detil pada setiap langkahnya.

1. Membuat shared secret dari secret API key Anda

Untuk membuat shared secret, gunakan secret API key apa pun dengan akses write yang dihasilkan dari Dasbor Xendit dan hash dengan sha256.

hash('sha256', 'put_your_Xendit_secret_API_key_here'); 
const sharedSecret = crypto.createHash('sha256')
                           .update('put_your_Xendit_secret_API_key_here')
                           .digest('hex');
String sha256hex = Hashing.sha256()
  .hashString('put_your_Xendit_secret_API_key_here', StandardCharsets.UTF_8)
  .toString();

Java dengan Apache Commons Codecs

String sha256hex = DigestUtils.sha256Hex('put_your_Xendit_secret_API_key_here'); 

Semua hal di atas harus menghasilkan string hex yang akan menjadi shared secret Anda yang digunakan untuk menandatangani transaksi, yang akan terlihat seperti ini 57425b47283422a8b0dd567374dd179232daca1da7f9cd21732b429d69b00f89

2. Membuat representasi string dari body request pada transaksi Anda

Saat membuat signature, buat string "name: value" yang dipisahkan koma dari body request POST yang disertakan dalam bidang signed_field_names.

Urutan parameter dalam string sangat penting untuk proses pembuatan signature.

Untuk contoh permintaan safe acceptance seperti di bawah ini:

{
    "amount": 10000,
    "authorization": "Basic eG5kX3B1YmxpY19wcm9kdWN0aW9uX2NoQXBYaUVlVjVVbkdkZm9GUm1vdHk6",
    "reference_id": "test-transaction",
    "request_timestamp": "2020-01-01T00:00:00.000Z",
    "return_url": "https://merchant.com/checkout/completed",
    "signed_field_names": "amount,authorization,return_url,reference_id,signed_field_names,transaction_timestamp"
}
INFO

Anda perlu melakukan hash pada otorisasi Anda ke format base64

String yang akan dilakukan tanda tangan amount=10000,authorization=Basic eG5kX3B1YmxpY19wcm9kdWN0aW9uX2NoQXBYaUVlVjVVbkdkZm9GUm1vdHk6,redirect_url=https://merchant.com/checkout/completed,reference_id=test-transaction,signed_field_names=amount,authorization,redirect_url,reference_id,signed_field_names,request_timestamp=2020-01-01T00:00:00.000Z

3. Tanda tangani string dengan shared secret Anda

Pembuatan signature harus dibuat menggunakan HMAC dengan algoritme SHA256 dan secret API key yang dibuat di atas. String yang akan ditandatangani harus dalam urutan yang sama persis dengan nilai string signed_field_names.

hash_hmac('sha256', string_to_sign, shared_secret, false) 
const signature = crypto.createHmac('sha256', shared_secret)
                      .update(string_to_sign)
                      .digest('hex');
String signature = Hashing.hmacSha256(shared_secret)
                   .newHasher()    
                   .putString(string_to_sign, UTF_8)
                   .hash()
                   .toString(); 

Java dengan Apache Commons Codecs

HmacUtils hm256 = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, shared_secret);
String signature = hm256.hmacHex(string_to_sign);

4. Tambahkan Signature dan signed_fields ke formulir yang akan di-POST ke API Safe Acceptance

Pengujian

Contoh berikut mengasumsikan bahwa secret API key adalah xnd_production_vkeTQhp5itRjUrGresYdi0t0kkY.

Mengirimkan request pembuatan signature

Contohnya parameter berikut:

{
  "amount": 10000,
  "authorization": "Basic eG5kX3B1YmxpY19wcm9kdWN0aW9uX2NoQXBYaUVlVjVVbkdkZm9GUm1vdHk6",
  "reference_id": "test-transaction",
  "request_timestamp": "1610678291403",
  "redirect_url": "https://merchant.com/checkout/completed",
  "signed_field_names": "amount,authorization,redirect_url,reference_id,signed_field_names,transaction_timestamp"
}

Hasil pembuatan signature Anda akan terlihat seperti ini: 847988a920b31da8c1f124a1930569b6444cf70abb34e8c22620d069ccc367fe

Validasi signature respon

Anda akan memvalidasi parameter signature menggunakan shared secret yang hanya diketahui oleh Anda dan Xendit.

Contohnya parameter berikut:

{
    "created": "2019-07-15T15:54:52.141Z",
    "business_id": "5d08a4nfea3b620019cfa213c",
    "authorized_amount": 1200000,
    "reference_id": "TVLK-123456",
    "merchant_reference_code": "5d1ec8f4a3bcd10019a7e2de",
    "masked_card_number": "400000XXXXXX0002",
    "charge_type": "MULTI_USE_TOKEN",
    "card_brand": "VISA",
    "card_type": "CREDIT",
    "status": "CAPTURED",
    "bank_reconciliation_id": "5622988916826241203012",
    "eci": "05",
    "capture_amount": "1200000",
    "currency": "IDR",
    "id": "5d1eca0ca3bcd10019a7e2ee",
    "authorized_amount": "1200000",
    "merchant_id": "00080091009103589348501",
    "mid_label": "xendit_ctv_agg",
    "descriptor": "MERCHANT*EXPERIENCE",
    "signed_field_names": "created,business_id,authorized_amount,reference_id,merchant_reference_code,masked_card_number,charge_type,card_brand,card_type,status,bank_reconciliation_id,eci,capture_amount,currency,id,authorized_amount,merchant_id,mid_label,descriptor",
    "signature": "df212f41629f11d50128f2742963e103a52db30f4da9948b38318edfbf0ab470"
}

Hasil validasi signature Anda harus memeriksa apakah isi respon cocok dengan signature ini: df212f41629f11d50128f2742963e103a52db30f4da9948b38318edfbf0ab470

Perhatikan bahwa Anda juga harus memeriksa apakah stempel waktu created dari respon berada dalam kisaran yang wajar dari stempel waktu tempat sistem Anda menerima respon.

Jika waktu ketika sistem Anda menerimanya jauh lebih lambat dari stempel waktu transaksi respon, ini mungkin berarti bahwa pihak ketiga mencegat respon Xendit dan mengirimi Anda respon mereka sendiri, yang merupakan risiko keamanan.

Xendit merekomendasikan rentang <5 menit perbedaan antara stempel waktu respon dan waktu aktual di mana sistem Anda menerimanya.

Last Updated on 2023-05-20