yii-ipay88 yii-iPay88 API will help you to implement iPay88 payment gateway integration (Subodh Kr. Prasad: pdsubodh@gmail.com)

  1. Authentication
  2. Requirements
  3. Usage

yii-iPay88 API will help you to implement iPay88 payment gateway to your application. Following operationas are included in this API

  • Normal Payment
  • Recurring Payment
  • Recurring Payment Termination
  • Backend Notification

Authentication

yii-iPay88 API use hexadecimal and base64 encoded technique to create a unique signature. Then this signature is used on every request made by client and every response send by iPay88 server. Basically this signature is based on merchant code, merchant key, payment amount, currency code, refno., etc. All API requests must be made over HTTPS.

Requirements

  • The component is build for Yii framework version 1.1 or above
  • Credentials needed
    1. Merchant Code
    2. Merchant Key
    3. Currency Code

Usage

main.php

'components' => array(
....
'ipay' => array(
	    'class'=>'Ipay',	
	    'merchantCode'=>'<<merchantCode>>',
	    'merchantKey'=>'<<merchantKey>>',
	    'currencyCode'=>'MYR', // length 5						
	    'responseUrl'=>'http://<<hostname>>/ipay/response',
	    'backendUrl'=>'http://<<hostname>>/ipaybackend/response',
	    'requeryUrl'=>'https://www.mobile88.com/epayment/enquiry.asp',
	    'paymentUrl'=>'https://www.mobile88.com/epayment/entry.asp',
	    'recurringUrlSubscription'=>'https://www.ipay88.com/recurringpayment/webservice/RecurringPayment.asmx/Subscription',
	    'recurringUrlTermination'=>'https://www.ipay88.com/recurringpayment/webservice/RecurringPayment.asmx/Termination'
	    
    ),
....
)

A dummy controller to demonstrate the usage of this component for iPay88 normal payment and get that response

  • The Controller
    • controllers/IpayController.php
class IpayController extends Controller {

    const TRANSACTION_TYPE_PAYMENT = 'payment';
    const TRANSACTION_TYPE_RECURRING_SUBSCRIPTION = 'recurring_subscription';
    const TRANSACTION_TYPE_RECURRING_TERMINATION = 'recurring_termination';

    /*
     * iPay88 normal payment Method
     */
    public function actionPayment() {

        // Unique merchant transaction number / Order ID (Retry for same RefNo only valid for 30 mins). (length 20)
        $paymentParams['RefNo'] = 'TEST123';

        // (Optional) (int)
        $paymentParams['PaymentId'] = '2';

        // Payment amount with two decimals.
        $paymentParams['Amount'] = '1.00';

        // Product description. (length 100)
        $paymentParams['ProdDesc'] = 'This is a test product';

        // Customer name. (length 100)
        $paymentParams['UserName'] = 'Abc';

        // Customer email.  (length 100)
        $paymentParams['UserEmail'] = 'abc@xyz.com';

        // Customer contact.  (length 20)
        $paymentParams['UserContact'] = '*************';

        // (Optional) Merchant remarks. (length 100)
        $paymentParams['Remark'] = 'Here is the description';

        $paymentFields = Yii::app()->ipay->getPaymentFields($paymentParams, self::TRANSACTION_TYPE_PAYMENT);
        $transactionUrl = Yii::app()->ipay->getTransactionUrl(self::TRANSACTION_TYPE_PAYMENT);
        $this->render('Payment', array(
            'paymentFields' => $paymentFields,
            'transactionUrl' => $transactionUrl
        ));
    }
    
    
    /*
     * Response after making payment through iPay88 payment gateway
     */
    public function actionResponse() {
        $rawPostData = file_get_contents('php://input');

        /* 1. Return response by payment Method 
         *  MerchantCode -
         *  PaymentId    - (Optional)
         *  RefNo        -
         *  Amount       -
         *  Currency     -
         *  Remark       - (Optional)
         *  TransId      - (Optional) IPay88 transaction Id.
         *  AuthCode     - (Optional) Bank's approval code.
         *  Status       - Payment status:- 1 - Success, 0 - Failed.
         *  ErrDesc      - (Optional) Payment status description.
         *  Signature    -
         */

        /* 2. Return response from recurring subscripton payments Method
         * - MerchantCode     -
         * - RefNo            -
         * - SubscriptionNo   - Unique iPay88 subscription number. 'SubscriptionNo' will be the 'RefNo' that will be returned back to merchant 'BackendURL' when its charged.
         * - FirstPaymentDate -
         * - Amount           -
         * - Currency         -
         * - NumberOfPayments -
         * - Frequency        -
         * - Desc             - (Optional)
         * - Status           - Subscription status:- 1 - Success, 0 - Failed.
         * - ErrDesc          - (Optional)
         */
        $resultData = array();
        if (strlen($rawPostData) > 0) {
            $rawPostArray = explode('&', $rawPostData);
            foreach ($rawPostArray as $keyval) {
                $keyval = explode('=', $keyval);
                if (count($keyval) == 2)
                    $resultData[$keyval[0]] = urldecode($keyval[1]);
            }
        }

        $this->render('response', array(
            'resultData' => $resultData,
        ));
    }

        
}
  • The Components
    • components/Ipay.php
