Skip to content

Commit

Permalink
Merge pull request #6 from RoomRoster/feature-credit-purchase
Browse files Browse the repository at this point in the history
Feature - Credit Card Purchase
  • Loading branch information
unoapp-dev authored Apr 1, 2021
2 parents 6eac5c8 + 0c2e792 commit db19ecb
Show file tree
Hide file tree
Showing 3 changed files with 385 additions and 3 deletions.
72 changes: 72 additions & 0 deletions src/Message/AbstractRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,34 @@

namespace Omnipay\Moneris\Message;

use Omnipay\Common\Exception\InvalidRequestException;

abstract class AbstractRequest extends \Omnipay\Common\Message\AbstractRequest
{
const MAIL_ORDER_TELEPHONE_ORDER_SINGLE = 1;
const MAIL_ORDER_TELEPHONE_ORDER_RECURRING = 2;
const MAIL_ORDER_TELEPHONE_ORDER_INSTALMENT = 3;
const MAIL_ORDER_TELEPHONE_ORDER_UNKNOWN_CLASSIFICATION = 4;
const AUTHENTICATED_E_COMMERCE_TRANSACTION_VBV = 5;
const NON_AUTHENTICATED_E_COMMERCE_TRANSACTION_VBV = 6;
const SSL_ENABLED_MERCHANT = 7;

/**
* Allowable values for the e-commerce transaction category being processed.
*
* @var array
* @link https://developer.moneris.com/en/Documentation/NA/E-Commerce%20Solutions/API/Purchase
*/
const ECOMMERCE_INDICATORS = [
self::MAIL_ORDER_TELEPHONE_ORDER_SINGLE,
self::MAIL_ORDER_TELEPHONE_ORDER_RECURRING,
self::MAIL_ORDER_TELEPHONE_ORDER_INSTALMENT,
self::MAIL_ORDER_TELEPHONE_ORDER_UNKNOWN_CLASSIFICATION,
self::AUTHENTICATED_E_COMMERCE_TRANSACTION_VBV,
self::NON_AUTHENTICATED_E_COMMERCE_TRANSACTION_VBV,
self::SSL_ENABLED_MERCHANT,
];

public $testEndpoint = 'https://esqa.moneris.com:443/gateway2/servlet/MpgRequest';
public $liveEndpoint = 'https://www3.moneris.com:443/gateway2/servlet/MpgRequest';

Expand Down Expand Up @@ -77,6 +103,52 @@ protected function getHttpMethod()
return 'POST';
}

/**
* Validate the request.
*
* @param string ... a variable length list of required parameters
* @throws InvalidRequestException
* @see Omnipay\Common\ParametersTrait::validate()
*/
public function validate(...$args)
{
foreach ($args as $key) {
$value = $this->parameters->get($key);

switch ($key) {
case 'orderNumber':
if (! isset($value)) {
throw new InvalidRequestException("The $key parameter is required");
} elseif (empty($value)) {
throw new InvalidRequestException("The $key parameter cannot be empty");
} elseif (strlen($value) > 50) {
throw new InvalidRequestException("The $key parameter cannot be longer than 50 characters");
}
break;

case 'cryptType':
if (! isset($value)) {
throw new InvalidRequestException("The $key parameter is required");
} elseif (! in_array($value, self::ECOMMERCE_INDICATORS)) {
throw new InvalidRequestException("The $key is invalid");
}
break;

case 'description':
if (isset($value) && strlen($value) > 20) {
throw new InvalidRequestException("The $key parameter cannot be longer than 20 characters");
}
break;

default:
if (! isset($value)) {
throw new InvalidRequestException("The $key parameter is required");
}
break;
}
}
}

