Bảo mật
Tổng quan
Mọi request gi ữa Baokim và CashPlus được ký số bằng RSA với hàm băm SHA1:
| Chiều | Bên ký | Khóa dùng để ký | Bên verify | Khóa dùng để verify |
|---|---|---|---|---|
| CashPlus → Baokim (gọi API) | CashPlus | Khóa riêng của CashPlus | Baokim | Khóa công khai CashPlus đã đăng ký với Baokim |
| Baokim → CashPlus (webhook) | Baokim | Khóa riêng của Baokim | CashPlus | Khóa công khai Baokim cung cấp |
- Chữ ký nằm ở header
Signature, mã hóa Base64. Không đưa chữ ký vào body. - Dữ liệu được ký là raw body của request, đúng từng byte gửi đi. Không format lại, không thêm/bớt khoảng trắng, không đổi thứ tự trường sau khi ký.
- Chỉ hỗ trợ SHA1. Chữ ký tạo bằng thuật toán khác sẽ bị từ chối với mã 120.
- Khóa của môi trường test và production khác nhau. Liên hệ Baokim để trao đổi khóa công khai cho từng môi trường.
CashPlus gọi API Baokim
Áp dụng cho tất cả API trong tài liệu này:
POST /collection/{env}/users
POST /collection/{env}/v1
POST /transaction/v2/share-amount
POST /transaction/v2/spend
POST /transaction/v2/spend-result
POST /ats/transaction
POST /ats/transaction-payment-share
POST /ats/merchant
POST /ats/user
Bước 1. Tạo body JSON — đây chính là chuỗi sẽ gửi đi:
{"RequestId":"ABC123","RequestTime":"2025-01-15 10:30:00","PartnerCode":"CASHPLUS","Data":[]}
Bước 2. Ký chuỗi body bằng khóa riêng của CashPlus, thuật toán RSA-SHA1, rồi mã hóa Base64:
$body = json_encode($data);
openssl_sign($body, $signature, $privateKey, OPENSSL_ALGO_SHA1);
$signatureBase64 = base64_encode($signature);
Bước 3. Gửi đúng chuỗi $body đã ký, kèm header Signature:
curl -X POST '{BASE_URL}/collection/live/v1' \
-H 'Content-Type: application/json' \
-H 'Signature: <signatureBase64>' \
-d '{"RequestId":"ABC123","RequestTime":"2025-01-15 10:30:00","PartnerCode":"CASHPLUS","Data":[]}'
Sai chữ ký hoặc thiếu header Signature → Baokim trả mã 120.
CashPlus nhận webhook từ Baokim
Áp dụng cho Webhook thu hộ và Webhook kết quả chi.
Baokim gửi:
- Header
Content-Type: application/json - Header
Signature: <Base64 của chữ ký RSA-SHA1 trên raw body>
CashPlus verify trên raw body nhận được (không parse rồi encode lại):
$rawBody = file_get_contents('php://input');
$signature = base64_decode($_SERVER['HTTP_SIGNATURE'] ?? '');
$isValid = openssl_verify($rawBody, $signature, $baokimPublicKey, OPENSSL_ALGO_SHA1);
if ($isValid !== 1) {
// Chữ ký không hợp lệ: không xử lý, trả ResponseCode khác 200
}
$data = json_decode($rawBody, true);
Format response CashPlus cần trả và chính sách gửi lại: xem trang của từng webhook.
Ví dụ Node.js
const crypto = require('crypto');
// CashPlus ký request gửi Baokim
function signBody(body, privateKeyPem) {
const signer = crypto.createSign('RSA-SHA1');
signer.update(body, 'utf8');
return signer.sign(privateKeyPem, 'base64');
}
// CashPlus verify webhook từ Baokim
function verifyWebhook(rawBody, signatureBase64, baokimPublicKeyPem) {
const verifier = crypto.createVerify('RSA-SHA1');
verifier.update(rawBody, 'utf8');
return verifier.verify(baokimPublicKeyPem, signatureBase64, 'base64');
}
const body = JSON.stringify({
RequestId: 'ABC123',
RequestTime: '2025-01-15 10:30:00',
PartnerCode: 'CASHPLUS',
Data: []
});
fetch('{BASE_URL}/collection/live/v1', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Signature': signBody(body, privateKeyPem) },
body // gửi đúng chuỗi đã ký
});