class Ipay extends CApplicationComponent {

    /**
     * Normal iPay88 payment method
     */
    const TRANSACTION_TYPE_PAYMENT = 'payment';

    /**
     * Normal iPay88 recurring payment subscription
     */
    const TRANSACTION_TYPE_RECURRING_SUBSCRIPTION = 'recurring_subscription';

    /**
     * Normal iPay88 recurring payment termination
     */
    const TRANSACTION_TYPE_RECURRING_TERMINATION = 'recurring_termination';

    /**
     * Merchant code assigned by iPay88
     */
    public $merchantCode;
    
    /**
     * Merchant Key assigned by iPay88
     */
    public $merchantKey;
    
    /**
     * Currency Code max length 5
     */
    public $currencyCode;
    
    /**
     * Merchant code assigned by iPay88
     */    
    public $responseUrl;
    
    /*
     * Response Url or Return Url after payment
     */
    public $paymentUrl;
    
    /*
     * Backend Url or Notify Url after payment (Send response by iPay88 server)
     */
    public $backendUrl;
    
    /*
     * Requery from iPay88 server regarding bill details
     */
    public $requeryUrl;
    
     /*
     * ipay88 Recurring Payment Url
     */
    public $recurringUrlSubscription;
    
     /*
     * ipay88 Recurring Payment Termination Url
     */
    public $recurringUrlTermination;
    
    
    /*
     * Details to be sent to IPay88 for payment request.
     */    
    private $paymentRequest = array(
        'MerchantCode', // Merchant code assigned by iPay88. (length 20)
        'PaymentId', // (Optional) (int)
        'RefNo', // Unique merchant transaction number / Order ID (Retry for same RefNo only valid for 30 mins). (length 20)
        'Amount', // Payment amount with two decimals.
        'Currency', // (length 5)
        'ProdDesc', // Product description. (length 100)
        'UserName', // Customer name. (length 100)
        'UserEmail', // Customer email.  (length 100)
        'UserContact', // Customer contact.  (length 20)
        'Remark', // (Optional) Merchant remarks. (length 100)
        'Lang', // (Optional) Encoding type:- ISO-8859-1 (English), UTF-8 (Unicode), GB2312 (Chinese Simplified), GD18030 (Chinese Simplified), BIG5 (Chinese Traditional)
        'Signature',
        'ResponseURL',
        'BackendURL',
    );

    
    /*
     * Details to be sent to iPay88 for recurring subscription payment request.
     */    
    private $recurringSubscriptionRequest = array(
        'MerchantCode', // Merchant code assigned by iPay88. (length 20)
        'RefNo', // Unique merchant transaction number / Order ID. (length 20)
        'FirstPaymentDate', // (ddmmyyyy)
        'Currency', // MYR only. (length 5)
        'Amount', // Payment amount with two decimals.
        'NumberOfPayments', // (int)
        'Frequency', // Frequency type; 1 - Monthly, 2 - Quarterly, 3 - Half-Yearly, 4 - Yearly. (int)
        'Desc', // Product description. (length 100)
        'CC_Name', // Name printed on credit card. (length 100)
        'CC_PAN', // 16-digit credit card number (Visa/Mastercard). (length 16)
        'CC_CVC', // 3-digit verification code behind credit card. (length 3)
        'CC_ExpiryDate', // Credit card expiry date. (mmyyyy)
        'CC_Country', // Credit card issuing country. (length 100)
        'CC_Bank', // Credit card issuing bank. (length 100)
        'CC_Ic', // Credit card holder IC / Passport number. (length 50)
        'CC_Email', // Credit card holder email address. (length 255)
        'CC_Phone', // Credit card phone number. (length 100)
        'CC_Remark', // (Optional) Remarks. (varchar 100)
        'P_Name', // Subscriber name as printed in IC / Passport. (length 100)
        'P_Email', // Subscriber email address. (length 255)
        'P_Phone', // Subscriber phone number. (length 100)
        'P_Addrl1', // Subscriber address line 1. (length 100)
        'P_Addrl2', // (Optional) Subscriber address line 2. (length 100)
        'P_City', // Subscriber city. (length 100)
        'P_State', // Subscriber state. (length 100)
        'P_Zip', // Subscriber zip code. (length 100)
        'P_Country', // Subscriber country. (varchar 100)
        'BackendURL', // Payment backend response page. (length 255)
        'Signature', // SHA1 signature. (length 100)
    );
    
    
    /*
     * Get required payment fields
     */
    public function getPaymentFields($reqParams = null, $paymentType) {
        $retnParams = array();
        try {
            if (isset($reqParams) && (count($reqParams) > 0)) {

                if (isset($paymentType) && $paymentType != "") {
                    $paymentType = strtolower(trim($paymentType));
                    switch ($paymentType) {
                        case 'payment':
                            $retnParams = $this->__getPaymentField($reqParams, $paymentType);
                            break;
                        case 'recurring_subscription':
                            $retnParams = $this->__getRecurringSubscriptionField($reqParams, $paymentType);
                            break;
                        case 'recurring_termination':
                            $retnParams = $this->__getRecurringTerminationField($reqParams, $paymentType);
                            break;
                    }
                } else {
                    throw new Exception("Ipay: Payment method missing");
                }
            } else {
                throw new Exception("Ipay: Required Parameters missing");
            }
        } catch (Exception $e) {
            Yii::log($e->getMessage(), CLogger::LEVEL_ERROR);
        }
        return $retnParams;
    }

