Skip to content

Commit

Permalink
Integrated payment provider paymill
Browse files Browse the repository at this point in the history
  • Loading branch information
henobi committed Jul 28, 2017
1 parent 20b2425 commit 54999d7
Show file tree
Hide file tree
Showing 7 changed files with 276 additions and 1 deletion.
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>

0 comments on commit 54999d7

Please sign in to comment.