@graphcommerce/magento-payment-adyen 4.14.0-canary.3

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,7 @@
1
+ # @graphcommerce/magento-payment-adyen
2
+
3
+ ## 4.14.0-canary.3
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1729](https://github.com/graphcommerce-org/graphcommerce/pull/1729) [`2e68e0560`](https://github.com/graphcommerce-org/graphcommerce/commit/2e68e0560690bbf9bad6dc2b33d6e2ddb16197ce) - Adyen Payment gateway support ([@paales](https://github.com/paales))
package/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # Magento Payment Adyen
2
+
3
+ Integrates https://github.com/Adyen/adyen-magento2 with GraphCommerce.
4
+
5
+ We currently have 'Alternative Payment Methods' implemented, this means that it
6
+ supports all off-site payment methods that Adyen supports. This includes CC,
7
+ iDeal, Bancontact, Sofort, etc.
8
+
9
+ We do not support on-site credit cards yet. Let us know if you want to have
10
+ this.
11
+
12
+ ## Requirements
13
+
14
+ - Magento Adyen module version 8.5.0 or later
15
+
16
+ ## Installation
17
+
18
+ 1. Find current version of your `@graphcommerce/magento-cart-payment-method` in
19
+ your package.json.
20
+ 2. `yarn add @graphcommerce/magento-payment-adyen@1.2.3` (replace 1.2.3 with the
21
+ version of the step above)
22
+
23
+ 3. Configure the Adyen module in Magento Admin like you would normally do.
24
+ 4. Stores -> Configuration -> Sales -> Payment Methods -> Adyen Payment methods
25
+ -> Headless integration -> Payment Origin URL: `https://www.yourdomain.com`
26
+ 5. Stores -> Configuration -> Sales -> Payment Methods -> Adyen Payment methods
27
+ -> Headless integration -> Payment Return URL:
28
+ `https://www.yourdomain.com/checkout/payment?locked=1&adyen=1` (make sure the
29
+ URL's match for your storeview)
30
+
31
+ This package uses GraphCommerce plugin systems, so there is no code modification
32
+ required.
33
+
34
+ ## Known issues
35
+
36
+ - We don't need to configure the Payment URL's anymore since the 8.3.3 release
37
+ https://github.com/Adyen/adyen-magento2/releases/tag/8.3.3, but that isn't
38
+ integrated in the frontend yet.
39
+
40
+ - This package is currently untested inside the GraphCommerce repo, which it
41
+ should, but is used in production for multiple shops.
@@ -0,0 +1,34 @@
1
+ import { Image } from '@graphcommerce/image'
2
+ import { PaymentMethodActionCardProps } from '@graphcommerce/magento-cart-payment-method'
3
+ import { ActionCard, useIconSvgSize } from '@graphcommerce/next-ui'
4
+ import { Trans } from '@lingui/react'
5
+ import { useAdyenPaymentMethod } from '../../hooks/useAdyenPaymentMethod'
6
+
7
+ export function AdyenPaymentActionCard(props: PaymentMethodActionCardProps) {
8
+ const { child } = props
9
+ const iconSize = useIconSvgSize('large')
10
+
11
+ const icon = useAdyenPaymentMethod(child)?.icon
12
+
13
+ return (
14
+ <ActionCard
15
+ {...props}
16
+ details={child === 'ideal' && <Trans id='Pay with iDEAL' />}
17
+ image={
18
+ !!icon?.url &&
19
+ !!icon?.width &&
20
+ !!icon?.height && (
21
+ <Image
22
+ layout='fixed'
23
+ width={icon.width}
24
+ height={icon.height}
25
+ sx={{ width: `calc(${iconSize} / ${icon.height} * ${icon.width})`, height: iconSize }}
26
+ sizes={iconSize}
27
+ unoptimized
28
+ src={icon.url}
29
+ />
30
+ )
31
+ }
32
+ />
33
+ )
34
+ }
@@ -0,0 +1,5 @@
1
+ mutation AdyenPaymentDetails($cartId: String!, $payload: String!) {
2
+ adyenPaymentDetails(cart_id: $cartId, payload: $payload) {
3
+ ...AdyenPaymentResponse
4
+ }
5
+ }
@@ -0,0 +1,95 @@
1
+ import { useLazyQuery, useMutation } from '@graphcommerce/graphql'
2
+ import { useCurrentCartId } from '@graphcommerce/magento-cart'
3
+ import { ErrorSnackbar } from '@graphcommerce/next-ui'
4
+ import { Trans } from '@lingui/react'
5
+ import { useEffect } from 'react'
6
+ import { useAdyenCartLock } from '../../hooks/useAdyenCartLock'
7
+ import {
8
+ ResultCodeEnum,
9
+ useAdyenHandlePaymentResponse,
10
+ useAdyenPaymentResponse,
11
+ } from '../../hooks/useAdyenHandlePaymentResponse'
12
+ import { AdyenPaymentDetailsDocument } from './AdyenPaymentDetails.gql'
13
+ import { AdyenPaymentStatusDocument } from './AdyenPaymentStatus.gql'
14
+
15
+ export function AdyenPaymentHandler() {
16
+ const [lockStatus] = useAdyenCartLock()
17
+
18
+ const [getDetails, { called }] = useMutation(AdyenPaymentDetailsDocument)
19
+ const [getStatus] = useLazyQuery(AdyenPaymentStatusDocument, { fetchPolicy: 'network-only' })
20
+ const { currentCartId } = useCurrentCartId()
21
+
22
+ const handleResponse = useAdyenHandlePaymentResponse()
23
+ const response = useAdyenPaymentResponse()
24
+
25
+ // This is actually due to a bug.
26
+ const isAdyen = lockStatus.adyen?.split('?')[0] === '1'
27
+ const orderNumber = lockStatus.merchantReference ?? lockStatus.adyen?.split('?')[1]?.slice(18)
28
+ const { redirectResult } = lockStatus
29
+
30
+ useEffect(() => {
31
+ const call = async () => {
32
+ if (!orderNumber || !isAdyen || !currentCartId || called) return
33
+
34
+ const payload = JSON.stringify({ orderId: orderNumber, details: { redirectResult } })
35
+
36
+ // Atempt 1; We first try and handle the payment for the order.
37
+ const details = await getDetails({
38
+ errorPolicy: 'all',
39
+ variables: { cartId: currentCartId, payload },
40
+ })
41
+
42
+ let paymentStatus = details.data?.adyenPaymentDetails
43
+
44
+ // Atempt 2; The adyenPaymentDetails mutation failed, because it was already called previously or no payment had been made.
45
+ if (details.errors) {
46
+ const status = await getStatus({
47
+ errorPolicy: 'all',
48
+ variables: { cartId: currentCartId, orderNumber },
49
+ })
50
+ paymentStatus = status.data?.adyenPaymentStatus
51
+ }
52
+ handleResponse(paymentStatus)
53
+ }
54
+
55
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
56
+ call()
57
+ }, [
58
+ redirectResult,
59
+ getDetails,
60
+ orderNumber,
61
+ isAdyen,
62
+ getStatus,
63
+ called,
64
+ handleResponse,
65
+ currentCartId,
66
+ ])
67
+
68
+ if (!response?.resultCode) return null
69
+
70
+ if (response.resultCode === ResultCodeEnum.RedirectShopper) {
71
+ return (
72
+ <ErrorSnackbar open>
73
+ <Trans id="The payment hasn't completed, please try again or select a different payment method." />
74
+ </ErrorSnackbar>
75
+ )
76
+ }
77
+
78
+ if (response.resultCode === ResultCodeEnum.Refused) {
79
+ return (
80
+ <ErrorSnackbar open>
81
+ <Trans id='The payment is refused, please try again or select a different payment method.' />
82
+ </ErrorSnackbar>
83
+ )
84
+ }
85
+
86
+ return (
87
+ <ErrorSnackbar open>
88
+ <Trans
89
+ id='We can not process your payment, we received an unsupported status "<0>{resultCode}</0>". Please try again or select a different payment method.'
90
+ values={{ resultCode: response.resultCode }}
91
+ components={{ 0: <strong /> }}
92
+ />
93
+ </ErrorSnackbar>
94
+ )
95
+ }
@@ -0,0 +1,5 @@
1
+ query AdyenPaymentStatus($cartId: String!, $orderNumber: String!) {
2
+ adyenPaymentStatus(cartId: $cartId, orderNumber: $orderNumber) {
3
+ ...AdyenPaymentResponse
4
+ }
5
+ }
@@ -0,0 +1,29 @@
1
+ mutation AdyenPaymentOptionsAndPlaceOrder(
2
+ $cartId: String!
3
+ $brandCode: String!
4
+ $stateData: String!
5
+ ) {
6
+ setPaymentMethodOnCart(
7
+ input: {
8
+ cart_id: $cartId
9
+ payment_method: {
10
+ code: "adyen_hpp"
11
+ adyen_additional_data_hpp: { brand_code: $brandCode, stateData: $stateData }
12
+ }
13
+ }
14
+ ) {
15
+ cart {
16
+ selected_payment_method {
17
+ ...SelectedPaymentMethod
18
+ }
19
+ }
20
+ }
21
+ placeOrder(input: { cart_id: $cartId }) {
22
+ order {
23
+ order_number
24
+ adyen_payment_status {
25
+ ...AdyenPaymentResponse
26
+ }
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,106 @@
1
+ import { useFormCompose, useFormPersist, useFormValidFields } from '@graphcommerce/ecommerce-ui'
2
+ import { useFormGqlMutationCart } from '@graphcommerce/magento-cart'
3
+ import {
4
+ PaymentOptionsProps,
5
+ usePaymentMethodContext,
6
+ } from '@graphcommerce/magento-cart-payment-method'
7
+ import { FormRow, InputCheckmark } from '@graphcommerce/next-ui'
8
+ import { TextField } from '@mui/material'
9
+ import { useRouter } from 'next/router'
10
+ import { useAdyenCartLock } from '../../hooks/useAdyenCartLock'
11
+ import { useAdyenPaymentMethod } from '../../hooks/useAdyenPaymentMethod'
12
+ import {
13
+ AdyenPaymentOptionsAndPlaceOrderMutation,
14
+ AdyenPaymentOptionsAndPlaceOrderMutationVariables,
15
+ AdyenPaymentOptionsAndPlaceOrderDocument,
16
+ } from './AdyenPaymentOptionsAndPlaceOrder.gql'
17
+
18
+ /** It sets the selected payment method on the cart. */
19
+ export function HppOptions(props: PaymentOptionsProps) {
20
+ const { code, step, child: brandCode } = props
21
+
22
+ const conf = useAdyenPaymentMethod(brandCode)
23
+
24
+ const [, lock] = useAdyenCartLock()
25
+ const { selectedMethod } = usePaymentMethodContext()
26
+ const { push } = useRouter()
27
+
28
+ /**
29
+ * In the this folder you'll also find a PaymentMethodOptionsNoop.graphql document that is
30
+ * imported here and used as the basis for the form below.
31
+ */
32
+ const form = useFormGqlMutationCart<
33
+ AdyenPaymentOptionsAndPlaceOrderMutation,
34
+ AdyenPaymentOptionsAndPlaceOrderMutationVariables & { issuer?: string }
35
+ >(AdyenPaymentOptionsAndPlaceOrderDocument, {
36
+ onBeforeSubmit: (vars) => ({
37
+ ...vars,
38
+ stateData: JSON.stringify({
39
+ paymentMethod: { type: brandCode, issuer: vars.issuer },
40
+ clientStateDataIndicator: true,
41
+ }),
42
+ brandCode,
43
+ }),
44
+ onComplete: async (result) => {
45
+ const merchantReference = result.data?.placeOrder?.order.order_number
46
+ const action = result?.data?.placeOrder?.order.adyen_payment_status?.action
47
+
48
+ if (result.errors || !merchantReference || !selectedMethod?.code || !action) return
49
+
50
+ const url = JSON.parse(action).url as string
51
+ lock({ method: selectedMethod.code, adyen: '1', merchantReference })
52
+ await push(url)
53
+ },
54
+ })
55
+
56
+ const { handleSubmit, muiRegister, formState, required } = form
57
+
58
+ const submit = handleSubmit(() => {})
59
+
60
+ const key = `PaymentMethodOptions_${code}${brandCode}`
61
+ useFormPersist({ form, name: key, persist: ['issuer'], storage: 'localStorage' })
62
+
63
+ const valid = useFormValidFields(form, required)
64
+
65
+ /** To use an external Pay button we register the current form to be handled there as well. */
66
+ useFormCompose({ form, step, submit, key })
67
+
68
+ if (!conf?.issuers?.length) return <form onSubmit={submit} noValidate />
69
+
70
+ /** This is the form that the user can fill in. In this case we don't wat the user to fill in anything. */
71
+ return (
72
+ <form key={key} onSubmit={submit} noValidate>
73
+ {conf?.issuers && (
74
+ <FormRow>
75
+ <TextField
76
+ defaultValue=''
77
+ variant='outlined'
78
+ color='secondary'
79
+ select
80
+ SelectProps={{ native: true, displayEmpty: true }}
81
+ error={formState.isSubmitted && !!formState.errors.issuer}
82
+ helperText={formState.isSubmitted && formState.errors.issuer?.message}
83
+ label={brandCode === 'ideal' ? 'Select your bank' : conf?.name}
84
+ required
85
+ {...muiRegister('issuer', {
86
+ required: { value: true, message: 'Please provide an issuer' },
87
+ })}
88
+ InputProps={{ endAdornment: <InputCheckmark show={valid.issuer} select /> }}
89
+ >
90
+ {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */}
91
+ <option value='' />
92
+ {conf.issuers.map((issuer) => {
93
+ if (!issuer?.id || !issuer.name) return null
94
+
95
+ return (
96
+ <option key={issuer.id} value={issuer.id}>
97
+ {issuer.name}
98
+ </option>
99
+ )
100
+ })}
101
+ </TextField>
102
+ </FormRow>
103
+ )}
104
+ </form>
105
+ )
106
+ }
@@ -0,0 +1,6 @@
1
+ fragment AdyenPaymentResponse on AdyenPaymentStatus {
2
+ action
3
+ additionalData
4
+ isFinal
5
+ resultCode
6
+ }
@@ -0,0 +1,46 @@
1
+ query UseAdyenPaymentMethods($cartId: String!) {
2
+ adyenPaymentMethods(cart_id: $cartId) {
3
+ paymentMethodsExtraDetails {
4
+ type
5
+ isOpenInvoice
6
+ configuration {
7
+ currency
8
+ amount {
9
+ currency
10
+ value
11
+ }
12
+ }
13
+ icon {
14
+ height
15
+ url
16
+ width
17
+ }
18
+ }
19
+ paymentMethodsResponse {
20
+ paymentMethods {
21
+ brand
22
+ brands
23
+ configuration {
24
+ merchantId
25
+ merchantName
26
+ }
27
+ details {
28
+ items {
29
+ id
30
+ name
31
+ }
32
+ key
33
+ optional
34
+ type
35
+ value
36
+ }
37
+ issuers {
38
+ id
39
+ name
40
+ }
41
+ name
42
+ type
43
+ }
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,24 @@
1
+ import { ExpandPaymentMethods } from '@graphcommerce/magento-cart-payment-method'
2
+ import { UseAdyenPaymentMethodsDocument } from './UseAdyenPaymentMethods.gql'
3
+
4
+ export const nonNullable = <T>(value: T): value is NonNullable<T> =>
5
+ value !== null && value !== undefined
6
+
7
+ export const adyenHppExpandMethods: ExpandPaymentMethods = async (available, context) => {
8
+ if (!context.id) return []
9
+
10
+ const result = await context.client.query({
11
+ query: UseAdyenPaymentMethodsDocument,
12
+ variables: { cartId: context.id },
13
+ })
14
+
15
+ const methods = result.data.adyenPaymentMethods?.paymentMethodsResponse?.paymentMethods ?? []
16
+
17
+ return methods
18
+ .map((method) => {
19
+ if (!method?.name || !method.type) return null
20
+
21
+ return { title: method.name, code: available.code, child: method.type }
22
+ })
23
+ .filter(nonNullable)
24
+ }
@@ -0,0 +1,14 @@
1
+ import { CartLockState, useCartLock } from '@graphcommerce/magento-cart-payment-method'
2
+
3
+ type AdyenLockState = CartLockState & {
4
+ adyen: string | null
5
+ merchantReference?: string | null
6
+ redirectResult?: string | null
7
+ }
8
+
9
+ /**
10
+ * The cart lock situation is a bit odd since are unable to actually influence the return URL we 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 ID is not available.
13
+ */
14
+ export const useAdyenCartLock = () => useCartLock<AdyenLockState>()
@@ -0,0 +1,122 @@
1
+ import type { Types } from '@adyen/api-library'
2
+ import { makeVar, useReactiveVar } from '@graphcommerce/graphql'
3
+ import { useClearCurrentCartId, useCurrentCartId } from '@graphcommerce/magento-cart'
4
+ import { useEventCallback } from '@mui/material'
5
+ import { useRouter } from 'next/router'
6
+ import { AdyenPaymentResponseFragment } from './AdyenPaymentResponse.gql'
7
+ import { useAdyenCartLock } from './useAdyenCartLock'
8
+
9
+ export enum ResultCodeEnum {
10
+ AuthenticationFinished = 'AuthenticationFinished',
11
+ Authorised = 'Authorised',
12
+ Cancelled = 'Cancelled',
13
+ ChallengeShopper = 'ChallengeShopper',
14
+ Error = 'Error',
15
+ IdentifyShopper = 'IdentifyShopper',
16
+ Pending = 'Pending',
17
+ PresentToShopper = 'PresentToShopper',
18
+ Received = 'Received',
19
+ RedirectShopper = 'RedirectShopper',
20
+ Refused = 'Refused',
21
+ Success = 'Success',
22
+ }
23
+
24
+ function isResultCodeEnum(value: string): value is ResultCodeEnum {
25
+ return Object.values(ResultCodeEnum).includes(value as ResultCodeEnum)
26
+ }
27
+
28
+ export type AdyenPaymentResponse = {
29
+ isFinal: boolean
30
+ resultCode: ResultCodeEnum
31
+ action?: Types.checkout.PaymentResponse['action']
32
+ additionalData?: Types.checkout.PaymentResponse['additionalData']
33
+ }
34
+
35
+ export function parsePaymentResponse(
36
+ status?: AdyenPaymentResponseFragment | null,
37
+ ): AdyenPaymentResponse {
38
+ if (!status?.resultCode) return { isFinal: false, resultCode: ResultCodeEnum.Error }
39
+
40
+ const { isFinal, resultCode, action, additionalData } = status
41
+
42
+ if (!isResultCodeEnum(resultCode) && process.env.NODE_ENV !== 'production')
43
+ throw Error(
44
+ `Returned resultCode ${resultCode} is not in available resultCodes: ${Object.values(
45
+ ResultCodeEnum,
46
+ )}`,
47
+ )
48
+
49
+ const response: AdyenPaymentResponse = {
50
+ isFinal: Boolean(isFinal),
51
+ // todo: do we need to check if these values are actually valid?
52
+ resultCode: isResultCodeEnum(resultCode) ? resultCode : ResultCodeEnum.Error,
53
+ }
54
+
55
+ if (action) {
56
+ try {
57
+ response.action = JSON.parse(action)
58
+ } catch (e) {
59
+ if (process.env.NODE_ENV !== 'production') {
60
+ throw Error('Could not parse AdyenPaymentStatusResult.action as JSON')
61
+ }
62
+ if (process.env.NODE_ENV === 'production') {
63
+ response.isFinal = false
64
+ response.resultCode = ResultCodeEnum.Error
65
+ }
66
+ }
67
+ }
68
+
69
+ if (additionalData) {
70
+ try {
71
+ response.additionalData = JSON.parse(additionalData)
72
+ } catch (e) {
73
+ if (process.env.NODE_ENV !== 'production') {
74
+ throw Error('Could not parse AdyenPaymentStatusResult.additionalData as JSON')
75
+ }
76
+ if (process.env.NODE_ENV === 'production') {
77
+ response.isFinal = false
78
+ response.resultCode = ResultCodeEnum.Error
79
+ }
80
+ }
81
+ }
82
+
83
+ return response
84
+ }
85
+
86
+ const paymentResult = makeVar<AdyenPaymentResponse | undefined>(undefined)
87
+
88
+ export const useAdyenPaymentResponse = () => useReactiveVar(paymentResult)
89
+
90
+ export function useAdyenHandlePaymentResponse() {
91
+ const clearCurrentCartId = useClearCurrentCartId()
92
+ const { currentCartId } = useCurrentCartId()
93
+ const { push } = useRouter()
94
+ const [, , unlockAdyen] = useAdyenCartLock()
95
+
96
+ const unlock = () => unlockAdyen({ adyen: null, redirectResult: null })
97
+
98
+ return useEventCallback((status?: AdyenPaymentResponseFragment | null) => {
99
+ const parsedResponse = parsePaymentResponse(status)
100
+ const resultCode = parsedResponse?.resultCode
101
+
102
+ // https://github.com/Adyen/adyen-magento2/blob/f814d4c095b04d775faced7bdad8f10866354612/Helper/PaymentResponseHandler.php#L91
103
+ switch (resultCode) {
104
+ case ResultCodeEnum.RedirectShopper:
105
+ case ResultCodeEnum.Refused:
106
+ case ResultCodeEnum.Pending:
107
+ case ResultCodeEnum.Error:
108
+ unlock()
109
+ break
110
+ case ResultCodeEnum.Authorised:
111
+ clearCurrentCartId()
112
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
113
+ push({ pathname: '/checkout/success', query: { cart_id: currentCartId } })
114
+ break
115
+ default:
116
+ if (process.env.NODE_ENV !== 'production') {
117
+ throw Error(`Unknown resultCode: ${resultCode}`)
118
+ }
119
+ }
120
+ paymentResult(parsedResponse)
121
+ })
122
+ }
@@ -0,0 +1,31 @@
1
+ import { useCartQuery } from '@graphcommerce/magento-cart'
2
+ import { useMemo } from 'react'
3
+ import { UseAdyenPaymentMethodsDocument } from './UseAdyenPaymentMethods.gql'
4
+
5
+ export function useAdyenPaymentMethod(brandCode: string) {
6
+ const methods = useCartQuery(UseAdyenPaymentMethodsDocument)
7
+
8
+ const result = useMemo(() => {
9
+ const config = methods.data?.adyenPaymentMethods?.paymentMethodsExtraDetails?.find(
10
+ (extra) => extra?.type === brandCode,
11
+ )
12
+
13
+ const methodConf =
14
+ methods.data?.adyenPaymentMethods?.paymentMethodsResponse?.paymentMethods?.find(
15
+ (extra) => extra?.type === brandCode,
16
+ )
17
+
18
+ if (!methodConf || !config) return undefined
19
+
20
+ return {
21
+ ...methodConf,
22
+ ...config,
23
+ }
24
+ }, [
25
+ brandCode,
26
+ methods.data?.adyenPaymentMethods?.paymentMethodsExtraDetails,
27
+ methods.data?.adyenPaymentMethods?.paymentMethodsResponse?.paymentMethods,
28
+ ])
29
+
30
+ return result
31
+ }
package/index.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { PaymentModule } from '@graphcommerce/magento-cart-payment-method'
2
+ import { AdyenPaymentActionCard } from './components/AdyenPaymentActionCard/AdyenPaymentActionCard'
3
+ import { AdyenPaymentHandler } from './components/AdyenPaymentHandler/AdyenPaymentHandler'
4
+ import { HppOptions } from './components/AdyenPaymentOptionsAndPlaceOrder/AdyenPaymentOptionsAndPlaceOrder'
5
+ import { adyenHppExpandMethods } from './hooks/adyenHppExpandMethods'
6
+
7
+ export const adyen_hpp: PaymentModule = {
8
+ PaymentOptions: HppOptions,
9
+ PaymentPlaceOrder: () => null,
10
+ PaymentHandler: AdyenPaymentHandler,
11
+ PaymentActionCard: AdyenPaymentActionCard,
12
+ expandMethods: adyenHppExpandMethods,
13
+ }
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-adyen",
3
+ "homepage": "https://www.graphcommerce.org/",
4
+ "repository": "github:graphcommerce-org/graphcommerce",
5
+ "version": "4.14.0-canary.3",
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.2",
16
+ "@graphcommerce/eslint-config-pwa": "^4.1.11",
17
+ "@graphcommerce/magento-cart-shipping-address": "4.14.0-canary.3",
18
+ "@graphcommerce/magento-product": "4.14.0-canary.3",
19
+ "@graphcommerce/magento-product-configurable": "4.14.0-canary.3",
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.2",
27
+ "@graphcommerce/graphql-mesh": "4.31.0-canary.2",
28
+ "@graphcommerce/image": "4.31.0-canary.2",
29
+ "@graphcommerce/magento-cart": "4.14.0-canary.3",
30
+ "@graphcommerce/magento-cart-payment-method": "4.14.0-canary.3",
31
+ "@graphcommerce/magento-store": "4.14.0-canary.3",
32
+ "@graphcommerce/next-ui": "4.31.0-canary.2",
33
+ "@graphcommerce/react-hook-form": "4.31.0-canary.2"
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,27 @@
1
+ import {
2
+ PaymentMethodContextProviderProps,
3
+ PaymentModule,
4
+ } from '@graphcommerce/magento-cart-payment-method'
5
+ import type { PluginProps } from '@graphcommerce/next-config'
6
+ import { AdyenPaymentActionCard } from '../components/AdyenPaymentActionCard/AdyenPaymentActionCard'
7
+ import { AdyenPaymentHandler } from '../components/AdyenPaymentHandler/AdyenPaymentHandler'
8
+ import { HppOptions } from '../components/AdyenPaymentOptionsAndPlaceOrder/AdyenPaymentOptionsAndPlaceOrder'
9
+ import { adyenHppExpandMethods } from '../hooks/adyenHppExpandMethods'
10
+
11
+ export const adyen_hpp: PaymentModule = {
12
+ PaymentOptions: HppOptions,
13
+ PaymentPlaceOrder: () => null,
14
+ PaymentHandler: AdyenPaymentHandler,
15
+ PaymentActionCard: AdyenPaymentActionCard,
16
+ expandMethods: adyenHppExpandMethods,
17
+ }
18
+
19
+ export const component = 'PaymentMethodContextProvider'
20
+ export const exported = '@graphcommerce/magento-cart-payment-method'
21
+
22
+ function AddAdyenMethods(props: PluginProps<PaymentMethodContextProviderProps>) {
23
+ const { modules, Component } = props
24
+ return <Component {...props} modules={{ ...modules, adyen_hpp }} />
25
+ }
26
+
27
+ export const Plugin = AddAdyenMethods
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
+ }