    /*
     * Code for hex2bin 
     */
    public function _hex2bin($hexSource) {
        $bin = '';
        for ($i = 0; $i < strlen($hexSource); $i = $i + 2) {
            $bin .= chr(hexdec(substr($hexSource, $i, 2)));
        }
        return $bin;
    }

    /*
     * Get payment fields for normal payment fields 
     */
    public function __getPaymentField($reqParams, $paymentType) {
        $retnParams = array();
        foreach ($this->paymentRequest as $pymtKey) {
            if (isset($reqParams[$pymtKey])) {
                $retnParams[$pymtKey] = $reqParams[$pymtKey];
            } else {

                switch ($pymtKey) {
                    case 'MerchantCode':
                        $retnParams[$pymtKey] = $this->merchantCode;
                        break;
                    case 'Currency':
                        $retnParams[$pymtKey] = $this->currencyCode;
                        break;
                    case 'Lang':
                        $retnParams[$pymtKey] = 'UTF-8'; //(Optional) Encoding type:- ISO-8859-1 (English), UTF-8 (Unicode), GB2312 (Chinese Simplified), GD18030 (Chinese Simplified), BIG5 (Chinese Traditional)
                        break;
                    case 'Signature':
                        $retnParams[$pymtKey] = $this->__createSignature($retnParams, $paymentType); // SHA1 signature.
                        break;
                    case 'ResponseURL':
                        $retnParams[$pymtKey] = $this->responseUrl; // (Optional) Payment response page.
                        break;
                    case 'BackendURL':
                        $retnParams[$pymtKey] = $this->backendUrl; // (Optional) BackendURL but should security purpose
                        break;
                }
            }
        }

        return $retnParams;
    }
    
