PluginProbe
seQura / 4.0.0
seQura v4.0.0
4.3.4 4.3.3 4.3.2 4.3.1 trunk 2.0.0 2.0.10 2.0.11 2.0.12 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 3.0.0 3.0.2 3.0.5 3.0.6 3.0.7 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 4.0.0 All 30 releases
sequra / src / Services / Payment / class-payment-method-service.php

class-payment-method-service.php in seQura 4.0.0, at src/Services/Payment/class-payment-method-service.php

256 lines 7.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Payment method service
4 *
5 * @package SeQura/WC
6 * @subpackage SeQura/WC/Services
7 */
8
9 namespace SeQura\WC\Services\Payment;
10
11 use SeQura\Core\BusinessLogic\CheckoutAPI\CheckoutAPI;
12 use SeQura\Core\BusinessLogic\CheckoutAPI\Solicitation\Response\SolicitationResponse;
13 use SeQura\Core\BusinessLogic\Domain\Multistore\StoreContext;
14 use SeQura\Core\BusinessLogic\Domain\Order\Models\SeQuraForm;
15 use SeQura\Core\Infrastructure\Logger\LogContextData;
16 use SeQura\WC\Core\Extension\BusinessLogic\Domain\Order\Builders\Interface_Create_Order_Request_Builder;
17 use SeQura\WC\Dto\Payment_Method_Data;
18 use SeQura\WC\Dto\Payment_Method_Option;
19 use SeQura\WC\Services\Log\Interface_Logger_Service;
20 use SeQura\WC\Services\Order\Interface_Current_Order_Provider;
21 use SeQura\WC\Services\Order\Interface_Order_Service;
22 use Throwable;
23 use WC_Order;
24
25 /**
26 * Handle use cases related to payment methods
27 */
28 class Payment_Method_Service implements Interface_Payment_Method_Service {
29
30 /**
31 * Payment methods
32 *
33 * @var Payment_Method_Option[]
34 */
35 private $payment_methods;
36
37 /**
38 * Create order request builder
39 *
40 * @var Interface_Create_Order_Request_Builder
41 */
42 private $create_order_request_builder;
43
44 /**
45 * Order service
46 *
47 * @var Interface_Order_Service
48 */
49 private $order_service;
50
51 /**
52 * Logger
53 *
54 * @var Interface_Logger_Service
55 */
56 private $logger;
57
58 /**
59 * Current order provider
60 *
61 * @var Interface_Current_Order_Provider
62 */
63 private $current_order_provider;
64
65 /**
66 * Store context
67 *
68 * @var StoreContext
69 */
70 private $store_context;
71
72 /**
73 * Constructor
74 */
75 public function __construct(
76 Interface_Create_Order_Request_Builder $create_order_request_builder,
77 Interface_Order_Service $order_service,
78 Interface_Logger_Service $logger,
79 Interface_Current_Order_Provider $current_order_provider,
80 StoreContext $store_context
81 ) {
82 $this->create_order_request_builder = $create_order_request_builder;
83 $this->order_service = $order_service;
84 $this->logger = $logger;
85 $this->current_order_provider = $current_order_provider;
86 $this->store_context = $store_context;
87 }
88
89 /**
90 * Request solicitation
91 */
92 private function request_solicitation( ?WC_Order $order = null ): ?SolicitationResponse {
93 try {
94 $this->current_order_provider->set( $order );
95
96 if ( ! $this->create_order_request_builder->is_allowed() ) {
97 $ctx = $order ? array( new LogContextData( 'order_id', $order->get_id() ) ) : array();
98 $this->logger->log_debug( 'Order is not allowed for solicitation', __FUNCTION__, __CLASS__, $ctx );
99 return null;
100 }
101
102 $response = CheckoutAPI::get()->solicitation( $this->store_context->getStoreId() )->solicitFor( $this->create_order_request_builder );
103
104 if ( ! $response->isSuccessful() ) {
105 $ctx = $order ? array( new LogContextData( 'order_id', $order->get_id() ) ) : array();
106 $ctx[] = new LogContextData( 'response', $response->toArray() );
107 $this->logger->log_error( 'Solicitation response is not successful', __FUNCTION__, __CLASS__, $ctx );
108 }
109
110 return $response instanceof SolicitationResponse ? $response : null;
111 } catch ( Throwable $e ) {
112 $this->logger->log_throwable( $e, __FUNCTION__, __CLASS__ );
113 return null;
114 }
115 }
116
117 /**
118 * Get identification form
119 */
120 public function get_identification_form( WC_Order $order ): ?SeQuraForm {
121
122 $response = $this->request_solicitation( $order );
123
124 if ( ! $response || ! $response->isSuccessful() ) {
125 return null;
126 }
127
128 /**
129 * Filter the options to be sent to seQura if needed
130 *
131 * @since 2.0.0
132 * */
133 $opts = \apply_filters(
134 'wc_sequra_pumbaa_options',
135 array(
136 'product' => $this->order_service->get_product( $order ),
137 'campaign' => $this->order_service->get_campaign( $order ),
138 ),
139 $order,
140 array()
141 );
142
143 try {
144 $cart_info = $this->order_service->get_cart_info( $order );
145
146 if ( ! $cart_info ) {
147 $this->logger->log_error( 'Cart info is null', __FUNCTION__, __CLASS__, array( new LogContextData( 'order_id', $order->get_id() ) ) );
148 return null;
149 }
150
151 $response = CheckoutAPI::get()
152 ->solicitation( $this->store_context->getStoreId() )
153 ->getIdentificationForm(
154 $cart_info->ref,
155 isset( $opts['product'] ) && '' !== $opts['product'] ? $opts['product'] : null,
156 isset( $opts['campaign'] ) && '' !== $opts['campaign'] ? $opts['campaign'] : null
157 );
158
159 if ( ! $response ) {
160 $this->logger->log_error( 'Identification form response is null', __FUNCTION__, __CLASS__, array( new LogContextData( 'order_id', $order->get_id() ) ) );
161 return null;
162 }
163
164 if ( ! $response->isSuccessful() ) {
165 $this->logger->log_error(
166 'Identification form response is not successful',
167 __FUNCTION__,
168 __CLASS__,
169 array(
170 new LogContextData( 'response', $response->toArray() ),
171 new LogContextData( 'order_id', $order->get_id() ),
172 )
173 );
174 return null;
175 }
176
177 return $response->getIdentificationForm();
178 } catch ( Throwable $e ) {
179 $this->logger->log_throwable( $e, __FUNCTION__, __CLASS__ );
180 return null;
181 }
182 }
183
184 /**
185 * Get payment methods
186 *
187 * @return Payment_Method_Option[]
188 */
189 public function get_payment_methods( ?WC_Order $order = null ) {
190 if ( null !== $this->payment_methods ) {
191 return $this->payment_methods;
192 }
193 // TODO: Implement a cache system to avoid multiple requests with the same payload.
194 $response = $this->request_solicitation( $order );
195
196 if ( ! $response || ! $response->isSuccessful() ) {
197 return array();
198 }
199 $this->payment_methods = array();
200 foreach ( (array) ( $response->toArray()['availablePaymentMethods'] ?? array() ) as $raw ) {
201 $this->payment_methods[] = Payment_Method_Option::from_array( $raw );
202 }
203 return $this->payment_methods;
204 }
205
206 /**
207 * Check if the payment method data matches a valid payment method.
208 */
209 public function is_payment_method_data_valid( ?Payment_Method_Data $data ): bool {
210 if ( null !== $data ) {
211 foreach ( $this->get_payment_methods() as $pm ) {
212 if ( $pm->match( $data ) ) {
213 return true;
214 }
215 }
216 }
217 return false;
218 }
219
220 /**
221 * Check if the current page is the order pay page
222 */
223 public function is_order_pay_page(): bool {
224 return ( (int) strval( \get_query_var( 'order-pay' ) ) ) > 0;
225 }
226
227 /**
228 * Check if the current page is the checkout page
229 */
230 public function is_checkout(): bool {
231 /**
232 * Check if current page is checkout
233 *
234 * @since 3.0.0
235 */
236 return (bool) \apply_filters( 'sequra_is_checkout', \is_checkout() || $this->is_order_pay_page() || $this->is_store_api_request() );
237 }
238
239 /**
240 * Returns true if the request is a store REST API request.
241 *
242 * @return bool
243 */
244 private function is_store_api_request() {
245 // @phpstan-ignore-next-line
246 if ( method_exists( 'WooCommerce', 'is_store_api_request' ) ) {
247 return WC()->is_store_api_request();
248 }
249 if ( empty( $_SERVER['REQUEST_URI'] ) ) {
250 return false;
251 }
252 // phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
253 return false !== strpos( $_SERVER['REQUEST_URI'], trailingslashit( rest_get_url_prefix() ) . 'wc/store/' );
254 }
255 }
256