对接路线图 - BNPL
概述
本文档指导客户完成与 QI Tech 平台的先买后付(BNPL)集成。文档概述了必要步骤,并解答常见问题。
1. 文件查询
可通过以下请求进行文件查询:
请求体上传
ENDPOINT
/document/[document_key]/urlMETHOD
GET路径参数
| 字段 | 描 述 |
|---|---|
document_key | 文件唯一标识符 |
注意
文件 URL 将在生成后 10 分钟内过期。
Response Body
{
"document_key": "8a1e62f3-7add-4240-a51d-e0f1a2f421fa",
"document_url": "expirable_url",
"signed_document_url": "expirable_url",
"expiration_datetime": "2024-05-01T01:00:00.000Z"
}
2. 文件上传
要获取债务发行文件的 document_key,您需要通过以下请求上传文件:
请求体上传
ENDPOINT
/uploadMETHOD
POSTResponse Body
{
"document_key": "cfbc8469-89ea-4a80-9f64-ba7b1566c68b",
"document_md5": "cd451103fa512frc98ce684d3896698c"
}
注意
请保存 document_key,查询文件时需要用到此密钥。
API 调用示例
以下为从 URL 上传图片的示例。
- Python
- Node.js
import jwt
import hashlib
import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder
import json
from datetime import datetime
BASE_URL = "https://api-auth.sandbox.qitech.app"
API_KEY = "4c268c0a-53ff-429b-92b6-47ef98a6d89a" # This key is an example; please use your own key.
CLIENT_PRIVATE_KEY = ''''
-----BEGIN EC PRIVATE KEY-----
MIHbAgEBBEHh1hIeOPE5XNNhn6bxRAmVswsPZ0wZCmzVvP8Tl/LZK9ofVmRVGzll
srU1uezJEyHKYdOHrE2p52xUj+pHzjJvb6AHBgUrgQQAI6GBiQOBhgAEAAofUz1J
hBSOyGHLsnV9Sz0DSWmhl7U+ljqbfa8PKVFWSV3w16I1v2zME5/UzUhHn1gWsjnv
7/ekcLLAQbvqMPNXAfjIhFXLAPzqbB9iCuVua1v0Vgy52rBemOWrJka/Ws2bnKR8
h1N1OxOYeYr6C2jqMygBLktKMAs+282CEiEb4bIv
-----END EC PRIVATE KEY-----
''' # This key is an example; please use your own key.
def get_document(url):
try:
response = requests.get(url)
return response.content
except Exception as error:
print("Error fetching document:", error)
raise
def upload_document(array_buffer):
endpointeger= "/upload"
method = "POST"
timestamp = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
md5_hash = hashlib.md5(array_buffer).hexdigest()
jwt_header = {
"typ": "JWT",
"alg": "ES512",
}
jwt_body = {
"payload_md5": md5_hash,
"timestamp": timestamp,
"method": method,
"uri": endpoint,
}
encoded_header_token = jwt.encode(jwt_body, CLIENT_PRIVATE_KEY, algorithm="ES512", headers=jwt_header)
signed_header = {
"Authorization": encoded_header_token,
"API-CLIENT-KEY": API_KEY,
"Content-Type": "multipart/form-data",
}
url = f"{BASE_URL}{endpoint}"
multipart_data = MultipartEncoder(
fields={'file': ('image.jpeg', array_buffer, 'image/jpeg')}
)
signed_header['Content-Type'] = multipart_data.content_type
try:
response = requests.post(url, headers=signed_header, data=multipart_data)
response_data = response.json()
document_key = response_data.get('document_key')
print(f'Response data is: {response_data} and document_key is: {document_key}')
return document_key
except Exception as error:
print('Error:', error)
raise
def main():
file_url = "{FILE_URL}"
document_buffer = get_document(file_url)
document_key = upload_document(document_buffer)
print("document_key is", document_key)
if __name__ == "__main__":
main()
const jwt = require('jsonwebtoken')
const crypto = require('crypto')
const axios = require('axios')
const FormData = require('form-data')
const fs = require('fs')
const fetch = require('node-fetch')
async function getDocument(url) {
try {
const response = await axios.get(url, { responseType: 'arraybuffer' })
return response.data
} catch (error) {
console.error('Error fetching document:', error)
throw error
}
}
async function uploadDocument(arrayBuffer) {
const endpointeger= '/upload'
const method = 'POST'
const timestamp = new Date().toISOString()
const md5_hash = crypto.createHash('md5').update(arrayBuffer).digest('hex')
const client_private_key = `-----BEGIN EC PRIVATE KEY-----
MIHbAgEBBEHh1hIeOPE5XNNhn6bxRAmVswsPZ0wZCmzVvP8Tl/LZK9ofVmRVGzll
srU1uezJEyHKYdOHrE2p52xUj+pHzjJvb6AHBgUrgQQAI6GBiQOBhgAEAAofUz1J
hBSOyGHLsnV9Sz0DSWmhl7U+ljqbfa8PKVFWSV3w16I1v2zME5/UzUhHn1gWsjnv
7/ekcLLAQbvqMPNXAfjIhFXLAPzqbB9iCuVua1v0Vgy52rBemOWrJka/Ws2bnKR8
h1N1OxOYeYr6C2jqMygBLktKMAs+282CEiEb4bIv
-----END EC PRIVATE KEY-----`; // This key is an example; please use your own key.
const api_key = '4c268c0a-53ff-429b-92b6-47ef98a6d89a' // This key is an example; please use your own key.
try {
const jwt_header = {
typ: 'JWT',
alg: 'ES512',
}
const jwt_body = {
payload_md5: md5_hash,
timestamp: timestamp,
method: method,
uri: endpoint,
}
const encoded_header_token = jwt.sign(jwt_body, client_private_key, {
algorithm: 'ES512',
header: jwt_header,
})
const signed_header = {
AUTHORIZATION: encoded_header_token,
'API-CLIENT-KEY': api_key,
'Content-Type': 'multipart/form-data',
}
const url = `${base_url}${endpoint}`
const formData = new FormData()
formData.append('file', Buffer.from(arrayBuffer), {
filename: 'image.jpeg',
})
fetch(url, {
method: 'POST',
headers: signed_header,
body: formData,
})
.then(data => {
console.log('Response data is: ' + data)
return data.document_key
})
.catch(error => {
console.log('Error: ' + error)
})
} catch (error) {
console.error('Error:', error)
}
}
async function main() {
const fileUrl = '<URL_LINK_TO_DOCUMENT_IMAGE>'
const documentBuffer = await getDocument(fileUrl)
const documentKey = await uploadDocument(documentBuffer)
console.log('Document key is: ' + documentKey)
}
main()
- 备注:上述示例使用 node-fetch 库进行调用,您也可以使用自己选择的库。重要的是,调用必须使用 POST 方法,
Content-Type请求头设置为multipart/form-data,请求体必须是包含键名为file、值为待发送文件二进制数据的 FormData 对象。
警告
'Axios' 库存在一个导致 FormData 发送为空的 bug,相关问题可在 GitHub 仓库 中查看。如果在您集成时该问题尚未解决,建议使用 'node-fetch' 库进行此调用。