You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

284 lines
7.6 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. <?php namespace Wpstudio\Sber\Classes;
  2. use OFFLINE\Mall\Classes\Payments\PaymentProvider;
  3. use OFFLINE\Mall\Classes\Payments\PaymentResult;
  4. use OFFLINE\Mall\Models\OrderProduct;
  5. use OFFLINE\Mall\Models\PaymentGatewaySettings;
  6. use OFFLINE\Mall\Models\OrderState;
  7. use OFFLINE\Mall\Models\Order;
  8. use Omnipay\Omnipay;
  9. use Omnipay\Sberbank\Gateway;
  10. use Omnipay\Sberbank\Message\AbstractRequest;
  11. use Omnipay\Sberbank\Message\AbstractResponse;
  12. use Omnipay\Sberbank\Message\AuthorizeRequest;
  13. use Omnipay\Sberbank\Message\AuthorizeResponse;
  14. use Throwable;
  15. use Session;
  16. use Lang;
  17. class SberCheckout extends PaymentProvider
  18. {
  19. /**
  20. * The order that is being paid.
  21. *
  22. * @var Order
  23. */
  24. public $order;
  25. /**
  26. * Data that is needed for the payment.
  27. * Card numbers, tokens, etc.
  28. *
  29. * @var array
  30. */
  31. public $data;
  32. /**
  33. * Return the display name of your payment provider.
  34. *
  35. * @return string
  36. */
  37. final public function name(): string
  38. {
  39. return Lang::get('wpstudio.sber::lang.settings.sber_checkout');
  40. }
  41. /**
  42. * Return a unique identifier for this payment provider.
  43. *
  44. * @return string
  45. */
  46. final public function identifier(): string
  47. {
  48. return 'sber';
  49. }
  50. /**
  51. * Validate the given input data for this payment.
  52. *
  53. * @return bool
  54. * @throws \October\Rain\Exception\ValidationException
  55. */
  56. final public function validate(): bool
  57. {
  58. return true;
  59. }
  60. /**
  61. * Process the payment.
  62. *
  63. * @param PaymentResult $result
  64. *
  65. * @return PaymentResult
  66. */
  67. final public function process(PaymentResult $result): PaymentResult
  68. {
  69. $gateway = $this->getGateway();
  70. try {
  71. $request = $gateway->authorize([
  72. 'orderNumber' => $this->order->id,
  73. 'amount' => $this->order->total_in_currency,
  74. 'returnUrl' => $this->returnUrl(),
  75. 'failUrl' => $this->cancelUrl(),
  76. 'description' => Lang::get('wpstudio.sber::lang.messages.order_number').$this->order->order_number,
  77. ]);
  78. assert($request instanceof AuthorizeRequest);
  79. $request->setOrderBundle($this->getOrderBundle());
  80. $response = $request->send();
  81. } catch (Throwable $e) {
  82. return $result->fail([], $e);
  83. }
  84. assert($response instanceof AuthorizeResponse);
  85. Session::put('mall.payment.callback', self::class);
  86. $this->setOrder($result->order);
  87. $result->order->payment_transaction_id = $response->getOrderId();
  88. $result->order->save();
  89. return $result->redirect($response->getRedirectResponse()->getTargetUrl());
  90. }
  91. /**
  92. * Gerenate sberbank orderBundle
  93. * @see https://securepayments.sberbank.ru/wiki/doku.php/integration:api:rest:requests:registerpreauth_cart#orderbundle
  94. *
  95. * @return array
  96. *
  97. */
  98. final public function getOrderBundle(): array
  99. {
  100. $orderCreationDateFormatted = $this->order->created_at->format('Y-m-dTH:m:s');
  101. $cartItems = $this->getOrderCartItems();
  102. if ($cartItems) {
  103. return [
  104. 'orderCreationDate' => $orderCreationDateFormatted ?? '',
  105. 'cartItems' => $cartItems
  106. ];
  107. }
  108. return [];
  109. }
  110. /**
  111. * Create order cartitems for order bundle
  112. *
  113. * @return array
  114. */
  115. final public function getOrderCartItems(): array
  116. {
  117. $cartItems = [];
  118. $items = [];
  119. foreach ($this->order->products as $positionId => $product) {
  120. assert($product instanceof OrderProduct);
  121. $items[] = [
  122. 'positionId' => $positionId + 1,
  123. 'name' => $product->name,
  124. 'quantity' => [
  125. 'value' => $product->quantity,
  126. 'measure' => 'шт.'
  127. ],
  128. 'itemCode' => $product->variant_id ?? $product->product_id,
  129. 'itemPrice' => $product->pricePostTaxes()->integer,
  130. ];
  131. }
  132. $cartItems['items'] = $items;
  133. return $cartItems;
  134. }
  135. /**
  136. * Y.K. has processed the payment and redirected the user back.
  137. *
  138. * @param PaymentResult $result
  139. *
  140. * @return PaymentResult
  141. */
  142. final public function complete(PaymentResult $result): PaymentResult
  143. {
  144. $this->setOrder($result->order);
  145. $gateway = $this->getGateway();
  146. try {
  147. /**
  148. * It will be similar to calling methods `completeAuthorize()` and `completePurchase()`
  149. */
  150. $response = $gateway->orderStatus(
  151. [
  152. 'orderId' => $result->order->payment_transaction_id, // gateway order number
  153. 'language' => 'ru'
  154. ]
  155. )->send();
  156. } catch (Throwable $e) {
  157. return $result->fail([], $e);
  158. }
  159. assert($response instanceof AbstractResponse);
  160. $data = (array)$response->getData();
  161. if ( ! $response->isSuccessful()) {
  162. return $result->fail($data, $response);
  163. }
  164. return $result->success($data, $response);
  165. }
  166. /**
  167. * Build the Omnipay Gateway for PayPal.
  168. *
  169. * @return \Omnipay\Common\GatewayInterface
  170. */
  171. final protected function getGateway(): Gateway
  172. {
  173. $gateway = Omnipay::create('Sberbank');
  174. $gateway->setUserName(PaymentGatewaySettings::get('username'));
  175. $gateway->setPassword(decrypt(PaymentGatewaySettings::get('password')));
  176. if (PaymentGatewaySettings::get('sber_test_mode')) {
  177. $gateway->setTestMode(true);
  178. }
  179. return $gateway;
  180. }
  181. /**
  182. * Return any custom backend settings fields.
  183. *
  184. * These fields will be rendered in the backend
  185. * settings page of your provider.
  186. *
  187. * @return array
  188. */
  189. final public function settings(): array
  190. {
  191. return [
  192. 'sber_test_mode' => [
  193. 'label' => 'wpstudio.sber::lang.settings.sber_test_mode',
  194. 'comment' => 'wpstudio.sber::lang.settings.sber_test_mode_label',
  195. 'span' => 'left',
  196. 'type' => 'switch',
  197. ],
  198. 'username' => [
  199. 'label' => Lang::get('wpstudio.sber::lang.settings.username'),
  200. 'comment' => Lang::get('wpstudio.sber::lang.settings.username_label'),
  201. 'span' => 'left',
  202. 'type' => 'text',
  203. ],
  204. 'password' => [
  205. 'label' => Lang::get('wpstudio.sber::lang.settings.password'),
  206. 'comment' => Lang::get('wpstudio.sber::lang.settings.password_label'),
  207. 'span' => 'left',
  208. 'type' => 'text',
  209. ],
  210. 'setPayedVirtualOrderAsComplete' => [
  211. 'label' => Lang::get('wpstudio.sber::lang.settings.set_payed_virtual_order_as_complete'),
  212. 'span' => 'left',
  213. 'type' => 'checkbox',
  214. ],
  215. ];
  216. }
  217. /**
  218. * Setting keys returned from this method are stored encrypted.
  219. *
  220. * Use this to store API tokens and other secret data
  221. * that is needed for this PaymentProvider to work.
  222. *
  223. * @return array
  224. */
  225. final public function encryptedSettings(): array
  226. {
  227. return ['password'];
  228. }
  229. /**
  230. * Getting order state id by flag
  231. *
  232. * @param $orderStateFlag
  233. * @return int
  234. */
  235. final protected function getOrderStateId($orderStateFlag): int
  236. {
  237. $orderStateModel = OrderState::where('flag', $orderStateFlag)->first();
  238. return $orderStateModel->id;
  239. }
  240. }