dimti
4 years ago
commit
5534bcf2f4
9 changed files with 386 additions and 0 deletions
-
3.gitignore
-
26Plugin.php
-
16classes/DefaultMoneyRepair.php
-
283classes/SberCheckout.php
-
14composer.json
-
18lang/en/lang.php
-
18lang/ru/lang.php
-
6plugin.yaml
-
2updates/version.yaml
@ -0,0 +1,3 @@ |
|||||
|
.idea |
||||
|
/vendor/ |
||||
|
/composer.lock |
@ -0,0 +1,26 @@ |
|||||
|
<?php namespace Wpstudio\Sber; |
||||
|
|
||||
|
use Wpstudio\Sber\Classes\DefaultMoneyRepair; |
||||
|
use OFFLINE\Mall\Classes\Payments\PaymentGateway; |
||||
|
use OFFLINE\Mall\Classes\Utils\Money; |
||||
|
use System\Classes\PluginBase; |
||||
|
use Wpstudio\Sber\Classes\SberCheckout; |
||||
|
|
||||
|
class Plugin extends PluginBase |
||||
|
{ |
||||
|
/** |
||||
|
* @var array Plugin dependencies |
||||
|
*/ |
||||
|
public $require = ['Offline.Mall']; |
||||
|
|
||||
|
final public function boot(): void |
||||
|
{ |
||||
|
$gateway = $this->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(); |
||||
|
}); |
||||
|
} |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
<?php namespace Wpstudio\Sber\Classes; |
||||
|
|
||||
|
use OFFLINE\Mall\Classes\Utils\DefaultMoney; |
||||
|
|
||||
|
/*** |
||||
|
* Helper class to solve this problem https://github.com/OFFLINE-GmbH/oc-mall-plugin/issues/258 |
||||
|
* paypal error after redirect to site |
||||
|
* After payment via PayPal upon returning to the site, we get an error Call to a member function getCurrent() on null |
||||
|
*/ |
||||
|
class DefaultMoneyRepair extends DefaultMoney |
||||
|
{ |
||||
|
final protected function render($contents, array $vars): string |
||||
|
{ |
||||
|
return number_format($vars['price'],$vars['currency']->decimals, ',', ' ').' '.$vars['currency']->symbol; |
||||
|
} |
||||
|
} |
@ -0,0 +1,283 @@ |
|||||
|
<?php namespace Wpstudio\Sber\Classes; |
||||
|
|
||||
|
use OFFLINE\Mall\Classes\Payments\PaymentProvider; |
||||
|
use OFFLINE\Mall\Classes\Payments\PaymentResult; |
||||
|
use OFFLINE\Mall\Models\OrderProduct; |
||||
|
use OFFLINE\Mall\Models\PaymentGatewaySettings; |
||||
|
use OFFLINE\Mall\Models\OrderState; |
||||
|
use OFFLINE\Mall\Models\Order; |
||||
|
use Omnipay\Omnipay; |
||||
|
use Omnipay\Sberbank\Gateway; |
||||
|
use Omnipay\Sberbank\Message\AbstractRequest; |
||||
|
use Omnipay\Sberbank\Message\AbstractResponse; |
||||
|
use Omnipay\Sberbank\Message\AuthorizeRequest; |
||||
|
use Omnipay\Sberbank\Message\AuthorizeResponse; |
||||
|
use Throwable; |
||||
|
use Session; |
||||
|
use Lang; |
||||
|
|
||||
|
|
||||
|
class SberCheckout extends PaymentProvider |
||||
|
{ |
||||
|
/** |
||||
|
* The order that is being paid. |
||||
|
* |
||||
|
* @var Order |
||||
|
*/ |
||||
|
public $order; |
||||
|
/** |
||||
|
* Data that is needed for the payment. |
||||
|
* Card numbers, tokens, etc. |
||||
|
* |
||||
|
* @var array |
||||
|
*/ |
||||
|
public $data; |
||||
|
|
||||
|
/** |
||||
|
* Return the display name of your payment provider. |
||||
|
* |
||||
|
* @return string |
||||
|
*/ |
||||
|
final public function name(): string |
||||
|
{ |
||||
|
return Lang::get('wpstudio.sber::lang.settings.sber_checkout'); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Return a unique identifier for this payment provider. |
||||
|
* |
||||
|
* @return string |
||||
|
*/ |
||||
|
final public function identifier(): string |
||||
|
{ |
||||
|
return 'sber'; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Validate the given input data for this payment. |
||||
|
* |
||||
|
* @return bool |
||||
|
* @throws \October\Rain\Exception\ValidationException |
||||
|
*/ |
||||
|
final public function validate(): bool |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Process the payment. |
||||
|
* |
||||
|
* @param PaymentResult $result |
||||
|
* |
||||
|
* @return PaymentResult |
||||
|
*/ |
||||
|
final public function process(PaymentResult $result): PaymentResult |
||||
|
{ |
||||
|
$gateway = $this->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; |
||||
|
} |
||||
|
} |
@ -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" |
||||
|
} |
@ -0,0 +1,18 @@ |
|||||
|
<?php return [ |
||||
|
'plugin' => [ |
||||
|
'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 №', |
||||
|
] |
||||
|
]; |
@ -0,0 +1,18 @@ |
|||||
|
<?php return [ |
||||
|
'plugin' => [ |
||||
|
'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' => 'Заказ №', |
||||
|
] |
||||
|
]; |
@ -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: '' |
@ -0,0 +1,2 @@ |
|||||
|
1.0.1: |
||||
|
- Initialize plugin. |
Write
Preview
Loading…
Cancel
Save
Reference in new issue