@graphcommerce/magento-payment-multisafepay 4.14.0-canary.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,31 @@
1
+ # @graphcommerce/magento-payment-multisafepay
2
+
3
+ ## 4.14.0-canary.10
4
+
5
+ ## 4.14.0-canary.9
6
+
7
+ ## 4.14.0-canary.8
8
+
9
+ ## 4.14.0-canary.7
10
+
11
+ ### Patch Changes
12
+
13
+ - [#1738](https://github.com/graphcommerce-org/graphcommerce/pull/1738) [`52882a63e`](https://github.com/graphcommerce-org/graphcommerce/commit/52882a63e96c0d3ba9641c3714d288fa4f420c82) - Do not forward the Prev prop in plugins ([@paales](https://github.com/paales))
14
+
15
+ ## 4.14.0-canary.6
16
+
17
+ ## 4.14.0-canary.5
18
+
19
+ ## 4.14.0-canary.4
20
+
21
+ ### Patch Changes
22
+
23
+ - [#1733](https://github.com/graphcommerce-org/graphcommerce/pull/1733) [`b2d73c726`](https://github.com/graphcommerce-org/graphcommerce/commit/b2d73c726fa123435fa6c54b4e0fd0db2df7c4ab) - Move to <Prev/> instead of <Component/> to call the plugin component ([@paales](https://github.com/paales))
24
+
25
+ - [#1733](https://github.com/graphcommerce-org/graphcommerce/pull/1733) [`be10e8cd1`](https://github.com/graphcommerce-org/graphcommerce/commit/be10e8cd1dce172a914ee9e5f65fdca4d0929fc8) - Migrated payment methods to use the new `onSuccess` method from `PaymentMethodContextProvider` instead of redirecting manually, makes sure the onSuccess method can be used by plugins. ([@paales](https://github.com/paales))
26
+
27
+ ## 4.14.0-canary.3
28
+
29
+ ### Minor Changes
30
+
31
+ - [#1729](https://github.com/graphcommerce-org/graphcommerce/pull/1729) [`366b05a7d`](https://github.com/graphcommerce-org/graphcommerce/commit/366b05a7da174a8a7c665b44e11422d8c873e4ed) - MultiSafePay Payment gateway support ([@paales](https://github.com/paales))
package/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # MultiSafePay
2
+
3
+ ## Requirements
4
+
5
+ - MultiSafePay Magento module: https://github.com/MultiSafepay/magento2
6
+ - MultiSafePay Magento GraphQL module:
7
+ https://github.com/MultiSafepay/magento2-graphql
8
+
9
+ ## Installation
10
+
11
+ 1. Find current version of your `@graphcommerce/magento-cart-payment-method` in
12
+ your package.json.
13
+ 2. `yarn add @graphcommerce/magento-payment-multisafepay@1.2.3` (replace 1.2.3
14
+ with the version of the step above)
15
+ 3. In Magento: Sales -> MultiSafePay -> General Settings -> Advanced Settings
16
+ (this should be configured per storeview)
17
+ - _Use custom return urls for PWA storefront integration_: Yes
18
+ - _Custom redirect url after cancelling the payment_:
19
+ `https://$domain/$locale/checkout/payment?locked=1&success=0&cart_id={{quote.masked_id}}&method={{payment.code}}&order_number={{order.increment_id}}`
20
+ - _Custom "Success page" url_:
21
+ `https://$domain/$locale/checkout/payment?locked=1&success=1&cart_id={{quote.masked_id}}&method={{payment.code}}&order_number={{order.increment_id}}`
@@ -0,0 +1,29 @@
1
+ import { Image } from '@graphcommerce/image'
2
+ import { PaymentMethodActionCardProps } from '@graphcommerce/magento-cart-payment-method'
3
+ import { ActionCard, responsiveVal as rv } from '@graphcommerce/next-ui'
4
+ import { Trans } from '@lingui/react'
5
+
6
+ export function MSPPaymentActionCard(props: PaymentMethodActionCardProps) {
7
+ const { child, multisafepay_additional_data } = props
8
+ const iconSize = rv(30, 44)
9
+
10
+ return (
11
+ <ActionCard
12
+ {...props}
13
+ details={child === 'ideal' && <Trans id='Pay with iDEAL' />}
14
+ image={
15
+ multisafepay_additional_data?.image && (
16
+ <Image
17
+ layout='fixed'
18
+ width={100}
19
+ height={100}
20
+ sx={{ width: iconSize, height: iconSize, objectFit: 'contain' }}
21
+ sizes={iconSize}
22
+ unoptimized
23
+ src={multisafepay_additional_data?.image}
24
+ />
25
+ )
26
+ }
27
+ />
28
+ )
29
+ }
@@ -0,0 +1,3 @@
1
+ mutation MSPPaymentHandler($cartId: String!) {
2
+ getPaymentMeta(input: { cart_id: $cartId })
3
+ }
@@ -0,0 +1,56 @@
1
+ import { useMutation } from '@graphcommerce/graphql'
2
+ import { useAssignCurrentCartId, useClearCurrentCartId } from '@graphcommerce/magento-cart'
3
+ import {
4
+ PaymentHandlerProps,
5
+ usePaymentMethodContext,
6
+ } from '@graphcommerce/magento-cart-payment-method'
7
+ import { ErrorSnackbar } from '@graphcommerce/next-ui'
8
+ import { Trans } from '@lingui/react'
9
+ import { useEffect } from 'react'
10
+ import { useMSPCartLock } from '../../hooks/useMSPCartLock'
11
+ import { MSPPaymentHandlerDocument } from './MSPPaymentHandler.gql'
12
+
13
+ export const MSPPaymentHandler = (props: PaymentHandlerProps) => {
14
+ const { code } = props
15
+ const [lockStatus, , unlock] = useMSPCartLock()
16
+ const assignCurrentCartId = useAssignCurrentCartId()
17
+ const { onSuccess } = usePaymentMethodContext()
18
+
19
+ const [restore, { error }] = useMutation(MSPPaymentHandlerDocument)
20
+
21
+ const { justLocked, success, cart_id: cartId, locked, method, order_number } = lockStatus
22
+
23
+ const canProceed = !(justLocked || !locked || !cartId || method !== code)
24
+
25
+ // When the payment has failed we restore the current cart
26
+ const shouldRestore = canProceed && success !== '1'
27
+ useEffect(() => {
28
+ if (!shouldRestore) return
29
+
30
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
31
+ restore({ variables: { cartId } }).then(({ data }) => {
32
+ if (!data?.getPaymentMeta) return undefined
33
+
34
+ assignCurrentCartId(data.getPaymentMeta)
35
+ return unlock({ success: null })
36
+ })
37
+ }, [assignCurrentCartId, cartId, restore, shouldRestore, unlock])
38
+
39
+ // If successfull we clear it's cart and redirect to the success page.
40
+ const shouldRedirect = canProceed && success === '1'
41
+ useEffect(() => {
42
+ if (!shouldRedirect || !order_number) return
43
+
44
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
45
+ onSuccess(order_number)
46
+ }, [cartId, onSuccess, order_number, shouldRedirect])
47
+
48
+ if (error) {
49
+ return (
50
+ <ErrorSnackbar open>
51
+ <Trans id='Payment has not completed succesfully, please try again.' />
52
+ </ErrorSnackbar>
53
+ )
54
+ }
55
+ return null
56
+ }
@@ -0,0 +1,18 @@
1
+ mutation MSPPaymentOptionsAndPlaceOrder($cartId: String!, $paymentMethod: PaymentMethodInput!) {
2
+ setPaymentMethodOnCart(input: { cart_id: $cartId, payment_method: $paymentMethod }) {
3
+ cart {
4
+ selected_payment_method {
5
+ ...SelectedPaymentMethod
6
+ }
7
+ }
8
+ }
9
+ placeOrder(input: { cart_id: $cartId }) {
10
+ order {
11
+ order_number
12
+ multisafepay_payment_url {
13
+ error
14
+ payment_url
15
+ }
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,91 @@
1
+ import {
2
+ useFormCompose,
3
+ useFormPersist,
4
+ useFormValidFields,
5
+ SelectElement,
6
+ } from '@graphcommerce/ecommerce-ui'
7
+ import { useFormGqlMutationCart } from '@graphcommerce/magento-cart'
8
+ import {
9
+ PaymentOptionsProps,
10
+ usePaymentMethodContext,
11
+ } from '@graphcommerce/magento-cart-payment-method'
12
+ import { filterNonNullableKeys, FormRow } from '@graphcommerce/next-ui'
13
+ import { useRouter } from 'next/router'
14
+ import { useMSPCartLock } from '../../hooks/useMSPCartLock'
15
+ import {
16
+ MSPPaymentOptionsAndPlaceOrderMutation,
17
+ MSPPaymentOptionsAndPlaceOrderMutationVariables,
18
+ MSPPaymentOptionsAndPlaceOrderDocument,
19
+ } from './MSPPaymentOptionsAndPlaceOrder.gql'
20
+
21
+ /** It sets the selected payment method on the cart. */
22
+ export function MSPPaymentOptionsAndPlaceOrder(props: PaymentOptionsProps) {
23
+ const { code, step, multisafepay_available_issuers } = props
24
+
25
+ const [, lock] = useMSPCartLock()
26
+ const { selectedMethod } = usePaymentMethodContext()
27
+ const { push } = useRouter()
28
+
29
+ /**
30
+ * In the this folder you'll also find a PaymentMethodOptionsNoop.graphql document that is
31
+ * imported here and used as the basis for the form below.
32
+ */
33
+ const form = useFormGqlMutationCart<
34
+ MSPPaymentOptionsAndPlaceOrderMutation,
35
+ MSPPaymentOptionsAndPlaceOrderMutationVariables
36
+ >(MSPPaymentOptionsAndPlaceOrderDocument, {
37
+ onComplete: async (result) => {
38
+ const url = result.data?.placeOrder?.order.multisafepay_payment_url
39
+
40
+ if (result.errors || !selectedMethod?.code || url?.error || !url?.payment_url) return
41
+
42
+ await lock({
43
+ method: selectedMethod.code,
44
+ order_number: result.data?.placeOrder?.order.order_number,
45
+ })
46
+ await push(url.payment_url)
47
+ },
48
+ })
49
+
50
+ const { handleSubmit, required, register, control } = form
51
+
52
+ const submit = handleSubmit(() => {})
53
+
54
+ const key = `PaymentMethodOptions_${code}`
55
+ useFormPersist({
56
+ form,
57
+ name: key,
58
+ persist: ['paymentMethod.multisafepay_ideal.issuer_id'],
59
+ storage: 'localStorage',
60
+ })
61
+
62
+ const valid = useFormValidFields(form, required)
63
+
64
+ /** To use an external Pay button we register the current form to be handled there as well. */
65
+ useFormCompose({ form, step, submit, key })
66
+
67
+ const issuers = filterNonNullableKeys(multisafepay_available_issuers, ['code', 'description'])
68
+
69
+ /** This is the form that the user can fill in. In this case we don't wat the user to fill in anything. */
70
+ return (
71
+ <form key={key} onSubmit={submit} noValidate>
72
+ <input type='hidden' value={code} {...register('paymentMethod.code')} />
73
+
74
+ {code === 'multisafepay_ideal' && issuers.length && (
75
+ <FormRow>
76
+ <SelectElement
77
+ control={control}
78
+ name='paymentMethod.multisafepay_ideal.issuer_id'
79
+ required
80
+ validation={{ required: { message: 'Please provide an issuer', value: true } }}
81
+ variant='outlined'
82
+ color='secondary'
83
+ select
84
+ label='Select your bank'
85
+ options={issuers.map(({ code: id, description: label }) => ({ id, label }))}
86
+ />
87
+ </FormRow>
88
+ )}
89
+ </form>
90
+ )
91
+ }
@@ -0,0 +1,11 @@
1
+ fragment MSPAvailablePaymentMethod on AvailablePaymentMethod
2
+ @inject(into: ["AvailablePaymentMethod"]) {
3
+ multisafepay_additional_data {
4
+ image
5
+ is_preselected
6
+ }
7
+ multisafepay_available_issuers {
8
+ code
9
+ description
10
+ }
11
+ }
@@ -0,0 +1,15 @@
1
+ import { CartLockState, useCartLock } from '@graphcommerce/magento-cart-payment-method'
2
+
3
+ type MSPLockState = CartLockState & {
4
+ success?: string | null
5
+ order_number?: string | null
6
+ }
7
+
8
+ /**
9
+ * The cart lock situation is a bit odd since are unable to actually influence the return URL we
10
+ * can't safely remember the cart ID.
11
+ *
12
+ * This is a potential bug because when the customer is returning from an icognito session, the cart
13
+ * ID is not available.
14
+ */
15
+ export const useMSPCartLock = () => useCartLock<MSPLockState>()
package/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './methods'
package/methods.ts ADDED
@@ -0,0 +1,100 @@
1
+ import { PaymentModule } from '@graphcommerce/magento-cart-payment-method'
2
+ import { MSPPaymentActionCard } from './components/MSPPaymentActionCard/MSPPaymentActionCard'
3
+ import { MSPPaymentHandler } from './components/MSPPaymentHandler/MSPPaymentHandler'
4
+ import { MSPPaymentOptionsAndPlaceOrder } from './components/MSPPaymentOptionsAndPlaceOrder/MSPPaymentOptionsAndPlaceOrder'
5
+
6
+ const mspModule: PaymentModule = {
7
+ PaymentOptions: MSPPaymentOptionsAndPlaceOrder,
8
+ PaymentActionCard: MSPPaymentActionCard,
9
+ PaymentHandler: MSPPaymentHandler,
10
+ PaymentPlaceOrder: () => null,
11
+ }
12
+
13
+ /**
14
+ * List is extracted from https://github.com/MultiSafepay/magento2-core/blob/master/etc/config.xml
15
+ *
16
+ * All payment methods are enabled except the ones that require additional imputs:
17
+ *
18
+ * - `multisafepay_afterpay`
19
+ * - `multisafepay_directbanktransfer`
20
+ * - `multisafepay_directdebit`
21
+ * - `multisafepay_einvoicing`
22
+ * - `multisafepay_in3`
23
+ * - `multisafepay_payafter`
24
+ *
25
+ * Excluded taken from:
26
+ * https://github.com/MultiSafepay/magento2-graphql/blob/53db83f1b3382c8e11c22a1fa2170b8b17ecb7d7/etc/schema.graphqls#L36-L41
27
+ */
28
+ export const multisafepay: Record<string, PaymentModule> = {
29
+ multisafepay_ideal: mspModule,
30
+ multisafepay_ideal_recurring: mspModule,
31
+ multisafepay_ideal_vault: mspModule,
32
+ // multisafepay_payafter: mspModule,
33
+ multisafepay_klarna: mspModule,
34
+ // multisafepay_afterpay: mspModule,
35
+ multisafepay_bancontact: mspModule,
36
+ multisafepay_amex: mspModule,
37
+ multisafepay_applepay: mspModule,
38
+ multisafepay_belfius: mspModule,
39
+ multisafepay_creditcard: mspModule,
40
+ multisafepay_creditcard_recurring: mspModule,
41
+ multisafepay_creditcard_vault: mspModule,
42
+ multisafepay_visa_recurring: mspModule,
43
+ multisafepay_visa_vault: mspModule,
44
+ multisafepay_mastercard_recurring: mspModule,
45
+ multisafepay_mastercard_vault: mspModule,
46
+ multisafepay_amex_recurring: mspModule,
47
+ multisafepay_amex_vault: mspModule,
48
+ multisafepay_dotpay: mspModule,
49
+ multisafepay_eps: mspModule,
50
+ multisafepay_giropay: mspModule,
51
+ multisafepay_googlepay: mspModule,
52
+ multisafepay_idealqr: mspModule,
53
+ multisafepay_maestro: mspModule,
54
+ multisafepay_maestro_recurring: mspModule,
55
+ multisafepay_maestro_vault: mspModule,
56
+ multisafepay_mastercard: mspModule,
57
+ multisafepay_mybank: mspModule,
58
+ multisafepay_paysafecard: mspModule,
59
+ multisafepay_sofort: mspModule,
60
+ multisafepay_trustpay: mspModule,
61
+ multisafepay_visa: mspModule,
62
+ multisafepay_alipay: mspModule,
63
+ multisafepay_alipayplus: mspModule,
64
+ // multisafepay_directbanktransfer: mspModule,
65
+ multisafepay_banktransfer: mspModule,
66
+ multisafepay_santander: mspModule,
67
+ multisafepay_cbc: mspModule,
68
+ // multisafepay_directdebit: mspModule,
69
+ // multisafepay_directdebit_recurring: mspModule,
70
+ // multisafepay_directdebit_vault: mspModule,
71
+ // multisafepay_einvoicing: mspModule,
72
+ multisafepay_inghomepay: mspModule,
73
+ multisafepay_kbc: mspModule,
74
+ multisafepay_paypal: mspModule,
75
+ multisafepay_trustly: mspModule,
76
+ // multisafepay_in3: mspModule,
77
+ multisafepay_genericgateway: mspModule,
78
+ multisafepay_babygiftcard: mspModule,
79
+ multisafepay_beautyandwellness: mspModule,
80
+ multisafepay_boekenbon: mspModule,
81
+ multisafepay_fashioncheque: mspModule,
82
+ multisafepay_fashiongiftcard: mspModule,
83
+ multisafepay_fietsenbon: mspModule,
84
+ multisafepay_edenred: mspModule,
85
+ multisafepay_gezondheidsbon: mspModule,
86
+ multisafepay_givacard: mspModule,
87
+ multisafepay_good4fun: mspModule,
88
+ multisafepay_goodcard: mspModule,
89
+ multisafepay_nationaletuinbon: mspModule,
90
+ multisafepay_parfumcadeaukaart: mspModule,
91
+ multisafepay_podiumcadeaukaart: mspModule,
92
+ multisafepay_sportenfit: mspModule,
93
+ multisafepay_vvvcadeaukaart: mspModule,
94
+ multisafepay_webshopgiftcard: mspModule,
95
+ multisafepay_wechatpay: mspModule,
96
+ multisafepay_wellnessgiftcard: mspModule,
97
+ multisafepay_wijncadeau: mspModule,
98
+ multisafepay_winkelcheque: mspModule,
99
+ multisafepay_yourgift: mspModule,
100
+ }
package/next-env.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/types/global" />
3
+ /// <reference types="next/image-types/global" />
4
+ /// <reference types="@graphcommerce/next-ui/types" />
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@graphcommerce/magento-payment-multisafepay",
3
+ "homepage": "https://www.graphcommerce.org/",
4
+ "repository": "github:graphcommerce-org/graphcommerce",
5
+ "version": "4.14.0-canary.10",
6
+ "sideEffects": false,
7
+ "prettier": "@graphcommerce/prettier-config-pwa",
8
+ "eslintConfig": {
9
+ "extends": "@graphcommerce/eslint-config-pwa",
10
+ "parserOptions": {
11
+ "project": "./tsconfig.json"
12
+ }
13
+ },
14
+ "devDependencies": {
15
+ "@graphcommerce/next-ui": "4.31.0-canary.6",
16
+ "@graphcommerce/eslint-config-pwa": "^4.1.11",
17
+ "@graphcommerce/magento-cart-shipping-address": "4.14.0-canary.10",
18
+ "@graphcommerce/magento-product": "4.14.0-canary.10",
19
+ "@graphcommerce/magento-product-configurable": "4.14.0-canary.10",
20
+ "@graphcommerce/prettier-config-pwa": "^4.0.7",
21
+ "@graphcommerce/typescript-config-pwa": "^4.0.5",
22
+ "@playwright/test": "^1.21.1",
23
+ "type-fest": "^2.12.2"
24
+ },
25
+ "dependencies": {
26
+ "@graphcommerce/graphql": "4.31.0-canary.6",
27
+ "@graphcommerce/graphql-mesh": "4.31.0-canary.6",
28
+ "@graphcommerce/image": "4.31.0-canary.6",
29
+ "@graphcommerce/magento-cart": "4.14.0-canary.10",
30
+ "@graphcommerce/magento-cart-payment-method": "4.14.0-canary.10",
31
+ "@graphcommerce/magento-store": "4.14.0-canary.10",
32
+ "@graphcommerce/next-ui": "4.31.0-canary.6",
33
+ "@graphcommerce/react-hook-form": "4.31.0-canary.6"
34
+ },
35
+ "peerDependencies": {
36
+ "@lingui/react": "^3.13.2",
37
+ "@lingui/core": "^3.13.2",
38
+ "@mui/material": "5.5.3",
39
+ "next": "^12.1.2",
40
+ "react": "^17.0.1",
41
+ "react-dom": "^17.0.1"
42
+ }
43
+ }
@@ -0,0 +1,13 @@
1
+ import { PaymentMethodContextProviderProps } from '@graphcommerce/magento-cart-payment-method'
2
+ import type { PluginProps } from '@graphcommerce/next-config'
3
+ import { multisafepay } from '../methods'
4
+
5
+ export const component = 'PaymentMethodContextProvider'
6
+ export const exported = '@graphcommerce/magento-cart-payment-method'
7
+
8
+ function AddMultisafepayMethods(props: PluginProps<PaymentMethodContextProviderProps>) {
9
+ const { modules, Prev, ...rest } = props
10
+ return <Prev {...rest} modules={{ ...modules, ...multisafepay }} />
11
+ }
12
+
13
+ export const Plugin = AddMultisafepayMethods
package/tsconfig.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "exclude": ["node_modules"],
3
+ "include": ["**/*.ts", "**/*.tsx"],
4
+ "extends": "@graphcommerce/typescript-config-pwa/nextjs.json"
5
+ }