first commit
This commit is contained in:
392
class/payments/class.PayPalPlus.php
Normal file
392
class/payments/class.PayPalPlus.php
Normal file
@@ -0,0 +1,392 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use Symfony\Component\Routing\Router;
|
||||
|
||||
require_once 'class.PayPal.php';
|
||||
|
||||
/**
|
||||
* Dependencies: `composer require paypal/rest-api-sdk-php=^1.14`
|
||||
* Example config: $cfg['Modules']['payments']['PayPal'] = [
|
||||
* 'clientID' => 'client id',
|
||||
* 'secret' => 'client secret',
|
||||
* webProfileID - create temporary (3 hours): symfony kupshop:paypal-create-web-profile
|
||||
* or permanent profile: symfony kupshop:paypal-create-web-profile --permanent
|
||||
* optional image path as an argument: symfony kupshop:paypal-create-web-profile --permanent templates/images/logo.png
|
||||
* 'webProfileID' => 'web profile id',
|
||||
* 'mode' => 'sandbox' OR 'live',
|
||||
* 'enableLog' => false,
|
||||
* ].
|
||||
*/
|
||||
class PayPalPlus extends PayPal
|
||||
{
|
||||
public static $name = 'PayPal Plus platební brána';
|
||||
|
||||
protected $templateCart = 'payment.PayPalPlus.cart.tpl';
|
||||
protected $templateOrderView = 'payment.PayPalPlus.orderView.tpl';
|
||||
protected $templateInit = 'payment.PayPalPlus.init.tpl';
|
||||
|
||||
public $class = 'PayPalPlus';
|
||||
|
||||
/** Vytáhne existující, nebo vytvoří novou platbu */
|
||||
public function getPayment()
|
||||
{
|
||||
$cart = ServiceContainer::getService(\KupShop\OrderingBundle\Cart::class);
|
||||
// Preferuj ID z objednavky
|
||||
if (isset($this->order) && ($this->order->getData('paypalplus')['id'] ?? false)) {
|
||||
$payment = $this->getPayPalPayment($this->getApiContext(), $this->order->getData('paypalplus')['id']);
|
||||
} elseif ($cart->getData('paypalplus') && $cart->getData('paypalplus')['id']) {
|
||||
$payment = $this->getPayPalPayment($this->getApiContext(), $cart->getData('paypalplus')['id']);
|
||||
} else {
|
||||
$payment = $this->createPayPalPayment();
|
||||
$cart->setData('paypalplus', ['id' => $payment->getId(), 'token' => $payment->getToken()]);
|
||||
}
|
||||
|
||||
return $payment;
|
||||
}
|
||||
|
||||
public function getPaymentUrl()
|
||||
{
|
||||
if (empty($this->order)) {
|
||||
throw new \KupShop\OrderingBundle\Exception\PaymentException(translate('sameDevicePayment', 'payment'));
|
||||
}
|
||||
|
||||
return path('kupshop_content_orders_order',
|
||||
['id' => $this->order->id, 'cf' => $this->order->getSecurityCode(), 'status' => 1, 'immediate_pay' => 1]);
|
||||
}
|
||||
|
||||
/** Pošle patch request pokud není platba aktualizovana - nema security code */
|
||||
public function makeSurePaymentIsUpdated()
|
||||
{
|
||||
$payment = $this->getPayment();
|
||||
if (empty($payment->getTransactions()[0]->getCustom())) {
|
||||
return $this->updatePayment();
|
||||
}
|
||||
|
||||
return $payment;
|
||||
}
|
||||
|
||||
/** Vytvoří payment s dummy daty - protože se musí tvořit už v košíku */
|
||||
protected function createPayPalPayment($useOriginalCurrency = true, $totalPrice = 0): PayPal\Api\Payment
|
||||
{
|
||||
$apiContext = $this->getApiContext();
|
||||
$dbcfg = Settings::getDefault();
|
||||
if ($this->order && $remainingPayment = roundPrice($this->order->getRemainingPayment())->asFloat() <= 0) {
|
||||
$this->success(translate('paymentSuccess', 'payment'));
|
||||
}
|
||||
|
||||
$payer = new \PayPal\Api\Payer();
|
||||
$payer->setPaymentMethod('paypal');
|
||||
|
||||
$amount = new \PayPal\Api\Amount();
|
||||
$amount->setCurrency('EUR')->setTotal('2.00');
|
||||
|
||||
$item1 = new \PayPal\Api\Item();
|
||||
$item1->setName('Payment for order '.($this->order ? $this->order->order_no : '').' on '.$dbcfg->shop_firm_name)
|
||||
->setCurrency('EUR')
|
||||
->setQuantity(1)
|
||||
->setPrice($totalPrice);
|
||||
|
||||
$itemList = new \PayPal\Api\ItemList();
|
||||
$itemList->setItems([$item1]);
|
||||
|
||||
$transaction = new \PayPal\Api\Transaction();
|
||||
$transaction->setAmount($amount)
|
||||
->setDescription('Payment for order')
|
||||
->setInvoiceNumber('123456')
|
||||
->setItemList($itemList);
|
||||
|
||||
$redirectUrls = new \PayPal\Api\RedirectUrls();
|
||||
$redirectUrls->setReturnUrl(
|
||||
path('kupshop_ordering_payment_legacypayment',
|
||||
array_merge([
|
||||
'step' => 2,
|
||||
'class' => $this->class,
|
||||
], []),
|
||||
Router::ABSOLUTE_URL)
|
||||
)->setCancelUrl(
|
||||
path('kupshop_ordering_payment_legacypayment',
|
||||
array_merge([
|
||||
'step' => 4,
|
||||
'class' => $this->class,
|
||||
], []),
|
||||
Router::ABSOLUTE_URL)
|
||||
);
|
||||
|
||||
$payment = new \PayPal\Api\Payment();
|
||||
$payment->setIntent('sale')
|
||||
->setPayer($payer)
|
||||
->setTransactions([$transaction])
|
||||
->setRedirectUrls($redirectUrls);
|
||||
|
||||
try {
|
||||
$payment->create($apiContext);
|
||||
} catch (PayPal\Exception\PayPalConnectionException $e) {
|
||||
$data = $e->getData();
|
||||
if ($data) {
|
||||
$data = json_decode($data, true);
|
||||
}
|
||||
|
||||
if (($data['name'] ?? false) === 'VALIDATION_ERROR') {
|
||||
$this->error(translate('PayPalConnectionException', 'paypal'));
|
||||
ServiceContainer::getService('logger')->error('PayPal exception: '.print_r($e->getData(), true),
|
||||
['file' => __FILE__, 'line' => __LINE__]);
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
return $payment;
|
||||
}
|
||||
|
||||
/** Funkce pro patch paymentu reálnými daty */
|
||||
public function updatePayment(): PayPal\Api\Payment
|
||||
{
|
||||
$payment = $this->getPayment();
|
||||
|
||||
if ($useOriginalCurrency = in_array($this->order->currency, $this->allowedCurrencies)) {
|
||||
$totalPrice = roundPrice($this->order->getRemainingPayment())->asFloat();
|
||||
} else {
|
||||
$totalPrice = $this->order->convertPriceToEUR(
|
||||
roundPrice($this->order->getRemainingPayment())->asFloat()
|
||||
);
|
||||
}
|
||||
|
||||
$patchAmount = new \PayPal\Api\Patch();
|
||||
$patchAddress = new \PayPal\Api\Patch();
|
||||
$patchPayer = new \PayPal\Api\Patch();
|
||||
$patchItems = new \PayPal\Api\Patch();
|
||||
$patchCustom = new \PayPal\Api\Patch();
|
||||
$patchInvoiceNo = new \PayPal\Api\Patch();
|
||||
|
||||
$amount = new \PayPal\Api\Amount();
|
||||
$amount->setCurrency($useOriginalCurrency ? ($this->order ? $this->order->currency : '') : 'EUR')
|
||||
->setTotal($totalPrice);
|
||||
|
||||
$patchAmount->setOp('replace')
|
||||
->setPath('/transactions/0/amount')
|
||||
->setValue($amount);
|
||||
|
||||
$payerDeliveryAddress = new \PayPal\Api\ShippingAddress();
|
||||
$payerDeliveryAddress->setState($this->order->delivery_state ?? '')
|
||||
->setCountryCode($this->order->delivery_country ?? '')
|
||||
->setCity($this->order->delivery_city ?? '')
|
||||
->setLine1($this->order->delivery_street ?? '')
|
||||
->setLine2($this->order->delivery_custom_address ?? '')
|
||||
->setPostalCode($this->order->delivery_zip ?? '')
|
||||
->setRecipientName($this->order->delivery_name.' '.$this->order->delivery_surname);
|
||||
|
||||
$patchAddress->setOp('add')
|
||||
->setPath('/transactions/0/item_list/shipping_address')
|
||||
->setValue($payerDeliveryAddress);
|
||||
|
||||
$payerInfoAddress = new \PayPal\Api\Address();
|
||||
$payerInfoAddress->setState($this->order->invoice_state ?? '')
|
||||
->setCountryCode($this->order->invoice_country ?? '')
|
||||
->setCity($this->order->invoice_city ?? '')
|
||||
->setLine1($this->order->invoice_street ?? '')
|
||||
->setLine2($this->order->invoice_custom_address ?? '')
|
||||
->setPostalCode($this->order->invoice_zip ?? '');
|
||||
|
||||
$payerInfo = new \PayPal\Api\PayerInfo();
|
||||
$payerInfo->setEmail($this->order ? $this->order->getUserEmail() : '')
|
||||
->setBillingAddress($payerInfoAddress)
|
||||
->setFirstName($this->order->invoice_name ?? '')
|
||||
->setLastName($this->order->invoice_surname ?? '');
|
||||
|
||||
$patchPayer->setOp('add')
|
||||
->setPath('/payer/payer_info')
|
||||
->setValue($payerInfo);
|
||||
|
||||
$items = [];
|
||||
$itemList = new \PayPal\Api\ItemList();
|
||||
|
||||
foreach ($this->order->fetchItems() as $orderItem) {
|
||||
$item = new \PayPal\Api\Item();
|
||||
$item->setName($orderItem['descr'])
|
||||
->setCurrency($useOriginalCurrency ? $this->order->currency ?? '' : 'EUR')
|
||||
->setQuantity($orderItem['pieces'])
|
||||
->setPrice($orderItem['piece_price']['value_with_vat']->asFloat());
|
||||
$items[] = $item;
|
||||
}
|
||||
$itemList->setItems($items);
|
||||
|
||||
$patchItems->setOp('replace')
|
||||
->setPath('/transactions/0/item_list')
|
||||
->setValue($itemList);
|
||||
|
||||
$patchCustom->setOp('add')
|
||||
->setPath('/transactions/0/custom')
|
||||
->setValue($this->order->getSecurityCode());
|
||||
|
||||
$patchInvoiceNo->setOp('add')
|
||||
->setPath('/transactions/0/invoice_number')
|
||||
->setValue($this->order->order_no);
|
||||
|
||||
$patchRequest = new \PayPal\Api\PatchRequest();
|
||||
$patchRequest->setPatches([
|
||||
$patchAddress,
|
||||
$patchAmount,
|
||||
$patchPayer,
|
||||
$patchItems,
|
||||
$patchCustom,
|
||||
$patchInvoiceNo,
|
||||
]);
|
||||
|
||||
try {
|
||||
$payment->update($patchRequest, $this->getApiContext());
|
||||
} catch (Exception $ex) {
|
||||
ServiceContainer::getService('logger')->error('PayPal exception: '.$ex->getMessage(), ['file' => __FILE__, 'line' => __LINE__]);
|
||||
|
||||
if ($ex instanceof \PayPal\Exception\PayPalConnectionException) {
|
||||
ServiceContainer::getService('logger')->error('PayPal exception: '.print_r($ex->getData(), true),
|
||||
['file' => __FILE__, 'line' => __LINE__]);
|
||||
}
|
||||
|
||||
$this->error('storno');
|
||||
}
|
||||
|
||||
return $payment;
|
||||
}
|
||||
|
||||
public function processStep_1()
|
||||
{
|
||||
// $this->error('');
|
||||
}
|
||||
|
||||
public function processStep_2()
|
||||
{
|
||||
ServiceContainer::getService('logger')->error('PayPal response: '.print_r([$_GET, $_POST, $_SERVER], true),
|
||||
['file' => __FILE__, 'line' => __LINE__]);
|
||||
$payPalPaymentID = getVal('paymentId', null, false);
|
||||
$apiContext = $this->getApiContext();
|
||||
$payment = $this->getPayPalPayment($apiContext, $payPalPaymentID);
|
||||
$error = false;
|
||||
if ($payment) {
|
||||
$this->orderId = $this->selectSQL('orders',
|
||||
['order_no' => $payment->getTransactions()[0]->getInvoiceNumber()],
|
||||
['id'])->fetchOne();
|
||||
$this->order = new Order();
|
||||
$this->order->createFromDB($this->orderId);
|
||||
if ($this->order->getSecurityCode() == $payment->getTransactions()[0]->getCustom()) {
|
||||
// Při platbě paypal umožňuje změnit adresu doručení....
|
||||
|
||||
// $address = $payment->getTransactions()[0]->getItemList()->getShippingAddress()->toArray();
|
||||
// $address = $payment->toArray();
|
||||
// if (isset($address['payer']['payer_info']['first_name']) && isset($address['payer']['payer_info']['last_name'])) {
|
||||
// // $this->order->updateSQL('orders', [
|
||||
// // 'delivery_name' => $address['payer']['payer_info']['first_name'],
|
||||
// // 'delivery_surname' => $address['payer']['payer_info']['last_name'],
|
||||
// // 'delivery_street' => $address['payer']['payer_info']['shipping_address']['line1'],
|
||||
// // 'delivery_city' => $address['payer']['payer_info']['shipping_address']['city'],
|
||||
// // 'delivery_zip' => $address['payer']['payer_info']['shipping_address']['postal_code'],
|
||||
// // 'delivery_country' => $address['payer']['payer_info']['shipping_address']['country_code'],
|
||||
// // 'delivery_phone' => $address['payer']['payer_info']['phone'] ?? '',
|
||||
// // 'delivery_state' => $address['payer']['payer_info']['shipping_address']['state'],
|
||||
// // ], ['id' => $this->orderId]);
|
||||
//
|
||||
// $name = explode(' ', $address['recipient_name']);
|
||||
// $firstname = $name[0] ?? '';
|
||||
// unset($name[0]);
|
||||
// $lastname = implode(' ', $name);
|
||||
// $this->order->updateSQL('orders', [
|
||||
// 'delivery_name' => $firstname,
|
||||
// 'delivery_surname' => $lastname ?? '',
|
||||
// 'delivery_street' => $address['line1'],
|
||||
// 'delivery_city' => $address['city'],
|
||||
// 'delivery_zip' => $address['postal_code'],
|
||||
// 'delivery_country' => $address['country_code'],
|
||||
// 'delivery_phone' => $address['payer']['payer_info']['phone'] ?? '',
|
||||
// 'delivery_state' => $address['payer']['payer_info']['shipping_address']['state'],
|
||||
// ], ['id' => $this->orderId]);
|
||||
// }
|
||||
|
||||
$this->createPayment(
|
||||
$payment->getId(),
|
||||
$payment->getTransactions()[0]->getAmount()->getTotal(),
|
||||
['paymentClass' => self::class]
|
||||
);
|
||||
$this->processPayment($payment);
|
||||
|
||||
$paymentInstructions = $payment->getPaymentInstruction();
|
||||
if ($paymentInstructions) {
|
||||
$paypalData = $this->order->getData('paypalplus');
|
||||
$paypalData['payment_instruction'] = $paymentInstructions->toArray();
|
||||
$this->order->setData('paypalplus', $paypalData);
|
||||
}
|
||||
|
||||
$this->step(3, 'wait', ['paymentId' => $payment->getId()]);
|
||||
} else {
|
||||
$error = true;
|
||||
}
|
||||
} else {
|
||||
$error = true;
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->error(translate('payment_status_check_error', 'payment'));
|
||||
}
|
||||
}
|
||||
|
||||
public function processStep_3()
|
||||
{
|
||||
$apiContext = $this->getApiContext();
|
||||
$payPalPaymentID = getVal('paymentId', null, false);
|
||||
if (!$payPalPaymentID) {
|
||||
$kupshopPayment = $this->getPendingPayment();
|
||||
if ($kupshopPayment) {
|
||||
// use already created payment
|
||||
$payPalPaymentID = $kupshopPayment['decoded_data']->session;
|
||||
} else {
|
||||
$this->error('storno');
|
||||
}
|
||||
}
|
||||
$this->processPayment($this->getPayPalPayment($apiContext, $payPalPaymentID));
|
||||
}
|
||||
|
||||
public function processStep_4()
|
||||
{
|
||||
$token = getVal('token', null, false);
|
||||
if (!$token) {
|
||||
$this->error('storno');
|
||||
}
|
||||
$payPalId = sqlQueryBuilder()
|
||||
->select("id, json_extract(note_admin, '$.paypalplus.id') as paypalID")
|
||||
->from('orders')
|
||||
->where("json_extract(note_admin, '$.paypalplus.token') = :token")
|
||||
->setParameter('token', $token)
|
||||
->execute()
|
||||
->fetchAssociative();
|
||||
|
||||
if (!$payPalId) {
|
||||
$this->error('storno');
|
||||
}
|
||||
$this->orderId = $payPalId['id'];
|
||||
$this->order = new \Order();
|
||||
$this->order->createFromDB($this->orderId);
|
||||
$this->error(translate('payment_storno', 'payment'));
|
||||
}
|
||||
|
||||
public static function getSettingsConfiguration(): array
|
||||
{
|
||||
return [
|
||||
'fields' => [
|
||||
'clientID' => [
|
||||
'title' => 'clientID',
|
||||
'type' => 'text',
|
||||
],
|
||||
'secret' => [
|
||||
'title' => 'secret',
|
||||
'type' => 'text',
|
||||
],
|
||||
'mode' => [
|
||||
'title' => 'Režim',
|
||||
'type' => 'select',
|
||||
'options' => ['live' => 'Produkční režim', 'sandbox' => 'Testovaci režim'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user