6 declare(strict_types=1);
76 protected $_apiType = \Magento\Paypal\Model\Api\Nvp::class;
308 \
Magento\Customer\Model\Session $customerSession,
314 \
Magento\Paypal\Model\CartFactory $cartFactory,
317 \
Magento\Paypal\Model\Billing\AgreementFactory $agreementFactory,
332 $this->_taxData = $taxData;
333 $this->_checkoutData = $checkoutData;
334 $this->_configCacheType = $configCacheType;
336 $this->_localeResolver = $localeResolver;
337 $this->_paypalInfo = $paypalInfo;
339 $this->_coreUrl = $coreUrl;
340 $this->_cartFactory = $cartFactory;
341 $this->_checkoutOnepageFactory = $onepageFactory;
342 $this->_agreementFactory = $agreementFactory;
343 $this->_apiTypeFactory = $apiTypeFactory;
344 $this->_objectCopyService = $objectCopyService;
345 $this->_checkoutSession = $checkoutSession;
348 $this->_messageManager = $messageManager;
353 $this->_customerSession = isset(
$params[
'session'])
354 &&
$params[
'session'] instanceof \Magento\Customer\Model\Session ?
$params[
'session'] : $customerSession;
357 $this->_config =
$params[
'config'];
359 throw new \Exception(
'Config instance is required.');
363 $this->_quote =
$params[
'quote'];
365 throw new \Exception(
'Quote instance is required.');
380 if ($this->_config->areButtonsDynamic()) {
381 $cacheId = self::PAL_CACHE_ID . $this->_storeManager->getStore()->getId();
382 $pal = $this->_configCacheType->load($cacheId);
383 if (self::PAL_CACHE_ID == $pal) {
388 $this->
_getApi()->callGetPalDetails();
389 $pal = $this->
_getApi()->getPal();
390 $this->_configCacheType->save($pal, $cacheId);
392 $this->_configCacheType->save(self::PAL_CACHE_ID, $cacheId);
393 $this->_logger->critical($e);
398 return $this->_config->getExpressCheckoutShortcutImageUrl(
399 $this->_localeResolver->getLocale(),
400 $this->_quote->getBaseGrandTotal(),
415 $this->_giropayUrls = [$successUrl, $cancelUrl, $pendingUrl];
427 $this->_isBARequested = $flag;
439 $this->_isBml = $isBml;
486 public function start($returnUrl, $cancelUrl, $button =
null)
488 $this->_quote->collectTotals();
490 if (!$this->_quote->getGrandTotal()) {
491 throw new \Magento\Framework\Exception\LocalizedException(
493 'PayPal can\'t process orders with a zero balance due. ' 494 .
'To finish your purchase, please go through the standard checkout process.' 499 $this->_quote->reserveOrderId();
500 $this->quoteRepository->save($this->_quote);
502 $solutionType = $this->_config->getMerchantCountry() ==
'DE' 504 : $this->_config->getValue(
'solutionType');
505 $totalAmount = round($this->_quote->getBaseGrandTotal(), 2);
507 ->setCurrencyCode($this->_quote->getBaseCurrencyCode())
508 ->setInvNum($this->_quote->getReservedOrderId())
509 ->setReturnUrl($returnUrl)
510 ->setCancelUrl($cancelUrl)
511 ->setSolutionType($solutionType)
512 ->setPaymentAction($this->_config->getValue(
'paymentAction'));
513 if ($this->_giropayUrls) {
517 'giropay_cancel_url' => $cancelUrl,
518 'giropay_success_url' => $successUrl,
519 'giropay_bank_txn_pending_url' => $pendingUrl,
525 $this->
_getApi()->setFundingSource(
'BML');
530 if ($this->_config->getValue(
'requireBillingAddress') == PaypalConfig::REQUIRE_BILLING_ADDRESS_ALL) {
531 $this->
_getApi()->setRequireBillingAddress(1);
536 if ($this->_quote->getIsVirtual()) {
537 if ($this->_config->getValue(
'requireBillingAddress')
538 == PaypalConfig::REQUIRE_BILLING_ADDRESS_VIRTUAL
540 $this->
_getApi()->setRequireBillingAddress(1);
542 $this->
_getApi()->setSuppressShipping(
true);
544 $this->
_getApi()->setBillingAddress($this->_quote->getBillingAddress());
546 $address = $this->_quote->getShippingAddress();
548 if (
true ===
$address->validate()) {
552 $this->_quote->getPayment()->setAdditionalInformation(
553 self::PAYMENT_INFO_TRANSPORT_SHIPPING_OVERRIDDEN,
556 $this->_quote->getPayment()->save();
560 $cart = $this->_cartFactory->create([
'salesModel' => $this->_quote]);
564 if (!$this->_taxData->getConfig()->priceIncludesTax()) {
568 $this->_config->exportExpressCheckoutStyleSettings($this->
_getApi());
571 $this->
_getApi()->setQuote($this->_quote);
572 $this->
_getApi()->callSetExpressCheckout();
578 $payment = $this->_quote->getPayment();
579 $payment->unsAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT);
581 if (!empty($button)) {
582 $payment->setAdditionalInformation(self::PAYMENT_INFO_BUTTON, 1);
583 }
elseif (
$payment->hasAdditionalInformation(self::PAYMENT_INFO_BUTTON)) {
584 $payment->unsAdditionalInformation(self::PAYMENT_INFO_BUTTON);
598 $isOnepageCheckout = !$this->_quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON);
599 return $this->_config->isOrderReviewStepDisabled() && $isOnepageCheckout;
616 ->callGetExpressCheckoutDetails();
619 $this->ignoreAddressValidation();
622 $isButton = (bool)
$quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON);
625 $exportedShippingAddress = $this->
_getApi()->getExportedShippingAddress();
626 if (!
$quote->getIsVirtual()) {
629 if ($exportedShippingAddress && $isButton) {
642 if ($this->
_getApi()->getShippingRateCode()) {
649 $quote->getPayment()->setAdditionalInformation(
650 self::PAYMENT_INFO_TRANSPORT_SHIPPING_METHOD,
657 $requireBillingAddress = (int)$this->_config->getValue(
658 'requireBillingAddress' 661 if ($isButton && !$requireBillingAddress && !
$quote->isVirtual()) {
663 $billingAddress->unsAddressId()->unsAddressType()->setCustomerAddressId(
null);
665 $data[
'save_in_address_book'] = 0;
667 $quote->getShippingAddress()->setSameAsBilling(1);
671 $exportedBillingAddress = $this->
_getApi()->getExportedBillingAddress();
677 if ($requireBillingAddress || $isEmptyAddress) {
680 $billingAddress->setCustomerNote($exportedBillingAddress->getData(
'note'));
686 $payment->setMethod($this->_methodType);
688 $payment->setAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_PAYER_ID, $this->
_getApi()->getPayerId())
689 ->setAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_TOKEN,
$token);
691 $this->quoteRepository->save(
$quote);
704 $payment = $this->_quote->getPayment();
705 if (!
$payment || !
$payment->getAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_PAYER_ID)) {
706 throw new \Magento\Framework\Exception\LocalizedException(
__(
'A payer is not identified.'));
708 $this->_quote->setMayEditShippingAddress(
709 1 != $this->_quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_SHIPPING_OVERRIDDEN)
711 $this->_quote->setMayEditShippingMethod(
712 '' == $this->_quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_SHIPPING_METHOD)
714 $this->ignoreAddressValidation();
715 $this->_quote->collectTotals();
716 $this->quoteRepository->save($this->_quote);
728 $debugData = [
'request' =>
$request,
'response' => []];
732 $address = $this->
_getApi()->prepareShippingOptionsCallbackAddress($request);
733 $quoteAddress = $this->_quote->getShippingAddress();
737 if (
$address && $quoteAddress && !$this->_quote->getIsVirtual()) {
738 foreach (
$address->getExportedKeys() as $key) {
739 $quoteAddress->setDataUsingMethod($key,
$address->getData($key));
741 $quoteAddress->setCollectShippingRates(
true);
742 $this->totalsCollector->collectAddressTotals($this->_quote, $quoteAddress);
749 $this->_logger->debug(var_export($debugData,
true));
752 $this->_logger->debug(var_export($debugData,
true));
768 $this->ignoreAddressValidation();
770 $cartExtension = $this->_quote->getExtensionAttributes();
771 if ($cartExtension && $cartExtension->getShippingAssignments()) {
772 $cartExtension->getShippingAssignments()[0]
776 $this->_quote->collectTotals();
777 $this->quoteRepository->save($this->_quote);
793 if ($shippingMethodCode) {
801 $this->ignoreAddressValidation();
802 $this->_quote->collectTotals();
803 $order = $this->quoteManagement->submit($this->_quote);
810 if (
$order->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_REDIRECT)) {
811 $this->_redirectUrl = $this->_config->getExpressCheckoutCompleteUrl(
$token);
814 switch (
$order->getState()) {
816 case \Magento\Sales\Model\Order::STATE_PENDING_PAYMENT:
820 case \Magento\Sales\Model\Order::STATE_PROCESSING:
821 case \Magento\Sales\Model\Order::STATE_COMPLETE:
822 case \Magento\Sales\Model\Order::STATE_PAYMENT_REVIEW:
824 if (!
$order->getEmailSent()) {
825 $this->orderSender->send(
$order);
828 $this->_logger->critical($e);
830 $this->_checkoutSession->start();
843 private function ignoreAddressValidation()
845 $this->_quote->getBillingAddress()->setShouldIgnoreValidation(
true);
846 if (!$this->_quote->getIsVirtual()) {
847 $this->_quote->getShippingAddress()->setShouldIgnoreValidation(
true);
848 if (!$this->_config->getValue(
'requireBillingAddress')
849 && !$this->_quote->getBillingAddress()->getEmail()
851 $this->_quote->getBillingAddress()->setSameAsBilling(1);
894 return \Magento\Checkout\Model\Type\Onepage::METHOD_CUSTOMER;
896 if (!$this->_quote->getCheckoutMethod()) {
897 if ($this->_checkoutData->isAllowedGuestCheckout($this->_quote)) {
903 return $this->_quote->getCheckoutMethod();
915 foreach ($exportedAddress->getExportedKeys() as $key) {
916 $data = $exportedAddress->getData($key);
930 if (!$this->_customerId) {
934 $isRequested = $this->_isBARequested || $this->_quote->getPayment()
935 ->getAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT);
937 if (!($this->_config->getValue(
'allow_ba_signup') == PaypalConfig::EC_BA_SIGNUP_AUTO
938 || $isRequested && $this->_config->shouldAskToCreateBillingAgreement())
943 if (!$this->_agreementFactory->create()->needToCreateForCustomer($this->_customerId)) {
946 $this->
_getApi()->setBillingType($this->
_getApi()->getBillingAgreementType());
957 if (
null === $this->_api) {
958 $this->_api = $this->_apiTypeFactory->create($this->_apiType)->setConfigObject($this->_config);
982 $userSelectedOption =
null;
987 if (
$rate->getErrorMessage()) {
990 $isDefault =
$address->getShippingMethod() ===
$rate->getCode();
991 $amountExclTax = $this->_taxData->getShippingPrice(
$amount,
false,
$address);
992 $amountInclTax = $this->_taxData->getShippingPrice(
$amount,
true,
$address);
994 $options[
$i] = new \Magento\Framework\DataObject(
996 'is_default' => $isDefault,
997 'name' => trim(
"{$rate->getCarrierTitle()} - {$rate->getMethodTitle()}",
' -'),
998 'code' =>
$rate->getCode(),
999 'amount' => $amountExclTax,
1002 if ($calculateTax) {
1004 $amountInclTax - $amountExclTax +
$address->getTaxAmount() -
$address->getShippingTaxAmount()
1010 if (
false === $min || $amountInclTax < $min) {
1011 $min = $amountInclTax;
1018 if ($mayReturnEmpty && $userSelectedOption ===
null) {
1019 $options[] = new \Magento\Framework\DataObject(
1021 'is_default' =>
true,
1022 'name' =>
__(
'N/A'),
1023 'code' =>
'no_rate',
1027 if ($calculateTax) {
1030 }
elseif ($userSelectedOption ===
null && isset(
$options[$iMin])) {
1031 $options[$iMin]->setIsDefault(
true);
1036 usort(
$options, [get_class($this),
'cmpShippingOptions']);
1039 if ($userSelectedOption !==
null && !in_array($userSelectedOption,
$options)) {
1059 if ($option1->getAmount() == $option2->getAmount()) {
1062 return ($option1->getAmount() < $option2->getAmount()) ? -1 : 1;
1080 if ($selectedCode ===
$option[
'code']
1081 || $selectedCode ===
$option[
'name']
1083 || $selectedCode ===
"{$option['code']} {$option['name']}" 1100 $this->_redirectUrl = ($button && !$this->_taxData->getConfig()->priceIncludesTax())
1101 ? $this->_config->getExpressCheckoutStartUrl(
$token)
1102 : $this->_config->getPayPalBasicStartUrl(
$token);
1125 $this->
_getApi()->setIsLineItemsEnabled($this->_config->getValue(PaypalConfig::TRANSFER_CART_LINE_ITEMS));
1128 $cartItems =
$cart->getAllItems();
1129 if ($this->_config->getValue(PaypalConfig::TRANSFER_CART_LINE_ITEMS)
1130 && $this->_config->getValue(PaypalConfig::TRANSFER_SHIPPING_OPTIONS)
1131 && !empty($cartItems)
1133 if (!$this->_quote->getIsVirtual()) {
1136 $this->
_getApi()->setShippingOptionsCallbackUrl(
1137 $this->_coreUrl->getUrl(
1138 '*/*/shippingOptionsCallback',
1139 [
'quote_id' => $this->_quote->getId()]
1155 $quote->setCustomerId(
null)
1156 ->setCustomerEmail(
$quote->getBillingAddress()->getEmail())
1157 ->setCustomerIsGuest(
true)
1158 ->setCustomerGroupId(\
Magento\Customer\Model\Group::NOT_LOGGED_IN_ID);
updateShippingMethod($methodCode)
_prepareShippingOptions(Address $address, $mayReturnEmpty=false, $calculateTax=false)
_setRedirectUrl($button, $token)
setCustomerData(CustomerDataObject $customerData)
elseif(isset( $params[ 'redirect_parent']))
setIsBillingAgreementRequested($flag)
getShippingOptionsCallbackResponse(array $request)
const PAYMENT_INFO_TRANSPORT_REDIRECT
setCustomerWithAddressChange(CustomerDataObject $customerData, $billingAddress=null, $shippingAddress=null)
const PAYMENT_INFO_TRANSPORT_TOKEN
const PAYMENT_INFO_TRANSPORT_SHIPPING_OVERRIDDEN
__construct(\Psr\Log\LoggerInterface $logger, \Magento\Customer\Model\Url $customerUrl, \Magento\Tax\Helper\Data $taxData, \Magento\Checkout\Helper\Data $checkoutData, \Magento\Customer\Model\Session $customerSession, \Magento\Framework\App\Cache\Type\Config $configCacheType, \Magento\Framework\Locale\ResolverInterface $localeResolver, \Magento\Paypal\Model\Info $paypalInfo, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\UrlInterface $coreUrl, \Magento\Paypal\Model\CartFactory $cartFactory, \Magento\Checkout\Model\Type\OnepageFactory $onepageFactory, \Magento\Quote\Api\CartManagementInterface $quoteManagement, \Magento\Paypal\Model\Billing\AgreementFactory $agreementFactory, \Magento\Paypal\Model\Api\Type\Factory $apiTypeFactory, \Magento\Framework\DataObject\Copy $objectCopyService, \Magento\Checkout\Model\Session $checkoutSession, \Magento\Framework\Encryption\EncryptorInterface $encryptor, \Magento\Framework\Message\ManagerInterface $messageManager, \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository, AccountManagement $accountManagement, OrderSender $orderSender, \Magento\Quote\Api\CartRepositoryInterface $quoteRepository, \Magento\Quote\Model\Quote\TotalsCollector $totalsCollector, $params=[])
const PAYMENT_INFO_TRANSPORT_SHIPPING_METHOD
prepareGiropayUrls($successUrl, $cancelUrl, $pendingUrl)
_setBillingAgreementRequest()
static cmpShippingOptions(DataObject $option1, DataObject $option2)
_matchShippingMethodCode(Address $address, $selectedCode)
const REQUIRE_BILLING_ADDRESS_ALL
prepareOrderReview($token=null)
_setExportedAddressData($address, $exportedAddress)
const PAYMENT_INFO_BUTTON
getCheckoutShortcutImageUrl()
const PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT
const PAYMENT_INFO_TRANSPORT_PAYER_ID
const EC_SOLUTION_TYPE_MARK
$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE]
place($token, $shippingMethodCode=null)