Skip to content

Commit

Permalink
init v1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
dimosKougiou committed Jul 5, 2024
1 parent 1bf65d8 commit 0122492
Show file tree
Hide file tree
Showing 65 changed files with 4,066 additions and 3,185 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/doc
225 changes: 0 additions & 225 deletions GNU GPL v3.txt

This file was deleted.

674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

67 changes: 67 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Cardlink Checkout Payment Gateway for VirtueMart

- Contributors: cardlink
- Tags: payments, payment-gateway
- Requires at least: Joomla 4.1.0, VirtueMart 4.x
- Tested up to: Joomle 4.4.3, VirtueMart 4.2.4
- Requires PHP: 7.x - 8.x
- License: GPLv2 or later
- License URI: http://www.gnu.org/licenses/gpl-2.0.html

## Changelog

- **1.0.0**
- Initial release

## Description

Cardlink Payment Gateway allows you to accept payment through various schemes such as Visa, Mastercard, Maestro, American Express, Diners, Discover cards on your website, with or without variable installments.
This module aims to offer new payment solutions to Cardlink merchants for their VirtueMart 4.x online store without having web development knowledge. However, for the initial module installation some technical knowledge will be required.

Merchants with e-shops (redirect cases only) will be able to integrate the Cardlink Payment Gateway to their checkout page using the CSS layout that they want. Also, they could choose between redirect or IFRAME option for the payment environment. Once the payment is made, the customer returns to the online store and the order is updated.
Once you have completed the requested tests and any changes to your website, you can activate your account and start accepting payments.

## Features

1. A dropdown option for instance between Worldline, Nexi και Cardlink business partner.
2. Option to enable test environment (sandbox). All transactions will be re-directed to the endpoint that represents the production environment by default. The endpoint will be different depending on which acquirer has been chosen from instance dropdown option.
3. Ability to define the maximum number of installments regardless of the total order amount.
4. Ability to define the ranges of the total order amounts and the maximum number of installments for each range.
5. Option for pre-authorization or sale transactions.
6. Option for a user tokenization service. The card token will be stored in the merchant’s e-shop database and will be used by customers to auto-complete future payments.
7. In-store checkout option: the merchant can configure the payment process to take place inside a pop up with IFRAME to mask the redirection process from the customers.
8. A text field for providing the absolute or relative (to Cardlink Payment Gateway location on server) URL of custom CSS stylesheet, to apply custom CSS styles in the payment page.
9. Translation ready for Greek & English languages.
10. Automatically cancel pending payment orders after a configurable number of minutes using Joomla Scheduled Tasks.
<!-->11. IRIS payment method support.-->

## Installation and Configuration

Download the Github repository archive and then upload it to your Joomla installation through the System > Install > Extensions menu options on your administrator panel.
Normally, if an order is abandoned (not paid), the order status will remain at Pending. You can use a scheduled task to automatically cancel orders that haven't been paid within a configurable amount of time. Go to System > Manage > Scheduled Tasks, then click the Add New button and select the "Cardlink - Auto cancel unpaid orders" as the task type. On the edit page, set a name for the task, the execution interval to 1 minute and then the number of minutes to wait for orders in pending payment state to be successfully paid for before automatically cancelling the order.


## Required Hosting Configuration Step

For hosting solutions running the Apache web server software, you will need to add the following lines to your web site’s root ``.htaccess`` file. These will manipulate all cookies set by your VirtueMart store to allow customer sessions to persist after returning from the payment gateway. If you fail to properly set these, customers returning from the payment gateway will be automatically logged out from their accounts.

```
<IfModule mod_headers.c>
Header always edit Set-Cookie ^(.*)$ $1;SameSite=None;Secure
</IfModule>
```

If your hosting provider uses the Nginx web server instead, you will need to add/edit the following lines of code to your virtual host’s configuration file.

```
location / {
proxy_cookie_path / "/; SameSite=None; Secure";
}
```

If you are unsure or unfamiliar with the actions described above, please ask a trained IT person or contact your hosting provider to do them for you.

## Support tickets

In case that you face any technical issue during the installation process, you can contact the Cardlink e-commerce team at [email protected] .
228 changes: 228 additions & 0 deletions cardlink.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
<?php
/**
* @package Cardlink Payment Helper
* @version 4.2
* @company Cardlink
* @developer Cardlink
* @link http://www.cardlink.gr
* @copyright Copyright (C) 2022 Cardlink All Rights Reserved
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
*/
defined('_JEXEC') or die('Restricted access');

