Merge pull request #282 from roadster31/basemodulecontroller
Standard pages and enhancements for payment modules
This commit is contained in:
@@ -48,9 +48,9 @@ class BaseFrontController extends BaseController
|
|||||||
/**
|
/**
|
||||||
* Redirect to à route ID related URL
|
* Redirect to à route ID related URL
|
||||||
*
|
*
|
||||||
* @param unknown $routeId the route ID, as found in Config/Resources/routing/admin.xml
|
* @param string $routeId the route ID, as found in Config/Resources/routing/admin.xml
|
||||||
* @param array|\Thelia\Controller\Front\unknown $urlParameters the URL parametrs, as a var/value pair array
|
* @param array $urlParameters the URL parametrs, as a var/value pair array
|
||||||
* @param bool $referenceType
|
* @param bool $referenceType
|
||||||
*/
|
*/
|
||||||
public function redirectToRoute($routeId, $urlParameters = array(), $referenceType = Router::ABSOLUTE_PATH)
|
public function redirectToRoute($routeId, $urlParameters = array(), $referenceType = Router::ABSOLUTE_PATH)
|
||||||
{
|
{
|
||||||
@@ -104,7 +104,7 @@ class BaseFrontController extends BaseController
|
|||||||
/**
|
/**
|
||||||
* Render the given template, and returns the result as an Http Response.
|
* Render the given template, and returns the result as an Http Response.
|
||||||
*
|
*
|
||||||
* @param $templateName the complete template name, with extension
|
* @param string $templateName the complete template name, with extension
|
||||||
* @param array $args the template arguments
|
* @param array $args the template arguments
|
||||||
* @param int $status http code status
|
* @param int $status http code status
|
||||||
* @return \Thelia\Core\HttpFoundation\Response
|
* @return \Thelia\Core\HttpFoundation\Response
|
||||||
|
|||||||
@@ -38,6 +38,13 @@ interface ParserInterface
|
|||||||
|
|
||||||
public function setStatus($status);
|
public function setStatus($status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup the parser with a template definition, which provides a template description.
|
||||||
|
*
|
||||||
|
* @param TemplateDefinition $templateDefinition
|
||||||
|
*/
|
||||||
|
public function setTemplateDefinition(TemplateDefinition $templateDefinition);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a template directory to the current template list
|
* Add a template directory to the current template list
|
||||||
*
|
*
|
||||||
@@ -54,7 +61,7 @@ interface ParserInterface
|
|||||||
* Return the registeted template directories for a givent template type
|
* Return the registeted template directories for a givent template type
|
||||||
*
|
*
|
||||||
* @param unknown $templateType
|
* @param unknown $templateType
|
||||||
* @throws InvalidArgumentException if the tempmateType is not defined
|
* @throws \InvalidArgumentException if the templateType is not defined
|
||||||
* @return array: an array of defined templates directories for the given template type
|
* @return array: an array of defined templates directories for the given template type
|
||||||
*/
|
*/
|
||||||
public function getTemplateDirectories($templateType);
|
public function getTemplateDirectories($templateType);
|
||||||
|
|||||||
@@ -92,11 +92,11 @@ class SmartyParser extends Smarty implements ParserInterface
|
|||||||
/**
|
/**
|
||||||
* Add a template directory to the current template list
|
* Add a template directory to the current template list
|
||||||
*
|
*
|
||||||
* @param unknown $templateType the template type (a TemplateDefinition type constant)
|
* @param int $templateType the template type (a TemplateDefinition type constant)
|
||||||
* @param string $templateName the template name
|
* @param string $templateName the template name
|
||||||
* @param string $templateDirectory path to the template dirtectory
|
* @param string $templateDirectory path to the template dirtectory
|
||||||
* @param unknown $key ???
|
* @param unknown $key ???
|
||||||
* @param string $unshift ??? Etienne ?
|
* @param boolean $unshift ??? Etienne ?
|
||||||
*/
|
*/
|
||||||
public function addTemplateDirectory($templateType, $templateName, $templateDirectory, $key, $unshift = false)
|
public function addTemplateDirectory($templateType, $templateName, $templateDirectory, $key, $unshift = false)
|
||||||
{
|
{
|
||||||
@@ -116,9 +116,9 @@ class SmartyParser extends Smarty implements ParserInterface
|
|||||||
/**
|
/**
|
||||||
* Return the registeted template directories for a givent template type
|
* Return the registeted template directories for a givent template type
|
||||||
*
|
*
|
||||||
* @param unknown $templateType
|
* @param int $templateType
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
* @return multitype:
|
* @return mixed:
|
||||||
*/
|
*/
|
||||||
public function getTemplateDirectories($templateType)
|
public function getTemplateDirectories($templateType)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -124,6 +124,19 @@ class Tlog Implements LoggerInterface
|
|||||||
return self::$instance;
|
return self::$instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Tlog instance, that could be configured without interfering with the "main" instance
|
||||||
|
*
|
||||||
|
* @return Tlog a new Tlog instance.
|
||||||
|
*/
|
||||||
|
public static function getNewInstance() {
|
||||||
|
$instance = new Tlog();
|
||||||
|
|
||||||
|
$instance->init();
|
||||||
|
|
||||||
|
return $instance;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initialize default configuration
|
* initialize default configuration
|
||||||
*/
|
*/
|
||||||
|
|||||||
132
core/lib/Thelia/Module/AbstractPaymentModule.php
Normal file
132
core/lib/Thelia/Module/AbstractPaymentModule.php
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
<?php
|
||||||
|
/*************************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* Thelia */
|
||||||
|
/* */
|
||||||
|
/* Copyright (c) OpenStudio */
|
||||||
|
/* email : info@thelia.net */
|
||||||
|
/* web : http://www.thelia.net */
|
||||||
|
/* */
|
||||||
|
/* This program is free software; you can redistribute it and/or modify */
|
||||||
|
/* it under the terms of the GNU General Public License as published by */
|
||||||
|
/* the Free Software Foundation; either version 3 of the License */
|
||||||
|
/* */
|
||||||
|
/* This program is distributed in the hope that it will be useful, */
|
||||||
|
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||||
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||||
|
/* GNU General Public License for more details. */
|
||||||
|
/* */
|
||||||
|
/* You should have received a copy of the GNU General Public License */
|
||||||
|
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
/* */
|
||||||
|
/*************************************************************************************/
|
||||||
|
|
||||||
|
namespace Thelia\Module;
|
||||||
|
|
||||||
|
use Symfony\Component\Routing\Router;
|
||||||
|
use Thelia\Core\HttpFoundation\Response;
|
||||||
|
use Thelia\Core\Template\ParserInterface;
|
||||||
|
use Thelia\Core\Template\TemplateHelper;
|
||||||
|
use Thelia\Exception\TheliaProcessException;
|
||||||
|
use Thelia\Model\Order;
|
||||||
|
use Thelia\Tools\URL;
|
||||||
|
|
||||||
|
abstract class AbstractPaymentModule extends BaseModule implements PaymentModuleInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* This method is called when the payement gateway needs to be invoked.
|
||||||
|
*
|
||||||
|
* If this method return a Response instance, this response is sent to the browser. Return null if you don't want to
|
||||||
|
* send a response and process the payment yourself.
|
||||||
|
*
|
||||||
|
* In many cases, it's necessary to send a form to the payment gateway. On your response you can return this form already
|
||||||
|
* completed, ready to be sent, instead of redirecting. The generateGatewayFormResponse() may help you in this case :)
|
||||||
|
*
|
||||||
|
* @param Order $order processed order
|
||||||
|
* @return null|Response
|
||||||
|
*/
|
||||||
|
abstract public function pay(Order $order);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called by the Payment loop, to check if the current module has to be displayed to the customer
|
||||||
|
*
|
||||||
|
* If you return true, the payment method will de displayed to the customed
|
||||||
|
* If you return false, the payment method will not be displayed
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
abstract public function isValidPayment();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the payment gateway template. The module should provide the gateway URL and the form fields names and values.
|
||||||
|
*
|
||||||
|
* @param Order $order the order
|
||||||
|
* @param string $gateway_url the payment gateway URL
|
||||||
|
* @param array $form_data an associative array of form data, that will be rendered as hiddent fields
|
||||||
|
*
|
||||||
|
* @return Response the HTTP response.
|
||||||
|
*/
|
||||||
|
public function generateGatewayFormResponse($order, $gateway_url, $form_data)
|
||||||
|
{
|
||||||
|
/** @var ParserInterface $parser */
|
||||||
|
$parser = $this->container->get("thelia.parser");
|
||||||
|
|
||||||
|
$parser->setTemplateDefinition(TemplateHelper::getInstance()->getActiveFrontTemplate());
|
||||||
|
|
||||||
|
$renderedTemplate = $parser->render(
|
||||||
|
"order-payment-gateway.html",
|
||||||
|
array(
|
||||||
|
"order_id" => $order->getId(),
|
||||||
|
"cart_count" => $this->getRequest()->getSession()->getCart()->getCartItems()->count(),
|
||||||
|
"gateway_url" => $gateway_url,
|
||||||
|
"payment_form_data" => $form_data
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return Response::create($renderedTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the order payment success page URL
|
||||||
|
*
|
||||||
|
* @param int $order_id the order ID
|
||||||
|
* @return string the order payment success page URL
|
||||||
|
*/
|
||||||
|
public function getPayementSuccessPageUrl($order_id)
|
||||||
|
{
|
||||||
|
$frontOfficeRouter = $this->container->get('router.front');
|
||||||
|
|
||||||
|
return URL::getInstance()->absoluteUrl(
|
||||||
|
$frontOfficeRouter->generate(
|
||||||
|
"order.placed",
|
||||||
|
array("order_id" => $order_id),
|
||||||
|
Router::ABSOLUTE_URL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect the customer to the failure payment page. if $message is null, a generic message is displayed.
|
||||||
|
*
|
||||||
|
* @param int $order_id the order ID
|
||||||
|
* @param string|null $message an error message.
|
||||||
|
*
|
||||||
|
* @return string the order payment failure page URL
|
||||||
|
*/
|
||||||
|
public function getPayementFailurePageUrl($order_id, $message)
|
||||||
|
{
|
||||||
|
$frontOfficeRouter = $this->container->get('router.front');
|
||||||
|
|
||||||
|
return URL::getInstance()->absoluteUrl(
|
||||||
|
$frontOfficeRouter->generate(
|
||||||
|
"order.failed",
|
||||||
|
array(
|
||||||
|
"order_id" => $order_id,
|
||||||
|
"message" => $message
|
||||||
|
),
|
||||||
|
Router::ABSOLUTE_URL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -158,6 +158,11 @@
|
|||||||
<default key="_controller">Front\Controller\OrderController::orderPlaced</default>
|
<default key="_controller">Front\Controller\OrderController::orderPlaced</default>
|
||||||
<default key="_view">order-placed</default>
|
<default key="_view">order-placed</default>
|
||||||
</route>
|
</route>
|
||||||
|
|
||||||
|
<route id="order.failed" path="/order/failed/{order_id}/{message}">
|
||||||
|
<default key="_controller">Front\Controller\OrderController::orderFailed</default>
|
||||||
|
<default key="_view">order-failed</default>
|
||||||
|
</route>
|
||||||
<!-- end order management process -->
|
<!-- end order management process -->
|
||||||
|
|
||||||
<!-- contact management -->
|
<!-- contact management -->
|
||||||
|
|||||||
@@ -234,6 +234,29 @@ class OrderController extends BaseFrontController
|
|||||||
$this->getParserContext()->set("placed_order_id", $placedOrder->getId());
|
$this->getParserContext()->set("placed_order_id", $placedOrder->getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function orderFailed($order_id, $message)
|
||||||
|
{
|
||||||
|
/* check if the placed order matched the customer */
|
||||||
|
$failedOrder = OrderQuery::create()->findPk(
|
||||||
|
$this->getRequest()->attributes->get('order_id')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (null === $failedOrder) {
|
||||||
|
throw new TheliaProcessException("No failed order", TheliaProcessException::NO_PLACED_ORDER, $failedOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
$customer = $this->getSecurityContext()->getCustomerUser();
|
||||||
|
|
||||||
|
if (null === $customer || $failedOrder->getCustomerId() !== $customer->getId()) {
|
||||||
|
throw new TheliaProcessException("Received failed order id does not belong to the current customer", TheliaProcessException::PLACED_ORDER_ID_BAD_CURRENT_CUSTOMER, $placedOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->getParserContext()
|
||||||
|
->set("failed_order_id", $failedOrder->getId())
|
||||||
|
->set("failed_order_message", $message)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getOrderEvent()
|
protected function getOrderEvent()
|
||||||
{
|
{
|
||||||
$order = $this->getOrder($this->getRequest());
|
$order = $this->getOrder($this->getRequest());
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
<ul class="breadcrumb pull-left">
|
<ul class="breadcrumb pull-left">
|
||||||
<li><a href="{url path='/admin/home'}">{intl l="Home"}</a></li>
|
<li><a href="{url path='/admin/home'}">{intl l="Home"}</a></li>
|
||||||
<li><a href="#">{intl l="Search"}</a></li>
|
<li><a href="#">{intl l="Search for '%term'" term=trim($smarty.get.search_term)}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
{loop name="customer_list" type="customer" current="false" visible="*" backend_context="1" search_term=$smarty.get.search_term search_in="ref,firstname,lastname,email"}
|
{loop name="customer_list" type="customer" current="false" visible="*" backend_context="1" search_term=trim($smarty.get.search_term) search_in="ref,firstname,lastname,email"}
|
||||||
{assign "lastOrderDate" ''}
|
{assign "lastOrderDate" ''}
|
||||||
{assign "lastOrderAmount" ''}
|
{assign "lastOrderAmount" ''}
|
||||||
{assign "lastOrderCurrency" ''}
|
{assign "lastOrderCurrency" ''}
|
||||||
@@ -131,7 +131,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
{loop type="order" name="order-search" backend_context=1 customer="*" search_term=$smarty.get.search_term search_in="ref,customer_ref,customer_firstname,customer_lastname,customer_email"}
|
{loop type="order" name="order-search" backend_context=1 customer="*" search_term=trim($smarty.get.search_term) search_in="ref,customer_ref,customer_firstname,customer_lastname,customer_email"}
|
||||||
{loop type="order_address" name="order-invoice-address" id=$INVOICE_ADDRESS}
|
{loop type="order_address" name="order-invoice-address" id=$INVOICE_ADDRESS}
|
||||||
{assign "orderInvoiceFirstName" $FIRSTNAME}
|
{assign "orderInvoiceFirstName" $FIRSTNAME}
|
||||||
{assign "orderInvoiceLastName" $LASTNAME}
|
{assign "orderInvoiceLastName" $LASTNAME}
|
||||||
@@ -187,7 +187,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
{loop type="product" name="product-search" visible="*" search_mode="sentence" search_term=$smarty.get.search_term search_in="ref,title"}
|
{loop type="product" name="product-search" visible="*" search_mode="sentence" search_term=trim($smarty.get.search_term) search_in="ref,title"}
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>{$ID}</td>
|
<td>{$ID}</td>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<div class="main">
|
<div class="main">
|
||||||
<article id="cart" class="col-main" role="main" aria-labelledby="main-label">
|
<article id="cart" class="col-main" role="main" aria-labelledby="main-label">
|
||||||
|
|
||||||
<h1 id="main-label" class="page-header">{intl l="Your Cart"}</h1>
|
<h1 id="main-label" class="page-header">{intl l="Billing and delivery"}</h1>
|
||||||
|
|
||||||
{include file="misc/checkout-progress.tpl" step="delivery"}
|
{include file="misc/checkout-progress.tpl" step="delivery"}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<div class="main">
|
<div class="main">
|
||||||
<article class="col-main" role="main" aria-labelledby="main-label">
|
<article class="col-main" role="main" aria-labelledby="main-label">
|
||||||
|
|
||||||
<h1 id="main-label" class="page-header">{intl l="Your Cart"}</h1>
|
<h1 id="main-label" class="page-header">{intl l="Check my order"}</h1>
|
||||||
|
|
||||||
{include file="misc/checkout-progress.tpl" step="invoice"}
|
{include file="misc/checkout-progress.tpl" step="invoice"}
|
||||||
|
|
||||||
|
|||||||
76
templates/frontOffice/default/order-payment-gateway.html
Normal file
76
templates/frontOffice/default/order-payment-gateway.html
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
{extends file="layout.tpl"}
|
||||||
|
|
||||||
|
{* Security *}
|
||||||
|
{block name="no-return-functions" prepend}
|
||||||
|
{check_auth role="CUSTOMER" login_tpl="login"}
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{* Body Class *}
|
||||||
|
{block name="body-class"}page-order-payment{/block}
|
||||||
|
|
||||||
|
{* Breadcrumb *}
|
||||||
|
{block name='no-return-functions' append}
|
||||||
|
{$breadcrumbs = [
|
||||||
|
['title' => {intl l="Cart"}, 'url'=>{url path="/cart"}],
|
||||||
|
['title' => {intl l="Secure Payment"}, 'url'=>{url path="/order/pay"}]
|
||||||
|
]}
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
|
||||||
|
{block name="main-content"}
|
||||||
|
<div class="main">
|
||||||
|
<article class="col-main clearfix" role="main" aria-labelledby="main-label">
|
||||||
|
|
||||||
|
<h1 id="main-label" class="page-header">{intl l="Secure payment"}</h1>
|
||||||
|
|
||||||
|
{include file="misc/checkout-progress.tpl" step="last"}
|
||||||
|
|
||||||
|
{loop type="order" name="placed-order" id=$order_id}
|
||||||
|
|
||||||
|
<div id="payment-success" class="panel">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">{intl l="You choose to pay by"} : <span class="payment-method">{loop name="payment-module" type="module" id=$PAYMENT_MODULE}{$TITLE}{/loop}</span></h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-body">
|
||||||
|
{if $cart_count > 0}
|
||||||
|
<div class="panel-heading clearfix">
|
||||||
|
{intl l="Connecting to the secure payment server, please wait a few seconds..."}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-body">
|
||||||
|
|
||||||
|
<form action="{$gateway_url}" method="post" id="payement_gateway_form">
|
||||||
|
{foreach from=$payment_form_data key='name' item='value'}
|
||||||
|
<input type="hidden" name="{$name}" value="{$value}" />
|
||||||
|
{/foreach}
|
||||||
|
|
||||||
|
<p>{intl l='If nothing happens within 10 seconds, <a id="force-submit-payment-form" href="#">please click here</a>.'}</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{else}
|
||||||
|
{intl l="Sorry, your cart is empty. There's nothing to pay."}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/loop}
|
||||||
|
</article>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block name="javascript-initialization"}
|
||||||
|
<script type="text/javascript">
|
||||||
|
jQuery(function($) {
|
||||||
|
$('#payement_gateway_form').submit();
|
||||||
|
|
||||||
|
$('#force-submit-payment-form').click(function(ev) {
|
||||||
|
$('#payement_gateway_form').submit();
|
||||||
|
|
||||||
|
ev.preventDefault();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user