
IPpay is an important source solution for accepting Card-not-Present (CNP) payment transactions. Card not Present (CNP) refers to a purchase a consumer makes without physically presenting his or her credit or debit card at the time of purchase.
Agriios is a Point of Sale (POS) software for cannabis related products. An authorized POS user can create a purchese order, track order details and sell the product to consumer with the help of Agriios.
Composer is a tool for dependency management in PHP. It allows you to declare the libraries your project depends on and it will manage (install/update) them for you.
Omnipay is a payment processing library for PHP. It has been designed based on ideas from Active Merchant, plus experience implementing dozens of gateways for CI Merchant.
$ git clone https://github.com/goorionlabs/agriios_1.0.git
$ sudo apt update && sudo apt install wget php-cli php-zip unzip curl
$ curl -sS https://getcomposer.org/installer |php
$ sudo mv composer.phar /usr/local/bin/composer
$ composer
This package is developed by the third party user on top of Omnipay libray
To install, simply add it to your composer.json file in application/third_party :
{
"require": {
"dranes/omnipay-ippay": "~1.1"
}
}
And run composer to update your dependencies. For that follow the below steps:
$ curl -s http://getcomposer.org/installer | php
$ php composer.phar update

In the very beginning, we need to add IPpay in our database to enable it while making payment in the POS.
There are 8 more payment gateways already added in this table. So we are adding IPpay in a 9th position.
INSERT INTO `geopos_gateways` (`id`, `name`, `enable`, `key1`, `key2`, `currency`, `dev_mode`, `ord`, `surcharge`, `extra`) VALUES ('9', 'IPpay', 'Yes', 'TestPay', 'TestKey', 'USD', 'true', '9', '0.00', 'none');
Note:
The above UI was designed based on the SecurePay payment gateway in Agriios.
After designing the IPpay gateway, we need to insert it in Billing controller.
Steps:
case 9:
$fname = 'ippay';
break;
private function ippay($cardNumber, $nmonth, $nyear, $cardCVC, $amount, $tid, $gateway_data) {
$gateway = Omnipay::create('Ippay');
$gateway->setTerminalId('TESTTERMINAL');
$gateway->setTestMode(true);
// Create a credit card object
$card = new \Omnipay\Common\CreditCard(['number' => $cardNumber, 'expiryMonth' => $nmonth, 'expiryYear' => $nyear, 'cvv' => $cardCVC, ]);
// Perform a purchase test
$transaction = $gateway->purchase(['amount' => $amount, 'transaction_type' => 'SALE', 'card' => $card, ]);
return $transaction->send();
}
Note: The above code is for testing purpose only. The transaction has been done with test card data. The above code need to be changed while get into production.
case 9:
$response = $this->ippay($cardNumber, $nmonth, $nyear, $cardCVC, $amount, $tid, $gateway_data);
break;
We need to make some changes in dranes/omnipay-ippay files to get everything working fine. Those files can be located in
application/third_party/vendor/dranes/omnipay-ippay/src/
Delete the source code inside getData() function as it was created for the transaction made by cheque. We need to change the data for card transaction. Copy and paste the below code inside that function.
public function getData() {
$this->getCard()->validate();
$data = array();
$data['TransactionType'] = $this->getTransactionType();
$data['CardNum'] = $this->getCard()->getNumber();
$data['CardExpMonth'] = $this->getCard()->getExpiryDate('m');
$data['CardExpYear'] = $this->getCard()->getExpiryDate('y');
$data['TotalAmount'] =floor($this->getAmount());
return $data;
}
Endpoint is mentioned in this file to perform a RESTful API call.
protected $sandboxEndpoint = "https://testgtwy.ippay.com/ippay";
protected $productionEndpoint = "https://gtwy.ippay.com/ippay";
POST data is constructed in XML format using dataSale() function. The test transaction POST data will look like this.
<ippay>
<TransactionType>SALE</TransactionType>
<TerminalID>TESTTERMINAL</TerminalID>
<CardNum>4000300020001000</CardNum>
<CardExpMonth>12</CardExpMonth>
<CardExpYear>22</CardExpYear>
<TotalAmount>8</TotalAmount>
</ippay>
We get the response like this for the successful transaction,
<ippayResponse>
<TransactionID>B20191106095946460</TransactionID>
<ActionCode>000</ActionCode>
<Approval>TEST01</Approval>
<ResponseText>APPROVED</ResponseText>
</ippayResponse>
We get the Action code as 000 for the successful transaction. It is also mentioned in isSuccessful() function in this file.
public function isSuccessful()
{
$response = new \SimpleXMLElement($this->response);
return ($response->ActionCode == "000");
}
We will get some different action code for unsuccessful transaction. Refer page number 7,8 and 9 in this Document for more Action codes.
Note: These are the acceptable amounts to make successful transaction under test environment in IPpay. Transaction get declined for other than this amount.
08, 09, 10, 11, 16, 17, 18, 20, 22, 23, 24, 25, 26, 27, 45, 46, 47, 48, 49, 50, 56, 60, 64, 66, 67, 68, 69, 70, 71, 72, 73, 74, 79,86, 87, 88, 89, 95, 97, 98, 99, 100
If the amount is higher than 100, than those last digits must be the above numbers only
Card number : 4000 3000 2000 1000
Expiry date/month : 11/22
CVV : 123
Documented by,
Balakrishnan Subramaniyan
Document version 1.0