Skip to content
This repository has been archived by the owner on Oct 30, 2020. It is now read-only.

Commit

Permalink
Finishes off basic purchase flow
Browse files Browse the repository at this point in the history
  • Loading branch information
Craig Paul committed Oct 19, 2016
1 parent 613cb0d commit 8a54723
Show file tree
Hide file tree
Showing 3 changed files with 272 additions and 2 deletions.
110 changes: 109 additions & 1 deletion src/Processor.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,43 @@

class Processor
{
/**
* API configuration.
*
* @var array
*/
protected static $config = [
'protocol' => 'https',
'host' => 'esqa.moneris.com',
'port' => '443',
'url' => '/gateway2/servlet/MpgRequest',
'api_version' => 'PHP - 2.5.1',
'timeout' => '60',
];

/**
* Global error response to maintain consistency.
*
* @var string
*/
protected static $error = "<?xml version=\"1.0\"?><response><receipt><ReceiptId>Global Error Receipt</ReceiptId><ReferenceNum>null</ReferenceNum><ResponseCode>null</ResponseCode><ISO>null</ISO> <AuthCode>null</AuthCode><TransTime>null</TransTime><TransDate>null</TransDate><TransType>null</TransType><Complete>false</Complete><Message>null</Message><TransAmount>null</TransAmount><CardType>null</CardType><TransID>null</TransID><TimedOut>null</TimedOut></receipt></response>";

/**
* Retrieve the API configuration.
*
* @param string $environment
*
* @return array
*/
public static function config(string $environment)
{
if ($environment === Moneris::ENV_LIVE) {
self::$config['host'] = 'www3.moneris.com';
}

return self::$config;
}

/**
* Determine if the request is valid. If so, process the
* transaction via the Moneris API.
Expand All @@ -22,6 +59,77 @@ public static function process(Transaction $transaction)
return $response;
}

return new Response($transaction);
$response = self::submit($transaction);

return $transaction->validate($response);
}

/**
* Parse the global error response stub.
*
* @return \SimpleXMLElement
*/
protected static function error()
{
return simplexml_load_string(self::$error);
}

/**
* Set up and send the request to the Moneris API.
*
* @param array $config
* @param string $url
* @param string $xml
*
* @return string
*/
protected static function send(array $config, string $url, string $xml)
{
$curl = curl_init();

curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $xml);
curl_setopt($curl, CURLOPT_TIMEOUT, $config['timeout']);
curl_setopt($curl, CURLOPT_USERAGENT, $config['api_version']);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);

$response = curl_exec($curl);

curl_close($curl);

return $response;
}

/**
* Submit the transaction to the Moneris API.
*
* @param \CraigPaul\Moneris\Transaction $transaction
*
* @return \SimpleXMLElement|string
*/
protected static function submit(Transaction $transaction)
{
$config = self::config($transaction->gateway->environment);

$url = $config['protocol'].'://'.$config['host'].':'.$config['port'].$config['url'];

$xml = str_replace(' </', '</', $transaction->toXml());

$response = self::send($config, $url, $xml);

if (!$response) {
return self::error();
}

$response = @simplexml_load_string($response);

if ($response === false) {
return self::error();
}

return $response;
}
}
110 changes: 110 additions & 0 deletions src/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace CraigPaul\Moneris;

use SimpleXMLElement;

/**
* CraigPaul\Moneris\Response
*
Expand All @@ -13,8 +15,22 @@ class Response
{
use Gettable, Settable;

const ERROR = -23;
const INVALID_TRANSACTION_DATA = 0;

const GLOBAL_ERROR_RECEIPT = -3;

const SYSTEM_UNAVAILABLE = -14;
const CARD_EXPIRED = -15;
const INVALID_CARD = -16;
const INSUFFICIENT_FUNDS = -17;
const PREAUTH_FULL = -18;
const DUPLICATE_TRANSACTION = -19;
const DECLINED = -20;
const NOT_AUTHORIZED = -21;

const CVD = -4;

/**
* The status code.
*
Expand Down Expand Up @@ -43,4 +59,98 @@ public function __construct(Transaction $transaction)
{
$this->transaction = $transaction;
}

/**
* Create a new Response instance.
*
* @param \CraigPaul\Moneris\Transaction $transaction
*
* @return $this
*/
public static function create(Transaction $transaction)
{
return new static($transaction);
}

