@graphcommerce/mollie-magento-payment 3.0.5 → 3.1.1
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 +44 -0
- package/Inject/MolliePaymentMethod.graphql +0 -4
- package/components/MollieOptionsIssuer/MollieIssuerOptions.tsx +3 -16
- package/components/MolliePaymentHandler/MolliePaymentHandler.graphql +8 -0
- package/components/MolliePaymentHandler/MolliePaymentHandler.tsx +82 -14
- package/components/MolliePaymentHandler/MollieRecoverCart.graphql +7 -0
- package/components/MolliePaymentToggle/MolliePaymentToggle.tsx +2 -11
- package/components/MolliePlaceOrder/MolliePlaceOrder.tsx +14 -19
- package/hooks/useCartLockWithToken.ts +22 -0
- package/index.ts +0 -1
- package/methods/mollie_methods_creditcard.ts +2 -2
- package/methods/mollie_methods_klarnapaylater.ts +0 -2
- package/package.json +17 -17
- package/test/creditcard.playwright.ts +70 -0
- package/test/ideal.playwright.ts +70 -0
- package/Inject/MollieSelectedPaymentMethod.graphql +0 -6
- package/_playwright/mollie_methods_ideal.spec.ts +0 -101
- package/hooks/UseMolliePaymentTokenHandler.graphql +0 -8
- package/hooks/index.ts +0 -1
- package/hooks/useMolliePaymentTokenHandler.ts +0 -65
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 3.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1378](https://github.com/graphcommerce-org/graphcommerce/pull/1378) [`b610a6e40`](https://github.com/graphcommerce-org/graphcommerce/commit/b610a6e4049e8c9e8b5d2aeff31b8e1bfc24abe5) Thanks [@paales](https://github.com/paales)! - Pin all versions internally so we can’t end up in an unfixable state for the user
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`b610a6e40`](https://github.com/graphcommerce-org/graphcommerce/commit/b610a6e4049e8c9e8b5d2aeff31b8e1bfc24abe5), [`22ff9df16`](https://github.com/graphcommerce-org/graphcommerce/commit/22ff9df1677742ae8e07d9b7e5b12fbb487580dc)]:
|
|
10
|
+
- @graphcommerce/graphql@3.0.7
|
|
11
|
+
- @graphcommerce/image@3.1.3
|
|
12
|
+
- @graphcommerce/magento-cart@4.2.3
|
|
13
|
+
- @graphcommerce/magento-cart-payment-method@3.0.7
|
|
14
|
+
- @graphcommerce/magento-store@4.1.5
|
|
15
|
+
- @graphcommerce/next-ui@4.5.1
|
|
16
|
+
- @graphcommerce/react-hook-form@3.0.7
|
|
17
|
+
|
|
18
|
+
## 3.1.0
|
|
19
|
+
|
|
20
|
+
### Minor Changes
|
|
21
|
+
|
|
22
|
+
- [#1368](https://github.com/graphcommerce-org/graphcommerce/pull/1368) [`892018809`](https://github.com/graphcommerce-org/graphcommerce/commit/8920188093d0422ec50580e408dc28ac5f93e46a) Thanks [@paales](https://github.com/paales)! - Fix issue where the cart couldn't be properly restored when a payment was cancelled
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- [#1369](https://github.com/graphcommerce-org/graphcommerce/pull/1369) [`ae6449502`](https://github.com/graphcommerce-org/graphcommerce/commit/ae64495024a455bbe5188588604368c1542840c9) Thanks [@paales](https://github.com/paales)! - Upgraded dependencies
|
|
27
|
+
|
|
28
|
+
- Updated dependencies [[`892018809`](https://github.com/graphcommerce-org/graphcommerce/commit/8920188093d0422ec50580e408dc28ac5f93e46a), [`892018809`](https://github.com/graphcommerce-org/graphcommerce/commit/8920188093d0422ec50580e408dc28ac5f93e46a), [`ae6449502`](https://github.com/graphcommerce-org/graphcommerce/commit/ae64495024a455bbe5188588604368c1542840c9), [`892018809`](https://github.com/graphcommerce-org/graphcommerce/commit/8920188093d0422ec50580e408dc28ac5f93e46a), [`892018809`](https://github.com/graphcommerce-org/graphcommerce/commit/8920188093d0422ec50580e408dc28ac5f93e46a), [`892018809`](https://github.com/graphcommerce-org/graphcommerce/commit/8920188093d0422ec50580e408dc28ac5f93e46a)]:
|
|
29
|
+
- @graphcommerce/graphql@3.0.6
|
|
30
|
+
- @graphcommerce/next-ui@4.5.0
|
|
31
|
+
- @graphcommerce/image@3.1.2
|
|
32
|
+
- @graphcommerce/magento-cart@4.2.2
|
|
33
|
+
- @graphcommerce/magento-cart-payment-method@3.0.6
|
|
34
|
+
- @graphcommerce/magento-store@4.1.4
|
|
35
|
+
- @graphcommerce/react-hook-form@3.0.6
|
|
36
|
+
|
|
37
|
+
## 3.0.6
|
|
38
|
+
|
|
39
|
+
### Patch Changes
|
|
40
|
+
|
|
41
|
+
- [#1353](https://github.com/graphcommerce-org/graphcommerce/pull/1353) [`0e5ee7ba8`](https://github.com/graphcommerce-org/graphcommerce/commit/0e5ee7ba89698e5e711001e846ed182528060cba) Thanks [@paales](https://github.com/paales)! - Eslint: enable rules that were previously disabled and make fixes
|
|
42
|
+
|
|
43
|
+
- Updated dependencies [[`49a2d6617`](https://github.com/graphcommerce-org/graphcommerce/commit/49a2d661712e1787fba46c6195f7b559189e23d9), [`f67da3cfb`](https://github.com/graphcommerce-org/graphcommerce/commit/f67da3cfbe2dcf5ea23519d088c5aa0074029182), [`218766869`](https://github.com/graphcommerce-org/graphcommerce/commit/218766869f7468c067a590857c942f3819f8add4), [`0e5ee7ba8`](https://github.com/graphcommerce-org/graphcommerce/commit/0e5ee7ba89698e5e711001e846ed182528060cba), [`829b8690b`](https://github.com/graphcommerce-org/graphcommerce/commit/829b8690bc5d0a46e596299e4120e9837a9f179c), [`829b8690b`](https://github.com/graphcommerce-org/graphcommerce/commit/829b8690bc5d0a46e596299e4120e9837a9f179c)]:
|
|
44
|
+
- @graphcommerce/next-ui@4.4.0
|
|
45
|
+
- @graphcommerce/magento-cart@4.2.1
|
|
46
|
+
|
|
3
47
|
## 3.0.5
|
|
4
48
|
|
|
5
49
|
### Patch Changes
|
|
@@ -13,7 +13,7 @@ const parts = ['root', 'list'] as const
|
|
|
13
13
|
const { classes } = extendableComponent(compName, parts)
|
|
14
14
|
|
|
15
15
|
export function MollieIssuerOptions(props: MollieIssuerOptionsProps) {
|
|
16
|
-
const { mollie_available_issuers = [] } = props
|
|
16
|
+
const { mollie_available_issuers = [], selected } = props
|
|
17
17
|
const { code, step, Container, label, title = '' } = props
|
|
18
18
|
|
|
19
19
|
const form = useFormGqlMutationCart(SetMolliePaymentMethodIssuerOnCartDocument, {
|
|
@@ -51,7 +51,6 @@ export function MollieIssuerOptions(props: MollieIssuerOptionsProps) {
|
|
|
51
51
|
>
|
|
52
52
|
{/* eslint-disable-next-line jsx-a11y/control-has-associated-label */}
|
|
53
53
|
<option value='' />
|
|
54
|
-
{/* <MenuItem value='' /> */}
|
|
55
54
|
{mollie_available_issuers?.map((issuer) => {
|
|
56
55
|
if (!issuer?.code || !issuer.name) return null
|
|
57
56
|
|
|
@@ -60,31 +59,19 @@ export function MollieIssuerOptions(props: MollieIssuerOptionsProps) {
|
|
|
60
59
|
{issuer.name}
|
|
61
60
|
</option>
|
|
62
61
|
)
|
|
63
|
-
// return (
|
|
64
|
-
// <MenuItem key={issuer.code} value={issuer.code}>
|
|
65
|
-
// <ListItemIcon>
|
|
66
|
-
// <IconSvg src={issuer.svg} alt={issuer.name} size='small' />
|
|
67
|
-
// </ListItemIcon>
|
|
68
|
-
// <Typography variant='inherit'>{issuer.name}</Typography>
|
|
69
|
-
// </MenuItem>
|
|
70
|
-
// )
|
|
71
62
|
})}
|
|
72
63
|
</TextField>
|
|
73
64
|
</FormRow>
|
|
74
65
|
<Box
|
|
75
66
|
component='ul'
|
|
76
67
|
className={classes.list}
|
|
77
|
-
sx={(theme) => ({
|
|
78
|
-
typography: 'body2',
|
|
79
|
-
paddingLeft: theme.spacings.xs,
|
|
80
|
-
margin: 0,
|
|
81
|
-
})}
|
|
68
|
+
sx={(theme) => ({ typography: 'body2', paddingLeft: theme.spacings.xs, margin: 0 })}
|
|
82
69
|
>
|
|
83
70
|
<li>
|
|
84
71
|
<Trans>Choose your bank, and place your order.</Trans>
|
|
85
72
|
</li>
|
|
86
73
|
<li>
|
|
87
|
-
<Trans>Complete the payment on your bank
|
|
74
|
+
<Trans>Complete the payment on your bank’s website.</Trans>
|
|
88
75
|
</li>
|
|
89
76
|
<li>
|
|
90
77
|
<Trans>
|
|
@@ -1,34 +1,102 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PaymentStatusEnum, useMutation } from '@graphcommerce/graphql'
|
|
2
|
+
import {
|
|
3
|
+
ApolloCartErrorFullPage,
|
|
4
|
+
useClearCurrentCartId,
|
|
5
|
+
useCurrentCartId,
|
|
6
|
+
} from '@graphcommerce/magento-cart'
|
|
7
|
+
import { usePaymentMethodContext } from '@graphcommerce/magento-cart-payment-method'
|
|
8
|
+
import { ErrorSnackbar } from '@graphcommerce/next-ui'
|
|
9
|
+
import { Trans } from '@lingui/macro'
|
|
2
10
|
import { Button, Dialog } from '@mui/material'
|
|
3
11
|
import { useRouter } from 'next/router'
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
12
|
+
import { useEffect } from 'react'
|
|
13
|
+
import { useCartLockWithToken } from '../../hooks/useCartLockWithToken'
|
|
14
|
+
import { MolliePaymentHandlerDocument } from './MolliePaymentHandler.gql'
|
|
15
|
+
import { MollieRecoverCartDocument } from './MollieRecoverCart.gql'
|
|
16
|
+
|
|
17
|
+
const successStatusses: PaymentStatusEnum[] = ['AUTHORIZED', 'COMPLETED', 'PAID', 'SHIPPING']
|
|
6
18
|
|
|
7
19
|
export function MolliePaymentHandler() {
|
|
8
|
-
const { error } = useMolliePaymentTokenHandler()
|
|
9
|
-
const clear = useClearCurrentCartId()
|
|
10
20
|
const router = useRouter()
|
|
21
|
+
const method = usePaymentMethodContext()
|
|
22
|
+
const clear = useClearCurrentCartId()
|
|
23
|
+
|
|
24
|
+
const isMollie = method.selectedMethod?.code.startsWith('mollie_methods')
|
|
11
25
|
|
|
12
|
-
const
|
|
13
|
-
|
|
26
|
+
const [lockState] = useCartLockWithToken()
|
|
27
|
+
|
|
28
|
+
const [handle, handleResult] = useMutation(MolliePaymentHandlerDocument)
|
|
29
|
+
const [recoverCart, recoverResult] = useMutation(MollieRecoverCartDocument)
|
|
30
|
+
|
|
31
|
+
const { called, error, data } = handleResult
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
14
34
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
15
|
-
|
|
16
|
-
|
|
35
|
+
;(async () => {
|
|
36
|
+
if (lockState.locked && lockState.redirecting) return
|
|
37
|
+
|
|
38
|
+
if (!lockState.mollie_payment_token) return
|
|
39
|
+
if (called || error) return
|
|
40
|
+
|
|
41
|
+
const result = await handle({
|
|
42
|
+
variables: { mollie_payment_token: lockState.mollie_payment_token },
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const paymentStatus = result.data?.mollieProcessTransaction?.paymentStatus
|
|
46
|
+
let returnedCartId = result.data?.mollieProcessTransaction?.cart?.id
|
|
47
|
+
|
|
48
|
+
if (paymentStatus === 'OPEN' && lockState.cart_id) {
|
|
49
|
+
const res = await recoverCart({ variables: { cartId: lockState.cart_id } })
|
|
50
|
+
returnedCartId = res.data?.mollieRestoreCart?.cart.id
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (result.errors || !paymentStatus) return
|
|
54
|
+
|
|
55
|
+
if (successStatusses.includes(paymentStatus)) {
|
|
56
|
+
clear()
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
58
|
+
await router.push({ pathname: '/checkout/success', query: { cart_id: lockState.cart_id } })
|
|
59
|
+
} else if (returnedCartId) {
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
61
|
+
router.replace('/checkout/payment')
|
|
62
|
+
}
|
|
63
|
+
})()
|
|
64
|
+
}, [called, clear, error, handle, lockState, recoverCart, router])
|
|
65
|
+
|
|
66
|
+
const paymentStatus = data?.mollieProcessTransaction?.paymentStatus
|
|
67
|
+
if (paymentStatus)
|
|
68
|
+
return (
|
|
69
|
+
<ErrorSnackbar open>
|
|
70
|
+
<Trans>Payment failed with status: {paymentStatus}</Trans>
|
|
71
|
+
</ErrorSnackbar>
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
if (!error || recoverResult.loading) return null
|
|
17
75
|
|
|
18
|
-
if (!error) return null
|
|
19
76
|
return (
|
|
20
77
|
<Dialog open fullWidth>
|
|
21
78
|
<ApolloCartErrorFullPage
|
|
22
79
|
error={error}
|
|
23
80
|
disableMargin
|
|
24
81
|
button={
|
|
25
|
-
<Button
|
|
26
|
-
|
|
82
|
+
<Button
|
|
83
|
+
variant='contained'
|
|
84
|
+
color='primary'
|
|
85
|
+
size='large'
|
|
86
|
+
onClick={() => {
|
|
87
|
+
clear()
|
|
88
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
89
|
+
router.push('/')
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
<Trans>Reset Cart and Return to home</Trans>
|
|
27
93
|
</Button>
|
|
28
94
|
}
|
|
29
95
|
>
|
|
30
|
-
|
|
31
|
-
|
|
96
|
+
<Trans>
|
|
97
|
+
If you’ve successfully paid your order, the order <strong>will</strong> come through, but
|
|
98
|
+
there is a communication error with the website.
|
|
99
|
+
</Trans>
|
|
32
100
|
</ApolloCartErrorFullPage>
|
|
33
101
|
</Dialog>
|
|
34
102
|
)
|
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
import { Image } from '@graphcommerce/image'
|
|
2
1
|
import { PaymentToggleProps } from '@graphcommerce/magento-cart-payment-method'
|
|
3
2
|
|
|
4
3
|
export function PaymentToggle(props: PaymentToggleProps) {
|
|
5
|
-
const {
|
|
4
|
+
const { title } = props
|
|
6
5
|
|
|
7
|
-
return
|
|
8
|
-
<>
|
|
9
|
-
{mollie_meta?.image && (
|
|
10
|
-
<Image layout='fixed' src={mollie_meta?.image} unoptimized alt={title} />
|
|
11
|
-
)}
|
|
12
|
-
|
|
13
|
-
{title}
|
|
14
|
-
</>
|
|
15
|
-
)
|
|
6
|
+
return <>{title}</>
|
|
16
7
|
}
|
|
@@ -3,18 +3,18 @@ import {
|
|
|
3
3
|
useCurrentCartId,
|
|
4
4
|
useFormGqlMutationCart,
|
|
5
5
|
} from '@graphcommerce/magento-cart'
|
|
6
|
-
import { PaymentPlaceOrderProps
|
|
6
|
+
import { PaymentPlaceOrderProps } from '@graphcommerce/magento-cart-payment-method'
|
|
7
7
|
import { useFormCompose } from '@graphcommerce/react-hook-form'
|
|
8
8
|
import { useRouter } from 'next/router'
|
|
9
9
|
import { useEffect } from 'react'
|
|
10
|
+
import { useCartLockWithToken } from '../../hooks/useCartLockWithToken'
|
|
10
11
|
import { MolliePlaceOrderDocument } from './MolliePlaceOrder.gql'
|
|
11
12
|
|
|
12
13
|
export function MolliePlaceOrder(props: PaymentPlaceOrderProps) {
|
|
13
14
|
const { step, code } = props
|
|
14
|
-
const
|
|
15
|
+
const { push } = useRouter()
|
|
15
16
|
const cartId = useCurrentCartId()
|
|
16
|
-
const
|
|
17
|
-
const { lock } = useCartLock()
|
|
17
|
+
const [, lock] = useCartLockWithToken()
|
|
18
18
|
|
|
19
19
|
const form = useFormGqlMutationCart(MolliePlaceOrderDocument, { mode: 'onChange' })
|
|
20
20
|
|
|
@@ -22,32 +22,27 @@ export function MolliePlaceOrder(props: PaymentPlaceOrderProps) {
|
|
|
22
22
|
|
|
23
23
|
useEffect(() => {
|
|
24
24
|
const current = new URL(window.location.href.replace(window.location.hash, ''))
|
|
25
|
-
current.searchParams.append('
|
|
25
|
+
// current.searchParams.append('locked', '1')
|
|
26
|
+
current.searchParams.set('cart_id', cartId ?? '')
|
|
27
|
+
current.searchParams.set('mollie_payment_token', 'PAYMENT_TOKEN')
|
|
26
28
|
const replaced = current.toString().replace('PAYMENT_TOKEN', '{{payment_token}}')
|
|
27
29
|
setValue('returnUrl', replaced)
|
|
28
|
-
}, [setValue])
|
|
30
|
+
}, [cartId, setValue])
|
|
29
31
|
|
|
30
32
|
const submit = handleSubmit(() => {})
|
|
31
33
|
|
|
32
34
|
useEffect(() => {
|
|
33
35
|
if (!data?.placeOrder?.order || error || !cartId) return
|
|
34
36
|
const redirectUrl = data?.placeOrder?.order.mollie_redirect_url
|
|
35
|
-
const
|
|
37
|
+
const mollie_payment_token = data?.placeOrder?.order.mollie_payment_token
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
setTimeout(() => {
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
42
|
-
router.push(redirectUrl)
|
|
43
|
-
}, 500)
|
|
44
|
-
}
|
|
45
|
-
if (!redirectUrl && molliePaymentToken) {
|
|
46
|
-
clear()
|
|
39
|
+
// When redirecting to the payment gateway
|
|
40
|
+
if (redirectUrl && mollie_payment_token) {
|
|
41
|
+
lock({ mollie_payment_token })
|
|
47
42
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
48
|
-
|
|
43
|
+
push(redirectUrl)
|
|
49
44
|
}
|
|
50
|
-
}, [cartId,
|
|
45
|
+
}, [cartId, data?.placeOrder?.order, error, lock, push])
|
|
51
46
|
|
|
52
47
|
useFormCompose({ form, step, submit, key: `PaymentMethodPlaceOrder_${code}` })
|
|
53
48
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CartLockState, useCartLock } from '@graphcommerce/magento-cart-payment-method'
|
|
2
|
+
import { useState } from 'react'
|
|
3
|
+
|
|
4
|
+
type MollieLockState = { mollie_payment_token?: string }
|
|
5
|
+
|
|
6
|
+
export const useCartLockWithToken = () => {
|
|
7
|
+
const [queryState, setRouterQuery] = useCartLock<MollieLockState>()
|
|
8
|
+
const [redirecting, setRedirecting] = useState(false)
|
|
9
|
+
|
|
10
|
+
const lock = (params: MollieLockState & CartLockState) => {
|
|
11
|
+
setRedirecting(true)
|
|
12
|
+
setRouterQuery(params)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const state = {
|
|
16
|
+
...queryState,
|
|
17
|
+
locked: queryState.locked === '1',
|
|
18
|
+
redirecting,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return [state, lock] as const
|
|
22
|
+
}
|
package/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { PaymentModule } from '@graphcommerce/magento-cart-payment-method'
|
|
1
|
+
import { PaymentMethodOptionsNoop, PaymentModule } from '@graphcommerce/magento-cart-payment-method'
|
|
2
2
|
import { MollieCreditCardOptions } from '../components/MollieOptionsToken/MollieCreditCardOptions'
|
|
3
3
|
import { PaymentToggle } from '../components/MolliePaymentToggle/MolliePaymentToggle'
|
|
4
4
|
import { MolliePlaceOrder } from '../components/MolliePlaceOrder/MolliePlaceOrder'
|
|
5
5
|
|
|
6
6
|
export const mollie_methods_creditcard: PaymentModule = {
|
|
7
7
|
PaymentToggle,
|
|
8
|
-
PaymentOptions:
|
|
8
|
+
PaymentOptions: PaymentMethodOptionsNoop,
|
|
9
9
|
PaymentPlaceOrder: MolliePlaceOrder,
|
|
10
10
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { PaymentMethodOptionsNoop, PaymentModule } from '@graphcommerce/magento-cart-payment-method'
|
|
2
|
-
import { PaymentToggle } from '../components/MolliePaymentToggle/MolliePaymentToggle'
|
|
3
2
|
import { MolliePlaceOrder } from '../components/MolliePlaceOrder/MolliePlaceOrder'
|
|
4
3
|
|
|
5
4
|
export const mollie_methods_klarnapaylater: PaymentModule = {
|
|
6
|
-
PaymentToggle,
|
|
7
5
|
PaymentOptions: PaymentMethodOptionsNoop,
|
|
8
6
|
PaymentPlaceOrder: MolliePlaceOrder,
|
|
9
7
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graphcommerce/mollie-magento-payment",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
-
"version": "3.
|
|
5
|
+
"version": "3.1.1",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"engines": {
|
|
8
8
|
"node": "14.x"
|
|
@@ -15,29 +15,29 @@
|
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@graphcommerce/eslint-config-pwa": "^4.
|
|
19
|
-
"@graphcommerce/magento-cart-shipping-address": "
|
|
20
|
-
"@graphcommerce/magento-product": "
|
|
21
|
-
"@graphcommerce/magento-product-configurable": "
|
|
22
|
-
"@graphcommerce/prettier-config-pwa": "^4.0.
|
|
18
|
+
"@graphcommerce/eslint-config-pwa": "^4.1.4",
|
|
19
|
+
"@graphcommerce/magento-cart-shipping-address": "3.0.6",
|
|
20
|
+
"@graphcommerce/magento-product": "4.1.4",
|
|
21
|
+
"@graphcommerce/magento-product-configurable": "4.0.8",
|
|
22
|
+
"@graphcommerce/prettier-config-pwa": "^4.0.5",
|
|
23
23
|
"@graphcommerce/typescript-config-pwa": "^4.0.2",
|
|
24
|
-
"@playwright/test": "^1.
|
|
24
|
+
"@playwright/test": "^1.20.1",
|
|
25
|
+
"type-fest": "2.12.1"
|
|
25
26
|
},
|
|
26
27
|
"dependencies": {
|
|
27
|
-
"@graphcommerce/graphql": "
|
|
28
|
-
"@graphcommerce/image": "
|
|
29
|
-
"@graphcommerce/magento-cart": "
|
|
30
|
-
"@graphcommerce/magento-cart-payment-method": "
|
|
31
|
-
"@graphcommerce/magento-store": "
|
|
32
|
-
"@graphcommerce/next-ui": "
|
|
33
|
-
"@graphcommerce/react-hook-form": "
|
|
34
|
-
"type-fest": "^2.12.0"
|
|
28
|
+
"@graphcommerce/graphql": "3.0.7",
|
|
29
|
+
"@graphcommerce/image": "3.1.3",
|
|
30
|
+
"@graphcommerce/magento-cart": "4.2.3",
|
|
31
|
+
"@graphcommerce/magento-cart-payment-method": "3.0.7",
|
|
32
|
+
"@graphcommerce/magento-store": "4.1.5",
|
|
33
|
+
"@graphcommerce/next-ui": "4.5.1",
|
|
34
|
+
"@graphcommerce/react-hook-form": "3.0.7"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@lingui/macro": "^3.13.2",
|
|
38
|
-
"@mui/material": "
|
|
38
|
+
"@mui/material": "5.5.3",
|
|
39
39
|
"framer-motion": "^6.2.4",
|
|
40
|
-
"next": "
|
|
40
|
+
"next": "12.1.2",
|
|
41
41
|
"react": "^17.0.1",
|
|
42
42
|
"react-dom": "^17.0.1"
|
|
43
43
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
|
+
import { waitForGraphQlResponse } from '@graphcommerce/graphql/test/apolloClient.fixture'
|
|
3
|
+
import { goToPayment } from '@graphcommerce/magento-cart-payment-method/test/goToPayment'
|
|
4
|
+
import { addConfigurableProductToCart } from '@graphcommerce/magento-product-configurable/test/addConfigurableProductToCart'
|
|
5
|
+
import { test } from '@graphcommerce/magento-product/test/productURL.fixture'
|
|
6
|
+
import { expect, Page } from '@playwright/test'
|
|
7
|
+
import { MolliePaymentHandlerDocument } from '../components/MolliePaymentHandler/MolliePaymentHandler.gql'
|
|
8
|
+
|
|
9
|
+
const selectCreditCard = async (page: Page) => {
|
|
10
|
+
await page.click('button[value=mollie_methods_creditcard]')
|
|
11
|
+
|
|
12
|
+
// Select Rabobank
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type Statuses = 'paid' | 'failed' | 'canceled' | 'open' | 'expired'
|
|
16
|
+
|
|
17
|
+
const placeOrder = async (page: Page, status: Statuses) => {
|
|
18
|
+
await Promise.all([page.waitForNavigation(), page.click('#place-order')])
|
|
19
|
+
|
|
20
|
+
await page.pause()
|
|
21
|
+
// await page.click(`input[name="final_state"][value=${status}]`)
|
|
22
|
+
// await Promise.all([page.waitForNavigation(), page.click('.footer button')])
|
|
23
|
+
|
|
24
|
+
const result = await waitForGraphQlResponse(page, MolliePaymentHandlerDocument)
|
|
25
|
+
expect(result.errors).toBeUndefined()
|
|
26
|
+
expect(result.data?.mollieProcessTransaction?.paymentStatus).toBe(status.toUpperCase())
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
test.describe('mollie creditcard place order', () => {
|
|
30
|
+
// test('CANCELED', async ({ page, productURL, apolloClient }) => {
|
|
31
|
+
// await addConfigurableProductToCart(page, productURL.ConfigurableProduct)
|
|
32
|
+
// await goToPayment(page, apolloClient)
|
|
33
|
+
// await selectCreditCard(page)
|
|
34
|
+
// await placeOrder(page, 'canceled')
|
|
35
|
+
// await placeOrder(page, 'paid')
|
|
36
|
+
// expect(await page.locator('text=Back to home').innerText()).toBeDefined()
|
|
37
|
+
// })
|
|
38
|
+
|
|
39
|
+
// test('OPEN', async ({ page, productURL, apolloClient }) => {
|
|
40
|
+
// await addConfigurableProductToCart(page, productURL.ConfigurableProduct)
|
|
41
|
+
// await goToPayment(page, apolloClient)
|
|
42
|
+
// await selectIdeal(page)
|
|
43
|
+
// await placeOrder(page, 'open')
|
|
44
|
+
// await placeOrder(page, 'paid')
|
|
45
|
+
// expect(await page.locator('text=Back to home').innerText()).toBeDefined()
|
|
46
|
+
// })
|
|
47
|
+
|
|
48
|
+
test('PAID', async ({ page, productURL, apolloClient }) => {
|
|
49
|
+
await addConfigurableProductToCart(page, productURL.ConfigurableProduct)
|
|
50
|
+
await goToPayment(page, apolloClient)
|
|
51
|
+
await selectCreditCard(page)
|
|
52
|
+
await placeOrder(page, 'paid')
|
|
53
|
+
expect(await page.locator('text=Back to home').innerText()).toBeDefined()
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
// test('Pressed back', async ({ page, productURL, apolloClient }) => {
|
|
57
|
+
// await addConfigurableProductToCart(page, productURL.ConfigurableProduct)
|
|
58
|
+
// await goToPayment(page, apolloClient)
|
|
59
|
+
// await selectIdeal(page)
|
|
60
|
+
// await Promise.all([page.waitForNavigation(), page.click('#place-order')])
|
|
61
|
+
|
|
62
|
+
// await page.pause()
|
|
63
|
+
// await page.goBack()
|
|
64
|
+
|
|
65
|
+
// expect(await page.locator('text=Payment failed with status: OPEN').innerText()).toBeDefined()
|
|
66
|
+
|
|
67
|
+
// await placeOrder(page, 'paid')
|
|
68
|
+
// expect(await page.locator('text=Back to home').innerText()).toBeDefined()
|
|
69
|
+
// })
|
|
70
|
+
})
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
|
+
import { waitForGraphQlResponse } from '@graphcommerce/graphql/test/apolloClient.fixture'
|
|
3
|
+
import { goToPayment } from '@graphcommerce/magento-cart-payment-method/test/goToPayment'
|
|
4
|
+
import { addConfigurableProductToCart } from '@graphcommerce/magento-product-configurable/test/addConfigurableProductToCart'
|
|
5
|
+
import { test } from '@graphcommerce/magento-product/test/productURL.fixture'
|
|
6
|
+
import { expect, Page } from '@playwright/test'
|
|
7
|
+
import { MolliePaymentHandlerDocument } from '../components/MolliePaymentHandler/MolliePaymentHandler.gql'
|
|
8
|
+
|
|
9
|
+
const selectIdeal = async (page: Page) => {
|
|
10
|
+
await page.click('button[value=mollie_methods_ideal]')
|
|
11
|
+
|
|
12
|
+
// Select Rabobank
|
|
13
|
+
await page.selectOption('select[name="issuer"]', 'ideal_RABONL2U')
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type Statuses = 'paid' | 'failed' | 'canceled' | 'open' | 'expired'
|
|
17
|
+
|
|
18
|
+
const placeOrder = async (page: Page, status: Statuses) => {
|
|
19
|
+
await Promise.all([page.waitForNavigation(), page.click('#place-order')])
|
|
20
|
+
|
|
21
|
+
await page.click(`input[name="final_state"][value=${status}]`)
|
|
22
|
+
await Promise.all([page.waitForNavigation(), page.click('.footer button')])
|
|
23
|
+
|
|
24
|
+
const result = await waitForGraphQlResponse(page, MolliePaymentHandlerDocument)
|
|
25
|
+
expect(result.errors).toBeUndefined()
|
|
26
|
+
expect(result.data?.mollieProcessTransaction?.paymentStatus).toBe(status.toUpperCase())
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
test.describe('mollie ideal place order', () => {
|
|
30
|
+
test('CANCELED', async ({ page, productURL, apolloClient }) => {
|
|
31
|
+
await addConfigurableProductToCart(page, productURL.ConfigurableProduct)
|
|
32
|
+
await goToPayment(page, apolloClient)
|
|
33
|
+
await selectIdeal(page)
|
|
34
|
+
await placeOrder(page, 'canceled')
|
|
35
|
+
await placeOrder(page, 'paid')
|
|
36
|
+
expect(await page.locator('text=Back to home').innerText()).toBeDefined()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('OPEN', async ({ page, productURL, apolloClient }) => {
|
|
40
|
+
await addConfigurableProductToCart(page, productURL.ConfigurableProduct)
|
|
41
|
+
await goToPayment(page, apolloClient)
|
|
42
|
+
await selectIdeal(page)
|
|
43
|
+
await placeOrder(page, 'open')
|
|
44
|
+
await placeOrder(page, 'paid')
|
|
45
|
+
expect(await page.locator('text=Back to home').innerText()).toBeDefined()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('PAID', async ({ page, productURL, apolloClient }) => {
|
|
49
|
+
await addConfigurableProductToCart(page, productURL.ConfigurableProduct)
|
|
50
|
+
await goToPayment(page, apolloClient)
|
|
51
|
+
await selectIdeal(page)
|
|
52
|
+
await placeOrder(page, 'paid')
|
|
53
|
+
expect(await page.locator('text=Back to home').innerText()).toBeDefined()
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
test('Pressed back', async ({ page, productURL, apolloClient }) => {
|
|
57
|
+
await addConfigurableProductToCart(page, productURL.ConfigurableProduct)
|
|
58
|
+
await goToPayment(page, apolloClient)
|
|
59
|
+
await selectIdeal(page)
|
|
60
|
+
await Promise.all([page.waitForNavigation(), page.click('#place-order')])
|
|
61
|
+
|
|
62
|
+
await page.pause()
|
|
63
|
+
await page.goBack()
|
|
64
|
+
|
|
65
|
+
expect(await page.locator('text=Payment failed with status: OPEN').innerText()).toBeDefined()
|
|
66
|
+
|
|
67
|
+
await placeOrder(page, 'paid')
|
|
68
|
+
expect(await page.locator('text=Back to home').innerText()).toBeDefined()
|
|
69
|
+
})
|
|
70
|
+
})
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
|
-
import { waitForGraphQlResponse } from '@graphcommerce/graphql/_playwright/apolloClient.fixture'
|
|
3
|
-
import { fillShippingAddressForm } from '@graphcommerce/magento-cart-shipping-address/_playwright/fillShippingAddressForm'
|
|
4
|
-
import { fillCartAgreementsForm } from '@graphcommerce/magento-cart/_playwright/fillCartAgreementsForm'
|
|
5
|
-
import { addConfigurableProductToCart } from '@graphcommerce/magento-product-configurable/_playwright/addConfigurableProductToCart'
|
|
6
|
-
import { test } from '@graphcommerce/magento-product/_playwright/productURL.fixture'
|
|
7
|
-
import { expect, Page } from '@playwright/test'
|
|
8
|
-
import { MolliePlaceOrderDocument } from '../components/MolliePlaceOrder/MolliePlaceOrder.gql'
|
|
9
|
-
import { UseMolliePaymentTokenHandlerDocument } from '../hooks/UseMolliePaymentTokenHandler.gql'
|
|
10
|
-
|
|
11
|
-
const goToPayment = async (page: Page) => {
|
|
12
|
-
await page.click('a:has-text("View shopping cart")')
|
|
13
|
-
|
|
14
|
-
await page.click('a[href="/checkout"]:last-of-type')
|
|
15
|
-
|
|
16
|
-
await page.click('input[name="email"]')
|
|
17
|
-
await page.fill('input[name="email"]', 'test@test.com')
|
|
18
|
-
|
|
19
|
-
await fillShippingAddressForm(page)
|
|
20
|
-
|
|
21
|
-
await page.click('button[value=flatrate-flatrate]')
|
|
22
|
-
await page.click('button:has-text("Next")')
|
|
23
|
-
|
|
24
|
-
// Select the iDEAL option
|
|
25
|
-
await page.click('button[value=mollie_methods_ideal___]')
|
|
26
|
-
|
|
27
|
-
// Select Rabobank
|
|
28
|
-
await page.selectOption('select[name="issuer"]', 'ideal_RABONL2U')
|
|
29
|
-
|
|
30
|
-
await fillCartAgreementsForm(page)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
test.describe('mollie ideal place order', () => {
|
|
34
|
-
test('CANCELED', async ({ page, productURL }) => {
|
|
35
|
-
test.fixme()
|
|
36
|
-
await addConfigurableProductToCart(page, productURL.ConfigurableProduct)
|
|
37
|
-
await goToPayment(page)
|
|
38
|
-
|
|
39
|
-
// Place the order and wait for the the redirect to the new page.
|
|
40
|
-
await Promise.all([page.waitForNavigation(), page.click('button[name="placeOrder"]')])
|
|
41
|
-
|
|
42
|
-
// Let the order fail
|
|
43
|
-
await page.click('input[name="final_state"][value=canceled]')
|
|
44
|
-
|
|
45
|
-
// Return to the website.
|
|
46
|
-
await Promise.all([page.waitForNavigation(), page.click('.footer button')])
|
|
47
|
-
|
|
48
|
-
const result = await waitForGraphQlResponse(page, UseMolliePaymentTokenHandlerDocument)
|
|
49
|
-
expect(result.errors).toBeUndefined()
|
|
50
|
-
expect(result.data?.mollieProcessTransaction?.paymentStatus).toBe('CANCELED')
|
|
51
|
-
|
|
52
|
-
// Select Rabobank
|
|
53
|
-
await page.selectOption('select[name="issuer"]', 'ideal_RABONL2U')
|
|
54
|
-
|
|
55
|
-
// Place the order and wait for the the redirect to the new page.
|
|
56
|
-
await Promise.all([page.waitForNavigation(), page.click('button[name="placeOrder"]')])
|
|
57
|
-
|
|
58
|
-
const placeOrder = await waitForGraphQlResponse(page, MolliePlaceOrderDocument)
|
|
59
|
-
expect(placeOrder.errors).toBeUndefined()
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
test('PAID', async ({ page, productURL }) => {
|
|
63
|
-
await addConfigurableProductToCart(page, productURL.ConfigurableProduct)
|
|
64
|
-
await goToPayment(page)
|
|
65
|
-
|
|
66
|
-
await page.pause()
|
|
67
|
-
|
|
68
|
-
// Place the order and wait for the the redirect to the new page.
|
|
69
|
-
await Promise.all([page.waitForNavigation(), page.click('button[name="placeOrder"]')])
|
|
70
|
-
|
|
71
|
-
// Let the order fail
|
|
72
|
-
await page.click('input[name="final_state"][value=paid]')
|
|
73
|
-
|
|
74
|
-
// Return to the website.
|
|
75
|
-
await Promise.all([page.waitForNavigation(), page.click('.footer button')])
|
|
76
|
-
|
|
77
|
-
const result = await waitForGraphQlResponse(page, UseMolliePaymentTokenHandlerDocument)
|
|
78
|
-
expect(result.errors).toBeUndefined()
|
|
79
|
-
expect(result.data?.mollieProcessTransaction?.paymentStatus).toBe('PAID')
|
|
80
|
-
|
|
81
|
-
await page.waitForNavigation()
|
|
82
|
-
})
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
// test('place order failed', async ({ page, productURL }) => {
|
|
86
|
-
// await addConfigurableProductToCart(page, productURL.ConfigurableProduct)
|
|
87
|
-
// await goToPayment(page)
|
|
88
|
-
|
|
89
|
-
// // Place the order and wait for the the redirect to the new page.
|
|
90
|
-
// await Promise.all([page.waitForNavigation(), page.click('button[name="placeOrder"]')])
|
|
91
|
-
|
|
92
|
-
// // Let the order fail
|
|
93
|
-
// await page.click('input[name="final_state"][value=failed]')
|
|
94
|
-
|
|
95
|
-
// // Return to the website.
|
|
96
|
-
// await Promise.all([page.waitForNavigation(), page.click('.footer button')])
|
|
97
|
-
|
|
98
|
-
// const result = await waitForGraphQlResponse(page, UseMolliePaymentTokenHandlerDocument)
|
|
99
|
-
// expect(result.errors).toBeUndefined()
|
|
100
|
-
// expect(result.data?.mollieProcessTransaction?.paymentStatus).toBeDefined()
|
|
101
|
-
// })
|
package/hooks/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './useMolliePaymentTokenHandler'
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { useMutation , PaymentStatusEnum } from '@graphcommerce/graphql'
|
|
2
|
-
import { useClearCurrentCartId, useCurrentCartId } from '@graphcommerce/magento-cart'
|
|
3
|
-
import { useCartLock, usePaymentMethodContext } from '@graphcommerce/magento-cart-payment-method'
|
|
4
|
-
import { useRouter } from 'next/router'
|
|
5
|
-
import { useEffect } from 'react'
|
|
6
|
-
import { UseMolliePaymentTokenHandlerDocument } from './UseMolliePaymentTokenHandler.gql'
|
|
7
|
-
|
|
8
|
-
const successStatusses: PaymentStatusEnum[] = ['AUTHORIZED', 'COMPLETED', 'PAID', 'SHIPPING']
|
|
9
|
-
|
|
10
|
-
export function useMolliePaymentTokenHandler() {
|
|
11
|
-
const router = useRouter()
|
|
12
|
-
const method = usePaymentMethodContext()
|
|
13
|
-
const cartId = useCurrentCartId()
|
|
14
|
-
const clear = useClearCurrentCartId()
|
|
15
|
-
|
|
16
|
-
const isMollie = method.selectedMethod?.code.startsWith('mollie_methods')
|
|
17
|
-
|
|
18
|
-
const paymentToken = router.query.payment_token as string | undefined
|
|
19
|
-
// const orderHash = router.query.orderHash
|
|
20
|
-
const [handlePaymentToken, res] = useMutation(UseMolliePaymentTokenHandlerDocument, {
|
|
21
|
-
errorPolicy: 'all',
|
|
22
|
-
})
|
|
23
|
-
const { lock, locked } = useCartLock()
|
|
24
|
-
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
if (locked && !paymentToken && isMollie) lock(false)
|
|
27
|
-
}, [isMollie, lock, locked, paymentToken])
|
|
28
|
-
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
if (!paymentToken || res.called || res.error)
|
|
31
|
-
return // eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
32
|
-
;(async () => {
|
|
33
|
-
const result = await handlePaymentToken({ variables: { paymentToken } })
|
|
34
|
-
|
|
35
|
-
const paymentStatus = result.data?.mollieProcessTransaction?.paymentStatus
|
|
36
|
-
const returnedCartId = result.data?.mollieProcessTransaction?.cart?.id
|
|
37
|
-
|
|
38
|
-
if (result.errors || !paymentStatus) return
|
|
39
|
-
|
|
40
|
-
if (successStatusses.includes(paymentStatus)) {
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
42
|
-
await router.push({ pathname: '/checkout/success', query: { cartId } })
|
|
43
|
-
clear()
|
|
44
|
-
} else if (returnedCartId) {
|
|
45
|
-
lock(false)
|
|
46
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
47
|
-
router.replace('/checkout/payment')
|
|
48
|
-
} else {
|
|
49
|
-
throw Error('Mollie backend error occured')
|
|
50
|
-
}
|
|
51
|
-
})()
|
|
52
|
-
}, [
|
|
53
|
-
cartId,
|
|
54
|
-
clear,
|
|
55
|
-
handlePaymentToken,
|
|
56
|
-
isMollie,
|
|
57
|
-
lock,
|
|
58
|
-
paymentToken,
|
|
59
|
-
res.called,
|
|
60
|
-
res.error,
|
|
61
|
-
router,
|
|
62
|
-
])
|
|
63
|
-
|
|
64
|
-
return res
|
|
65
|
-
}
|