Tạo chữ ký cho dữ liệu trước khi gọi API
Tất cả yêu cầu gửi đến Bizzi Pay OpenAPI đều yêu cầu các giá trị x-request-id, x-request-time, x-request-signature trong Headers để chứng thực yêu cầu và chắc chắn rằng yêu cầu được gửi đến từ Client cũng như kiểm tra tính chính xác của dữ liệu
Cách tạo chữ ký cho payload
- Sử dụng thuật toán HMAC_SHA256 (mặc định) hoặc thuật toán mà Client đã cấu hình trên Bizzi Pay
- Payload phải được mã hóa trước khi gửi sang Bizzi Pay
ghi chú
Các thuật toán mã hóa và cặp khóa mã hóa phải đúng với thông tin đã đăng ký với Bizzi Pay, nếu không yêu cầu của bạn sẽ không thể thực hiện
Code mẫu để tạo chữ ký cho payload
- JavaScript
- JAVA
import { createHmac, randomUUID } from 'crypto';
const secret = '';
const payload = {
foo: 'bar',
baz: {
qux: 'quux',
},
};
const algo = 'sha256';
const genSig = () => {
const reqId = randomUUID();
const reqTime = new Date().getTime();
const stringify = stringifyInOrder(payload);
const rawSig = [reqId, reqTime, stringify].join('|');
const reqSig = sign(secret, rawSig, algo);
return { reqId, reqTime, reqSig };
};
function stringifyInOrder(payload) {
return Object.keys(payload)
.sort()
.map((key) => {
const val = payload[key];
if (typeof val === 'object') {
return `${key}${stringifyInOrder(val)}`;
}
return `${key}${val}`;
})
.join('|');
}
const sign = (rawSecret, rawSig, algo) => {
const secret = Buffer.from(rawSecret, 'hex');
const signature = createHmac(algo, secret).update(rawSig).digest('base64');
return signature;
};
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
import java.util.TreeMap;
public class SignatureGenerator {
private static final String SECRET = "0804d9e4be435940e1b63cb024d149a7"; // Replace with your actual secret
private static final String ALGO = "HmacSHA256";
private static class Payload {
public String foo = "bar";
public Baz baz = new Baz();
}
private static class Baz {
public String qux = "quux";
}
public static void main(String[] args) {
SignatureData signatureData = null;
try {
signatureData = genSig();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
throw new RuntimeException(e);
}
System.out.println(signatureData);
}
public static SignatureData genSig() throws NoSuchAlgorithmException, InvalidKeyException {
String reqId = UUID.randomUUID().toString();
long reqTime = new Date().getTime();
Payload payload = new Payload();
String stringifiedPayload = stringifyInOrder(payload);
String rawSig = String.join("|", reqId, String.valueOf(reqTime), stringifiedPayload);
String reqSig = sign(SECRET, rawSig, ALGO);
return new SignatureData(reqId, reqTime, reqSig);
}
private static String stringifyInOrder(Object payload) {
// Using Gson for convenient JSON serialization
com.google.gson.Gson gson = new com.google.gson.Gson();
String json = gson.toJson(payload);
TreeMap<String, Object> map = gson.fromJson(json, TreeMap.class);
StringBuilder sb = new StringBuilder();
for (String key : map.keySet()) {
Object val = map.get(key);
if (val instanceof String) {
sb.append(key).append((String) val);
} else {
sb.append(key).append(stringifyInOrder(val));
}
sb.append("|");
}
// Remove the trailing '|'
return sb.substring(0, sb.length() - 1);
}
private static String sign(String rawSecret, String rawSig, String algo)
throws NoSuchAlgorithmException, InvalidKeyException {
SecretKeySpec secretKeySpec = new SecretKeySpec(rawSecret.getBytes(StandardCharsets.UTF_8), algo);
Mac mac = Mac.getInstance(algo);
mac.init(secretKeySpec);
byte[] signature = mac.doFinal(rawSig.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(signature);
}
private static class SignatureData {
public String reqId;
public long reqTime;
public String reqSig;
public SignatureData(String reqId, long reqTime, String reqSig) {
this.reqId = reqId;
this.reqTime = reqTime;
this.reqSig = reqSig;
}
@Override
public String toString() {
return "SignatureData{" +
"reqId='" + reqId + '\'' +
", reqTime=" + reqTime +
", reqSig='" + reqSig + '\'' +
'}';
}
}
}