// if (!class_exists('vmDefines')) {
// require_once (JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'components' . DIRECTORY_SEPARATOR . 'com_virtuemart' . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'vmdefines.php');
// vmDefines::defines('site');
// }
// if (!class_exists('vmPlugin')) {
// require_once (JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'components' . DIRECTORY_SEPARATOR . 'com_virtuemart' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'vmplugin.php');
// }
// if (!class_exists('vmPSPlugin')) {
// require_once (JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'components' . DIRECTORY_SEPARATOR . 'com_virtuemart' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'vmpsplugin.php');
// }

use Joomla\Database\DatabaseInterface;
use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\Folder;
use Joomla\Plugin\CMSPlugin;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Router\ApiRouter;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Router\Router;

class plgSystemCardlink extends JPlugin
{
protected $debug = array();
protected $isNotify = 0;
protected $replacements = array();

public function __construct(&$subject, $config)
{
parent::__construct($subject, $config);
}

public function onAfterInitialise()
{
$app = Factory::getApplication();

if ($app->isClient('admin')) {
return;
}

$session = $app->getSession();
$component = $app->input->get->get('com', '');
$option = $app->input->get->get('option', '');
$paymentMethod = $app->input->get->get('type', '');
$paymentStatus = $app->input->get->get('status', '');
$layout = $app->input->get->get('layout', '');
$actions = array('ok' => 'pluginresponsereceived', 'cancel' => 'pluginUserPaymentCancel', 'notify' => 'pluginNotification', 'none' => null);
$components = array('cardlink' => 'com_virtuemart');
$paymentMethodsList = array('card' => 'cardlinkcard', 'iris' => 'cardlinkiris');

$task = $paymentStatus;

if ($layout == 'orderdone') {
$app->allowCache(false);
$app->set('caching', 0);
}

if ($option == 'com_ajax') {
require_once (JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'components' . DIRECTORY_SEPARATOR . 'com_virtuemart' . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'vmdefines.php');
vmDefines::defines('site');

require_once (JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'components' . DIRECTORY_SEPARATOR . 'com_virtuemart' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'vmplugin.php');
require_once (JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'components' . DIRECTORY_SEPARATOR . 'com_virtuemart' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'vmpsplugin.php');
}

if (
(array_key_exists($paymentMethod, $paymentMethodsList) || in_array($paymentMethod, $paymentMethodsList))
&& (array_key_exists($component, $components) || in_array($option, $components))
&& $app->input->get('t') == 'checkout'
) {
$html = $session->get('cardlink_checkouthtml', null);
if (!empty($html)) {
echo '<!DOCTYPE html>
<html xmlns="//www.w3.org/1999/xhtml" xml:lang="en-gb" lang="en-gb" dir="ltr">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Redirecting to payment gateway...</title>
</head>
<body>
' . $html . '
</body>
</html>';
$session->set('cardlink_checkouthtml', '');
} else {
echo 'There was a problem with your request, please contact with us or go back to your order and try again.';
}
$app->close();
}

if (
(array_key_exists($paymentMethod, $paymentMethodsList) || in_array($paymentMethod, $paymentMethodsList))
&& (array_key_exists($component, $components) || in_array($option, $components))
&& count($_REQUEST) > 2
) {
$this->isNotify = 1;
if (array_key_exists($paymentMethod, $paymentMethodsList)) {
$paymentMethod = $paymentMethodsList[$paymentMethod];
}

if (array_key_exists($component, $components)) {
$option = $components[$component];
$this->setVar('option', $option);
}

if ($this->params->get('disablesef', 0)) {
$params = $app->getParams();
$params->set('sef', 0);
}

if ($option == 'com_virtuemart') {
$view = is_dir(JPATH_SITE . '/components/com_virtuemart/views/pluginresponse') ? 'pluginresponse' : 'vmplg';
$this->setVar('view', $view);
$this->setVar('task', isset($actions[$task]) ? $actions[$task] : $task);
if ($task == 'notify') {
$this->setVar('tmpl', 'component');
}
$orderid = $app->input->getCmd('oid', '');
$onumber = $app->input->getCmd('on', '');
if (empty($onumber) && $orderid) {
$app->input->set('on', $orderid);
}
}

$Itemid = (int) $this->params->get('Itemid', 0);
if ($Itemid) {
$this->setVar('Itemid', $Itemid);
}

$lang = $this->params->get('lang');
if (!empty($lang)) {
$this->setVar('lang', $lang);
}

if (method_exists($app, 'getRouter') && $this->params->get('router', 0)) {
$this->debug[] = 'Router Attached';

$router = Factory::getContainer()->get(ApiRouter::class);
$router->attachBuildRule(array($this, 'preprocessBuildRule'), Router::PROCESS_BEFORE);
}
}
}

protected function setVar($var, $value = NULL)
{
$app = Factory::getApplication();
$this->replacements[$var] = $_REQUEST[$var] = $_GET[$var] = $value;
$app->input->set($var, $value);
$this->debug[] = 'Var set ' . $var . '=' . $value;
}

public function onAfterRoute()
{
$app = Factory::getApplication();

if ($this->params->get('debug', 0)) {
$app->enqueueMessage('Router Vars:' . print_r(Factory::getContainer()->get(ApiRouter::class)->getVars(), true));
}
}

public function onAfterRender()
{
$app = Factory::getApplication();
if ($app->isClient('admin') || !$this->isNotify) {
return;
}

$session = $app->getSession();
$router = Factory::getContainer()->get(ApiRouter::class);
$redirectURL = $session->get('cardlink_redirect', null);

if ($this->params->get('debug', 0)) {
$buffer = Factory::getApplication()->getBody();
$debug = '<p>CARDLINK PLUGIN DEBUG</p>';
$debug .= '<p>Debug:<br/>' . implode("\n<br/>", $this->debug) . '</p>';
$debug .= '<p>Router:<br/><pre>' . print_r($router->getVars(), true) . '</pre></p>';
if (!empty($redirectURL)) {
$debug .= '<p>Redirect URL:' . Route::_($redirectURL) . '</p>';
}

$debug .= '<p>Option:' . $app->input->get('option') . ' View:' . $app->input->get('view') . ' Task:' . $app->input->get('task') . ' Lang:' . $app->input->get('lang') . ' Itemid:' . $app->input->get('Itemid') . '</p>';
$debug .= '<p>$_GET: <pre>' . print_r($_GET, true) . '</pre></p>';
$debug .= '<p>$_POST: <pre>' . print_r($_POST, true) . '</pre></p>';
$app->setBody(str_replace('</body>', $debug . '</body>', $buffer));
}

if (!$this->params->get('debug', 0) && !empty($redirectURL)) {
$session->set('cardlink_redirect', null);
$app->redirect(Route::_($redirectURL));
$app->close();
}
}

public function preprocessBuildRule(&$router, &$uri)
{
//$router->setVars($this->replacements);
foreach ($this->replacements as $k => $v) {
$uri->setVar($k, $v);
$router->setVar($k, $v);
}
$uri->delVar('b');
$uri->delVar('virtuemart_manufacturer_id');
$uri->delVar('virtuemart_category_id');
}

public function getOrderByID($virtuemart_order_id)
{
if (method_exists($this, 'getDatasByOrderId')) {
return $this->getDatasByOrderId($virtuemart_order_id);
}
$db = Factory::getContainer()->get(DatabaseInterface::class);
$q = 'SELECT * FROM `#__virtuemart_orders` '
. 'WHERE `order_number` = "' . $virtuemart_order_id . '" ';
$db->setQuery($q);
return $db->loadObjectList();
}

}
42 changes: 42 additions & 0 deletions cardlink.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<extension version="2.5" type="plugin" group="system" method="upgrade">
<name>Cardlink Payment Gateway Helper</name>
<version>1.0.0</version>
<modified>22-01-2024</modified>
<creationDate>22/01/2024</creationDate>
<author>Cardlink</author>
<authorEmail>[email protected]</authorEmail>
<authorUrl>http://www.cardlink.gr/</authorUrl>
<copyright>(C) 2024 Cardlink</copyright>
<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
<description>Cardlink Payment Gateway Installer</description>
<scriptfile>script.cardlink.php</scriptfile>
<files>
<filename plugin="cardlink">cardlink.php</filename>
<filename>index.html</filename>
</files>
<config>
<fields name="params">
<fieldset name="Basic">
<field default="0" type="radio" name="router" label="Router Fix" description="Router values by-pass">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field default="0" type="radio" name="disablesef" label="Disable Sef on Redirect" description="Disable Sef on Return to thank you page">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field default="0" type="radio" name="debug" label="Debug" description="Only for testing">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
</fieldset>
</fields>
</config>
<plugins>
<!-- Virtuemart -->
<plugin plugin="cardlinkcard" group="vmpayment" />
<!--<plugin plugin="cardlinkiris" group="vmpayment" />-->
<plugin plugin="cardlink_cancel_unpaid_orders" group="task" />
</plugins>
</extension>
Loading

0 comments on commit 0122492

Please sign in to comment.