From 5534bcf2f4b230638012c31ebccdec5e98064d04 Mon Sep 17 00:00:00 2001 From: dimti Date: Fri, 18 Jun 2021 12:15:18 +0300 Subject: [PATCH] Initial --- .gitignore | 3 + Plugin.php | 26 ++++ classes/DefaultMoneyRepair.php | 16 +++ classes/SberCheckout.php | 283 +++++++++++++++++++++++++++++++++++++++++ composer.json | 14 ++ lang/en/lang.php | 18 +++ lang/ru/lang.php | 18 +++ plugin.yaml | 6 + updates/version.yaml | 2 + 9 files changed, 386 insertions(+) create mode 100644 .gitignore create mode 100644 Plugin.php create mode 100644 classes/DefaultMoneyRepair.php create mode 100644 classes/SberCheckout.php create mode 100644 composer.json create mode 100644 lang/en/lang.php create mode 100644 lang/ru/lang.php create mode 100644 plugin.yaml create mode 100644 updates/version.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7695407 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea +/vendor/ +/composer.lock diff --git a/Plugin.php b/Plugin.php new file mode 100644 index 0000000..abf1455 --- /dev/null +++ b/Plugin.php @@ -0,0 +1,26 @@ +app->get(PaymentGateway::class); + $gateway->registerProvider(new SberCheckout()); + + // For solve this issue https://github.com/OFFLINE-GmbH/oc-mall-plugin/issues/258 + $this->app->singleton(Money::class, function () { + return new DefaultMoneyRepair(); + }); + } +} diff --git a/classes/DefaultMoneyRepair.php b/classes/DefaultMoneyRepair.php new file mode 100644 index 0000000..d2fdd06 --- /dev/null +++ b/classes/DefaultMoneyRepair.php @@ -0,0 +1,16 @@ +decimals, ',', ' ').' '.$vars['currency']->symbol; + } +} diff --git a/classes/SberCheckout.php b/classes/SberCheckout.php new file mode 100644 index 0000000..25df8d6 --- /dev/null +++ b/classes/SberCheckout.php @@ -0,0 +1,283 @@ +getGateway(); + + try { + $request = $gateway->authorize([ + 'orderNumber' => $this->order->id, + 'amount' => $this->order->total_in_currency, + 'returnUrl' => $this->returnUrl(), + 'failUrl' => $this->cancelUrl(), + 'description' => Lang::get('wpstudio.sber::lang.messages.order_number').$this->order->order_number, + ]); + + assert($request instanceof AuthorizeRequest); + + // hacking private method + $reflectionMethod = new \ReflectionMethod(AbstractRequest::class, 'setParameter'); + $reflectionMethod->setAccessible(true); + $reflectionMethod->invoke($request, 'orderBundle', $this->getOrderBundle()); + + $response = $request->send(); + } catch (Throwable $e) { + return $result->fail([], $e); + } + + assert($response instanceof AuthorizeResponse); + + Session::put('mall.payment.callback', self::class); + + $this->setOrder($result->order); + + $result->order->payment_transaction_id = $response->getOrderId(); + + $result->order->save(); + + return $result->redirect($response->getRedirectResponse()->getTargetUrl()); + } + + /** + * Gerenate sberbank orderBundle + * @see https://securepayments.sberbank.ru/wiki/doku.php/integration:api:rest:requests:registerpreauth_cart#orderbundle + * + * @return array + * + */ + final public function getOrderBundle(): array + { + $orderCreationDateFormatted = $this->order->created_at->format('Y-m-dTH:m:s'); + + $cartItems = $this->getOrderCartItems(); + + if ($cartItems) { + return [ + 'orderCreationDate' => $orderCreationDateFormatted ?? '', + 'cartItems' => $cartItems + ]; + } + + return []; + } + + /** + * Create order cartitems for order bundle + * + * @return array + */ + final public function getOrderCartItems(): array + { + $cartItems = []; + + foreach ($this->order->products as $positionId => $product) { + assert($product instanceof OrderProduct); + + $cartItems['items'] = [ + 'positionId' => $positionId, + 'name' => $product->name, + 'quantity' => [ + 'value' => $product->quantity, + 'measure' => '' + ], + 'itemCode' => $product->variant_id ?? $product->product_id, + 'itemPrice' => $product->pricePostTaxes()->float, + ]; + } + + return $cartItems; + } + + /** + * Y.K. has processed the payment and redirected the user back. + * + * @param PaymentResult $result + * + * @return PaymentResult + */ + final public function complete(PaymentResult $result): PaymentResult + { + $this->setOrder($result->order); + + $gateway = $this->getGateway(); + + try { + /** + * It will be similar to calling methods `completeAuthorize()` and `completePurchase()` + */ + $response = $gateway->orderStatus( + [ + 'orderId' => $result->order->payment_gateway_id, // gateway order number + 'language' => 'ru' + ] + )->send(); + } catch (Throwable $e) { + return $result->fail([], $e); + } + + assert($response instanceof AbstractResponse); + + $data = (array)$response->getData(); + + if ( ! $response->isSuccessful()) { + return $result->fail($data, $response); + } + + return $result->success($data, $response); + } + + /** + * Build the Omnipay Gateway for PayPal. + * + * @return \Omnipay\Common\GatewayInterface + */ + final protected function getGateway(): Gateway + { + $gateway = Omnipay::create('Sberbank'); + + $gateway->setUserName(PaymentGatewaySettings::get('username')); + $gateway->setPassword(decrypt(PaymentGatewaySettings::get('password'))); + + if (PaymentGatewaySettings::get('sber_test_mode')) { + $gateway->setTestMode(true); + } + + + return $gateway; + } + + /** + * Return any custom backend settings fields. + * + * These fields will be rendered in the backend + * settings page of your provider. + * + * @return array + */ + final public function settings(): array + { + return [ + 'sber_test_mode' => [ + 'label' => 'wpstudio.sber::lang.settings.sber_test_mode', + 'comment' => 'wpstudio.sber::lang.settings.sber_test_mode_label', + 'span' => 'left', + 'type' => 'switch', + ], + 'username' => [ + 'label' => Lang::get('wpstudio.sber::lang.settings.username'), + 'comment' => Lang::get('wpstudio.sber::lang.settings.username_label'), + 'span' => 'left', + 'type' => 'text', + ], + 'password' => [ + 'label' => Lang::get('wpstudio.sber::lang.settings.password'), + 'comment' => Lang::get('wpstudio.sber::lang.settings.password_label'), + 'span' => 'left', + 'type' => 'text', + ], + 'setPayedVirtualOrderAsComplete' => [ + 'label' => Lang::get('wpstudio.sber::lang.settings.set_payed_virtual_order_as_complete'), + 'span' => 'left', + 'type' => 'checkbox', + ], + ]; + } + + /** + * Setting keys returned from this method are stored encrypted. + * + * Use this to store API tokens and other secret data + * that is needed for this PaymentProvider to work. + * + * @return array + */ + final public function encryptedSettings(): array + { + return ['password']; + } + + /** + * Getting order state id by flag + * + * @param $orderStateFlag + * @return int + */ + final protected function getOrderStateId($orderStateFlag): int + { + $orderStateModel = OrderState::where('flag', $orderStateFlag)->first(); + + return $orderStateModel->id; + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..6607d9a --- /dev/null +++ b/composer.json @@ -0,0 +1,14 @@ +{ + "name": "dimti/oc-sber-plugin", + "description": "Sber payment gateway for offline.mall", + "require": { + "andrewnovikof/omnipay-sberbank": "^3.0" + }, + "authors": [ + { + "name": "WP Studio Team", + "email": "info@wpstudio.ru" + } + ], + "minimum-stability": "dev" +} diff --git a/lang/en/lang.php b/lang/en/lang.php new file mode 100644 index 0000000..078864e --- /dev/null +++ b/lang/en/lang.php @@ -0,0 +1,18 @@ + [ + 'name' => 'Sber for Offline.Mall', + 'description' => 'Adding Sber payment to offline.mall' + ], + 'settings' => [ + 'sber_checkout' => 'Sber', + 'sber_test_mode' => 'Test mode', + 'sber_test_mode_label' => 'Turned on test mode for sber gateway', + 'username' => 'Username', + 'username_label' => 'Sber api username: T****-api', + 'password' => 'Password', + 'password_label' => 'Sber api password', + ], + 'messages' => [ + 'order_number' => 'Order №', + ] +]; diff --git a/lang/ru/lang.php b/lang/ru/lang.php new file mode 100644 index 0000000..1031dba --- /dev/null +++ b/lang/ru/lang.php @@ -0,0 +1,18 @@ + [ + 'name' => 'Sber для Mall', + 'description' => 'Добавляет платежный провайдер Sber в плагин Mall' + ], + 'settings' => [ + 'sber_checkout' => 'Sber', + 'sber_test_mode' => 'Тестовый режим', + 'sber_test_mode_label' => 'Тестовый режим', + 'username' => 'Пользователь', + 'username_label' => 'Пользователь', + 'password' => 'Пароль', + 'password_label' => 'Пароль', + ], + 'messages' => [ + 'order_number' => 'Заказ №', + ] +]; diff --git a/plugin.yaml b/plugin.yaml new file mode 100644 index 0000000..8dc7ca9 --- /dev/null +++ b/plugin.yaml @@ -0,0 +1,6 @@ +plugin: + name: 'wpstudio.sber::lang.plugin.name' + description: 'wpstudio.sber::lang.plugin.description' + author: WP Studio, info@wpstudio.ru + icon: oc-icon-credit-card + homepage: '' diff --git a/updates/version.yaml b/updates/version.yaml new file mode 100644 index 0000000..5a3af98 --- /dev/null +++ b/updates/version.yaml @@ -0,0 +1,2 @@ +1.0.1: + - Initialize plugin.