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 / README.md

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

166 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 # Checkout payment methods
2
3 ## Vipps (`vipps`)
4
5 `Vipps.class.php` registers the Blocks integration and supplies `vipps_data`.
6 `js/wc-payment-method-vipps.js` registers its label, description/event subscriber,
7 and custom place-order button. The button and subscriber share a controller
8 because WooCommerce renders them as separate components.
9
10 ### Order creation and widget handoff
11
12 1. The button validates checkout, creates a pending payment-URL promise, and starts
13 the SDK trigger. The trigger resolver waits for that promise.
14 2. The button calls WooCommerce's `onSubmit()`. Do not await `trigger.open()` first:
15 the trigger needs the URL from the order this submission will create.
16 3. `onPaymentSetup` supplies the payment method and `vipps_checkout_widget` marker.
17 Its success response means request data is ready; it does not mean the customer
18 has paid. The PHP bridge currently selects requests by payment method, not by
19 this marker.
20 4. WooCommerce creates/processes the order through the Store API. The PHP bridge
21 calls the gateway's normal `process_payment()` unless its pre-process filter
22 supplies a result. It places the payment URL/reference in payment details and
23 sets the result status to success. This status also tells WooCommerce's later
24 legacy fallback that processing has already been handled.
25 5. `onCheckoutSuccess` reads `processingResponse.paymentDetails`, with support for
26 older event/response shapes. It prefers `vippsPaymentUrl` and accepts the normal
27 `redirectUrl` as a fallback for a legacy gateway response.
28 6. The controller resolves the SDK promise with the URL. The observer returns
29 `{ type: SUCCESS, redirectUrl: '' }`, completing WooCommerce checkout while
30 clearing its automatic redirect. This override applies only to an active
31 widget attempt; unrelated success events return `true`.
32
33 ### Why the empty redirect is required
34
35 WooCommerce and the SDK can both receive the same payment URL. Delivering it to
36 the SDK does not consume or clear WooCommerce's stored redirect. Returning plain
37 `SUCCESS` or `true` lets WooCommerce complete checkout and navigate to that URL,
38 interrupting the widget flow.
39
40 WooCommerce's success observer handler passes the response to `SET_COMPLETE`.
41 The completion reducer accepts any string `redirectUrl`, including `''`, in place
42 of the stored URL. The checkout processor navigates only when its redirect is
43 nonempty. Preserve the explicit empty string; do not replace it with omission,
44 `null`, or `true`.
45
46 Source references (reviewed September 2026; upstream paths may change):
47
48 - [](https://developer.woocommerce.com/docs/block-development/extensible-blocks/cart-and-checkout-blocks/checkout-payment-methods/checkout-flow-and-events/#oncheckoutsuccessCheckout event contract](https://developer.woocommerce.com/docs/block-development/extensible-blocks/cart-and-checkout-blocks/checkout-payment-methods/checkout-flow-and-events/#oncheckoutsuccess](https://developer.woocommerce.com/docs/block-development/extensible-blocks/cart-and-checkout-blocks/checkout-payment-methods/checkout-flow-and-events/#oncheckoutsuccess)
49 - [](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/client/blocks/packages/public-api/block-data/checkout/utils.tsSuccess observer handling](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/client/blocks/packages/public-api/block-data/checkout/utils.ts](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/client/blocks/packages/public-api/block-data/checkout/utils.ts)
50 - [](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/client/blocks/packages/public-api/block-data/checkout/reducers.tsSET_COMPLETE redirect override](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/client/blocks/packages/public-api/block-data/checkout/reducers.ts](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/client/blocks/packages/public-api/block-data/checkout/reducers.ts)
51 - [](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/client/blocks/assets/js/base/context/providers/cart-checkout/checkout-processor.tsCheckout navigation](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/client/blocks/assets/js/base/context/providers/cart-checkout/checkout-processor.ts](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/client/blocks/assets/js/base/context/providers/cart-checkout/checkout-processor.ts)
52 - [](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/StoreApi/Legacy.phpLegacy gateway adapter and status guard](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/StoreApi/Legacy.php](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/StoreApi/Legacy.php)
53
54 ### SDK lifecycle and recovery
55
56 `vipps.js` exposes `ensureVippsWidgetHostStarted()` so express and standard checkout
57 share one desktop host. The Blocks controller can also start the host if the
58 helper is absent. Host initialization alone does not affect WooCommerce navigation.
59
60 The SDK owns payment presentation: desktop normally uses a dialog; mobile/tablet
61 and desktop fallback paths may navigate. SDK success/cancel handlers close the
62 dialog and follow the merchant-return URL when supplied. These return URLs serve
63 a different purpose from the initial payment-session URL. See the
64 [](https://developer.vippsmobilepay.com/docs/knowledge-base/widget/Widget SDK documentation](https://developer.vippsmobilepay.com/docs/knowledge-base/widget/](https://developer.vippsmobilepay.com/docs/knowledge-base/widget/).
65
66 The controller's attempt ends when the URL is delivered. It does not represent
67 payment settlement. WooCommerce's processing/redirect flags also disable the
68 button. During the attempt, `setVippsPaymentBusy()` in `vipps.js` shows the same
69 spinner and overlay as express checkout, reusing the existing `.vippsoverlay`
70 markup and `body.processing` styles. Each flow has its own owner key so clearing
71 one cannot hide the other's spinner. URL delivery or failure releases the overlay
72 for the SDK UI; unmounting the checkout button also releases its overlay owner.
73 The button exposes `aria-busy` while its attempt is pending.
74 Missing payment URLs return a retryable checkout error; checkout failures
75 reject the waiting resolver. If the SDK is unavailable at handoff, the controller
76 uses full-page navigation directly.
77
78 A session-storage handoff marker refreshes stale checkout pages on history restore,
79 focus, or visibility return. A per-path guard prevents repeated reloads. This is
80 separate from payment confirmation; order metadata in the marker is optional.
81
82 ## Express Vipps (`vippsexpress`)
83
84 `ExpressCheckoutButton` renders the server shortcode markup. `vipps.js` handles
85 the express button, calls the express session endpoint, and supplies its URL
86 directly to the SDK. Although registration maps `paymentMethodId` to `vipps`,
87 this express flow does not use the standard button's pending Store API promise.
88 Its confirmation dialog and handoff recovery remain in the shared script.
89
90 ## Classic shortcode checkout
91
92 `vipps-classic-checkout.js` uses the existing WooCommerce form and the optional
93 branded `#vipps-classic-checkout-submit` submit button. It handles
94 `checkout_place_order_vipps` synchronously, suppresses core's default AJAX request,
95 and submits the full checkout form to `wc_checkout_params.checkout_url` from the
96 SDK resolver. WooCommerce still performs validation, creates/resumes the order,
97 and invokes the gateway. This adapter owns the response, so core does not also
98 redirect to the payment URL. It does not emit the classic success hook, whose
99 normal consumer would redirect or enter its generic error branch.
100
101 The script reuses the shared host and spinner. Form fields are serialized before
102 being disabled; their prior disabled states are restored on a known checkout
103 failure. The form stays locked after URL delivery until the dialog exits, so
104 another payment cannot be submitted behind the dialog. A close/cancel without a
105 return URL reloads checkout; a close during submission waits for the request to
106 finish first. Restoring an old attempt from the back-forward cache also reloads.
107
108 Server checkout errors remain visible through WooCommerce's error presenter when
109 available, with a notice fallback for versions that do not pass the checkout
110 controller into the hook. Refresh/reload responses are honored. An unconfirmed
111 network result or unusable success response offers a reload link and blocks a
112 second POST; it never automatically retries a possibly successful payment request.
113 If the SDK fails after submission, a valid returned payment URL can be followed
114 directly without creating another payment.
115
116 The branded button is selected by the checked `payment_method` radio. For Vipps,
117 the script removes its `hidden` class and hides `#place_order`; for every other
118 gateway it restores the normal button. The switch is delegated so it survives
119 WooCommerce replacing the payment section after `updated_checkout`. The native
120 button remains the fallback when the branded button or JavaScript is unavailable.
121 The button uses the same form-submit path, so it does not bypass WooCommerce
122 validation or create a second payment request.
123
124 On `woocommerce-order-pay` pages it uses the existing-order Store API route rather
125 than cart checkout AJAX. It localizes `VippsOrderPayConfig` before this script runs:
126
127 ```js
128 window.VippsOrderPayConfig = {
129 orderId: 123,
130 orderKey: 'wc_order_key_for_guest_links',
131 billingEmail: '[email protected]',
132 endpoint: '/wp-json/wc/store/v1/checkout/123',
133 nonce: 'store-api-nonce',
134 billingAddress: { first_name: '', last_name: '', address_1: '', city: '', state: '', postcode: '', country: '', email: '' },
135 shippingAddress: { first_name: '', last_name: '', address_1: '', city: '', state: '', postcode: '', country: '' }
136 };
137 ```
138 The adapter sends the selected Vipps method and form fields as
139 `payment_data`, then reads the URL from `payment_result.payment_details` or its
140 redirect fallback. It never sends the pay form to cart checkout AJAX.
141
142 Before sending a Vipps request, it checks the same `terms-field` marker and
143 `terms` checkbox used by WooCommerce's native pay-for-order handler. Missing
144 terms are displayed using standard WooCommerce error-notice markup, and the page
145 scrolls to the notice. Store API failures, missing payment URLs, and SDK startup
146 failures use the same notice path. The notice container is refreshed and focused
147 so the customer can correct the form and retry.
148
149 The order-pay form remains native when this configuration or the SDK is missing.
150 Its existing submit handler is prevented only for an active Vipps SDK attempt.
151 Success hands the URL to the SDK; cancellation/close reloads the same authorized
152 pay URL, and failures restore the form for retry. The adapter never automatically
153 reposts an uncertain request.
154 Blocks and non-Vipps methods retain their existing handlers. If the main plugin
155 already attaches a Vipps-specific classic submit handler, consolidate that handler
156 with this one so it cannot initiate a second payment independently.
157
158 ### Loading and dependencies
159
160 Load `vipps-classic-checkout.js` only on the classic checkout and
161 `woocommerce-order-pay` pages. Order-pay must remain enabled when the configured
162 checkout page uses Blocks, because WooCommerce renders the pay form through the
163 classic shortcode template in that case. The script depends on `jquery`,
164 `wc-checkout`, and `vipps-gw`; the latter must load `vipps.js` and the SDK before
165 the customer submits. Do not load this adapter on the Checkout Block itself.
166