Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR to integrate Paymill #1831

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Expand Up @@ -25,7 +25,8 @@
"terminal42/contao-tablelookupwizard": "~3.2",
"terminal42/notification_center": "~1.0",
"terminal42/dc_multilingual": "~2.0",
"guzzlehttp/guzzle": "~6.0"
"guzzlehttp/guzzle": "~6.0",
"paymill/paymill": "^4.4"
},
"require-dev": {
"discordier/httprequestextended": "~1.1",
Expand Down
2 changes: 2 additions & 0 deletions system/modules/isotope/config/autoload.php
Expand Up @@ -41,6 +41,7 @@
'be_iso_overview' => 'system/modules/isotope/templates/backend',
'be_iso_old' => 'system/modules/isotope/templates/backend',
'be_iso_upgrade' => 'system/modules/isotope/templates/backend',
'be_iso_payment_paymill' => 'system/modules/isotope/templates/backend',
'iso_checkout_address' => 'system/modules/isotope/templates/checkout',
'iso_checkout_order_conditions' => 'system/modules/isotope/templates/checkout',
'iso_checkout_order_info' => 'system/modules/isotope/templates/checkout',
Expand All @@ -60,6 +61,7 @@
'iso_payment_datatrans' => 'system/modules/isotope/templates/payment',
'iso_payment_innopay' => 'system/modules/isotope/templates/payment',
'iso_payment_epay' => 'system/modules/isotope/templates/payment',
'iso_payment_paymill' => 'system/modules/isotope/templates/payment',
'iso_payment_paybyway' => 'system/modules/isotope/templates/payment',
'iso_payment_paypal' => 'system/modules/isotope/templates/payment',
'iso_payment_payone' => 'system/modules/isotope/templates/payment',
Expand Down
1 change: 1 addition & 0 deletions system/modules/isotope/config/config.php
Expand Up @@ -193,6 +193,7 @@
\Isotope\Model\Payment::registerModelType('expercash', 'Isotope\Model\Payment\Expercash');
\Isotope\Model\Payment::registerModelType('innopay', 'Isotope\Model\Payment\Innopay');
\Isotope\Model\Payment::registerModelType('paybyway', 'Isotope\Model\Payment\Paybyway');
\Isotope\Model\Payment::registerModelType('paymill', 'Isotope\Model\Payment\Paymill');
\Isotope\Model\Payment::registerModelType('payone', 'Isotope\Model\Payment\Payone');
\Isotope\Model\Payment::registerModelType('paypal', 'Isotope\Model\Payment\Paypal');
\Isotope\Model\Payment::registerModelType('postfinance', 'Isotope\Model\Payment\Postfinance');
Expand Down
17 changes: 17 additions & 0 deletions system/modules/isotope/dca/tl_iso_payment.php
Expand Up @@ -137,6 +137,7 @@
'worldpay' => '{type_legend},name,label,type;{note_legend:hide},note;{config_legend},new_order_status,quantity_mode,minimum_quantity,maximum_quantity,minimum_total,maximum_total,countries,shipping_modules,product_types,product_types_condition,config_ids;{gateway_legend},worldpay_instId,worldpay_callbackPW,worldpay_signatureFields,worldpay_md5secret,worldpay_description;{price_legend:hide},price,tax_class;{expert_legend:hide},guests,protected;{enabled_legend},debug,enabled',
'quickpay' => '{type_legend},name,label,type;{note_legend:hide},note;{config_legend},new_order_status,trans_type,quantity_mode,minimum_quantity,maximum_quantity,minimum_total,maximum_total,countries,shipping_modules,product_types,product_types_condition,config_ids;{gateway_legend},quickpay_merchantId,quickpay_agreementId,quickpay_apiKey,quickpay_privateKey,quickpay_paymentMethods;{price_legend:hide},price,tax_class;{expert_legend:hide},guests,protected;{enabled_legend},debug,enabled',
'opp' => '{type_legend},name,label,type;{note_legend:hide},note;{config_legend},new_order_status,trans_type,quantity_mode,minimum_quantity,maximum_quantity,minimum_total,maximum_total,countries,shipping_modules,product_types,product_types_condition,config_ids;{gateway_legend},opp_user_id,opp_password,opp_entity_id;{price_legend:hide},price,tax_class;{expert_legend:hide},guests,protected;{enabled_legend},debug,enabled',
'paymill' => '{type_legend},name,label,type;{note_legend:hide},note;{paymill_legend},paymill_public_key,paymill_private_key;{config_legend:hide},new_order_status,minimum_total,maximum_total,countries,shipping_modules,product_types;{gateway_legend},trans_type;{price_legend:hide},price,tax_class;{expert_legend:hide},guests,protected;{enabled_legend},enabled',
),

