# 虚拟账号接口

# 支持虚拟账号

支付方式 是否用户信息
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通知后回查下订单状态,尤其是虚拟账号订单。