/**
* @param SimpleXMLElement $receipt
*/
protected function handle(SimpleXMLElement $receipt)
{
switch ($receipt->ResponseCode) {
case '050':
case '074':
case 'null':
$this->status = Response::SYSTEM_UNAVAILABLE;
break;
case '051':
case '482':
case '484':
$this->status = Response::CARD_EXPIRED;
break;
case '075':
$this->status = Response::INVALID_CARD;
break;
case '076':
case '079':
case '080':
case '081':
case '082':
case '083':
$this->status = Response::INSUFFICIENT_FUNDS;
break;
case '077':
$this->status = Response::PREAUTH_FULL;
break;
case '078':
$this->status = Response::DUPLICATE_TRANSACTION;
break;
case '481':
case '483':
$this->status = Response::DECLINED;
break;
case '485':
$this->status = Response::NOT_AUTHORIZED;
break;
case '486':
case '487':
case '489':
case '490':
$this->status = Response::CVD;
break;
default:
$this->status = Response::ERROR;
}
}

/**
* Validate the response.
*
* @return $this
*/
public function validate()
{
/** @var \SimpleXMLElement $receipt */
$receipt = $this->transaction->response->receipt;

if ($receipt->ReceiptId === 'Global Error Receipt') {
$this->status = Response::GLOBAL_ERROR_RECEIPT;
$this->successful = false;

return $this;
}

$code = (int)$receipt->ResponseCode;

if ($code >= 50 || $code === 0) {
$this->handle($receipt);
$this->successful = false;

return $this;
}

$this->successful = true;

return $this;
}
}
54 changes: 53 additions & 1 deletion src/Transaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@

namespace CraigPaul\Moneris;

use SimpleXMLElement;

/**
* CraigPaul\Moneris\Gateway
*
* @property-read array $errors
* @property-read \CraigPaul\Moneris\Gateway $gateway
* @property-read array $params
* @property SimpleXMLElement $response
*/
class Transaction
{
use Gettable;
use Gettable, Settable;

/**
* The errors for the transaction.
Expand All @@ -33,6 +37,11 @@ class Transaction
*/
protected $params;

/**
* @var SimpleXMLElement
*/
protected $response;

/**
* Create a new Transaction instance.
*
Expand Down Expand Up @@ -82,6 +91,32 @@ protected function prepare(array $params)
return $params;
}

/**
* Convert the transaction parameters into an XML structure.
*
* @return string|bool
*/
public function toXml()
{
$gateway = $this->gateway;
$params = $this->params;

$type = in_array($params['type'], ['txn', 'acs']) ? 'MpiRequest' : 'request';

$xml = new SimpleXMLElement("<$type/>");
$xml->addChild('store_id', $gateway->id);
$xml->addChild('api_token', $gateway->token);

$type = $xml->addChild($params['type']);
unset($params['type']);

foreach ($params as $key => $value) {
$type->addChild($key, $value);
}

return $xml->asXML();
}

/**
* Check that the required parameters have been provided to the transaction.
*
Expand Down Expand Up @@ -115,4 +150,21 @@ public function valid()

return empty($errors);
}

/**
* Validate the result of the Moneris API call.
*
* @param \SimpleXMLElement $result
*
* @return \CraigPaul\Moneris\Response
*/
public function validate(SimpleXMLElement $result)
{
$this->response = $result;

$response = Response::create($this);
$response->validate();

return $response;
}
}

0 comments on commit 8a54723

Please sign in to comment.