iPay88 Thailand - Core API
Welcome to the iPay88 Thailand Core API page. Immediately integrate this API with your site to start transactions with iPay88 Thailand payment gateway.
Vital Records
- iPay88 Thailand does not yet provide the iFrame feature for the payment page on the merchant page.
- The CURL method cannot be used for all Thai iPay88 APIs.
- Do a test transaction in the development or sandbox phase first before entering the production phase.
- Make sure all the code you write meets programming and data security standards.
Online Payment System Gateway Version 1.6.2
Immediately integrate this iPay88 Online Payment System Gateway (OPSG) with your site. This API makes your site accept online payments directly via iPay88 Thailand.
Download OPSG Version 1.6.2
ePayment
This document describes the following functionalities of iPay88’s Online Payment Switching Gateway (OPSG) system:
- ePayment: Multiple payment methods for merchant e-commerce website.
- Reports: Online view transaction report.
Objective
Enable iPay88’s OPSG merchant to perform multiple payment types for their customers to make online purchase(s).
Pre-requisite of Merchant Integration
- Merchant Code dan Merchant Key from iPay88 are required.
- Merchant to provideRequest Url to iPay88 Support team.
- Registered Request URL must be either IP or domain based.
Note: Localhost is not allowed.
Important Notice
- Test transaction must from registered Request URL
- Test transaction with amount IDR 3.000,00.
- Test transaction limited to credit cardONLY
- Credit Card test transaction will be refund at the end of day.
- Response URL can be set in request page with ResponseURL field.
- Backend post URL can be set in request page with BackendURL field.
- Email notification is NOT guarantee by iPay88 OPSG as it is ISP dependent. Refer section 4.3 Email Notification Disclaimer Email notification should not use as action identifier by merchant instead use Online Report to check for payment status.
- Ensure a technical person is assigned by merchant before integration.
- Merchant must notify iPay88 Support team the intended live date of merchant account minimum 3 working days in advance.
Transaction Flow Diagram
The following is a merchant transaction flow chart with iPay88 Indonesia.

