本指南将通过四个步骤引导您完成首次付款。
前提条件
- 您的客户端密钥 (
X-PARTNER-ID) — 在入驻时提供 - 您的 RSA 私钥 — 用于签署每个请求(参见签名生成)
- 您的基础 URL — 在入驻时提供
第一步:生成 RSA 密钥对
生成 2048 位 RSA 密钥对。在入驻时提供公钥;私钥请妥善保管。
# 生成私钥
openssl genrsa -out private_key.pem 2048
# 提取公钥
openssl rsa -in private_key.pem -pubout -out public_key.pem
第二步:构建请求头
每个 API 请求都需要三个请求头:
| 请求头 | 值 |
|---|---|
| X-PARTNER-ID | 您的客户端密钥 |
| X-TIMESTAMP | 当前时间,ISO 8601 格式(例如 2025-01-15T14:30:00+07:00) |
| X-SIGNATURE | RSA-SHA256 签名(见下文) |
签名由以下内容生成:{METHOD}:{URL}:{SHA256_OF_BODY}:{TIMESTAMP}
完整算法和代码示例请参阅签名生成。
第三步:创建 QRIS 支付
向 /api/create/qris 发送 POST 请求:
# 变量 — 请替换为您的实际值
CLIENT_KEY="your-client-key"
TIMESTAMP="$(date -u +%Y-%m-%dT%H:%M:%SZ)" # 当前时间,带时区偏移的 ISO 8601 格式
SIGNATURE="your-generated-signature"
BASE_URL="https://your-assigned-base-url.com"
curl -X POST "${BASE_URL}/api/create/qris" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-PARTNER-ID: ${CLIENT_KEY}" \
-H "X-TIMESTAMP: ${TIMESTAMP}" \
-H "X-SIGNATURE: ${SIGNATURE}" \
-d '{
"merchant_transaction_id": "ORDER-001",
"amount": "50000",
"currency": "IDR",
"customer_name": "John Doe",
"product_name": "Test Order"
}'
const crypto = require('crypto');
const fs = require('fs');
const https = require('https');
const CLIENT_KEY = 'your-client-key';
const BASE_URL = 'https://your-assigned-base-url.com';
const ENDPOINT = '/api/create/qris';
const timestamp = new Date().toISOString();
const body = JSON.stringify({
merchant_transaction_id: 'ORDER-001',
amount: '50000',
currency: 'IDR',
customer_name: 'John Doe',
product_name: 'Test Order'
});
// 生成签名
const payloadHash = crypto.createHash('sha256').update(body).digest('hex').toLowerCase();
const stringToSign = `POST:${ENDPOINT}:${payloadHash}:${timestamp}`;
const privateKey = fs.readFileSync('./private_key.pem');
const sign = crypto.createSign('RSA-SHA256');
sign.update(stringToSign);
const signature = sign.sign(privateKey, 'base64');
// 发送请求
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-PARTNER-ID': CLIENT_KEY,
'X-TIMESTAMP': timestamp,
'X-SIGNATURE': signature
}
};
const req = https.request(`${BASE_URL}${ENDPOINT}`, options, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => console.log(JSON.parse(data)));
});
req.write(body);
req.end();
<?php
$clientKey = 'your-client-key';
$baseUrl = 'https://your-assigned-base-url.com';
$endpoint = '/api/create/qris';
$timestamp = date('c'); // ISO 8601
$body = json_encode([
'merchant_transaction_id' => 'ORDER-001',
'amount' => '50000',
'currency' => 'IDR',
'customer_name' => 'John Doe',
'product_name' => 'Test Order',
]);
// 生成签名
$payloadHash = strtolower(bin2hex(hash('sha256', $body, true)));
$stringToSign = "POST:{$endpoint}:{$payloadHash}:{$timestamp}";
$privateKey = openssl_pkey_get_private('file://./private_key.pem');
openssl_sign($stringToSign, $signature, $privateKey, OPENSSL_ALGO_SHA256);
$signatureB64 = base64_encode($signature);
// 发送请求
$ch = curl_init("{$baseUrl}{$endpoint}");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Accept: application/json',
"X-PARTNER-ID: {$clientKey}",
"X-TIMESTAMP: {$timestamp}",
"X-SIGNATURE: {$signatureB64}",
],
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
成功响应:
{
"status": true,
"message": "success",
"data": {
"transaction_id": "8366a675-f1cc-418c-b3a8-358410671ca0",
"qr_url": "{host}/images/payment/qris/BP1f44d20caefb8b0ef181797bffed088c.png",
"qr_content": "00020101021226660014ID.EXAMPLE.WWW01189360000000000000000215ID12345678901230303UMI51440014ID.CO.QRIS.WWW0215ID12345678901230303UMI5204599953033605405100005802ID5913EXAMPLE STORE6007JAKARTA61051234562230703A010812qris_invoice6304FF2D",
"redirect_url": "{host}/checkout/8366a675-f1cc-418c-b3a8-358410671ca0/qris",
"expired_at": "2025-01-15T15:00:00.000000Z"
}
}
通过 data.qr_url 显示二维码,或将客户重定向至 data.redirect_url。
第四步:接收 Webhook
当客户完成支付后,网关会向您注册的端点发送 payment.v2.completed Webhook:
{
"event": "payment.v2.completed",
"timestamp": "2025-01-15T14:35:00+07:00",
"data": {
"transaction_id": "8366a675-f1cc-418c-b3a8-358410671ca0",
"merchant_transaction_id": "ORDER-001",
"amount": "50000.00",
"currency": "IDR",
"channel": "QRIS",
"status": "success",
"payment_at": "2025-01-15T14:34:58+07:00",
"customer_info": {
"customer_name": "John Doe",
"product_name": "Test Order"
}
}
}
您的端点必须:
- 验证签名 — 参见签名验证
- 在 5 秒内返回 HTTP 200
- 实现幂等性 — 使用
data.transaction_id检测重复投递
下一步
| 目标 | 页面 |
|---|---|
| 通过托管结账页面接受付款 | 结账发票 |
| 通过虚拟账户、银行转账或电子钱包接受付款 | 生成直接支付 |
| 发送出款 / 转账 | 出款 |
| 处理所有 Webhook 事件 | Webhook V2 |
| 验证传入的 Webhook 签名 | 签名验证 |
| 了解完整的集成流程 | 集成流程 |