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
  1. iPay88 Thailand does not yet provide the iFrame feature for the payment page on the merchant page.
  2. The CURL method cannot be used for all Thai iPay88 APIs.
  3. Do a test transaction in the development or sandbox phase first before entering the production phase.
  4. 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:

  1. ePayment: Multiple payment methods for merchant e-commerce website.
  2. 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

  1. Merchant Code dan Merchant Key from iPay88 are required.
  2. Merchant to provideRequest Url to iPay88 Support team.
  3. Registered Request URL must be either IP or domain based.
    Note: Localhost is not allowed.

Important Notice

  1. Test transaction must from registered Request URL
  2. Test transaction with amount IDR 3.000,00.
  3. Test transaction limited to credit cardONLY
  4. Credit Card test transaction will be refund at the end of day.
  5. Response URL can be set in request page with ResponseURL field.
  6. Backend post URL can be set in request page with BackendURL field.
  7. 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.
  8. Ensure a technical person is assigned by merchant before integration.
  9. 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.

  1. Merchant sends HTTPs Post Request containing payment details to iPay88 OPSG payment page. Payment Details contain the following fields:
    1. Merchant Code.
    2. Payment Method.
    3. Merchant Reference Number.
    4. Payment Amount.
    5. Currency.
    6. Product Description.
    7. Customer Name.
    8. Customer Email.
    9. Customer Contact.
    10. Merchant Remark.
    11. Signature.
    12. Response URL.
    13. Backend URL.

  2. User views and confirms payment details entered in Step 1. For credit card payment, the user will need to key-in credit card information.

  3. User continues to fill in Username and Password at bank website (for noncredit card payment)

  4. User selects the account to debit the payment. (for non-credit card payment)

  5. User confirms the payment. If yes, go to next step. (for non-credit card payment)

  6. User views and prints the payment detail. (for non-credit card payment)

  7. Response is returned to the iPay88 OPSG website indicating a successful or failed transaction.

  8. iPay88 OPSG response back the payment status to merchant with a signature

  9. 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

  1. Development: https://sandbox.ipay88.co.th/epayment/entry.asp
  2. Production: https://payment.ipay88.co.th/epayment/entry.asp
  3. 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


Field Name
Data Type
M/O
Description
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.


Field Name
Type (Size)
M/O
Description
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.

  1. Drupal
  2. Magento
  3. OpenCart
  4. Prestashop
  5. WHMCS
  6. Woocommerce
  7. WP Charitable


Note

  1. This Backend post feature will ONLY return status if the transaction is a payment success. No status will return if the payment is failed.

  2. The Backend page should implement checking same like response page such as signature checking, and etc. to prevent user hijack merchant system.

  3. 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.

  4. 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"

  5. 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


Field Name
Type (Size)
M/O
Description
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


