
Table Of Content
1 Prerequisites
- PHP 8.1+ with extensions: curl, openssl, mbstring.
- Composer installed.
- MySQL database.
- Moneris Merchant Account (sign up at Moneris Developer Portal).
- For testing: Use Moneris test credentials and cards from their docs.
2 Introduction
3 Create / Install a Codeigniter 4 Project
3.1 Install Codeigniter 4 Project
Use the following command to install new Codeigniter 4 Project.
composer create-project codeigniter4/appstarter ci4-moneris-integration
Then, navigate to your project directory:
cd ci4-moneris-integration
3.2 Configure MySql Database
database.default.hostname = localhost
database.default.database = ci4_moneris
database.default.username = root
database.default.password =
database.default.DBDriver = MySQLi
database.default.DBPrefix =
database.default.port = 3306
4 Add Payment Gateway Library
4.1 Download and Add Moneris Library
- Download the Moneris PHP API from GitHub: https://github.com/Moneris/Moneris-Gateway-API-PHP.
- Extract and copy the php folder contents to app/Libraries/Moneris/.
- Ensure the namespace is correct (the library uses procedural code, so we'll include it manually).
5 Get Moneris Payment Gateway Configuration Keys
5.1 Login into Moneris Merchant Resource Center
5.2 Get Moneris API Token



6 Configure Moneris Credentials
6.1 Add the Moneris API Credentials in .env
# Moneris Credentials (get from Moneris dashboard)
MONERIS_STORE_ID = your_test_store_id
MONERIS_API_TOKEN = your_test_api_token
MONERIS_ENV = test # 'prod' for production
7 Create Migration and Model
php spark make:migration CreatePaymentsTable
edit app/Database/Migrations/XXXX_CreatePaymentsTable.php
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreatePaymentsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'order_id' => [
'type' => 'VARCHAR',
'constraint' => 50,
],
'txn_number' => [
'type' => 'VARCHAR',
'constraint' => 50,
'null' => true,
],
'receipt_id' => [
'type' => 'VARCHAR',
'constraint' => 50,
'null' => true,
],
'reference_num' => [
'type' => 'VARCHAR',
'constraint' => 50,
'null' => true,
],
'email' => [
'type' => 'VARCHAR',
'constraint' => 100,
],
'amount' => [
'type' => 'DECIMAL',
'constraint' => '10,2',
],
'response_code' => [
'type' => 'VARCHAR',
'constraint' => 10,
'null' => true,
],
'message' => [
'type' => 'TEXT',
'null' => true,
],
'status' => [
'type' => 'ENUM',
'constraint' => ['success', 'failed', 'pending'],
'default' => 'pending',
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('payments');
}
public function down()
{
$this->forge->dropTable('payments');
}
}
Use the following command to run the migration to update your database.
php spark migrate
php spark make:model Payment
open the created model at app/Models/Payment.php. Inside the file you can see configuration options, you can read the documentation to further learn about its configuration options. We will now update the configs:
app/Models/Payment.php
<?php
namespace App\Models;
use CodeIgniter\Model;
class Payment extends Model
{
protected $table = 'payments';
protected $primaryKey = 'id';
protected $useAutoIncrement = true;
protected $returnType = 'array';
protected $useSoftDeletes = false;
protected $protectFields = true;
protected $allowedFields = [
'order_id', 'txn_number', 'receipt_id', 'reference_num', 'email', 'amount',
'response_code', 'message', 'status', 'created_at'
];
// Dates
protected $useTimestamps = true;
protected $dateFormat = 'datetime';
protected $createdField = 'created_at';
}
8 Create Controller
php spark make:controller PaymentController
app/Controllers/PaymentController.php
<?php
paymentModel = new Payment();
}
public function index()
{
return view('payment_form');
}
public function process()
{
helper('form');
// Validation rules
$validation = \Config\Services::validation();
$validation->setRules([
'amount' => 'required|decimal|greater_than[0]',
'card_number' => 'required|numeric|min_length[13]|max_length[19]',
'expiry_month' => 'required|numeric|exact_length[2]|greater_than[0]|less_than[13]',
'expiry_year' => 'required|numeric|exact_length[2]',
'cvv' => 'required|numeric|min_length[3]|max_length[4]',
'email' => 'required|valid_email',
]);
if (!$validation->withRequest($this->request)->run()) {
return view('payment_form', ['validation' => $validation]);
}
// Get form data
$amount = $this->request->getPost('amount');
$cardNumber = $this->request->getPost('card_number');
$expiryMonth = $this->request->getPost('expiry_month');
$expiryYear = $this->request->getPost('expiry_year');
$cvv = $this->request->getPost('cvv');
$email = $this->request->getPost('email');
// Generate unique order ID
$orderId = 'ORD-' . time();
// Moneris configuration
$storeId = env('MONERIS_STORE_ID');
$apiToken = env('MONERIS_API_TOKEN');
$testMode = env('MONERIS_ENV') === 'test';
/**************************** Transaction Variables ***************************/
$type = 'purchase';
$custId = 'cust123'; // Optional customer ID
/**************************** Request Variables *******************************/
$host = $testMode ? 'esqa.moneris.com' : 'www3.moneris.com';
$url = 'https://' . $host . '/gateway2/servlet/MpgRequest';
/************************* Transactional Associative Array ********************/
$txnArray = [
'type' => $type,
'order_id' => $orderId,
'amount' => number_format($amount, 2, '.', ''),
'pan' => $cardNumber,
'expdate' => $expiryYear . $expiryMonth, // YYMM format
'crypt_type' => '7', // SSL enabled merchant
'cust_id' => $custId,
];
/********************** Transaction Object ************************************/
$mpgTxn = new mpgTransaction($txnArray);
/************************** CVD Info ***********************/
$cvdTemplate = [
'cvd_indicator' => '1',
'cvd_value' => $cvv,
];
$mpgCvdInfo = new mpgCvd($cvdTemplate);
$mpgTxn->setCvdInfo($mpgCvdInfo);
/****************************** Request Object **********************************/
$mpgRequest = new mpgRequest($mpgTxn);
$mpgRequest->setProcCountryCode("CA"); // "US" for USA
$mpgRequest->setTestMode($testMode);
/************************ mpgHttpsPost Object **********************************/
$mpgHttpPost = new mpgHttpsPost($storeId, $apiToken, $mpgRequest);
/******************************* Response **************************************/
$mpgResponse = $mpgHttpPost->getMpgResponse();
// Handle response
$responseCode = $mpgResponse->getResponseCode();
$message = $mpgResponse->getMessage();
// Save to database
$paymentData = [
'order_id' => $orderId,
'txn_number' => $mpgResponse->getTxnNumber(),
'receipt_id' => $mpgResponse->getReceiptId(),
'reference_num' => $mpgResponse->getReferenceNum(),
'email' => $email,
'amount' => $amount,
'response_code' => $responseCode,
'message' => $message,
'status' => ($responseCode != null && (int)$responseCode < 50) ? 'success' : 'failed',
'created_at' => date('Y-m-d H:i:s'),
];
$this->paymentModel->insert($paymentData);
if ((int)$responseCode < 50) {
session()->setFlashdata('success', 'Payment successful! Receipt ID: ' . $mpgResponse->getReceiptId());
} else {
session()->setFlashdata('error', 'Payment failed: ' . $message);
}
return redirect()->to('/payment');
}
}
?>
Notes on Controller:
- Uses Moneris mpgClasses.php (included from library).
- Handles purchase transaction.
- Validates input to prevent errors.
- Checks response code: Codes < 50 are typically approvals.
- Never log or store full card details (PAN, CVV) – this code doesn't.
9 Create Payment View File
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Moneris Payment Form</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-5">
<h2>Moneris Payment Gateway Test</h2>
<?php if (session()->getFlashdata('success')): ?>
<div class="alert alert-success"><?= session()->getFlashdata('success') ?></div>
<?php endif; ?>
<?php if (session()->getFlashdata('error')): ?>
<div class="alert alert-danger"><?= session()->getFlashdata('error') ?></div>
<?php endif; ?>
<?php $validation = \Config\Services::validation(); ?>
<form action="<?= site_url('payment/process') ?>" method="post">
<?= csrf_field() ?>
<div class="form-group">
<label for="amount">Amount (CAD/USD)</label>
<input type="text" name="amount" id="amount" class="form-control" value="<?= set_value('amount', '10.00') ?>">
<?= $validation->showError('amount', 'single') ?>
</div>
<div class="form-group">
<label for="card_number">Card Number</label>
<input type="text" name="card_number" id="card_number" class="form-control" value="<?= set_value('card_number') ?>">
<?= $validation->showError('card_number', 'single') ?>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="expiry_month">Expiry Month (MM)</label>
<input type="text" name="expiry_month" id="expiry_month" class="form-control" value="<?= set_value('expiry_month') ?>">
<?= $validation->showError('expiry_month', 'single') ?>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="expiry_year">Expiry Year (YY)</label>
<input type="text" name="expiry_year" id="expiry_year" class="form-control" value="<?= set_value('expiry_year') ?>">
<?= $validation->showError('expiry_year', 'single') ?>
</div>
</div>
</div>
<div class="form-group">
<label for="cvv">CVV</label>
<input type="text" name="cvv" id="cvv" class="form-control" value="<?= set_value('cvv') ?>">
<?= $validation->showError('cvv', 'single') ?>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" name="email" id="email" class="form-control" value="<?= set_value('email') ?>">
<?= $validation->showError('email', 'single') ?>
</div>
<button type="submit" class="btn btn-primary">Pay Now</button>
</form>
</div>
</body>
</html>
10 Define a Route
$routes->get('payment', 'PaymentController::index');
$routes->post('payment/process', 'PaymentController::process');
11 Folder Structure
12 Run the Application
php spark serve
Visit http://localhost:8080/payment
Testing
- Use Moneris test cards (e.g., Visa: 4242424242424242, Expiry: any future, CVV: 123).
- Check database for records after submission.
- For production, change .env to prod, use live credentials, and ensure HTTPS.
13 Conclusion
Reference URL
Written by Revathi M
PHP Developer & Technical Writer · 10+ years building web applications with CodeIgniter and Laravel
Revathi specializes in PHP backend development, authentication systems, and REST API design. She writes practical, production-tested tutorials at Get Sample Code to help developers build secure applications faster.
Frequently Asked Questions
You need PHP 8.2 or higher, Composer, a MySQL database, and a Moneris Merchant Resource Center account with Store ID, Username, Password, and API Token.
Run `composer create-project codeigniter4/appstarter ci-4-moneris-payment`, then `cd ci-4-moneris-payment`.
Edit the `.env` file and set `database.default.hostname = localhost`, `database.default.database = codeigniter_4`, `database.default.username = root`, `database.default.password = `, `database.default.DBDriver = MySQLi`, and `database.default.port = 3306`
Download the Moneris library ZIP from the provided link, extract it, and place the files in `app/Libraries/Moneris/`.
Log into the Moneris Merchant Resource Center with your Username, Store ID, and Password. Go to My Account > ADMIN > Store Settings > Generate API Token.
In the `.env` file, add `MONERIS_STORE_ID=Your Store ID` and `MONERIS_API_TOKEN=Your Store API Token`.
Run `php spark make:model PaymentModel` and `php spark make:migration AddPayment`. Define the `payments` table in the migration (fields: id, txn_number, receipt_id, referenc_num, user_email, amount, message, created_at, updated_at), then run `php spark mi
Run `php spark make:controller MonerisController`, then implement `index()` to return the payment view and `store()` to process the transaction.
Retrieve form data, set transaction variables (type='purchase', order_id, amount, etc.), configure AVS and CVD info, create MpgRequest and MpgHttpsPost objects, send the request, and handle the response (success if responseCode <= 50).
AVS (Address Verification Service) uses street, zipcode, email, etc., for address validation. CVD (Card Verification Data) uses CVV for card security. Both are optional but recommended to prevent fraud.
Common causes: invalid credentials (Store ID/API Token), incorrect crypt_type ('7' for secure), missing AVS/CVD fields, or test mode issues. Check the response message with `$mpgResponse->getMessage()`.
In `app/Config/Routes.php`, add `$routes->get('payment', 'MonerisController::index');` and `$routes->post('moneris-payment', 'MonerisController::store');`.
Set `setTestMode(true)` in the request, use test credentials from Moneris docs, run `php spark serve`, and visit `http://localhost:8080/index.php/payment` to submit a test transaction.
Set `setTestMode(false)`, use live credentials, ensure PCI compliance for card data, and add error logging for responses.
