Skip to content

Commit

Permalink
Merge pull request #56 from thelia-modules/rework
Browse files Browse the repository at this point in the history
Merge branch rework
  • Loading branch information
NicolasBarbey authored Oct 28, 2024
2 parents 8e46eaf + ae98fdc commit f341320
Show file tree
Hide file tree
Showing 20 changed files with 724 additions and 159 deletions.
9 changes: 9 additions & 0 deletions Config/Update/5.0.0.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
SET FOREIGN_KEY_CHECKS = 0;

-- ---------------------------------------------------------------------
-- paypal_planified_payment
-- ---------------------------------------------------------------------
ALTER TABLE paypal_planified_payment
ADD `paypal_id` VARCHAR(255) NOT NULL;

SET FOREIGN_KEY_CHECKS = 1;
1 change: 1 addition & 0 deletions Config/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
<hook id="paypal.front.hook" class="PayPal\Hook\FrontHookManager">
<argument type="service" id="request_stack"/>
<argument type="service" id="service_container" />
<tag name="hook.event_listener" event="main.head-bottom" type="front" method="injectCSS" />
<tag name="hook.event_listener" event="login.main-bottom" type="front" method="onLoginMainBottom"/>
<tag name="hook.event_listener" event="order-invoice.payment-extra" type="front" method="onOrderInvoicePaymentExtra"/>
<tag name="hook.event_listener" event="order-invoice.bottom" type="front" method="onOrderInvoiceBottom"/>
Expand Down
2 changes: 1 addition & 1 deletion Config/module.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<language>en_US</language>
<language>fr_FR</language>
</languages>
<version>4.0.9</version>
<version>5.0.0</version>
<authors>
<author>
<name>gbarral</name>
Expand Down
1 change: 1 addition & 0 deletions Config/schema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

