# API Virtual account

# Support Method

Method Require User Info
SPEI Required

Luxpag provide virtual SPEI account: Merchants can apply for virtual SPEI account from Luxpag. Luxpag response with information of a virtual SPEI acount. Merchants forward this virtual SPEI account to one user. The user pay to this virtual account. The channel received the fund and callback to Luxpag. Luxpag generate an order and callback to the merchant to inform the SUCCESS payment.

# Request Base URL

  Test Environment : https://gateway-sandbox.luxpag.com
  Prod Environment : https://gateway.luxpag.com

# EndPoints

  Create virtual account: /virtual-account/spei/create
  Cancel virtual account: /virtual-account/spei/cancel
  Query virtual account: /virtual-account/spei/query
  Number of available accounts: /virtual-account/spei/quantity

# Request Header

Parameter Required Description
Content-Type recommend application/json
Authorization yes Basic Base64(app_id:secret_key)

# Request Body (JSON format)

# Create virtual account

Parameter Type Required Max Length(or Default Value) Description
app_id string yes 32 created app's id at dashboard
timestamp string yes 19 yyyy-MM-dd HH:mm:ss
notify_url string yes 255 IPN URL to merchant
customer.buyer_id string yes 128 merchant user's id
customer.email string yes user's email('+' is not supported)
customer.name string no user's name
customer.phone string no user's mobile phone number
customer.identify.number string yes user's ID number
customer.identify.type string yes user's ID type

# Query virtual account

Parameter Type Required Max Length(or Default Value) Description
app_id string yes 32 created app's id at dashboard
timestamp string yes 19 yyyy-MM-dd HH:mm:ss
account_id string yes Virtual Account ID

# Cancel virtual account

Parameter Type Required Max Length(or Default Value) Description
app_id string yes 32 created app's id at dashboard
timestamp string yes 19 yyyy-MM-dd HH:mm:ss
account_id string yes Virtual Account ID

# Number of available accounts

Parameter Type Required Max Length(or Default Value) Description
app_id string yes 32 created app's id at dashboard
timestamp string yes 19 yyyy-MM-dd HH:mm:ss

# Request Sample

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",
    "timestamp": "{{datetime}}"
}'

# Http Response (JSON format)

Parameter Type Description
code string return code
msg string return msg
sub_code string return sub code(only error)
sub_msg string return sub msg(only error)
account_id string Virtual Account ID
account_number string Virtual Account(SPEI Clabe)
provider string provider
status string status;ACTIVE、CANCELED
notify_url string IPN URL to merchant
beneficiary_name string Service provider
available_quantity Integer Number of available accounts

# Return Code (Succes)

{
    "code": "10000",
    "msg": "Success",
    "account_id": "{account_id}",
    "account_number": "{account_number}",
    "provider": "{provider}",
    "status": "{status}",
    "notify_url": "{notify_url}",
}

# Return Code (Fail)

{
    "code": "40002",
    "msg": "Business Failed",
    "sub_code": "invalid-signature",
    "sub_msg": "invalid signature"
}

# IPN Notifications

IPN (Instant Payment Notification) is a notification sent from one server to another through an HTTP POST request informing your transactions.

In order to receive notifications about the events in your platform, you have to previously configure the notification when you do the POST of the payment, indicating the URL in the field notify_url.

# Events

Whenever an event occurs, we will send you a notification in json format using HTTP POST to the URL that you specified.

We will notify the following events:

Action Description
SUCCESS trade succeeded

Luxpag will send notifications with the following schedule of retries and confirmation awaiting times. You must return an HTTP STATUS 200 (OK) with reponse data "success" or "{"result":"success"}" before the corresponding time expires. If not, it will be assumed that you did not receive it correctly and you will be notified again.

Event Time after the first dispatch
Dispatch -
1st retry 10 minutes
2nd retry 30 minutes
3rd retry 60 minutes
4th retry 120 minutes
5th retry 360 minutes
6th retry 840 minutes

# Notification Body (JSON format)

Parameter Type Required Max Length(or Default Value) Description
app_id string yes 32 created app's id at dashboard
trade_no string yes 64 Luxpag trade NO.
out_trade_no string yes 64 ID given by the merchant in their system
out_request_no string no 64 refund number
method string yes 32 Payment methods
trade_status string yes 16 trade's status
currency string yes 3 MXN for mexico
amount string yes request payment amount
user.name string no user's name
user.email string no user's email
user.phone string no user's mobile phone number
user.identify.number string no user's ID number
user.identify.type string no user's ID type
card.card_no string no card number
transfer_account.account_id string yes virtual account's ID
transfer_account.account_number string yes virtual account(SPEI Clabe)
transfer_account.provider string yes virtual account's provider
transfer_account.buyer_id string yes virtual account's merchant user's id
transfer_account.transfer_timestamp string yes virtual account's timestamp
transfer_account.beneficiary_name string yes virtual account's Service provider

The notification sent has the following format:


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:The data sent to the merchant by post, and the payload is JSON string.

# What should I do when I receive a notification?

When you receive a notification on your platform, Luxpag waits for a response to validate that you received it correctly. For this, you must return an HTTP STATUS 200 (OK) with reponse data "success" or "{"result":"success"}".

It is recommended that you respond to the notification before executing business logic or prior to accessing external resources so as not to exceed the estimated response times.

This communication is exclusively between the servers of Luxpag and your server, so there will not be a physical user seeing any type of result.

# Check Signature(Optional)

Luxpag includes a signature in the Luxpag-Signature header of each event. You can verify the signature to enhance security.

We will use the merchant's private key to encrypt the callback payload with 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();
 }
}

# Security Policy

Suggestion: Perform whitelist verification on the Luxpag callback service IP;

Suggestion: After receiving the successful IPN notification of the order, check back on Luxpag, especially for virtual account orders.