# 虚拟账号接口
# 支持虚拟账号
支付方式 | 是否用户信息 |
---|---|
SPEI | 是 |
Luxpag 为商户提供虚拟账号功能:商户向Luxpag请求创建虚拟账号,Luxpag返回一个虚拟账号信息,商户将虚拟账号发给一用户,用户向虚拟账号中充值,Luxpag的渠道收到充值后回调Luxpag,Luxpag生成订单并IPN回调商户,通知商户订单支付成功。
# 请求接口ROOT地址
测试环境 : https://gateway-sandbox.luxpag.com
正式环境 : https://gateway.luxpag.com
# 接口
虚拟账号创建:/virtual-account/spei/create
虚拟账号取消:/virtual-account/spei/cancel
虚拟账号查询:/virtual-account/spei/query
可用虚拟账号数量:/virtual-account/spei/quantity
# Request Header
参数名 | 必须 | 描述 |
---|---|---|
Content-Type | 推荐 | application/json |
Authorization | yes | Basic Base64(app_id:secret_key) |
# 请求参数(JSON格式)
# 创建虚拟账号
参数名 | 类型 | 必须 | 最大长度/默认值 | 描述 |
---|---|---|---|---|
app_id | string | yes | 32 | 商户后台创建并获得 |
timestamp | string | yes | 19 | yyyy-MM-dd HH:mm:ss |
notify_url | string | yes | 255 | 回调地址,IPN通知 |
customer.buyer_id | string | yes | 128 | 商户的用户ID |
customer.email | string | yes | 用户邮箱(不支持‘+’号) | |
customer.name | string | no | 用户姓名 | |
customer.phone | string | no | 用户电话 | |
customer.identify.number | string | yes | 用户ID | |
customer.identify.type | string | yes | 用户ID类型 |
# 查询虚拟账号
参数名 | 类型 | 必须 | 最大长度/默认值 | 描述 |
---|---|---|---|---|
app_id | string | yes | 32 | 商户后台创建并获得 |
timestamp | string | yes | 19 | yyyy-MM-dd HH:mm:ss |
account_id | string | yes | 虚拟账号ID |
# 取消虚拟账号
参数名 | 类型 | 必须 | 最大长度/默认值 | 描述 |
---|---|---|---|---|
app_id | string | yes | 32 | 商户后台创建并获得 |
timestamp | string | yes | 19 | yyyy-MM-dd HH:mm:ss |
account_id | string | yes | 虚拟账号ID |
# 可用虚拟账号数量
参数名 | 类型 | 必须 | 最大长度/默认值 | 描述 |
---|---|---|---|---|
app_id | string | yes | 32 | 商户后台创建并获得 |
timestamp | string | yes | 19 | yyyy-MM-dd HH:mm:ss |
# 请求样例
curl --location --request POST 'https://gateway.luxpag.com/virtual-account/spei/create' \
--header 'Authorization: Basic Base64(appid:secret_key)' \
--header 'Content-Type: application/json' \
--data-raw '{
"app_id": "app_id",
"notify_url": "notify_url",
"timestamp": "{{datetime}}",
"customer": {
"email": "email",
"buyer_id": "buyer_id"
}
}'
curl --location --request POST 'https://gateway.luxpag.com/virtual-account/spei/query' \
--header 'Authorization: Basic Base64(appid:secret_key)' \
--header 'Content-Type: application/json' \
--data-raw '{
"app_id": "app_id",
"account_id": "account_id",
"timestamp": "{{datetime}}"
}'
curl --location --request POST 'https://gateway.luxpag.com/virtual-account/spei/cancel' \
--header 'Authorization: Basic Base64(appid:secret_key)' \
--header 'Content-Type: application/json' \
--data-raw '{
"app_id": "app_id",
"account_id": "account_id",
"timestamp": "{{datetime}}"
}'
curl --location --request POST 'https://gateway.luxpag.com/virtual-account/spei/quantity' \
--header 'Authorization: Basic Base64(appid:secret_key)' \
--header 'Content-Type: application/json' \
--data-raw '{
"app_id": "app_id",
"account_id": "account_id",
"timestamp": "{{datetime}}"
}'
# 响应(JSON格式)
参数名 | 类型 | 描述 |
---|---|---|
code | string | 返回码 |
msg | string | 返回消息 |
sub_code | string | 子码 |
sub_msg | string | 子消息 |
account_id | string | 虚拟账号ID |
account_number | string | 虚拟账号(SPEI Clabe) |
provider | string | 渠道 |
status | string | 状态;ACTIVE、CANCELED |
notify_url | string | 回调地址,IPN通知地址 |
beneficiary_name | string | 服务商 |
available_quantity | Integer | 虚拟账号剩余个数 |
# 返回样例(成功)
{
"code": "10000",
"msg": "Success",
"account_id": "{account_id}",
"account_number": "{account_number}",
"provider": "{provider}",
"status": "{status}",
"notify_url": "{notify_url}",
}
# 返回样例(失败)
{
"code": "40002",
"msg": "Business Failed",
"sub_code": "invalid-signature",
"sub_msg": "invalid signature"
}
# IPN通知
IPN(即时付款通知)是一种通过HTTP POST请求从一台服务器发送到另一台服务器的通知,用于通知您的交易。
为了接收有关您平台中事件的通知,您必须在进行付款POST时预先配置通知,并在字段notify_ur中指示URL。
# 事件
每当发生事件时,我们都会使用HTTP POST到您指定的URL的json格式发送通知给您。
我们将通知以下事件:
动作 | 描述 |
---|---|
SUCCESS | 支付成功(用户完成付款) |
您必须在相应时间到期之前返回带有响应数据"success"或"{"result":"success"}"的HTTP STATUS 200(OK)。
否则,将假定您没有正确收到它,并且将再次通知您;重试6次后本次交易不再通知,6次后如果需要可以在dashboard订单详细点callback按钮。
Luxpag发送通知,其中包含以下重试时间表和确认等待时间:
事件 | 距离第一次通知的时间 |
---|---|
立即 | - |
1st retry | 10 minutes |
2nd retry | 30 minutes |
3rd retry | 60 minutes |
4th retry | 120 minutes |
5th retry | 360 minutes |
6th retry | 840 minutes |
# 通知参数(JSON格式)
参数名 | 类型 | 必须 | 最大长度/默认值 | 描述 |
---|---|---|---|---|
app_id | string | yes | 32 | 商户后台创建并获得 |
trade_no | string | yes | 64 | Luxpag 订单号 |
out_trade_no | string | yes | 64 | 商户订单号 |
out_request_no | string | no | 64 | 退款唯一单号 |
method | string | yes | 32 | 支付方式 |
trade_status | string | yes | 16 | 订单状态 |
currency | string | yes | 3 | 币种:墨西哥(MXN) |
amount | string | yes | 订单金额 | |
user.name | string | no | 用户姓名 | |
user.email | string | no | 用户邮箱 | |
user.phone | string | no | 用户电话 | |
user.identify.number | string | no | 用户ID | |
user.identify.type | string | no | 用户ID类型 | |
card.card_no | string | no | 卡号 | |
transfer_account.account_id | string | yes | 虚拟账号ID | |
transfer_account.account_number | string | yes | 虚拟账号(SPEI Clabe) | |
transfer_account.provider | string | yes | 虚拟账号渠道 | |
transfer_account.buyer_id | string | yes | 虚拟账号商户的用户ID | |
transfer_account.transfer_timestamp | string | yes | 虚拟账号时间戳 | |
transfer_account.beneficiary_name | string | yes | 虚拟账号服务商 |
发送的通知使用以下格式:
Method: POST
Header:Content-Type: application/json
Header:Luxpag-Signature: hmacSHA256(payload, secret_key)
Body:
{
"amount":"",
"out_trade_no":"",
"method":"",
"trade_status":"",
"trade_no":"",
"currency":"",
"out_request_no":"",
"app_id":"",
"user":{
"identify":{
"number":"",
"type":""
},
"phone":"",
"email":""
},
"card":{
"card_no":"F6L4"
},
"transfer_account":{
"account_id":"",
"account_number":"",
"beneficiary_name":"",
"buyer_id":"",
"provider":"",
"transfer_timestamp":1669192513
}
}
payload:IPN通知POST给商户的数据,payload为JSON字符串。
# 收到通知后该怎么办?
当您在平台上收到通知时,Luxpag等待响应以验证您是否正确接收了该通知。 为此,您必须返回HTTP状态200(OK),其响应数据为“ success”或“ {” result“:” success“}”。
建议您在执行业务逻辑之前或在访问外部资源之前对通知做出响应,以免超出估计的响应时间。
该通信专门在Luxpag的服务器与您的服务器之间进行,因此不会有物理用户看到任何类型的结果。
# 检查回调签名(可选)
Luxpag在每个事件的Luxpag-Signature标头中都包含一个签名,您可对签名进行验证从而增强安全性。
我们会使用商户私钥(盐值)对回调payload进行hmacSHA256加密。
Header:Luxpag-Signature: SignHelper.hmacSHA256(payload, secret_key)
// Step 1
String payload = JSON.toJSONString(notify);
String sign = SignHelper.macSha256(payload, secret_key);
// Step 2
Header:Luxpag-Signature: 5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
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.*;
/**
*
*/
public final class SignHelper{
/**
* HMAC with SHA-256
*
* @param content
* @param salt
* @return
*/
public static String macSha256(String content, String salt) {
StringBuilder result = new StringBuilder();
try {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(salt.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] hash = mac.doFinal(content.getBytes(StandardCharsets.UTF_8));
for (byte b : hash) {
result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
}
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
}
return result.toString();
}
}
# 安全策略
建议:对Luxpag回调服务IP进行白名单验证;
建议:收到订单成功IPN通知后回查下订单状态,尤其是虚拟账号订单。