public function sendData($data)
{
$headers = [
Expand Down
145 changes: 143 additions & 2 deletions src/Message/PurchaseRequest.php
Original file line number Diff line number Diff line change
@@ -1,16 +1,124 @@
<?php
/**
* Moneris Purchase Request.
*/

namespace Omnipay\Moneris\Message;

use Omnipay\Common\Exception\InvalidRequestException;

/**
* Moneris Purchase Request class.
*
* Moneris provides various payment related operations based on the data
* submitted to their API. Use purchase for direct credit card payments
* and customer profile payments.
*
* ### Example
*
* #### Initialize Gateway
*
* <code>
* // Create a gateway for the Moneris Gateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('Moneris');
*
* // Initialise the gateway
* $gateway->initialize(array(
* 'merchantId' => 'MyMonerisStoreId',
* 'merchantSecret' => 'MyMonerisAPIToken',
* 'cryptType' => 7,
* 'testMode' => true, // Or false when you are ready for live transactions
* ));
* </code>
*
* #### Direct Credit Card Payment
*
* This is for the use case where a customer has presented their
* credit card details and you intend to use the Moneris gateway
* for processing a transaction using that credit card data.
*
* <code>
* // Create a credit card object
* // DO NOT USE THESE CARD VALUES -- substitute your own
* // see the documentation in the class header.
* $card = new CreditCard(array(
* 'firstName' => 'Example',
* 'lastName' => 'User',
* 'number' => '4111111111111111',
* 'expiryMonth' => '01',
* 'expiryYear' => '2020',
* 'cvv' => '123',
* 'billingAddress1' => '1 Scrubby Creek Road',
* 'billingCountry' => 'AU',
* 'billingCity' => 'Scrubby Creek',
* 'billingPostcode' => '4999',
* 'billingState' => 'QLD',
* ));
*
* // Do a purchase transaction on the gateway
* try {
* $transaction = $gateway->purchase(array(
* 'orderNumber' => 'XXXX-XXXX',
* 'amount' => '10.00',
* 'description' => 'This is a test purchase transaction.',
* 'card' => $card,
* ));
* $response = $transaction->send();
* $data = $response->getData();
* echo "Gateway purchase response data == " . print_r($data, true) . "\n";
*
* if ($response->isSuccessful()) {
* echo "Purchase transaction was successful!\n";
* }
* } catch (\Exception $e) {
* echo "Exception caught while attempting authorize.\n";
* echo "Exception type == " . get_class($e) . "\n";
* echo "Message == " . $e->getMessage() . "\n";
* }
* </code>
*
* @link https://developer.moneris.com/en/Documentation/NA/E-Commerce%20Solutions/API/Purchase
*/
class PurchaseRequest extends AbstractRequest
{
/**
* CVD value is deliberately bypassed or is not provided by the merchant.
*
* @var int
* @link https://developer.moneris.com/en/Documentation/NA/E-Commerce%20Solutions/API/Purchase
*/
const CVD_BYPASSED = 0;

/**
* CVD value is present.
*
* @var int
* @link https://developer.moneris.com/en/Documentation/NA/E-Commerce%20Solutions/API/Purchase
*/
const CVD_PRESENT = 1;

/**
* CVD value is on the card, but is illegible.
*
* @var int
* @link https://developer.moneris.com/en/Documentation/NA/E-Commerce%20Solutions/API/Purchase
*/
const CVD_ILLEGIBLE = 2;

/**
* Cardholder states that the card has no CVD imprint.
*
* @var int
* @link https://developer.moneris.com/en/Documentation/NA/E-Commerce%20Solutions/API/Purchase
*/
const NO_CVD = 9;

public function getData()
{
$data = null;

$this->validate('orderNumber', 'amount', 'paymentMethod');
$this->validate('paymentMethod', 'orderNumber', 'cryptType', 'amount', 'description');

$paymentMethod = $this->getPaymentMethod();

Expand All @@ -29,10 +137,43 @@ public function getData()
$res_purchase_cc->addChild('amount', $this->getAmount());
$res_purchase_cc->addChild('crypt_type', $this->getCryptType());

if ($this->getDescription()) {
$res_purchase_cc->addChild('dynamic_descriptor', $this->getDescription());
}

$data = $request->asXML();
break;

case 'card':
$this->validate('card');

$card = $this->getCard();
$card->validate();

$request = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><request></request>');
$request->addChild('store_id', $this->getMerchantId());
$request->addChild('api_token', $this->getMerchantKey());

$purchase = $request->addChild('purchase');
$purchase->addChild('pan', $card->getNumber());
$purchase->addChild('expdate', $card->getExpiryDate('ym'));
$purchase->addChild('order_id', $this->getOrderNumber());
$purchase->addChild('cust_id', 'Transaction_'.$this->getOrderNumber());
$purchase->addChild('amount', $this->getAmount());
$purchase->addChild('crypt_type', $this->getCryptType());

if ($this->getDescription()) {
$purchase->addChild('dynamic_descriptor', $this->getDescription());
}

$cvd_info = $purchase->addChild('cvd_info');
$cvd_info->addChild('cvd_indicator', self::CVD_PRESENT);
$cvd_info->addChild('cvd_value', $card->getCvv());

$data = $request->asXML();
break;

// Todo: card & token payment
// Todo: token payment

default:
throw new InvalidRequestException('Invalid payment method');
Expand Down
Loading

0 comments on commit db19ecb

Please # to comment.