    /*
     * Get payment fields for recurring payment
     */
    public function __getRecurringSubscriptionField($reqParams, $paymentType) {
        $retnParams = array();
        foreach ($this->recurringSubscriptionRequest as $pymtKey) {
            if (isset($reqParams[$pymtKey])) {
                $retnParams[$pymtKey] = $reqParams[$pymtKey];
            } else {

                switch ($pymtKey) {
                    case 'MerchantCode':
                        $retnParams[$pymtKey] = $this->merchantCode;
                        break;
                    case 'Currency':
                        $retnParams[$pymtKey] = $this->currencyCode;
                        break;
                    case 'Lang':
                        $retnParams[$pymtKey] = 'UTF-8'; //(Optional) Encoding type:- ISO-8859-1 (English), UTF-8 (Unicode), GB2312 (Chinese Simplified), GD18030 (Chinese Simplified), BIG5 (Chinese Traditional)
                        break;
                    case 'Signature':
                        $retnParams[$pymtKey] = $this->__createSignature($retnParams, $paymentType); // SHA1 signature.
                        break;
                    case 'ResponseURL':
                        $retnParams[$pymtKey] = $this->responseUrl; // (Optional) Payment response page.
                        break;
                    case 'BackendURL':
                        $retnParams[$pymtKey] = $this->backendUrl; // (Optional) BackendURL but should security purpose
                        break;
                }
            }
        }

        return $retnParams;
    }

    
    
    /*
     * Get payment fields for recurring payment termination
     */
    public function __getRecurringTerminationField($reqParams, $paymentType) {
        $retnParams = array();
        foreach ($this->recurringSubscriptionRequest as $pymtKey) {
            if (isset($reqParams[$pymtKey])) {
                $retnParams[$pymtKey] = $reqParams[$pymtKey];
            } else {

                switch ($pymtKey) {
                    case 'MerchantCode':
                        $retnParams[$pymtKey] = $this->merchantCode;
                        break;
                }
            }
        }

        return $retnParams;
    }
    
    /*
     * Create signature for payment
     */
    public function __createSignature($signatureParams, $paymentType) {
        //echo "<pre>";
        //print_r($signatureParams);
        $signature = '';
        if (isset($signatureParams)) {
            $_signatureParams = array();
            if ($paymentType == self::TRANSACTION_TYPE_PAYMENT) {
                $_signatureParams = array('MerchantCode', 'RefNo', 'Amount', 'Currency');
            } else if ($paymentType == self::TRANSACTION_TYPE_RECURRING_SUBSCRIPTION) {
                $_signatureParams = array('MerchantCode', 'RefNo', 'FirstPaymentDate', 'Currency', 'Amount', 'NumberOfPayments', 'Frequency', 'CC_PAN');
            } else if ($paymentType == self::TRANSACTION_TYPE_RECURRING_TERMINATION) {
                $_signatureParams = array('MerchantCode', 'RefNo');
            }


            foreach ($_signatureParams as $val) {
                if (!isset($signatureParams[$val])) {
                    throw new Exception("Ipay: Missing required parameters for signature.");
                    return false;
                }
            }
        }

        // Make sure the order is correct.
        if ($paymentType == self::TRANSACTION_TYPE_PAYMENT) {
            $signature .= $this->merchantKey;
            $signature .= $signatureParams['MerchantCode'];
            $signature .= $signatureParams['PaymentId'];
            $signature .= $signatureParams['RefNo'];
            $signature .= preg_replace("/[^\d]+/", "", $signatureParams['Amount']);
            $signature .= $signatureParams['Currency'];
        } else if ($paymentType == self::TRANSACTION_TYPE_RECURRING_SUBSCRIPTION) {
            $signature .= $signatureParams['MerchantCode'];
            $signature .= $this->merchantKey;
            $signature .= $signatureParams['RefNo'];
            $signature .= $signatureParams['FirstPaymentDate'];
            $signature .= $signatureParams['Currency'];
            $signature .= $signatureParams['Amount'];
            $signature .= $signatureParams['NumberOfPayments'];
            $signature .= $signatureParams['Frequency'];
            $signature .= $signatureParams['CC_PAN'];
        } else if ($paymentType == self::TRANSACTION_TYPE_RECURRING_TERMINATION) {
            $signature .= $signatureParams['MerchantCode'];
            $signature .= $this->merchantKey;
            $signature .= $signatureParams['RefNo'];
        }


        // Hash the signature.
        return $signature = base64_encode($this->_hex2bin(sha1($signature)));
    }