Possible reply from iPay88 OPSG
Description
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):

  1. Check the HTTP_REFERER value is from https://payment.ipay88.co.th (only applicable if the merchant web site is working with SSL Certificate).
  2. Check the payment amount from iPay88 OPSG is match with yours.
  3. 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:

  1. MerchantKey (Provided by iPay88 OPSG and share between iPay88 and merchant only)
  2. MerchantCode
  3. RefNo
  4. Amount
  5. 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:

  1. MerchantKey ((Provided by iPay88 OPSG and share between iPay88 and merchant only)
  2. MerchantCode
  3. PaymentId
  4. RefNo
  5. Amount
  6. Currency
  7. 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.

  1. Merchant dapat mengunjungi laman laporan iPay88 OPSG melalui:
    1. Report URL
      • Sandbox: https://sandbox.ipay88.co.th/epayment/report/index.asp
      • Production: https://payment.ipay88.co.th/epayment/report/index.asp
    2. Login Name: disediakan oleh iPay88 OPSG
    3. Password: disediakan oleh iPay88 OPSG
  2. Setelah login, select all transaction, filter transaction date, dan klik search.
  3. 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:

  1. From your mailbox, please white-list iPay88 OPSG mail address by adding sales@ipay88.co.th into your friend list.
  2. Also, please make sure your mailbox has not blacklisted our address which is the following sales@ipay88.co.th
  3. 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.

Versi
Tanggal
Deskripsi Perubahan
1.6.1 21 Mei 2013
  1. Penerbitan pertama.
1.6.2 19 Desember 2017
  1. Menambah parameter status Pending dan Xfield1 dibagian payment request.
  2. Mengubah URL test signature.
  3. Mengubah sampel kode untuk payment request dan payment response.
  4. Menambah "Haven't Paid (0)", "Haven't Paid (1)", dan "Payment Pending" yang memungkinkan pada saat Re-Query.
  5. Mengubah signature dibagian request page dan response page.
  6. Mengubah report url.

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:

  1. ePayment: berbagai metode pembayaran untuk situs e-commerce milik merchant.
  2. 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

  1. Diharuskan menggunakan merchant code dan merchant key dari iPay88 Indonesia.
  2. Merchant harus menyediakan request url ke iPay88 Support Team.
  3. Request URL yang terdaftar harus berupa IP atau berbasis domain.
    Catatan: Localhost tidak diperbolehkan.

Catatan Penting

  1. Uji transaksi harus dari Request URL yang terdaftar.
  2. Uji transaksi dengan jumlah IDR 3.000,00.
  3. Uji transaksi bersifat terbatas untuk metode pembayaran dengan kartu kredit.
  4. Uji transaksi dengan kartu kredit akan dikembalikan (refund) pada hari akhir.
  5. Response URL dapat diatur dibagian input ResponseURL pada saat request laman pembayaran iPay88.
  6. Backend post URL dapat diatur dibagian input BackendURL pada saat request laman pembayaran iPay88.
  7. 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.
  8. Pastikan orang teknik ditugaskan oleh merchant sebelum integrasi.
  9. 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.

  1. Merchant mengirimkan HTTPs Post Request yang berisi detail pembayaran ke laman pembayaran iPay88 Indonesia. Detil pembayaran harus menyertakan:
    1. MerchantCode
    2. PaymentId
    3. RefNo
    4. Amount
    5. Currency
    6. ProdDesc
    7. UserName
    8. UserEmail
    9. UserContact
    10. Remark
    11. CCHolderName
    12. CCNo
    13. CCMonth
    14. CCYear
    15. CCCVV
    16. Lang
    17. Signature
    18. Response URL
    19. Backend URL

  2. iPay88 OPSG akan memverifikasi semua nilai yang dikirim oleh merchant, jika sudah sesuai dilanjutkan dengan kangkah berikutnya.

  3. Informasi akan dikirim ke bank untuk verifikasi lebih lanjut.

  4. Jika kartu tersebut adalah kartu 3D, halaman verifikasi 3D akan muncul, jika tidak akan dilanjutkan dengan langkah selanjutnya.

  5. Respon dikembalikan ke iPay88 Indonesia untuk untuk menunjukkan apakah transaksi telah berhasil atau gagal.

  6. iPay88 Indonesia merespon kembali status pembayaran ke merchant dengan signature.

  7. 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

  1. Development: https://sandbox.ipay88.co.id/epayment/entry_v2.asp
  2. Production: https://payment.ipay88.co.id/epayment/entry_v2.asp
  3. 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.


Nama Field
Tipe Data
M/O
Deskripsi
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.

Nama Field
Tipe Data
M/O
Deskripsi
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.

  1. Drupal
  2. Magento
  3. OpenCart
  4. Prestashop
  5. WHMCS
  6. Woocommerce
  7. WP Charitable


Catatan

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.


Nama Field
Tipe Data
M/O
Deskripsi
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.


Pesan
Deskripsi
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).

  1. Periksa nilai HTTP_REFERER dari https://payment.ipay88.co.id (hanya berlaku jika situs web merchant berfungsi dengan Sertifikat SSL).
  2. Periksa jumlah pembayaran dari iPay88 OPSG sesuai dengan pelanggan Anda.
  3. 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.

  1. MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 OPSG)
  2. MerchantCode
  3. RefNo
  4. CCNo
  5. CCMonth
  6. CCYear
  7. CCCVV
  8. Amount
  9. 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.

  1. MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 OPSG)
  2. MerchantCode
  3. PaymentId
  4. RefNo
  5. Amount
  6. Currency
  7. 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.

  1. Merchant dapat mengunjungi laman laporan iPay88 OPSG melalui:
    1. Report URL
      • Sandbox: https://sandbox.ipay88.co.id/epayment/report/index.asp
      • Production: https://payment.ipay88.co.id/epayment/report/index.asp
    2. Login Name: disediakan oleh iPay88 OPSG
    3. Password: disediakan oleh iPay88 OPSG
  2. Setelah login, select all transaction, filter transaction date, dan klik search.
  3. 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:

  1. Dari mailbox Anda, pastikan white-list alamat email iPay88 dengan menambahkan sales@ipay88.co.id ke dalam daftar teman Anda.
  2. Selain itu, pastikan mailbox Anda tidak melakukan black-list alamat email iPay88 yaitu sales@ipay88.co.id.
  3. 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.

  1. Subscription Request URL:
    https://payment.ipay88.co.id/recurringpayment2.0/subscription.asp
  2. 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.