Transaction Processing Step
Berikut ini adalah proses transaksi merchant dengan iPay88 Indonesia.
- Merchant sends HTTPs Post Request containing payment details to iPay88
OPSG payment page. Payment Details contain the following fields:
- Merchant Code.
- Payment Method.
- Merchant Reference Number.
- Payment Amount.
- Currency.
- Product Description.
- Customer Name.
- Customer Email.
- Customer Contact.
- Merchant Remark.
- Signature.
- Response URL.
- Backend URL.
- User views and confirms payment details entered in Step 1. For credit card payment, the user will need to key-in credit card information.
- User continues to fill in Username and Password at bank website (for noncredit card payment)
- User selects the account to debit the payment. (for non-credit card payment)
- User confirms the payment. If yes, go to next step. (for non-credit card payment)
- User views and prints the payment detail. (for non-credit card payment)
- Response is returned to the iPay88 OPSG website indicating a successful or failed transaction.
- iPay88 OPSG response back the payment status to merchant with a signature
- For successful payment transaction, the merchant needs to compare the signature from iPay88 OPSG. Refer to (3.2)
Merchant Integration
Berikut ini adalah langkah-langkah integrasi merchant dengan iPay88 online payment switching gateway (OPSG).
URL
- Development: https://sandbox.ipay88.co.th/epayment/entry.asp
- Production: https://payment.ipay88.co.th/epayment/entry.asp
- Requery: https://payment.ipay88.co.th/epayment/enquiry.asp
Merchant Request URL provided by merchant before the integration.
Definition: Merchant Request URL is a checkout page at merchant website that submits the required parameter/value to iPay88 OPSG.
Merchant Response URL can be specify with ResponseURL in request page.
Definition: Response page URL is the page at merchant website that will receive payment status from iPay88 OPSG.
Logo
iPay88’s OPSG allow merchant logo/banner to appear in payment page and email notification. Merchant can provide the logo to iPay88 Support team and upload to merchant account.
The maximum allow size for the logo is 600 pixel (width) by 100 pixel (height) and the allow format are JPG, PNG, BMP, and GIF.
Payment Request Parameter
Merchant HTTPS POST payment request parameters to iPay88 OPSG
|
|
|
|
---|---|---|---|
MerchantCode | String (20) | M | The Merchant Code provided by iPay88 and use to uniquely identify the Merchant. |
PaymentId | Integer | O | Refer to Appendix I.pdf file for IDR gateway. |
RefNo | String (20) | M | Unique merchant transaction number / Order ID |
Amount | Currency | M | The amount must not contain any decimal points, thousands separators or currency symbols. For example, Rp. 1.278,00 is expressed as 127800 |
Currency | String (5) | M | Refer to Appendix I.pdf file for IDR gateway. |
ProdDesc | String (100) | M | Product description |
UserName | String (100) | M | Customer name |
UserEmail | String (100) | M | Customer email for receiving receipt |
UserContact | String (20) | M | Customer contact number |
Remark | String (100) | O | Merchant remarks |
Lang | String (20) | O |
Encoding type
"ISO-8859-1" – English. "UTF-8" – Unicode. "GB2312" – Chinese Simplified. "GD18030" – Chinese Simplified. "BIG5" – Chinese Traditionl. |
Signature | String (100) | M | SHA signature. |
ResponseURL | String (200) | M | Payment response page. |
BackendURL | String (200) | M | Backend response page URL. |
xfield1 | String | O | To enable installment and discount payment. |
Legend:
M: Mandatory field.
O: Optional field, value can be empty but parameter must exist.
<html>
<body>
<form method="post" name="ePayment" action="https://sandbox.ipay88.co.th/epayment/entry.asp">
<input type="hidden" name="MerchantCode" value="ID00001">
<input type="hidden" name="PaymentId" value="1">
<input type="hidden" name="RefNo" value="A00000001">
<input type="hidden" name="Amount" value="300000">
<input type="hidden" name="Currency" value="IDR">
<input type="hidden" name="ProdDesc" value="Photo Print">
<input type="hidden" name="UserName" value="John Tan">
<input type="hidden" name="UserEmail" value="john@hotmail.com">
<input type="hidden" name="UserContact" value="0126500100">
<input type="hidden" name="Remark" value="">
<input type="hidden" name="Lang" value="UTF-8">
<input type="hidden" name="Signature" value="Q/iIMzpjZCrhJ2Yt2dor1PaFEFI=">
<input type="hidden" name="ResponseURL" value="http://www.abc.com/payment/response.asp">
<input type="hidden" name="BackendURL" value="http://www.abc.com/payment/backend_response.asp">
<input type="submit" value="Proceed with Payment" name="Submit">
</form>
</body>
</html>
<html>
<body>
<!--Parameter xfield1 ditambahkan khusus untuk metode
pembayaran kartu kredit dengan fitur cicilan dan diskon-->
<form method="post" name="ePayment" action="https://sandbox.ipay88.co.th/epayment/entry.asp">
<input type="hidden" name="MerchantCode" value="ID00001">
<input type="hidden" name="PaymentId" value="1">
<input type="hidden" name="RefNo" value="A00000001">
<input type="hidden" name="Amount" value="300000">
<input type="hidden" name="Currency" value="IDR">
<input type="hidden" name="ProdDesc" value="Photo Print">
<input type="hidden" name="UserName" value="John Tan">
<input type="hidden" name="UserEmail" value="john@hotmail.com">
<input type="hidden" name="UserContact" value="0126500100">
<input type="hidden" name="Remark" value="">
<input type="hidden" name="Lang" value="UTF-8">
<input type="hidden" name="Signature" value="Q/iIMzpjZCrhJ2Yt2dor1PaFEFI=">
<input type="hidden" name="ResponseURL" value="http://www.abc.com/payment/response.asp">
<input type="hidden" name="BackendURL" value="http://www.abc.com/payment/backend_response.asp">
<input type="hidden" name="xfield1" value="||IPP:3||">
<input type="submit" value="Proceed with Payment" name="Submit">
</form>
</body>
</html>
Payment Response Parameter
Berikut ini adalah respon dengan HTTPS POST dari iPay88 OPSG ke merchant setelah selesai proses pembayaran.
|
|
|
|
---|---|---|---|
MerchantCode | String (20) | M | The Merchant Code provided by iPay88 and use to uniquely identify the Merchant. |
PaymentId | Integer | O | Refer to Appendix I.pdf file for IDR gateway |
RefNo | Varchar (20) | M | Unique merchant transaction number / Order ID |
Amount | Currency | M | The amount must not contain any decimal points, thousands separators or currency symbols. For example, Rp 1.278,00 is expressed as 127800. |
Currency | Varchar (5) | M | Refer to Appendix I.pdf file for IDR gateway. |
Remark | Varchar (100) | O | Merchant remarks |
TransId | Varchar (30) | O | iPay88 OPSG Transaction ID |
AuthCode | Varchar (20) | O | Bank’s approval code |
Status | Varchar (1) | M |
Payment Status
"1" – Success. "0" – Fail. "6" – Pending (Only available for ATM Transfer payment). |
ErrDesc | Varchar (100) | O | Payment status description (Refer to Appendix I.pdf file) |
Signature | Varchar (100) | M | SHA1 Signature (refer to 3.2). |
xfield1 | String | O | To enable installment and discount payment |
VirtualAccountAssigned | String | O | Parameter ini hanya berlaku untuk metode pembayaran ATM Transfer. |
TransactionExpiryDate | String | O | Parameter ini hanya berlaku untuk metode pembayaran ATM Transfer. |
Legend:
M: Mandatory field
O: Optional field, value can be empty but parameter must exist
<%
MerchantCode = Request.Form("MerchantCode")
PaymentId = Request.Form("PaymentId")
RefNo = Request.Form("RefNo")
Amount = Request.Form("Amount")
eCurrency = Request.Form("Currency")
Remark = Request.Form("Remark")
TransId = Request.Form("TransId")
AuthCode = Request.Form("AuthCode")
eStatus = Request.Form("Status")
ErrDesc = Request.Form("ErrDesc")
Signature = Request.Form("Signature")
%>
<Add your programming code here>
<?php
$merchantcode = $_REQUEST["MerchantCode"];
$paymentid = $_REQUEST["PaymentId"];
$refno = $_REQUEST["RefNo"];
$amount = $_REQUEST["Amount"];
$ecurrency = $_REQUEST["Currency"];
$remark = $_REQUEST["Remark"];
$transid = $_REQUEST["TransId"];
$authcode = $_REQUEST["AuthCode"];
$estatus = $_REQUEST["Status"];
$errdesc = $_REQUEST["ErrDesc"];
$signature = $_REQUEST["Signature"];
?>
//Add your programming code here
<%
'Parameter xfield1 ditambahkan khusus untuk metode pembayaran kartu kredit dengan fitur cicilan dan diskon.
'Parameter VirtualAccountAssigned dan TransactionExpiryDate ditambahkan khusus untuk metode pembayaran ATM Transfer.
MerchantCode = Request.Form("MerchantCode")
PaymentId = Request.Form("PaymentId")
RefNo = Request.Form("RefNo")
Amount = Request.Form("Amount")
eCurrency = Request.Form("Currency")
Remark = Request.Form("Remark")
TransId = Request.Form("TransId")
AuthCode = Request.Form("AuthCode")
eStatus = Request.Form("Status")
ErrDesc = Request.Form("ErrDesc")
Signature = Request.Form("Signature")
xfield1 = Request.Form("xfield1")
VirtualAccountAssigned = Request.Form("VirtualAccountAssigned")
TransactionExpiryDate = Request.Form("TransactionExpiryDate")
%>
<Add your programming code here>
<?php
//Parameter xfield1 ditambahkan khusus untuk metode pembayaran kartu kredit dengan fitur cicilan dan diskon.
//Parameter VirtualAccountAssigned dan TransactionExpiryDate ditambahkan khusus untuk metode pembayaran ATM Transfer.
$merchantcode = $_REQUEST["MerchantCode"];
$paymentid = $_REQUEST["PaymentId"];
$refno = $_REQUEST["RefNo"];
$amount = $_REQUEST["Amount"];
$ecurrency = $_REQUEST["Currency"];
$remark = $_REQUEST["Remark"];
$transid = $_REQUEST["TransId"];
$authcode = $_REQUEST["AuthCode"];
$estatus = $_REQUEST["Status"];
$errdesc = $_REQUEST["ErrDesc"];
$signature = $_REQUEST["Signature"];
$xfield1 = $_REQUEST["xfield1"];
$va_assigned = $_REQUEST["VirtualAccountAssigned"];
$expiry_date = $_REQUEST["ETransactionExpiryDate"];
?>
//Add your programming code here
Backend Post Feature
The Backend POST feature is server to server technology where it does not depend on the user’s web browser to return payment response data to merchant website. With this feature implemented, your system still can get the payment status on the backend (asynchronously) even if the merchant normal response page fails to get status from iPay88 OPSG which may be due to a closed web browser, internet connection timeout and etc.
Current Supported e-Commerce system with Backend Post.
Note
-
This Backend post feature will ONLY return status if the transaction is a payment success. No status will return if the payment is failed.
-
The Backend page should implement checking same like response page such as signature checking, and etc. to prevent user hijack merchant system.
-
The backend page should not have session related code so that merchant systems are still able accept payment status from iPay88 OPSG even if the user is logged out or the session is expired.
-
You need to implement a check to determine either "response page" or "backend page" to update the order so it won't update order status in merchant system more than 1 time.
Note: After receiving the payment success status, iPay88 OPSG will simultaneously return payment status to "response page" and "backend page"
-
The backend page is not a replacement for the response page. You will still need to continue to use the normal response page as usual.
Implementation
On the merchant website, create another page to accept backend post response
parameters from iPay88 OPSG.
The return backend post response parameters are same like normal response page
parameters.
On the request page, specify the backend post URL by using "BackendURL"
parameter.
Example, <input name = "BackendURL" value = "http://www.abc.com/backend_response">
On the 'backend_response.asp' page you need to write out the word 'RECEIVEOK' only (without quote) as an acknowledgement once the backend page success get the payment status from iPay88 OPSG. iPay88 OPSG will re-try send the payment status to the 'backend_response.asp' page up to 5 times on different interval if no 'RECEVEIOK' acknowledgement detected.
Example:
In ASP >> response.write "RECEIVEOK"
In PHP >> echo "RECEIVEOK";
Note: Make sure just the word 'RECEIVEOK' only on the backend page and without any HTML tag on the page.
Requery Payment Status Parameters (Response URL to enquiry.asp)
Merchant HTTPS POST re-query payment status parameters to iPay88 OPSG
|
|
|
|
---|---|---|---|
MerchantCode | Varchar (20) | M | Merchant Code assigned by iPay88 |
RefNo | Varchar (20) | M | Unique merchant transaction number / Order ID |
Amount | Currency | M | Payment amount with two decimals |
Legend:
M: Mandatory field
O: Optional field, value can be empty but parameter must exist
Possible message reply on the page from iPay88 OPSG
|
|
---|---|
00 | Successful payment |
Invalid parameters | Parameters pass in incorrect |
Record not found | Cannot found the record |
Incorrect amount | Amount different |
Payment fail | Payment fail |
Payment Pending | Payment is pending and need customer to pay at the ATM |
Haven’t Paid (0) | Payment is not paid yet or idle on iPay88 payment page |
Haven’t Paid (1) | Payment is not paid yet or idle on Bank page |
M88Admin | Payment status updated by iPay88 Admin(Fail) |
<%
Function SendToiPayInq(byval MerchantCode, byval RefNo,
byval Amount)
Dim TryNo, thenQString, URL, strReturn
TryNo = 0
QString = "MerchantCode=" & MerchantCode &
"&RefNo=" & RefNo & _
"&Amount=" & Amount
URL = "https://payment.ipay88.co.th/epayment/enquiry.asp"
On Error Resume Next
Do
Set xobj = Server.CreateObject ("Msxml2.ServerXMLHTTP.3.0")
xobj.setTimeouts 30000, 60000, 60000, 60000
xobj.open "POST", URL, false
xobj.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
xobj.send QString
TryNo = TryNo + 1
Loop While xobj.status <> 200 and TryNo < 3
If xobj.status <> 200 Then
SendToiPayInq = Err.Description & "(" & Err.Number & ")"
Else
SendToiPayInq = xobj.responseText
End If
set xobj = nothing
End Function
%>
<?php
function Requery ($MerchantCode, $RefNo, $Amount)
{
$query = "https://payment.ipay88.co.th/epayment/enquiry.asp?MerchantCode=".$MerchantCode."&RefNo=".$RefNo."&Amount=".$Amount;
$url = parse_url($query);
$host = $url["host"];
$path = $url["path"] . "?" . $url["query"];
$timeout = 1;
$fp = fsockopen ($host, 80, $errno, $errstr, $timeout);
if ($fp)
{
fputs ($fp, "GET $path HTTP/1.0\nHost: ".$host."\n\n");
while (!feof($fp))
{
$buf .= fgets($fp, 128);
}
$lines = split("\n", $buf);
$Result = $lines[count($lines)-1];
fclose($fp);
}
else
{
//enter error handing code here
}
return $Result;
}
?>
Security Control
To enhance security, please go through the following steps at the merchant’s payment status receiving page (Response URL):
- Check the HTTP_REFERER value is from https://payment.ipay88.co.th (only applicable if the merchant web site is working with SSL Certificate).
- Check the payment amount from iPay88 OPSG is match with yours.
- Compare the Signature from iPay88 OPSG with your own generated Signature.
Data Integrity and Security using Hash Signature
SHA1 hash is a security feature that enables your script to identify the results of a transaction are actually from the appropriate authorization source and also for iPay88 OPSG to make sure the integrity of data received on a transaction request.
Using the SHA1 algorithm, a unique signature or fingerprint of the transaction can be created. This mathematical algorithm used to construct this signature is designed in such a way that any change to the information used in the calculation of the signature will cause a completely different signature to be created.
Also, the information used in the calculation of the signature cannot be discovered through any analysis of the signature itself. This is done by using information from your account. Every transaction that is processed through the system has a corresponding hash signature of the transaction created during the transaction process.
Request Page Signature
This signature must be included in the request of every transaction. This hash signature for a request is a hash of the following five fields:
- MerchantKey (Provided by iPay88 OPSG and share between iPay88 and merchant only)
- MerchantCode
- RefNo
- Amount
- Currency
The fields must set in the following order,
MerchantKey &
MerchantCode & RefNo & Amount & Currency
Example:
MerchantKey | = | "applekey" |
MerchantCode | = | "ID00001" |
RefNo | = | "A00000001" |
Amount | = | "300000" (Note: 300000 represent amount as Rp 3.000,00) |
Currency | = | "IDR" |
The hash would be calculated on the following string:
applekeyID00001A00000001300000IDR
The resulting has signature value equals to (using SHA1 algorithm)
Q/iIMzpjZCrhJ2Yt2dor1PaFEFI=
To ensure the signature generated was correct, visit the link below for signature comparison. link
Public Shared Function ComputeHas(ByVal Key As String)
Dim objSHA1 As New SHA1CryptoServicesProvider()
objSHA1.ComputeHas(system.Text.Encoding.UTF8.GetBytes(Key.ToCharArray))
Dim buffer() As Byte = objSHA1.Hash
DIm HashValue As String = System.Convert.ToBase64String(buffer)
Return HashValue
End Function
<?php
function iPay88_signature($source)
{
return base64_encode(hex2bin(sha1($source)));
}
function hex2bin($hexSource)
{
for ($i=0;$i<strlen($hexSource);$i=$i+2)
{
$bin .= chr(hexdec(substr($hexSource,$i,2)));
}
return $bin;
}
?>
import java.security.*;
import sun.misc.BASE64Encoder;
import java.io.*;
public class test
{
public static String encrypt(String password)
{
MessageDigest md;
try
{
md = MessageDigest.getInstance("SHA");
md.update(password.getBytes("UTF-8"));
byte raw[] = md.digest();
String hash = (new BASE64Encoder()).encode(raw);
return hash;
}
catch (NoSuchAlgorithmException e)
{
}
catch (java.io.UnsupportedEncodingException e)
{
}
return null;
}
public static void main(String[] args)
{
System.out.println(encrypt("my password"));
// string to hash is here
}
}
<script language="javascript" type="text/javascript"
src="sha1.js"></script>
<script language="javascript">
document.write(iPay88Signature("d3kdhKeH93M00045A00257110800MYR")); //sample signature
</script>
sha1.js file
var hexcase = 0;
/* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = "";
/* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8;
/* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function iPay88Signature(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz))+"=";}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
/*
* Perform a simple self-test to see if the VM is working
*/
function sha1_vm_test()
{
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1(key, data)
{
var bkey = str2binb(key);
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
return core_sha1(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
return bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
return str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
Response Page Signature
If the Merchant request is successful, the response message will contain as SHA1 hashed signature. The hash signature for the response is a hash of the following fields:
- MerchantKey ((Provided by iPay88 OPSG and share between iPay88 and merchant only)
- MerchantCode
- PaymentId
- RefNo
- Amount
- Currency
- Status
The fields must be set in the following order,
MerchantKey & MerchantCode & PaymentId & RefNo &
Amount & Currency & Status
Example:
MerchantKey | = | "applekey" |
MerchantCode | = | "ID00001" |
PaymentId | = | "1" |
RefNo | = | "A00000001" |
Amount | = | "300000" (Note: 300000 represent amount as Rp 3.000,00) |
Currency | = | "IDR" |
Status | = | "1" |
The hash would be calculated on the following string:
applekeyID000011A00000001300000IDR1
The resulting has signature value equals to (using SHA1 algorithm)
01sh+jPUL2wdqCcWJTgiuNuiiTI=
When iPay88 OPSG receives the request or transaction order from the merchant, it will check the hash value it generates to match with the value you as a merchant have included. When your script receives the results of the transaction, you can create the hash on your side and be sure that matches ours. As you will already know your Merchant Key and the Merchant Code, and will receive the Ref No which will then be presented to us. Do take note that the signature in the response will only be present if the transaction is not in error, that is, for approved and declined transactions.
A developer would then take the results of the transaction AFTER it has been returned to your site, and run the hash algorithm on the fields mentioned above. The only way that the results of a developer’s procession can match the signature included with the transaction results is if the password used in the hash on the developer’s end MATCHES the one used in the transaction.The iPay88 OPSG Merchant Key is a shared secret (between merchant and iPay88 OPSG), and is one of the key pieces of information in the hash. One can be assured that if the signature generated on your end matched the one sent with the transaction, then the transaction has in fact been processed by our system, and has not been posted back to the merchant’s server from any other location.
The iPay88 OPSG Merchant Key is generated by us that it’s send to you. The key will only recreate if iPay88 OPSG suspects that the key is not secure or any fraud cases happen. More information about the SHA1 hash algorithm, including sample implementation code, can be found in RFC 3174 in The Internet Engineering Task Force web site.
Public Shared Function ComputeHas(ByVal Key As String)
Dim objSHA1 As New SHA1CryptoServicesProvider()
objSHA1.ComputeHas(system.Text.Encoding.UTF8.GetBytes(Key.ToCharArray))
Dim buffer() As Byte = objSHA1.Hash
DIm HashValue As String = System.Convert.ToBase64String(buffer)
Return HashValue
End Function
<?php
function iPay88_signature($source)
{
return base64_encode(hex2bin(sha1($source)));
}
function hex2bin($hexSource)
{
for ($i=0;$i<strlen($hexSource);$i=$i+2)
{
$bin .= chr(hexdec(substr($hexSource,$i,2)));
}
return $bin;
}
?>
import java.security.*;
import sun.misc.BASE64Encoder;
import java.io.*;
public class test
{
public static String encrypt(String password)
{
MessageDigest md;
try
{
md = MessageDigest.getInstance("SHA");
md.update(password.getBytes("UTF-8"));
byte raw[] = md.digest();
String hash = (new BASE64Encoder()).encode(raw);
return hash;
}
catch (NoSuchAlgorithmException e)
{
}
catch (java.io.UnsupportedEncodingException e)
{
}
return null;
}
public static void main(String[] args)
{
System.out.println(encrypt("my password"));
// string to hash is here
}
}
<script language="javascript" type="text/javascript"
src="sha1.js"></script>
<script language="javascript">
document.write(iPay88Signature("d3kdhKeH93M00045A00257110800MYR")); //sample signature
</script>
sha1.js file
var hexcase = 0;
/* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = "";
/* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8;
/* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function iPay88Signature(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz))+"=";}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
/*
* Perform a simple self-test to see if the VM is working
*/
function sha1_vm_test()
{
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1(key, data)
{
var bkey = str2binb(key);
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
return core_sha1(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
return bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
return str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
Reports and Notification
Kami menyediakan referensi sebagai informasi tambahan untuk Anda. Berikut ini adalah referensi mengenai laporan dan pemberitahuan. Informasi ini perlu Anda ketahui sebagai merchant kami.
Laporan dan Transaksi Merchant
Kami memberikan fasilitas kepada merchant untuk melihat laporan dan cek transaksi secara online.
-
Merchant dapat mengunjungi laman laporan iPay88 OPSG melalui:
- Report URL
- Sandbox: https://sandbox.ipay88.co.th/epayment/report/index.asp
- Production: https://payment.ipay88.co.th/epayment/report/index.asp
- Login Name: disediakan oleh iPay88 OPSG
- Password: disediakan oleh iPay88 OPSG
- Report URL
- Setelah login, select all transaction, filter transaction date, dan klik search.
- Laporan transaksi akan ditampilkan.
Email Notification Disclaimer
Note: Email notifications are NOT guaranteed by iPay88 OPSG as it is ISP dependent. Online Report is the primary channel to obtain transaction status. Email notification should not be taken as a replacement of the primary channel.
E-mail transmissions cannot be guaranteed to be secure or error-free as information could be intercepted, corrupted, lost, destroyed, arrive late or incomplete, or contain viruses. The sender therefore does not accept liability for any errors or omissions in the contents of the email, which arise as a result of e-mail transmission. iPay88 accepts no liability for the content of the email, or for the consequences of any actions taken on the basis of the information provided, unless that information is subsequently confirmed in writing.
1. Customer Payment Receipt Email
Customers will receive a payment detail’s email after successful payment. Below is the email sample:

2. Merchant Payment Notification Email
The Merchant will also receive a payment notification email after successful payment. In order to ensure you are able received all our mail; do make sure you proceed with the following steps:
- From your mailbox, please white-list iPay88 OPSG mail address by adding sales@ipay88.co.th into your friend list.
- Also, please make sure your mailbox has not blacklisted our address which is the following sales@ipay88.co.th
- Allow us to serve you better by white listing our email address and domain iPay88.co.th . Please verify or allow your technical personnel (at the webhosting or email server) to verify the status of your email.
Below is the email sample:

Log Online Payment System Gateway
Kami memberikan informasi mengenai perubahan pada dokumentasi Online Payment Switching Gateway iPay88 Indonesia (iPay88 OPSG). Apabila ada pertanyaan silahkan kirim email ke techsupport@ipay88.co.th.
|
|
|
---|---|---|
1.6.1 | 21 Mei 2013 |
|
1.6.2 | 19 Desember 2017 |
|
Online Payment System Gateway Versi 2.0.6
Segera integrasikan iPay88 Online Payment System Gateway (OPSG) ini dengan situs Anda. API ini menjadikan situs Anda untuk menerima pembayaran online secara langsung melalui iPay88 Indonesia.
Download OPSG Verse 2.0.6 PDF Documentations
Online Payment System
Gateway
Merchant Host - Credit Card Versi 1.0.0
Segera integrasikan iPay88 Online Payment System Gateway (OPSG) Merchant Host - Credit Card ini dengan situs Anda. API ini menjadikan situs Anda untuk menerima pembayaran online secara langsung melalui iPay88 Indonesia.
Download OPSG Merchant Host
ePayment
Segmen ini menjelaskan fungsionalitas dari sistem Online Payment Switching Gateway (OPSG) iPay88 Indonesia. Diantaranya:
- ePayment: berbagai metode pembayaran untuk situs e-commerce milik merchant.
- Reports: online view transaction report.
Objektif
Merchant dapat menyediakan metode pembayaran kartu kredit dan pelanggan dapat melakukan pengisian data kartu kredit secara langsung di laman merchant dengan metode HTTPs Post Form Data melalui iPay88 Indonesia.
Prasyarat Integrasi Merchant
- Diharuskan menggunakan merchant code dan merchant key dari iPay88 Indonesia.
- Merchant harus menyediakan request url ke iPay88 Support Team.
- Request URL yang terdaftar harus berupa IP atau berbasis domain.
Catatan: Localhost tidak diperbolehkan.
Catatan Penting
- Uji transaksi harus dari Request URL yang terdaftar.
- Uji transaksi dengan jumlah IDR 3.000,00.
- Uji transaksi bersifat terbatas untuk metode pembayaran dengan kartu kredit.
- Uji transaksi dengan kartu kredit akan dikembalikan (refund) pada hari akhir.
- Response URL dapat diatur dibagian input ResponseURL pada saat request laman pembayaran iPay88.
- Backend post URL dapat diatur dibagian input BackendURL pada saat request laman pembayaran iPay88.
- Notifikasi email tidak dijamin oleh iPay88 Indonesia karena bergantung pada ISP. Lihat bagian pemberitahuan via email pada laman dokumentasi. Notifikasi email tidak boleh digunakan sebagai patokan identifikasi oleh merchant, gunakan online report untuk memeriksa status pembayaran.
- Pastikan orang teknik ditugaskan oleh merchant sebelum integrasi.
- Merchant harus memberi tahu iPay88 Support Team untuk tanggal live yang diinginkan minimal 3 hari kerja sebelumnya.
Diagram Transaksi
Berikut ini adalah diagram alir transaksi merchant dengan iPay88 Indonesia.

Proses Transaksi
Berikut ini adalah proses transaksi merchant dengan iPay88 Indonesia.
- Merchant mengirimkan HTTPs Post Request yang berisi detail pembayaran ke laman
pembayaran iPay88 Indonesia. Detil pembayaran harus menyertakan:
- MerchantCode
- PaymentId
- RefNo
- Amount
- Currency
- ProdDesc
- UserName
- UserEmail
- UserContact
- Remark
- CCHolderName
- CCNo
- CCMonth
- CCYear
- CCCVV
- Lang
- Signature
- Response URL
- Backend URL
- iPay88 OPSG akan memverifikasi semua nilai yang dikirim oleh merchant, jika sudah sesuai dilanjutkan dengan kangkah berikutnya.
- Informasi akan dikirim ke bank untuk verifikasi lebih lanjut.
- Jika kartu tersebut adalah kartu 3D, halaman verifikasi 3D akan muncul, jika tidak akan dilanjutkan dengan langkah selanjutnya.
- Respon dikembalikan ke iPay88 Indonesia untuk untuk menunjukkan apakah transaksi telah berhasil atau gagal.
- iPay88 Indonesia merespon kembali status pembayaran ke merchant dengan signature.
- Jika status pembayaran sukses, merchant harus membandingkan signature dari iPay88 Indonesia dengan signature yang dihasilkan oleh merchant.
Integrasi Merchant
Berikut ini adalah langkah-langkah integrasi merchant dengan iPay88 online payment switching gateway (OPSG).
URL
- Development: https://sandbox.ipay88.co.id/epayment/entry_v2.asp
- Production: https://payment.ipay88.co.id/epayment/entry_v2.asp
- Requery: https://payment.ipay88.co.id/epayment/enquiry.asp
Merchant Request URL disediakan oleh merchant sebelum integrasi.
Definisi: Merchant Request URL adalah laman pembayaran di situs merchant yang mengirimkan parameter / nilai yang diperlukan ke iPay88 OPSG.
Merchant Response URL dapat ditentukan dengan mengisi parameter ResponseURL di laman request.
Definisi: Response page URL adalah laman di situs merchant yang akan menerima status pembayaran dari iPay88 OPSG.
Logo
iPay88 OPSG menyediakan merchant logo/banner tampil di laman pembayaran dan pemberitahuan email. Merchant dapat memberikan logo ke tim iPay88 Support untuk diunggah ke akun merchant.
Ukuran maksimum yang diperbolehkan untuk logo adalah 600 piksel (lebar) dan 100 piksel (tinggi). Format yang diperbolehkan adalah JPG, PNG, BMP, dan GIF.
Payment Request Parameter
Berikut ini adalah parameter request dengan HTTPS POST pada merchant yang dikirim ke iPay88 OPSG untuk menuju laman pembayaran.
|
|
|
|
---|---|---|---|
MerchantCode | String (20) | M | Merchant Code disediakan oleh iPay88 dan digunakan untuk mengidentifikasi merchant. |
PaymentId | Integer | O | Payment ID untuk metode pembayaran yang dituju. |
RefNo | String (20) | M | Nomor unik transaksi merchant atau Order ID. |
Amount | Currency | M | Total diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp1.278,00 diekspresikan menjadi 127800. |
Currency | String (5) | M | Harus IDR. |
ProdDesc | String (100) | M | Deskripsi produk. |
UserName | String (100) | M | Nama pelanggan. |
UserEmail | String (100) | M | Email pelanggan untuk mendapatkan nota pembayaran. |
UserContact | String (20) | M | Nomor kontak pelanggan. |
Remark | String (100) | O | Catatan merchant. |
CCHolderName | String (100) | M | Nama pemegang kartu kredit. |
CCNo | Integer | M | Nomor kartu kredit. |
CCCVV | Integer | M | Nomor CVV pemegang kartu kredit. Contoh 123. |
CCMonth | Integer | M | Bulan kadaluarsa kartu kredit. Contoh 01. |
CCYear | Integer | M | Tahun kadaluarsa kartu kredit. Contoh 15. |
Lang | String (20) | O |
Encoding type
"ISO-8859-1" – English. "UTF-8" – Unicode. "GB2312" – Chinese Simplified. "GD18030" – Chinese Simplified. "BIG5" – Chinese Traditionl. |
Signature | String (100) | M | SHA signature (merujuk ke 3.1). |
ResponseURL | String (200) | M | Payment response page. |
BackendURL | String (200) | M | Backend response page URL. |
Keterangan:
M: Mandatory (diharuskan).
O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
<html>
<body>
<form method="post" name="ePayment" action="https://sandbox.ipay88.co.id/epayment/entry_v2.asp">
<input type="hidden" name="MerchantCode" value="ID00001">
<input type="hidden" name="PaymentId" value="1">
<input type="hidden" name="RefNo" value="A00000001">
<input type="hidden" name="Amount" value="300000">
<input type="hidden" name="Currency" value="IDR">
<input type="hidden" name="ProdDesc" value="Photo Print">
<input type="hidden" name="UserName" value="John Tan">
<input type="hidden" name="UserEmail" value="john@hotmail.com">
<input type="hidden" name="UserContact" value="0126500100">
<input type="hidden" name="Remark" value="">
<input type="hidden" name="CCHolderName" value="">
<input type="hidden" name="CCNo" value="">
<input type="hidden" name="CCCVV" value="">
<input type="hidden" name="CCMonth" value="">
<input type="hidden" name="CCYear" value="">
<input type="hidden" name="Lang" value="UTF-8">
<input type="hidden" name="Signature" value="Q/iIMzpjZCrhJ2Yt2dor1PaFEFI=">
<input type="hidden" name="ResponseURL" value="http://www.abc.com/payment/response.asp">
<input type="hidden" name="BackendURL" value="http://www.abc.com/payment/backend_response.asp">
<input type="submit" value="Proceed with Payment" name="Submit">
</form>
</body>
</html>
Payment Response Parameter
Berikut ini adalah respon dengan HTTPS POST dari iPay88 OPSG ke merchant setelah selesai proses pembayaran.
|
|
|
|
---|---|---|---|
MerchantCode | String (20) | M | Merchant Code disediakan oleh iPay88 dan digunakan untuk mengidentifikasi merchant. |
PaymentId | Integer | O | Payment ID untuk metode pembayaran yang dituju. |
RefNo | Varchar (20) | M | Nomor unik transaksi merchant atau Order ID. |
Amount | Currency | M | Total diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp1.278,00 diekspresikan menjadi 127800. |
Currency | Varchar (5) | M | Harus IDR. |
Remark | Varchar (100) | O | Catatan merchant. |
TransId | Varchar (30) | O | iPay88 OPSG ID Transaksi. |
AuthCode | Varchar (20) | O | Kode persetujuan bank. |
Status | Varchar (1) | M |
Status pembayaran
"1" – Success. "0" – Fail. "6" – Pending (hanya tersedia untuk metode pembayaran ATM Transfer). |
ErrDesc | Varchar (100) | O | Deskripsi penyebab gagal-nya transaksi. |
Signature | Varchar (100) | M | SHA1 Signature (merujuk ke 3.2). |
Keterangan:
M: Mandatory (diharuskan).
O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
<%
MerchantCode = Request.Form("MerchantCode")
PaymentId = Request.Form("PaymentId")
RefNo = Request.Form("RefNo")
Amount = Request.Form("Amount")
eCurrency = Request.Form("Currency")
Remark = Request.Form("Remark")
TransId = Request.Form("TransId")
AuthCode = Request.Form("AuthCode")
eStatus = Request.Form("Status")
ErrDesc = Request.Form("ErrDesc")
Signature = Request.Form("Signature")
%>
<Add your programming code here>
<?php
$merchantcode = $_REQUEST["MerchantCode"];
$paymentid = $_REQUEST["PaymentId"];
$refno = $_REQUEST["RefNo"];
$amount = $_REQUEST["Amount"];
$ecurrency = $_REQUEST["Currency"];
$remark = $_REQUEST["Remark"];
$transid = $_REQUEST["TransId"];
$authcode = $_REQUEST["AuthCode"];
$estatus = $_REQUEST["Status"];
$errdesc = $_REQUEST["ErrDesc"];
$signature = $_REQUEST["Signature"];
?>
//Add your programming code here
Backend Post Feature
Backend post feature adalah teknologi server ke server yang tidak bergantung pada web browser si pelanggan merchant. Fitur ini harus diimplementasikan di situs merchant. Tujuan fitur ini adalah untuk mendapatkan status pembayaran dari iPay88 OPSG. Merchant bisa mendapatkan status pembayaran melalui laman backend merchant. iPay88 OPSG dapat mengirim status pembayaran secara berulang walaupun laman respon merchant gagal mendapatkan status tersebut yang disebabkan oleh browser web ditutup, batas waktu koneksi internet, dan lain sebagainya.
Sistem manajemen konten yang telah mendukung fitur backend post melalui plugin iPay88 Indonesia.
Catatan
-
iPay88 OPSG hanya mengirim status pembayaran melalui laman backend merchant apabila status pembayaran pada transaksi merchant telah sukses. Jika status pembayaran gagal, maka iPay88 OPSG tidak akan mengirimkan status melalui laman backend merchant.
-
Laman backend merchant harus menerapkan beberapa pengecekan yang sama seperti laman response seperti pengecekan signature, dan lain sebagainya untuk mencegah tejadinya pembajakan pada sistem merchant.
-
laman backend merchant tidak boleh memiliki kode session sehingga sistem merchant masih dapat menerima status pembayaran dari iPay88 OPSG bahkan jika pelanggan telah keluar atau session telah berakhir.
-
Anda perlu melakukakan pemeriksaan untuk menentukan fungsi perubah status transaksi baik di "laman response" atau "laman backend" sehingga tidak terjadinya perubahan status transaksi lebih dari satu kali.
Note: Setelah iPay88 OPSG menerima informasi dari bank bahwa status pembayaran pada transaksi merchant telah suskes, iPay88 OPSG secara bersamaan akan mengirimkan status pembayaran tersebut ke "laman response" dan "laman backend" merchant.
-
Laman backend bukan sebagai pengganti laman response. Anda harus terus menggunakan laman response seperti biasa.
Implementasi
Pada situs merchant, buat laman lain sebagai backend untuk menerima parameter dari iPay88 OPSG. Parameter backend yang dikirim oleh iPay88 OPSG sama seperti parameter yang dikirim ke laman response merchant. Pada laman request merchant, tentukan url backend melalui parameter "BackendURL".
Sebagai contoh, <input name = "BackendURL" value = "http://www.abc.com/backend_response">
Pada laman 'backend_response' Anda perlu menuliskan kata 'RECEIVEOK' saja (tanpa tanda kutip) sebagai konfirmasi setelah laman backend berhasil mendapatkan status pembayaran dari iPay88 OPSG. Tentunya kata tersebut tertulis setelah dilakukan pengecekan seperti signature dan lain sebagainya di laman backend merchant. iPay88 OPSG akan mencoba mengirim kembali status pembayaran ke laman 'backend_response' hingga 5 kali pada interval yang berbeda jika tidak terdeteksi 'RECEVEIOK'.
Contoh:
Di ASP >> response.write "RECEIVEOK"
Di PHP >> echo "RECEIVEOK";
Catatan: Pastikan hanya kata 'RECEIVEOK' tanpa tag HTML apa pun.
Requery Payment Status Parameters (Response URL to enquiry.asp)
Berikut ini adalah parameter dengan HTTPS POST pada merchant yang dikirim ke iPay88 OPSG untuk re-query status pembayaran.
|
|
|
|
---|---|---|---|
MerchantCode | Varchar (20) | M | Merchant Code disediakan oleh iPay88 dan digunakan untuk mengidentifikasi merchant. |
RefNo | Varchar (20) | M | Nomor unik transaksi merchant atau Order ID. |
Amount | Currency | M | Total diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp1.278,00 diekspresikan menjadi 127800. |
Keterangan:
M: Mandatory (diharuskan).
O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
Berikut ini adalah kemungkinan pesan didapatkan dari iPay88 OPSG.
|
|
---|---|
00 | Pembayaran sukses. |
Invalid parameters | Parameter yang dikirimkan merchant tidak tepat. |
Record not found | Data tidak ditemukan. |
Incorrect amount | Total yang tidak tepat (berbeda). |
Payment fail | Pembayaran gagal. |
Payment Pending | Pembayaran tertunda dan pelanggan harus membayar di mesin ATM. |
Haven’t Paid (0) | Tagihan belum dibayar atau berhenti di laman pembayaran iPay88. |
Haven’t Paid (1) | Tagihan belum dibayar atau berhenti di laman bank. |
M88Admin | Status pembayaran diubah oleh iPay88 Admin (gagal). |
<%
Function SendToiPayInq(byval MerchantCode, byval RefNo,
byval Amount)
Dim TryNo, thenQString, URL, strReturn
TryNo = 0
QString = "MerchantCode=" & MerchantCode &
"&RefNo=" & RefNo & _
"&Amount=" & Amount
URL = "https://payment.ipay88.co.id/epayment/enquiry.asp"
On Error Resume Next
Do
Set xobj = Server.CreateObject ("Msxml2.ServerXMLHTTP.3.0")
xobj.setTimeouts 30000, 60000, 60000, 60000
xobj.open "POST", URL, false
xobj.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
xobj.send QString
TryNo = TryNo + 1
Loop While xobj.status <> 200 and TryNo < 3
If xobj.status <> 200 Then
SendToiPayInq = Err.Description & "(" & Err.Number & ")"
Else
SendToiPayInq = xobj.responseText
End If
set xobj = nothing
End Function
%>
<?php
function Requery ($MerchantCode, $RefNo, $Amount)
{
$query = "https://payment.ipay88.co.id/epayment/enquiry.asp?MerchantCode=".$MerchantCode."&RefNo=".$RefNo."&Amount=".$Amount;
$url = parse_url($query);
$host = $url["host"];
$path = $url["path"] . "?" . $url["query"];
$timeout = 1;
$fp = fsockopen ($host, 80, $errno, $errstr, $timeout);
if ($fp)
{
fputs ($fp, "GET $path HTTP/1.0\nHost: ".$host."\n\n");
while (!feof($fp))
{
$buf .= fgets($fp, 128);
}
$lines = split("\n", $buf);
$Result = $lines[count($lines)-1];
fclose($fp);
}
else
{
//enter error handing code here
}
return $Result;
}
?>
Kontrol Keamanan
Untuk meningkatkan keamanan, silahkan ikuti langkah-langkah berikut di laman penerimaan status pembayaran merchant (Response URL).
- Periksa nilai HTTP_REFERER dari https://payment.ipay88.co.id (hanya berlaku jika situs web merchant berfungsi dengan Sertifikat SSL).
- Periksa jumlah pembayaran dari iPay88 OPSG sesuai dengan pelanggan Anda.
- Bandingkan signature dari iPay88 OPSG dengan signature yang Anda hasilkan sendiri.
Integritas Data dan Keamanan menggunakan Signature Acak
Pengacakan SHA1 adalah fitur keamanan yang memungkinkan skrip Anda untuk mengidentifikasi hasil transaksi sebenarnya dari sumber otorisasi yang sesuai. Bagi iPay88 OPSG, fitur ini berguna untuk memastikan integritas data yang diterima pada setiap request transaksi dari merchant.
Menggunakan algoritma SHA1, signature atau fingerprint dari transaksi dapat dihasilkan. Algoritma matematika yang digunakan untuk membangun signature ini dirancang sedemikian rupa sehingga setiap adanya perubahan pada informasi yang digunakan dalam perhitungan akan menghasilkan signature yang berbeda pula.
Informasi yang digunakan dalam perhitungan signature tidak dapat diketahui walau dengan menganalisa signature itu sendiri. Signature dihasilkan dengan menggunakan informasi dari akun Anda sebagai merchant. Setiap transaksi yang diproses melalui sistem memiliki pengacakan signature tersendiri yang berkaitan dengan transaksi tersebut.
Request Page Signature
Signature harus disertakan pada proses request laman pembayaran iPay88 OPSG disetiap transaksi merchant. Signature tersebut adalah hasil dari pengacakan lima bidang utama berikut.
- MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 OPSG)
- MerchantCode
- RefNo
- CCNo
- CCMonth
- CCYear
- CCCVV
- Amount
- Currency
Field harus tersusun mengikuti aturan berikut:
MerchantKey & MerchantCode & RefNo & CCNo & CCMonth
& CCYear & CCCVV & Amount & Currency
Contoh:
MerchantKey | = | "apple" |
MerchantCode | = | "ID00001" |
RefNo | = | "A00000001" |
CCNo | = | "4111111111111111" |
CCMonth | = | "01" |
CCYear | = | "18" |
CCCVV | = | "123" |
Amount | = | "1000000" (catatan: 1000000 adalah representasi dari total Rp10.000,00) |
Currency | = | "IDR" |
Pengacakan akan dihitung melalui string berikut:
appleID00001A00000001411111111111111101181231000000IDR
Hasil signature (menggunakan algoritma SHA1) adalah:
u4UJxVz6jgxx0qFA0b6oLC6sUgs=
Untuk memastikan signature yang dihasilkan sudah benar, silahkan klik tautan ini untuk perbandingan signature.
Public Shared Function ComputeHas(ByVal Key As String)
Dim objSHA1 As New SHA1CryptoServicesProvider()
objSHA1.ComputeHas(system.Text.Encoding.UTF8.GetBytes(Key.ToCharArray))
Dim buffer() As Byte = objSHA1.Hash
DIm HashValue As String = System.Convert.ToBase64String(buffer)
Return HashValue
End Function
<?php
function iPay88_signature($source)
{
return base64_encode(hex2bin(sha1($source)));
}
function hex2bin($hexSource)
{
for ($i=0;$i<strlen($hexSource);$i=$i+2)
{
$bin .= chr(hexdec(substr($hexSource,$i,2)));
}
return $bin;
}
?>
import java.security.*;
import sun.misc.BASE64Encoder;
import java.io.*;
public class test
{
public static String encrypt(String password)
{
MessageDigest md;
try
{
md = MessageDigest.getInstance("SHA");
md.update(password.getBytes("UTF-8"));
byte raw[] = md.digest();
String hash = (new BASE64Encoder()).encode(raw);
return hash;
}
catch (NoSuchAlgorithmException e)
{
}
catch (java.io.UnsupportedEncodingException e)
{
}
return null;
}
public static void main(String[] args)
{
System.out.println(encrypt("my password"));
// string to hash is here
}
}
<script language="javascript" type="text/javascript"
src="sha1.js"></script>
<script language="javascript">
document.write(iPay88Signature("d3kdhKeH93M00045A00257110800MYR")); //sample signature
</script>
sha1.js file
var hexcase = 0;
/* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = "";
/* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8;
/* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function iPay88Signature(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz))+"=";}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
/*
* Perform a simple self-test to see if the VM is working
*/
function sha1_vm_test()
{
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1(key, data)
{
var bkey = str2binb(key);
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
return core_sha1(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
return bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
return str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
Response Page Signature
Jika status pembayaran dari transaksi merchant dinyatakan sukses, iPay88 OPSG akan mengirim signature di laman response dan backend merchant. Signature ini harus dibandingkan dengan signature yang dihasilkan oleh merchant sendiri guna mengindari adanya pembajakan. Signature tersebut adalah hasil dari pengacakan tujuh bidang utama berikut.
- MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 OPSG)
- MerchantCode
- PaymentId
- RefNo
- Amount
- Currency
- Status
Field harus tersusun mengikuti aturan berikut:
MerchantKey & MerchantCode & PaymentId & RefNo &
Amount & Currency & Status
Contoh:
MerchantKey | = | "apple" |
MerchantCode | = | "ID00001" |
PaymentId | = | "1" |
RefNo | = | "A00000001" |
Amount | = | "1000000" (catatan: 1000000 adalah representasi dari total Rp10.000,00) |
Currency | = | "IDR" |
Status | = | "1" |
Pengacakan akan dihitung melalui string berikut:
appleID000011A000000011000000IDR1
Hasil signature (menggunakan algoritma SHA1) adalah:
vewK2KcOl3lyFug1UEsnzDjTDDA=
Untuk memastikan signature yang dihasilkan sudah benar, silahkan klik tautan ini untuk perbandingan signature.
Ketika iPay88 OPSG menerima request atau transaksi dari merchant, iPay88 OPSG akan memeriksa nilai acak signature yang dihasilkan untuk dicocokkan dengan nilai signature yang merchant kirim. Ketika sistem merchant menerima hasil transaksi, merchant dapat membuat signature dan pastikan sama dengan signature yang dikirim balik oleh iPay88 OPSG. Merchant akan mendapatkan signature di laman response jika transaksi tidak error (tidak termasuk transaksi yang disetujui atau ditolak).
Setelah merchant menerima informasi dari iPay88 OPSG terkait status pembayaran dari transaksi, merchant harus menjalanakan algoritma acak pada tujuh bidang utama yg telah disebutkan diatas sehingga menghasilkan suatu signature. Merchant wajib mencocokkan hasil signature merchant dengan signature iPay88 OPSG. Dapat dipastikan jika signature yang dihasilkan merchant saat proses request dan dikirim ke iPay88 OPSG, maka transaksi merchant telah diproses oleh sistem iPay88 OPSG.
Merchant key dibuat oleh iPay88 OPSG untuk merchant. Merchant key bersifat rahasia bersama (antara merchant dan iPay88 OPSG), dan merupakan salah satu bagian kunci informasi untuk proses pengacakan signature. Merchant key akan dibuat ulang jika iPay88 OPSG mencurigai bahwa merchant key sudah tidak aman atau terjadi kasus penipuan. Informasi lebih lanjut tentang algoritma acak SHA1, termasuk sampel kode untuk implementasi dapat ditemukan di RFC 3174 dalam laman Task Force Internet Engineering.
Public Shared Function ComputeHas(ByVal Key As String)
Dim objSHA1 As New SHA1CryptoServicesProvider()
objSHA1.ComputeHas(system.Text.Encoding.UTF8.GetBytes(Key.ToCharArray))
Dim buffer() As Byte = objSHA1.Hash
DIm HashValue As String = System.Convert.ToBase64String(buffer)
Return HashValue
End Function
<?php
function iPay88_signature($source)
{
return base64_encode(hex2bin(sha1($source)));
}
function hex2bin($hexSource)
{
for ($i=0;$i<strlen($hexSource);$i=$i+2)
{
$bin .= chr(hexdec(substr($hexSource,$i,2)));
}
return $bin;
}
?>
import java.security.*;
import sun.misc.BASE64Encoder;
import java.io.*;
public class test
{
public static String encrypt(String password)
{
MessageDigest md;
try
{
md = MessageDigest.getInstance("SHA");
md.update(password.getBytes("UTF-8"));
byte raw[] = md.digest();
String hash = (new BASE64Encoder()).encode(raw);
return hash;
}
catch (NoSuchAlgorithmException e)
{
}
catch (java.io.UnsupportedEncodingException e)
{
}
return null;
}
public static void main(String[] args)
{
System.out.println(encrypt("my password"));
// string to hash is here
}
}
<script language="javascript" type="text/javascript"
src="sha1.js"></script>
<script language="javascript">
document.write(iPay88Signature("d3kdhKeH93M00045A00257110800MYR")); //sample signature
</script>
sha1.js file
var hexcase = 0;
/* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = "";
/* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8;
/* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function iPay88Signature(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz))+"=";}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
/*
* Perform a simple self-test to see if the VM is working
*/
function sha1_vm_test()
{
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1(key, data)
{
var bkey = str2binb(key);
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
return core_sha1(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
return bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
return str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
Laporan dan Pemberitahuan
Kami menyediakan referensi sebagai informasi tambahan untuk Anda. Berikut ini adalah referensi mengenai laporan dan pemberitahuan. Informasi ini perlu Anda ketahui sebagai merchant kami.
Laporan dan Transaksi Merchant
Kami memberikan fasilitas kepada merchant untuk melihat laporan dan cek transaksi secara online.
-
Merchant dapat mengunjungi laman laporan iPay88 OPSG melalui:
- Report URL
- Sandbox: https://sandbox.ipay88.co.id/epayment/report/index.asp
- Production: https://payment.ipay88.co.id/epayment/report/index.asp
- Login Name: disediakan oleh iPay88 OPSG
- Password: disediakan oleh iPay88 OPSG
- Report URL
- Setelah login, select all transaction, filter transaction date, dan klik search.
- Laporan transaksi akan ditampilkan.
Pemberitahuan Via Email
Pemberitahuan via email tidak dijamin oleh iPay88 OPSG karena bergantung pada ISP. Laporan Online (online report) adalah media utama untuk melihat status transaksi. Pemberitahuan via email tidak boleh diambil atau disimpulkan sebagai pengganti media utama.
Transmisi email tidak dapat dijamin aman atau bebas dari kesalahan karena informasi dapat disadap, rusak, hilang, hancur, datang terlambat atau tidak lengkap, atau mengandung virus. Oleh karena itu pengirim tidak bertanggung jawab atas kesalahan atau kelalaian apa pun dalam isi email, yang timbul sebagai akibat dari transmisi email. iPay88 tidak bertanggung jawab atas isi email, atau konsekuensi dari tindakan apa pun yang diambil atas dasar informasi yang diberikan, kecuali jika informasi itu kemudian dikonfirmasi secara tertulis.
1. Email Pembayaran Pelanggan
Pelanggan akan menerima email pemberitahuan berisi detil pembayaran setelah pembayaran berhasil. Dibawah ini adalah contoh email yang dikirimkan ke pelanggan.

2. Email Pemberitahuan Merchant
Merchant juga menerima email pemberitahuan berisi detil pembayaran setelah pembayaran berhasil. Untuk memastikan Anda dapat menerima semua email kami, pastikan Anda telah menjalani langkah-langkah berikut:
- Dari mailbox Anda, pastikan white-list alamat email iPay88 dengan menambahkan sales@ipay88.co.id ke dalam daftar teman Anda.
- Selain itu, pastikan mailbox Anda tidak melakukan black-list alamat email iPay88 yaitu sales@ipay88.co.id.
- Untuk pelayanan yang lebih baik, white-list alamat email dan domain iPay88.co.id. Harap verifikasi atau izinkan personel teknik Anda (webhosting atau email server) untuk memverifikasi status email Anda. Di bawah ini adalah contoh email:
Dibawah ini adalah contoh email yang dikirimkan ke merchant.

Recurring Payment Versi 2.0.3
Segera integrasikan iPay88 Recurring Payment ini dengan situs Anda. API ini menjadikan situs Anda untuk menerima pembayaran berulang dan memudahkan memudahkan pelanggan Anda dalam bertransaksi.
Download iPay88 Recurring Payment
Objektif
Merchant dapat mendaftarkan transaksi recurring payment kepada pelanggan dengan metode HTTPs Post Form Data melalui iPay88 Indonesia.
URL
Berikut URL yang digunakan sebagai Subscription Request dan Response.
- Subscription Request URL:
https://payment.ipay88.co.id/recurringpayment2.0/subscription.asp - Subscription Response URL:
[provided by merchant before start the integration]
Parameter
Berikut ini adalah parameter yang digunakan untuk proses recurring dengan iPay88 Indonesia.
Subscription Request Parameters
Merchant mengirimkan parameter melalui HTTPS POST sebagai subscription request kepada iPay88 Indonesia.
|
|
|
|
---|---|---|---|
MerchantCode | Varchar (20) | M | Merchant Code disediakan oleh iPay88 dan digunakan untuk mengidentifikasi merchant. |
RefNo | Varchar (20) | M | Nomor unik transaksi merchant atau Order ID. |
FirstPaymentDate | Datetime | M | Tanggal pembayaran pertama (DDMMYYYY). |
Currency | Varchar (5) | M | Hanya IDR. |
Amount | Currency | M | Total diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp1.278,00 diekspresikan menjadi 127800. |
NumberofPayments | int | M | Subscription cycle. Contoh 12. |
Frequency | Int | M | Tipe frekuensi: 1 = Weekly 2 = Monthly 3 = Quarterly 4 = Half-Yearly 5 = Yearly *Pass “2” for monthly frequency. |
Desc | Varchar (100) | M | Deskripsi produk. |
CC_Ic | Varchar (50) | M | IC pemegang kartu kredit atau nomor paspor. |
CC_Email | Varchar (255) | M | Alamat email pemegang kartu kredit. |
CC_Phone | Varchar (100) | M | Nomor kontak pemegang kartu kredit. |
P_Name | Varchar (100) | M | Nama subscriber yang tertulis pada kartu identitas (KTP) atau passpor. |
P_Email | Varchar (255) | M | Alamat email subscriber. |
P_Phone | Varchar (100) | M | Nomor kontak subscriber. |
P_Addr|1 | Varchar (100) | M | Alamat baris pertama subscriber. |
P_Addr|2 | Varchar (100) | O | Alamat baris kedua subscriber. |
P_City | Varchar (100) | M | Kota subscriber. |
P_State | Varchar (100) | M | Provinsi subscriber. |
P_Zip | Varchar (100) | M | Kode pos subscriber. |
P_Country | Varchar (100) | M | Negara subscriber. |
Signature | String (100) | M | SHA signature. |
ResponseURL | String (200) | M | Payment response page. |
BackendURL | String (200) | M | Backend response page URL. |
Keterangan:
M: Mandatory (diharuskan).
O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
Subscription Response Parameters
iPay88 Indonesia mengirimkan parameter melalui HTTPS POST sebagai subscription response kepada merchant.
|
|
|
|
---|---|---|---|
MerchantCode | Varchar (20) | M | Merchant Code disediakan oleh iPay88 dan digunakan untuk mengidentifikasi merchant. |
RefNo | Varchar (20) | M | Nomor unik transaksi merchant atau Order ID. |
SubscriptionNo | Varchar (20) | M | Unique iPay88 subscription number. Note: SubscriptionNo sebagai RefNo yang dikirim kembali kepada merchant melalui BackendURL ketika recurring payment telah sukses. Contoh S00001701. |
FirstPaymentDate | Datetime | M | Tanggal pembayaran pertama (DDMMYYYY). |
Currency | Varchar (3) | M | Hanya IDR. |
Amount | Currency | M | Total diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp1.278,00 diekspresikan menjadi 127800. |
NumberofPayments | Int (10) | M | Subscription cycle. Contoh 12. |
Frequency | Int (10) | M | Tipe frekuensi: 1 = Weekly 2 = Monthly 3 = Quarterly 4 = Half-Yearly 5 = Yearly *Pass “2” for monthly frequency |
TransId | Varchar (30) | O | iPay88 transaction ID. |
AuthCode | Varchar (10) | O | Kode konfirmasi bank. |
Desc | Varchar (100) | M | Deskripsi subscription. |
Status | Varchar (2) | M | Subscription status. '00' - Success. '01' - Fail. |
ErrDesc | Varchar (100) | M | Error deskripsi. |
Keterangan:
M: Mandatory (diharuskan).
O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
Termination Request Parameters
Merchant mengirimkan parameter melalui HTTPS POST sebagai termination request kepada iPay88 Indonesia.
|
|
|
|
---|---|---|---|
MerchantCode | Varchar (20) | M | Merchant Code disediakan oleh iPay88 dan digunakan untuk mengidentifikasi merchant. |
RefNo | Varchar (20) | M | Nomor unik transaksi merchant atau Order ID yang dikirim oleh merchant sebagai penanda untuk subscription request. |
Signature | String (100) | M | SHA signature. |
Keterangan:
M: Mandatory (diharuskan).
O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
Termination Response Parameters
iPay88 Indonesia mengirimkan parameter melalui HTTPS POST sebagai termination response kepada merchant.
|
|
|
|
---|---|---|---|
MerchantCode | Varchar (20) | M | Merchant Code disediakan oleh iPay88 dan digunakan untuk mengidentifikasi merchant. |
RefNo | Varchar (20) | M | Nomor unik transaksi merchant atau Order ID. |
Status | Varchar (2) | M | Subscription status. '00' - Success. '01' - Fail. |
ErrDesc | Varchar (100) | M | Error deskripsi. |
Keterangan:
M: Mandatory (diharuskan).
O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
**Gunakan XML parser untuk to mendapatkan termination response kembali.
Backend URL Response Parameters
Fitur pada backend post ini akan dikirim oleh iPay88 Indonesia kepada merchant jika proses recurring payment pelanggan Anda telah dinyatakan sukses. Fitur ini tidak berlaku jika proses pembayaran dinyatakan gagal.
Implementasi
Pada situs merchant, Anda harus membuat sebuah laman yang dapat
menerima response paramenets yang disebutkan dibawah. Contoh laman: http://www.abc.com/backend_response.asp
Di laman subscription request, Anda dapat memberi spesifikasi backend post URL melalui BackendURL parameter. Contoh: <input name = "BackendURL" value = "http://www.abc.com/backend_response">
Di laman backend_response Anda harus menulis kata "RECEIVEOK" saja (tanpa petik) jika laman backend sukses atau berhasil mendapatkan balikan status dari iPay88 Indonesia. Jika tidak, iPay88 Indonesia akan mengirim status ke laman backend merchant sebanyak 3 kali dalam tempo yang berbeda.
Contoh:
Di ASP >> response.write "RECEIVEOK"
Di PHP >> echo "RECEIVEOK";
Catatan: Pastikan hanya kata 'RECEIVEOK' tanpa tag HTML apa pun.
|
|
|
|
---|---|---|---|
MerchantCode | String (20) | M | Merchant Code disediakan oleh iPay88 dan digunakan untuk mengidentifikasi merchant. |
PaymentId | Integer | O | Payment ID untuk metode pembayaran yang dituju. |
RefNo | Varchar (20) | M | Nomor unik transaksi untuk recurring payment yang dikembalikan oleh iPay88.
Contoh: S00001701-1 (first recurring payment). S00001701-2 (second recurring payment). Catatan: Refno ini adalah SubscriptionNo yang dikembalikan ke merchant setelah selesai tahap register recurring payment. Pengembalian RefNo akan memiliki tanda hubung (-) diikuti oleh 1 atau 2 untuk menunjukkan cicilan keberapa. |
RecurringRefno | Varchar (20) | M | Nomor unik transaksi merchant atau Order ID. Catatan: nilai yang dikembalikan melalui RecurringRefno adalah RefNo yang dikirimkan oleh merchant. |
Amount | Currency | M | Total diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp1.278,00 diekspresikan menjadi 127800. |
Currency | Varchar (5) | M | Hanya IDR. |
Remark | Varchar (100) | O | Catatan merchant. |
TransId | Varchar (30) | O | iPay88 OPSG ID Transaksi. |
AuthCode | Varchar (20) | O | Kode persetujuan bank. |
Status | Varchar (1) | M |
Status pembayaran
"1" – Success. "0" – Fail. |
ErrDesc | Varchar (100) | O | Deskripsi penyebab gagal-nya transaksi. |
Signature | Varchar (100) | M | SHA1 Signature. |
Keterangan:
M: Mandatory (diharuskan).
O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
<%
MerchantCode = Request.Form("MerchantCode")
PaymentId = Request.Form("PaymentId")
RefNo = Request.Form("RefNo")
RecurringRefno = Request.Form("RecurringRefno")
Amount = Request.Form("Amount")
eCurrency = Request.Form("Currency")
Remark = Request.Form("Remark")
TransId = Request.Form("TransId")
AuthCode = Request.Form("AuthCode")
eStatus = Request.Form("Status")
ErrDesc = Request.Form("ErrDesc")
Signature = Request.Form("Signature")
%>
<Add your programming code here>
<?php
$merchantcode = $_REQUEST["MerchantCode"];
$paymentid = $_REQUEST["PaymentId"];
$refno = $_REQUEST["RefNo"];
$RecurringRefno = $_REQUEST["RecurringRefno"];
$amount = $_REQUEST["Amount"];
$ecurrency = $_REQUEST["Currency"];
$remark = $_REQUEST["Remark"];
$transid = $_REQUEST["TransId"];
$authcode = $_REQUEST["AuthCode"];
$estatus = $_REQUEST["Status"];
$errdesc = $_REQUEST["ErrDesc"];
$signature = $_REQUEST["Signature"];
?>
//Add your programming code here
Kontrol Keamanan
Untuk meningkatkan keamanan, silahkan ikuti langkah-langkah berikut di laman penerimaan status pembayaran merchant (Response URL).
- Periksa nilai HTTP_REFERER dari https://payment.ipay88.co.id (hanya berlaku jika situs web merchant berfungsi dengan Sertifikat SSL).
- Periksa jumlah pembayaran dari iPay88 Indonesia sesuai dengan pelanggan Anda.
- Bandingkan signature dari iPay88 Indonesia dengan signature yang Anda hasilkan sendiri.
Integritas Data dan Keamanan menggunakan Signature Acak
Pengacakan SHA1 adalah fitur keamanan yang memungkinkan skrip Anda untuk mengidentifikasi hasil transaksi sebenarnya dari sumber otorisasi yang sesuai. Bagi iPay88 Indonesia, fitur ini berguna untuk memastikan integritas data yang diterima pada setiap request transaksi dari merchant.
Menggunakan algoritma SHA1, signature atau fingerprint dari transaksi dapat dihasilkan. Algoritma matematika yang digunakan untuk membangun signature ini dirancang sedemikian rupa sehingga setiap adanya perubahan pada informasi yang digunakan dalam perhitungan akan menghasilkan signature yang berbeda pula.
Informasi yang digunakan dalam perhitungan signature tidak dapat diketahui walau dengan menganalisa signature itu sendiri. Signature dihasilkan dengan menggunakan informasi dari akun Anda sebagai merchant. Setiap transaksi yang diproses melalui sistem memiliki pengacakan signature tersendiri yang berkaitan dengan transaksi tersebut.
Subscription Request Page Signature
Signature harus disertakan pada proses request laman pembayaran iPay88 Indonesia disetiap transaksi merchant. Signature tersebut adalah hasil dari pengacakan delapan bidang utama berikut.
- MerchantCode
- MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 Indonesia)
- RefNo
- Firstpaymentdate
- Currency
- Amount
- NumberofPayments
- Frequency
Field harus tersusun mengikuti aturan berikut:
MerchantCode & MerchantKey & RefNo & Firstpaymentdate
& Currency & Amount & NumberofPayments & Frequency
Contoh:
MerchantCode | = | "M00003" |
MerchantKey | = | "apple" |
RefNo | = | "A00000001" |
Firstpaymentdate | = | "11112013" |
Currency | = | "IDR" |
Amount | = | "100" (catatan: 100 adalah representasi dari total Rp1,00) |
NumberOfPayments | = | "12" |
Frequency | = | "1" |
Pengacakan akan dihitung melalui string berikut:
M00003appleA0000000111112013IDR100121
Hasil signature (menggunakan algoritma SHA1) adalah:
eR9amDNDKTzlX3sE8ZTgx5lFZ8M=
Untuk memastikan signature yang dihasilkan sudah benar, silahkan klik tautan ini untuk perbandingan signature.
Public Shared Function ComputeHas(ByVal Key As String)
Dim objSHA1 As New SHA1CryptoServicesProvider()
objSHA1.ComputeHas(system.Text.Encoding.UTF8.GetBytes(Key.ToCharArray))
Dim buffer() As Byte = objSHA1.Hash
DIm HashValue As String = System.Convert.ToBase64String(buffer)
Return HashValue
End Function
<?php
function iPay88_signature($source)
{
return base64_encode(hex2bin(sha1($source)));
}
function hex2bin($hexSource)
{
for ($i=0;$i<strlen($hexSource);$i=$i+2)
{
$bin .= chr(hexdec(substr($hexSource,$i,2)));
}
return $bin;
}
?>
import java.security.*;
import sun.misc.BASE64Encoder;
import java.io.*;
public class test
{
public static String encrypt(String password)
{
MessageDigest md;
try
{
md = MessageDigest.getInstance("SHA");
md.update(password.getBytes("UTF-8"));
byte raw[] = md.digest();
String hash = (new BASE64Encoder()).encode(raw);
return hash;
}
catch (NoSuchAlgorithmException e)
{
}
catch (java.io.UnsupportedEncodingException e)
{
}
return null;
}
public static void main(String[] args)
{
System.out.println(encrypt("my password"));
// string to hash is here
}
}
<script language="javascript" type="text/javascript"
src="sha1.js"></script>
<script language="javascript">
document.write(iPay88Signature("d3kdhKeH93M00045A00257110800MYR")); //sample signature
</script>
sha1.js file
var hexcase = 0;
/* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = "";
/* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8;
/* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function iPay88Signature(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz))+"=";}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
/*
* Perform a simple self-test to see if the VM is working
*/
function sha1_vm_test()
{
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1(key, data)
{
var bkey = str2binb(key);
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
return core_sha1(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
return bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
return str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
Termination Request Page Signature
Signature harus disertakan pada proses request laman pembayaran iPay88 Indonesia disetiap transaksi merchant. Signature tersebut adalah hasil dari pengacakan tiga bidang utama berikut.
- MerchantCode
- MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 Indonesia)
- RefNo
Field harus tersusun mengikuti aturan berikut:
MerchantCode & MerchantKey & RefNo
Contoh:
MerchantCode | = | "M00003" |
MerchantKey | = | "apple" |
RefNo | = | "A00000001" |
Pengacakan akan dihitung melalui string berikut:
M00003appleA00000001
Hasil signature (menggunakan algoritma SHA1) adalah:
4d3NplZBQx8cdm/b5sHZ2exSTS8=
Untuk memastikan signature yang dihasilkan sudah benar, silahkan klik tautan ini untuk perbandingan signature.
Public Shared Function ComputeHas(ByVal Key As String)
Dim objSHA1 As New SHA1CryptoServicesProvider()
objSHA1.ComputeHas(system.Text.Encoding.UTF8.GetBytes(Key.ToCharArray))
Dim buffer() As Byte = objSHA1.Hash
DIm HashValue As String = System.Convert.ToBase64String(buffer)
Return HashValue
End Function
<?php
function iPay88_signature($source)
{
return base64_encode(hex2bin(sha1($source)));
}
function hex2bin($hexSource)
{
for ($i=0;$i<strlen($hexSource);$i=$i+2)
{
$bin .= chr(hexdec(substr($hexSource,$i,2)));
}
return $bin;
}
?>
import java.security.*;
import sun.misc.BASE64Encoder;
import java.io.*;
public class test
{
public static String encrypt(String password)
{
MessageDigest md;
try
{
md = MessageDigest.getInstance("SHA");
md.update(password.getBytes("UTF-8"));
byte raw[] = md.digest();
String hash = (new BASE64Encoder()).encode(raw);
return hash;
}
catch (NoSuchAlgorithmException e)
{
}
catch (java.io.UnsupportedEncodingException e)
{
}
return null;
}
public static void main(String[] args)
{
System.out.println(encrypt("my password"));
// string to hash is here
}
}
<script language="javascript" type="text/javascript"
src="sha1.js"></script>
<script language="javascript">
document.write(iPay88Signature("d3kdhKeH93M00045A00257110800MYR")); //sample signature
</script>
sha1.js file
var hexcase = 0;
/* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = "";
/* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8;
/* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function iPay88Signature(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz))+"=";}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
/*
* Perform a simple self-test to see if the VM is working
*/
function sha1_vm_test()
{
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1(key, data)
{
var bkey = str2binb(key);
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
return core_sha1(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
return bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
return str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
Backend URL Signature
Jika transaksi yang dilakukan merchant telah berhasil, merchant diharuskan membuat signature untuk faktor keamanan data disetiap transaksi merchant. Signature tersebut adalah hasil dari pengacakan tujuh bidang utama berikut.
- MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 Indonesia)
- MerchantCode
- PaymentId
- RefNo
- Amount
- Currency
- Status
Field harus tersusun mengikuti aturan berikut:
MerchantKey & MerchantCode & PaymentId & RefNo &
Amount & Currency & Status
Contoh:
MerchantKey | = | "apple" |
MerchantCode | = | "M00003" |
PaymentId | = | "2" |
RefNo | = | "S00001701-1" |
Amount | = | "100" (catatan: 100 adalah representasi dari total Rp1,00) |
Currency | = | "IDR" |
Status | = | "1" |
Pengacakan akan dihitung melalui string berikut:
appleM000032S00001701-1100IDR1
Hasil signature (menggunakan algoritma SHA1) adalah:
kX7Icxcj2TtCbSL/wWw5haKaU4A=
Untuk memastikan signature yang dihasilkan sudah benar, silahkan klik tautan ini untuk perbandingan signature.
Ketika iPay88 Indonesia menerima request atau transaksi dari merchant, iPay88 Indonesia akan memeriksa nilai acak signature yang dihasilkan untuk dicocokkan dengan nilai signature yang merchant kirim. Ketika sistem merchant menerima hasil transaksi, merchant dapat membuat signature dan pastikan sama dengan signature yang dikirim balik oleh iPay88 Indonesia. Merchant akan mendapatkan signature di laman response jika transaksi tidak error (tidak termasuk transaksi yang disetujui atau ditolak).
Setelah merchant menerima informasi dari iPay88 Indonesia terkait status pembayaran dari transaksi, merchant harus menjalanakan algoritma acak pada tujuh bidang utama yg telah disebutkan diatas sehingga menghasilkan suatu signature. Merchant wajib mencocokkan hasil signature merchant dengan signature iPay88 Indonesia. Dapat dipastikan jika signature yang dihasilkan merchant saat proses request dan dikirim ke iPay88 Indonesia, maka transaksi merchant telah diproses oleh sistem iPay88 Indonesia.
Merchant key dibuat oleh iPay88 Indonesia untuk merchant. Merchant key bersifat rahasia bersama (antara merchant dan iPay88 Indonesia), dan merupakan salah satu bagian kunci informasi untuk proses pengacakan signature. Merchant key akan dibuat ulang jika iPay88 Indonesia mencurigai bahwa merchant key sudah tidak aman atau terjadi kasus penipuan. Informasi lebih lanjut tentang algoritma acak SHA1, termasuk sampel kode untuk implementasi dapat ditemukan di RFC 3174 dalam laman Task Force Internet Engineering.
Public Shared Function ComputeHas(ByVal Key As String)
Dim objSHA1 As New SHA1CryptoServicesProvider()
objSHA1.ComputeHas(system.Text.Encoding.UTF8.GetBytes(Key.ToCharArray))
Dim buffer() As Byte = objSHA1.Hash
DIm HashValue As String = System.Convert.ToBase64String(buffer)
Return HashValue
End Function
<?php
function iPay88_signature($source)
{
return base64_encode(hex2bin(sha1($source)));
}
function hex2bin($hexSource)
{
for ($i=0;$i<strlen($hexSource);$i=$i+2)
{
$bin .= chr(hexdec(substr($hexSource,$i,2)));
}
return $bin;
}
?>
import java.security.*;
import sun.misc.BASE64Encoder;
import java.io.*;
public class test
{
public static String encrypt(String password)
{
MessageDigest md;
try
{
md = MessageDigest.getInstance("SHA");
md.update(password.getBytes("UTF-8"));
byte raw[] = md.digest();
String hash = (new BASE64Encoder()).encode(raw);
return hash;
}
catch (NoSuchAlgorithmException e)
{
}
catch (java.io.UnsupportedEncodingException e)
{
}
return null;
}
public static void main(String[] args)
{
System.out.println(encrypt("my password"));
// string to hash is here
}
}
<script language="javascript" type="text/javascript"
src="sha1.js"></script>
<script language="javascript">
document.write(iPay88Signature("d3kdhKeH93M00045A00257110800MYR")); //sample signature
</script>
sha1.js file
var hexcase = 0;
/* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = "";
/* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8;
/* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function iPay88Signature(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz))+"=";}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
/*
* Perform a simple self-test to see if the VM is working
*/
function sha1_vm_test()
{
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1(key, data)
{
var bkey = str2binb(key);
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
return core_sha1(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
return bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
return str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
Sampel Email
Berikut adalah sampel email yang akan dikirimkan kepada pelanggan Anda.
Recurring Berhasil Ditagih
Berikut ini adalah sampel email jika proses recurring telah berhasil.

Recurring Gagal Ditagih
Berikut ini adalah sampel email jika proses recurring gagal.

Seamless Payment Versi 1.0.5
Segera integrasikan iPay88 Seamless Payment ini dengan platform online bisnis Anda. API ini menjadikan situs Anda dapat menerima pembayaran melalui Online Credit seperti Kredivo, Indodana, dan Akulaku.
Download iPay88 Seamless Payment
Objektif
Merchant dapat menyediakan metode pembayaran Kredivo, Indodana, dan Akulaku secara full payment maupun cicilan kepada pelanggan dengan metode JavaScript Object Notation (JSON) melalui iPay88 Indonesia.
Proses Transaksi
Berikut ini adalah diagram alir transaksi merchant dengan iPay88 Indonesia.

Payment Request
Berikut ini adalah parameter yang digunakan untuk proses request dengan iPay88 Indonesia.
URL Request
- Development:
https://sandbox.ipay88.co.id/ePayment/WebService/PaymentAPI/Checkout - Production:
https://payment.ipay88.co.id/ePayment/WebService/PaymentAPI/Checkout
Request Format
Merchant mengirimkan parameter melalui JSON sebagai request kepada iPay88 Indonesia. Merchant diharuskan untuk melakukan pengacakan pada signature.
|
|
|
|
|
---|---|---|---|---|
1 | MerchantCode | Varchar (20) | M | Merchant Code disediakan oleh iPay88 dan digunakan untuk mengidentifikasi merchant. |
2 | PaymentId | Integer | M | Payment ID 55 untuk untuk metode pembayaran Kredivo, 70 untuk metode pembayaran Indodana, dan 71 untuk metode pembayaran Akulaku. |
3 | Currency | Varchar (5) | M | Hanya IDR. |
4 | RefNo | Varchar (20) | M | Nomor unik transaksi merchant atau Order ID. |
5 | Amount | Integer | M | Total diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp1.278,00 diekspresikan menjadi 127800. Total adalah jumlah yang harus dibayar secara keseluruhan. |
6 | ProdDesc | Varchar (100) | M | Deskripsi produk. |
7 | UserName | Varchar (100) | M | Nama pelanggan. |
8 | UserEmail | Varchar (100) | M | Email pelanggan untuk mendapatkan nota pembayaran. |
9 | UserContact | Varchar (20) | M | Nomor kontak pelanggan. |
10 | Remark | Varchar (100) | O | Catatan merchant. |
11 | Lang | Varchar (20) | O |
Encoding type
"ISO-8859-1" – English. "UTF-8" – Unicode. "GB2312" – Chinese Simplified. "GD18030" – Chinese Simplified. "BIG5" – Chinese Traditionl. |
12 | ResponseURL | Varchar (200) | M | Payment response page. Contoh https://ipay88-store.com/response. |
13 | BackendURL | Varchar (200) | M | Backend response page URL. Contoh https://ipay88-store.com/backend. |
14 | Signature | Varchar (100) | M | SHA signature (merujuk ke 3.1). |
15 | xfield1 | Varchar (20) | O | Parameter ini hanya berlaku untuk metode pembayaran kartu kredit dengan fitur cicilan dan diskon. |
16 | itemTransaction | List (n) | M | Daftar produk yang dipesan oleh pelanggan. |
16.1 | Id | Varchar (50) | M | ID produk yang dipesan. |
16.2 | Name | Varchar (100) | M | Nama produk yang dipesan. |
16.3 | Quantity | Integer | M | Kuantitas produk yang dipesan. |
16.4 | Amount | Integer | M | Harga produk dikalikan dengan jumlah kuantitas. Total diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp1.278,00 diekspresikan menjadi 127800. |
16.5 | Type | Varchar (100) | M | Tipe produk yang dipesan. Khusus taxfee, shippingfee, dan discount tidak perlu mencantumkan parameter ini. |
16.6 | Url | Varchar (100) | M | Url produk yang dipesan. Khusus taxfee, shippingfee, dan discount tidak perlu mencantumkan parameter ini. |
16.7 | ImageUrl | Varchar (100) | O | Url gambar produk yang dipesan. Khusus taxfee, shippingfee, dan discount tidak perlu mencantumkan parameter ini. |
16.8 | ParentType | Varchar (100) | M | Parameter ini dapat diisi dengan Seller atau Item. |
16.9 | ParentId | Varchar (100) | M | Parameter ini dapat diisi dengan Seller ID jika parameter ParentType berisi Seller atau diisi dengan Item ID jika parameter ParentType berisi Item. |
17 | ShippingAddress | List (n) | M | Daftar alamat pengiriman produk. |
17.1 | FirstName | Varchar (100) | M | Nama awal yang tertuju untuk alamat pengiriman produk. |
17.2 | LastName | Varchar (100) | M | Nama akhir yang tertuju untuk alamat pengiriman produk. |
17.3 | Address | Varchar (100) | M | Alamat yang tertuju untuk pengiriman produk. |
17.4 | City | Varchar (100) | M | Kota yang tertuju untuk alamat pengiriman produk. |
17.5 | PostalCode | Varchar (6) | M | Kode pos yang tertuju untuk alamat pengiriman produk. |
17.6 | Phone | Varchar (20) | M | Nomor telepon yang tertuju untuk alamat pengiriman produk. |
17.7 | CountryCode | Varchar (3) | M | Kode negara yang tertuju untuk alamat pengiriman produk. Contoh ID untuk Indonesia. |
18 | BillingAddress | List (n) | M | Daftar alamat pengiriman produk. |
18.1 | FirstName | Varchar (100) | M | Nama awal yang tertuju untuk alamat pengiriman produk. |
18.2 | LastName | Varchar (100) | M | Nama akhir yang tertuju untuk alamat pengiriman produk. |
18.3 | Address | Varchar (100) | M | Alamat yang tertuju untuk pengiriman produk. |
18.4 | City | Varchar (100) | M | Kota yang tertuju untuk alamat pengiriman produk. |
18.5 | PostalCode | Varchar (6) | M | Kode pos yang tertuju untuk alamat pengiriman produk. |
18.6 | Phone | Varchar (20) | M | Nomor telepon yang tertuju untuk alamat pengiriman produk. |
18.7 | CountryCode | Varchar (3) | M | Kode negara yang tertuju untuk alamat pengiriman produk. Contoh ID untuk Indonesia. |
19 | Sellers | List (n) | M | Daftar informasi Seller. |
19.1 | Id | Varchar (100) | M | Seller ID. |
19.2 | Name | Varchar (100) | M | Nama Seller. |
19.3 | Url | Varchar (100) | M | Url Seller. |
19.4 | SerialIdNumber | Varchar (100) | M | Nomor tanda pengenal Seller seperti KTP, SIM, dan sebagainya. |
19.5 | Varchar (100) | M | Alamat email Seller. | |
19.6 | Address | List(n) | M | Daftar informasi toko Seller. |
19.6.1 | FirstName | Varchar (100) | M | Nama awal toko Seller. |
19.6.2 | LastName | Varchar (100) | M | Nama akhir toko Seller. |
19.6.3 | Address | Varchar (100) | M | Alamat Seller. |
19.6.4 | City | Varchar (100) | M | Kota yang tertuju pada alamat toko Seller. |
19.6.5 | PostalCode | Varchar (6) | M | Kode pos yang tertuju pada alamat toko Seller. |
19.6.6 | Phone | Varchar (20) | M | Nomor telepon toko Seller. |
19.6.7 | CountryCode | Varchar (3) | M | Kode negara yang tertuju pada alamat toko Seller. |
Keterangan:
M: Mandatory (diharuskan).
O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
{
"MerchantCode" : "your-merchant-code",
"PaymentId" : "71",
"Currency" : "IDR",
"RefNo" : "88",
"Amount" : "6500000",
"ProdDesc" : "Souvenir 1, Souvenir 2",
"UserName" : "Your Customer Name",
"UserEmail" : "your.customer.email.@ipay88.co.id",
"UserContact" : "08788888888",
"Remark" : "Transaction 2018-03-26 17:12:55",
"Lang" : "UTF-8",
"ResponseURL" : "https://your-site/ipay88-response",
"BackendURL" : "https://your-site/ipay88-backend",
"Signature" : "SrhVUhH2IboZYrGhfqJ01Qx0clM=",
"xfield1" : "",
"itemTransactions":
[{
"Id" : "88",
"Name" : "Souvenir 1",
"Quantity" : "2",
"Amount" : "1000000",
"Type" : "Product 88",
"Url" : "https://your-site/product-id=88",
"ImageUrl" : "https://your-site/product-id=88/image.png",
"ParentType" : "SELLER",
"ParentId" : "SELLER88"
},
{
"Id" : "89",
"Name" : "Souvenir 1",
"Quantity" : "1",
"Amount" : "2000000",
"Type" : "Product 89",
"Url" : "https://your-site/product-id=89",
"ImageUrl" : "https://your-site/product-id=88/image.png",
"ParentType" : "SELLER",
"ParentId" : "SELLER88"
},
{
"Id" : "shippingfee",
"Name" : "Shipping Fee",
"Quantity" : "1",
"Amount" : "2500000",
"Type" : null,
"Url" : null,
"ImageUrl" : null,
"ParentType" : null,
"ParentId" : null
},
{
"Id" : "taxfee",
"Name" : "Tax Fee",
"Quantity" : "1",
"Amount" : "1500000",
"Type" : null,
"Url" : null,
"ImageUrl" : null,
"ParentType" : null,
"ParentId" : null
},
{
"Id" : "discount",
"Name" : "Discount",
"Quantity" : "1",
"Amount" : "500000",
"Type" : null,
"Url" : null,
"ImageUrl" : null,
"ParentType" : null,
"ParentId" : null
}],
"ShippingAddress":
{
"FirstName" : "Customer recipient first name",
"LastName" : "Customer recipient last name",
"Address" : "Jl. Letjen S. Parman No.22-24",
"City" : "Jakarta Barat",
"PostalCode" : "11480",
"Phone" : "08788888888",
"CountryCode" : "ID"
},
"BillingAddress":
{
"FirstName" : "Customer first name",
"LastName" : "Customer last name",
"Address" : "Jl. Letjen S. Parman No.22-24",
"City" : "Jakarta Barat",
"PostalCode" : "11480",
"Phone" : "08788888888",
"CountryCode" : "ID"
},
"Sellers":
[{
"Id" : "your-seller-id",
"Name" : "Your Seller Name",
"Url" : "https://your-seller-site",
"SellerIdNumber" : "your-seller-id-number",
"Email" : "seller@ipay88.co.id",
"address":
{
"FirstName" : "Seller first name",
"LastName" : "Seller last name",
"Address" : "Jl. Letjen S. Parman No.22-24",
"City" : "Jakarta Barat",
"PostalCode" : "11480",
"Phone" : "08788888888",
"CountryCode" : "ID"
}
}],
}
Response Format
iPay88 Indonesia akan mengirimkan parameter melalui JSON sebagai response kepada merchant. Merchant diharuskan melakukan perbandingan terhadap signature yang dikirim oleh iPay88 Indonesia dengan hasil pengacakan yang dilakukan oleh Merchant sendiri.
|
|
|
|
|
---|---|---|---|---|
1 | MerchantCode | Varchar (20) | M | Merchant Code disediakan oleh iPay88 dan digunakan untuk mengidentifikasi merchant. |
2 | PaymentId | Integer | M | Payment ID 55 untuk untuk metode pembayaran Kredivo, 70 untuk metode pembayaran Indodana, dan 71 untuk metode pembayaran Akulaku. |
3 | RefNo | Varchar (20) | M | Nomor unik transaksi merchant atau Order ID. |
4 | Amount | Integer | M | Total diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp1.278,00 diekspresikan menjadi 127800. |
5 | Currency | Varchar (5) | M | Hanya IDR. |
6 | Remark | Varchar (100) | O | Catatan merchant. |
7 | TransId | Varchar (30) | O | iPay88 OPSG ID Transaksi. |
8 | AuthCode | Varchar (20) | M | Kode persetujuan Bank. |
9 | Status | Varchar (1) | M |
Status pembayaran
"0" – Fail. "6" – Pending. |
10 | ErrDesc | Varchar (100) | O | Deskripsi penyebab gagal-nya transaksi (lihat referensi). |
11 | Signature | Varchar (100) | M | SHA signature (merujuk ke 3.1). |
12 | CheckoutURL | Varchar (100) | M | URL untuk redirect ke laman pembayaran iPay88 Indonesia. |
13 | xfield1 | Varchar (20) | O | Parameter ini hanya berlaku untuk metode pembayaran kartu kredit dengan fitur cicilan dan diskon. |
Keterangan:
M: Mandatory (diharuskan).
O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
{
"MerchantCode" : "ID00001",
"PaymentId" : "71",
"RefNo" : "720201745653AM",
"Amount" : "100000000",
"Currency" : "IDR",
"Remark" : "",
"TransId" : "T0027546100",
"AuthCode" : "",
"Status" : "6",
"ErrDesc" : "",
"Signature" : "lkvo2Xuy7BImSfMoTBznJSUOEC8=",
"CheckoutURL" : "https://sandbox.ipay88.co.id/epayment/entry.asp?CheckoutID=5F822C024A102470C16A762C19EA29D7879A47B2EFF7C4151E309F00EDEADC6F&Signature=Nv2ub5JULwXf1X2x7B9CLe3z7K4%3d",
"xfield1" : "",
}
Checkout URL
Setelah Merchant mendapatkan data response yang dikirimkan oleh iPay88 Indonesia, langkah selanjutnya adalah membandingkan hasil signature. Jika nilai signature sama, maka merchant harus redirect ke laman pembayaran iPay88 Indonesia melalui parameter CheckoutURL.
window.location.replace("https://sandbox.ipay88.co.id/epayment/entry.asp?CheckoutID=5F822C024A102470C16A762C19EA29D7879A47B2EFF7C4151E309F00EDEADC6F&Signature=Nv2ub5JULwXf1X2x7B9CLe3z7K4%3d");
<?php
$checkout = 'https://sandbox.ipay88.co.id/epayment/entry.asp?CheckoutID=5F822C024A102470C16A762C19EA29D7879A47B2EFF7C4151E309F00EDEADC6F&Signature=Nv2ub5JULwXf1X2x7B9CLe3z7K4%3d';
$load_file_function = '<script language="JavaScript"> $(document).ready(function(){ document.ipay88_request_paramaters.submit();});</script>';
echo $load_file_function;
echo "<form name='ipay88_request_paramaters' ACTION='".$checkout."' method='POST'>";
echo "</form>";
?>
Payment Response
Berikut ini adalah parameter yang digunakan ketika mendapatkan response dari iPay88 Indonesia.
Response Format
Berikut ini adalah respon dengan HTTPS POST dari iPay88 Indonesia ke merchant setelah selesai proses pembayaran.
|
|
|
|
---|---|---|---|
MerchantCode | Varchar (20) | M | Merchant Code disediakan oleh iPay88 dan digunakan untuk mengidentifikasi merchant. |
PaymentId | Integer | O | Lihat referensi. |
RefNo | Varchar (20) | M | Nomor unik transaksi merchant atau Order ID. |
Amount | Integer | M | Total diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp1.278,00 diekspresikan menjadi 127800. |
Currency | Varchar (5) | M | Harus IDR. |
Remark | Varchar (100) | O | Catatan merchant. |
TransId | Varchar (30) | O | iPay88 OPSG ID Transaksi. |
AuthCode | Varchar (20) | O | Kode persetujuan bank. |
Status | Varchar (1) | M |
Status pembayaran
"1" – Success. "0" – Fail. |
ErrDesc | Varchar (100) | O | Deskripsi penyebab gagal-nya transaksi (lihat referensi). |
Signature | Varchar (100) | M | SHA1 Signature (merujuk ke 3.2). |
xfield1 | Varchar (20) | O | Parameter ini hanya berlaku untuk metode pembayaran kartu kredit dengan fitur cicilan dan diskon. |
Keterangan:
M: Mandatory (diharuskan).
O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
<%
MerchantCode = Request.Form("MerchantCode")
PaymentId = Request.Form("PaymentId")
RefNo = Request.Form("RefNo")
Amount = Request.Form("Amount")
eCurrency = Request.Form("Currency")
Remark = Request.Form("Remark")
TransId = Request.Form("TransId")
AuthCode = Request.Form("AuthCode")
eStatus = Request.Form("Status")
ErrDesc = Request.Form("ErrDesc")
Signature = Request.Form("Signature")
%>
<Add your programming code here>
<?php
$merchantcode = $_REQUEST["MerchantCode"];
$paymentid = $_REQUEST["PaymentId"];
$refno = $_REQUEST["RefNo"];
$amount = $_REQUEST["Amount"];
$ecurrency = $_REQUEST["Currency"];
$remark = $_REQUEST["Remark"];
$transid = $_REQUEST["TransId"];
$authcode = $_REQUEST["AuthCode"];
$estatus = $_REQUEST["Status"];
$errdesc = $_REQUEST["ErrDesc"];
$signature = $_REQUEST["Signature"];
?>
//Add your programming code here
Backend Post Feature
Backend post feature adalah teknologi server ke server yang tidak bergantung pada web browser si pelanggan merchant. Fitur ini harus diimplementasikan di situs merchant. Tujuan fitur ini adalah untuk mendapatkan status pembayaran dari iPay88 OPSG. Merchant bisa mendapatkan status pembayaran melalui laman backend merchant. iPay88 OPSG dapat mengirim status pembayaran secara berulang walaupun laman respon merchant gagal mendapatkan status tersebut yang disebabkan oleh browser web ditutup, batas waktu koneksi internet, dan lain sebagainya.
Sistem manajemen konten yang telah mendukung fitur backend post melalui plugin iPay88 Indonesia.
Catatan
-
iPay88 OPSG hanya mengirim status pembayaran melalui laman backend merchant apabila status pembayaran pada transaksi merchant telah sukses. Jika status pembayaran gagal, maka iPay88 OPSG tidak akan mengirimkan status melalui laman backend merchant.
-
Laman backend merchant harus menerapkan beberapa pengecekan yang sama seperti laman response seperti pengecekan signature, dan lain sebagainya untuk mencegah tejadinya pembajakan pada sistem merchant.
-
laman backend merchant tidak boleh memiliki kode session sehingga sistem merchant masih dapat menerima status pembayaran dari iPay88 OPSG bahkan jika pelanggan telah keluar atau session telah berakhir.
-
Anda perlu melakukakan pemeriksaan untuk menentukan fungsi perubah status transaksi baik di "laman response" atau "laman backend" sehingga tidak terjadinya perubahan status transaksi lebih dari satu kali.
Note: Setelah iPay88 OPSG menerima informasi dari bank bahwa status pembayaran pada transaksi merchant telah suskes, iPay88 OPSG secara bersamaan akan mengirimkan status pembayaran tersebut ke "laman response" dan "laman backend" merchant.
-
Laman backend bukan sebagai pengganti laman response. Anda harus terus menggunakan laman response seperti biasa.
Implementasi
Pada situs merchant, buat laman lain sebagai backend untuk menerima parameter dari iPay88 OPSG. Parameter backend yang dikirim oleh iPay88 OPSG sama seperti parameter yang dikirim ke laman response merchant. Pada laman request merchant, tentukan url backend melalui parameter "BackendURL".
Sebagai contoh, <input name = "BackendURL" value = "http://www.abc.com/backend_response">
Pada laman 'backend_response' Anda perlu menuliskan kata 'RECEIVEOK' saja (tanpa tanda kutip) sebagai konfirmasi setelah laman backend berhasil mendapatkan status pembayaran dari iPay88 OPSG. Tentunya kata tersebut tertulis setelah dilakukan pengecekan seperti signature dan lain sebagainya di laman backend merchant. iPay88 OPSG akan mencoba mengirim kembali status pembayaran ke laman 'backend_response' hingga 5 kali pada interval yang berbeda jika tidak terdeteksi 'RECEVEIOK'.
Contoh:
Di ASP >> response.write "RECEIVEOK"
Di PHP >> echo "RECEIVEOK";
Catatan: Pastikan hanya kata 'RECEIVEOK' tanpa tag HTML apa pun.
Kontrol Keamanan
Untuk meningkatkan keamanan, silahkan ikuti langkah-langkah berikut di laman penerimaan status pembayaran merchant (Response URL).
- Periksa nilai HTTP_REFERER dari https://payment.ipay88.co.id (hanya berlaku jika situs web merchant berfungsi dengan Sertifikat SSL).
- Periksa jumlah pembayaran dari iPay88 OPSG sesuai dengan pelanggan Anda.
- Bandingkan signature dari iPay88 OPSG dengan signature yang Anda hasilkan sendiri.
Integritas Data dan Keamanan menggunakan Signature Acak
Pengacakan SHA1 adalah fitur keamanan yang memungkinkan skrip Anda untuk mengidentifikasi hasil transaksi sebenarnya dari sumber otorisasi yang sesuai. Bagi iPay88 OPSG, fitur ini berguna untuk memastikan integritas data yang diterima pada setiap request transaksi dari merchant.
Menggunakan algoritma SHA1, signature atau fingerprint dari transaksi dapat dihasilkan. Algoritma matematika yang digunakan untuk membangun signature ini dirancang sedemikian rupa sehingga setiap adanya perubahan pada informasi yang digunakan dalam perhitungan akan menghasilkan signature yang berbeda pula.
Informasi yang digunakan dalam perhitungan signature tidak dapat diketahui walau dengan menganalisa signature itu sendiri. Signature dihasilkan dengan menggunakan informasi dari akun Anda sebagai merchant. Setiap transaksi yang diproses melalui sistem memiliki pengacakan signature tersendiri yang berkaitan dengan transaksi tersebut.
Request Page Signature
Signature harus disertakan pada proses request laman pembayaran iPay88 OPSG disetiap transaksi merchant. Signature tersebut adalah hasil dari pengacakan lima bidang utama berikut.
- MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 OPSG)
- MerchantCode
- RefNo
- Amount
- Currency
Field harus tersusun mengikuti aturan berikut:
MerchantKey & MerchantCode & RefNo & Amount &
Currency
Contoh:
MerchantKey | = | "applekey" |
MerchantCode | = | "ID00001" |
RefNo | = | "A00000001" |
Amount | = | "300000" (catatan: 300000 adalah representasi dari total Rp3.000,00) |
Currency | = | "IDR" |
Pengacakan akan dihitung melalui string berikut:
applekeyID00001A00000001300000IDR
Hasil signature (menggunakan algoritma SHA1) adalah:
Q/iIMzpjZCrhJ2Yt2dor1PaFEFI=
Untuk memastikan signature yang dihasilkan sudah benar, silahkan klik tautan ini untuk perbandingan signature.
Public Shared Function ComputeHas(ByVal Key As String)
Dim objSHA1 As New SHA1CryptoServicesProvider()
objSHA1.ComputeHas(system.Text.Encoding.UTF8.GetBytes(Key.ToCharArray))
Dim buffer() As Byte = objSHA1.Hash
DIm HashValue As String = System.Convert.ToBase64String(buffer)
Return HashValue
End Function
<?php
function iPay88_signature($source)
{
return base64_encode(hex2bin(sha1($source)));
}
function hex2bin($hexSource)
{
for ($i=0;$i<strlen($hexSource);$i=$i+2)
{
$bin .= chr(hexdec(substr($hexSource,$i,2)));
}
return $bin;
}
?>
import java.security.*;
import sun.misc.BASE64Encoder;
import java.io.*;
public class test
{
public static String encrypt(String password)
{
MessageDigest md;
try
{
md = MessageDigest.getInstance("SHA");
md.update(password.getBytes("UTF-8"));
byte raw[] = md.digest();
String hash = (new BASE64Encoder()).encode(raw);
return hash;
}
catch (NoSuchAlgorithmException e)
{
}
catch (java.io.UnsupportedEncodingException e)
{
}
return null;
}
public static void main(String[] args)
{
System.out.println(encrypt("my password"));
// string to hash is here
}
}
<script language="javascript" type="text/javascript"
src="sha1.js"></script>
<script language="javascript">
document.write(iPay88Signature("d3kdhKeH93M00045A00257110800MYR")); //sample signature
</script>
sha1.js file
var hexcase = 0;
/* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = "";
/* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8;
/* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function iPay88Signature(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz))+"=";}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
/*
* Perform a simple self-test to see if the VM is working
*/
function sha1_vm_test()
{
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1(key, data)
{
var bkey = str2binb(key);
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
return core_sha1(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
return bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
return str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
Response Page Signature
Jika status pembayaran dari transaksi merchant dinyatakan sukses, iPay88 OPSG akan mengirim signature di laman response dan backend merchant. Signature ini harus dibandingkan dengan signature yang dihasilkan oleh merchant sendiri guna mengindari adanya pembajakan. Signature tersebut adalah hasil dari pengacakan tujuh bidang utama berikut.
- MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 OPSG)
- MerchantCode
- PaymentId
- RefNo
- Amount
- Currency
- Status
Field harus tersusun mengikuti aturan berikut:
MerchantKey & MerchantCode & PaymentId & RefNo &
Amount & Currency & Status
Contoh:
MerchantKey | = | "applekey" |
MerchantCode | = | "ID00001" |
PaymentId | = | "1" |
RefNo | = | "A00000001" |
Amount | = | "300000" (catatan: 300000 adalah representasi dari total Rp3.000,00) |
Currency | = | "IDR" |
Status | = | "1" |
Pengacakan akan dihitung melalui string berikut:
applekeyID000011A00000001300000IDR1
Hasil signature (menggunakan algoritma SHA1) adalah:
01sh+jPUL2wdqCcWJTgiuNuiiTI=
Untuk memastikan signature yang dihasilkan sudah benar, silahkan klik tautan ini untuk perbandingan signature.
Ketika iPay88 OPSG menerima request atau transaksi dari merchant, iPay88 OPSG akan memeriksa nilai acak signature yang dihasilkan untuk dicocokkan dengan nilai signature yang merchant kirim. Ketika sistem merchant menerima hasil transaksi, merchant dapat membuat signature dan pastikan sama dengan signature yang dikirim balik oleh iPay88 OPSG. Merchant akan mendapatkan signature di laman response jika transaksi tidak error (tidak termasuk transaksi yang disetujui atau ditolak).
Setelah merchant menerima informasi dari iPay88 OPSG terkait status pembayaran dari transaksi, merchant harus menjalanakan algoritma acak pada tujuh bidang utama yg telah disebutkan diatas sehingga menghasilkan suatu signature. Merchant wajib mencocokkan hasil signature merchant dengan signature iPay88 OPSG. Dapat dipastikan jika signature yang dihasilkan merchant saat proses request dan dikirim ke iPay88 OPSG, maka transaksi merchant telah diproses oleh sistem iPay88 OPSG.
Merchant key dibuat oleh iPay88 OPSG untuk merchant. Merchant key bersifat rahasia bersama (antara merchant dan iPay88 OPSG), dan merupakan salah satu bagian kunci informasi untuk proses pengacakan signature. Merchant key akan dibuat ulang jika iPay88 OPSG mencurigai bahwa merchant key sudah tidak aman atau terjadi kasus penipuan. Informasi lebih lanjut tentang algoritma acak SHA1, termasuk sampel kode untuk implementasi dapat ditemukan di RFC 3174 dalam laman Task Force Internet Engineering.
Public Shared Function ComputeHas(ByVal Key As String)
Dim objSHA1 As New SHA1CryptoServicesProvider()
objSHA1.ComputeHas(system.Text.Encoding.UTF8.GetBytes(Key.ToCharArray))
Dim buffer() As Byte = objSHA1.Hash
DIm HashValue As String = System.Convert.ToBase64String(buffer)
Return HashValue
End Function
<?php
function iPay88_signature($source)
{
return base64_encode(hex2bin(sha1($source)));
}
function hex2bin($hexSource)
{
for ($i=0;$i<strlen($hexSource);$i=$i+2)
{
$bin .= chr(hexdec(substr($hexSource,$i,2)));
}
return $bin;
}
?>
import java.security.*;
import sun.misc.BASE64Encoder;
import java.io.*;
public class test
{
public static String encrypt(String password)
{
MessageDigest md;
try
{
md = MessageDigest.getInstance("SHA");
md.update(password.getBytes("UTF-8"));
byte raw[] = md.digest();
String hash = (new BASE64Encoder()).encode(raw);
return hash;
}
catch (NoSuchAlgorithmException e)
{
}
catch (java.io.UnsupportedEncodingException e)
{
}
return null;
}
public static void main(String[] args)
{
System.out.println(encrypt("my password"));
// string to hash is here
}
}
<script language="javascript" type="text/javascript"
src="sha1.js"></script>
<script language="javascript">
document.write(iPay88Signature("d3kdhKeH93M00045A00257110800MYR")); //sample signature
</script>
sha1.js file
var hexcase = 0;
/* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = "";
/* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8;
/* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function iPay88Signature(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz))+"=";}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
/*
* Perform a simple self-test to see if the VM is working
*/
function sha1_vm_test()
{
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1(key, data)
{
var bkey = str2binb(key);
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
return core_sha1(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
return bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
return str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
Seamless Virtual Account versi 1.0.0
Segera integrasikan iPay88 Seamless Payment ini dengan platform online bisnis Anda. API ini menjadikan situs Anda dapat menerima pembayaran melalui Online Credit seperti Kredivo, Indodana, dan Akulaku.
Download iPay88 Seamless Virtual Account
BCA KlikPay Versi 1.7.3
Segera integrasikan iPay88 Technical Documentation untuk BCA KlikPay versi 1.7.3 ini dengan situs Anda. API ini menjadikan situs Anda untuk menerima pembayaran melalui online banking BCA KlikPay.
Download iPay88 - BCA KlikPay
Objektif
Merchant dapat menyediakan metode pembayaran online banking BCA KlikPay kepada pelanggan melalui iPay88 Indonesia.
Langkah Awal
Dokumentasi ini ditujukan untuk merchant yang ingin memiliki metode pembayaran online banking menggunakan proyek KlikPay di BCA. Dokumen ini mendukung kebutuhan proses bisnis dan pergerakan data dengan secara teknis, dari BCA ke merchant. Dokumen ini juga menjelaskan proses sistem, aliran data, dan beberapa hal yang diperlukan, baik untuk BCA atau merchant agar dapat berkomunikasi.
Konsep utama yang diterapkan adalah pelanggan dapat melakukan pembayaran untuk semua transaksi di laman merchant menggunakan akun BCA KlikPay.
Flowchart
Berikut ini adalah diagram alir transaksi merchant dengan BCA KlikPay melalui iPay88 Indonesia.

Proses Transaksi
Berikut ini adalah proses transaksi merchant dengan BCA KlikPay melalui iPay88 Indonesia.

Sistem Proses
Proses sistem dipisahkan dalam tiga sub proses, yaitu payment request, redirect forward, dan pemanggilan payment flag kepada merchant.
Payment Request
Ketika pelanggan memilih pembayaran menggunakan KlikPay di situs merchant, merchant harus memastikan bahwa jumlah total transaksi tidak melebihi batas transaksi KlikPay. Setelah itu, merchant akan melakukan proses pertama yaitu payment request.

URL yang digunakan untuk payment request adalah:
- UAT:
https://sandbox.ipay88.co.id/ePayment/WebService/SeamlessPayment/Entry.asmx - Production:
https://payment.ipay88.co.id/ePayment/WebService/SeamlessPayment/Entry.asmx
Request
Berikut ini adalah data yang dikirimkan merchant dengan metode web service.
|
|
|
|
---|---|---|---|
1 | MerchantCode | Varchar (20) | Merchant Code disediakan oleh iPay88 dan digunakan untuk mengidentifikasi merchant. |
2 | PaymentId | Integer | Payment ID 8 untuk metode pembayaran online banking BCA KlikPay. |
3 | Currency | Varchar (5) | Harus IDR. |
4 | RefNo | Varchar (20) | Nomor unik transaksi merchant atau Order ID. |
5 | Amount | Currency | Total diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp3.000,00 diekspresikan menjadi 300000. Amount = FullTransactionAmount + installmentTransactions[n].amount + MiscFee |
6 | ProdDesc | Varchar (100) | Deskripsi produk. |
7 | UserName | Varchar (100) | Nama pelanggan. |
8 | UserEmail | Varchar (100) | Email pelanggan untuk mendapatkan nota pembayaran. |
9 | UserContact | Varchar (20) | Nomor kontak pelanggan. |
10 | Remark | Varchar (100) | Catatan merchant. |
11 | Lang | Varchar (20) |
Encoding type
"ISO-8859-1" – English. "UTF-8" – Unicode. "GB2312" – Chinese Simplified. "GD18030" – Chinese Simplified. "BIG5" – Chinese Traditionl. |
12 | ResponseURL | Varchar (200) | Payment response page. Contoh merchant-ipay88.co.id/response. |
13 | BackendURL | Varchar (200) | Backend response page URL. Contoh merchant.ipay88.co.id/backend. |
14 | Signature | Varchar (100) | SHA signature. |
15 | xfield1 | Varchar (20) | |
16 | MiscFee | Varchar (12) | Biaya lain lain. MiscFee diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp500,00 diekspresikan menjadi 50000. |
17 | FullTransactionAmount | List (n) | FullTransactionAmount diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp1.000,00 diekspresikan menjadi 100000. |
18 | InstallmentTransactions | List (n) | Parameter ini hanya berlaku untuk jenis pembayaran cicilan dengan berbagai macam produk. |
18.1 | itemName | String (50) | Nama dari produk yang dibeli dengan jenis pembayaran cicilan. |
18.2 | quantity | Integer (3) | Kuantitas dari produk yang dibeli dengan jenis pembayaran cicilan. |
18.3 | amount | Currency | Harga produk dikalikan dengan jumlah kuantitas. Total diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp1.500,00 diekspresikan menjadi 150000. |
18.4 | tenor | Integer (2) | Tenor cicilan. Sebagai contoh, 3 bulan masa cicilan diekspresikan menjadi 03. |
18.5 | codePlan | String (2) | Contoh 000. |
18.6 | merchantId | Integer (9) | MID dari BCA. Contoh 1241. |
Keterangan:
M: Mandatory (diharuskan).
O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
Full Payment
POST [DOMAIN]/ePayment/WebService/SeamlessPayment/Entry.asmx HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/soap+xml;charset=UTF-8;
SOAPAction="Request"
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Request xmlns="http://www.ipay88.co.id">
<MerchantCode>your-merchant-code</MerchantCode>
<PaymentId>8</PaymentId>
<Currency>IDR</Currency>
<RefNo>117201783440AM</RefNo>
<Amount>10000000</Amount>
<ProdDesc>Souvenir 1</ProdDesc>
<UserName>Customer Name</UserName>
<UserEmail>customer.email.@ipay88.co.id</UserEmail>
<UserContact>08788888888</UserContact>
<Remark>Transaction 2018-03-26 17:12:55</Remark>
<Lang></Lang>
<ResponseURL>https://your-site/response</ResponseURL>
<BackendURL>https://your-site/backend</BackendURL>
<Signature>42QMKfAYvkaUUvPp9MTo8loOtGY=</Signature>
<xfield1></xfield1>
<FullTransactionAmount>10000000</FullTransactionAmount>
<MiscFee>000</MiscFee>
<InstallmentTransactions>
<installmentTransaction>
<itemName></itemName>
<quantity></quantity>
<amount>000</amount>
<tenor></tenor>
<codePlan></codePlan>
<merchantId></merchantId>
</installmentTransaction>
</InstallmentTransactions>
</Request>
</soap:Body>
</soap:Envelope>
<?php
//Full Payment
$client = new SoapClient("https://sandbox.ipay88.co.id/epayment/WebService/SeamlessPayment/Entry.asmx?WSDL");
$client->__setLocation('https://sandbox.ipay88.co.id/ePayment/WebService/SeamlessPayment/Entry.asmx');
$params = new stdClass();
$params->MerchantCode = 'your-merchant-code';
$params->PaymentId = '8';
$params->Currency = 'IDR';
$params->RefNo = '117201783440AM';
$params->Amount = '100000000';
$params->ProdDesc = 'Souvenir 1';
$params->UserName = 'Customer Name';
$params->UserEmail = 'customer.email.@ipay88.co.id';
$params->UserContact = '08788888888';
$params->Remark = 'Transaction 2018-03-26 17:12:55';
$params->Lang = 'iso-8859-1';
$params->ResponseURL = 'https://your-site/response';
$params->BackendURL = 'https://your-site/backend';
$params->Signature = '42QMKfAYvkaUUvPp9MTo8loOtGY=';
$params->xfield1 = '';
$params->MiscFee = '000';
$params->FullTransactionAmount = '50000000';
$installmentTransaction = new stdClass();
$installmentTransaction->itemName = '';
$installmentTransaction->quantity = '';
$installmentTransaction->amount = '';
$installmentTransaction->tenor = '';
$installmentTransaction->codePlan = '';
$installmentTransaction->merchantId = '';
$params->InstallmentTransactions[0] = $installmentTransaction;
//Approval ipay88
$results = $client->Request($params);
$result = $results[0];
$Amount = $result->Amount;
$Currency = $result->Currency;
$ErrDesc = $result->ErrDesc;
$MerchantCode = $result->MerchantCode;
$PaymentId = $result->PaymentId;
$RefNo = $result->RefNo;
$Remark = $result->Remark;
$Status = $result->Status;
$TransId = $result->TransId;
$Signature = $result->Signature;
echo "ErrDesc: ".$ErrDesc."</br>";
echo "Status: ".$Status."</br>";
echo "TransId: ".$TransId."</br>";
?>
Installment
POST [DOMAIN]/ePayment/WebService/SeamlessPayment/Entry.asmx HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/soap+xml;charset=UTF-8;
SOAPAction="Request"
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Request xmlns="http://www.ipay88.co.id">
<MerchantCode>ID00001</MerchantCode>
<PaymentId>8</PaymentId>
<Currency>IDR</Currency>
<RefNo>117201783440AM</RefNo>
<Amount>100000000</Amount>
<ProdDesc>Buku</ProdDesc>
<UserName>Customer Name</UserName>
<UserEmail>customer.email.@ipay88.co.id</UserEmail>
<UserContact>08788888888</UserContact>
<Remark>Transaction 2018-03-26 17:12:55</Remark>
<Lang></Lang>
<ResponseURL>https://your-site/response</ResponseURL>
<BackendURL>https://your-site/backend</BackendURL>
<Signature>42QMKfAYvkaUUvPp9MTo8loOtGY=</Signature>
<xfield1></xfield1>
<FullTransactionAmount></FullTransactionAmount>
<MiscFee>000</MiscFee>
<InstallmentTransactions>
<installmentTransaction>
<itemName>Product 1</itemName>
<quantity>2</quantity>
<amount>30000000</amount>
<tenor>06</tenor>
<codePlan>000</codePlan>
<merchantId>12323</merchantId>
</installmentTransaction>
<installmentTransaction>
<itemName>Product 2</itemName>
<quantity>2</quantity>
<amount>30000000</amount>
<tenor>03</tenor>
<codePlan>000</codePlan>
<merchantId>12322</merchantId>
</installmentTransaction>
<installmentTransaction>
<itemName>Product 3</itemName>
<quantity>2</quantity>
<amount>40000000</amount>
<tenor>09</tenor>
<codePlan>000</codePlan>
<merchantId>12324</merchantId>
</installmentTransaction>
</InstallmentTransactions>
</Request>
</soap:Body>
</soap:Envelope>
<?php
//Installment
$client = new SoapClient("https://sandbox.ipay88.co.id/epayment/WebService/SeamlessPayment/Entry.asmx?WSDL");
$client->__setLocation('https://sandbox.ipay88.co.id/ePayment/WebService/SeamlessPayment/Entry.asmx');
$params = new stdClass();
$params->MerchantCode = 'your-merchant-code';
$params->PaymentId = '8';
$params->Currency = 'IDR';
$params->RefNo = '117201783440AM';
$params->Amount = '100000000';
$params->ProdDesc = 'Souvenir 1';
$params->UserName = 'Customer Name';
$params->UserEmail = 'customer.email.@ipay88.co.id';
$params->UserContact = '08788888888';
$params->Remark = 'Transaction 2018-03-26 17:12:55';
$params->Lang = 'iso-8859-1';
$params->ResponseURL = 'https://your-site/response';
$params->BackendURL = 'https://your-site/backend';
$params->Signature = '42QMKfAYvkaUUvPp9MTo8loOtGY=';
$params->xfield1 = '';
$params->MiscFee = '000';
$params->FullTransactionAmount = '50000000';
$installmentTransaction = new stdClass();
$installmentTransaction->itemName = 'test product';
$installmentTransaction->quantity = '2';
$installmentTransaction->amount = '50000000';
$installmentTransaction->tenor = '03';
$installmentTransaction->codePlan = '000';
$installmentTransaction->merchantId = '12322';
$params->InstallmentTransactions[0] = $installmentTransaction;
//approval ipay88
$results = $client->Request($params);
$result = $results[0];
$Amount = $result->Amount;
$Currency = $result->Currency;
$ErrDesc = $result->ErrDesc;
$MerchantCode = $result->MerchantCode;
$PaymentId = $result->PaymentId;
$RefNo = $result->RefNo;
$Remark = $result->Remark;
$Status = $result->Status;
$TransId = $result->TransId;
$Signature = $result->Signature;
echo "ErrDesc: ".$ErrDesc."</br>";
echo "Status: ".$Status."</br>";
echo "TransId: ".$TransId."</br>";
?>
Request Signature Algorithm
Parameter yang digunakan adalah sebagai berikut.
- KlikPay Code
- Transaction Time (format: ddMMyyyy)
- Transaction Number
- Total Amount (catatan: format dalam nilai integer, tidak ada angka desimal)
- Currency
- Key Id (key digunakan untuk transaksi)
Fungsi PHP mcrypt_encrypt hanya berlaku untuk PHP 4 >= 4.0.2, PHP 5, PHP 7 < 7.2.0.
Berikut penjelasan yang dikutip dari situs resmi PHP.

Untuk informasi lebih lanjut, silahkan klik tautan berikut.
using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
public class GenerateKey
{
private static String HEX_DIGITS = "0123456789ABCDEF";
private static int getHash(String val)
{
int h = 0;
char[] vals = val.ToCharArray();
for (int i = 0; i < vals.Length; i++)
{
h = (h * 31) + (int)vals[i];
}
return h;
}
public static String generateSignature(String klikPayCode, String transactionDate, String transactionNo, String amount, String currency, String keyId)
{
// Generate Key Step 1
String tempKey1 = klikPayCode + transactionNo + currency + keyId;
int hashKey1 = getHash(tempKey1);
// Generate Key Step 2
// Reformat Input Date
DateTime date = new DateTime();
date = DateTime.ParseExact(transactionDate, "dd/MM/yyyy HH:mm:ss", null);
int transDate = Convert.ToInt32(date.ToString("ddMMyyyy"));
int amt = (Int32)Convert.ToDouble(amount);
String tempKey2 = (transDate + amt).ToString();
int hashKey2 = getHash(tempKey2);
// Hash the value using integer arithmatic and absolute value
Decimal hash = Math.Abs(decimal.Add(new Decimal(hashKey1), new Decimal(hashKey2)));
return hash.ToString();
}
private static byte[] fromHexString(String s)
{
byte[] bytes = new byte[s.Length / 2];
for (int i = 0; i < s.Length / 2; i++)
{
bytes[i] = (byte)(Convert.ToInt32(s.Substring(2 * i, 2), 16));
}
return bytes;
}
private static String toHexString(byte[] b)
{
if ((b == null) || (b.Length == 0))
{
return "";
}
else
{
return toHexString(b, 0, b.Length);
}
}
/** Convert bytes to HEX string */
private static String toHexString(byte[] b, int off, int len)
{
StringBuilder s = new StringBuilder();
for (int i = off; i < off + len; i++)
{
s.Append(HEX_DIGITS[(b[i] & 0xff) >> 4]); s.Append(HEX_DIGITS[b[i] & 0xf]);
// or
//s.Append((b[i]).ToString("X2"));
}
return s.ToString();
}
public static String generateAuthKey(String klikPayCode, String transactionNo, String currency, string transactionDate, String keyId)
{
return generateAuthKey(klikPayCode.PadRight(10, '0') + transactionNo.PadRight(18, 'A') + currency.PadRight(5, '1') + transactionDate.PadLeft(19, 'C') + keyId, keyId);
}
private static String generateAuthKey(String secondValue, String keyId)
{
MD5 sha = MD5.Create();
byte[] byteHash = sha.ComputeHash(Encoding.UTF8.GetBytes(secondValue)); ;
String hashData = toHexString(byteHash);
byte[] byteHashData = fromHexString(hashData);
byte[] byteKey = fromHexString(keyId);
if (!(byteKey.Length == 16 || byteKey.Length == 24))
{
throw new Exception("Length not valid :" + byteKey.Length);
}
byte[] key = new byte[24];
if (byteKey.Length == 16)
{
for (int za = 0; za < 16; za++)
{
key[za] = byteKey[za];
}
for (int za = 0; za < 8; za++)
{
key[za + 16] = byteKey[za];
}
}
if (byteKey.Length == 24)
{
for (int za = 0; za < 24; za++)
{
key[za] = byteKey[za];
}
}
MemoryStream ms = new MemoryStream();
TripleDES alg = TripleDES.Create();
alg.Key = key;
alg.Mode = CipherMode.ECB;
alg.Padding = PaddingMode.None;
CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(byteHashData, 0, byteHashData.Length);
cs.FlushFinalBlock();
byte[] CipherBytes = ms.ToArray();
ms.Close();
cs.Close();
String encryptedHashKey = toHexString(CipherBytes);
return encryptedHashKey;
}
public static String generateKeyId(String clearKey)
{
byte[] bytes = Encoding.UTF8.GetBytes(clearKey);
return toHexString(bytes);
}
}
private void static example()
{
String keyId = BcaKeyGenerator.GenerateKey.generateKeyId(clearKey);
sSignature = BcaKeyGenerator.GenerateKey.generateSignature(klikPayCode, transactionDate, transactionNo, totalAmount, currency, keyId);
sAuthKey = BcaKeyGenerator.GenerateKey.generateAuthKey(klikPayCode, transactionNo, currency, transactionDate, keyId);
}
<?php
function toHexString($string)
{
$hex = '';
for ($i=0; $i<strlen($string); $i++)
{
$ord = ord($string[$i]);
$hexCode = dechex($ord);
$hex .= substr('0'.$hexCode, -2);
}
return strToUpper($hex);
}
function fromHexString($hex)
{
$string = '';
for ($i=0; $i < strlen($hex)-1; $i+=2)
{
$string .= chr(hexdec($hex[$i].$hex[$i+1]));
}
return $string;
}
function generateSignature($klikPayCode, $transactionDate, $transactionNo, $amount, $currency, $keyId)
{
date_default_timezone_set("Asia/Jakarta");
$tempKey1 = $klikPayCode.$transactionNo.$currency.$keyId;
$hashKey1 = getHash($tempKey1);
$tdate = date_create_from_format("d/m/Y G:i:s",$transactionDate);
$idate = (int)date_format($tdate, 'dmY');
$iamount = (int)$amount;
$tempKey2 = ($idate + $iamount);
$tempKey2 = $tempKey2 . "";
$hashKey2 = getHash($tempKey2);
$hash = abs($hashKey1+$hashKey2);
return $hash."";
}
function generateAuthKey($klikPayCode, $transactionNo, $currency, $transactionDate, $keyId)
{
$str1 = str_pad($klikPayCode,10, '0', STR_PAD_RIGHT) . str_pad($transactionNo,18, 'A', STR_PAD_RIGHT) . str_pad($currency,5, '1',STR_PAD_RIGHT) . str_pad($transactionDate,19, 'C', STR_PAD_LEFT) . $keyId;
$mdstr1 = md5($str1);
$my_key = fromHexString($keyId);
$data = fromHexString($mdstr1);
$my_key .= substr($my_key,0,8);
$secret = mcrypt_encrypt(MCRYPT_3DES, $my_key, $data, MCRYPT_MODE_ECB);
return toHexString($secret);
}
function generateKeyId($str)
{
return toHexString($str);
}
function getHash ($value)
{
$hash = 0;
for ($i = 0; $i < strlen($value); $i++)
{
$hash = (intval($hash) * 31) + ord($value[$i]);
$hash = intval32bits($hash);
}
return (int)$hash;
}
function intval32bits($value)
{
$value = ($value & 0xFFFFFFFF);
if ($value & 0x80000000)
{
$value = -((~$value & 0xFFFFFFFF) + 1);
}
return $value;
}
$clearKey = "ClearKey00000001";
$klikPayCode = "BCAPAY0001";
//format: "d/m/Y G:i:s"
$transactionDate = "11/04/2014 16:15:53";
$transactionNo = "R223248";
$totalAmount = 3000.00;
$currency = "IDR";
$keyId = generateKeyId($clearKey);
$sSignature = generateSignature($klikPayCode, $transactionDate, $transactionNo, $totalAmount, $currency, $keyId);
$sAuthKey = generateAuthKey($klikPayCode, $transactionNo, $currency, $transactionDate, $keyId);
echo $keyId."<br/>".$sSignature."<br/>".$sAuthKey;
?>
Payment Approval
Payment approval adalah hasil balikan dari payment request webservice dengan iPay88 Indonesia. Berikut ini adalah parameter response yang dikirim iPay88 Indonesia kepada merchant.
|
|
|
|
---|---|---|---|
1 | MerchantCode | Varchar (20) | Merchant Code disediakan oleh iPay88 dan digunakan untuk mengidentifikasi merchant. |
2 | PaymentId | Integer | Payment ID untuk metode pembayaran yang dituju. Payment ID 8 untuk metode pembayaran online banking BCA KlikPay. |
3 | RefNo | String (20) | Nomor unik transaksi merchant atau Order ID. |
4 | Amount | Currency | Total diharuskan tidak mengandung angka desimal, penanda ribuan, dan kode mata uang. Sebagai contoh, Rp1.278,00 diekspresikan menjadi 127800. |
5 | Currency | String (5) | Harus IDR. |
6 | Remark | String (100) | Catatan merchant. |
7 | Signature | String (100) | SHA signature. |
8 | xfield1 | String | |
9 | TransId | Varchar (30) | |
10 | Status | Integer (2) |
Status pembayaran
"0" – Payment request approved. "6" – Payment request failed. |
11 | ErrDesc | Varchar (100) | Deskripsi penyebab gagal-nya transaksi (lihat referensi). |
Keterangan:
M: Mandatory (diharuskan).
O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<RequestResponse xmlns="http://www.ipay88.co.id">
<RequestResult>
<Status>6</Status>
<ErrDesc/>
<MerchantCode>ID00001</MerchantCode>
<PaymentId>8</PaymentId>
<RefNo>117201783440AM</RefNo>
<Amount>100000000</Amount>
<Currency>IDR</Currency>
<Remark/>
<xfield1/>
<Signature>jVZBU7kXCMKijkhEc1p8CFZnf50=</Signature>
<TransId>T0000970500</TransId>
<AuthCode/>
</RequestResult>
</RequestResponse>
</soap:Body>
</soap:Envelope>
Payment Approval Signature Algorithm
Parameter yang digunakan adalah sebagai berikut.
- KlikPay Code
- Transaction Time (format: ddMMyyyy)
- Transaction Number
- Total Amount (catatan: format dalam nilai integer, tidak ada angka desimal)
- Currency
- Key Id (key digunakan untuk transaksi)
Fungsi PHP mcrypt_encrypt hanya berlaku untuk PHP 4 >= 4.0.2, PHP 5, PHP 7 < 7.2.0.
Berikut penjelasan yang dikutip dari situs resmi PHP.

Untuk informasi lebih lanjut, silahkan klik tautan berikut.
using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
public class GenerateKey
{
private static String HEX_DIGITS = "0123456789ABCDEF";
private static int getHash(String val)
{
int h = 0;
char[] vals = val.ToCharArray();
for (int i = 0; i < vals.Length; i++)
{
h = (h * 31) + (int)vals[i];
}
return h;
}
public static String generateSignature(String klikPayCode, String transactionDate, String transactionNo, String amount, String currency, String keyId)
{
// Generate Key Step 1
String tempKey1 = klikPayCode + transactionNo + currency + keyId;
int hashKey1 = getHash(tempKey1);
// Generate Key Step 2
// Reformat Input Date
DateTime date = new DateTime();
date = DateTime.ParseExact(transactionDate, "dd/MM/yyyy HH:mm:ss", null);
int transDate = Convert.ToInt32(date.ToString("ddMMyyyy"));
int amt = (Int32)Convert.ToDouble(amount);
String tempKey2 = (transDate + amt).ToString();
int hashKey2 = getHash(tempKey2);
// Hash the value using integer arithmatic and absolute value
Decimal hash = Math.Abs(decimal.Add(new Decimal(hashKey1), new Decimal(hashKey2)));
return hash.ToString();
}
private static byte[] fromHexString(String s)
{
byte[] bytes = new byte[s.Length / 2];
for (int i = 0; i < s.Length / 2; i++)
{
bytes[i] = (byte)(Convert.ToInt32(s.Substring(2 * i, 2), 16));
}
return bytes;
}
private static String toHexString(byte[] b)
{
if ((b == null) || (b.Length == 0))
{
return "";
}
else
{
return toHexString(b, 0, b.Length);
}
}
/** Convert bytes to HEX string */
private static String toHexString(byte[] b, int off, int len)
{
StringBuilder s = new StringBuilder();
for (int i = off; i < off + len; i++)
{
s.Append(HEX_DIGITS[(b[i] & 0xff) >> 4]); s.Append(HEX_DIGITS[b[i] & 0xf]);
// or
//s.Append((b[i]).ToString("X2"));
}
return s.ToString();
}
public static String generateAuthKey(String klikPayCode, String transactionNo, String currency, string transactionDate, String keyId)
{
return generateAuthKey(klikPayCode.PadRight(10, '0') + transactionNo.PadRight(18, 'A') + currency.PadRight(5, '1') + transactionDate.PadLeft(19, 'C') + keyId, keyId);
}
private static String generateAuthKey(String secondValue, String keyId)
{
MD5 sha = MD5.Create();
byte[] byteHash = sha.ComputeHash(Encoding.UTF8.GetBytes(secondValue)); ;
String hashData = toHexString(byteHash);
byte[] byteHashData = fromHexString(hashData);
byte[] byteKey = fromHexString(keyId);
if (!(byteKey.Length == 16 || byteKey.Length == 24))
{
throw new Exception("Length not valid :" + byteKey.Length);
}
byte[] key = new byte[24];
if (byteKey.Length == 16)
{
for (int za = 0; za < 16; za++)
{
key[za] = byteKey[za];
}
for (int za = 0; za < 8; za++)
{
key[za + 16] = byteKey[za];
}
}
if (byteKey.Length == 24)
{
for (int za = 0; za < 24; za++)
{
key[za] = byteKey[za];
}
}
MemoryStream ms = new MemoryStream();
TripleDES alg = TripleDES.Create();
alg.Key = key;
alg.Mode = CipherMode.ECB;
alg.Padding = PaddingMode.None;
CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(byteHashData, 0, byteHashData.Length);
cs.FlushFinalBlock();
byte[] CipherBytes = ms.ToArray();
ms.Close();
cs.Close();
String encryptedHashKey = toHexString(CipherBytes);
return encryptedHashKey;
}
public static String generateKeyId(String clearKey)
{
byte[] bytes = Encoding.UTF8.GetBytes(clearKey);
return toHexString(bytes);
}
}
private void static example()
{
String keyId = BcaKeyGenerator.GenerateKey.generateKeyId(clearKey);
sSignature = BcaKeyGenerator.GenerateKey.generateSignature(klikPayCode, transactionDate, transactionNo, totalAmount, currency, keyId);
sAuthKey = BcaKeyGenerator.GenerateKey.generateAuthKey(klikPayCode, transactionNo, currency, transactionDate, keyId);
}
<?php
function toHexString($string)
{
$hex = '';
for ($i=0; $i<strlen($string); $i++)
{
$ord = ord($string[$i]);
$hexCode = dechex($ord);
$hex .= substr('0'.$hexCode, -2);
}
return strToUpper($hex);
}
function fromHexString($hex)
{
$string = '';
for ($i=0; $i < strlen($hex)-1; $i+=2)
{
$string .= chr(hexdec($hex[$i].$hex[$i+1]));
}
return $string;
}
function generateSignature($klikPayCode, $transactionDate, $transactionNo, $amount, $currency, $keyId)
{
date_default_timezone_set("Asia/Jakarta");
$tempKey1 = $klikPayCode.$transactionNo.$currency.$keyId;
$hashKey1 = getHash($tempKey1);
$tdate = date_create_from_format("d/m/Y G:i:s",$transactionDate);
$idate = (int)date_format($tdate, 'dmY');
$iamount = (int)$amount;
$tempKey2 = ($idate + $iamount);
$tempKey2 = $tempKey2 . "";
$hashKey2 = getHash($tempKey2);
$hash = abs($hashKey1+$hashKey2);
return $hash."";
}
function generateAuthKey($klikPayCode, $transactionNo, $currency, $transactionDate, $keyId)
{
$str1 = str_pad($klikPayCode,10, '0', STR_PAD_RIGHT) . str_pad($transactionNo,18, 'A', STR_PAD_RIGHT) . str_pad($currency,5, '1',STR_PAD_RIGHT) . str_pad($transactionDate,19, 'C', STR_PAD_LEFT) . $keyId;
$mdstr1 = md5($str1);
$my_key = fromHexString($keyId);
$data = fromHexString($mdstr1);
$my_key .= substr($my_key,0,8);
$secret = mcrypt_encrypt(MCRYPT_3DES, $my_key, $data, MCRYPT_MODE_ECB);
return toHexString($secret);
}
function generateKeyId($str)
{
return toHexString($str);
}
function getHash ($value)
{
$hash = 0;
for ($i = 0; $i < strlen($value); $i++)
{
$hash = (intval($hash) * 31) + ord($value[$i]);
$hash = intval32bits($hash);
}
return (int)$hash;
}
function intval32bits($value)
{
$value = ($value & 0xFFFFFFFF);
if ($value & 0x80000000)
{
$value = -((~$value & 0xFFFFFFFF) + 1);
}
return $value;
}
$clearKey = "ClearKey00000001";
$klikPayCode = "BCAPAY0001";
//format: "d/m/Y G:i:s"
$transactionDate = "11/04/2014 16:15:53";
$transactionNo = "R223248";
$totalAmount = 3000.00;
$currency = "IDR";
$keyId = generateKeyId($clearKey);
$sSignature = generateSignature($klikPayCode, $transactionDate, $transactionNo, $totalAmount, $currency, $keyId);
$sAuthKey = generateAuthKey($klikPayCode, $transactionNo, $currency, $transactionDate, $keyId);
echo $keyId."<br/>".$sSignature."<br/>".$sAuthKey;
?>
Redirect Forward
Setelah menerima persetujuan pembayaran dari iPay88 Indonesia, merchant harus menetapkan atau mengatur proses redirect forward, jadi pelanggan akan melakukan login di laman BCA KlikPay.

URL yang digunakan untuk proses redirect forward adalah:
- Development:
https://sandbox.ipay88.co.id/klikpaybca/purchasing/purchase.asp?action=loginRequest - UAT:
https://sb-ipay.klikbca.com:8081/purchasing/purchase.do?action=loginRequest - Production:
https://klikpay.klikbca.com/purchasing/purchase.do?action=loginRequest
Input
Berikut ini adalah data table spesifikasi pada input dan tipe data yag digunakan.
|
|
|
|
|
|
---|---|---|---|---|---|
1 | klikPayCode | klikPay Code | String (10) | (AN) | M |
2 | transactionNo | Transaction Number | String (18) | (AN) | M |
3 | totalAmount | Total Amount | String (12) | 999999999.00 | M |
4 | currency | Currency | String (5) | (A) | M |
5 | payType | Payment Type | String (2) | 99 | M |
6 | callback | Call Back URL | String (100) | (AN) | M |
7 | transactionDate | Transaction Date | String (19) | DD/MM/YYYY hh:mm:ss |
M |
8 | Descp | Description | String (60) | (AN) | O |
9 | miscFee | Miscellanous Fee | String (12) | 999999999.00 | O |
10 | signature | Signature | String (10) | (N) | M |
Keterangan:
- (AN): Alpha-numeric format.
- 2 digit terakhir untuk totalAmount dan miscFee harus menjadi titik desimal. Titik desimal harus bernilai .00.
- Nilai dari TotalAmount adalah total untuk transaksi tetapi tidak termasuk miscFee.
- payType dapat diisi dengan nilai berikut:
- 01 = Full
- 02 = Installment
- 03 = 01 dan 02
- Currency harus bernilai IDR.
- M: Mandatory (diharuskan).
- O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
<html>
<body>
<form method="post" name="ePayment" action="https://klikpay.klikbca.com/purchasing/purchase.do?action=loginRequest">
<input type="hidden" name="klikPayCode" value="BCAPAY0001">
<input type="hidden" name="clearKey" value="ClearKey00000001">
<input type="hidden" name="transactionNo" value="R811184">
<input type="hidden" name="totalAmount" value="3000\">
<input type="hidden" name="Currency" value="IDR">
<input type="hidden" name="payType" value="01">
<input type="hidden" name="transactionDate" value="17/04/2014 11:24:55">
<input type="hidden" name="descp" value="test Pembelian">
<input type="hidden" name="miscFee" value="0.00">
<input type="hidden" name="signature" value="240101082">
<input type="hidden" name="callback" value="https://dvl1.ipay88.co.id/klikpaybca/purchasing/callback.asp?trxno=R811184">
<input type="submit" value="Proceed with Payment" name="Submit">
</form>
</body>
</html>
Signature Algorithm
Parameter yang digunakan adalah sebagai berikut.
- KlikPay Code
- Transaction Time (format: ddMMyyyy)
- Transaction Number
- Total Amount (catatan: format dalam nilai integer, tidak ada angka desimal)
- Currency
- Key Id (key digunakan untuk transaksi)
Fungsi PHP mcrypt_encrypt hanya berlaku untuk PHP 4 >= 4.0.2, PHP 5, PHP 7 < 7.2.0.
Berikut penjelasan yang dikutip dari situs resmi PHP.

Untuk informasi lebih lanjut, silahkan klik tautan berikut.
using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
public class GenerateKey
{
private static String HEX_DIGITS = "0123456789ABCDEF";
private static int getHash(String val)
{
int h = 0;
char[] vals = val.ToCharArray();
for (int i = 0; i < vals.Length; i++)
{
h = (h * 31) + (int)vals[i];
}
return h;
}
public static String generateSignature(String klikPayCode, String transactionDate, String transactionNo, String amount, String currency, String keyId)
{
// Generate Key Step 1
String tempKey1 = klikPayCode + transactionNo + currency + keyId;
int hashKey1 = getHash(tempKey1);
// Generate Key Step 2
// Reformat Input Date
DateTime date = new DateTime();
date = DateTime.ParseExact(transactionDate, "dd/MM/yyyy HH:mm:ss", null);
int transDate = Convert.ToInt32(date.ToString("ddMMyyyy"));
int amt = (Int32)Convert.ToDouble(amount);
String tempKey2 = (transDate + amt).ToString();
int hashKey2 = getHash(tempKey2);
// Hash the value using integer arithmatic and absolute value
Decimal hash = Math.Abs(decimal.Add(new Decimal(hashKey1), new Decimal(hashKey2)));
return hash.ToString();
}
private static byte[] fromHexString(String s)
{
byte[] bytes = new byte[s.Length / 2];
for (int i = 0; i < s.Length / 2; i++)
{
bytes[i] = (byte)(Convert.ToInt32(s.Substring(2 * i, 2), 16));
}
return bytes;
}
private static String toHexString(byte[] b)
{
if ((b == null) || (b.Length == 0))
{
return "";
}
else
{
return toHexString(b, 0, b.Length);
}
}
/** Convert bytes to HEX string */
private static String toHexString(byte[] b, int off, int len)
{
StringBuilder s = new StringBuilder();
for (int i = off; i < off + len; i++)
{
s.Append(HEX_DIGITS[(b[i] & 0xff) >> 4]); s.Append(HEX_DIGITS[b[i] & 0xf]);
// or
//s.Append((b[i]).ToString("X2"));
}
return s.ToString();
}
public static String generateAuthKey(String klikPayCode, String transactionNo, String currency, string transactionDate, String keyId)
{
return generateAuthKey(klikPayCode.PadRight(10, '0') + transactionNo.PadRight(18, 'A') + currency.PadRight(5, '1') + transactionDate.PadLeft(19, 'C') + keyId, keyId);
}
private static String generateAuthKey(String secondValue, String keyId)
{
MD5 sha = MD5.Create();
byte[] byteHash = sha.ComputeHash(Encoding.UTF8.GetBytes(secondValue)); ;
String hashData = toHexString(byteHash);
byte[] byteHashData = fromHexString(hashData);
byte[] byteKey = fromHexString(keyId);
if (!(byteKey.Length == 16 || byteKey.Length == 24))
{
throw new Exception("Length not valid :" + byteKey.Length);
}
byte[] key = new byte[24];
if (byteKey.Length == 16)
{
for (int za = 0; za < 16; za++)
{
key[za] = byteKey[za];
}
for (int za = 0; za < 8; za++)
{
key[za + 16] = byteKey[za];
}
}
if (byteKey.Length == 24)
{
for (int za = 0; za < 24; za++)
{
key[za] = byteKey[za];
}
}
MemoryStream ms = new MemoryStream();
TripleDES alg = TripleDES.Create();
alg.Key = key;
alg.Mode = CipherMode.ECB;
alg.Padding = PaddingMode.None;
CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(byteHashData, 0, byteHashData.Length);
cs.FlushFinalBlock();
byte[] CipherBytes = ms.ToArray();
ms.Close();
cs.Close();
String encryptedHashKey = toHexString(CipherBytes);
return encryptedHashKey;
}
public static String generateKeyId(String clearKey)
{
byte[] bytes = Encoding.UTF8.GetBytes(clearKey);
return toHexString(bytes);
}
}
private void static example()
{
String keyId = BcaKeyGenerator.GenerateKey.generateKeyId(clearKey);
sSignature = BcaKeyGenerator.GenerateKey.generateSignature(klikPayCode, transactionDate, transactionNo, totalAmount, currency, keyId);
sAuthKey = BcaKeyGenerator.GenerateKey.generateAuthKey(klikPayCode, transactionNo, currency, transactionDate, keyId);
}
<?php
function toHexString($string)
{
$hex = '';
for ($i=0; $i<strlen($string); $i++)
{
$ord = ord($string[$i]);
$hexCode = dechex($ord);
$hex .= substr('0'.$hexCode, -2);
}
return strToUpper($hex);
}
function fromHexString($hex)
{
$string = '';
for ($i=0; $i < strlen($hex)-1; $i+=2)
{
$string .= chr(hexdec($hex[$i].$hex[$i+1]));
}
return $string;
}
function generateSignature($klikPayCode, $transactionDate, $transactionNo, $amount, $currency, $keyId)
{
date_default_timezone_set("Asia/Jakarta");
$tempKey1 = $klikPayCode.$transactionNo.$currency.$keyId;
$hashKey1 = getHash($tempKey1);
$tdate = date_create_from_format("d/m/Y G:i:s",$transactionDate);
$idate = (int)date_format($tdate, 'dmY');
$iamount = (int)$amount;
$tempKey2 = ($idate + $iamount);
$tempKey2 = $tempKey2 . "";
$hashKey2 = getHash($tempKey2);
$hash = abs($hashKey1+$hashKey2);
return $hash."";
}
function generateAuthKey($klikPayCode, $transactionNo, $currency, $transactionDate, $keyId)
{
$str1 = str_pad($klikPayCode,10, '0', STR_PAD_RIGHT) . str_pad($transactionNo,18, 'A', STR_PAD_RIGHT) . str_pad($currency,5, '1',STR_PAD_RIGHT) . str_pad($transactionDate,19, 'C', STR_PAD_LEFT) . $keyId;
$mdstr1 = md5($str1);
$my_key = fromHexString($keyId);
$data = fromHexString($mdstr1);
$my_key .= substr($my_key,0,8);
$secret = mcrypt_encrypt(MCRYPT_3DES, $my_key, $data, MCRYPT_MODE_ECB);
return toHexString($secret);
}
function generateKeyId($str)
{
return toHexString($str);
}
function getHash ($value)
{
$hash = 0;
for ($i = 0; $i < strlen($value); $i++)
{
$hash = (intval($hash) * 31) + ord($value[$i]);
$hash = intval32bits($hash);
}
return (int)$hash;
}
function intval32bits($value)
{
$value = ($value & 0xFFFFFFFF);
if ($value & 0x80000000)
{
$value = -((~$value & 0xFFFFFFFF) + 1);
}
return $value;
}
$clearKey = "ClearKey00000001";
$klikPayCode = "BCAPAY0001";
//format: "d/m/Y G:i:s"
$transactionDate = "11/04/2014 16:15:53";
$transactionNo = "R223248";
$totalAmount = 3000.00;
$currency = "IDR";
$keyId = generateKeyId($clearKey);
$sSignature = generateSignature($klikPayCode, $transactionDate, $transactionNo, $totalAmount, $currency, $keyId);
$sAuthKey = generateAuthKey($klikPayCode, $transactionNo, $currency, $transactionDate, $keyId);
echo $keyId."<br/>".$sSignature."<br/>".$sAuthKey;
?>
Payment Flag Invocations to Merchants
Dari proses pertama (list inquiry of transactions) sampai proses terakhir (setelah melakukan semua proses transaksi), BCA akan memproses nilai akun rekening pelanggan (debit dan/atau akun kredit) dan mengirim konfirmasi pembayaran untuk dikonfirmasi oleh merchant.
Proses Transaksi
Berikut proses transaksi antara Merchant dengan iPay88 Indonesia.

Catatan:
- Payment flag from BCA to Merchant.
- Response from Merchant to BCA.
Input
Berikut ini adalah data table spesifikasi pada input dan tipe data yag digunakan.
|
|
|
|
|
|
---|---|---|---|---|---|
1 | klikPayCode | klikPay Code | String (10) | (AN) | M |
2 | transactionDate | Transaction Date | String (19) | DD/MM/YYYY hh:mm:ss |
M |
3 | transactionNo | Transaction Number | String (18) | (AN) | M |
4 | currency | Currency | String (5) | (A) | M |
5 | totalAmount | Total Amount | String (12) | 999999999.00 | M |
6 | payType | Payment Type | String (2) | 99 | M |
7 | approvalCodeFullTransaction | Kode persetujuan untuk transaksi full payment | Number (6) | (N) | O |
8 | approvalCodeInstallmentTransaction | Kode persetujuan untuk transaksi cicilan | Number (6) | (N) | O |
9 | authKey | Kunci otorisasi | String (32) | (N) | M |
10 | additionalData | Data tambahan | String (999) | (AN) | O |
Keterangan:
- (AN): Alpha-numeric format.
- Approval Code untuk fullTransaction akan diisi jika pelanggan memiliki transaksi penuh dan memilih untuk melakukan pembayaran pada transaksi penuh tersebut menggunakan kartu kredit.
- Approval Code untuk installmentTransaction akan diisi jika pelanggan memiliki angsuran transaksi.
- 2 digit terakhir untuk totalAmount dan miscFee harus menjadi titik desimal. Titik desimal harus bernilai .00.
- Field pada totalAmount adalah total untuk transaksi.
- payType dapat diisi dengan nilai berikut:
- 01 = Full
- 02 = Installment
- 03 = 01 dan 02
- Currency harus bernilai IDR.
- M: Mandatory (diharuskan).
- O: Optional (tidak diharuskan), nilai boleh kosong tetapi parameter harus ada.
Auth Key Algorithm
Berikut Authkey Flag yang digunakan untuk transaksi:

Parameter yang digunakan adalah sebagai berikut.
- A = klikPayCode
- B = transactionNo
- C = currency
- D = transactionDate
- K = keyId (current key used for transaction)
- e = encrypt using 3DES by keyId
- h = hash function
Fungsi PHP mcrypt_encrypt hanya berlaku untuk PHP 4 >= 4.0.2, PHP 5, PHP 7 < 7.2.0.
Berikut penjelasan yang dikutip dari situs resmi PHP.

Untuk informasi lebih lanjut, silahkan klik tautan berikut.
using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
public class GenerateKey
{
private static String HEX_DIGITS = "0123456789ABCDEF";
private static int getHash(String val)
{
int h = 0;
char[] vals = val.ToCharArray();
for (int i = 0; i < vals.Length; i++)
{
h = (h * 31) + (int)vals[i];
}
return h;
}
public static String generateSignature(String klikPayCode, String transactionDate, String transactionNo, String amount, String currency, String keyId)
{
// Generate Key Step 1
String tempKey1 = klikPayCode + transactionNo + currency + keyId;
int hashKey1 = getHash(tempKey1);
// Generate Key Step 2
// Reformat Input Date
DateTime date = new DateTime();
date = DateTime.ParseExact(transactionDate, "dd/MM/yyyy HH:mm:ss", null);
int transDate = Convert.ToInt32(date.ToString("ddMMyyyy"));
int amt = (Int32)Convert.ToDouble(amount);
String tempKey2 = (transDate + amt).ToString();
int hashKey2 = getHash(tempKey2);
// Hash the value using integer arithmatic and absolute value
Decimal hash = Math.Abs(decimal.Add(new Decimal(hashKey1), new Decimal(hashKey2)));
return hash.ToString();
}
private static byte[] fromHexString(String s)
{
byte[] bytes = new byte[s.Length / 2];
for (int i = 0; i < s.Length / 2; i++)
{
bytes[i] = (byte)(Convert.ToInt32(s.Substring(2 * i, 2), 16));
}
return bytes;
}
private static String toHexString(byte[] b)
{
if ((b == null) || (b.Length == 0))
{
return "";
}
else
{
return toHexString(b, 0, b.Length);
}
}
/** Convert bytes to HEX string */
private static String toHexString(byte[] b, int off, int len)
{
StringBuilder s = new StringBuilder();
for (int i = off; i < off + len; i++)
{
s.Append(HEX_DIGITS[(b[i] & 0xff) >> 4]); s.Append(HEX_DIGITS[b[i] & 0xf]);
// or
//s.Append((b[i]).ToString("X2"));
}
return s.ToString();
}
public static String generateAuthKey(String klikPayCode, String transactionNo, String currency, string transactionDate, String keyId)
{
return generateAuthKey(klikPayCode.PadRight(10, '0') + transactionNo.PadRight(18, 'A') + currency.PadRight(5, '1') + transactionDate.PadLeft(19, 'C') + keyId, keyId);
}
private static String generateAuthKey(String secondValue, String keyId)
{
MD5 sha = MD5.Create();
byte[] byteHash = sha.ComputeHash(Encoding.UTF8.GetBytes(secondValue)); ;
String hashData = toHexString(byteHash);
byte[] byteHashData = fromHexString(hashData);
byte[] byteKey = fromHexString(keyId);
if (!(byteKey.Length == 16 || byteKey.Length == 24))
{
throw new Exception("Length not valid :" + byteKey.Length);
}
byte[] key = new byte[24];
if (byteKey.Length == 16)
{
for (int za = 0; za < 16; za++)
{
key[za] = byteKey[za];
}
for (int za = 0; za < 8; za++)
{
key[za + 16] = byteKey[za];
}
}
if (byteKey.Length == 24)
{
for (int za = 0; za < 24; za++)
{
key[za] = byteKey[za];
}
}
MemoryStream ms = new MemoryStream();
TripleDES alg = TripleDES.Create();
alg.Key = key;
alg.Mode = CipherMode.ECB;
alg.Padding = PaddingMode.None;
CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(byteHashData, 0, byteHashData.Length);
cs.FlushFinalBlock();
byte[] CipherBytes = ms.ToArray();
ms.Close();
cs.Close();
String encryptedHashKey = toHexString(CipherBytes);
return encryptedHashKey;
}
public static String generateKeyId(String clearKey)
{
byte[] bytes = Encoding.UTF8.GetBytes(clearKey);
return toHexString(bytes);
}
}
private void static example()
{
String keyId = BcaKeyGenerator.GenerateKey.generateKeyId(clearKey);
sSignature = BcaKeyGenerator.GenerateKey.generateSignature(klikPayCode, transactionDate, transactionNo, totalAmount, currency, keyId);
sAuthKey = BcaKeyGenerator.GenerateKey.generateAuthKey(klikPayCode, transactionNo, currency, transactionDate, keyId);
}
<?php
function toHexString($string)
{
$hex = '';
for ($i=0; $i<strlen($string); $i++)
{
$ord = ord($string[$i]);
$hexCode = dechex($ord);
$hex .= substr('0'.$hexCode, -2);
}
return strToUpper($hex);
}
function fromHexString($hex)
{
$string = '';
for ($i=0; $i < strlen($hex)-1; $i+=2)
{
$string .= chr(hexdec($hex[$i].$hex[$i+1]));
}
return $string;
}
function generateSignature($klikPayCode, $transactionDate, $transactionNo, $amount, $currency, $keyId)
{
date_default_timezone_set("Asia/Jakarta");
$tempKey1 = $klikPayCode.$transactionNo.$currency.$keyId;
$hashKey1 = getHash($tempKey1);
$tdate = date_create_from_format("d/m/Y G:i:s",$transactionDate);
$idate = (int)date_format($tdate, 'dmY');
$iamount = (int)$amount;
$tempKey2 = ($idate + $iamount);
$tempKey2 = $tempKey2 . "";
$hashKey2 = getHash($tempKey2);
$hash = abs($hashKey1+$hashKey2);
return $hash."";
}
function generateAuthKey($klikPayCode, $transactionNo, $currency, $transactionDate, $keyId)
{
$str1 = str_pad($klikPayCode,10, '0', STR_PAD_RIGHT) . str_pad($transactionNo,18, 'A', STR_PAD_RIGHT) . str_pad($currency,5, '1',STR_PAD_RIGHT) . str_pad($transactionDate,19, 'C', STR_PAD_LEFT) . $keyId;
$mdstr1 = md5($str1);
$my_key = fromHexString($keyId);
$data = fromHexString($mdstr1);
$my_key .= substr($my_key,0,8);
$secret = mcrypt_encrypt(MCRYPT_3DES, $my_key, $data, MCRYPT_MODE_ECB);
return toHexString($secret);
}
function generateKeyId($str)
{
return toHexString($str);
}
function getHash ($value)
{
$hash = 0;
for ($i = 0; $i < strlen($value); $i++)
{
$hash = (intval($hash) * 31) + ord($value[$i]);
$hash = intval32bits($hash);
}
return (int)$hash;
}
function intval32bits($value)
{
$value = ($value & 0xFFFFFFFF);
if ($value & 0x80000000)
{
$value = -((~$value & 0xFFFFFFFF) + 1);
}
return $value;
}
$clearKey = "ClearKey00000001";
$klikPayCode = "BCAPAY0001";
//format: "d/m/Y G:i:s"
$transactionDate = "11/04/2014 16:15:53";
$transactionNo = "R223248";
$totalAmount = 3000.00;
$currency = "IDR";
$keyId = generateKeyId($clearKey);
$sSignature = generateSignature($klikPayCode, $transactionDate, $transactionNo, $totalAmount, $currency, $keyId);
$sAuthKey = generateAuthKey($klikPayCode, $transactionNo, $currency, $transactionDate, $keyId);
echo $keyId."<br/>".$sSignature."<br/>".$sAuthKey;
?>
Output
Berikut ini adalah data table spesifikasi pada output dan tipe data yag digunakan.
|
|
|
|
|
---|---|---|---|---|
1 | status | string (2) | (AN) | False |
2 | english | String (50) | (AN) | False |
3 | indonesian | String (50) | (AN) | False |
<?php
$vklikPayCode = $_REQUEST['klikPayCode'];
$vtransactionNo = $_REQUEST['transactionNo'];
$vtransactionDate = $_REQUEST['transactionDate'];
$vcurrency = $_REQUEST['currency'];
$vtotalAmount = $_REQUEST['totalAmount'];
$vpayType = $_REQUEST['payType'];
$vapprovalCodeFullTransaction
= $_REQUEST['approvalCodeFullTransaction'];
$vapprovalCodeInstallmentTransaction
= $_REQUEST['approvalCodeInstallmentTransaction'];
$vauthKey = $_REQUEST['authKey'];
$vadditionalData = $_REQUEST['additionalData'];
//Do Authkey & Amount checking,write success if correct
echo "00:||:Success.:||:Sukses.";
Key ID untuk Transaksi
Berikut Key ID yang digunakan untuk transaksi.

Catatan:
- clearKey: Clear key yang diberikan oleh BCA.
- bytes: Array daripada bytes dari clear key.
- hexArray: Array daripada char untuk karakter hexa.
- keyId: String daripada hexa dari clear key, dikenal sebagai current key yang digunakan untuk transaksi.
Lampiran
Berikut lampiran yang dapat digunakan sebagai informasi tambahan untuk integrasi dengan BCA KlikPay melalui iPay88 Indonesia.
Response Codes
Berikut ini adalah data table spesifikasi kode yang didapatkan ketika response dari merchant.
|
|
|
---|---|---|
1 | 00 | TRX_SUCCESS (*) |
2 | 01 | TRX_REJECTED (*) |
Reason (Deskripsi Error)
Berikut ini adalah data table spesifikasi untuk contoh penyebab kegagalan pada transaksi yang dapat digunakan oleh merchant.
|
|
|
---|---|---|
1 | Your transaction has been canceled | Transaksi Anda telah dibatalkan |
2 | Your transaction has been paid | Transaksi Anda sudah dibayar |
3 | Your transaction has expired or exceeded Your transaction has expired or exceededtime limit | Transaksi Anda sudah kadaluarsa atau telah mencapai waktu yang ditetapkan |
4 | Technical problem | Transaksi Anda tidak bisa diproses |
5 | Transaction data (amount, etc.) from bank is different with transaction data in the merchantTechnical problem | Transaksi Anda tidak sesuai |
Referensi
Kami berusaha memberikan informasi selengkap mungkin untuk Anda. Adanya informasi tersebut menjadikan proses integrasi Anda dengan iPay88 OPSG menjadi mudah dan cepat. Untuk itu, kami meyediakan referensi sebagai informasi tambahan untuk Anda. Berikut ini adalah referensi dari iPay88 OPSG.
Testing Credentials
Uji transaksi dengan metode pembayaran kartu kredit melalui sandbox memerlukan data sampel kartu. Berikut ini adalah testing credentials yang dapat digunakan untuk uji transaksi dengan metode pembayaran kartu kredit.
1. Pengujian Data
|
|
|
|
---|---|---|---|
|
|
|
|
|
|
|
|
2. Pengujian Data Eksespsi
|
|
|
|
|
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Payment ID
Berikut ini adalah daftar Payment ID iPay88 Indonesia berdasarkan metode pembayaran yang tersedia.
1. Credit Card
|
|
---|---|
Credit Card (BCA) |
|
Credit Card (BRI) |
|
Credit Card (CIMB) |
|
Credit Card (CIMB Authorization) |
|
Credit Card (CIMB IPG) |
|
Credit Card (Danamon) |
|
Credit Card (Mandiri) |
|
Credit Card (Maybank) |
|
Credit Card (UnionPay) |
|
Credit Card (UOB) |
|
Credit Card (GPN) |
|
2. Online Banking
|
|
---|---|
BCA KlikPay |
|
CIMB Clicks |
|
Muamalat IB |
|
Danamon Online Banking |
|
3. ATM Transfer
|
|
---|---|
Maybank VA |
|
Mandiri ATM |
|
BCA VA |
|
BNI VA |
|
Permata VA |
|
BRI VA |
|
4. e-Wallet
|
|
---|---|
ShopeePay |
|
DANA |
|
LinkAja |
|
OVO |
|
5. Others
|
|
---|---|
PayPal |
|
Kredivo |
|
Alfamart |
|
Indomaret |
|
Indodana |
|
Akulaku |
|
Mata Uang
Berikut ini adalah mata uang yang diharuskan untuk integrasi dengan iPay88 Indonesia.
|
|
---|---|
Indonesia Rupiah |
|
Deskripsi Error
Berikut ini adalah daftar pesan dan deskripsi error dari iPay88 Indonesia saat integrasi dengan merchant.
|
|
---|---|
Duplicate transaction reference number. | Nomor referensi digunakan kembali setelah nomor tersebut digunakan untuk pembayaran yang terlah sukses. |
Merchant identifier is missing or unregistered. | Merchant code tidak terdaftar atau merchant code salah. |
Transaction exceeds maximum allowed amount. | Kelebihan nilai total per transaksi. |
Unregistered merchant callback URL. | Request url milik merchant yang terdaftar di iPay88 tidak tepat. Silahkan registrasi request url situs Anda ke iPay88. |
Transaction signature is not match. | Signature yang dihasilkan merchant tidak tepat. |
Merchant account is suspended or inactive. | Akun telah disuspend atau tidak aktif. |
Invalid transaction amount format. | Format value pada parameter Amount tidak sesuai atau tidak ada value pada parameter tersebut ketika merchant request ke iPay88. |
Invalid transaction currency format. | Format value pada parameter Currency tidak sesuai atau tidak ada value pada parameter tersebut ketika merchant request ke iPay88. |
Invalid merchant identifier. | Format value pada parameter MerchantCode tidak sesuai atau tidak ada value pada parameter tersebut ketika merchant request ke iPay88. |
Invalid transaction channel identifier. | Format value pada parameter PaymentId tidak sesuai atau tidak ada value pada parameter tersebut ketika merchant request ke iPay88. |
Invalid purchased item description format. | Format value pada parameter ProdDesc tidak sesuai atau tidak ada value pada parameter tersebut ketika merchant request ke iPay88. |
Invalid transaction reference number. | Format value pada parameter RefNo tidak sesuai atau tidak ada value pada parameter tersebut ketika merchant request ke iPay88. |
Invalid customer email format. | Format value pada parameter UserEmail tidak sesuai atau tidak ada value pada parameter tersebut ketika merchant request ke iPay88. |
Invalid customer name format. | Format value pada parameter UserName tidak sesuai atau tidak ada value pada parameter tersebut ketika merchant request ke iPay88. |
Transaction time has expired when receiving authorization response. | Respon dari Issuer/Acquirer melebihi waktu transaksi (timeout). |
Payment method or channel is not subscribed. | Merchant menggunakan metode pembayaran yang tidak didaftarkan ke iPay88. |
Transaction does not pass all fraud security check. | Transaksi ditolak oleh parameter Fraud Detection System (FDS). |