    /*
     * Get url for respective payment redirection url
     */
    public function getTransactionUrl($paymentType) {
        if ($paymentType == self::TRANSACTION_TYPE_PAYMENT) {
            return $this->paymentUrl;
        } else if ($paymentType == self::TRANSACTION_TYPE_RECURRING_SUBSCRIPTION) {
            return $this->recurringUrlSubscription;
        } else if ($paymentType == self::TRANSACTION_TYPE_RECURRING_TERMINATION) {
            return $this->recurringUrlTermination;
        }
    }


    /*
     * iPay88 payment signature validation
     */
    public function checkiPay88Signature($reqParams) {
        $status = 'fail';
        try {
            if (isset($reqParams) && count($reqParams) > 0) {
                $orginalKey = $this->merchantKey . $this->merchantCode;
                if (isset($reqParams['RefNo'])) {
                    $orginalKey .=$reqParams['RefNo'];
                }

                if (isset($reqParams['Amount'])) {
                    $orginalKey .=preg_replace("/[^\d]+/", "", $reqParams['Amount']);
                }
                $orginalKey .= $this->currencyCode;
                if (isset($reqParams['Status'])) {
                    $orginalKey .=$reqParams['Status'];
                }

                $orginalKeyGen = base64_encode($this->_hex2bin(sha1($orginalKey)));
                $returnKey = $this->merchantKey;
                if (isset($reqParams['MerchantCode'])) {
                    $returnKey .=$reqParams['MerchantCode'];
                }


                if (isset($reqParams['RefNo'])) {
                    $returnKey .=$reqParams['RefNo'];
                }
                if (isset($reqParams['Amount'])) {
                    $returnKey .=preg_replace("/[^\d]+/", "", $reqParams['Amount']);
                }
                if (isset($reqParams['Currency'])) {
                    $returnKey .=$reqParams['Currency'];
                }
                if (isset($reqParams['Status'])) {
                    $returnKey .=$reqParams['Status'];
                }


                $returnKeyGen = base64_encode($this->_hex2bin(sha1($returnKey)));
                if ($orginalKeyGen === $returnKeyGen) {
                    $status = 'success';
                }
            } else {
                throw new Exception("Ipay::checkiPay88Signature: Params missing");
            }
        } catch (exception $e) {
            Yii::log($e->getMessage(), CLogger::LEVEL_ERROR);
        }

        return $status;
    }

    /*
     * Curl hit to get bill deyails 
     */
    public function requeryPayment($rawPostData) {
        try {
            $result = '';
            if (is_callable('curl_init')) {
                if (isset($rawPostData) && $rawPostData != "") {
                    $ch = curl_init();
                    $url = $this->requeryUrl . '?' . $rawPostData;
                    curl_setopt($ch, CURLOPT_URL, $url);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                    $result = curl_exec($ch);
                    curl_close($ch);
                } else {
                    throw new Exception("Ipay::requeryPayment: No request string");
                }
            } else {
                throw new Exception("Ipay::requeryPayment: Curl not enabled");
            }
        } catch (exception $e) {
            Yii::log($e->getMessage(), CLogger::LEVEL_ERROR);
        }

        return $result;
    }

}
  • The View
    • views/ipay/payment.php
<h3>IPay88: Payment</h3>
<?php if (!empty($paymentFields)): ?>
        <form action="<?php echo $transactionUrl; ?>" method="post">
            <table>
                <?php foreach ($paymentFields as $key => $val): ?>
                    <tr>
                        <td><label><?php echo $key; ?></label></td>
                        <td><input type="text" readonly="readonly" name="<?php echo $key; ?>" value="<?php echo $val; ?>" /></td>
                    </tr>
                <?php endforeach; ?>
                <tr>
                <td colspan="2"><input type="submit" value="Pay Now" name="Pay with IPay88" /></td>
                </tr>
            </table>
        </form>
    <?php endif; ?>
    
   

views/ipay/response.php

<h3>IPay88: Payment Result</h3>
<br/>
<?php 
if(count($resultData)> 0){
?>
<b>Transaction Id: </b><?php echo $resultData['TransId'];?><br/>
<?php 
echo "<pre>";
print_r($resultData);
}
else{
	echo "Payment Error";
}
?>

1 0
1 follower
126 downloads
Yii Version: 1.1
License: BSD-2-Clause
Category: Others
Developed by: pd_subodh
Created on: Dec 6, 2015
Last updated: 3 years ago

Downloads

show all

Related Extensions