PluginProbe
seQura / 4.3.0
seQura v4.3.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.3.0, at src/Services/Payment/class-payment-method-service.php

270 lines 7.6 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\AdminAPI\Response\Response;
12 use SeQura\Core\BusinessLogic\CheckoutAPI\CheckoutAPI;
13 use SeQura\Core\BusinessLogic\CheckoutAPI\Solicitation\Response\IdentificationFormResponse;
14 use SeQura\Core\BusinessLogic\Domain\Multistore\StoreContext;
15 use SeQura\Core\BusinessLogic\Domain\Order\Models\SeQuraForm;
16 use SeQura\Core\Infrastructure\Logger\LogContextData;
17 use SeQura\WC\Core\Extension\BusinessLogic\Domain\Order\Builders\Interface_Create_Order_Request_Builder;
18 use SeQura\WC\Dto\Payment_Method_Data;
19 use SeQura\WC\Dto\Payment_Method_Option;
20 use SeQura\WC\Services\Log\Interface_Logger_Service;
21 use SeQura\WC\Services\Order\Interface_Current_Order_Provider;
22 use SeQura\WC\Services\Order\Interface_Order_Service;
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 ): ?Response {
93 $this->current_order_provider->set( $order );
94
95 if ( ! $this->create_order_request_builder->is_allowed() ) {
96 $ctx = $order ? array( new LogContextData( 'order_id', $order->get_id() ) ) : array();
97 $this->logger->log_debug( 'Order is not allowed for solicitation', __FUNCTION__, __CLASS__, $ctx );
98 return null;
99 }
100
101 /**
102 * Response
103 *
104 * @var Response $response */
105 $response = CheckoutAPI::get()->solicitation( $this->store_context->getStoreId() )->solicitFor( $this->create_order_request_builder );
106 if ( ! $response->isSuccessful() ) {
107 $ctx = $order ? array( new LogContextData( 'order_id', $order->get_id() ) ) : array();
108 $ctx[] = new LogContextData( 'response', $response->toArray() );
109 $this->logger->log_error( 'Solicitation response is not successful', __FUNCTION__, __CLASS__, $ctx );
110 }
111
112 return $response;
113 }
114
115 /**
116 * Get identification form
117 */
118 public function get_identification_form( WC_Order $order ): ?SeQuraForm {
119
120 $response = $this->request_solicitation( $order );
121
122 if ( ! $response || ! $response->isSuccessful() ) {
123 return null;
124 }
125
126 /**
127 * Filter the options to be sent to seQura if needed
128 *
129 * @since 2.0.0
130 * */
131 $opts = \apply_filters(
132 'wc_sequra_pumbaa_options',
133 array(
134 'product' => $this->order_service->get_product( $order ),
135 'campaign' => $this->order_service->get_campaign( $order ),
136 ),
137 $order,
138 array()
139 );
140
141 $cart_info = $this->order_service->get_cart_info( $order );
142
143 if ( ! $cart_info ) {
144 $this->logger->log_error( 'Cart info is null', __FUNCTION__, __CLASS__, array( new LogContextData( 'order_id', $order->get_id() ) ) );
145 return null;
146 }
147
148 /**
149 * Response
150 *
151 * @var IdentificationFormResponse $response */
152 $response = CheckoutAPI::get()
153 ->solicitation( $this->store_context->getStoreId() )
154 ->getIdentificationForm(
155 $cart_info->ref,
156 isset( $opts['product'] ) && '' !== $opts['product'] ? $opts['product'] : null,
157 isset( $opts['campaign'] ) && '' !== $opts['campaign'] ? $opts['campaign'] : null
158 );
159
160 if ( ! $response ) {
161 $this->logger->log_error( 'Identification form response is null', __FUNCTION__, __CLASS__, array( new LogContextData( 'order_id', $order->get_id() ) ) );
162 return null;
163 }
164
165 if ( ! $response->isSuccessful() ) {
166 $this->logger->log_error(
167 'Identification form response is not successful',
168 __FUNCTION__,
169 __CLASS__,
170 array(
171 new LogContextData( 'response', $response->toArray() ),
172 new LogContextData( 'order_id', $order->get_id() ),
173 )
174 );
175 return null;
176 }
177
178 return $response->getIdentificationForm();
179 }
180
181 /**
182 * Get payment methods
183 *
184 * @return Payment_Method_Option[]
185 */
186 public function get_payment_methods( ?WC_Order $order = null ) {
187 if ( null !== $this->payment_methods ) {
188 return $this->payment_methods;
189 }
190 // TODO: Implement a cache system to avoid multiple requests with the same payload.
191 $response = $this->request_solicitation( $order );
192
193 if ( ! $response || ! $response->isSuccessful() ) {
194 return array();
195 }
196 $this->payment_methods = array();
197 foreach ( (array) ( $response->toArray()['availablePaymentMethods'] ?? array() ) as $raw ) {
198 $this->payment_methods[] = Payment_Method_Option::from_array( $raw );
199 }
200 return $this->payment_methods;
201 }
202
203 /**
204 * Check if the payment method data matches a valid payment method.
205 */
206 public function is_payment_method_data_valid( ?Payment_Method_Data $data ): bool {
207 if ( null !== $data ) {
208 foreach ( $this->get_payment_methods() as $pm ) {
209 if ( $pm->match( $data ) ) {
210 return true;
211 }
212 }
213 }
214 return false;
215 }
216
217 /**
218 * Check if the current page is the order pay page
219 */
220 public function is_order_pay_page(): bool {
221 return ( (int) strval( \get_query_var( 'order-pay' ) ) ) > 0;
222 }
223
224 /**
225 * Check if payment method selection is delegated to the seQura checkout form.
226 */
227 public function is_delegated_payment_selection( ?WC_Order $order = null ): bool {
228 /**
229 * Filter to delegate payment method selection to the seQura checkout form.
230 * When truthy, `product=tbs` is passed to the seQura form URL and payment
231 * option selection is handled within the seQura-hosted form.
232 *
233 * @param bool $enabled Whether delegated selection is enabled. Default false.
234 * @param \WC_Order|null $order The current WooCommerce order, or null if not yet created.
235 *
236 * @since 4.3.0
237 */
238 return (bool) \apply_filters( 'sequra_delegate_payment_method_selection', false, $order );
239 }
240
241 /**
242 * Check if the current page is the checkout page
243 */
244 public function is_checkout(): bool {
245 /**
246 * Check if current page is checkout
247 *
248 * @since 3.0.0
249 */
250 return (bool) \apply_filters( 'sequra_is_checkout', \is_checkout() || $this->is_order_pay_page() || $this->is_store_api_request() );
251 }
252
253 /**
254 * Returns true if the request is a store REST API request.
255 *
256 * @return bool
257 */
258 private function is_store_api_request() {
259 // @phpstan-ignore-next-line
260 if ( method_exists( 'WooCommerce', 'is_store_api_request' ) ) {
261 return WC()->is_store_api_request();
262 }
263 if ( empty( $_SERVER['REQUEST_URI'] ) ) {
264 return false;
265 }
266 // phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
267 return false !== strpos( $_SERVER['REQUEST_URI'], trailingslashit( rest_get_url_prefix() ) . 'wc/store/' );
268 }
269 }
270