PluginProbe
Pay with Vipps and MobilePay for WooCommerce / 6.3.0
Pay with Vipps and MobilePay for WooCommerce v6.3.0
6.2.6 6.3.0 6.2.5 6.2.4 6.2.3 6.2.2 6.2.1 6.2.0 6.1.10 6.1.9 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1.0 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 6.0.0 All 189 releases
woo-vipps / payment / Blocks / Payment / Vipps.class.php

Vipps.class.php in Pay with Vipps and MobilePay for WooCommerce 6.3.0, at payment/Blocks/Payment/Vipps.class.php

286 lines 9.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Vipps payment gateway implementation for Gutenberg Blocks
4 *
5 * @package WooCommerce/Blocks
6 * @since 3.0.0
7 */
8
9 namespace Automattic\WooCommerce\Blocks\Payments\Integrations;
10
11 final class Vipps extends AbstractPaymentMethodType {
12 private $localized = 0;
13 private static $store_api_payment_processor = null;
14 protected $name = 'vipps';
15 protected $payment_method_name = 'Vipps';
16
17 /**
18 * Load gateway settings and register the Store API bridge when Blocks initializes this integration.
19 */
20 public function initialize() {
21 $this->settings = get_option( 'woocommerce_vipps_settings', [] );
22 $this->payment_method_name = \WC_Gateway_Vipps::instance()->get_payment_method_name();
23 $this->register_store_api_payment_processor();
24 }
25
26 /**
27 * Register once at priority 10. Setting a result status here lets WooCommerce's
28 * legacy fallback at priority 999 skip calling process_payment a second time.
29 */
30 protected function register_store_api_payment_processor() {
31 if ( self::$store_api_payment_processor ) {
32 return;
33 }
34
35 self::$store_api_payment_processor = $this;
36
37 add_action(
38 'woocommerce_rest_checkout_process_payment_with_context',
39 array( $this, 'process_gutenberg_checkout_payment' ),
40 10,
41 2
42 );
43 }
44
45 // Register this payment method IOK 2020-08-10
46 /**
47 * Register the integration with the Blocks payment-method registry.
48 */
49 public static function register() {
50 add_action(
51 'woocommerce_blocks_payment_method_type_registration',
52 function ( $registry ) {
53 $registry->register( new static() );
54 }
55 );
56 }
57
58 /**
59 * Expose the method to Blocks only when it is enabled in the gateway settings.
60 */
61 public function is_active() {
62 return filter_var( $this->get_setting( 'enabled', false ), FILTER_VALIDATE_BOOLEAN );
63 }
64
65 /**
66 * Load the checkout component after shared gateway code; filemtime invalidates cached JavaScript.
67 */
68 public function get_payment_method_script_handles() {
69
70 $version = filemtime( dirname( __FILE__ ) . '/js/wc-payment-method-vipps.js' );
71 $path = plugins_url( 'js/wc-payment-method-vipps.js', __FILE__ );
72 $handle = 'wc-payment-method-vipps';
73 $dependencies = array( 'wp-hooks', 'wp-element', 'vipps-gw' );
74
75 wp_register_script( $handle, $path, $dependencies, $version, true );
76
77 // Will not use wp_set_script_translations yet, it seems to be not fully compatible with Loco Translate etc. Instead use
78 // old-fashioned localize-script IOK 2020-08-11
79 // wp_set_script_translations( 'wc-payment-method-vipps', 'woo-vipps' );
80 // VippsLocale is localized for vipps-gw instead of this, as it seems it does no longer work to do localize-script at this point.
81 // IOK 2022-12-13
82
83 return [ 'wc-payment-method-vipps' ];
84 }
85
86 /**
87 * Reuse the gateway shortcode so express checkout retains its existing markup and data attributes.
88 */
89 public function get_express_checkout_button () {
90 $context = 'checkout_gutenberg';
91 if (is_cart()) {
92 $context='cart_gutenberg';
93 }
94
95 ob_start();
96 \Vipps::instance()->cart_express_checkout_button_html($context);
97 $button = ob_get_clean();
98 return $button;
99 }
100
101 /**
102 * Check cart support before exposing the merchant's express-checkout setting.
103 */
104 public function show_express_checkout_button() {
105 $gw = \Vipps::instance()->gateway();
106 if ( ! $gw->cart_supports_express_checkout() ) return false;
107 return $gw->show_express_checkout();
108 }
109
110 /**
111 * Process an existing Store API order through the gateway and expose its URL as
112 * widget payment details. The pre-process filter may supply a result instead of
113 * calling the gateway; subsequent filters may adapt the result, URL and reference.
114 * Exceptions are surfaced by WooCommerce as checkout errors. A successful result
115 * means payment initiation succeeded, not that payment has been captured.
116 * The browser suppresses the normal redirect only after accepting the widget handoff.
117 */
118 public function process_gutenberg_checkout_payment( $context, $result ) {
119
120 if ( empty( $context->payment_method ) || 'vipps' !== $context->payment_method ) {
121 return;
122 }
123
124 $order = isset( $context->order ) ? $context->order : null;
125
126 if ( ! $order || ! is_callable( array( $order, 'get_id' ) ) ) {
127 throw new \Exception( $this->get_payment_method_error_message( __( '%s could not process the order.', 'woo-vipps' ) ) );
128 }
129
130 $gateway = $this->get_gutenberg_checkout_gateway();
131
132 if ( ! $gateway ) {
133 throw new \Exception( $this->get_payment_method_error_message( __( '%s is not available.', 'woo-vipps' ) ) );
134 }
135
136 $payment_result = apply_filters(
137 'woo_vipps_gutenberg_checkout_process_payment_result',
138 null,
139 $context,
140 $result,
141 $gateway
142 );
143
144 if ( null === $payment_result ) {
145 if ( ! is_callable( array( $gateway, 'process_payment' ) ) ) {
146 throw new \Exception( $this->get_payment_method_error_message( __( '%s could not start the payment.', 'woo-vipps' ) ) );
147 }
148
149 $payment_result = $gateway->process_payment( $order->get_id() );
150 }
151
152 $payment_result = apply_filters(
153 'woo_vipps_gutenberg_checkout_processed_payment_result',
154 $payment_result,
155 $context,
156 $result,
157 $gateway
158 );
159
160 if ( ! is_array( $payment_result ) ) {
161 throw new \Exception( $this->get_payment_method_error_message( __( '%s returned an invalid payment response.', 'woo-vipps' ) ) );
162 }
163
164 if ( isset( $payment_result['result'] ) && 'success' !== $payment_result['result'] ) {
165 $message = ! empty( $payment_result['message'] )
166 ? $payment_result['message']
167 : $this->get_payment_method_error_message( __( '%s could not start the payment.', 'woo-vipps' ) );
168 throw new \Exception( wp_strip_all_tags( $message ) );
169 }
170
171 $payment_url = apply_filters(
172 'woo_vipps_gutenberg_checkout_payment_url',
173 isset( $payment_result['redirect'] ) ? $payment_result['redirect'] : '',
174 $payment_result,
175 $context,
176 $result,
177 $gateway
178 );
179
180 if ( ! $payment_url ) {
181 throw new \Exception( $this->get_payment_method_error_message( __( '%s did not return a payment URL.', 'woo-vipps' ) ) );
182 }
183
184 $payment_reference = apply_filters(
185 'woo_vipps_gutenberg_checkout_payment_reference',
186 $this->get_gutenberg_checkout_payment_reference( $payment_result, $order ),
187 $payment_result,
188 $context,
189 $result,
190 $gateway
191 );
192
193 $payment_details = array(
194 'vippsPaymentUrl' => esc_url_raw( $payment_url ),
195 'vippsPaymentReference' => $payment_reference ? sanitize_text_field( $payment_reference ) : '',
196 );
197
198 if ( isset( $result->payment_details ) && is_array( $result->payment_details ) ) {
199 $payment_details = array_merge( $result->payment_details, $payment_details );
200 }
201
202 $payment_details = apply_filters(
203 'woo_vipps_gutenberg_checkout_payment_details',
204 $payment_details,
205 $payment_result,
206 $context,
207 $result,
208 $gateway
209 );
210
211 $result->set_status( 'success' );
212 $result->set_payment_details( $payment_details );
213 }
214
215 /**
216 * Resolve the gateway singleton, allowing the main plugin accessor as a compatibility fallback.
217 */
218 protected function get_gutenberg_checkout_gateway() {
219 if ( class_exists( '\WC_Gateway_Vipps' ) && is_callable( array( '\WC_Gateway_Vipps', 'instance' ) ) ) {
220 return \WC_Gateway_Vipps::instance();
221 }
222
223 if ( class_exists( '\Vipps' ) && is_callable( array( '\Vipps', 'instance' ) ) ) {
224 $vipps = \Vipps::instance();
225
226 if ( is_callable( array( $vipps, 'gateway' ) ) ) {
227 return $vipps->gateway();
228 }
229 }
230
231 return null;
232 }
233
234 /**
235 * Prefer the returned payment reference, then known order metadata; a missing reference is optional.
236 */
237 protected function get_gutenberg_checkout_payment_reference( $payment_result, $order ) {
238 foreach ( array( 'paymentReference', 'reference', 'vippsPaymentReference' ) as $key ) {
239 if ( ! empty( $payment_result[ $key ] ) ) {
240 return $payment_result[ $key ];
241 }
242 }
243
244 foreach ( array( '_vipps_payment_reference', '_vipps_reference', 'vipps_payment_reference' ) as $key ) {
245 $reference = $order->get_meta( $key, true );
246
247 if ( $reference ) {
248 return $reference;
249 }
250 }
251
252 return '';
253 }
254
255 /**
256 * Format customer-facing errors using the configured payment method name.
257 */
258 protected function get_payment_method_error_message( $message ) {
259 return sprintf( $message, $this->payment_method_name );
260 }
261
262 /**
263 * Expose localized labels, branding and express eligibility as vipps_data for the JS component.
264 */
265 public function get_payment_method_data() {
266 $logo = ( $this->payment_method_name == 'Vipps' ) ? plugins_url( '../../img/vipps-mark.svg', __FILE__ ) : plugins_url( '../../img/mobilepay-mark.png', __FILE__ );
267 $brand = ( $this->payment_method_name == 'Vipps' ) ? 'vipps' : 'mobilepay';
268 $language = substr( determine_locale(), 0, 2 );
269 if ( ! in_array( $language, array( 'no', 'en', 'da', 'fi', 'sv' ), true ) ) {
270 $language = 'en';
271 }
272
273 $data = [
274 'title' => $this->payment_method_name,
275 'description' => $this->get_setting( 'description' ),
276 'iconsrc' => apply_filters( 'woo_vipps_block_logo_url', $logo ),
277 'brand' => apply_filters( 'woo_vipps_block_widget_brand', $brand ),
278 'language' => apply_filters( 'woo_vipps_block_widget_language', $language ),
279 'show_express_checkout' => $this->show_express_checkout_button(),
280 'expressbutton' => $this->get_express_checkout_button(),
281 ];
282
283 return $data;
284 }
285 }
286