<table name="paypal_planified_payment" namespace="PayPal\Model">
<column name="id" autoIncrement="true" primaryKey="true" required="true" type="INTEGER" />
<column name="paypal_id" size="255" type="VARCHAR" required="true" />
<column name="title" size="255" type="VARCHAR" required="true" />
<column name="description" type="CLOB" />
<column name="frequency" size="255" type="VARCHAR" required="true" />
Expand Down
1 change: 1 addition & 0 deletions Config/thelia.sql
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ DROP TABLE IF EXISTS `paypal_planified_payment`;
CREATE TABLE `paypal_planified_payment`
(
`id` INTEGER NOT NULL AUTO_INCREMENT,
`paypal_id` VARCHAR(255) NOT NULL,
`frequency` VARCHAR(255) NOT NULL,
`frequency_interval` INTEGER NOT NULL,
`cycle` INTEGER NOT NULL,
Expand Down
169 changes: 169 additions & 0 deletions Controller/PayPalApiController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<?php

namespace PayPal\Controller;

use PayPal\Model\PaypalOrderQuery;
use PayPal\Model\PaypalPlanifiedPaymentQuery;
use PayPal\PayPal;
use PayPal\Service\PayPalApiService;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;
use Thelia\Controller\Front\BaseFrontController;
use Thelia\Log\Tlog;
use Thelia\Model\CurrencyQuery;
use Thelia\Model\OrderQuery;

#[Route("/paypal/api", name: "paypal_api_")]
class PayPalApiController extends BaseFrontController
{

#[Route("/pay", name: "pay", methods: "POST")]
public function createPaypalOrder(Request $request, PayPalApiService $payPalApiService){
$data = json_decode($request->getContent(), true);

if (array_key_exists('planified_payment_id', $data) && !empty($data['planified_payment_id'])) {
return $this->createPlan($request, $payPalApiService, $data);
}

return $this->createOrder($request, $payPalApiService, $data);
}


public function createOrder(Request $request, PayPalApiService $payPalApiService, $data)
{
try {
$order = OrderQuery::create()->findPk($data['order_id']);

$currency = CurrencyQuery::create()->findPk($order->getCurrencyId());

$body = [
'intent' => 'CAPTURE',
'purchase_units' => [
[
'reference_id' => $order->getRef(),
'amount' => [
'currency_code' => $currency?->getCode(),
'value' => $order->getTotalAmount($tax, true, true)
]
]
]
];

$body['payment_source'] = [
'paypal' => [
'experience_context' => [
'landing_page' => 'NO_PREFERENCE',
'user_action' => 'PAY_NOW',
'payment_method_preference' => 'IMMEDIATE_PAYMENT_REQUIRED',
'return_url' => $data['return_url'],
'cancel_url' => $data['cancel_url'],
]
]
];

if (!empty($data['use_card']) && true === (bool)$data['use_card']) {
$body['payment_source'] = [
'card' => [
'card_name' => $data['name'],
'card_number' => $data['number'],
'card_security_code' => $data['security_code'],
'card_expiry' => $data['expiry']
]
];
}

$response = $payPalApiService->sendPostResquest($body, PayPal::getBaseUrl().PayPal::PAYPAL_API_CREATE_ORDER_URL);
$responseContent = $response->getContent();
$responseInfo = json_decode($responseContent, true);

$paypalOrder = PaypalOrderQuery::create()
->filterById($order->getId())
->findOneOrCreate();

$paypalOrder
->setPaymentId($responseInfo['id'])
->save();

return new JsonResponse($responseContent);
}catch (\Exception $exception){
Tlog::getInstance()->error($exception->getMessage());
return new JsonResponse(json_encode(['error' => $exception->getMessage()]), $exception->getCode());
}

}

#[Route("/capture", name: "capture", methods: "POST")]
public function captureOrder(Request $request, PayPalApiService $payPalApiService)
{
try {
$data = json_decode($request->getContent(), true);

$paypalOrder = PaypalOrderQuery::create()->findPk($data['order_id']);

$response = $payPalApiService->sendPostResquest(
null,
PayPal::getBaseUrl().PayPal::PAYPAL_API_CREATE_ORDER_URL.'/'.$paypalOrder->getPaymentId().'/capture'
);

$responseContent = $response->getContent();
return new JsonResponse($responseContent);
} catch (\Exception $exception) {
Tlog::getInstance()->error($exception->getMessage());
return new JsonResponse(json_encode(['error' => $exception->getMessage()]), $exception->getCode());
}
}

public function createPlan(Request $request, PayPalApiService $payPalApiService, $data)
{
try {
$lang = $request->getSession()->getLang();

$order = OrderQuery::create()->findPk($data['order_id']);

$planifiedPayment = PaypalPlanifiedPaymentQuery::create()->findPk($data["planified_payment_id"]);
$planifiedPayment->setLocale($lang?->getLocale());

$totalAmount = $order->getTotalAmount();
$cycleAmount = round($totalAmount / $planifiedPayment->getCycle(), 2);

$currency = CurrencyQuery::create()->findPk($order->getCurrencyId());

$body = [
"product_id" => $planifiedPayment->getPaypalId(),
"name" => $planifiedPayment->getTitle(),
"description" => $planifiedPayment->getDescription(),
"billing_cycles" => [[
"tenure_type" => 'REGULAR',
"sequence" => 1,
"total_cycles" => $planifiedPayment->getCycle(),
"frequency" => [
"interval_unit" => $planifiedPayment->getFrequency(),
"interval_count" => $planifiedPayment->getFrequencyInterval(),
],
"pricing_scheme" => [
"fixed_price" => [
"currency_code" => $currency->getCode(),
"value" => $cycleAmount
]
]
]],
"payment_preferences" => [
"setup_fee" => [
"currency_code" => $currency->getCode(),
"value" => 0,
]
]
];

$response = $payPalApiService->sendPostResquest($body, PayPal::getBaseUrl() . PayPal::PAYPAL_API_CREATE_PLAN_URL);
$responseContent = $response->getContent();
return new JsonResponse($responseContent);
} catch (\Exception $exception) {
Tlog::getInstance()->error($exception->getMessage());
return new JsonResponse(json_encode(['error' => $exception->getMessage()]), $exception->getCode());
}

}

}
49 changes: 49 additions & 0 deletions Controller/PayPalFrontController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace PayPal\Controller;

use OpenApi\Controller\Front\CheckoutController;
use PayPal\Model\Base\PaypalPlanifiedPayment;
use PayPal\Model\PaypalPlanifiedPaymentQuery;
use PayPal\Service\Base\PayPalBaseService;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;
use Thelia\Controller\Front\BaseFrontController;

#[Route("/order/paypal", name: "paypal_front_")]
class PayPalFrontController extends BaseFrontController
{
#[Route("/pay", name: "pay", methods: "GET")]
public function showPayPalPaymentPage(Request $request)
{
$templateData = [];
$templateData['paypal_mode'] = PayPalBaseService::getMode();
$templateData['paypal_merchant_id'] = PayPalBaseService::getMerchantId();
$templateData['paypal_client_id'] = PayPalBaseService::getLogin();
$paymentOptions = $request->getSession()->get(CheckoutController::PAYMENT_MODULE_OPTION_CHOICES_SESSION_KEY);
$lang = $request->getSession()->getLang();

$templateData['intent'] = "capture";
$templateData['planified_payment_id'] = null;

if (!empty($paymentOptions) && 'paypal' !== $paymentType = $paymentOptions['code']) {
$planifiedPaymentId = explode('_', $paymentType)[1];


$plan = PaypalPlanifiedPaymentQuery::create()->findPk($planifiedPaymentId);
$plan->setLocale($lang->getLocale());

$templateData['intent'] = "subscription";
$templateData['planified_payment_id'] = $planifiedPaymentId;
$templateData['plan_title'] = $plan->getTitle();
$templateData['plan_description'] = $plan->getDescription();
$templateData['plan_frequency'] = $plan->getFrequency();
$templateData['plan_frequency_interval'] = $plan->getFrequencyInterval();
$templateData['plan_cycle'] = $plan->getCycle();
}

$templateData['order_id'] = $request->get('order_id');

return $this->render("paypal/paypal-payment", $templateData);
}
}
26 changes: 18 additions & 8 deletions Controller/PayPalPlanifiedPaymentController.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
use PayPal\Model\PaypalPlanifiedPayment;
use PayPal\Model\PaypalPlanifiedPaymentQuery;
use PayPal\PayPal;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
Expand All @@ -39,7 +40,9 @@
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Template\ParserContext;
use Symfony\Component\Routing\Annotation\Route;
use Thelia\Model\LangQuery;
use Thelia\Tools\TokenProvider;
use Thelia\Tools\URL;

/**
* @Route("/admin/module/paypal/configure/planified", name="configure_planified")
Expand Down Expand Up @@ -143,8 +146,17 @@ protected function getUpdateForm()
protected function hydrateObjectForm(ParserContext $parserContext, $object)
{
/** @var \Thelia\Model\Lang $lang */
$parserContext->getSession()->get('thelia.current.lang');
$object->getTranslation($lang->getLocale());
$lang = $parserContext->getSession()->get('thelia.admin.edition.lang');
$editLanguageId = $this->getRequest()->get('edit_language_id');

if (
null !== $editLanguageId &&
null !== $editLang = LangQuery::create()->findPk($editLanguageId)
){
$lang = $editLang;
}

$object->setLocale($lang->getLocale());

$data = [
PayPalFormFields::FIELD_PP_ID => $object->getId(),
Expand All @@ -158,7 +170,7 @@ protected function hydrateObjectForm(ParserContext $parserContext, $object)
PayPalFormFields::FIELD_PP_POSITION => $object->getPosition()
];

return $this->createForm(PayPalPlanifiedPaymentUpdateForm::getName(), 'form', $data);
return $this->createForm(PayPalPlanifiedPaymentUpdateForm::getName(), FormType::class, $data);
}