Nama Field
Tipe Data
M/O
Deskripsi
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.


Nama Field
Tipe Data
M/O
Deskripsi
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.


Nama Field
Tipe Data
M/O
Deskripsi
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.


Nama Field
Tipe Data
M/O
Deskripsi
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.


Nama Field
Tipe Data
M/O
Deskripsi
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).

  1. Periksa nilai HTTP_REFERER dari https://payment.ipay88.co.id (hanya berlaku jika situs web merchant berfungsi dengan Sertifikat SSL).
  2. Periksa jumlah pembayaran dari iPay88 Indonesia sesuai dengan pelanggan Anda.
  3. 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.

  1. MerchantCode
  2. MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 Indonesia)
  3. RefNo
  4. Firstpaymentdate
  5. Currency
  6. Amount
  7. NumberofPayments
  8. 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.

  1. MerchantCode
  2. MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 Indonesia)
  3. 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.

  1. MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 Indonesia)
  2. MerchantCode
  3. PaymentId
  4. RefNo
  5. Amount
  6. Currency
  7. 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

  1. Development:
    https://sandbox.ipay88.co.id/ePayment/WebService/PaymentAPI/Checkout
  2. 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.


No
Nama Field
Tipe Data
M/O
Deskripsi
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 Email 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.


No
Nama Field
Tipe Data
M/O
Deskripsi
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.


Nama Field
Tipe Data
M/O
Deskripsi
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.

  1. Drupal
  2. Magento
  3. OpenCart
  4. Prestashop
  5. WHMCS
  6. Woocommerce
  7. WP Charitable


Catatan

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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).

  1. Periksa nilai HTTP_REFERER dari https://payment.ipay88.co.id (hanya berlaku jika situs web merchant berfungsi dengan Sertifikat SSL).
  2. Periksa jumlah pembayaran dari iPay88 OPSG sesuai dengan pelanggan Anda.
  3. 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.

  1. MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 OPSG)
  2. MerchantCode
  3. RefNo
  4. Amount
  5. 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.

  1. MerchantKey (disediakan dan hanya untuk merchant oleh iPay88 OPSG)
  2. MerchantCode
  3. PaymentId
  4. RefNo
  5. Amount
  6. Currency
  7. 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:

  1. UAT:
    https://sandbox.ipay88.co.id/ePayment/WebService/SeamlessPayment/Entry.asmx
  2. Production:
    https://payment.ipay88.co.id/ePayment/WebService/SeamlessPayment/Entry.asmx


Request

Berikut ini adalah data yang dikirimkan merchant dengan metode web service.


No
Nama Field
Tipe
Deskripsi
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.

  1. KlikPay Code
  2. Transaction Time (format: ddMMyyyy)
  3. Transaction Number
  4. Total Amount (catatan: format dalam nilai integer, tidak ada angka desimal)
  5. Currency
  6. 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.


No
Nama Field
Tipe
Deskripsi
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.

  1. KlikPay Code
  2. Transaction Time (format: ddMMyyyy)
  3. Transaction Number
  4. Total Amount (catatan: format dalam nilai integer, tidak ada angka desimal)
  5. Currency
  6. 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:

  1. Development:
    https://sandbox.ipay88.co.id/klikpaybca/purchasing/purchase.asp?action=loginRequest
  2. UAT:
    https://sb-ipay.klikbca.com:8081/purchasing/purchase.do?action=loginRequest
  3. Production:
    https://klikpay.klikbca.com/purchasing/purchase.do?action=loginRequest


Input

Berikut ini adalah data table spesifikasi pada input dan tipe data yag digunakan.


