Source of file ImprovedPaystationHostedPayment.php
Size: 14,536 Bytes - Last Modified: 2021-12-23T10:45:55+00:00
/var/www/docs.ssmods.com/process/src/code/ImprovedPaystationHostedPayment.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 | <?php /** * PaystationHostedPayment - www.paystation.co.nz * Contains improvements * * Test cards: * Type - number - expiry - security code * VISA - 5123456789012346 - 0513 - 100 * MASTERCARD - 5123456789012346 - 0513 - 100 * * How to get different responses (by changing transaction cents value): * cents - response - response code * .00 - approved - 0 * .51 - Insufficient Funds -5 * .57 - Invalid transaction - 8 * .54 - Expired card - 4 * .91 - Error communicating with bank - 6 * * URL paramaters: * * paystation (REQUIRED) * pstn_pi = paystation ID (REQUIRED) - This is an initiator flag for the payment engine and can be nothing, or if your environment requires to assign a value please send ‘_empty’ * pstn_gi = Gateway ID (REQUIRED) - The Gateway ID that the payments will be made against * pstn_ms = Merchant Session (REQUIRED) - a unique identification code for each financial transaction request. Used to identify the transaction when tracing transactions. Must be unique for each attempt at every transaction. * pstn_am = Ammount (REQUIRED) - the amount of the transaction, in cents. * pstn_cu = Currency - the three letter currency identifier. If not sent the default currency for the gateway is used. * pstn_tm = Test Mode - sets the Paystation server into Test Mode (for the single transaction only). It uses the merchants TEST account on the VPS server, and marks the transaction as a Test in the Paystation server. This allows the merchant to run test transactions without incurring any costs or running live card transactions. * pstn_mr = Merchant Reference Code - a non-unique reference code which is stored against the transaction. This is recommended because it can be used to tie the transaction to a merchants customers account, or to tie groups of transactions to a particular ledger at the merchant. This will be seen from Paystation Admin. pstn_mr can be empty or omitted. * pstn_ct = Card Type - the type of card used. When used, the card selection screen is skipped and the first screen displayed from the bank systems is the card details entry screen. Your merchant account must be enabled for External Payment Selection (EPS), you may have to ask your bank to enable this - check with us if you have problems. CT cannot be empty, but may be omitted. * pstn_af = Ammount Format - Tells Paystation what format the Amount is in. If omitted, it will be assumed the amount is in cents * */ class ImprovedPaystationHostedPayment extends Payment { public static $db = array( 'MerchantSession' => 'Varchar', 'TransactionID' => 'Varchar' ); protected static $privacy_link = 'http://paystation.co.nz/privacy-policy'; protected static $logo = 'payment/images/payments/paystation.jpg'; protected static $url = 'https://www.paystation.co.nz/direct/paystation.dll'; protected static $test_mode = false; protected static $paystation_id; protected static $gateway_id; protected static $merchant_ref; protected static $returnurl = null; //setters public static function set_test_mode() { self::$test_mode = true; } public static function set_return_url($url) { self::$returnurl = $url; } public static function set_paystation_id($paystation_id) { self::$paystation_id = $paystation_id; } public static function set_gateway_id($gateway_id) { self::$gateway_id = $gateway_id; } public static function set_merchant_ref($merchant_ref) { self::$merchant_ref = $merchant_ref; } public static function get_paystation_id() { return self::$paystation_id; } public function getPaymentFormFields() { $logo = '<img src="' . self::$logo . '" title="Credit card payments powered by Paystation"/>'; $privacyLink = '<a href="' . self::$privacy_link . '" target="_blank" title="Read Paystation\'s privacy policy">' . $logo . '</a><br/>'; return new FieldSet( new LiteralField('PaystationInfo', $privacyLink), new LiteralField( 'PaystationPaymentsList', '<img src="payment/images/payments/methods/visa.jpg" title="Visa"/>' . '<img src="payment/images/payments/methods/mastercard.jpg" title="MasterCard"/>' ) ); } public function getPaymentFormRequirements() { return null; } public function processPayment($data, $form) { //check for correct set up info if (!self::$paystation_id) { user_error('No paystation id specified. Use PaystationHostedPayment::set_paystation_id() in your _config.php file.', E_USER_ERROR); } if (!self::$gateway_id) { user_error('No gateway id specified. Use PaystationHostedPayment::set_gateway_id() in your _config.php file.', E_USER_ERROR); } //merchant Session: built from (php session id)-(payment id) to ensure uniqueness $this->MerchantSession = session_id()."-".$this->ID; //set up required parameters $data = array( 'paystation' => '_empty', 'pstn_pi' => self::$paystation_id, //paystation ID 'pstn_gi' => self::$gateway_id, //gateway ID 'pstn_ms' => $this->MerchantSession, 'pstn_am' => $this->Amount * 100 //ammount in cents ); //add optional parameters //$data['pstn_cu'] = //currency if (self::$test_mode) { $data['pstn_tm'] = 't'; } //test mode if (self::$merchant_ref) { $data['pstn_mr'] = self::$merchant_ref; } //merchant refernece //$data['pstn_ct'] = //card type //$data['pstn_af'] = //ammount format //Make POST request to Paystation via RESTful service $paystation = new RestfulService(self::$url, 0); //REST connection that will expire immediately $paystation->httpHeader('Accept: application/xml'); $paystation->httpHeader('Content-Type: application/x-www-form-urlencoded'); $data = http_build_query($data); $response = $paystation->request('', 'POST', $data); $sxml = $response->simpleXML(); //set up a page for redirection $page = new Page(); $page->Logo = '<img src="'.self::$logo.'" alt="Payments powered by Paystation"/>'; $controller = new Page_Controller($page); if ($paymenturl = $sxml->DigitalOrder) { //TODO: store order details $page->Title = 'Redirection to Paystation...'; $page->Loading = true; $page->Message = "redirecting to paystation payment"; $page->ExtraMeta = '<meta http-equiv="Refresh" content="1;url='.$paymenturl.'"/>'; $this->Status = 'Incomplete'; $this->write(); Requirements::javascript(THIRDPARTY_DIR."/jquery/jquery.js"); //Requirements::block(THIRDPARTY_DIR."/jquery/jquery.js"); //Requirements::javascript(Director::protocol()."ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"); $output = $controller->renderWith('PaymentProcessingPage'); Director::redirect($paymenturl); //redirect to payment gateway return EcommercePayment_Processing::create($output); } if (isset($sxml->PaystationErrorCode) && $sxml->PaystationErrorCode > 0) { //provide useful feedback on failure $error = $sxml->PaystationErrorCode." ".$sxml->PaystationErrorMessage; $this->Message = $error; $this->Status = 'Failure'; $this->write(); //user_error('Paystation error: $error'); return EcommercePayment_Failure::create($sxml->PaystationErrorMessage); } //else recieved bad xml or transaction falied for an unknown reason //what should happen here? return EcommercePayment_Failure::create("Unknown error"); } public function ProcessError($errorcode) { //if errorcode = 4,5,7? //then user has failed in some way //if error code = 10,11,12,13,22,23,25,26,101,102,104 // then this payment code has failed in some way //else system failed somehow } public function RedirectJavascript($url) { $url = Convert::raw2xml($url); return<<<HTML <script type="text/javascript"> jQuery(document).ready(function() { location = "$url"; }); </script> HTML; } public function redirectToReturnURL() { if (self::$returnurl) { Director::redirect(self::$returnurl.'/'.$this->ID); return; } //TODO: show some default thing if there's no return url?...or throw error immediately in the processPayment method? } } /** * Handler for responses from the PayPal site */ class ImprovedPaystationHostedPayment_Handler extends Controller { protected static $usequicklookup = true; protected static $quicklookupurl = 'https://www.paystation.co.nz/lookup/quick/'; public static $URLSegment = 'paystation'; public static function complete_link() { return self::$URLSegment . '/complete'; } public function complete() { //TODO: check that request came from paystation.co.nz if (isset($_REQUEST['ec'])) { if (isset($_REQUEST['ms'])) { $payid = (int)substr($_REQUEST['ms'], strpos($_REQUEST['ms'], '-')+1);//extract PaystationPayment ID off the end if ($payment = DataObject::get_by_id('PaystationHostedPaymentBurnbright', $payid)) { $payment->Status = $_REQUEST['ec'] == '0' ? 'Success' : 'Failure'; if ($_REQUEST['ti']) { $payment->TransactionID = $_REQUEST['ti']; } if ($_REQUEST['em']) { $payment->Message = $_REQUEST['em']; } $this->Status = 'Success'; //Quick Lookup if (self::$usequicklookup) { $paystation = new RestfulService(self::$quicklookupurl, 0); //REST connection that will expire immediately $paystation->httpHeader('Accept: application/xml'); $paystation->httpHeader('Content-Type: application/x-www-form-urlencoded'); $data = array( 'pi' => PaystationHostedPaymentBurnbright::get_paystation_id(), //'ti' => $payment->TransactionID 'ms' => $_REQUEST['ms'] ); $paystation->setQueryString($data); $response = $paystation->request(null, 'GET'); $sxml = $response->simpleXML(); echo "<br/>"; if ($sxml && $s = $sxml->LookupResponse) { //check transaction ID matches if ($payment->TransactionID != (string)$s->PaystationTransactionID) { $payment->Status = "Failure"; $payment->Message .= "The transaction ID didn't match."; } //check amount matches if ($payment->Amount*100 != (int)$s->PurchaseAmount) { $payment->Status = "Failure"; $payment->Message .= "The purchase amount was inconsistent."; } //check session ID matches if (session_id() != substr($_REQUEST['ms'], 0, strpos($_REQUEST['ms'], '-'))) { $payment->Status = "Failure"; $payment->Message .= "Session id didn't match."; } //TODO: extra - check IP address against $payment->IP?? } elseif ($sxml && $s = $sxml->LookupStatus) { $payment->Status = "Failure"; $payment->Message .= $s->LookupMessage; } else { //falied connection? $payment->Status = "Failure"; $payment->Message .= "Paystation quick lookup failed."; } } $payment->write(); $payment->redirectToReturnURL(); return; } else { user_error('There is no any Paystation payment which ID is #' . $payid, E_USER_ERROR); } } else { user_error('There is no any Paystation hosted payment ID specified', E_USER_ERROR); } } else { user_error('There is no any Paystation hosted payment error code specified', E_USER_ERROR); } //TODO: sawp errors for payment failures?? } /** Quick Lookup Refernce: * * AcquirerName - Merchants Acquirer Name * AcquirerMerchantID - The acquirer’s merchant ID used for the transaction * PaystationUserID - Paystation username * PaystationTransactionID - A string containing the unique transaction ID assigned to the transaction attempt by the Paystation server. * PurchaseAmount - The amount of the transaction, in cents. * MerchantSession - A string containing the unique reference assigned to the transaction by the merchants system * ReturnReceiptNumber - The RRN number is a virtual terminal counter for the transaction and is not unique. * ShoppingTransactionNumber - Unique bank reference assigned to the transaction * AcquirerResponseCode - Acquirer’s response code. The result code’s vary from acquirer to acquirer and is included for debugging purposes. Please process transaction result from the PaystationErrorCode. * QSIResponseCode - Payment Server Response code – the actual raw result from the payment server. Please process transaction result from the PaystationErrorCode. * PaystationErrorCode - The result of the transaction * BatchNumber - The Batch number on the Payment Server that this transaction will be added to in order to be processed by the acquiring institution. * Cardtype - The card type used */ } |