/**
Expand Down Expand Up @@ -328,11 +340,9 @@ protected function renderEditionTemplate()
*/
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
'paypal.admin.configuration.planified.update',
[],
$this->getEditionArguments()
);
$result = $this->getEditionArguments();
return $this->generateRedirect(URL::getInstance()->absoluteUrl('/admin/module/paypal/configure/planified/'.$result['planifiedPaymentId']));

}

/**
Expand Down
34 changes: 31 additions & 3 deletions EventListeners/PayPalPlanifiedPaymentListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,44 @@

use PayPal\Event\PayPalEvents;
use PayPal\Event\PayPalPlanifiedPaymentEvent;
use PayPal\PayPal;
use PayPal\Service\PayPalApiService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Thelia\Log\Tlog;

class PayPalPlanifiedPaymentListener implements EventSubscriberInterface
{
public function __construct(private PayPalApiService $payPalApiService)
{
}

/**
* @param PayPalPlanifiedPaymentEvent $event
* @throws \Exception
* @throws \Propel\Runtime\Exception\PropelException
*/
public function createOrUpdate(PayPalPlanifiedPaymentEvent $event)
public function create(PayPalPlanifiedPaymentEvent $event)
{
$planifiedPayment = $event->getPayPalPlanifiedPayment();
$planifiedPayment->save();

try {
$body = [
"name" => $planifiedPayment->getTitle(),
"description" => $planifiedPayment->getDescription(),
"type" => "SERVICE",
];

$response = $this->payPalApiService->sendPostResquest($body, PayPal::getBaseUrl() . PayPal::PAYPAL_API_CREATE_PRODUCT_URL);
$responseContent = $response->getContent();
$responseInfo = json_decode($responseContent, true);
$planifiedPayment->setPaypalId($responseInfo['id'])->save();
}catch (\Exception $exception) {
Tlog::getInstance()->error($exception->getMessage());
}
}

public function update(PayPalPlanifiedPaymentEvent $event)
{
$event->getPayPalPlanifiedPayment()->save();
}
Expand All @@ -55,8 +83,8 @@ public function delete(PayPalPlanifiedPaymentEvent $event)
public static function getSubscribedEvents()
{
return [
PayPalEvents::PAYPAL_PLANIFIED_PAYMENT_CREATE => ['createOrUpdate', 128],
PayPalEvents::PAYPAL_PLANIFIED_PAYMENT_UPDATE => ['createOrUpdate', 128],
PayPalEvents::PAYPAL_PLANIFIED_PAYMENT_CREATE => ['create', 128],
PayPalEvents::PAYPAL_PLANIFIED_PAYMENT_UPDATE => ['update', 128],
PayPalEvents::PAYPAL_PLANIFIED_PAYMENT_DELETE => ['delete', 128]
];
}
Expand Down
Loading

0 comments on commit f341320

Please sign in to comment.