No
Nama Field
Deskripsi
Tipe
Format
M/O
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:

  1. (AN): Alpha-numeric format.
  2. 2 digit terakhir untuk totalAmount dan miscFee harus menjadi titik desimal. Titik desimal harus bernilai .00.
  3. Nilai dari TotalAmount adalah total untuk transaksi tetapi tidak termasuk miscFee.
  4. payType dapat diisi dengan nilai berikut:
    1. 01 = Full
    2. 02 = Installment
    3. 03 = 01 dan 02
  5. Currency harus bernilai IDR.
  6. M: Mandatory (diharuskan).
  7. 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.

  1. KlikPay Code
  2. Transaction Time (format: ddMMyyyy)
  3. Transaction Number
  4. Total Amount (catatan: format dalam nilai integer, tidak ada angka desimal)
  5. Currency
  6. 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:

  1. Payment flag from BCA to Merchant.
  2. Response from Merchant to BCA.


Input

Berikut ini adalah data table spesifikasi pada input dan tipe data yag digunakan.


No
Nama Field
Deskripsi
Tipe
Format
M/O
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:

  1. (AN): Alpha-numeric format.
  2. Approval Code untuk fullTransaction akan diisi jika pelanggan memiliki transaksi penuh dan memilih untuk melakukan pembayaran pada transaksi penuh tersebut menggunakan kartu kredit.
  3. Approval Code untuk installmentTransaction akan diisi jika pelanggan memiliki angsuran transaksi.
  4. 2 digit terakhir untuk totalAmount dan miscFee harus menjadi titik desimal. Titik desimal harus bernilai .00.
  5. Field pada totalAmount adalah total untuk transaksi.
  6. payType dapat diisi dengan nilai berikut:
    1. 01 = Full
    2. 02 = Installment
    3. 03 = 01 dan 02
  7. Currency harus bernilai IDR.
  8. M: Mandatory (diharuskan).
  9. 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.

  1. A = klikPayCode
  2. B = transactionNo
  3. C = currency
  4. D = transactionDate
  5. K = keyId (current key used for transaction)
  6. e = encrypt using 3DES by keyId
  7. 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.


No
Nama Field
Tipe
Format
Nullable
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:

  1. clearKey: Clear key yang diberikan oleh BCA.
  2. bytes: Array daripada bytes dari clear key.
  3. hexArray: Array daripada char untuk karakter hexa.
  4. 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.


No
Response Code
Response Code
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.


No
Condition
Reason (Error Deskripsi)
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

Card Number
CVV/CVV2
EXP Date (MM/YY)
Card Status
4000000000000044
123
03/33
Good card
5500000000000004
123
03/33
Good card

2. Pengujian Data Eksespsi

Card Number
CVV/CVV2
EXP Date (MM/YY)
Card Status
Error Message
4000000000000028
223
07/18
Bad card
Bank declined transaction
5200000000000007
223
07/18
Bad card
Bank declined transaction
5200000000000015
223
07/18
Bad card
Bank declined transaction


Payment ID

Berikut ini adalah daftar Payment ID iPay88 Indonesia berdasarkan metode pembayaran yang tersedia.


1. Credit Card

Metode Pembayaran
Payment ID
Credit Card (BCA)
52
Credit Card (BRI)
35
Credit Card (CIMB)
42
Credit Card (CIMB Authorization)
56
Credit Card (CIMB IPG)
34
Credit Card (Danamon)
45
Credit Card (Mandiri)
53
Credit Card (Maybank)
43
Credit Card (UnionPay)
54
Credit Card (UOB)
46
Credit Card (GPN)
49

2. Online Banking

Metode Pembayaran
Payment ID
BCA KlikPay
8
CIMB Clicks
11
Muamalat IB
14
Danamon Online Banking
23

3. ATM Transfer

Metode Pembayaran
Payment ID
Maybank VA
9
Mandiri ATM
17
BCA VA
25/30
BNI VA
26/68
Permata VA
31
BRI VA
61

4. e-Wallet

Metode Pembayaran
Payment ID
ShopeePay
75
DANA
77
LinkAja
13
OVO
63

5. Others

Metode Pembayaran
Payment ID
PayPal
6
Kredivo
55
Alfamart
60
Indomaret
65
Indodana
70
Akulaku
71


Mata Uang

Berikut ini adalah mata uang yang diharuskan untuk integrasi dengan iPay88 Indonesia.

Deskripsi Mata Uang
Simbol
Indonesia Rupiah
IDR


Deskripsi Error

Berikut ini adalah daftar pesan dan deskripsi error dari iPay88 Indonesia saat integrasi dengan merchant.

Pesan Error
Deskripsi Error
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).