// Subpalettes
Expand Down Expand Up @@ -811,6 +812,22 @@
'inputType' => 'checkbox',
'sql' => "char(1) NOT NULL default ''"
),
'paymill_public_key' => array
(
'label' => &$GLOBALS['TL_LANG']['tl_iso_payment']['paymill_public_key'],
'exclude' => true,
'inputType' => 'text',
'eval' => array('mandatory'=>true, 'maxlength'=>255, 'tl_class'=>'w50'),
'sql' => "varchar(255) NOT NULL default ''",
),
'paymill_private_key' => array
(
'label' => &$GLOBALS['TL_LANG']['tl_iso_payment']['paymill_private_key'],
'exclude' => true,
'inputType' => 'text',
'eval' => array('mandatory'=>true, 'maxlength'=>255, 'tl_class'=>'w50'),
'sql' => "varchar(255) NOT NULL default ''",
),
'guests' => array
(
'label' => &$GLOBALS['TL_LANG']['tl_iso_payment']['guests'],
Expand Down
161 changes: 161 additions & 0 deletions system/modules/isotope/library/Isotope/Model/Payment/Paymill.php
@@ -0,0 +1,161 @@
<?php

/**
* Copyright (C) 2017 Comolo GmbH
*
* @author Hendrik Obermayer
* @copyright 2017 Comolo GmbH <https://www.comolo.de>
* @license MIT
*/

namespace Isotope\Model\Payment;

use System;
use Environment;
use RequestToken;
use Isotope\Interfaces\IsotopePayment;
use Isotope\Interfaces\IsotopeProductCollection;
use Isotope\Interfaces\IsotopePurchasableCollection;
use Isotope\Model\Payment\Postsale;
use Isotope\Model\Product;
use Isotope\Model\ProductCollection\Order;
use Isotope\Module\Checkout;
use Isotope\Template;
use Isotope\Currency;
use Paymill\Models\Request\Transaction as PaymillTransaction;
use Paymill\Request as PaymillRequest;
use Paymill\Services\PaymillException;

/**
* Paymill payment method
*
* @property string $paymill_private_key
* @property string $paymill_public_key
*/
class Paymill extends Postsale
{
/**
* Return information in the backend.
*
* @param integer
* @return string
*/
public function backendInterface($orderId)
{
$database = \Database::getInstance();
$order = $database
->prepare("SELECT * FROM tl_iso_product_collection WHERE id LIKE ?")
->limit(1)
->execute($orderId);
$template = new \BackendTemplate('be_iso_payment_paymill');
$template->order = $order;
$template->payment_data = unserialize($order->payment_data);

return $template->parse();
}

/**
* @inheritdoc
*/
public function processPayment(IsotopeProductCollection $objOrder, \Module $objModule)
{
if ($objOrder->order_status < 1) {
$this->processPostsale($objOrder);
}

return parent::processPayment($objOrder, $objModule);
}

/**
* @inheritdoc
*/
public function processPostsale(IsotopeProductCollection $objOrder)
{
if (!$objOrder instanceof IsotopePurchasableCollection) {
\System::log('Product collection ID "' . $objOrder->getId() . '" is not purchasable', __METHOD__, TL_ERROR);
return false;
}

$paymillToken = \Input::post('paymillToken');

if (!$paymillToken || empty($paymillToken)) {
return false;
}

$transaction = new PaymillTransaction();
$transaction
->setAmount(Currency::getAmountInMinorUnits($objOrder->getTotal(), $objOrder->getCurrency()))
->setCurrency($objOrder->getCurrency())
->setToken($paymillToken)
->setDescription('#'.$objOrder->getId())
;

try {
$request = new PaymillRequest($this->paymill_private_key);
$response = $request->create($transaction);

/**
* @see: https://developers.paymill.com/API/index#response-codes
*/
if ($response->getResponseCode() == 20000) {
// Received payment
$objOrder->payment_data = [
'paymill_code' => $response->getResponseCode(),
'paymill_status' => $response->getStatus(),
'paymill_id' => $response->getId(),
];
$objOrder->setDatePaid(time());
$objOrder->updateOrderStatus($this->new_order_status);
$objOrder->save();

return true;
}

return false;

} catch(PaymillException $e){
System::log('Paymill error. Order "' . $objOrder->getId() . '". Paymill Status: '.$e->getResponseCode() .' Error: '.$e->getErrorMessage(), __METHOD__, TL_ERROR);
return false;
}
}

/**
* @inheritdoc
*/
public function getPostsaleOrder()
{
return Order::findByPk((int) \Input::get('id'));
}

/**
* @inheritdoc
*/
public function checkoutForm(IsotopeProductCollection $objOrder, \Module $objModule)
{
if (!$objOrder instanceof IsotopePurchasableCollection) {
\System::log('Product collection ID "' . $objOrder->getId() . '" is not purchasable', __METHOD__, TL_ERROR);
return false;
}

/** @var Template|\stdClass $objTemplate */
$objTemplate = new Template('iso_payment_paymill');

$objTemplate->setData($this->arrData);
$objTemplate->id = $objOrder->getId();
$objTemplate->amount = Currency::getAmountInMinorUnits($objOrder->getTotal(), $objOrder->getCurrency());
$objTemplate->currency = $objOrder->getCurrency();
$objTemplate->paymill_public_key = $this->paymill_public_key;
$objTemplate->address = $objOrder->getBillingAddress();


$objTemplate->request_token = RequestToken::get();
$objTemplate->action = Environment::get('base') . Checkout::generateUrlForStep('complete', $objOrder);
$objTemplate->cancel_return = Environment::get('base') . Checkout::generateUrlForStep('failed');

$objTemplate->headline = specialchars($GLOBALS['TL_LANG']['MSC']['pay_with_redirect'][0]);
$objTemplate->slabel = specialchars($GLOBALS['TL_LANG']['MSC']['pay_with_redirect'][2]);
$objTemplate->blabel = specialchars($GLOBALS['TL_LANG']['MSC']['goBack']);

return $objTemplate->parse();
}
}
@@ -0,0 +1,33 @@
<?php
\System::loadLanguageFile('payment_paymill');
?>
<div style="padding: 5px 18px;">
<h2 class="pending"><? echo $GLOBALS['TL_LANG']['payment_paymill']['translation_details']; ?></h2>
</div>

<div>
<table cellpadding="0" cellspacing="0" class="tl_show" style="width:650px">
<tbody>
<tr>
<td style="vertical-align:top"><span class="tl_label"><? echo $GLOBALS['TL_LANG']['payment_paymill']['order_id']; ?>:</span></td>
<td><? echo $this->order->id; ?></td>
</tr>
<tr>
<td class="tl_bg" style="vertical-align:top">
<span class="tl_label"><? echo $GLOBALS['TL_LANG']['payment_paymill']['paymill_code']; ?>:
<a href="https://developers.paymill.com/API/index#response-codes">(Info)</a>
</span>
</td>
<td class="tl_bg"><? echo $this->payment_data['paymill_code']; ?></td>
</tr>
<tr>
<td class="" style="vertical-align:top"><span class="tl_label"><? echo $GLOBALS['TL_LANG']['payment_paymill']['paymill_status']; ?>: </span></td>
<td class=""><? echo $this->payment_data['paymill_status']; ?></td>
</tr>
<tr>
<td class="tl_bg" style="vertical-align:top"><span class="tl_label"><? echo $GLOBALS['TL_LANG']['payment_paymill']['paymill_id']; ?>:</span></td>
<td class="tl_bg"><? echo $this->payment_data['paymill_id']; ?></td>
</tr>
</tbody>
</table>
</div>
60 changes: 60 additions & 0 deletions system/modules/isotope/templates/payment/iso_payment_paymill.html5
@@ -0,0 +1,60 @@
<script type="text/javascript">
var PAYMILL_PUBLIC_KEY = '<? echo $this->paymill_public_key; ?>';
</script>

<script type="text/javascript" src="https://bridge.paymill.com/"></script>

<script type="text/javascript">
var options = {
lang: '<? echo strtolower($GLOBALS['TL_LANGUAGE']); ?>'
};

var callback = function (error) {
if (error) {
console.log(error.apierror, error.message);
}
else {
console.log('Frame loaded successfully');
}
};

var initPayframe = function () {
paymill.embedFrame('credit-card-fields', options, callback);
};

var submitForm = function () {
paymill.createTokenViaFrame({
amount_int: <? echo $this->amount; ?>,
currency: '<? echo $this->currency; ?>',
email: '<?php echo $this->address->email; ?>'
},
function (error, result) {
if (error) {
console.log(error.apierror, error.message); // todo: view error
}
else {
var form = document.getElementById("payment-form");
var tokenField = document.getElementById("paymillToken");
tokenField.value = result.token;
form.submit();
}
}
);
};

window.onload = function () {
initPayframe();
};
</script>

<h2><?= $this->headline ?></h2>
<form id="payment-form" action="<?= $this->action ?>" method="post">
<div id="credit-card-fields"></div>
<input id="paymillToken" name="paymillToken" type="hidden">
<input name="REQUEST_TOKEN" type="hidden" value="<?php echo $this->request_token; ?>">

<div class="submit_container">
<a href="<?php echo $this->cancel_return; ?>" class="submit previous button"><?= $this->blabel ?></a>
<button type="button" class="submit confirm button" onclick="submitForm();"><?= $this->slabel ?></button>
</div>
</form>