The Document of philippines
About 2282 wordsAbout 8 min
1:XwinPay developer documentation
1.1:Http Request
- Http Method : POST
- Content type : application/json
- Sandbox Environment Payment Gateway End Points:https://uat-trade.xwinpay.tech
- Production Environment Payment Gateway End Points:https://trade.xwinpay.tech
- Request URL:Payment Gateway + Resource path
- Note: If there is business logic associated processing, please use the code field. Name, message and other fields may change at any time.
1.2:After Create The Account (Http Request Need)
- merchantNo(also the http header : X-MERCHANT-CODE):123456
- merchantName: XwinPay8848
- Merchant private key (For Request XwinPay ) :MIICdQIBADANBgkqhkiG9w0B********qqLS
- Merchant public key (XwinPay Verify The Merchant Request):MIGIb3DQEBAQUAGNAD*****QAB
- Platform public key (Merchant Verify The XwinPay WebHook):MIGfMA0GCSqG3DEBAQ*****QAB
- apikey(also the http header : X-API-KEY):74918b3925ccd0******27478087
1.3:Http Header
Params Key | required | Type | description |
---|---|---|---|
X-MERCHANT-CODE | yes | Http Header (String) | merchantNo |
X-API-KEY | yes | Http Header (String) | apikey |
1.4:Common Request Http Body
{
"param": {
"accountNumber": "",
"amount": 50000,
"app": "NICE",
****,
****,
****,
},
"sign": "SQiqFRTmBn0***4Yz8iUCdeyWi/JObp9mXzXfNCQ+zbOCQ="
}
Params Key | required | Type | description |
---|---|---|---|
param | yes | Object | Business Params |
sign | yes | String | After encryp String |
1.5:Common Reponse Http Body
{
"code": 200,
"message": "Success",
"data": {
"merchantNo": "58256833",
"merchantOrderNo": "5825683320230508569",
****,
****,
****
}
}
Params Key | required | Type | description |
---|---|---|---|
code | yes | Integer | Interface Status(200: Success) |
message | yes | String | message |
data | yes | Object | Business data |
1.6:Error Code
code | description |
---|---|
200 | Request successful"), |
415 | parameter passing exception |
500 | Please contact technical support for business exceptions. |
4001 | Merchant code cannot be empty |
4002 | Merchant does not exist |
4003 | Merchant APIKEY is incorrect |
4004 | Merchant APIKEY cannot be empty |
4005 | The sign signature cannot be empty. |
4006 | Sign Failure |
4007 | The current merchant does not have this type of currency account |
4008 | The current merchant balance is insufficient and the payment on behalf of the merchant has failed! |
40081 | There is an outstanding escrow order on the account! |
40082 | Payment on behalf of an order creation exception! |
40083 | Payment on behalf of an order rate calculation anomaly! |
4009 | Duplicate Merchant Order Number |
4010 | Merchant order number not passed |
4011 | Missing parameter error |
4012 | Merchant order does not exist |
4013 | Current order parameter validation error |
4014 | channel request param error |
4015 | No permission to pay for products, please contact the administrator |
4016 | Merchant fee calculation method is wrong |
4017 | amount in excess of limit |
4018 | bank request param error |
4019 | ewallet request param error |
4020 | Abnormal rate setting |
4021 | The bank has suspended use, please contact the administrator. |
4022 | param error" |
4023 | reached daily transaction count limit |
4024 | transaction must between %d and %d" |
4025 | The daily transaction volume has reached %d" |
5001 | The payment channel is temporarily unavailable, please try again later. |
5002 | Order data does not exist |
5003 | Unknown handling fee calculation method |
5004 | Not getting the fee calculation method |
5006 | Payment request is abnormal, please check the parameters |
5007 | Payment product is not configured |
5008 | Payment exception |
50071 | The merchant has not configured payment products |
40084 | Abnormal data in access channel for payment orders |
40085 | Pipeline write exception |
1.7:Order Status
Params Key |
---|
PENDING |
COMPLETED |
FAILED |
CANCEL |
NO_PAY |
1.8:The Method For Get Sign String
SHA256WithRSAUtils signature verification method. After sorting the keys of all non-empty parameters according to ASCII, take the parameter values (excluding Key) and splice them, and then use the SHA256WithRSAUtils algorithm to calculate the string to calculate the signature string.
for example
String sign = SHA256WithRSAUtils.encryptByPrivateKey(SignUtils.getSign(Params), privateKey);
1.9:demo
Params Key | Type |
---|---|
merchantCode | S820211021094748000001 |
orderNum | T1642592278863 |
payMoney | 150.6 |
notifyUrl | your notify ur |
dateTime | 2022/1/1 10:55 |
expiryPeriod | 1440 |
1.10:The Describe For Get Signed string
示例 sorting the keys of all non-empty parameters according to ASCII
StrA = 2022-01-01 10:55:[email protected] notify urlT1642593166888150.60082122965511Test Pay
1.11:Amount Limit
TransType | limit (Unit:PHP) |
---|---|
Pay In | 100-50000 |
Pay Out | 1-50000 |
2:JAVA Demo
2.1:SignUtils (Signed string method)
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class SignUtils {
public static String getSign(Map<String, Object> map) {
Set<String> keys = map.keySet();
List<String> list = new ArrayList<>(keys);
Collections.sort(list);
// 构造签名键值对的格式
StringBuilder sb = new StringBuilder();
// 构造签名键值对的格式
for (String key : list) {
Object val = map.get(key);
if (!("".equals(val) || val == null || "sign".equals(key))) {
sb.append(val);
}
}
return sb.toString();
}
}
2.2:SHA256WithRSA
package com.example.eventdemo;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* SHA256WithRSA
* Base64 Use apache tools, maven https://mvnrepository.com/artifact/commons-codec/commons-codec
*/
public class SHA256WithRSAUtils {
/**
* Key algorithm
*/
public static final String ALGORITHM_RSA = "RSA";
private SHA256WithRSAUtils() {
}
/**
* get private key
*
* @param privateKey Key string (base64 encoded)
*/
public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
//通过PKCS#8编码的Key指令获得私钥对象
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
return (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
}
/**
* get public key
*
* @param publicKey Key string (base64 encoded)
*/
public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
//通过X509编码的Key指令获得公钥对象
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
return (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
}
/**
* RSA algorithm public key decrypts data
*
* @param data Base64-encoded ciphertext string to be decrypted
* @param key RSA public key string
* @return Plain text string decrypted by RSA public key
*/
public static String decryptByPublicKey(String data, String key) {
try {
RSAPublicKey publicKey = getPublicKey(key);
Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException("decrypt [" + data + "] error", e);
}
}
/**
* RSA algorithm private key encrypted data
*
* @param data Plain text string to be encrypted
* @param key RSA private key string
* @return Base64-encoded ciphertext string encrypted by RSA private key
*/
public static String encryptByPrivateKey(String data, String key) {
try {
//通过PKCS#8编码的Key指令获得私钥对象
RSAPrivateKey privateKey = getPrivateKey(key);
Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return Base64.encodeBase64String(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(StandardCharsets.UTF_8), privateKey.getModulus().bitLength()));
} catch (Exception e) {
throw new RuntimeException("encrypt [" + data + "] error", e);
}
}
private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) throws IOException {
int maxBlock = 0;
if (opmode == Cipher.DECRYPT_MODE) {
maxBlock = keySize / 8;
} else {
maxBlock = keySize / 8 - 11;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] buff;
int i = 0;
try {
while (datas.length > offSet) {
if (datas.length - offSet > maxBlock) {
buff = cipher.doFinal(datas, offSet, maxBlock);
} else {
buff = cipher.doFinal(datas, offSet, datas.length - offSet);
}
out.write(buff, 0, buff.length);
i++;
offSet = i * maxBlock;
}
} catch (Exception e) {
throw new RuntimeException("encrypt [" + maxBlock + "] error", e);
}
byte[] resultDatas = out.toByteArray();
out.close();
return resultDatas;
}
}
2.3:测试demo
/**
* demo
*
* @param args
*/
public static void main(String[] args) {
String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANkyOMTXOBCWBy3Ps39b/rymWWFqujOPxpdp1IAVlk8PuTxWBBscFIHLVAXdf9sCqAw+Wm89RSGDzky6TVIgRXSo6+6hk3ZSIMnu53f9cZlL2G/3+b4BRP3lKsP7nVTTwAEOH1uiJFlJbcCaRuRpGyQJ0mNg/HbCTIWxdKyelBXPAgMBAAECgYAB/eTpYTPhaw7Ly8DQpS5T2o6tRwZIHMRsdQr+1bPYK8O+GufUu9AwVIYDu8FFZ+PUoOnBZWVx5jyJFZhJ7YPVhrZSE4XqMqrtJqIER7m0VDejDSKcKIm6pnmdZHlIvQqkhoCdaCI9kFYgmS0x82SrlMqBpsA9qkSYrRJMZdDv2QJBAPiqjtR5LmfHtrgWE8JezcQqq6IQGQXzGTY73PpuBdIuRAPIvE3b8zuccyUPdozwNzxWEY429aw/XnkZQImZCHsCQQDfmhA2vmSh4eJqtpfhoQqa3IH7wQ20O6nQeIr10lwScfnj8UiKh5GuiOrus8EY0KIQUtA5DAks8RBcJfpNfYm9AkEA9n37P1swSOeLlEcuJwpa5g12PRu/8knbwArvLb9KPeJmwWmGX5ecMIcRDLebSHIGDuUyWcrZFHlsaJZDhyIPaQJBAIgxoNqXUVhA69Yv7YbivkDhOtMLHbu/84klQw7D2Izrm1e5qYOnW5bBksdd+amRuoTSzD1TFWuoUVyvTSxR4MkCQAgTzQAytBOYITp/Ks+0KOrsDPP7KquBDLKNLttayW+0L+ZLJyZvLCpY9Rj1T8lElUD2O16NBp8SafLz7XYEgLk=";
String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZMjjE1zgQlgctz7N/W/68pllharozj8aXadSAFZZPD7k8VgQbHBSBy1QF3X/bAqgMPlpvPUUhg85Muk1SIEV0qOvuoZN2UiDJ7ud3/XGZS9hv9/m+AUT95SrD+51U08ABDh9boiRZSW3AmkbkaRskCdJjYPx2wkyFsXSsnpQVzwIDAQAB";
Map<String, Object> param = new HashMap<>();
param.put("merOrderNo", "123456");
param.put("amount", 100);
String sign = SignUtils.getSign(param);
// sign = 100123456
System.out.println("sign = " + sign);
String encryptData = SHA256WithRSAUtils.encryptByPrivateKey(sign, privateKey);
String decryptData = SHA256WithRSAUtils.decryptByPublicKey(encryptData, publicKey);
//encrypt:bg2Q3dZY0Tv9ycQUMGKVOL7rR1sRZCUk5EnkYeOCpKaCgg1E/NRM9njtNEW5205/BABW6PHnLX9tmNR+C7n9Aj4edsXdCr1uOdgSgaki+4M/Kh2Z3vO+PrYJxBRZjolV+ue51RUqlxYQXcKrygj74QLCLsFRKzk4V2qcHVhs8e4=
System.out.println("encrypt:" + encryptData);
//decrypt:100123456
System.out.println("decrypt:" + decryptData);
//Verify Sign:true
System.out.println("Verify Sign:" + sign.equals(decryptData));
}
2:Python Demo (In progress)
2:C## Demo (In progress)
3:Account Balance
Resource path :/common/openapi/account/balance
Params:
Params Key | required | value |
---|---|---|
country | yes | PHL |
currency | yes | PHP |
request
{
"param": {
"country": "PHL",
"currency": "PHP",
},
"sign": "Gw6D0kuWlnngLMiSxQQ2Dz2ciZz4LUZ7gWA8dRkEbcsE+UoiTOy6T3g6vNvGUlz+vPV2aRHKZ6aPBh0PaJkWW36T/lf8qId4D9uh8lFeTe7zW0+hTgTnN9YmruA6rlRNCo9QytbMRk6qkEZh1PZ2NrFnC77FhYVEVdOk6bIOv/vnGo1RVpbmsO+Gw+tPnvkQ1jvVDEHUlKgnAFGYa7+oWw8eClh9T4Ob7ZUPI0Z+dhefAmEX+z8DCyUxZrtbgA0li21KW2TmErIiRJQxep/f4quWRoTKkPziiMefKo1jFgbyL/gVzgkp91YaMMyk1QJKW1UoZ8iqHKNMI6pmvBCk8g=="
}
response
{
"code": 200,
"message": "",
"data": {
"merId": "",
"merName": "",
"currency": "",
"amountTotal": "0.00",
"freeAmount": "1085178690.00",
"unrecordedAmount": "0.00",
"freezeAmount": "1085178690.00",
"frzBal": "0.00",
"sign": "签名"
}
}
response data
Params Key | Type | description |
---|---|---|
merId | string | merchant no |
merName | string | merchant name |
currency | string | PHP |
amountTotal | BigDecimal | total balance |
freeAmount | BigDecimal | available amount |
unrecordedAmount | BigDecimal | Amount in transit |
freezeAmount | BigDecimal | frozen amount |
sign | string |
4:PayOut
4.1:payout apply
Resource path:/phl/openapi/disbursement/transfer
Params:
Params Key | required | Type | description |
---|---|---|---|
amount | yes | number | The payment amount is required and supports two decimal places (unit yuan) (No 0 after the decimal point, for example: transmission of 123.40 is prohibited, should be transmitted: 123.4) |
cardNumber | yes | string | The payee’s account number, the e-wallet will send the mobile phone number, and the bank will send the bank card number (the mobile phone number starts with 09, 11 digits) |
chanelNo | yes | string | channel no |
currency | yes | string | PHP |
customerName | yes | string | |
merchantOrderNo | yes | string | Merchant order id, format: letters + numbers, 1-32 digits |
method | yes | string | Method :1-Bank,2-Wallet) |
notifyUrl | yes | string | WebHook Url, Notify merchant when order is successful or failed |
remark | no | string | |
timestamp | yes | long | current Time Millis |
transferCode | yes | string | 4.2:Bank Code And 4.3:Wallet Code |
request
{
"param": {
"amount": 0,
"cardNumber": "",
"chanelNo": "",
"currency": "",
"customerName": "",
"merchantOrderNo": "",
"method": "",
"notifyUrl": "",
"remark": "",
"timestamp": 0,
"transferCode": ""
},
"sign": ""
}
response
{
"code": 0,
"data": {
"merchantOrderNo": "",
"plaOrderNo": 0,
"sign": "",
"status": "",
"timestamp": 0
},
"message": ""
}
data param
Params Key | Type | description |
---|---|---|
merchantOrderNo | string | Merchant order id, format: letters + numbers, 1-32 digits |
plaOrderNo | long | Platform order number |
sign | string | Sign String |
status | string | order status |
timestamp | long | current Time Millis |
4.2:Bank Code(PayOut)
bankCode | bankName |
---|---|
ABP | AllBank Inc. |
AUB | Asia United Bank |
BDO | Banco de Oro |
BMB | Bangko Mabuhay |
BOC | Bank Of Commerce |
BPIDB | BPI Direct BanKO, Inc., A Savings Bank |
BPI | Bank of the Philippine Islands |
BRB | Binangonan Rural Bank (BRBDigital) |
CBC | China Banking Corporation(China Bank) |
CBS | China Bank Savings, Inc |
CMG | CAMALIG BANK |
CTBC | Ctbc Bank (Philippines) Corp. |
DBI | Dungganon Bank |
DBP | Development Bank of the Philippines |
EQB | Equicom Savings Bank |
EWB | East-West Banking Corporation |
EWR | East West Rural Bank (Green Bank) |
IBI | ISLA Bank |
ING | ING Bank N.V. |
JPM | JP Morgan Chase Bank, N.A. |
LBP | Land Bank of the Philippines |
MET | Metrobank |
MSB | Malayan Bank |
ONB | One Network Bank |
PAR | Partner Rural Bank(Cotabato) Inc. |
PBB | Philippine Business Bank |
PNB | Philippine National Bank |
PRB | Producers Bank |
PTC | Philippine Trust Company |
PVB | Philippine Veterans Bank |
QCB | Queen City Development Bank, Inc. |
QRB | Quezon Capital Rural Bank |
RCBC | Rizal Commercial Banking Corp. (RCBC) |
RBG | RURAL BANK OF GUINOBATAN, INC. |
RSBI | Rcbc Savings Bank Inc. |
RSB | Robinsons Bank |
SBA | Sterling Bank Of Asia |
SBC | Security Bank |
SPY | Starpay Corporation |
SSB | Sun Savings Bank |
UBP | Union Bank Of The Philippines |
UCPB | United Coconut Planters Bank (UCPB) |
WDB | Wealth Development Bank |
YUANSB | Yuanta Savings Bank |
4.3:Wallet Code(PayOut)
bankCode | bankName |
---|---|
GCASH | gcash |
GRABPAY | grabpay |
OMNIPAY | omnipay |
PAYMAYA | paymaya |
5:PayIn
5.0:The video for PayIn
PH_GCASH_URL: https://drive.google.com/file/d/1HO92-0kEcQbw2_1_Fugn4DG43pKCu45M/view
PH_QRPH_DYNAMIC: https://drive.google.com/file/d/1JwjP5YhfzSxJPkc5Nj96THXuVCqSlWlD/view
5.1:payin apply
Resource path:/phl/openapi/payment/generate
Params:
Params Key | required | Type | description |
---|---|---|---|
amount | yes | number | The payment amount is required and supports two decimal places (unit yuan) (No 0 after the decimal point, for example: transmission of 123.40 is prohibited, should be transmitted: 123.4) |
cardNumber | no | string | User payment card number (real) must be needed when transferring money using online banking |
chanelNo | yes | string | |
channelCode | yes | string | PayIn Channel |
currency | yes | string | PHP |
customerName | yes | string | |
yes | string | ||
merchantOrderNo | yes | string | Merchant order id, format: letters + numbers, 1-32 digits |
mobile | yes | string | Payer’s mobile phone number (mobile phone number starting with 09) |
notifyUrl | yes | string | WebHook Url, Notify merchant when order is successful or failed |
redirectUrl | yes | string | callback url when the Payer’s pay success |
remark | no | string | |
timestamp | yes | integer | current Time Millis |
request
{
"param": {
"amount": 0,
"cardNumber": "",
"chanelNo": "",
"channelCode": "",
"currency": "",
"customerName": "",
"email": "",
"merchantOrderNo": "",
"mobile": "",
"notifyUrl": "",
"redirectUrl": "",
"remark": "",
"timestamp": 0
},
"sign": ""
}
response
{
"code": 0,
"data": {
"merchantOrderNo": "",
"payData": "",
"plaOrderNo": 0,
"sign": "",
"status": "",
"payUrl": "",
"timestamp": 0
},
"message": ""
}
response data
Params Key | Type |
---|---|
merchantOrderNo | string |
payData | string |
plaOrderNo | long |
sign | string |
status | string |
timestamp | long |
payUrl | string |
5.2:PayIn Channel
渠道编码channelCode | 支付渠道描述 |
---|---|
PH_PAYMAYA_URL | paymaya |
PH_QRPH_DYNAMIC | QR |
PH_GCASH_URL | GCASH |
6:Order Status
Resource path:/phl/openapi/orderStatus
Params:
Params Key | required | Type | description |
---|---|---|---|
merchantOrderNo | yes | String | Merchant order id, format: letters + numbers, 1-32 digits |
plaOrderNo | yes | String |
request
{
"param": {
"plaOrderNo": "1223050839733260230"
},
"sign": "111"
}
response — 订单成功
{
"code": 200,
"message": "Success",
"data": {
"amount": "50000",
"merchantOrderNo": "5825683320230508569",
"merchantPayTime": "2023-05-08 11:13:21",
"plaOrderNo": "1223050839733260230",
"plaStatusTime": "2023-05-08 11:13:41"
"status": "COMPLETED",
"sign": "sadnmfasdnmz"
}
}
response data
Params Key | Type |
---|---|
amount | string |
merchantOrderNo | string |
merchantPayTime | string |
plaOrderNo | long |
plaStatusTime | string |
sign | string |
status | string |
7:WebHook
URL: When the system transaction is completed or the balance is insufficient, a callback will be sent to the notify_url callback notification address.
Response Body: After accepting the request, please return the "success" string to us
Request Method:
- method: POST
- Content Type: application/json
body Params:
Params Key | Type | description |
---|---|---|
amount | number | order amount |
merchantNo | string | gcash is valuable when payin |
merchantOrderNo | string | |
merchantPayTime | string | request Time Millis |
plaOrderNo | integer(int64) | |
plaStatusTime | string | Platform order status change time |
sign | string | sign |
status | string | order status |
statusValue | string | Payment status description (valid during paymaya, PHQR and payment callbacks) |
fee | string | |
code | integer(int32) | |
message | string |
request demo
{
"amount": 0,
"merchantOrderNo": "",
"merchantPayTime": "",
"plaOrderNo": 0,
"plaStatusTime": "",
"sign": "",
"status": "",
"fee": "",
"code": 0,
"message": ""
}