Files
redline.com.pl/modules/paypal/classes/API/Request/V_1/PaypalOrderCreateRequest.php
2024-11-11 18:46:54 +01:00

321 lines
11 KiB
PHP

<?php
/**
* 2007-2020 PayPal
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author 2007-2020 PayPal
* @author 202 ecommerce <tech@202-ecommerce.com>
* @copyright PayPal
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
namespace PaypalAddons\classes\API\Request\V_1;
use Cart;
use Configuration;
use Context;
use \Address;
use \Customer;
use \Country;
use Module;
use PayPal;
use PayPal\Api\RedirectUrls;
use PaypalAddons\classes\API\Response\Error;
use PaypalAddons\classes\API\Response\ResponseOrderCreate;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\ItemList;
use PayPal\Api\Item;
use PayPal\Api\Amount;
use PayPal\Api\Transaction;
use PayPal\Api\PayerInfo;
use PayPal\Api\ShippingAddress;
use PayPal\Api\Details;
use State;
use Tools;
class PaypalOrderCreateRequest extends RequestAbstractMB
{
/** @var Amount*/
protected $_amount;
/** @var ItemList*/
protected $_itemList;
/** @var Item[]*/
protected $_items;
/** @var float*/
protected $_itemTotalValue;
/** @var float*/
protected $_taxTotalValue;
/**
* @return ResponseOrderCreate
*/
public function execute()
{
$response = new ResponseOrderCreate();
if ($this->method->isConfigured() == false) {
$error = new Error();
$error->setMessage('Module is not configured');
return $response->setSuccess(false)->setError($error);
}
$payer = new Payer();
$payer->setPaymentMethod("paypal");
$payer->setPayerInfo($this->getPayerInfo());
// ### Itemized information
// (Optional) Lets you specify item wise information
$this->_itemList = new ItemList();
$this->_amount = new Amount();
$this->_getPaymentDetails();
if (Context::getContext()->cart->isVirtualCart() === false) {
$this->_itemList->setShippingAddress($this->getPayerShippingAddress());
}
// ### Transaction
// A transaction defines the contract of a
// payment - what is the payment for and who
// is fulfilling it.
$transaction = new Transaction();
$transaction->setAmount($this->_amount)
->setItemList($this->_itemList)
->setDescription("Payment description")
->setInvoiceNumber(uniqid());
if (is_callable(array(get_class($this->method), 'getIpnUrl'), true)) {
$transaction->setNotifyUrl($this->method->getIpnUrl());
}
// ### Redirect urls
// Set the urls that the buyer must be redirected to after
// payment approval/ cancellation.
$redirectUrls = new RedirectUrls();
$redirectUrls
->setReturnUrl($this->method->getReturnUrl())
->setCancelUrl($this->method->getCancelUrl());
// ### Payment
// A Payment Resource; create one using
// the above types and intent set to 'sale'
$payment = new Payment();
$payment->setIntent("sale")
->setPayer($payer)
->setRedirectUrls($redirectUrls)
->setTransactions(array($transaction));
// Set application_context
$payment->application_context = $this->getApplicationContext();
// ### Create Payment
// Create a payment by calling the 'create' method
// passing it a valid apiContext.
// The return object contains the state and the
// url to which the buyer must be redirected to
// for payment approval
try {
$payment->create($this->getApiContext());
} catch (\Exception $e) {
$error = new Error();
$error
->setErrorCode($e->getCode())
->setMessage($e->getMessage());
return $response->setError($error)->setSuccess(false);
}
return $response
->setApproveLink($payment->getApprovalLink())
->setPaymentId($payment->getId())
->setSuccess(true);
}
protected function getApplicationContext()
{
if (Context::getContext()->cart->isVirtualCart()) {
$applicationContext = [
'shipping_preference' => 'NO_SHIPPING'
];
} else {
$applicationContext = [
'shipping_preference' => 'SET_PROVIDED_ADDRESS'
];
}
return $applicationContext;
}
/**
* @return PayerInfo
*/
protected function getPayerInfo()
{
$customer = Context::getContext()->customer;
$addressCustomer = new Address(Context::getContext()->cart->id_address_delivery);
$countryCustomer = new Country($addressCustomer->id_country);
$payerInfo = new PayerInfo();
$payerInfo->setEmail($customer->email);
$payerInfo->setFirstName($customer->firstname);
$payerInfo->setLastName($customer->lastname);
if ($countryCustomer->iso_code == 'BR') {
$payerTaxId = str_replace(array('.', '-', '/'), '', $addressCustomer->vat_number);
$payerInfo->setTaxId($payerTaxId);
$payerInfo->setTaxIdType($this->method->getTaxIdType($payerTaxId));
}
return $payerInfo;
}
/**
* @return ShippingAddress
*/
protected function getPayerShippingAddress()
{
$addressCustomer = new Address(Context::getContext()->cart->id_address_delivery);
$payerShippingAddress = new ShippingAddress();
$payerShippingAddress->setCountryCode(Tools::strtoupper(Country::getIsoById($addressCustomer->id_country)));
$payerShippingAddress->setCity($addressCustomer->city);
$payerShippingAddress->setLine1($addressCustomer->address1);
$payerShippingAddress->setPostalCode($addressCustomer->postcode);
$payerShippingAddress->setRecipientName(implode(" ", array($addressCustomer->firstname, $addressCustomer->lastname)));
if ((int)$addressCustomer->id_state) {
$state = new State($addressCustomer->id_state);
$payerShippingAddress->setState(Tools::strtoupper($state->iso_code));
}
return $payerShippingAddress;
}
protected function _getPaymentDetails()
{
$paypal = Module::getInstanceByName($this->method->name);
$currency = $paypal->getPaymentCurrencyIso();
$this->_getProductsList($currency);
$this->_getDiscountsList($currency);
$this->_getGiftWrapping($currency);
$this->_getPaymentValues($currency);
}
protected function _getProductsList($currency)
{
$products = Context::getContext()->cart->getProducts();
foreach ($products as $product) {
$product['product_tax'] = $this->method->formatPrice($this->method->formatPrice($product['price_wt']) - $this->method->formatPrice($product['price']));
$item = new Item();
$item->setName(Tools::substr($product['name'], 0, 126))
->setCurrency($currency)
->setDescription(isset($product['attributes']) ? $product['attributes'] : '')
->setQuantity($product['quantity'])
->setSku($product['id_product']) // Similar to `item_number` in Classic API
->setPrice($this->method->formatPrice($product['price']));
$this->_items[] = $item;
$this->_itemTotalValue += $this->method->formatPrice($product['price']) * $product['quantity'];
$this->_taxTotalValue += $this->method->formatPrice($product['product_tax'] * $product['quantity']);
}
}
protected function _getDiscountsList($currency)
{
$totalDiscounts = Context::getContext()->cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS);
if ($totalDiscounts > 0) {
$module = Module::getInstanceByName($this->method->name);
$discountItem = new Item();
$discountItem->setName($module->l('Total discounts', get_class($this)))
->setCurrency($currency)
->setQuantity(1)
->setSku('discounts')
->setPrice(-1 * $totalDiscounts);
$this->_items[] = $discountItem;
$this->_itemTotalValue += (-1 * $totalDiscounts);
}
}
protected function _getGiftWrapping($currency)
{
$wrapping_price = Context::getContext()->cart->gift ? Context::getContext()->cart->getGiftWrappingPrice() : 0;
if ($wrapping_price > 0) {
$wrapping_price = $this->method->formatPrice($wrapping_price);
$item = new Item();
$item->setName('Gift wrapping')
->setCurrency($currency)
->setQuantity(1)
->setSku('wrapping') // Similar to `item_number` in Classic API
->setPrice($wrapping_price);
$this->_items[] = $item;
$this->_itemTotalValue += $wrapping_price;
}
}
private function _getPaymentValues($currency)
{
$this->_itemList->setItems($this->_items);
$context = Context::getContext();
$cart = $context->cart;
$shipping_cost_wt = $cart->getTotalShippingCost();
$shipping = $this->method->formatPrice($shipping_cost_wt);
$total = $this->method->formatPrice($cart->getOrderTotal(true, Cart::BOTH));
$summary = $cart->getSummaryDetails();
$subtotal = $this->method->formatPrice($summary['total_products']);
$total_tax = number_format($this->_taxTotalValue, Paypal::getDecimal(), ".", '');
// total shipping amount
$shippingTotal = $shipping;
if ($subtotal != $this->_itemTotalValue) {
$subtotal = $this->_itemTotalValue;
}
//total
$total_cart = $shippingTotal + $this->_itemTotalValue + $this->_taxTotalValue;
if ($total != $total_cart) {
$total = $total_cart;
}
// ### Additional payment details
// Use this optional field to set additional
// payment information such as tax, shipping
// charges etc.
$details = new Details();
$details->setShipping($shippingTotal)
->setTax($total_tax)
->setSubtotal($subtotal);
// ### Amount
// Lets you specify a payment amount.
// You can also specify additional details
// such as shipping, tax.
$this->_amount->setCurrency($currency)
->setTotal($total)
->setDetails($details);
}
}