Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
[Omnipay](https://github.com/thephpleague/omnipay) is a framework agnostic, multi-gateway payment
processing library for PHP. This package implements SecurePay support for Omnipay.

A fork version of Ominipay SecurePay. The purpose of this repo is to support Periodic and Triggered API.

## Installation

Omnipay is installed via [Composer](http://getcomposer.org/). To install, simply require `league/omnipay` and `omnipay/securepay` with Composer:
Expand Down
88 changes: 65 additions & 23 deletions src/Message/SecureXMLAbstractRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ abstract class SecureXMLAbstractRequest extends AbstractRequest
* @var string
*/
public $liveEndpoint = 'https://api.securepay.com.au/xmlapi/payment';
public $testPeriodicEndpoint = 'https://test.securepay.com.au/xmlapi/periodic';
public $livePeriodicEndpoint = 'https://api.securepay.com.au/xmlapi/periodic';

/**
* @var string
Expand All @@ -27,6 +29,23 @@ abstract class SecureXMLAbstractRequest extends AbstractRequest
*/
protected $requiredFields = [];

public function getEndpoint()
{
if ($this->getRequestType() == $this->requestType) {
return $this->getTestMode() ? $this->testEndpoint : $this->liveEndpoint;
} else {
return $this->getTestMode() ? $this->testPeriodicEndpoint : $this->livePeriodicEndpoint;
}
}

/**
* get request type
*
*/
public function getRequestType(){
return $this->getCardReference() ? 'Periodic' : 'Payment';
}

/**
* Set the messageID on the request.
*
Expand Down Expand Up @@ -75,7 +94,11 @@ public function sendData($data)
protected function getBaseXML()
{
foreach ($this->requiredFields as $field) {
$this->validate($field);
if ($field == 'card' && $this->getCardReference()){
$this->validate('cardReference');
} else {
$this->validate($field);
}
}

$xml = new \SimpleXMLElement('<SecurePayMessage/>');
Expand All @@ -84,13 +107,17 @@ protected function getBaseXML()
$messageInfo->messageID = $this->getMessageId();
$messageInfo->addChild('messageTimestamp', $this->generateTimestamp());
$messageInfo->addChild('timeoutValue', 60);
$messageInfo->addChild('apiVersion', 'xml-4.2');
if($this->getCardReference()){
$messageInfo->addChild('apiVersion', 'spxml-3.0');
}else{
$messageInfo->addChild('apiVersion', 'xml-4.2');
}

$merchantInfo = $xml->addChild('MerchantInfo');
$merchantInfo->addChild('merchantID', $this->getMerchantId());
$merchantInfo->addChild('password', $this->getTransactionPassword());

$xml->addChild('RequestType', $this->requestType); // Not related to the transaction type
$xml->addChild('RequestType', $this->getRequestType()); // Not related to the transaction type

return $xml;
}
Expand All @@ -103,18 +130,32 @@ protected function getBaseXML()
protected function getBasePaymentXML()
{
$xml = $this->getBaseXML();

$payment = $xml->addChild('Payment');
$txnList = $payment->addChild('TxnList');
$txnList->addAttribute('count', 1); // One transaction per request supported by current API.

$transaction = $txnList->addChild('Txn');
$transaction->addAttribute('ID', 1); // One transaction per request supported by current API.
$transaction->addChild('txnType', $this->txnType);
$transaction->addChild('txnSource', 23); // Must always be 23 for SecureXML.
$transaction->addChild('amount', $this->getAmountInteger());
$transaction->addChild('currency', $this->getCurrency());
$transaction->purchaseOrderNo = $this->getTransactionId();
$cardReference = $this->getCardReference();

if($cardReference) {
$periodic = $xml->addChild( 'Periodic' );
$periodicList = $periodic->addChild( 'PeriodicList' );
$periodicList->addAttribute('count', 1);

$periodicItem = $periodicList->addChild( 'PeriodicItem' );
$periodicItem->addAttribute('ID', 1);
$periodicItem->addChild('actionType', 'trigger');
$periodicItem->addChild('clientID', $cardReference);
$periodicItem->addChild('amount', $this->getAmountInteger());
$periodicItem->addChild('currency', $this->getCurrency());
}else{
$payment = $xml->addChild('Payment');
$txnList = $payment->addChild('TxnList');
$txnList->addAttribute('count', 1); // One transaction per request supported by current API.

$transaction = $txnList->addChild('Txn');
$transaction->addAttribute('ID', 1); // One transaction per request supported by current API.
$transaction->addChild('txnType', $this->txnType);
$transaction->addChild('txnSource', 23); // Must always be 23 for SecureXML.
$transaction->addChild('amount', $this->getAmountInteger());
$transaction->addChild('currency', $this->getCurrency());
$transaction->purchaseOrderNo = $this->getTransactionId();
}

return $xml;
}
Expand All @@ -125,15 +166,16 @@ protected function getBasePaymentXML()
*/
protected function getBasePaymentXMLWithCard()
{
$this->getCard()->validate();

$xml = $this->getBasePaymentXML();

$card = $xml->Payment->TxnList->Txn->addChild('CreditCardInfo');
$card->addChild('cardNumber', $this->getCard()->getNumber());
$card->addChild('cvv', $this->getCard()->getCvv());
$card->addChild('expiryDate', $this->getCard()->getExpiryDate('m/y'));


if(!$this->getCardReference()) {
$this->getCard()->validate();

$card = $xml->Payment->TxnList->Txn->addChild('CreditCardInfo');
$card->addChild('cardNumber', $this->getCard()->getNumber());
$card->addChild('cvv', $this->getCard()->getCvv());
$card->addChild('expiryDate', $this->getCard()->getExpiryDate('m/y'));
}
return $xml;
}

Expand Down
30 changes: 30 additions & 0 deletions src/Message/SecureXMLAddPayorRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Omnipay\SecurePay\Message;

/**
* SecurePay SecureXML Add Payor Request.
*
* Add Payor for periodical payment
*
*/
class SecureXMLAddPayorRequest extends SecureXMLAbstractRequest
{
protected $actionType = 'add';
protected $requiredFields = array('amount', 'card', 'currency');

public function getData()
{
$xml = $this->getBasePaymentXML();

$card = $xml->Periodic->PeriodicList->PeriodicItem->addChild('CreditCardInfo');
$card->addChild('cardNumber', $this->getCard()->getNumber());
$card->addChild('cvv', $this->getCard()->getCvv());
$card->addChild('expiryDate', $this->getCard()->getExpiryDate('m/y'));

$xml->Periodic->PeriodicList->PeriodicItem->addChild('periodicType', 4);
$xml->Periodic->PeriodicList->PeriodicItem->actionType = 'add';

return $xml;
}
}
24 changes: 24 additions & 0 deletions src/Message/SecureXMLDeletePayorRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Omnipay\SecurePay\Message;

/**
* SecurePay SecureXML Delete Payor Request.
*
* Delete Payor for periodical payment
*
*/
class SecureXMLDeletePayorRequest extends SecureXMLAbstractRequest
{
protected $actionType = 'delete';
protected $requiredFields = array('card');

public function getData()
{
$xml = $this->getBasePaymentXML();

$xml->Periodic->PeriodicList->PeriodicItem->addChild('periodicType', 4);

return $xml;
}
}
71 changes: 56 additions & 15 deletions src/Message/SecureXMLResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,29 @@ class SecureXMLResponse extends AbstractResponse
public function isSuccessful()
{
// As per appendix F, 000 means the message was processed correctly
if ((string) $this->data->Status->statusCode !== '000'
|| ($this->hasTransaction()
&& (string) $this->data->Payment->TxnList->Txn->approved !== 'Yes')) {
if ( $this->isFailedCode() || $this->isNotApproved() ) {
return false;
}

return true;
}

private function isFailedCode()
{
return (string) $this->data->Status->statusCode !== '000' && (string) $this->data->Status->statusCode !== '0';
}

private function isNotApproved()
{
if ($this->hasTransaction())
return (string) $this->data->Payment->TxnList->Txn->approved !== 'Yes';
if ($this->hasPeriodic())
return (string) $this->getResponseItem()->responseCode !== '00'
&& (string) $this->getResponseItem()->responseCode !== '08'
&& (string) $this->getResponseItem()->responseCode !== '77';
return true;
}

/**
* Determine if we have had payment information returned.
*
Expand All @@ -39,16 +53,43 @@ protected function hasTransaction()
return isset($this->data->Payment->TxnList->Txn);
}

/**
* Determine if we have had periodic payment information returned.
*
* @note For certain errors a Periodic element is returned but has an empty
* TxnList so this will tell us if we actually have a transaction to check.
*
* @return bool True if we have a transaction.
*/
protected function hasPeriodic()
{
return isset($this->data->Periodic->PeriodicList->PeriodicItem);
}

/**
* Return the response item, transaction or periodicItem or null
*
* @return transaction or periodicItem or null
*/
protected function getResponseItem()
{
if ($this->hasTransaction())
return $this->data->Payment->TxnList->Txn;
if ($this->hasPeriodic())
return $this->data->Periodic->PeriodicList->PeriodicItem;
return null;
}

/**
* @link https://www.securepay.com.au/_uploads/files/SecurePay_Response_Codes.pdf
*
* @return string Gateway failure code or transaction code if available.
*/
public function getCode()
{
return $this->hasTransaction()
? (string) $this->data->Payment->TxnList->Txn->responseCode
: (string) $this->data->Status->statusCode;
if ($this->hasTransaction() || $this->hasPeriodic())
return (string) $this->getResponseItem()->responseCode;
return (string) $this->data->Status->statusCode;
}

/**
Expand All @@ -57,19 +98,19 @@ public function getCode()
*/
public function getMessage()
{
return $this->hasTransaction()
? (string) $this->data->Payment->TxnList->Txn->responseText
: (string) $this->data->Status->statusDescription;
if ($this->hasTransaction() || $this->hasPeriodic())
return (string) $this->getResponseItem()->responseText;
return (string) $this->data->Status->statusDescription;
}

/**
* @return string Unique SecurePay bank transaction reference.
*/
public function getTransactionReference()
{
return $this->hasTransaction()
? (string) $this->data->Payment->TxnList->Txn->txnID
: null;
if ($this->hasTransaction() || $this->hasPeriodic())
return (string) $this->getResponseItem()->txnID;
return null;
}

/**
Expand All @@ -78,8 +119,8 @@ public function getTransactionReference()
*/
public function getSettlementDate()
{
return $this->hasTransaction()
? (string) $this->data->Payment->TxnList->Txn->settlementDate
: null;
if ($this->hasTransaction() || $this->hasPeriodic())
return (string) $this->getResponseItem()->settlementDate;
return null;
}
}
10 changes: 10 additions & 0 deletions src/SecureXMLGateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,14 @@ public function echoTest(array $parameters = array())
{
return $this->createRequest('\Omnipay\SecurePay\Message\SecureXMLEchoTestRequest', $parameters);
}

public function createCard(array $parameters = array())
{
return $this->createRequest('\Omnipay\SecurePay\Message\SecureXMLAddPayorRequest', $parameters);
}

public function deleteCard(array $parameters = array())
{
return $this->createRequest('\Omnipay\SecurePay\Message\SecureXMLDeletePayorRequest', $parameters);
}
}