Indonesia OpenAPI
About 3293 wordsAbout 11 min
Guidelines for Merchant
Documentation description
Prepare parameters in advance
- appId:Merchant backend->Dashboard->Applications-ID)
- platformPublicKey: Platform public key(Merchant backend->Dashboard->Applications-Platform Public Key)
- merchantPublicKey:Merchant Public Key(Encryption instructions -> SHA256WithRSAUtils.initRSAKey , The public key is saved to Haipay, and the private key is saved by the customer.)
- payOutNotifyUrl:Withdrawal callback address(Merchant backend->Dashboard->Applications)
- payInNotifyUrl:Payment callback address(Merchant backend->Dashboard->Applications)
- merchantSecretKey:Encrypted fields(Merchant backend->Dashboard->Applications)
API Request method
- POST
- Content type : application/json
- test URL:https://uat-interface.haipay.asia
- prod URL:
- Business request address:URL + Resource path
Request interface public parameters
{
"appId": 1000,
......
"sign": "fCywFPOojpRIPi4ph81+CwoAvMXV1va2XR1DQVJeGnZwzNVd0hmvpud7nbP/3lc5JeTVELomruwVTGLtr+BTGT0IweAFTGNvNUuqOs3I4KG5tjvhPM7wm9NtwK2uAX1niLoylt4DcLfy2TeaxPQYDCJJRf7Qm7sDwJX5VoFt8RO9EC2ih+0Ike2+cAyRpIfKENPoIGQbUwvH6KkzHzjljcuvcSqq4D+iZid7up58A866RFrrJH9vkwaF+2mYxa/7awQIwAq8HPOxHkzLfVg74MZC8I1TOKvQAxkAquoNMMyrcAqRIopURfrgEaAtyW/ThPdyduYVlFeMg7BkpGLqZQ=="
}
parameter name | required | type | illustrate |
---|---|---|---|
appId | yes | Integer | Obtain from merchant background |
sign | yes | String | sign |
Response interface public parameters
{
{
"status": "1",
"error": "00000000",
"msg": "",
"data": {
......
"sign": "PWA7B2u1hGr1VRxOCZbRuXQXtJiA6BgPExFnFv73hKJ+zcZfOe/R+y+inlwWcdDBzfix35+dl6raEs/yG/hcYyQOwDQ+mVjIt5wFk6iX7GPw557138yBdAmuMqvWM2IF+omLFcQFJvzfbR84rCyOmebDJlhkYMga5TTFHVLicUx3bPIrOJLoWJHrnZfcVFAJ+P5mUQhMH/cf+YmYZvrqq34pMJh6PcP5vyruJ8aNV0QfyHR42AHLIgp+HnOcZpA0aUzFXM5zpsgXK3QR/KO3vLiKd77UaZNO6g5TN/Ck2MtLkBVxyvIHstgXFXKF1e+uc91FdBHK5nfmrjLQ2wyeUA=="
}
}
}
parameter name | required | type | illustrate |
---|---|---|---|
status | yes | String | 1: normal, 0: abnormal |
error | yes | String | error code |
msg | yes | String | error description |
data | yes | Object | Business data (participating in signature verification) |
error code
error coding | error description |
---|---|
1001 | param is null |
1002 | Illegal Param |
1003 | system exception |
1004 | system is busy |
4005 | order already exit |
4011 | appId do not exit |
4012 | you do not have an available product, please connect admin |
4013 | order not exit |
4014 | order is already end status |
4015 | this merchant do not have a collect bank |
4016 | your account do not have enough money |
4031 | ip adress is Forbidden |
5012 | pay in channel not functional, please connect customer service |
Amount Limit
trans type | limit (Unit:IDR) 1w=10000 |
---|---|
payin | QR: 10,000-5000,000 VA: 10,000-200,000,000 EWALLET:10,000-200,000,000 |
pay out | BANK_ACCOUNT: 10,000-400,000,000 EWALLET: 10,000-200,000,000 |
Encryption instructions(JAVA)
一、SignUtils
public static String getSign(Map<String, Object> map, String merchantSecretKey) {
String result = "";
try {
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(key).append("=").append(val).append("&");
}
}
sb.append("key=").append(merchantSecretKey);
result = sb.toString();
} catch (Exception e) {
return null;
}
二、utils
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName SHA256WithRSAUtils
* @Description (SHA256WithRSA)
* @Author Finlay
* @Date 2021-02-01
* @Version 1.0.0
*/
@Slf4j
public class SHA256WithRSAUtils {
public static final Charset CHARSET = StandardCharsets.UTF_8;
/**
* RSA
*/
public static final String ALGORITHM_RSA = "RSA";
/**
* RSA SIGN
*/
public static final String ALGORITHM_RSA_SIGN = "SHA256WithRSA";
public static final int ALGORITHM_RSA_PRIVATE_KEY_LENGTH = 2048;
private SHA256WithRSAUtils() {
}
/**
*init rsa key
*/
public static Map<String, String> initRSAKey(int keysize) {
if (keysize != ALGORITHM_RSA_PRIVATE_KEY_LENGTH) {
throw new IllegalArgumentException("RSA1024 is no longer safe, please use" + ALGORITHM_RSA_PRIVATE_KEY_LENGTH + "Initialize RSA key pair");
}
KeyPairGenerator kpg;
try {
kpg = KeyPairGenerator.getInstance(ALGORITHM_RSA);
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException("No such algorithm-->[" + ALGORITHM_RSA + "]");
}
kpg.initialize(ALGORITHM_RSA_PRIVATE_KEY_LENGTH);
KeyPair keyPair = kpg.generateKeyPair();
Key publicKey = keyPair.getPublic();
String publicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());
Key privateKey = keyPair.getPrivate();
String privateKeyStr = Base64.getEncoder().encodeToString(privateKey.getEncoded());
Map<String, String> keyPairMap = new HashMap<>();
keyPairMap.put("publicKey", publicKeyStr);
keyPairMap.put("privateKey", privateKeyStr);
return keyPairMap;
}
/**
* RSA Public key encrypted data
*/
public static String buildRSAEncryptByPublicKey(String data, String key) {
try {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.getEncoder().encodeToString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET)));
} catch (Exception e) {
throw new RuntimeException("encrypted string [" + data + "],encountered an exception", e);
}
}
/**
* RSA Public key decrypts data
*/
public static String buildRSADecryptByPublicKey(String data, String key) {
try {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.getDecoder().decode(data)), CHARSET);
} catch (Exception e) {
throw new RuntimeException("Decrypt string [" + data + "],encountered an exception", e);
}
}
/**
* RSA Private key encrypted data
*/
public static String buildRSAEncryptByPrivateKey(String data, String key) {
try {
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return Base64.getEncoder().encodeToString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET)));
} catch (Exception e) {
throw new RuntimeException("encrypted string [" + data + "],encountered an exception", e);
}
}
/**
* RSA Private key decrypts data
*/
public static String buildRSADecryptByPrivateKey(String data, String key) {
try {
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.getDecoder().decode(data)), CHARSET);
} catch (Exception e) {
throw new RuntimeException("Decrypt string[" + data + "],encountered an exception", e);
}
}
/**
* RSA Generate digital signatures on data using private keys
*/
public static String buildRSASignByPrivateKey(String data, String key) {
try {
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance(ALGORITHM_RSA_SIGN);
signature.initSign(privateKey);
signature.update(data.getBytes(CHARSET));
return Base64.getEncoder().encodeToString(signature.sign());
} catch (Exception e) {
throw new RuntimeException("Signature string [" + data + "],encountered an exception", e);
}
}
/**
* RSA Verify digital signature using public key
*/
public static boolean buildRSAverifyByPublicKey(String data, String key, String sign) {
try {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
Signature signature = Signature.getInstance(ALGORITHM_RSA_SIGN);
signature.initVerify(publicKey);
signature.update(data.getBytes(CHARSET));
return signature.verify(Base64.getDecoder().decode(sign));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* RSA Segmented encryption and decryption of data
*/
private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas) {
int maxBlock = 0;
if (opmode == Cipher.DECRYPT_MODE) {
maxBlock = ALGORITHM_RSA_PRIVATE_KEY_LENGTH / 8;
} else {
maxBlock = ALGORITHM_RSA_PRIVATE_KEY_LENGTH / 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("The encryption and decryption threshold is [" + maxBlock + "],An exception occurs", e);
}
byte[] resultDatas = out.toByteArray();
IOUtils.closeQuietly(out);
return resultDatas;
}
}
三、demo
public static void main(String[] args) {
String privateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCKqgxszb4ObuoJ5U8Ddz2ytOFFc81fmniRFo+jvNtrOegMUpd9gBPvMEaBzdeJC74Cg/HsAE7f9u24APLi0oLYZCwthhs01xTIhAis8h7IYCSdWrcbn8gpB7apSe4Ud0dS6zkuRcDTVGsLNrzNOMKHfT8S13dtsqDyDBBhSpkBwe9TkeLQB8K5ZjDYJ8uTtsrcey95eNFe22r8qAhv562yUBTG0PjZpQmiJWD0T6URLLzNYEOXEzsVVZgPKBNWSVZvMjLg32eFv/2Mw+x83n44w39FLx6E347A5hVQYWbBLuHDyFUzW/endOmMSj1YJmGDhctgEK+UIA1bNbexYo33AgMBAAECggEAZlZ6NRLjYeOZ9xO17OjkMDAu0gNVX2mx8eKkwENx7QEfsXiDNayBCdanMsWofQydf13B/lt72u9zIooQuDaFOw8zS6XeDnFudU582KcY8OmEHF4HJewW3bFDrk1R2OjvStMvsGbqmQ2EsxIC5bMuXrChDFbZXayn+/vLWwKjShetqPkN2cRHcKWaASqOnWOAnpgHm5VuGu2ttaR5K14pmMq7a0TOaj7lDYyHelWejCfqFFiWfYLefNj3oFVAfiNxwsxj8q42xWwPZ/Xzhn8p0cInja//1AMuNLIadyC4r6VR7cOIKm4F7XwCTCRCSmPbhDu5pOEA//pERFTTNtE7gQKBgQDdzbujAJRqkn0WwPtbKE7ZxR2KFjc4fM1LyPyODz4tbXhtXtZeMcjjsKn8pTpzbgj+Cfmhz9X8sKAqdxe1WJTtkgg5zbvPQ8A+Q0Su19LZMfFCuC0RCp1SX/asl4XeQe6fQZCft3AG7RgA5HjHET0/7Mpwb3C7A/xBwMfn51T0+wKBgQCgCuy9NmpG2bG/MEz1gDojYe08yKOGgTLp6v/UZcn+U6Oit37/sFe0vU7n9NMtkCLdhf2mqF1cNCUv+rzHkvtgG8FaNlsuozOMXuTNCJ6nj/IypMOnU8vV9DL9zUq5cUnny7HKwCTuS8FYZTjI75GfDDwrxIhhzOIkh2leQD+iNQKBgDV1xOgA18ToEeZOFUdfa8HpVLlXqW+gBQtjIhxLaD0iyYfy99A0R6s5hX8zg+cWemxgkx6BLZ5+I9yYX8qB00N/kyP7hmzqc4eORxutQVDATNo78gDNgiW8o4Pt8YIkehNAhk84s3O36bUtXD7+1Lh3pkN7WLx6tW5TvNsUUtHJAoGBAIYOoJ8dpYgTccAkRVKfRhO9Q2tW5SMVtgAayJCxcrGGfdseuVKT8+OBb0b83KedxJaqVf3zqcBCLaQy80543/dxSFS4k0hNjDBYjG7yeXMCMG4bdYgDuQpOsyfFfoI3UyDGjva2XDj/W8UfhKFLiz8ekIhY56SEaikPBEPerW7BAoGBAIW+5xD7BH4Z/w+GNrA5WFWNNH02+32AD/k6W59GQ+ejrFzCa9/SPa/7WEbBjKNWnzYl9pcdA0lP3LGEbKzrm6Zy+6lCHI6Hx/o4PbHaKTQg2jAIJdEUrAOKR44rjIY41a8wtgilfZA4I4zDSvJMPkMYOItIXjFCwHTxLLfw0CJp";
String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiqoMbM2+Dm7qCeVPA3c9srThRXPNX5p4kRaPo7zbaznoDFKXfYAT7zBGgc3XiQu+AoPx7ABO3/btuADy4tKC2GQsLYYbNNcUyIQIrPIeyGAknVq3G5/IKQe2qUnuFHdHUus5LkXA01RrCza8zTjCh30/Etd3bbKg8gwQYUqZAcHvU5Hi0AfCuWYw2CfLk7bK3HsveXjRXttq/KgIb+etslAUxtD42aUJoiVg9E+lESy8zWBDlxM7FVWYDygTVklWbzIy4N9nhb/9jMPsfN5+OMN/RS8ehN+OwOYVUGFmwS7hw8hVM1v3p3TpjEo9WCZhg4XLYBCvlCANWzW3sWKN9wIDAQAB";
Map<String, Object> request = new HashMap<>();
request.put("merId", "1000");
request.put("orderNo", "1000");
String content = SignUtils.getSign(request, "WFZflvcV75jYP2G6QIpSsMtoX1e4awxO");
String sign = buildRSASignByPrivateKey(content, privateKey);
System.out.println("sign:" + buildRSASignByPrivateKey(content, privateKey));
System.out.println("verify:" + buildRSAverifyByPublicKey(content, publicKey, buildRSASignByPrivateKey(content, privateKey)));
}
Encryption instructions(PHP)
一、SignUtils
/*
require 'SignUtils.php';
$sign = new SignUtils();
$merchantSecretKey = "WFZflvcV75jYP2G6QIpSsMtoX1e4awxO";
$request = array(
"merId" => "1000",
"orderNo" => "1000"
);
$result = $sign->getSign($request,$merchantSecretKey);
var_dump($result)
*/
class SignUtils
{
function getSign($array, $merchantSecretKey) {
$result = "";
try {
$keys = array_keys($array);
sort($keys);
$str = "";
foreach ($keys as $key) {
$val = $array[$key];
if (!empty($val) && $key != "sign") {
$str .= $key . "=" . $val . "&";
}
}
$str = $str . "key=" . $merchantSecretKey;
$result = $str;
} catch (Exception $e) {
return null;
}
return $result;
}
}
二、utils
/*
require 'SHA256WithRSAUtils.php';
$rsa = new SHA256WithRSAUtils();
$publicKey = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiqoMbM2+Dm7qCeVPA3c9srThRXPNX5p4kRaPo7zbaznoDFKXfYAT7zBGgc3XiQu+AoPx7ABO3/btuADy4tKC2GQsLYYbNNcUyIQIrPIeyGAknVq3G5/IKQe2qUnuFHdHUus5LkXA01RrCza8zTjCh30/Etd3bbKg8gwQYUqZAcHvU5Hi0AfCuWYw2CfLk7bK3HsveXjRXttq/KgIb+etslAUxtD42aUJoiVg9E+lESy8zWBDlxM7FVWYDygTVklWbzIy4N9nhb/9jMPsfN5+OMN/RS8ehN+OwOYVUGFmwS7hw8hVM1v3p3TpjEo9WCZhg4XLYBCvlCANWzW3sWKN9wIDAQAB';
$privateKey = 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCKqgxszb4ObuoJ5U8Ddz2ytOFFc81fmniRFo+jvNtrOegMUpd9gBPvMEaBzdeJC74Cg/HsAE7f9u24APLi0oLYZCwthhs01xTIhAis8h7IYCSdWrcbn8gpB7apSe4Ud0dS6zkuRcDTVGsLNrzNOMKHfT8S13dtsqDyDBBhSpkBwe9TkeLQB8K5ZjDYJ8uTtsrcey95eNFe22r8qAhv562yUBTG0PjZpQmiJWD0T6URLLzNYEOXEzsVVZgPKBNWSVZvMjLg32eFv/2Mw+x83n44w39FLx6E347A5hVQYWbBLuHDyFUzW/endOmMSj1YJmGDhctgEK+UIA1bNbexYo33AgMBAAECggEAZlZ6NRLjYeOZ9xO17OjkMDAu0gNVX2mx8eKkwENx7QEfsXiDNayBCdanMsWofQydf13B/lt72u9zIooQuDaFOw8zS6XeDnFudU582KcY8OmEHF4HJewW3bFDrk1R2OjvStMvsGbqmQ2EsxIC5bMuXrChDFbZXayn+/vLWwKjShetqPkN2cRHcKWaASqOnWOAnpgHm5VuGu2ttaR5K14pmMq7a0TOaj7lDYyHelWejCfqFFiWfYLefNj3oFVAfiNxwsxj8q42xWwPZ/Xzhn8p0cInja//1AMuNLIadyC4r6VR7cOIKm4F7XwCTCRCSmPbhDu5pOEA//pERFTTNtE7gQKBgQDdzbujAJRqkn0WwPtbKE7ZxR2KFjc4fM1LyPyODz4tbXhtXtZeMcjjsKn8pTpzbgj+Cfmhz9X8sKAqdxe1WJTtkgg5zbvPQ8A+Q0Su19LZMfFCuC0RCp1SX/asl4XeQe6fQZCft3AG7RgA5HjHET0/7Mpwb3C7A/xBwMfn51T0+wKBgQCgCuy9NmpG2bG/MEz1gDojYe08yKOGgTLp6v/UZcn+U6Oit37/sFe0vU7n9NMtkCLdhf2mqF1cNCUv+rzHkvtgG8FaNlsuozOMXuTNCJ6nj/IypMOnU8vV9DL9zUq5cUnny7HKwCTuS8FYZTjI75GfDDwrxIhhzOIkh2leQD+iNQKBgDV1xOgA18ToEeZOFUdfa8HpVLlXqW+gBQtjIhxLaD0iyYfy99A0R6s5hX8zg+cWemxgkx6BLZ5+I9yYX8qB00N/kyP7hmzqc4eORxutQVDATNo78gDNgiW8o4Pt8YIkehNAhk84s3O36bUtXD7+1Lh3pkN7WLx6tW5TvNsUUtHJAoGBAIYOoJ8dpYgTccAkRVKfRhO9Q2tW5SMVtgAayJCxcrGGfdseuVKT8+OBb0b83KedxJaqVf3zqcBCLaQy80543/dxSFS4k0hNjDBYjG7yeXMCMG4bdYgDuQpOsyfFfoI3UyDGjva2XDj/W8UfhKFLiz8ekIhY56SEaikPBEPerW7BAoGBAIW+5xD7BH4Z/w+GNrA5WFWNNH02+32AD/k6W59GQ+ejrFzCa9/SPa/7WEbBjKNWnzYl9pcdA0lP3LGEbKzrm6Zy+6lCHI6Hx/o4PbHaKTQg2jAIJdEUrAOKR44rjIY41a8wtgilfZA4I4zDSvJMPkMYOItIXjFCwHTxLLfw0CJp';
$decoded = 'eA8//4cK0DZvrOHrfc8vmr5htYqrb8k6gZiZtXAkSoLHOBkgsknRi8SP5YsYar7xXUSOo2b2LLOHB31JlOfXnH5vxIoG6/rHjkPagKA4r8+8cIp6glGou5f41ONJcsMoUPxThgsI+eTe4HxBUKlkjZ/6hh/WSdfcn8lRGGjBmOL5IqRGtvHQBNiJ9l7diezVPhQKZ+YGLOnmH6f+AKNM9/lY+2BWojsLcbLntUr9FGOIkrSf4GiYpWzVRsVOaqY4qmq+1be8qlvA7/MP+bWYCxDtk1OrZh852M4m0LEQosu8rtsalUZhgktBxhmMSR4I6z7e1KkaZdD4Y4iR+AU1Bg==';
$content = 'amount=200¤cy=PHP&merId=1000&orderId=M1234567904&key=WFZflvcV75jYP2G6QIpSsMtoX1e4awxO';
//$data = $rsa->buildRSAverifyByPublicKey($content,$publicKey,$decoded);
$data = $rsa->buildRSASignByPrivateKey($content,$privateKey);
var_dump($data)
*/
class SHA256WithRSAUtils
{
/**
* Initialize RSA algorithm key pair
*
* @param int $keysize 2048
*
*
$result = initRSAKey(2048);
echo "private key:\n";
echo $result['private_key'] . "\n";
echo "public key:\n";
echo $result['public_key'] . "\n";
*/
public function initRSAKey($keysize) {
$config = array(
"digest_alg" => "sha256",
"private_key_bits" => $keysize,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
);
$rsaKey = openssl_pkey_new($config);
openssl_pkey_export($rsaKey, $privateKey);
$publicKey = openssl_pkey_get_details($rsaKey);
$publicKey = $publicKey["key"];
return array(
'public_key' => $publicKey,
'private_key' => $privateKey
);
}
/**
* get privateKey
*/
public function getPrivateKey($privateKey)
{
$pem = "-----BEGIN RSA PRIVATE KEY-----" . PHP_EOL;
$pem .= chunk_split($privateKey, 64, PHP_EOL);
$pem .= "-----END RSA PRIVATE KEY-----" . PHP_EOL;
return openssl_pkey_get_private($pem);
}
/**
* get publicKey
*/
public function getPublicKey($publicKey)
{
$pem = "-----BEGIN PUBLIC KEY-----" . PHP_EOL;
$pem .= chunk_split($publicKey, 64, PHP_EOL);
$pem .= "-----END PUBLIC KEY-----" . PHP_EOL;
return openssl_pkey_get_public($pem);
}
/**
* Private key encryption
*/
public function buildRSASignByPrivateKey($data,$privateKey)
{
$privatekey = openssl_get_privatekey($this->getPrivateKey($privateKey));
//php5.4+ OPENSSL_ALGO_SHA256
openssl_sign($data, $result, $privatekey, OPENSSL_ALGO_SHA256);
//php5.3 SHA256
//openssl_sign($data, $result, $privatekey, 'SHA256');
$result = base64_encode($result);
return $result;
}
/**
* Public key verification
*/
public function buildRSAverifyByPublicKey($data,$publicKey,$sign)
{
$publicKey = openssl_get_publickey($this->getPublicKey($publicKey));
//php5.4+ OPENSSL_ALGO_SHA256
$result = openssl_verify($data, base64_decode($sign), $publicKey, OPENSSL_ALGO_SHA256) == 1 ? true : false;
//php5.3 SHA256
//$result = openssl_verify($data, base64_decode($sign), $publicKey, 'SHA256') == 1 ? true : false;
return $result;
}
}
三、demo
require 'SHA256WithRSAUtils.php';
require 'SignUtils.php';
$publicKey = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiqoMbM2+Dm7qCeVPA3c9srThRXPNX5p4kRaPo7zbaznoDFKXfYAT7zBGgc3XiQu+AoPx7ABO3/btuADy4tKC2GQsLYYbNNcUyIQIrPIeyGAknVq3G5/IKQe2qUnuFHdHUus5LkXA01RrCza8zTjCh30/Etd3bbKg8gwQYUqZAcHvU5Hi0AfCuWYw2CfLk7bK3HsveXjRXttq/KgIb+etslAUxtD42aUJoiVg9E+lESy8zWBDlxM7FVWYDygTVklWbzIy4N9nhb/9jMPsfN5+OMN/RS8ehN+OwOYVUGFmwS7hw8hVM1v3p3TpjEo9WCZhg4XLYBCvlCANWzW3sWKN9wIDAQAB';
$privateKey = 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCKqgxszb4ObuoJ5U8Ddz2ytOFFc81fmniRFo+jvNtrOegMUpd9gBPvMEaBzdeJC74Cg/HsAE7f9u24APLi0oLYZCwthhs01xTIhAis8h7IYCSdWrcbn8gpB7apSe4Ud0dS6zkuRcDTVGsLNrzNOMKHfT8S13dtsqDyDBBhSpkBwe9TkeLQB8K5ZjDYJ8uTtsrcey95eNFe22r8qAhv562yUBTG0PjZpQmiJWD0T6URLLzNYEOXEzsVVZgPKBNWSVZvMjLg32eFv/2Mw+x83n44w39FLx6E347A5hVQYWbBLuHDyFUzW/endOmMSj1YJmGDhctgEK+UIA1bNbexYo33AgMBAAECggEAZlZ6NRLjYeOZ9xO17OjkMDAu0gNVX2mx8eKkwENx7QEfsXiDNayBCdanMsWofQydf13B/lt72u9zIooQuDaFOw8zS6XeDnFudU582KcY8OmEHF4HJewW3bFDrk1R2OjvStMvsGbqmQ2EsxIC5bMuXrChDFbZXayn+/vLWwKjShetqPkN2cRHcKWaASqOnWOAnpgHm5VuGu2ttaR5K14pmMq7a0TOaj7lDYyHelWejCfqFFiWfYLefNj3oFVAfiNxwsxj8q42xWwPZ/Xzhn8p0cInja//1AMuNLIadyC4r6VR7cOIKm4F7XwCTCRCSmPbhDu5pOEA//pERFTTNtE7gQKBgQDdzbujAJRqkn0WwPtbKE7ZxR2KFjc4fM1LyPyODz4tbXhtXtZeMcjjsKn8pTpzbgj+Cfmhz9X8sKAqdxe1WJTtkgg5zbvPQ8A+Q0Su19LZMfFCuC0RCp1SX/asl4XeQe6fQZCft3AG7RgA5HjHET0/7Mpwb3C7A/xBwMfn51T0+wKBgQCgCuy9NmpG2bG/MEz1gDojYe08yKOGgTLp6v/UZcn+U6Oit37/sFe0vU7n9NMtkCLdhf2mqF1cNCUv+rzHkvtgG8FaNlsuozOMXuTNCJ6nj/IypMOnU8vV9DL9zUq5cUnny7HKwCTuS8FYZTjI75GfDDwrxIhhzOIkh2leQD+iNQKBgDV1xOgA18ToEeZOFUdfa8HpVLlXqW+gBQtjIhxLaD0iyYfy99A0R6s5hX8zg+cWemxgkx6BLZ5+I9yYX8qB00N/kyP7hmzqc4eORxutQVDATNo78gDNgiW8o4Pt8YIkehNAhk84s3O36bUtXD7+1Lh3pkN7WLx6tW5TvNsUUtHJAoGBAIYOoJ8dpYgTccAkRVKfRhO9Q2tW5SMVtgAayJCxcrGGfdseuVKT8+OBb0b83KedxJaqVf3zqcBCLaQy80543/dxSFS4k0hNjDBYjG7yeXMCMG4bdYgDuQpOsyfFfoI3UyDGjva2XDj/W8UfhKFLiz8ekIhY56SEaikPBEPerW7BAoGBAIW+5xD7BH4Z/w+GNrA5WFWNNH02+32AD/k6W59GQ+ejrFzCa9/SPa/7WEbBjKNWnzYl9pcdA0lP3LGEbKzrm6Zy+6lCHI6Hx/o4PbHaKTQg2jAIJdEUrAOKR44rjIY41a8wtgilfZA4I4zDSvJMPkMYOItIXjFCwHTxLLfw0CJp';
$request = array(
"merId" => "1000",
"orderNo" => "1000"
);
$sign = new SignUtils();
$merchantSecretKey = "WFZflvcV75jYP2G6QIpSsMtoX1e4awxO";
$content = $sign->getSign($request,$merchantSecretKey);
$rsa = new SHA256WithRSAUtils();
$sign = $rsa->buildRSASignByPrivateKey($content,$privateKey);
$flag = $rsa->buildRSAverifyByPublicKey($content,$publicKey,$sign);
var_dump($content,$sign,$flag)
Account Inquiry
description:
- Query the balance of the account corresponding to the current business
URL:/idr/account/ledger
Request method:
- POST
parameter:
parameter name | required | type | illustrate |
---|---|---|---|
appId | yes | Long | Obtain from merchant background |
sign | yes | String | sign |
request
{
"appId": 1054,
"sign": "fMPmNpU1GOcNdlE8iHsuel5zuO6Rp6RQreFed06lQd+y7YYwyovBsh/pfAg3wfEwwBgUMoKhBiWfhLkLiy9wVUKlRmt0Wyr+LaZ6eCvS+0R7rvYmD3SOu9GMD3IXcATzIOLclQTt7dOgWEKhu+/2k+0sHE33rLeiC2nCYTEZ3DM+MevQvVuK1hG7+j8QSix6rf2CwTuIDVrlOTJTJwt3DxRmWlXiWdheoDEIYBmnhoRRxDkPjfxjOny+vT+BWtSdyKaC54ONC9GmSsOJMAMqy2iL8IqSSdVTzxYJcf++gEB0eJx/QmrbuG4fciCHEYz7YOXReeeZDBQGLTaFT0PBFA=="
}
response
{
"status": "1",
"error": "00000000",
"msg": "",
"data": {
"bal": "751433709.40",
"availableBal": "751433709.40",
"frzBal": "0.00",
"unSettleBal": "0.00",
"sign": "MrKt6KktrigZQaut4J/Ds12H3r+bfdcV/9HV2FGcbkE6+Xkm0fuz0eOVkwxiL684B+tOcWEZRfiZmg5yDSkWxOUdMfzjYTsPM9gHe3UXkhZLPaRIEkfaOnPjYwDPQPvTxKDe94F2AWdnm7QLzuponQvRvdJc2UlnITZqDCIncRYLKUfxN0aLV3m2llWe5zBxf29CUPVy2LEd0eCluks8LGGH3sU1ur3Roo01ftjV1dlkJBJeZ/aJzRNv8SAdx03c+T4662gOnWfw5MMRtJxFfMg/7EUfeVEhSVU4BDKRFWfX6ZQzwM2YO99+SxSIE5msZ9JTl3uCNvmjzrUtjirZjA=="
}
}
Return data parameter description
parameter name | required | illustrate |
---|---|---|
bal | String | Account Balance |
availableBal | String | Amount Available |
frzBal | String | frozen amount |
unSettleBal | String | Amount to be credited |
sign | String | sign |
Pay Out API
Apply
description:
- Create pay out order
URL:/idr/pay/apply
Request method:
- POST
parameter:
parameter name | required | type | illustrate |
---|---|---|---|
appId | yes | Long | Obtain from merchant background |
orderId | yes | String | Merchant order number (must ensure uniqueness) |
amount | yes | String | Transaction amount (unit: IDR) Range: 10000-50000000 |
accountType | yes | String | account type:EWALLET , BANK_ACCOUNT |
bankCode | yes | String | Bank code or wallet code |
accountNo | yes | String | User bank account number |
name | yes | String | Payee's name (payee's name format: English uppercase and lowercase and spaces allowed, 1-30 digits, "firstName middleName lastName" (middleName is optional, special characters supported '.-)) |
phone | yes | String | Mobile phone number (format: starting with 09, pure numbers, 11 digits in total) |
yes | String | ||
subject | no | String | Payment remarks (transaction title, product name, payment reason) |
body | no | String | Remark details |
sign | yes | String | sign |
Example:
request(accountType:BANK_CARD)
{
"appId": 1054,
"orderId": "M100000450012",
"amount": "10000",
"accountType": "BANK_ACCOUNT",
"bankCode": "BDO",
"accountNo": "09876543210",
"name": "john doe",
"phone": "09876543210",
"email": "[email protected]",
"subject": "iphone13",
"body": "ProMotion technology with adaptive refresh rates up to 120Hz",
"sign": "I1PeK3eJOVsFFNowxVRqMXpeWm1lr/BcRpBi8WsW4wVo1+5CC3JsrFq/m/L2O69NzKHvtDWi4zia3DL3dPut0yMyUyqL91LNCSaeISbGsQPlhEsQpyTOryS/RKOfsrn2Xo37SCF/phAvndOk2jwwGwqM5xLz1ms9Ukl85wv27QFNrXIMxK2p18oe7MpMYrgf+xvEBE/VqCtKMtN9pO449wWwXzHWNPbZ76s4pAvKwRE9yXQDr7Iw14Dktcnl1FoLM4gWM/obkO+mz6SyAGDuXhVh/+OD/IGNiCyTCNq6ciQY28UnCFV6ZIP40gxsFhfBJKbK+Raw7y1Bh912ifYfug=="
}
response
{
"status": "1",
"error": "00000000",
"msg": "",
"data": {
"orderId": "M100000450013",
"orderNo": "3023062014149637",
"sign": "LmhUnkw5j0pMiimsG8rKwdNNZGvXH5MpSmD6mdHZwq1SQwuK5BohmdEoqKB/jkMk28o3da4Cxh6Q+tW97+yTCemRrF+dMaHA73rpOeUuujKQl/UcFvJuMhfLBa2tp09L71NzoBqpPD6aXf37mYAz8E1HmERwFPpac5FVxIYanHG8cqmMLJYsVmHTSxWavgWU03ys9UczBePkBiR8sl2FSOhFABB0wAP28lswrV/ABS68IsLKtyd1fyI3GBfSbIK5nDEEnlE+EdElFdLs9taAxJImeVF1x4eT47+bkPJ2qS8z3K8QGzKLF3W+8SiRZGfSwDTsLKH+2Vycvy5auRl+ag=="
}
}
Return data parameter description
parameter name | required | type |
---|---|---|
orderId | String | Merchant order number (must ensure uniqueness) |
orderNo | String | Platform order number |
sign | String | sign |
Pay Out query
description:
- Check pay out order results
URL:/idr/pay/query
Request method:
- POST
parameter:
parameter name | required | type | illustrate |
---|---|---|---|
appId | yes | Long | Obtain from merchant background |
orderId | yes | String | Merchant order number (must ensure uniqueness) |
orderNo | no | String | Platform order number(recommend) |
sign | yes | String | sign |
request
{
"appId": 1000,
"orderId": "M1234567111",
"orderNo": "3022111516571436",
"sign": "ZxkVZL+GAyv0VhvWn4IvuYahTzxgQuthkuV2ONWiqIfIDb2avvHlFOUJVzqZi1q8CPHXZm1ltanRTRVTxfsuftLvGeDioUHglWt46/RU6c1OPznpLGsZ35Q3n5tW2y1EnOsxPynXBFLuDQy+aZ3l9u6AQ30T0zQexMGT+IxuFkmUp02g/6juaHa5ZgNMv7lN67ixIp162wrM7OJuaOif872QijSceRdZhzaMGImAwB0D4MosRV4WMBOKkwgPdmS7GuZN66YUidXk3wTGqX3MYRw6M0kj4eNegSUwPXvp4q4p0KO8Y3xUMld54GY2ApX3WN3CBtC/vpJqEszjGBbbGg=="
}
response — Order failed
{
"status": "1",
"error": "00000000",
"msg": "",
"data": {
"orderId": "M1234567111",
"orderNo": "3022111516571436",
"amount": "100000.00",
"fee": "0.00",
"status": 3,
"errorMsg": "Đơn hàng không tồn tại",
"sign": "KKuvCl0SuNANJs+l2ogDaJm8pmV+Hi+Xa7q27vJ6D1Ehs4aOp13kRbITfJAhczh3T81BE9qwHeJaYwf+r0EypKM9TL6pMwfG8Az4gRy1D57wiUaVjl2PWcvbEqrn1hL0b+btkjvAM9I+CcSv+wuOW3/uku17Ws3FhgJLj9sFsQUBAPjDO+758VnwBytCOLBmljLBXyKgNgpmFQ1/DNkqWl0UNzyLK45Zw3yf5NiwhEFbvW0jlOWlfu/ql4hluISUQG573jEoFCBEnQLb2tQoRZj1QYNRCXPf5lbej0vzqbEwvR9h+ZOf255t1MocJkdIe463DTV5U3KZdVT87HMagw=="
}
}
response — Order successful
{
"status": "1",
"error": "00000000",
"msg": "",
"data": {
"orderId": "M1234567112",
"orderNo": "3022111517401574",
"amount": "100000.00",
"fee": "1003.00",
"status": 2,
"payTime": "2024-03-01 23:59:59",
"sign": "khPtOmGq+cpKX0HFAI/lbP0dx4oVyNAnL5oLsdmhDJdASlQm0yg5I3o+MhImYggEsL6c2bo5fP29t54OZFqSdQDfIuNDvGbAMAr4mRBxc0hoHLkBLyyagfVPBLyQA1JY8XV3ZL4ySzQ3ZQnMCfrh2K39ueUuz6HpZ03Hj0KYijVRCXAZaio/L5jfLBT12QXmvIfAHa8s/k9flhK05ENHPep3zjj/MZGOEaX7jkEJLfjK0duypDCa61BRQjM+oePOdVsgleIl1Yf98UAxMDZ/A3912KFHEb+/jvmdnulNbiJFyuT1fEe+j2teUgw3vFsZAtwNWAgxhC7UO+N0Q5z4EA=="
}
}
Return data parameter description
parameter name | required | type |
---|---|---|
orderId | String | Merchant order number (must ensure uniqueness) |
orderNo | String | Platform order number |
amount | String | amount |
fee | String | fee |
status | Integer | Order status (0 not started, 1 lending in progress, 2 lending successful, 3 lending failed -1 exception to be confirmed) |
payTime | String | Payment success time (valid when status=2) (Indonesia time), format: yyyy-MM-dd HH:mm:ss |
errorMsg | String | Reason for payment failure (valid when status=3) |
sign | String | sign |
Asynchronous notification
description:
- When the order payment is successful or failed, we will push the order status and call back every 5 minutes for 5 times.
URL:you provide
Request method:
- POST
parameter:
parameter name | type | illustrate |
---|---|---|
appId | Long | Obtain from merchant background |
currency | String | Currency, fixed value - IDR |
orderId | String | Merchant order number (must ensure uniqueness) |
orderNo | String | Platform order number |
amount | String | amount |
fee | String | fee |
status | Integer | Order status ( 2 lending successful, 3 lending failed ) |
payTime | String | Payment success time (valid when status=2) (Indonesia time), format: yyyy-MM-dd HH:mm:ss |
errorMsg | String | Reason for payment failure (valid when status=3) |
sign | String | sign |
request
{
"appId": 1002,
"currency": "IDR",
"orderId": "M123456789",
"orderNo": "PLAT123456789",
"status": 2,
"amount": "2100.00",
"payTime": "2024-03-01 23:59:59",
"sign": "SIGN123456789"
}
Note: After receiving the return notification, please return body (uppercase) SUCCESS otherwise the notification will continue for 5 times.
Wallet code and bank code
EWALLET
bankCode | bankName |
---|---|
DANA | dana ewallet |
OVO | ovo ewallet |
BANK_ACCOUNT
bankCode | bankName |
---|---|
567 | ALLO BANK INDONESIA |
116 | BANK ACEH SYARIAH |
947 | BANK ALADIN SYARIAH |
037 | BANK ARTHA GRAHA INTERNASIONAL |
213 | BANK BTPN |
547 | BANK BTPN SYARIAH |
076 | BANK BUMI ARTA |
054 | BANK CAPITAL INDONESIA |
036 | BANK CHINA CONSTRUCTION |
949 | BANK CTBC |
011 | BANK DANAMON |
722 | BANK DANAMON SYARIAH |
111 | BANK DKI |
724 | BANK DKI SYARIAH |
945 | BANK IBK INDONESIA |
164 | BANK ICBC INDONESIA |
513 | BANK INA PERDANA |
555 | BANK INDEX SELINDO |
542 | BANK JAGO/SYARIAH |
472 | BANK JASA JAKARTA |
097 | BANK MAYAPADA |
553 | BANK MAYORA |
506 | BANK MEGA SYARIAH |
147 | BANK MUAMALAT |
548 | BANK MULTI ARTA SENTOSA |
033 | BANK OF AMERICA NA |
069 | BANK OF CHINA |
019 | BANK PAN INDONESIA |
110 | BANK PEMBANGUNAN DAERAH JAWA BARAT DAN BANTEN |
425 | BANK PEMBANGUNAN DAERAH JAWA BARAT DAN BANTEN SYARIAH |
167 | BANK QNB INDONESIA |
494 | BANK RAYA INDONESIA |
047 | BANK RESONA PERDANIA |
451 | BANK SYARIAH INDONESIA |
566 | BANK VICTORIA INTERNASIONAL |
014 | BCA |
501 | BCA Digital |
536 | BCA SYARIAH |
009 | BNI |
129 | BPD BALI |
137 | BPD BANTEN |
133 | BPD BENGKULU |
112 | BPD DIY |
736 | BPD DIY SYARIAH |
115 | BPD JAMBI/SYARIAH |
113 | BPD JAWA TENGAH |
725 | BPD JAWA TENGAH SYARIAH |
114 | BPD JAWA TIMUR/SYARIAH |
123 | BPD KALIMANTAN BARAT |
727 | BPD KALIMANTAN BARAT SYARIAH |
122 | BPD KALIMANTAN SELATAN |
728 | BPD KALIMANTAN SELATAN SYARIAH |
125 | BPD KALIMANTAN TENGAH |
124 | BPD KALIMANTAN TIMUR DAN KALIMANTAN UTARA |
729 | BPD KALIMANTAN TIMUR DAN KALIMANTAN UTARA SYARIAH |
131 | BPD MALUKU DAN MALUKU UTARA |
130 | BPD NTT |
128 | BPD NUSA TENGGARA BARAT SYARIAH |
119 | BPD RIAU KEPRI |
126 | BPD SULAWESI SELATAN DAN SULAWESI BARAT |
735 | BPD SULAWESI SELATAN DAN SULAWESI BARAT SYARIAH |
135 | BPD SULAWESI TENGGARA |
127 | BPD SULAWESI UTARA DAN GORONTALO |
118 | BPD SUMATERA BARAT/NAGARI SYARIAH |
120 | BPD SUMATERA SELATAN BANGKA BELITUNG/SYARIAH |
117 | BPD SUMATERA UTARA |
733 | BPD SUMATERA UTARA SYARIAH |
002 | BRI |
200 | BTN/SYARIAH |
022 | CIMB NIAGA/SYARIAH |
031 | CITIBANK NA |
046 | DBS |
161 | GANESHA |
008 | MANDIRI |
157 | MASPION |
016 | MAYBANK INDONESIA/SYARIAH |
426 | MEGA |
151 | MESTIKA DHARMA |
485 | MNC BANK |
042 | MUFG BANK |
490 | NEO COMMERCE |
503 | NATIONALNOBU |
028 | OCBC NISP/SYARIAH |
013 | PERMATA/SYARIAH |
484 | PT BANK KEB HANA INDONESIA |
564 | PT BANK MANDIRI TASPEN POS |
523 | PT BANK SAHABAT SAMPOERNA |
068 | PT BANK WOORI SAUDARA INDONESIA 1906 |
041 | PT. BANK HSBC INDONESIA |
132 | PT.BANK PEMBANGUNAN DAERAH PAPUA |
535 | SEABANK |
153 | SINARMAS |
734 | SINARMAS SYARIAH |
050 | STANDARD CHARTERED BANK |
023 | UOB INDONESIA |
Pay In API
Apply
description:
- Create a collection order
URL:/idr/collect/apply
Request method:
- POST
parameter:
parameter name | required | type | illustrate |
---|---|---|---|
appId | yes | Long | Obtain from merchant background |
orderId | yes | String | Merchant order number (must ensure uniqueness) |
name | yes | String | Payee's name (payee's name format: English uppercase and lowercase and spaces allowed, 1-30 digits, "firstName middleName lastName" (middleName is optional, special characters supported '.-)) |
phone | yes | String | Mobile phone number (format: starting with 09, pure numbers, 11 digits in total) |
yes | String | ||
amount | yes | String | Transaction amount (unit: IDR,) Range: 10000-50000000 |
payType | yes | String | Normal mode:QR,EWALLET, VA cashier mode:CASHIER |
inBankCode | yes | String | Code |
callBackUrl | yes | String | redirect url |
subject | no | String | Payment remarks (transaction title, product name, payment reason) |
body | no | String | Remark details |
sign | yes | String | sign |
request
{
"appId": 1054,
"orderId": "M233323000059",
"amount": "300",
"phone": "09230219312",
"email": "[email protected]",
"name": "test",
"inBankCode": "014",
"payType": "VA",
"sign": "af0gAHkUOyYHu9owQp8NJ4mPEeUW4vuJcjdxqLIzrVw8AvpLSjD1DXupReSG/CyuSkFRyiIvCp5u703AuGGmfgD2gKDH3Ywau41bAbG2jnHJ8mtjiSJ5iWUzanyd4Kr7d1+rETbzUl7/BkW3t0X8UUFdqpxwG8DPUjAwUKfplWDHV7koG51Ozexd80DCsmW6eWdouAZ1uNXGLYmV3ftE3BmfNRtuv1C5bfTJWrTEIOxbF6g2uYOFZTlIgrQgd7/2PsAYwQQXNz8Q8CYl4OxqCv4pXJxaLWPbR5tqZu9og5kn32C9aHW/NlU1y39vzz+4ef81yPAqUV9oHlSMSPrMmw=="
}
va-response
{
"status": "1",
"error": "00000000",
"msg": "",
"data": {
"orderId": "M233323000059",
"orderNo": "6023071013539074",
"payUrl": "https://a.api-uat.idr.com/1L9zQS2",
"bankCode": "014",
"bankNo": "PC0007I10000035",
"qrCode": "00020101021228760011ph.ppmi.p2m0111OPDVPHM1XXX0315777148000000017041652948137245442930503001520460165303608540810000.php Of Mandalu62310010ph.allbank05062110000803***88310012ph.ppmi.qrph0111OPDVPHM1XXX63042763",
"sign": "YEoA8Y2JzQFGVzwJSqmemm1Kfv/bfyIfCqv2dp7RNzT5B72AQvdD+nt2nR4sL1HWscvmNHyVt5ovAi7MMhy3ziih/sMph+wPx4YjH3W1h5DyBvSlWvaKfKrK5ViomZ0pPYWydwRHnnRnicxToHK9S6qtSy7Q73O0hdz4hJ9p41Th3ycBl2Q9SeqSZYSY1ohcPDhdyRf2y0prb8rHgpBKzxZ5BKX/1bsE9OmsSEHAEYT8OGgko6aNe8XPAhr4G48cpWTftvnGQuzh0O65nuZRI/PF+Axt2zJCVbFHDDSREI9NlAT82ebDqhlVdxQzKE67D1nxgjb3dPmDUYHOBpmwxQ=="
}
}
Return data parameter description
parameter name | type | illustrate |
---|---|---|
orderId | String | Merchant order number (must ensure uniqueness) |
orderNo | String | Platform order number |
payUrl | String | pay url |
bankNo | String | number |
bankCode | String | Code |
qrCode | String | QR code content - you can generate a QR code yourself |
sign | String | sign |
Pay In Query
description:
- Create payment order
URL:/idr/collect/query
Request method:
- POST
parameter:
parameter name | required | type | illustrate |
---|---|---|---|
appId | yes | Long | Obtain from merchant background |
orderId | yes | String | Merchant order number (must ensure uniqueness) |
orderNo | no | String | Platform order number(recommend) |
sign | yes | String | sign |
request
{
"appId": 1054,
"orderId": "M22222000028",
"sign": "EmyJGm3ELzG4FsOd0Krs9ncbSjo4oTGuXWML+7djYla3+VAwd9wS17z38p/7U2ZAjroO04XrE7YXcB1o76Dtyipj3h3bJzs7FYma1QNkMUdt9hh7m8U6hMsMQX7vIWHtXNwz4pbTSC75+kQWXaCew7KoE6LXECdJU8AISgNgeki2TK9R0pCfshr0Z2SZBPeuT6OvIH5LdmqgdZhuqnffGU2qnXk4KMkO848e6/WALLBR+LE1wyKHfPnYVcuKSMVYxkvKyyIL5JIPEgW0o5bh4RCbaUn3NZtyYwrU1uQ3ZDFRThm9j6XAQP+LBlmq3nOePqBtp/VDVarRaV+7FbQg3A=="
}
response
{
"status": "1",
"error": "00000000",
"msg": "",
"data": {
"orderId": "M22222000028",
"orderNo": "6023042811314347",
"amount": "50000.00",
"actualAmount": "0.00",
"fee": "0.00",
"status": 1,
"sign": "fP433ygWVDLVGxYkVnIJj7riGq0U3vyVX+MbBAImxfGLZkZcEAHVEoVYuULZSmXAAXKRSyd67WlDNm+24pougM54ofAoH4HMtCL2tfCoBReFyz3z02AGKkrKE2xWhSpWoqfQoBvzwuN5iGMMu0s9Q1YvqiwJ8WDVIENnmiIyD8qDJN7caHTW2US14/faG+69AvnuIgJ/nu7/jogOlgEYdZdVYU7gcRDE+d47KjlFGswQkJ/h/uzV7cWtUqrtOO7ZnZ3/z33Xx8awokX36QoYcPSWAU0h+Ij9O9402HNhm1eTbYcLU0uI/z8xCAtyAI/tTyiFijpiNlxUKQj+zKsILw=="
}
}
Return data parameter description
parameter name | required | type |
---|---|---|
orderId | String | Merchant order number (must ensure uniqueness) |
orderNo | String | Platform order number |
amount | String | order amount |
actualAmount | String | Amount received |
fee | String | fee |
status | Integer | Collection status (0 not started, 1 receiving payment, 2 collection successful, 3: collection failed, 4: partial collection, 5: excess collection, -1 exception to be confirmed) |
payTime | String | The payment is successful (valid when status=2,4,5) (Indonesia time), format: yyyy-MM-dd HH:mm:ss |
errorMsg | String | Reason for repayment failure (valid when status=3) |
sign | String | sign |
Asynchronous notification
description:
- When the customer's collection is successful or failed, we will push the order status and call back every 5 minutes for 5 times.
- What is pushed is the customer's current payment information, amount: this repayment amount, handling fee: this handling fee
URL:you provide
Request method:
- POST
parameter:
parameter name | type | illustrate |
---|---|---|
appId | Long | Obtain from merchant background |
currency | String | Currency, fixed value - IDR |
orderId | String | Merchant order number (uniqueness must be ensured). The callback for multiple repayments will add the number of multiple repayments to the original number:xxxxx_1,xxxxx_2 |
orderNo | String | Platform order number |
amount | String | amount |
fee | String | fee |
status | Integer | Order status (2: successful collection, 3: failed to collect, 4: partial collection, 5: excessive collection) |
payTime | String | The payment is successful (valid when status=2,4,5) (Indonesia time), format: yyyy-MM-dd HH:mm:ss |
errorMsg | String | Reason for payment failure (valid when status=3) |
sign | String | sign |
request
{
"appId": 10002,
"currency": "IDR",
"orderId": "M123456789",
"orderNo": "PLAT123456789",
"amount": "2100.00",
"fee": "10.00",
"status": 2,
"payTime": "2024-03-01 23:59:59",
"sign": "SIGN123456789"
}
Note: After receiving the return notification, please return body (uppercase) SUCCESS otherwise the notification will continue for 5 times.
inBankCode
payType=QR
bankCode | bankName |
---|---|
dynamic | dynamic qris |
payType=EWALLET
bankCode | bankName |
---|---|
DANA | dana ewallet |
payType=VA
bankCode | bankName |
---|---|
014 | BCA |
008 | Mandiri |
002 | BRI |
009 | BNI |
011 | Danamon |
013 | PERMATA |
022 | CIMB |
payType=CASHIER
bankCode | bankName |
---|---|
CASHIER | cashier |