php 对接国外支付 ipay88支付
Posted 寒冬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php 对接国外支付 ipay88支付相关的知识,希望对你有一定的参考价值。
ipay88支付
近期接了一个国外的项目,客户指定要这种支付,就搞搞呗,其实流程和思路都是差不多的,往下看
他的流程其实非常简单 下面的流程仔细看看,看懂了就会了
1 首先我们需要先获取下单所需要的参数(这个需要去ipay88官网去申请),
就是下面main.php里面的一些参数merchantCode,merchantKey
2 参数完整之后我们要做的就是验证签名了(下面有我的验证签名的方式,支付类文件,拿着用就好)
3 当我们在页面实际付款的时候,我们需要使用一个form表单 post方式执行我们的操作,
我们需要将签名所需要的参数都以form表单的形式提交到ipay88给我们提供的地址,会自动跳转到支付页(成功唤醒就代表对接成功了)
4 注意form表单提交的时候,参数一定要完整
5 测试的时候,ipay88只支持信用卡支付(visa,master),并且支付金额只能为1元
yii-iPay88 API将帮助您为应用程序实现iPay88付款网关。此API中包含以下操作
- 正常付款
- 定期付款
- 定期付款终止
- 后端通知
认证方式
yii-iPay88 API使用十六进制和base64编码技术来创建唯一签名。然后,此签名将用于客户端的每个请求以及iPay88服务器发送的每个响应。
基本上,此签名基于商户代码,商户密钥,付款金额,货币代码,refno。等。所有API请求都必须通过HTTPS进行。
用法
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‘ ), .... )
一个虚拟控制器,演示此组件用于iPay88正常付款的用法并获得该响应,这个也就是你传给支付类文件的参数方法
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 )); } }
/Ipay.php 这个就是你的支付类文件了,用的时候改一下里面的参数就可以,因为这个是基于yii框架的,你可以改一下里面的有些参数,或者删除就好
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; } }
views / ipay / payment.php 这个相当于你的回调地址了,下单成功后跳转到这里执行你想要的操作
<?php $rawPostData = file_get_contents(‘php://input‘); $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]); } }
这个就是模拟的form表单了,参照这个提交就没问题了
<FORM method="post" name="ePayment" action="https://payment.ipay88.com.my/ePayment/entry.asp"> <INPUT type="hidden" name="MerchantCode" value="M00003"> <INPUT type="hidden" name="PaymentId" value="2"> <INPUT type="hidden" name="RefNo" value="A00000001"> <INPUT type="hidden" name="Amount" value="1.00"> <INPUT type="hidden" name="Currency" value="MYR"> <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="gfdfgd"> <INPUT type="hidden" name="Lang" value="UTF-8"> <INPUT type="hidden" name="SignatureType" value="SHA256"> <INPUT type="hidden" name="Signature" value="b81af9c4048b0f6c447129f0f5c0eec8d67cbe19eec26f2cdaba5df4f4dc5a28"> <INPUT type="hidden" name="ResponseURL" value="http://gx.oeob.net/mobile/respons_ipay.php"> <INPUT type="hidden" name="BackendURL" value="http://gx.oeob.net/mobile/respons_ipay.php"> <INPUT type="submit" value="Proceed with Payment" name="Submit"> </FORM>
如果有不明白的地方,评论给我,或者发我邮箱2653293344@qq.com
以上是关于php 对接国外支付 ipay88支付的主要内容,如果未能解决你的问题,请参考以下文章