This page describes a plug-in example, where a fake gateway named Plug-in Example, having the endpoint https://pluginexample.foo.ext and implementing a SOAP engine, will be used.
The setup page will display three input fields for the gateway's endpoint and merchant's username and password along with a selection list containing the available currency supported by gateway.
<pimmodule name="PluginExample" uid="pluginexample" version="1.0.0" type="onlinepayment" subtype="gateway"> <title langname="pe_title_page"/> <fieldset langname="pe_lg_connection"> <field langname="pe_endpoint" param="endpoint" type="text" required="1" size="xlarge" validate="/^(ht|f)tp(s?)\:\/\/[0-9a-z]([-.\w]*[0-9a-z])*(:(0-9)*)*(\/?)([\~a-z0-9\-\.\?\=\,\'\/\\\+&%\$#_]*)?$/i" alert="regexp=pe_error_incorect_pe_endpoint,notempty=pe_error_invalid_pe_endpoint" default="https://plugin.foo.ext" /> <field langname="pe_username" param="username" type="text" required="1" alert="notempty=pe_error_invalid_pe_username"/> <field langname="pe_password" param="password" type="text" size="large" required="1" alert="notempty=pe_error_invalid_pe_password"/> <field langname="pe_curency_title" param="currency" type="selection_lists" size="medium" required="1" alert="array_notempty=pe_error_invalid_pe_curency_title"> <lefttitle langname="pe_currency_left_title"/> <leftvalue value="USD"/> <righttitle langname="pe_currency_right_title"/> </field> </fieldset> </pimmodule> |
The Requirements
file has specified that:
Authorize
method 4 fields are required for
CreditCardNumber
,
CardExpMonth
,
CardExpYear
and
CardSecurityCode
parameters;Refund
method a field for the
Amount
needed to be refunded.Please note that expiration date is grouped and that all existing methods are present in the |
<pimmodule name="Authorize" uid="authorize" version="1.0.0" type="onlinepayment" subtype="gateway"> <operation id="PreAuthorisePayment"/> <operation id="ProcessPreAuthorisePayment"/> <operation id="AuthorisePayment"> <field langname="pe_cc_number" param="CreditCardNumber" type="text" size="large" required="1" validate="/^[0-9]{6,25}$/" validate_error="pe_invalid_cc_number" position="2" /> <block langname="pe_cc_expire" position="3" > <field param="CardExpYear" type="select" size="small" required="1" validate_error="pe_invalid_cc_date_year" tip="/"> <fieldvalue langname="2009" value="2009"/> <fieldvalue langname="2010" value="2010"/> <fieldvalue langname="2011" value="2011"/> <fieldvalue langname="2012" value="2012"/> <fieldvalue langname="2013" value="2013"/> <fieldvalue langname="2014" value="2014"/> <fieldvalue langname="2015" value="2015"/> </field> <field param="CardExpMonth" type="select" size="small" required="1" validate_error="pe_invalid_cc_date_month" tip="pe_cc_expire_tip"> <fieldvalue langname="01" value="01"/> <fieldvalue langname="02" value="02"/> <fieldvalue langname="03" value="03"/> <fieldvalue langname="04" value="04"/> <fieldvalue langname="05" value="05"/> <fieldvalue langname="06" value="06"/> <fieldvalue langname="07" value="07"/> <fieldvalue langname="08" value="08"/> <fieldvalue langname="09" value="09"/> <fieldvalue langname="10" value="10"/> <fieldvalue langname="11" value="11"/> <fieldvalue langname="12" value="12"/> </field> </block> <field langname="pe_cc_cvv2" param="CardSecurityCode" type="text" size="small" required="1" validate="/^[0-9]{3,4}$/" validate_error="pe_invalid_cc_ccv2" position="3" /> </operation> <operation id="CapturePayment"/> <operation id="GetTransactionDetails"/> <operation id="RefundTransaction"> <field langname="pe_refund_amount" param="Amount" type="text" size="medium" validate="/^(\-?)[0-9]+(\.[0-9]+){0,1}$/i" validate_error="pe_invalid_cc_refund_amount" position="1" /> </operation> <operation id="RecurringPayment"/> </pimmodule> |
<?php $_required_params = array( 'AuthorisePayment' => array( 'CreditCardNumber', 'CardExpMonth', 'CardExpYear', 'CardSecurityValue', 'OrderTotal', 'InvoiceID' ), 'CapturePayment' => array( 'TransactionID', ), 'GetTransactionDetails' => array( 'TransactionID', ), 'RefundTransaction' => array( 'TransactionID', 'OrderTotal', ), 'RecurringPayment' => array( 'SubscriptionID', 'OrderTotal', 'InvoiceID' ), ); ?> |
<?php $plugin_msg_arr = array(); $plugin_msg_arr['pe_api_10002'] = 'Security Data : MerchantToken authentication failed.'; $plugin_msg_arr['pe_api_connect'] = 'Unable to connect to Plug-in Example endpoint.'; $plugin_msg_arr['pe_api_notset_param'] = 'This transaction cannot be processed. Missing parameter {param}.'; /* Plug-in custom errors */ $plugin_msg_arr['pe_invalid_cc_type'] = 'Credit card type must not be empty.'; $plugin_msg_arr['pe_invalid_cc_number'] = 'The credit card number must be a number between 6 and 25 digits.'; $plugin_msg_arr['pe_invalid_cc_date_month'] = 'The credit card expire date month must be a number between 1 and 12.'; $plugin_msg_arr['pe_invalid_cc_date_year'] = 'The credit card expire year must be a 4 digit number greater or equal to the current year.'; $plugin_msg_arr['pe_invalid_cc_refund_amount'] = 'The refund amount must be a number greater than 0.'; $plugin_msg_arr['pe_invalid_cc_ccv2'] = 'The Card Validation Code must be a 4 digit number for American Express and 3 digit number for all other cards. You can find this number on the back of the credit card.'; $plugin_msg_arr['pe_error_incorect_pe_endpoint'] = 'The url for Plug-in Example endpoint is invalid. Please fill in a valid url.'; $plugin_msg_arr['pe_error_invalid_pe_endpoint'] = 'Please fill in the Plug-in Example endpoint url.'; $plugin_msg_arr['pe_error_incorect_pe_username'] = 'The API version is incorrect. Please fill in a valid version.'; $plugin_msg_arr['pe_error_invalid_pe_password'] = 'Please fill in the password.'; $plugin_msg_arr['pe_error_invalid_pe_username'] = 'Please fill in the Merchant ID.'; $plugin_msg_arr['pe_error_invalid_pe_curency_title'] = 'Please select at least one currency.'; /* Page titles */ $plugin_msg_arr['pe_title_page'] = 'Example Plug-in'; /* Fieldset title definitions */ $plugin_msg_arr['pe_lg_connection'] = 'Example Plug-in configuration'; /* Plug-in configuration parameters */ $plugin_msg_arr['pe_endpoint'] = 'Plug-in Example endpoint'; $plugin_msg_arr['pe_username'] = 'Merchant'; $plugin_msg_arr['pe_password'] = 'Password'; /* Plug-in required parameters */ $plugin_msg_arr['pe_cc_number'] = 'Credit card number'; $plugin_msg_arr['pe_cc_expire'] = 'Credit card expiration'; $plugin_msg_arr['pe_transaction_cost'] = 'Charge amount'; $plugin_msg_arr['pe_cc_expire_tip'] = '(yyyy/mm)'; $plugin_msg_arr['pe_cc_cvv2'] = 'Card verification value'; $plugin_msg_arr['pe_amount'] = 'Capture amount'; $plugin_msg_arr['pe_refund_amount'] = 'Refund amount'; $plugin_msg_arr['pe_recurring_cost'] = 'Charge amount'; $plugin_msg_arr['pe_curency_title'] = 'Currencies'; $plugin_msg_arr['pe_currency_left_title'] = 'Available currencies'; $plugin_msg_arr['pe_currency_right_title'] = 'Currencies in use'; $plugin_msg_arr['USD']='US Dollar'; ?> |
<?php class pluginexample extends OnlinePaymentAbstract { /** * Operation constants */ const OPERATION_AUTHORIZE = 'AUTHORIZE'; const OPERATION_CAPTURE = 'CAPTURE'; const OPERATION_REFUND = 'REFUND'; const OPERATION_GET_DETAILS = 'DETAILS'; const OPERATION_REFERENCED = 'REFERENCED'; const OPERATION_VOID = 'VOID'; const OPERATION_CREATE_SUBSCRIPTION = 'CREATE_SUBSCRIPTION'; const OPERATION_VERIFY_SUBSCRIPTION = 'VERIFY_SUBSCRIPTION'; /** * @var {string} username * * @see pluginexample::__construct() */ private $_username = ''; /** * @var {string} password * * @see pluginexample::__construct() */ private $_password = ''; /** * @var {string} endpoint * * @see pluginexample::__construct() * @see pluginexample::__call() */ static private $_endpoint = 'http://pluginexample.foo.ext'; /** * @var {object} client * * @see pluginexample::__construct() * @see pluginexample::__call() */ private $client = null; /** * Class constructor: implements connection to endpoint * * @return boolean */ public function __construct() { /* query plug-in setup data */ $payment_plugin_data = self::GetPluginParams(); /* setup protocol endpoint */ if (isset($payment_plugin_data['endpoint'])) { $endpoint = $payment_plugin_data['endpoint']; } else { $endpoint = $this->_endpoint; } /* Set authentication: headers */ if (!isset($payment_plugin_data['username']) || !isset($payment_plugin_data['password'])) { // push error: code taken from reference guide return self::RaiseError('10002', self::Translate('pp_api_10002'), ERR_PLUGIN_CUSTOM); } /* Create SOAP client based on WSDL, with trace for debugging */ $this->client = new SoapClient($endpoint); /* Authentication */ $credentials = array( 'credentials' => array( 'Username' => $payment_plugin_data['username'], 'Password' => $payment_plugin_data['password'], ) ); $headers = new SoapHeader('credentials', 'credentials', $credentials); $this->client->__setSoapHeader($headers); return; } /** * Call method * * @return {array} * */ private function __call($method, $package, $log_request = false) { /* call request method */ $result = $this->client->__soapCall($method, array($package), null); /* enqueue protocol errors */ if (is_soap_fault($result)) { if ($log_request) { self::ErrorAttachLogs($this->client->__getLastRequest(), $this->client->__getLastResponse()); } return self::RaiseError($result->faultcode, $result->faultstring, ERR_PLUGIN_API); } /* check PluginExample custom errors */ // here you should check if the returned answer does not have other type of errors /* transform all results to array structures */ // here you should convert the answer into an array based structure // We will assume further that $result indexes are the indexes returned by this gateway $result['ACK'] = (isset($result['Ack']) $result['Ack'] != 'Success') ? 'failure' : 'success'; $result['Date'] = strtotime($result['Timestamp']); $result['Currency'] = $result['currencyID']; $result['BankRef'] = $result['CorrelationID']; $result['MerchantID'] = ''; if ($log_request) { $result['APIRequest'] = $this->client->__getLastRequest(); $result['APIResponse'] = $this->client->__getLastResponse(); } switch ($method) { case 'Authorize': { // We assumed that TransactionID already exists from the soap response $result['SubscriptionID'] = $result['TransactionID']; $result['Amount'] = $result['AuthoriseAmount']; break; } case 'Capture': { $result['Amount'] = $result['CaptureAmount']; break; } case 'Refund': { $result['Amount'] = $result['RefundAmount']; break; } case 'ReferencedAuthorize': { $result['SubscriptionID'] = $result['TransactionID']; $result['Amount'] = $result['Amount']; break; } case 'GetTransactionDetails': { break; } } if (isset($result['Ack'])) { unset($result['Ack']); } return $result; } /** * Checks required params in package for a specific method * * @param params array with input parameters * @return array with required fields empty * */ final private function __check($params) { /* include requirements file */ require_once self::GetPaymentPluginRoot() . '/required_inc.php'; // here you check if the parameters given to the function are according to the // ones from the required_inc.php file. // if any of the parameters from required_inc.php for the called function is // missing, e suggest the return of the following error // // $msg = self::Translate('pe_api_notset_param'); // $msg = str_replace('{param_name}', $param_name, $msg) // return self::RaiseError('PARAM_MISSING', $msg, ERR_PLUGIN_CUSTOM); // return true; } /* * pluginexample::PreauthorisePayment * * We will assume this function is not supported by this plug-in * (which in most credit card gateways it true) */ public function PreAuthorisePayment($params) { $msg = self::Translate('pe_api_missing_method'); $msg = str_replace('{method}', 'PreAuthorisePayment', $sg); return self::RaiseError('METHOD_MISSING', $msg, ERR_PLUGIN_CUSTOM); } /* * Process a credit card payment * * @return SOAP method response */ final public function AuthorisePayment($params) { /* check SOAP client resource and package headers */ if (!$this->client) { self::__construct(); } if (!$this->client) { self::RaiseError(0100, self::Translate('pe_client_could_not_connect'), ERR_PLUGIN_API); } // RaiseError function can also be used like this // the OnlinePaymentInterface function will keep the error from // __check function and pass it to the new empty call if (!$this->__check($params)) { return self::RaiseError(); } // We will assume that the all the soap variables are the same with the ones // in the documentation. This will shorten the example of a very long // unnecessary index mapping /* call request method */ $result = array(); $result[parent::method_auth] = self::__call('Authorize', $params, true); /* credit card info */ if ($result[parent::method_auth]['ACK'] == 'success') { $result[parent::method_auth]['CardNumberEnding'] = substr($params['CreditCardNumber'], -4); $result[parent::method_auth]['CardExpMonth'] = $params['CardExpMonth']; $result[parent::method_auth]['CardExpYear'] = $params['CardExpYear']; } return $result; } // further implementations of the other methods } ?> |