mrsnax

iPay88 Class <Indonesia>

Aug 4th, 2015
1,809
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 30.76 KB | None | 0 0
  1. <?php
  2.  
  3. /**
  4.  * Integrate Ipay88 (Malaysia) payment gateway system.
  5.  *
  6.  * @author Leow Kah Thong <http://kahthong.com>
  7.  * @edited Sterli <http://www.sterli.net><FOR INDONESIA PAYMENT>
  8.  * @copyright Leow Kah Thong 2012
  9.  * @version 2.0
  10.  */
  11. class IPay88 {
  12.  
  13.     // Payment methods, please view technical spec for latest update.
  14.     // for Engienring please edit array below with Indonesia Region.
  15.     public static $paymentMethods = array(
  16.         54 => array('Alipay', 'USD'),
  17.         8 => array('Alliance Online Transfer', 'MYR'),
  18.         10 => array('AmBank', 'MYR'),
  19.         21 => array('China Union Pay', 'MYR'),
  20.         20 => array('CIMB Clicks', 'MYR'),
  21.         39 => array('Credit Card', 'AUD'),
  22.         37 => array('Credit Card', 'CAD'),
  23.         41 => array('Credit Card', 'EUR'),
  24.         35 => array('Credit Card', 'GBP'),
  25.         42 => array('Credit Card', 'HKD'),
  26.         46 => array('Credit Card', 'IDR'),
  27.         45 => array('Credit Card', 'INR'),
  28.         2 => array('Credit Card', 'MYR'),
  29.         40 => array('Credit Card', 'MYR'), // For multi-currency only
  30.         47 => array('Credit Card', 'PHP'),
  31.         38 => array('Credit Card', 'SGD'),
  32.         36 => array('Credit Card', 'THB'),
  33.         50 => array('Credit Card', 'TWD'),
  34.         25 => array('Credit Card', 'USD'),
  35.         16 => array('FPX', 'MYR'),
  36.         15 => array('Hong Leong Bank Transfer', 'MYR'),
  37.         6 => array('Maybank2U', 'MYR'),
  38.         23 => array('Meps Cash', 'MYR'),
  39.         17 => array('Mobile Money', 'MYR'),
  40.         32 => array('Payeasy', 'PHP'),
  41.         65 => array('PayPal', 'AUD'),
  42.         63 => array('PayPal', 'CAD'),
  43.         66 => array('PayPal', 'EUR'),
  44.         61 => array('PayPal', 'GBP'),
  45.         67 => array('PayPal', 'HKD'),
  46.         48 => array('PayPal', 'MYR'),
  47.         56 => array('PayPal', 'PHP'),
  48.         64 => array('PayPal', 'SGD'),
  49.         62 => array('PayPal', 'THB'),
  50.         68 => array('PayPal', 'TWD'),
  51.         33 => array('PayPal', 'USD'),
  52.         53 => array('Paysbuy (Credit Card only)', 'THB'),
  53.         52 => array('Paysbuy (E-wallet & Counter Services only)', 'THB'),
  54.         14 => array('RHB', 'MYR'),
  55.     );
  56.  
  57.     public static $paymentUrl               = 'https://www.ipay88.co.id/epayment/entry.asp';
  58.     public static $requeryUrl               = 'https://www.ipay88.co.id/epayment/enquiry.asp';
  59.     public static $refererHost              = 'www.ipay88.co.id';  // Without scheme (http/https).
  60. /*
  61.     public static $recurringUrlSubscription = 'https://www.ipay88.co.id/recurringpayment/webservice/RecurringPayment.asmx/Subscription';
  62.     public static $recurringUrlTermination  = 'https://www.ipay88.co.id/recurringpayment/webservice/RecurringPayment.asmx/Termination';
  63. */
  64.  
  65.     private $merchantKey = '';
  66.  
  67.     const TRANSACTION_TYPE_PAYMENT                = 'payment';
  68.     const TRANSACTION_TYPE_RECURRING_SUBSCRIPTION = 'recurring_subscription';
  69.     const TRANSACTION_TYPE_RECURRING_TERMINATION  = 'recurring_termination';
  70.     private $transactionType = '';
  71.  
  72.     // Details to be sent to IPay88 for payment request.
  73.     private $paymentRequest = array(
  74.       'MerchantCode' => '',       // Merchant code assigned by iPay88. (varchar 20)
  75.       'PaymentId'    => '',       // (Optional) (int)
  76.       'RefNo'        => '',       // Unique merchant transaction number / Order ID (Retry for same RefNo only valid for 30 mins). (varchar 20)
  77.       'Amount'       => '',       // Payment amount with two decimals.
  78.       'Currency'     => '',       // (varchar 5)
  79.       'ProdDesc'     => '',       // Product description. (varchar 100)
  80.       'UserName'     => '',       // Customer name. (varchar 100)
  81.       'UserEmail'    => '',       // Customer email.  (varchar 100)
  82.       'UserContact'  => '',       // Customer contact.  (varchar 20)
  83.       'Remark'       => '',       // (Optional) Merchant remarks. (varchar 100)
  84.       'Lang'         => 'UTF-8',  // (Optional) Encoding type:- ISO-8859-1 (English), UTF-8 (Unicode), GB2312 (Chinese Simplified), GD18030 (Chinese Simplified), BIG5 (Chinese Traditional)
  85.       'Signature'    => '',       // SHA1 signature.
  86.       'ResponseURL'  => '',       // (Optional) Payment response page.
  87.     );
  88.     /* Return response from iPay88 for normal payments:
  89.      * - MerchantCode -
  90.      * - PaymentId    - (Optional)
  91.      * - RefNo        -
  92.      * - Amount       -
  93.      * - Currency     -
  94.      * - Remark       - (Optional)
  95.      * - TransId      - (Optional) IPay88 transaction Id.
  96.      * - AuthCode     - (Optional) Bank's approval code.
  97.      * - Status       - Payment status:- 1 - Success, 0 - Failed.
  98.      * - ErrDesc      - (Optional) Payment status description.
  99.      * - Signature    -
  100.      */
  101.  
  102.     // Details to be sent to iPay88 for recurring subscription payment request.
  103.     private $recurringSubscriptionRequest = array(
  104.       'MerchantCode'     => '',  // Merchant code assigned by iPay88. (varchar 20)
  105.       'RefNo'            => '',  // Unique merchant transaction number / Order ID. (varchar 20)
  106.       'FirstPaymentDate' => '',  // (ddmmyyyy)
  107.       'Currency'         => '',  // MYR only. (varchar 5)
  108.       'Amount'           => '',  // Payment amount with two decimals.
  109.       'NumberOfPayments' => '',  // (int)
  110.       'Frequency'        => '',  // Frequency type; 1 - Monthly, 2 - Quarterly, 3 - Half-Yearly, 4 - Yearly. (int)
  111.       'Desc'             => '',  // Product description. (varchar 100)
  112.       'CC_Name'          => '',  // Name printed on credit card. (varchar 100)
  113.       'CC_PAN'           => '',  // 16-digit credit card number (Visa/Mastercard). (varchar 16)
  114.       'CC_CVC'           => '',  // 3-digit verification code behind credit card. (varchar 3)
  115.       'CC_ExpiryDate'    => '',  // Credit card expiry date. (mmyyyy)
  116.       'CC_Country'       => '',  // Credit card issuing country. (varchar 100)
  117.       'CC_Bank'          => '',  // Credit card issuing bank. (varchar 100)
  118.       'CC_Ic'            => '',  // Credit card holder IC / Passport number. (varchar 50)
  119.       'CC_Email'         => '',  // Credit card holder email address. (varchar 255)
  120.       'CC_Phone'         => '',  // Credit card phone number. (varchar 100)
  121.       'CC_Remark'        => '',  // (Optional) Remarks. (varchar 100)
  122.       'P_Name'           => '',  // Subscriber name as printed in IC / Passport. (varchar 100)
  123.       'P_Email'          => '',  // Subscriber email address. (varchar 255)
  124.       'P_Phone'          => '',  // Subscriber phone number. (varchar 100)
  125.       'P_Addrl1'         => '',  // Subscriber address line 1. (varchar 100)
  126.       'P_Addrl2'         => '',  // (Optional) Subscriber address line 2. (varchar 100)
  127.       'P_City'           => '',  // Subscriber city. (varchar 100)
  128.       'P_State'          => '',  // Subscriber state. (varchar 100)
  129.       'P_Zip'            => '',  // Subscriber zip code. (varchar 100)
  130.       'P_Country'        => '',  // Subscriber country. (varchar 100)
  131.       'BackendURL'       => '',  // Payment backend response page. (varchar 255)
  132.       'Signature'        => '',  // SHA1 signature. (varchar 100)
  133.     );
  134.     /* Return response from iPay88 for recurring subscripton payments:
  135.      * - MerchantCode     -
  136.      * - RefNo            -
  137.      * - SubscriptionNo   - Unique iPay88 subscription number. 'SubscriptionNo' will be the 'RefNo' that will be returned back to merchant 'BackendURL' when its charged.
  138.      * - FirstPaymentDate -
  139.      * - Amount           -
  140.      * - Currency         -
  141.      * - NumberOfPayments -
  142.      * - Frequency        -
  143.      * - Desc             - (Optional)
  144.      * - Status           - Subscription status:- 1 - Success, 0 - Failed.
  145.      * - ErrDesc          - (Optional)
  146.      */
  147.  
  148.     // Details to be sent to iPay88 for recurring termination request.
  149.     private $recurringTerminationRequest = array(
  150.       'MerchantCode' => '',  // Merchant code assigned by iPay88. (varchar 20)
  151.       'RefNo'        => '',  // Unique merchant transaction number / Order ID. (varchar 20)
  152.       'Signature'    => '',  // SHA1 signature. (varchar 20) ???
  153.     );
  154.     /* Return response from iPay88 for recurring termination request:
  155.      * - MerchantCode -
  156.      * - RefNo        -
  157.      * - Status       - Subscription status:- 1 - Success, 0 - Failed.
  158.      * - ErrDesc      - (Optional)
  159.      */
  160.  
  161.     /* Response from iPay88 after recurring payment is charged.
  162.      * - MerchantCode -
  163.      * - PaymentId    - Default to 2 (credit card MYR).
  164.      * - RefNo        - Unique transaction number returned from iPay88.
  165.      *                  This is the 'SubscriptionNo' returned to merchant after subscription of recurring payment.
  166.      *                  Eg:
  167.      *                    S00001701-1 (First recurring payment)
  168.      *                    S00001701-2 (Second recurring payment)
  169.      *                  The returned 'RefNo' will have a hyphen followed by a number to indicate the installment.
  170.      * - Amount       -
  171.      * - Currency     - Default to MYR.
  172.      * - Remark       - (Optional)
  173.      * - TransId      - (Optional) iPay88 transaction ID.
  174.      * - AuthCode     - (Optional) Bank's approval code.
  175.      * - Status       - Payment status:- 1 - Success, 0 - Failed.
  176.      * - ErrDesc      - (Optional)
  177.      * - Signature    -
  178.      */
  179.  
  180.     /**
  181.      * @access public
  182.      * @param string $merchantCode Merchant code supplied by Ipay88.
  183.      * @param string $merchantKey Merchant key supplied by Ipay88.
  184.      * @param string $transactionType (Optional) Transaction type. Available values are; TRANSACTION_TYPE_PAYMENT, TRANSACTION_TYPE_RECURRING_SUBSCRIPTION, or TRANSACTION_TYPE_RECURRING_TERMINATION.
  185.      */
  186.     public function __construct($merchantCode, $merchantKey, $transactionType = self::TRANSACTION_TYPE_PAYMENT) {
  187.         $this->setField('MerchantCode', $merchantCode);
  188.         $this->setMerchantKey($merchantKey);
  189.         $this->setTransactionType($transactionType);
  190.     }
  191.  
  192.     /**
  193.      * Validate the data given by user according to the rules specified by IPay88 API.
  194.      *
  195.      * @access public
  196.      * @param string $field The field to check.
  197.      * @param string $data  Data supplied by user.
  198.      * @return boolean true if passed validation and vice-versa.
  199.      */
  200.     public function validateField($field, $data) {
  201.         switch ($field) {
  202.             case 'MerchantCode':
  203.             case 'RefNo':
  204.             case 'UserContact':
  205.                 if (strlen($data) <= 20) {
  206.                     return true;
  207.                 }
  208.                 break;
  209.             case 'PaymentId':
  210.             case 'NumberOfPayments':
  211.                 if (is_int($data)) {
  212.                     return true;
  213.                 }
  214.                 break;
  215.             case 'Amount':
  216.                 if (preg_match('^[0-9]+\.[0-9]{2}$^', $data)) {
  217.                     return true;
  218.                 }
  219.                 break;
  220.             case 'Currency':
  221.                 if (strlen($data) <= 5) {
  222.                     return true;
  223.                 }
  224.                 break;
  225.             case 'CC_Email':
  226.             case 'P_Email':
  227.             case 'BackendURL':
  228.                 if (strlen($data) <= 255) {
  229.                     return true;
  230.                 }
  231.                 break;
  232.             case 'ProdDesc':
  233.             case 'UserName':
  234.             case 'UserEmail':
  235.             case 'Remark':
  236.             case 'Desc':
  237.             case 'CC_Name':
  238.             case 'CC_Country':
  239.             case 'CC_Bank':
  240.             case 'CC_Phone':
  241.             case 'CC_Remark':
  242.             case 'P_Name':
  243.             case 'P_Phone':
  244.             case 'P_Addrl1':
  245.             case 'P_Addrl2':
  246.             case 'P_City':
  247.             case 'P_State':
  248.             case 'P_Zip':
  249.             case 'P_Country':
  250.                 if (strlen($data) <= 100) {
  251.                     return true;
  252.                 }
  253.                 break;
  254.             case 'CC_Ic':
  255.                 if (strlen($data) <= 50) {
  256.                     return true;
  257.                 }
  258.                 break;
  259.             case 'Lang':
  260.                 if (in_array(strtoupper($data), array('ISO-8859-1', 'UTF-8', 'GB2312', 'GD18030', 'BIG5'))) {
  261.                     return true;
  262.                 }
  263.                 break;
  264.             case 'Signature':
  265.                 if (strlen($data) <= 40) {
  266.                     return true;
  267.                 }
  268.                 break;
  269.             case 'FirstPaymentDate':
  270.                 if (strlen($data) == 8) {
  271.                     return true;
  272.                 }
  273.                 break;
  274.             case 'CC_ExpiryDate':
  275.                 if (strlen($data) == 6) {
  276.                     return true;
  277.                 }
  278.                 break;
  279.             case 'Frequency':
  280.                 if (in_array((int) $data, array(1, 2, 3, 4))) {
  281.                     return true;
  282.                 }
  283.                 break;
  284.             case 'CC_PAN':
  285.                 if (ctype_digit($data) && strlen($data) == 16) {
  286.                     return true;
  287.                 }
  288.                 break;
  289.             case 'CC_CVC':
  290.                 if (ctype_digit($data) && strlen($data) == 3) {
  291.                     return true;
  292.                 }
  293.                 break;
  294.             case 'MerchantKey':
  295.             case 'ResponseURL':
  296.             case 'TransId':
  297.             case 'AuthCode':
  298.             case 'Status':
  299.             case 'ErrDesc':
  300.             case 'SubscriptionNo':
  301.                 return true;
  302.         }
  303.  
  304.         return false;
  305.     }
  306.  
  307.     /**
  308.      * @access private
  309.      * @return string Merchant key.
  310.      */
  311.     private function getMerchantKey() {
  312.         return $this->merchantKey;
  313.     }
  314.  
  315.     /**
  316.      * Get info about payment method.
  317.      *
  318.      * @access public
  319.      * @param int $paymentId Payment method ID.
  320.      * @return array Name and currency of payment method.
  321.      */
  322.     public function getPaymentMethod($paymentId) {
  323.         if (isset(self::$paymentMethods[$paymentId])) {
  324.             list($name, $currency) = self::$paymentMethods[$paymentId];
  325.             return array(
  326.                 'name' => $name,
  327.                 'currency' => $currency,
  328.             );
  329.         }
  330.     }
  331.  
  332.     /**
  333.      * Wrapper method to receive response and return status. If transaction was successful, a requery will be done to double-check.
  334.      *
  335.      * @access public
  336.      * @param boolean $requery     (Optional) Whether to requery Ipay88 server for transaction confirmation.
  337.      * @param boolean $return_data (Optional) Whether to return data back.
  338.      * @return array Status of the transaction and processed response.
  339.      */
  340.     public function getResponse($requery = true, $return_data = true) {
  341.         $return = array(
  342.             'status' => '',
  343.             'message' => '',
  344.             'data' => array(),
  345.         );
  346.  
  347.         $data = $_POST;
  348.         $return['status'] = isset($data['Status']) ? $data['Status'] : false;
  349.         $return['message'] = isset($data['ErrDesc']) ? $data['ErrDesc'] : '';
  350.  
  351.         if ($requery && $return['status']) {
  352.             $data['_RequeryStatus'] = $this->requery($data);
  353.             if ($data['_RequeryStatus'] != '00') {
  354.                 // Requery failed, return empty array.
  355.                 $return['status'] = false;
  356.                 return $return;
  357.             }
  358.         }
  359.  
  360.         if ($return_data) {
  361.             $return['data'] = $data;
  362.         }
  363.  
  364.         return $return;
  365.     }
  366.  
  367.     /**
  368.      * Return all the fields (normally after setField() method is called).
  369.      * Can be used to populate forms.
  370.      *
  371.      * @access public
  372.      * @return array Payment method fields.
  373.      */
  374.     public function getFields() {
  375.         if ($this->getTransactionType() == self::TRANSACTION_TYPE_PAYMENT) {
  376.             return $this->paymentRequest;
  377.         } else if ($this->getTransactionType() == self::TRANSACTION_TYPE_RECURRING_SUBSCRIPTION) {
  378.             return $this->recurringSubscriptionRequest;
  379.         } else if ($this->getTransactionType() == self::TRANSACTION_TYPE_RECURRING_TERMINATION) {
  380.             return $this->recurringTerminationRequest;
  381.         }
  382.     }
  383.  
  384.     /**
  385.      * Get payment URL.
  386.      *
  387.      * @access public
  388.      * @return array Payment method fields.
  389.      */
  390.     public function getTransactionUrl() {
  391.         if ($this->getTransactionType() == self::TRANSACTION_TYPE_PAYMENT) {
  392.             return self::$paymentUrl;
  393.         } else if ($this->getTransactionType() == self::TRANSACTION_TYPE_RECURRING_SUBSCRIPTION) {
  394.             return self::$recurringUrlSubscription;
  395.         } else if ($this->getTransactionType() == self::TRANSACTION_TYPE_RECURRING_TERMINATION) {
  396.             return self::$recurringUrlTermination;
  397.         }
  398.     }
  399.  
  400.     /**
  401.      * Return individual field values.
  402.      *
  403.      * @access public
  404.      * @param string $field Field name.
  405.      * @return string Value of the field. If field name is invalid, returns FALSE.
  406.      */
  407.     public function getField($field) {
  408.         if ($this->getTransactionType() == self::TRANSACTION_TYPE_PAYMENT) {
  409.             return (isset($this->paymentRequest[$field]) ? $this->paymentRequest[$field] : false);
  410.         } else if ($this->getTransactionType() == self::TRANSACTION_TYPE_RECURRING_SUBSCRIPTION) {
  411.             return (isset($this->recurringSubscriptionRequest[$field]) ? $this->recurringSubscriptionRequest[$field] : false);
  412.         } else if ($this->getTransactionType() == self::TRANSACTION_TYPE_RECURRING_TERMINATION) {
  413.             return (isset($this->recurringTerminationRequest[$field]) ? $this->recurringTerminationRequest[$field] : false);
  414.         }
  415.     }
  416.  
  417.     /**
  418.      * Get the current transaction type / mode.
  419.      *
  420.      * @access public
  421.      * @return string Transaction type.
  422.      */
  423.     public function getTransactionType() {
  424.         return $this->transactionType;
  425.     }
  426.  
  427.     /**
  428.      * Change transaction type.
  429.      *
  430.      * @access public
  431.      * @param string $transactionType Transaction type.
  432.      */
  433.     public function setTransactionType($transactionType) {
  434.         if ($transactionType == self::TRANSACTION_TYPE_PAYMENT || $transactionType == self::TRANSACTION_TYPE_RECURRING_SUBSCRIPTION || $transactionType == self::TRANSACTION_TYPE_RECURRING_TERMINATION) {
  435.             $this->transactionType = $transactionType;
  436.         }
  437.     }
  438.  
  439.     /**
  440.      * Set variable to field. Data supplied will be validated before it is set and any error found will be thrown to user.
  441.      *
  442.      * @access public
  443.      * @param string $field The field name to set.
  444.      * @param string $data  Data supplied by user.
  445.      */
  446.     public function setField($field, $data) {
  447.         if ($this->validateField($field, $data)) {
  448.             switch ($field) {
  449.                 case 'Currency':
  450.                 case 'Lang':
  451.                     $data = strtoupper($data);
  452.                     break;
  453.             }
  454.  
  455.             if ($field == 'MerchantCode') {
  456.                 $this->paymentRequest[$field] = $data;
  457.                 $this->recurringSubscriptionRequest[$field] = $data;
  458.                 $this->recurringTerminationRequest[$field] = $data;
  459.             } else {
  460.                 if ($this->getTransactionType() == self::TRANSACTION_TYPE_PAYMENT) {
  461.                     $this->paymentRequest[$field] = $data;
  462.                 } else if ($this->getTransactionType() == self::TRANSACTION_TYPE_RECURRING_SUBSCRIPTION) {
  463.                     $this->recurringSubscriptionRequest[$field] = $data;
  464.                 } else if ($this->getTransactionType() == self::TRANSACTION_TYPE_RECURRING_TERMINATION) {
  465.                     $this->recurringTerminationRequest[$field] = $data;
  466.                 }
  467.             }
  468.         } else {
  469.             // Return error message
  470.             $field = "<em>$field</em>";
  471.             $errorMsg = "Failed validation for $field. ";
  472.             switch (strip_tags($field)) {
  473.                 case 'MerchantCode':
  474.                 case 'RefNo':
  475.                 case 'UserContact':
  476.                     $errorMsg .= "$field must not be more than 20 characters in length.";
  477.                     break;
  478.                 case 'PaymentId':
  479.                 case 'NumberOfPayments':
  480.                     $errorMsg .= "$field must be a number.";
  481.                     break;
  482.                 case 'Amount':
  483.                     $errorMsg .= "$field must be a number with 2 decimal points.";
  484.                     break;
  485.                 case 'Currency':
  486.                     $errorMsg .= "$field must not be more than 5 characters in length.";
  487.                     break;
  488.                 case 'CC_Email':
  489.                 case 'P_Email':
  490.                 case 'BackendURL':
  491.                     $errorMsg .= "$field must not be more than 255 characters in length.";
  492.                     break;
  493.                 case 'ProdDesc':
  494.                 case 'UserName':
  495.                 case 'UserEmail':
  496.                 case 'Remark':
  497.                 case 'Desc':
  498.                 case 'CC_Name':
  499.                 case 'CC_Country':
  500.                 case 'CC_Bank':
  501.                 case 'CC_Phone':
  502.                 case 'CC_Remark':
  503.                 case 'P_Name':
  504.                 case 'P_Phone':
  505.                 case 'P_Addrl1':
  506.                 case 'P_Addrl2':
  507.                 case 'P_City':
  508.                 case 'P_State':
  509.                 case 'P_Zip':
  510.                 case 'P_Country':
  511.                     $errorMsg .= "$field must not be more than 100 characters in length.";
  512.                     break;
  513.                 case 'CC_Ic':
  514.                     $errorMsg .= "$field must not be more than 50 characters in length.";
  515.                     break;
  516.                 case 'Lang':
  517.                     $langs = array('ISO-8859-1', 'UTF-8', 'GB2312', 'GD18030', 'BIG5');
  518.                     $errorMsg .= "$field must be either " . implode(', ', $langs) . '.';
  519.                     break;
  520.                 case 'Signature':
  521.                     $errorMsg .= "$field must not be more than 40 characters in length.";
  522.                     break;
  523.                 case 'FirstPaymentDate':
  524.                     $errorMsg .= "$field must not be 8 characters in length.";
  525.                     break;
  526.                 case 'CC_ExpiryDate':
  527.                     $errorMsg .= "$field must not be 6 characters in length.";
  528.                     break;
  529.                 case 'Frequency':
  530.                     $errorMsg .= "$field must either 1, 2, 3, or 4 only.";
  531.                     break;
  532.                 case 'CC_CVC':
  533.                     $errorMsg .= "$field must digit with 3 characters only.";
  534.                     break;
  535.             }
  536.             trigger_error($errorMsg);
  537.         }
  538.     }
  539.  
  540.     /**
  541.      * Set merchant key.
  542.      *
  543.      * @access public
  544.      * @param string $merchantKey Private key for merchant.
  545.      */
  546.     public function setMerchantKey($merchantKey) {
  547.         $this->merchantKey = $merchantKey;
  548.     }
  549.  
  550.     /**
  551.      * Generate signature to be used for transaction.
  552.      *
  553.      * You may verify your signature with online tool provided by iPay88
  554.      * http://www.mobile88.com/epayment/testing/TestSignature.asp
  555.      *
  556.      * @access public
  557.      * @param array $signatureParams (Optional) Fields required to generate signature (MerchantKey is set via setMerchantKey() method). If not passed, will use values that were set earlier.
  558.      * - MerchantCode
  559.      * - RefNo
  560.      * - Amount
  561.      * - Currency
  562.      */
  563.     public function generateSignature($signatureParams = array()) {
  564.         $signature = '';
  565.  
  566.         if ($signatureParams) {
  567.             $_signatureParams = array();
  568.             if ($this->getTransactionType() == self::TRANSACTION_TYPE_PAYMENT) {
  569.                 $_signatureParams = array('MerchantCode', 'RefNo', 'Amount', 'Currency');
  570.             } else if ($this->getTransactionType() == self::TRANSACTION_TYPE_RECURRING_SUBSCRIPTION) {
  571.                 $_signatureParams = array('MerchantCode', 'RefNo', 'FirstPaymentDate', 'Currency', 'Amount', 'NumberOfPayments', 'Frequency', 'CC_PAN');
  572.             } else if ($this->getTransactionType() == self::TRANSACTION_TYPE_RECURRING_TERMINATION) {
  573.                 $_signatureParams = array('MerchantCode', 'RefNo');
  574.             }
  575.  
  576.             foreach ($_signatureParams as $val) {
  577.                 if (!isset($signatureParams[$val])) {
  578.                     trigger_error('Missing required parameters for signature.');
  579.                     return false;
  580.                 }
  581.             }
  582.  
  583.             foreach ($signatureParams as $key => $val) {
  584.                 // Validate parameters for signature.
  585.                 if (!$this->validateField($key, $val)) {
  586.                     trigger_error('Invalid parameters for signature.');
  587.                     return false;
  588.                 }
  589.  
  590.                 // Some formatting..
  591.                 switch ($key) {
  592.                     case 'Amount':
  593.                         // Remove ',' and '.' from amount
  594.                         $signatureParams[$key] = str_replace(',', '', $val);
  595.                         $signatureParams[$key] = str_replace('.', '', $val);
  596.                         break;
  597.                     case 'Currency':
  598.                     case 'Lang':
  599.                         $signatureParams[$key] = strtoupper($val);
  600.                         break;
  601.                 }
  602.             }
  603.         } else {
  604.             $signatureParams['MerchantCode'] = $this->getField('MerchantCode');
  605.             $signatureParams['RefNo']        = $this->getField('RefNo');
  606.             $signatureParams['Amount']       = str_replace('.', '', str_replace(',', '', $this->getField('Amount')));
  607.             $signatureParams['Currency']     = $this->getField('Currency');
  608.  
  609.             if ($this->getTransactionType() == self::TRANSACTION_TYPE_RECURRING_SUBSCRIPTION) {
  610.                 $signatureParams['FirstPaymentDate'] = $this->getField('FirstPaymentDate');
  611.                 $signatureParams['NumberOfPayments'] = $this->getField('NumberOfPayments');
  612.                 $signatureParams['Frequency']        = $this->getField('Frequency');
  613.                 $signatureParams['CC_PAN']           = $this->getField('CC_PAN');
  614.             }
  615.         }
  616.  
  617.         if (!$this->getMerchantKey()) {
  618.             trigger_error('Merchant key is required.');
  619.             return false;
  620.         }
  621.  
  622.         // Make sure the order is correct.
  623.         if ($this->getTransactionType() == self::TRANSACTION_TYPE_PAYMENT) {
  624.             $signature .= $this->getMerchantKey();
  625.             $signature .= $signatureParams['MerchantCode'];
  626.             $signature .= $signatureParams['RefNo'];
  627.             $signature .= $signatureParams['Amount'];
  628.             $signature .= $signatureParams['Currency'];
  629.         } else if ($this->getTransactionType() == self::TRANSACTION_TYPE_RECURRING_SUBSCRIPTION) {
  630.             $signature .= $signatureParams['MerchantCode'];
  631.             $signature .= $this->getMerchantKey();
  632.             $signature .= $signatureParams['RefNo'];
  633.             $signature .= $signatureParams['FirstPaymentDate'];
  634.             $signature .= $signatureParams['Currency'];
  635.             $signature .= $signatureParams['Amount'];
  636.             $signature .= $signatureParams['NumberOfPayments'];
  637.             $signature .= $signatureParams['Frequency'];
  638.             $signature .= $signatureParams['CC_PAN'];
  639.         } else if ($this->getTransactionType() == self::TRANSACTION_TYPE_RECURRING_TERMINATION) {
  640.             $signature .= $signatureParams['MerchantCode'];
  641.             $signature .= $this->getMerchantKey();
  642.             $signature .= $signatureParams['RefNo'];
  643.         }
  644.  
  645.         // Hash the signature.
  646.         $signature = base64_encode($this->_hex2bin(sha1($signature)));
  647.  
  648.         $this->setField('Signature', $signature);
  649.     }
  650.  
  651.     /**
  652.      * Referred from iPay88 technical specification v1.5.2.
  653.      *
  654.      * @access private
  655.      * @param string $source Source string to convert (hexadecimal value).
  656.      * @return string Binary representation of the string.
  657.      */
  658.     private function _hex2bin($source) {
  659.         $bin = '';
  660.         for ($i = 0; $i < strlen($source); $i += 2) {
  661.             $bin .= chr(hexdec(substr($source, $i, 2)));
  662.         }
  663.         return $bin;
  664.     }
  665.  
  666.     /**
  667.      * Receives response returned from iPay88 server after payment is processed.
  668.      *
  669.      * @access public
  670.      * @param array $response Response returned from IPay88 server after transaction is processed.
  671.      * @return boolean Only returns false for failed transaction. You should only check for false status.
  672.      */
  673.     public function validateResponse($response) {
  674.         // Check referer, must be from www.mobile88.com only.
  675.         // Only valid if payment went through IPay88.
  676.         if (!isset($_SERVER['HTTP_REFERER'])) {
  677.             trigger_error('Invalid request.');
  678.             return false;
  679.         }
  680.         $referer = parse_url($_SERVER['HTTP_REFERER']);
  681.         if ($referer['host'] != self::$refererHost) {
  682.             trigger_error('Referer check failed, mismatch with settings.');
  683.             return false;
  684.         }
  685.  
  686.         // Re-query to check payment.
  687.         if ($this->requery(array(
  688.                 'MerchantCode' => $response['MerchantCode'],
  689.                 'RefNo'        => $response['RefNo'],
  690.                 'Amount'       => $response['Amount'],
  691.             )) != '00') {
  692.             trigger_error('Requery with server failed to verify transaction.');
  693.             return false;
  694.         }
  695.  
  696.         // Compare signature.
  697.         if ($this->generateSignature(array(
  698.                 'MerchantKey'  => $this->getMerchantKey(),
  699.                 'MerchantCode' => $response['MerchantCode'],
  700.                 'RefNo'        => $response['RefNo'],
  701.                 'Amount'       => $response['Amount'],
  702.                 'Currency'     => $response['Currency'],
  703.             )) != trim($response['Signature'])) {
  704.             trigger_error('Failed to verify signature.');
  705.             return false;
  706.         }
  707.  
  708.         return true;
  709.     }
  710.  
  711.     /**
  712.      * Check payment status (re-query).
  713.      *
  714.      * @access public
  715.      * @param array $paymentDetails The following variables are required:
  716.      * - MerchantCode (Optional)
  717.      * - RefNo
  718.      * - Amount
  719.      * @return string Possible payment status from iPay88 server:
  720.      * - 00                 - Successful payment
  721.      * - Invalid parameters - Parameters passed is incorrect
  722.      * - Record not found   - Could not find the record.
  723.      * - Incorrect amount   - Amount differs.
  724.      * - Payment fail       - Payment failed.
  725.      * - M88Admin           - Payment status updated by Mobile88 Admin (Fail)
  726.      */
  727.     public function requery($paymentDetails) {
  728.         if (!function_exists('curl_init')) {
  729.             trigger_error('PHP cURL extension is required.');
  730.             return false;
  731.         }
  732.         if (!isset($paymentDetails['MerchantCode'])) {
  733.             $paymentDetails['MerchantCode'] = $this->getField('MerchantCode');
  734.         }
  735.  
  736.         $curl = curl_init(self::$requeryUrl . '?' . http_build_query($paymentDetails));
  737.         curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  738.         $result = trim(curl_exec($curl));
  739.         curl_close($curl);
  740.  
  741.         return $result;
  742.     }
  743.  
  744. }
Add Comment
Please, Sign In to add comment