@graphcommerce/mollie-magento-payment 3.0.6 → 3.1.0

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 CHANGED
@@ -1,5 +1,24 @@
1
1
  # Change Log
2
2
 
3
+ ## 3.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#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
8
+
9
+ ### Patch Changes
10
+
11
+ - [#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
12
+
13
+ - 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)]:
14
+ - @graphcommerce/graphql@3.0.6
15
+ - @graphcommerce/next-ui@4.5.0
16
+ - @graphcommerce/image@3.1.2
17
+ - @graphcommerce/magento-cart@4.2.2
18
+ - @graphcommerce/magento-cart-payment-method@3.0.6
19
+ - @graphcommerce/magento-store@4.1.4
20
+ - @graphcommerce/react-hook-form@3.0.6
21
+
3
22
  ## 3.0.6
4
23
 
5
24
  ### Patch Changes
@@ -2,11 +2,7 @@ fragment MollieAvailablePaymentMethod on AvailablePaymentMethod
2
2
  @inject(into: ["AvailablePaymentMethod"]) {
3
3
  mollie_available_issuers {
4
4
  code
5
- image
6
5
  name
7
6
  svg
8
7
  }
9
- mollie_meta {
10
- image
11
- }
12
8
  }
@@ -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,25 +59,13 @@ 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>
@@ -0,0 +1,8 @@
1
+ mutation MolliePaymentHandler($mollie_payment_token: String!) {
2
+ mollieProcessTransaction(input: { payment_token: $mollie_payment_token }) {
3
+ cart {
4
+ id
5
+ }
6
+ paymentStatus
7
+ }
8
+ }
@@ -1,34 +1,102 @@
1
- import { ApolloCartErrorFullPage, useClearCurrentCartId } from '@graphcommerce/magento-cart'
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 React from 'react'
5
- import { useMolliePaymentTokenHandler } from '../../hooks/useMolliePaymentTokenHandler'
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 handle = () => {
13
- clear()
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
- router.push('/')
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 variant='contained' color='primary' size='large' onClick={handle}>
26
- Reset Cart and Return to home
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
- If you’ve successfully paid your order, the order <strong>will</strong> come through, but
31
- there is a communication error with the website.
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
  )
@@ -0,0 +1,7 @@
1
+ mutation MollieRecoverCart($cartId: String!) {
2
+ mollieRestoreCart(input: { cart_id: $cartId }) {
3
+ cart {
4
+ id
5
+ }
6
+ }
7
+ }
@@ -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 { mollie_meta, title } = props
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
- &nbsp;
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, useCartLock } from '@graphcommerce/magento-cart-payment-method'
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 router = useRouter()
15
+ const { push } = useRouter()
15
16
  const cartId = useCurrentCartId()
16
- const clear = useClearCurrentCartId()
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('payment_token', 'PAYMENT_TOKEN')
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 molliePaymentToken = data?.placeOrder?.order.mollie_payment_token
37
+ const mollie_payment_token = data?.placeOrder?.order.mollie_payment_token
36
38
 
37
- if (redirectUrl) {
38
- lock(true)
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
- router.push({ pathname: '/checkout/success', query: { cartId, molliePaymentToken } })
43
+ push(redirectUrl)
49
44
  }
50
- }, [cartId, clear, data?.placeOrder?.order, error, lock, router])
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,3 +1,2 @@
1
- export * from './hooks'
2
1
  export * as mollie_methods from './methods'
3
2
  export * from './components/MolliePaymentToggle/MolliePaymentToggle'
@@ -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: MollieCreditCardOptions,
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.0.6",
5
+ "version": "3.1.0",
6
6
  "sideEffects": false,
7
7
  "engines": {
8
8
  "node": "14.x"
@@ -15,23 +15,23 @@
15
15
  }
16
16
  },
17
17
  "devDependencies": {
18
- "@graphcommerce/eslint-config-pwa": "^4.1.2",
19
- "@graphcommerce/magento-cart-shipping-address": "^3.0.4",
20
- "@graphcommerce/magento-product": "^4.1.2",
21
- "@graphcommerce/magento-product-configurable": "^4.0.6",
22
- "@graphcommerce/prettier-config-pwa": "^4.0.3",
18
+ "@graphcommerce/eslint-config-pwa": "^4.1.3",
19
+ "@graphcommerce/magento-cart-shipping-address": "^3.0.5",
20
+ "@graphcommerce/magento-product": "^4.1.3",
21
+ "@graphcommerce/magento-product-configurable": "^4.0.7",
22
+ "@graphcommerce/prettier-config-pwa": "^4.0.5",
23
23
  "@graphcommerce/typescript-config-pwa": "^4.0.2",
24
- "@playwright/test": "^1.19.2"
24
+ "@playwright/test": "^1.20.1",
25
+ "type-fest": "2.12.1"
25
26
  },
26
27
  "dependencies": {
27
- "@graphcommerce/graphql": "^3.0.4",
28
- "@graphcommerce/image": "^3.1.1",
29
- "@graphcommerce/magento-cart": "^4.2.1",
30
- "@graphcommerce/magento-cart-payment-method": "^3.0.5",
31
- "@graphcommerce/magento-store": "^4.1.2",
32
- "@graphcommerce/next-ui": "^4.4.0",
33
- "@graphcommerce/react-hook-form": "^3.0.4",
34
- "type-fest": "^2.12.0"
28
+ "@graphcommerce/graphql": "^3.0.6",
29
+ "@graphcommerce/image": "^3.1.2",
30
+ "@graphcommerce/magento-cart": "^4.2.2",
31
+ "@graphcommerce/magento-cart-payment-method": "^3.0.6",
32
+ "@graphcommerce/magento-store": "^4.1.4",
33
+ "@graphcommerce/next-ui": "^4.5.0",
34
+ "@graphcommerce/react-hook-form": "^3.0.6"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@lingui/macro": "^3.13.2",
@@ -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,6 +0,0 @@
1
- fragment MollieSelectedPaymentMethod on SelectedPaymentMethod
2
- @inject(into: ["SelectedPaymentMethod"]) {
3
- mollie_meta {
4
- image
5
- }
6
- }
@@ -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
- // })
@@ -1,8 +0,0 @@
1
- mutation UseMolliePaymentTokenHandler($paymentToken: String!) {
2
- mollieProcessTransaction(input: { payment_token: $paymentToken }) {
3
- cart {
4
- id
5
- }
6
- paymentStatus
7
- }
8
- }
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
- }