PluginProbe
PayPlug for WooCommerce (Official) / 2.9.0
PayPlug for WooCommerce (Official) v2.9.0
3.0.0 2.18.0 1.0.17 1.0.18 1.0.19 1.0.20 1.0.21 1.0.22 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.1.0 1.10.0 1.10.1 1.2.1 1.2.10 1.2.11 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 All 101 releases
payplug / src / Controller / ApplePay.php

ApplePay.php in PayPlug for WooCommerce (Official) 2.9.0, at src/Controller/ApplePay.php

514 lines 15.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Payplug\PayplugWoocommerce\Controller;
4
5 use Payplug\Exception\HttpException;
6 use Payplug\PayplugWoocommerce\Gateway\PayplugAddressData;
7 use Payplug\PayplugWoocommerce\PayplugWoocommerceHelper;
8 use Payplug\PayplugWoocommerce\Gateway\PayplugGateway;
9 use Payplug\Resource\Payment as PaymentResource;
10 use function is_cart;
11 use function is_checkout;
12
13 class ApplePay extends PayplugGateway
14 {
15
16 public $domain_name = "";
17
18 protected $cart=false;
19
20 protected $checkout = false;
21
22 protected $carriers = [];
23
24 const ENABLE_ON_TEST_MODE = false;
25
26 public $image = "apple-pay-checkout.svg";
27
28 public function __construct()
29 {
30
31 parent::__construct();
32
33 /** @var \WC_Settings_API override $id */
34 $this->id = 'apple_pay';
35
36 /** @var \WC_Payment_Gateway overwrite for apple pay settings */
37 $this->method_title = __('payplug_apple_pay_title', 'payplug');
38 $this->method_description = "";
39 $this->has_fields = false;
40
41 $this->title = __('payplug_apple_pay_title', 'payplug');
42 $this->description = '<div id="apple-pay-button-wrapper"><apple-pay-button buttonstyle="black" type="pay" locale="'. get_locale() .'"></apple-pay-button></div>';
43 $this->domain_name = $_SERVER['HTTP_HOST'];
44 $this->enabled = "no";
45
46
47 if( $this->checkApplePay() && is_admin()){
48 $this->enabled = "yes";
49
50 }else if( $this->checkApplePay() && $this->checkDeviceComptability() && $this->isSSL() ){
51
52 if (!is_admin() && $this->get_button_checkout()) {
53 $this->enabled = 'yes';
54 }
55
56
57 if (!is_admin() && is_checkout() && !$this->is_checkout_block() && $this->get_button_checkout()) {
58 $this->add_apple_pay_css();
59 add_action('wp_enqueue_scripts', [$this, 'add_apple_pay_js']);
60 }
61
62 if (!is_admin() && $this->get_button_cart()) {
63 $this->enabled = 'yes';
64 $this->add_apple_pay_css();
65 add_action('woocommerce_proceed_to_checkout', [$this, "add_apple_pay_cart_js"], 15);
66
67 }
68 }
69
70 }
71
72 /**
73 * @return bool|void
74 */
75 public function process_admin_options() {
76 $data = $this->get_post_data();
77 if (isset($data['woocommerce_payplug_mode'])) {
78 if ( $this->get_post_data()['woocommerce_payplug_mode'] === '0' ) {
79 $options = get_option( 'woocommerce_payplug_settings', [] );
80 $options['apple_pay'] = 'no';
81 update_option( 'woocommerce_payplug_settings', apply_filters( 'woocommerce_settings_api_sanitized_fields_payplug', $options ) );
82 }
83 }
84 if (isset($data['woocommerce_payplug_apple_pay'])) {
85 if (($data['woocommerce_payplug_apple_pay'] == 1) && (!$this->checkApplePay())) {
86 add_action( 'admin_notices', [$this ,"display_notice"] );
87 }
88 }
89
90 }
91
92 /**
93 *
94 * Check Apple Pay Authorization
95 *
96 * @return bool
97 */
98
99 public function checkApplePay(){
100 $options = PayplugWoocommerceHelper::get_payplug_options();
101
102 //it's disabled
103 if(isset($options['apple_pay']) && $options['apple_pay'] === "no"){
104 return false;
105 }
106
107 //Amount validations
108 if ( is_cart() && !empty( WC()->cart ) ) {
109 $order_amount = (float) WC()->cart->total;
110 if ($order_amount < self::MIN_AMOUNT || $order_amount > self::MAX_AMOUNT) {
111 return false;
112 }
113 }
114
115 //support legacy applepay
116 if( !isset($options['applepay_checkout']) && !isset($options['applepay_cart']) && isset($options['apple_pay']) && $options['apple_pay'] ==="yes"){
117 $this->set_button_checkout(true);
118 }
119
120 if(isset($options['applepay_checkout']) && $options['applepay_checkout'] === "yes"){
121 $this->set_button_checkout(true);
122 }
123
124 if(isset($options['applepay_cart']) && $options['applepay_cart'] === "yes"){
125 $this->set_button_cart(true);
126 }
127
128 if(isset($options['applepay_carriers']) ){
129 $this->set_carriers($options['applepay_carriers']);
130 }
131
132 $account = PayplugWoocommerceHelper::generic_get_account_data_from_options($this->id);
133 //no auth
134 if(!isset($account['payment_methods']['apple_pay']) || !isset($account['payment_methods']['apple_pay']['allowed_domain_names']) ){
135 return false;
136 }
137
138 //$account has permissions to use apple_pay
139 $auth = isset($account['payment_methods']['apple_pay']['enabled']) && $account['payment_methods']['apple_pay']['enabled'];
140 $auth_domains = in_array(strtr(get_site_url(), array("http://" => "", "https://" => "")), $account['payment_methods']['apple_pay']['allowed_domain_names']);
141
142 //lost auth
143 if(!($auth && $auth_domains)){
144 return false;
145 }
146
147 return true;
148 }
149
150 public function payment_fields()
151 {
152 $description = $this->get_description();
153
154 if (!empty($description)) {
155 echo wpautop(wptexturize($description));
156 }
157 }
158
159 /**
160 * extend the woocommmerce get description to include personalized html
161 *
162 * @return mixed|string|null
163 */
164 public function get_description()
165 {
166 return apply_filters('woocommerce_gateway_description', $this->description, $this->id);
167 }
168 public function add_apple_pay_cart_js(){
169 wp_enqueue_script( 'apple-pay-sdk', 'https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js', array(), false, true );
170 wp_enqueue_script('payplug-apple-pay-cart', PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/js/payplug-apple-pay-cart.js', ['jquery', 'apple-pay-sdk'], PAYPLUG_GATEWAY_VERSION, true);
171 wp_localize_script( 'payplug-apple-pay-cart', 'apple_pay_params',
172 array(
173 'ajax_url_applepay_get_shippings' => \WC_AJAX::get_endpoint('applepay_get_shippings'),
174 'ajax_url_place_order_with_dummy_data' => \WC_AJAX::get_endpoint('place_order_with_dummy_data'),
175 'ajax_url_update_applepay_order' => \WC_AJAX::get_endpoint('update_applepay_order'),
176 'ajax_url_update_applepay_payment' => \WC_AJAX::get_endpoint('update_applepay_payment'),
177 'ajax_url_applepay_get_order_totals' => \WC_AJAX::get_endpoint('applepay_get_order_totals'),
178 'ajax_url_applepay_cancel_order' => \WC_AJAX::get_endpoint('applepay_cancel_order'),
179 'is_cart' => is_cart(),
180 'countryCode' => WC()->customer->get_billing_country(),
181 'currencyCode' => get_woocommerce_currency(),
182 'apple_pay_domain' => $_SERVER['HTTP_HOST']
183 )
184 );
185
186 if($this->checkButtonVisibility()){
187 echo $this->get_description();
188 }
189 }
190
191 /**
192 * Check if the shipping address is a carrier
193 *
194 * @return bool
195 */
196 private function checkButtonVisibility(){
197 $apple_carriers = $this->get_carriers();
198 $allowed = false;
199 $post = $this->get_post_data();
200 $chosen_method = isset($post["shipping_method"][0]) ? $post["shipping_method"][0] : null;
201 if(!$chosen_method){
202 $chosen_method = WC()->session->chosen_shipping_methods[0];
203 }
204
205 foreach ( WC()->shipping()->get_packages() as $i => $package ) {
206 $available_rates = !empty($package['rates']) ? $package['rates'] : [];
207 if(!empty($available_rates)){
208 foreach($available_rates as $method){
209 if(in_array($method->get_method_id(), $apple_carriers) ){
210 if($chosen_method === $method->get_method_id() . ":" . $method->get_instance_id()){
211 $allowed = true;
212 }
213 }
214 }
215 }
216 }
217
218 return $allowed;
219 }
220
221
222 /**
223 * Display unauthorized error
224 *
225 * @return void
226 */
227
228 public static function display_notice() {
229 ?>
230 <div class="notice notice-error is-dismissible">
231 <p><?php echo __( 'payplug_apple_pay_unauthorized_error', 'payplug' ); ?></p>
232 </div>
233 <?php
234 }
235
236 /**
237 * Check User-Agent to make sure it is on Mac OS
238 *
239 * @return bool
240 */
241 public function checkDeviceComptability(){
242 $user_agent = isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER['HTTP_USER_AGENT'] : '';
243
244 // Check if the Browser is Safari
245 if (stripos( $user_agent, 'Chrome') !== false) {
246 return false;
247
248 } elseif (stripos( $user_agent, 'Safari') !== false) {
249 // Check if the OS is Mac
250 if(!preg_match('/macintosh|mac os x/i', $user_agent)) {
251 return false;
252 }
253 }
254 return true;
255 }
256
257 /**
258 * Check if SSL
259 *
260 */
261 public function isSSL()
262 {
263 if( !empty( $_SERVER['HTTPS'] ) ) {
264 if ( 'on' == strtolower($_SERVER['HTTPS']) )
265 return true;
266 } elseif ( isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
267 return true;
268 }
269
270 if( !empty( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https' )
271 return true;
272
273 return false;
274 }
275
276 /**
277 * Add CSS
278 *
279 */
280 public function add_apple_pay_css() {
281 wp_enqueue_style('payplug-apple-pay', PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/css/payplug-apple-pay.css', [], PAYPLUG_GATEWAY_VERSION);
282 }
283
284 /**
285 * Add JS
286 *
287 */
288 public function add_apple_pay_js() {
289 wp_enqueue_script( 'apple-pay-sdk', 'https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js', array(), false, true );
290 wp_enqueue_script('payplug-apple-pay', PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/js/payplug-apple-pay.js',
291 [
292 'jquery',
293 'apple-pay-sdk'
294 ], PAYPLUG_GATEWAY_VERSION, true);
295 wp_localize_script( 'payplug-apple-pay', 'apple_pay_params',
296 array(
297 'ajax_url_payplug_create_order' => \WC_AJAX::get_endpoint('payplug_create_order'),
298 'ajax_url_applepay_update_payment' => \WC_AJAX::get_endpoint('applepay_update_payment'),
299 'ajax_url_applepay_get_order_totals' => \WC_AJAX::get_endpoint('applepay_get_order_totals'),
300 'countryCode' => WC()->customer->get_billing_country(),
301 'currencyCode' => get_woocommerce_currency(),
302 'total' => WC()->cart->total,
303 'apple_pay_domain' => $this->domain_name
304 )
305 );
306 }
307
308 /**
309 * Get payment icons.
310 *
311 * @return string
312 */
313 public function get_icon()
314 {
315 $available_img = 'apple-pay-checkout.svg';
316 $icons = apply_filters('payplug_payment_icons', [
317 'payplug' => sprintf('<img src="%s" alt="Apple Pay" class="payplug-payment-icon" />', esc_url(PAYPLUG_GATEWAY_PLUGIN_URL . '/assets/images/checkout/' . $available_img)),
318 ]);
319 $icons_str = '';
320 foreach ($icons as $icon) {
321 $icons_str .= $icon;
322 }
323 return $icons_str;
324 }
325
326 /**
327 * if payment was generated by an intend, we shouldn't generate another one and try to pay it, this would generate duplications
328 * @param $order
329 * @return array|null
330 * @throws \Exception
331 */
332 private function process_standard_intent_payment($order){
333
334 if ( !is_wc_endpoint_url('order-pay') &&
335 $this->is_checkout_block() &&
336 !empty($order->get_transaction_id()) ) {
337
338 $order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
339
340 try {
341 $payment = $this->api->payment_retrieve($order->get_transaction_id());
342 if (ob_get_length() > 0) {
343 ob_clean();
344 }
345
346 $return_url = esc_url_raw($order->get_checkout_order_received_url());
347
348 wp_send_json_success(
349 array(
350 'payment_id' => $payment->id,
351 'result' => 'success',
352 'redirect' => !empty($payment->hosted_payment->payment_url) ? $payment->hosted_payment->payment_url : $return_url,
353 'cancel' => !empty($payment->hosted_payment->cancel_url) ? $payment->hosted_payment->cancel_url : null
354 )
355 );
356
357 return array("stt" => "OK");
358
359 } catch (HttpException $e) {
360 PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
361 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
362 } catch (\Exception $e) {
363 PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, $e->getMessage()), 'error');
364 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
365 }
366 }
367
368 return null;
369 }
370
371
372 /**
373 * @param \WC_Order $order
374 * @param int $amount
375 * @param int $customer_id
376 *
377 * @return array
378 * @throws \Exception
379 */
380 public function process_standard_payment($order, $amount, $customer_id, $workflow = 'checkout')
381 {
382
383 $intent = $this->process_standard_intent_payment($order);
384 if( !empty($intent) ){
385 return $intent;
386 }
387
388 $order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
389 try {
390 $address_data = PayplugAddressData::from_order($order);
391
392 $return_url = esc_url_raw($order->get_checkout_order_received_url());
393
394 if (!(substr( $return_url, 0, 4 ) === "http")) {
395 $return_url = get_site_url().$return_url;
396 }
397
398 // delivery_type must be removed in Apple Pay
399 $billing = $address_data->get_billing();
400 unset($billing['delivery_type']);
401 $shipping = $address_data->get_shipping();
402 unset($shipping['delivery_type']);
403
404 $payment_data = [
405 'amount' => $amount,
406 'currency' => get_woocommerce_currency(),
407 'payment_method' => $this->id,
408 'payment_context' => array(
409 'apple_pay' => array(
410 'domain_name' => $this->domain_name,
411 'application_data' => base64_encode(json_encode(array(
412 'apple_pay_domain' => $this->domain_name,
413 )))
414 )
415 ),
416 'billing' => $billing,
417 'shipping' => $shipping,
418 'hosted_payment' => [
419 'return_url' => $return_url,
420 'cancel_url' => esc_url_raw($order->get_cancel_order_url_raw()),
421 ],
422 'notification_url' => esc_url_raw(WC()->api_request_url('PayplugGateway')),
423 'metadata' => [
424 'order_id' => $order_id,
425 'customer_id' => ((int) $customer_id > 0) ? $customer_id : 'guest',
426 'domain' => $this->domain_name,
427 'applepay_workflow' => $workflow
428 ]
429 ];
430
431 /**
432 * Filter the payment data before it's used
433 *
434 * @param array $payment_data
435 * @param int $order_id
436 * @param array $customer_details
437 * @param PayplugAddressData $address_data
438 */
439 $payment_data = apply_filters('payplug_gateway_payment_data', $payment_data, $order_id, [], $address_data);
440 $payment = $this->api->payment_create($payment_data);
441
442 // Save transaction id for the order
443 PayplugWoocommerceHelper::is_pre_30()
444 ? update_post_meta($order_id, '_transaction_id', $payment->id)
445 : $order->set_transaction_id($payment->id);
446
447 if (is_callable([$order, 'save'])) {
448 $order->save();
449 }
450
451 /**
452 * Fires once a payment has been created.
453 *
454 * @param int $order_id Order ID
455 * @param PaymentResource $payment Payment resource
456 */
457 \do_action('payplug_gateway_payment_created', $order_id, $payment);
458
459 $metadata = PayplugWoocommerceHelper::extract_transaction_metadata($payment);
460 PayplugWoocommerceHelper::save_transaction_metadata($order, $metadata);
461
462 PayplugGateway::log(sprintf('Payment creation complete for order #%s', $order_id));
463
464 return [
465 'result' => 'success',
466 'merchant_session' => $payment->payment_method["merchant_session"],
467 'payment_id' => $payment->id,
468 'cancel_url' => esc_url_raw($order->get_cancel_order_url_raw()),
469 'return_url' => $return_url,
470 ];
471
472 } catch (HttpException $e) {
473 PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
474 if($workflow === "cart"){
475 wp_send_json_error(["code" => $e->getCode(), "msg" => __('Payment processing failed. Please retry.', 'payplug'), "order_id" => $order_id ]);
476 }
477 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
478 } catch (\Exception $e) {
479 PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, $e->getMessage()), 'error');
480 if($workflow === "cart"){
481 wp_send_json_error(["code" => $e->getCode(), "msg" => __('Payment processing failed. Please retry.', 'payplug'), "order_id" => $order_id ]);
482 }
483 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
484 }
485
486 }
487
488 private function set_button_checkout($status){
489 $this->checkout = $status;
490 }
491
492 private function set_button_cart($status){
493 $this->cart = $status;
494 }
495
496 private function get_button_checkout(){
497 return $this->checkout;
498 }
499
500 private function get_button_cart(){
501 return $this->cart;
502 }
503
504 private function get_carriers(){
505 return $this->carriers;
506 }
507
508 private function set_carriers($carriers){
509 $this->carriers = $carriers;
510 }
511
512
513 }
514