$json['users'] = $userModule->findUsers(); | $json['users'] = $userModule->findUsers(); | ||||
$json['one_distribution_week_active'] = $distributionModule->isOneDistributionWeekActive($date); | $json['one_distribution_week_active'] = $distributionModule->isOneDistributionWeekActive($date); | ||||
$json['tiller_is_synchro'] = $this->buildAjaxInfosResponseTiller($producer, $date); | $json['tiller_is_synchro'] = $this->buildAjaxInfosResponseTiller($producer, $date); | ||||
$json['tiller_is_authenticated'] = $this->getOrderModule()->getTillerManager()->isAuthenticated(); | |||||
$json['tiller_url_authorize_code'] = $this->getOrderModule()->getTillerManager()->getUrlAuthorizeCode(); | |||||
$json['missing_subscriptions'] = $this->buildAjaxInfosResponseMissingSubscriptions($date, $distribution, $ordersArrayObject); | $json['missing_subscriptions'] = $this->buildAjaxInfosResponseMissingSubscriptions($date, $distribution, $ordersArrayObject); | ||||
} | } | ||||
<?php | |||||
/** | |||||
* Copyright distrib (2018) | |||||
* | |||||
* contact@opendistrib.net | |||||
* | |||||
* Ce logiciel est un programme informatique servant à aider les producteurs | |||||
* à distribuer leur production en circuits courts. | |||||
* | |||||
* Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||||
* respectant les principes de diffusion des logiciels libres. Vous pouvez | |||||
* utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||||
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||||
* sur le site "http://www.cecill.info". | |||||
* | |||||
* En contrepartie de l'accessibilité au code source et des droits de copie, | |||||
* de modification et de redistribution accordés par cette licence, il n'est | |||||
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||||
* seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||||
* titulaire des droits patrimoniaux et les concédants successifs. | |||||
* | |||||
* A cet égard l'attention de l'utilisateur est attirée sur les risques | |||||
* associés au chargement, à l'utilisation, à la modification et/ou au | |||||
* développement et à la reproduction du logiciel par l'utilisateur étant | |||||
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||||
* manipuler et qui le réserve donc à des développeurs et des professionnels | |||||
* avertis possédant des connaissances informatiques approfondies. Les | |||||
* utilisateurs sont donc invités à charger et tester l'adéquation du | |||||
* logiciel à leurs besoins dans des conditions permettant d'assurer la | |||||
* sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||||
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||||
* | |||||
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||||
* pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||||
* termes. | |||||
*/ | |||||
namespace backend\controllers; | |||||
use yii\filters\AccessControl; | |||||
use linslin\yii2\curl; | |||||
class TillerController extends BackendController | |||||
{ | |||||
public function behaviors() | |||||
{ | |||||
return [ | |||||
'access' => [ | |||||
'class' => AccessControl::class, | |||||
'rules' => [ | |||||
[ | |||||
'allow' => true, | |||||
'roles' => ['@'], | |||||
'matchCallback' => function ($rule, $action) { | |||||
return $this->getUserModule() | |||||
->getAuthorizationChecker() | |||||
->isGrantedAsProducer($this->getUserCurrent()); | |||||
} | |||||
] | |||||
], | |||||
], | |||||
]; | |||||
} | |||||
public function actionOauth(string $code) | |||||
{ | |||||
$producerModule = $this->getProducerModule(); | |||||
$curl = new curl\Curl(); | |||||
$redirectUri = $producerModule->getSolver()->getConfig('tiller_redirect_uri'); | |||||
$clientId = $producerModule->getSolver()->getConfig('tiller_client_id'); | |||||
$clientSecret = $producerModule->getSolver()->getConfig('tiller_client_secret'); | |||||
$url = "https://oauth.api.tiller.systems/oauth2/token?grant_type=authorization_code&redirect_uri=$redirectUri&client_id=$clientId&client_secret=$clientSecret&code=$code"; | |||||
$response = $curl | |||||
->setHeaders(['Content-type' => 'application/x-www-form-urlencoded']) | |||||
->post($url); | |||||
$datasResponse = json_decode($response); | |||||
$accessToken = $datasResponse->access_token; | |||||
$refreshToken = $datasResponse->refresh_token; | |||||
$producer = $this->getProducerCurrent(); | |||||
$producer->tiller_access_token = $accessToken; | |||||
$producer->tiller_refresh_token = $refreshToken; | |||||
$producer->save(); | |||||
return $this->redirectDashboard(); | |||||
} | |||||
} |
</div> | </div> | ||||
<button id="btn-add-subscriptions" @click="addSubscriptions" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-plus"></span> Importer les abonnements</button> | <button id="btn-add-subscriptions" @click="addSubscriptions" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-plus"></span> Importer les abonnements</button> | ||||
<template v-if="producer && producer.tiller == true"> | <template v-if="producer && producer.tiller == true"> | ||||
<button v-if="tillerIsSynchro" id="btn-tiller" class="btn btn-success btn-xs" disabled><span class="glyphicon glyphicon-refresh"></span> Synchronisé avec Tiller</button> | |||||
<template v-else-if="!isDistributionToday()"> | |||||
<template v-if="tillerIsAuthenticated"> | |||||
<button v-if="tillerIsSynchro" id="btn-tiller" class="btn btn-success btn-xs" disabled><span class="glyphicon glyphicon-refresh"></span> Synchronisé avec Tiller</button> | |||||
<template v-else-if="!isDistributionToday()"> | |||||
<span data-toggle="tooltip" data-placement="top" data-original-title="Synchronisation possible uniquement le jour de la distribution"> | <span data-toggle="tooltip" data-placement="top" data-original-title="Synchronisation possible uniquement le jour de la distribution"> | ||||
<button id="btn-tiller" class="btn btn-xs btn-default" disabled><span class="glyphicon glyphicon-refresh"></span> Synchroniser avec Tiller</button> | <button id="btn-tiller" class="btn btn-xs btn-default" disabled><span class="glyphicon glyphicon-refresh"></span> Synchroniser avec Tiller</button> | ||||
</span> | </span> | ||||
</template> | |||||
<button v-else id="btn-tiller" class="btn btn-xs btn-default" @click="synchroTiller"><span class="glyphicon glyphicon-refresh"></span> Synchroniser avec Tiller</button> | |||||
</template> | |||||
<template v-else> | |||||
<a :href="tillerUrlAuthorizeCode" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-refresh"></span> Connexion Tiller</a> | |||||
</template> | </template> | ||||
<button v-else id="btn-tiller" class="btn btn-xs btn-default" @click="synchroTiller"><span class="glyphicon glyphicon-refresh"></span> Synchroniser avec Tiller</button> | |||||
</template> | </template> | ||||
<button v-if="producer && producer.credit" id="btn-pay-orders" class="btn btn-default btn-xs" @click="payOrders"><span class="glyphicon glyphicon-euro"></span> Débiter les commandes</button> | <button v-if="producer && producer.credit" id="btn-pay-orders" class="btn btn-default btn-xs" @click="payOrders"><span class="glyphicon glyphicon-euro"></span> Débiter les commandes</button> | ||||
<button id="btn-add-order" @click="openModalFormOrderCreate" class="btn btn-xs btn-primary"><span class="glyphicon glyphicon-plus"></span> Ajouter une commande</button> | <button id="btn-add-order" @click="openModalFormOrderCreate" class="btn btn-xs btn-primary"><span class="glyphicon glyphicon-plus"></span> Ajouter une commande</button> |
<?= $form->field($model, 'tiller') | <?= $form->field($model, 'tiller') | ||||
->dropDownList(Dropdown::noYesChoices()) | ->dropDownList(Dropdown::noYesChoices()) | ||||
->label('Synchroniser avec Tiller'); ?> | ->label('Synchroniser avec Tiller'); ?> | ||||
<?= $form->field($model, 'tiller_api_version') | |||||
->dropDownList([ | |||||
'v2' => 'v2', | |||||
'v3' => 'v3' | |||||
]); ?> | |||||
<h4>API V2</h4> | |||||
<?= $form->field($model, 'tiller_provider_token'); ?> | <?= $form->field($model, 'tiller_provider_token'); ?> | ||||
<?= $form->field($model, 'tiller_restaurant_token'); ?> | <?= $form->field($model, 'tiller_restaurant_token'); ?> | ||||
<h4>API V3</h4> | |||||
<?= $form->field($model, 'tiller_redirect_uri'); ?> | |||||
<?= $form->field($model, 'tiller_client_id'); ?> | |||||
<?= $form->field($model, 'tiller_client_secret'); ?> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
showModalPayment: false, | showModalPayment: false, | ||||
idOrderPayment: 0, | idOrderPayment: 0, | ||||
showLoading: false, | showLoading: false, | ||||
tillerIsAuthenticated: false, | |||||
tillerUrlAuthorizeCode: '#', | |||||
tillerIsSynchro: false, | tillerIsSynchro: false, | ||||
checkboxSelectAllOrders: false, | checkboxSelectAllOrders: false, | ||||
messageGenerateDeliveryNoteDisplayed: false, | messageGenerateDeliveryNoteDisplayed: false, | ||||
app.deliveryNotes = response.data.delivery_notes; | app.deliveryNotes = response.data.delivery_notes; | ||||
} | } | ||||
app.tillerUrlAuthorizeCode = response.data.tiller_url_authorize_code; | |||||
app.tillerIsAuthenticated = response.data.tiller_is_authenticated; | |||||
app.tillerIsSynchro = response.data.tiller_is_synchro; | app.tillerIsSynchro = response.data.tiller_is_synchro; | ||||
app.calendar.attrs = []; | app.calendar.attrs = []; | ||||
.then(function (response) { | .then(function (response) { | ||||
app.init(app.idActivePointSale); | app.init(app.idActivePointSale); | ||||
}); | }); | ||||
}, | |||||
authTiller: function() { | |||||
}, | }, | ||||
totalActivePointSale: function () { | totalActivePointSale: function () { | ||||
var total = 0; | var total = 0; |
<?php | |||||
namespace common\components\Tiller; | |||||
interface TillerClientInterface | |||||
{ | |||||
public function isAuthenticated(): bool; | |||||
public function getOrders($date); | |||||
public function postOrder($params); | |||||
} |
* termes. | * termes. | ||||
*/ | */ | ||||
namespace common\components; | |||||
namespace common\components\Tiller; | |||||
use linslin\yii2\curl; | use linslin\yii2\curl; | ||||
class TillerClient | |||||
class TillerClientV2 implements TillerClientInterface | |||||
{ | { | ||||
var $curl; | var $curl; | ||||
var $providerToken; | var $providerToken; | ||||
$this->restaurantToken = $restaurantToken; | $this->restaurantToken = $restaurantToken; | ||||
} | } | ||||
public function isAuthenticated(): bool | |||||
{ | |||||
return true; | |||||
} | |||||
public function getOrders($date) | public function getOrders($date) | ||||
{ | { | ||||
$orders = $this->curl->setGetParams([ | $orders = $this->curl->setGetParams([ |
<?php | |||||
/** | |||||
* Copyright distrib (2018) | |||||
* | |||||
* contact@opendistrib.net | |||||
* | |||||
* Ce logiciel est un programme informatique servant à aider les producteurs | |||||
* à distribuer leur production en circuits courts. | |||||
* | |||||
* Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||||
* respectant les principes de diffusion des logiciels libres. Vous pouvez | |||||
* utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||||
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||||
* sur le site "http://www.cecill.info". | |||||
* | |||||
* En contrepartie de l'accessibilité au code source et des droits de copie, | |||||
* de modification et de redistribution accordés par cette licence, il n'est | |||||
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||||
* seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||||
* titulaire des droits patrimoniaux et les concédants successifs. | |||||
* | |||||
* A cet égard l'attention de l'utilisateur est attirée sur les risques | |||||
* associés au chargement, à l'utilisation, à la modification et/ou au | |||||
* développement et à la reproduction du logiciel par l'utilisateur étant | |||||
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||||
* manipuler et qui le réserve donc à des développeurs et des professionnels | |||||
* avertis possédant des connaissances informatiques approfondies. Les | |||||
* utilisateurs sont donc invités à charger et tester l'adéquation du | |||||
* logiciel à leurs besoins dans des conditions permettant d'assurer la | |||||
* sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||||
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||||
* | |||||
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||||
* pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||||
* termes. | |||||
*/ | |||||
namespace common\components\Tiller; | |||||
use common\components\Tiller\TillerClientInterface; | |||||
use linslin\yii2\curl; | |||||
class TillerClientV3 implements TillerClientInterface | |||||
{ | |||||
var $curl; | |||||
var $clientId; | |||||
var $clientSecret; | |||||
var $urlApi = 'https://app.tillersystems.com/api/'; | |||||
public function __construct(string $clientId = null, string $clientSecret = null) | |||||
{ | |||||
$this->curl = new curl\Curl(); | |||||
$this->clientId = $clientId; | |||||
$this->clientSecret = $clientSecret; | |||||
} | |||||
public function getUrlAuthorizeCode(string $clientId, string $redirectUri): string | |||||
{ | |||||
return "https://oauth.api.tiller.systems/oauth2/authorize?client_id=$clientId&response_type=code&scope=&redirect_uri=$redirectUri"; | |||||
} | |||||
public function isAuthenticated(): bool | |||||
{ | |||||
return false; | |||||
} | |||||
public function getOrders($date) | |||||
{ | |||||
$orders = $this->curl->setGetParams([ | |||||
'client_id' => $this->clientId, | |||||
'client_secret' => $this->clientSecret, | |||||
'dateFrom' => date('Y-m-d H-i-s', strtotime($date)), | |||||
'dateTo' => date( | |||||
'Y-m-d H-i-s', | |||||
strtotime($date) + 24 * 60 * 60 - 1 | |||||
), | |||||
'status' => 'IN_PROGRESS', | |||||
])->get($this->urlApi . 'orders'); | |||||
return json_decode($orders); | |||||
} | |||||
public function postOrder($params) | |||||
{ | |||||
return $this->curl->setPostParams( | |||||
array_merge([ | |||||
'client_id' => $this->clientId, | |||||
'client_secret' => $this->clientSecret, | |||||
], $params) | |||||
) | |||||
->post($this->urlApi . 'orders'); | |||||
} | |||||
} |
namespace common\logic\Order\Order\Service; | namespace common\logic\Order\Order\Service; | ||||
use common\components\TillerClient; | |||||
use common\components\Tiller\TillerClientV2; | |||||
use common\helpers\MeanPayment; | use common\helpers\MeanPayment; | ||||
use common\logic\AbstractManager; | use common\logic\AbstractManager; | ||||
use common\logic\Order\Order\Model\Order; | use common\logic\Order\Order\Model\Order; | ||||
use common\logic\Order\ProductOrder\Service\ProductOrderSolver; | use common\logic\Order\ProductOrder\Service\ProductOrderSolver; | ||||
use common\logic\Producer\Producer\Service\ProducerSolver; | use common\logic\Producer\Producer\Service\ProducerSolver; | ||||
use common\components\Tiller\TillerClientInterface; | |||||
use common\components\Tiller\TillerClientV3; | |||||
class TillerManager extends AbstractManager | class TillerManager extends AbstractManager | ||||
{ | { | ||||
protected ?bool $tillerActivated; | protected ?bool $tillerActivated; | ||||
protected ProducerSolver $producerSolver; | protected ProducerSolver $producerSolver; | ||||
protected TillerClient $tillerClient; | |||||
protected TillerClientInterface $tillerClient; | |||||
protected OrderSolver $orderSolver; | protected OrderSolver $orderSolver; | ||||
protected OrderBuilder $orderBuilder; | protected OrderBuilder $orderBuilder; | ||||
protected ProductOrderSolver $productOrderSolver; | protected ProductOrderSolver $productOrderSolver; | ||||
$this->productOrderSolver = $this->loadService(ProductOrderSolver::class); | $this->productOrderSolver = $this->loadService(ProductOrderSolver::class); | ||||
} | } | ||||
public function getClient(): TillerClient | |||||
public function getClient(): ?TillerClientInterface | |||||
{ | { | ||||
return new TillerClient( | |||||
$this->producerSolver->getConfig('tiller_provider_token'), | |||||
$this->producerSolver->getConfig('tiller_restaurant_token') | |||||
$apiVersion = $this->producerSolver->getConfig('tiller_api_version'); | |||||
if($apiVersion == 'v2') { | |||||
return new TillerClientV2( | |||||
$this->producerSolver->getConfig('tiller_provider_token'), | |||||
$this->producerSolver->getConfig('tiller_restaurant_token') | |||||
); | |||||
} | |||||
elseif($apiVersion == 'v3') { | |||||
return new TillerClientV3( | |||||
$this->producerSolver->getConfig('tiller_client_id'), | |||||
$this->producerSolver->getConfig('tiller_client_secret') | |||||
); | |||||
} | |||||
return null; | |||||
} | |||||
public function getUrlAuthorizeCode(): string | |||||
{ | |||||
return $this->tillerClient->getUrlAuthorizeCode( | |||||
$this->producerSolver->getConfig('tiller_client_id'), | |||||
$this->producerSolver->getConfig('tiller_redirect_uri') | |||||
); | ); | ||||
} | } | ||||
public function isAuthenticated(): bool | |||||
{ | |||||
return $this->tillerClient->isAuthenticated(); | |||||
} | |||||
public function synchronizeDistribution(string $date): array | public function synchronizeDistribution(string $date): array | ||||
{ | { | ||||
$return = []; | $return = []; |
'admin_comment', | 'admin_comment', | ||||
'export_shopping_cart_labels_format', | 'export_shopping_cart_labels_format', | ||||
'document_image_bottom', | 'document_image_bottom', | ||||
'website' | |||||
'website', | |||||
'tiller_api_version', | |||||
'tiller_client_id', | |||||
'tiller_client_secret', | |||||
'tiller_access_token', | |||||
'tiller_refresh_token', | |||||
'tiller_redirect_uri' | |||||
], | ], | ||||
'string' | 'string' | ||||
], | ], | ||||
'website' => 'Site web', | 'website' => 'Site web', | ||||
'option_leave_period_start' => 'Prochains congés : date de début', | 'option_leave_period_start' => 'Prochains congés : date de début', | ||||
'option_leave_period_end' => 'Prochains congés : date de fin', | 'option_leave_period_end' => 'Prochains congés : date de fin', | ||||
'tiller_api_version' => 'Tiller : version API', | |||||
'tiller_client_id' => 'Tiller : client ID', | |||||
'tiller_client_secret' => 'Tiller : client secret', | |||||
'tiller_access_token' => 'Tiller : access token', | |||||
'tiller_refresh_token' => 'Tiller : refresh token', | |||||
'tiller_redirect_uri' => 'Tiller : callback URL', | |||||
]; | ]; | ||||
} | } | ||||
<?php | |||||
use yii\db\Migration; | |||||
use yii\db\Schema; | |||||
/** | |||||
* Class m240206_135558_add_columns_producer_tiller_api_v3 | |||||
*/ | |||||
class m240206_135558_add_columns_producer_tiller_api_v3 extends Migration | |||||
{ | |||||
/** | |||||
* {@inheritdoc} | |||||
*/ | |||||
public function safeUp() | |||||
{ | |||||
$this->addColumn('producer', 'tiller_api_version', Schema::TYPE_STRING.' DEFAULT \'v3\''); | |||||
$this->addColumn('producer', 'tiller_client_id', Schema::TYPE_STRING); | |||||
$this->addColumn('producer', 'tiller_client_secret', Schema::TYPE_STRING); | |||||
$this->addColumn('producer', 'tiller_access_token', Schema::TYPE_TEXT); | |||||
$this->addColumn('producer', 'tiller_refresh_token', Schema::TYPE_TEXT); | |||||
$this->addColumn('producer', 'tiller_redirect_uri', Schema::TYPE_STRING); | |||||
} | |||||
/** | |||||
* {@inheritdoc} | |||||
*/ | |||||
public function safeDown() | |||||
{ | |||||
$this->dropColumn('producer', 'tiller_api_version'); | |||||
$this->dropColumn('producer', 'tiller_client_id'); | |||||
$this->dropColumn('producer', 'tiller_client_secret'); | |||||
$this->dropColumn('producer', 'tiller_access_token'); | |||||
$this->dropColumn('producer', 'tiller_refresh_token'); | |||||
$this->dropColumn('producer', 'tiller_redirect_uri'); | |||||
} | |||||
} |