@akinon/pz-gpay 1.15.0 → 1.16.1
Sign up to get free protection for your applications and to get access to all the features.
- package/.gitattributes +15 -15
- package/.prettierrc +13 -13
- package/CHANGELOG.md +4 -0
- package/package.json +1 -1
- package/readme.md +38 -38
- package/src/endpoints.ts +45 -45
- package/src/index.tsx +1 -1
- package/src/routes/garanti-pay-redirect.tsx +29 -29
- package/src/views/gpay-option.tsx +111 -111
package/.gitattributes
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
*.js text eol=lf
|
2
|
-
*.jsx text eol=lf
|
3
|
-
*.ts text eol=lf
|
4
|
-
*.tsx text eol=lf
|
5
|
-
*.json text eol=lf
|
6
|
-
*.md text eol=lf
|
7
|
-
|
8
|
-
.eslintignore text eol=lf
|
9
|
-
.eslintrc text eol=lf
|
10
|
-
.gitignore text eol=lf
|
11
|
-
.prettierrc text eol=lf
|
12
|
-
.yarnrc text eol=lf
|
13
|
-
|
14
|
-
* text=auto
|
15
|
-
|
1
|
+
*.js text eol=lf
|
2
|
+
*.jsx text eol=lf
|
3
|
+
*.ts text eol=lf
|
4
|
+
*.tsx text eol=lf
|
5
|
+
*.json text eol=lf
|
6
|
+
*.md text eol=lf
|
7
|
+
|
8
|
+
.eslintignore text eol=lf
|
9
|
+
.eslintrc text eol=lf
|
10
|
+
.gitignore text eol=lf
|
11
|
+
.prettierrc text eol=lf
|
12
|
+
.yarnrc text eol=lf
|
13
|
+
|
14
|
+
* text=auto
|
15
|
+
|
package/.prettierrc
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
{
|
2
|
-
"bracketSameLine": false,
|
3
|
-
"tabWidth": 2,
|
4
|
-
"singleQuote": true,
|
5
|
-
"jsxSingleQuote": false,
|
6
|
-
"bracketSpacing": true,
|
7
|
-
"semi": true,
|
8
|
-
"useTabs": false,
|
9
|
-
"arrowParens": "always",
|
10
|
-
"endOfLine": "lf",
|
11
|
-
"proseWrap": "never",
|
12
|
-
"trailingComma": "none"
|
13
|
-
}
|
1
|
+
{
|
2
|
+
"bracketSameLine": false,
|
3
|
+
"tabWidth": 2,
|
4
|
+
"singleQuote": true,
|
5
|
+
"jsxSingleQuote": false,
|
6
|
+
"bracketSpacing": true,
|
7
|
+
"semi": true,
|
8
|
+
"useTabs": false,
|
9
|
+
"arrowParens": "always",
|
10
|
+
"endOfLine": "lf",
|
11
|
+
"proseWrap": "never",
|
12
|
+
"trailingComma": "none"
|
13
|
+
}
|
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
package/readme.md
CHANGED
@@ -1,38 +1,38 @@
|
|
1
|
-
# pz-gpay
|
2
|
-
|
3
|
-
### Example Usage
|
4
|
-
##### File Path: src/views/checkout/steps/payment/options/gpay.tsx
|
5
|
-
|
6
|
-
```javascript
|
7
|
-
import { GPayOption } from '@akinon/pz-gpay';
|
8
|
-
|
9
|
-
export default function GPay() {
|
10
|
-
return (
|
11
|
-
<GPayOption
|
12
|
-
translations={{
|
13
|
-
title: 'Pay with GarantiPay',
|
14
|
-
description:
|
15
|
-
'Click the button below to pay for your order using GarantiPay.',
|
16
|
-
button: 'Pay Now'
|
17
|
-
}}
|
18
|
-
titleClassName="text-4xl"
|
19
|
-
/>
|
20
|
-
);
|
21
|
-
}
|
22
|
-
```
|
23
|
-
|
24
|
-
##### File Path: src/app/[commerce]/[locale]/[currency]/orders/garanti-pay-redirect/page.tsx
|
25
|
-
|
26
|
-
```javascript
|
27
|
-
import { GarantiPayRedirect } from '@akinon/pz-gpay/src/routes/garanti-pay-redirect';
|
28
|
-
|
29
|
-
export default GarantiPayRedirect;
|
30
|
-
```
|
31
|
-
|
32
|
-
### Props
|
33
|
-
| Properties | Type | Description |
|
34
|
-
|----------------------|--------|--------------------------------------------|
|
35
|
-
| translations | object | The translations of the component. |
|
36
|
-
| titleClassName | string | The CSS class to apply to the title. |
|
37
|
-
| descriptionClassName | string | The CSS class to apply to the description. |
|
38
|
-
| buttonClassName | string | The CSS class to apply to the button. |
|
1
|
+
# pz-gpay
|
2
|
+
|
3
|
+
### Example Usage
|
4
|
+
##### File Path: src/views/checkout/steps/payment/options/gpay.tsx
|
5
|
+
|
6
|
+
```javascript
|
7
|
+
import { GPayOption } from '@akinon/pz-gpay';
|
8
|
+
|
9
|
+
export default function GPay() {
|
10
|
+
return (
|
11
|
+
<GPayOption
|
12
|
+
translations={{
|
13
|
+
title: 'Pay with GarantiPay',
|
14
|
+
description:
|
15
|
+
'Click the button below to pay for your order using GarantiPay.',
|
16
|
+
button: 'Pay Now'
|
17
|
+
}}
|
18
|
+
titleClassName="text-4xl"
|
19
|
+
/>
|
20
|
+
);
|
21
|
+
}
|
22
|
+
```
|
23
|
+
|
24
|
+
##### File Path: src/app/[commerce]/[locale]/[currency]/orders/garanti-pay-redirect/page.tsx
|
25
|
+
|
26
|
+
```javascript
|
27
|
+
import { GarantiPayRedirect } from '@akinon/pz-gpay/src/routes/garanti-pay-redirect';
|
28
|
+
|
29
|
+
export default GarantiPayRedirect;
|
30
|
+
```
|
31
|
+
|
32
|
+
### Props
|
33
|
+
| Properties | Type | Description |
|
34
|
+
|----------------------|--------|--------------------------------------------|
|
35
|
+
| translations | object | The translations of the component. |
|
36
|
+
| titleClassName | string | The CSS class to apply to the title. |
|
37
|
+
| descriptionClassName | string | The CSS class to apply to the description. |
|
38
|
+
| buttonClassName | string | The CSS class to apply to the button. |
|
package/src/endpoints.ts
CHANGED
@@ -1,45 +1,45 @@
|
|
1
|
-
import { CheckoutContext, PreOrder } from '@akinon/next/types';
|
2
|
-
import { api } from '@akinon/next/data/client/api';
|
3
|
-
import { buildClientRequestUrl } from '@akinon/next/utils';
|
4
|
-
import { setPaymentStepBusy } from '@akinon/next/redux/reducers/checkout';
|
5
|
-
|
6
|
-
interface CheckoutResponse {
|
7
|
-
pre_order?: PreOrder;
|
8
|
-
errors: {
|
9
|
-
non_field_errors: string;
|
10
|
-
};
|
11
|
-
context_list?: CheckoutContext[];
|
12
|
-
template_name?: string;
|
13
|
-
redirect_url?: string;
|
14
|
-
}
|
15
|
-
|
16
|
-
export const gpayApi = api.injectEndpoints({
|
17
|
-
endpoints: (build) => ({
|
18
|
-
setGPayMethod: build.mutation<CheckoutResponse, void>({
|
19
|
-
query: () => ({
|
20
|
-
url: buildClientRequestUrl(`/orders/checkout?page=GPaySelectionPage`),
|
21
|
-
method: 'POST',
|
22
|
-
body: {}
|
23
|
-
}),
|
24
|
-
async onQueryStarted(arg, { dispatch, queryFulfilled }) {
|
25
|
-
dispatch(setPaymentStepBusy(true));
|
26
|
-
await queryFulfilled;
|
27
|
-
dispatch(setPaymentStepBusy(false));
|
28
|
-
}
|
29
|
-
}),
|
30
|
-
setCompleteGPay: build.mutation<CheckoutResponse, void>({
|
31
|
-
query: () => ({
|
32
|
-
url: buildClientRequestUrl(`/orders/checkout?page=GPayRedirectPage`),
|
33
|
-
method: 'POST',
|
34
|
-
body: {}
|
35
|
-
}),
|
36
|
-
async onQueryStarted(arg, { dispatch, queryFulfilled }) {
|
37
|
-
dispatch(setPaymentStepBusy(true));
|
38
|
-
await queryFulfilled;
|
39
|
-
dispatch(setPaymentStepBusy(false));
|
40
|
-
}
|
41
|
-
})
|
42
|
-
})
|
43
|
-
});
|
44
|
-
|
45
|
-
export const { useSetGPayMethodMutation, useSetCompleteGPayMutation } = gpayApi;
|
1
|
+
import { CheckoutContext, PreOrder } from '@akinon/next/types';
|
2
|
+
import { api } from '@akinon/next/data/client/api';
|
3
|
+
import { buildClientRequestUrl } from '@akinon/next/utils';
|
4
|
+
import { setPaymentStepBusy } from '@akinon/next/redux/reducers/checkout';
|
5
|
+
|
6
|
+
interface CheckoutResponse {
|
7
|
+
pre_order?: PreOrder;
|
8
|
+
errors: {
|
9
|
+
non_field_errors: string;
|
10
|
+
};
|
11
|
+
context_list?: CheckoutContext[];
|
12
|
+
template_name?: string;
|
13
|
+
redirect_url?: string;
|
14
|
+
}
|
15
|
+
|
16
|
+
export const gpayApi = api.injectEndpoints({
|
17
|
+
endpoints: (build) => ({
|
18
|
+
setGPayMethod: build.mutation<CheckoutResponse, void>({
|
19
|
+
query: () => ({
|
20
|
+
url: buildClientRequestUrl(`/orders/checkout?page=GPaySelectionPage`),
|
21
|
+
method: 'POST',
|
22
|
+
body: {}
|
23
|
+
}),
|
24
|
+
async onQueryStarted(arg, { dispatch, queryFulfilled }) {
|
25
|
+
dispatch(setPaymentStepBusy(true));
|
26
|
+
await queryFulfilled;
|
27
|
+
dispatch(setPaymentStepBusy(false));
|
28
|
+
}
|
29
|
+
}),
|
30
|
+
setCompleteGPay: build.mutation<CheckoutResponse, void>({
|
31
|
+
query: () => ({
|
32
|
+
url: buildClientRequestUrl(`/orders/checkout?page=GPayRedirectPage`),
|
33
|
+
method: 'POST',
|
34
|
+
body: {}
|
35
|
+
}),
|
36
|
+
async onQueryStarted(arg, { dispatch, queryFulfilled }) {
|
37
|
+
dispatch(setPaymentStepBusy(true));
|
38
|
+
await queryFulfilled;
|
39
|
+
dispatch(setPaymentStepBusy(false));
|
40
|
+
}
|
41
|
+
})
|
42
|
+
})
|
43
|
+
});
|
44
|
+
|
45
|
+
export const { useSetGPayMethodMutation, useSetCompleteGPayMutation } = gpayApi;
|
package/src/index.tsx
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export * from './views/gpay-option';
|
1
|
+
export * from './views/gpay-option';
|
@@ -1,29 +1,29 @@
|
|
1
|
-
import { cookies } from 'next/headers';
|
2
|
-
import settings from 'settings';
|
3
|
-
import { redirect } from 'next/navigation';
|
4
|
-
import { ROUTES } from 'routes';
|
5
|
-
|
6
|
-
export const GarantiPayRedirect = async () => {
|
7
|
-
const nextCookies = cookies();
|
8
|
-
const sessionId = nextCookies.get('osessionid')?.value;
|
9
|
-
|
10
|
-
if (!sessionId) {
|
11
|
-
return redirect(ROUTES.CHECKOUT);
|
12
|
-
}
|
13
|
-
|
14
|
-
const commerceUrl = settings.commerceUrl;
|
15
|
-
|
16
|
-
const response = await fetch(`${commerceUrl}/orders/garanti-pay-redirect`, {
|
17
|
-
headers: {
|
18
|
-
Cookie: nextCookies.toString()
|
19
|
-
}
|
20
|
-
});
|
21
|
-
|
22
|
-
const data = await response.text();
|
23
|
-
|
24
|
-
if (!data.includes('form3D')) {
|
25
|
-
return redirect(ROUTES.CHECKOUT);
|
26
|
-
}
|
27
|
-
|
28
|
-
return <div dangerouslySetInnerHTML={{ __html: data }}></div>;
|
29
|
-
};
|
1
|
+
import { cookies } from 'next/headers';
|
2
|
+
import settings from 'settings';
|
3
|
+
import { redirect } from 'next/navigation';
|
4
|
+
import { ROUTES } from 'routes';
|
5
|
+
|
6
|
+
export const GarantiPayRedirect = async () => {
|
7
|
+
const nextCookies = cookies();
|
8
|
+
const sessionId = nextCookies.get('osessionid')?.value;
|
9
|
+
|
10
|
+
if (!sessionId) {
|
11
|
+
return redirect(ROUTES.CHECKOUT);
|
12
|
+
}
|
13
|
+
|
14
|
+
const commerceUrl = settings.commerceUrl;
|
15
|
+
|
16
|
+
const response = await fetch(`${commerceUrl}/orders/garanti-pay-redirect`, {
|
17
|
+
headers: {
|
18
|
+
Cookie: nextCookies.toString()
|
19
|
+
}
|
20
|
+
});
|
21
|
+
|
22
|
+
const data = await response.text();
|
23
|
+
|
24
|
+
if (!data.includes('form3D')) {
|
25
|
+
return redirect(ROUTES.CHECKOUT);
|
26
|
+
}
|
27
|
+
|
28
|
+
return <div dangerouslySetInnerHTML={{ __html: data }}></div>;
|
29
|
+
};
|
@@ -1,111 +1,111 @@
|
|
1
|
-
'use client';
|
2
|
-
|
3
|
-
import * as yup from 'yup';
|
4
|
-
import { ReactNode, useEffect, useState } from 'react';
|
5
|
-
import { RootState } from 'redux/store';
|
6
|
-
import { SubmitHandler, useForm } from 'react-hook-form';
|
7
|
-
import { useAppSelector } from '@akinon/next/redux/hooks';
|
8
|
-
import { useSetPaymentOptionMutation } from '@akinon/next/data/client/checkout';
|
9
|
-
import {
|
10
|
-
useSetCompleteGPayMutation,
|
11
|
-
useSetGPayMethodMutation
|
12
|
-
} from '../endpoints';
|
13
|
-
import { twMerge } from 'tailwind-merge';
|
14
|
-
import { yupResolver } from '@hookform/resolvers/yup';
|
15
|
-
import { Button } from '@akinon/next/components/button';
|
16
|
-
|
17
|
-
const gpayFormSchema = yup.object();
|
18
|
-
|
19
|
-
enum Elements {
|
20
|
-
title,
|
21
|
-
description,
|
22
|
-
button
|
23
|
-
}
|
24
|
-
|
25
|
-
type ElementClassKey = `${keyof typeof Elements}ClassName`;
|
26
|
-
|
27
|
-
type GpayOptionProps = {
|
28
|
-
[key in ElementClassKey]?: string;
|
29
|
-
} & {
|
30
|
-
translations?: {
|
31
|
-
[element in keyof typeof Elements]?: string | ReactNode;
|
32
|
-
};
|
33
|
-
};
|
34
|
-
|
35
|
-
export function GPayOption(props: GpayOptionProps) {
|
36
|
-
const [formError, setFormError] = useState(null);
|
37
|
-
|
38
|
-
const { preOrder } = useAppSelector((state: RootState) => state.checkout);
|
39
|
-
const isPaymentStepBusy = useAppSelector(
|
40
|
-
(state: RootState) => state.checkout.steps.payment.busy
|
41
|
-
);
|
42
|
-
|
43
|
-
const { handleSubmit } = useForm({
|
44
|
-
resolver: yupResolver(gpayFormSchema)
|
45
|
-
});
|
46
|
-
|
47
|
-
const [setPaymentOption] = useSetPaymentOptionMutation();
|
48
|
-
const [setGPayMethod] = useSetGPayMethodMutation();
|
49
|
-
const [setCompleteGPay] = useSetCompleteGPayMutation();
|
50
|
-
|
51
|
-
const onSubmit: SubmitHandler<null> = async () => {
|
52
|
-
if (isPaymentStepBusy) return;
|
53
|
-
|
54
|
-
setFormError([]);
|
55
|
-
|
56
|
-
await setGPayMethod();
|
57
|
-
|
58
|
-
const response = await setCompleteGPay().unwrap();
|
59
|
-
|
60
|
-
if (response?.errors?.non_field_errors) {
|
61
|
-
setFormError(response?.errors?.non_field_errors);
|
62
|
-
}
|
63
|
-
};
|
64
|
-
|
65
|
-
// this is necessary because we need to set the payment_option after the redirect
|
66
|
-
useEffect(() => {
|
67
|
-
setPaymentOption(preOrder.payment_option.pk);
|
68
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
69
|
-
}, []);
|
70
|
-
|
71
|
-
return (
|
72
|
-
<form
|
73
|
-
id="gpay_payment"
|
74
|
-
className="p-5 space-y-5 lg:p-10"
|
75
|
-
onSubmit={handleSubmit(onSubmit)}
|
76
|
-
>
|
77
|
-
<h1 className={twMerge('text-2xl font-bold', props.titleClassName)}>
|
78
|
-
{props.translations?.title ?? 'Pay with GarantiPay'}
|
79
|
-
</h1>
|
80
|
-
<div className={twMerge('text-sm', props.descriptionClassName)}>
|
81
|
-
{props.translations?.description ? (
|
82
|
-
props.translations.description
|
83
|
-
) : (
|
84
|
-
<>
|
85
|
-
<li>
|
86
|
-
Click on the “Pay with GarantiPay” button. Guarantee for payment
|
87
|
-
you will be redirected to the payment page.
|
88
|
-
</li>
|
89
|
-
<li>
|
90
|
-
Log in to your account with your username and password on the
|
91
|
-
Garanti Pay page. If you do not have a Garanti Pay membership,
|
92
|
-
create a new membership you can create.
|
93
|
-
</li>
|
94
|
-
<li>
|
95
|
-
Complete the payment process by selecting your card and payment
|
96
|
-
type.
|
97
|
-
</li>
|
98
|
-
</>
|
99
|
-
)}
|
100
|
-
</div>
|
101
|
-
<Button className={twMerge('w-full mt-3', props.buttonClassName)}>
|
102
|
-
{props.translations?.button ?? 'Pay with GarantiPay'}
|
103
|
-
</Button>
|
104
|
-
{formError && (
|
105
|
-
<div className="w-full text-xs text-start px-1 mt-3 text-error">
|
106
|
-
{formError}
|
107
|
-
</div>
|
108
|
-
)}
|
109
|
-
</form>
|
110
|
-
);
|
111
|
-
}
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import * as yup from 'yup';
|
4
|
+
import { ReactNode, useEffect, useState } from 'react';
|
5
|
+
import { RootState } from 'redux/store';
|
6
|
+
import { SubmitHandler, useForm } from 'react-hook-form';
|
7
|
+
import { useAppSelector } from '@akinon/next/redux/hooks';
|
8
|
+
import { useSetPaymentOptionMutation } from '@akinon/next/data/client/checkout';
|
9
|
+
import {
|
10
|
+
useSetCompleteGPayMutation,
|
11
|
+
useSetGPayMethodMutation
|
12
|
+
} from '../endpoints';
|
13
|
+
import { twMerge } from 'tailwind-merge';
|
14
|
+
import { yupResolver } from '@hookform/resolvers/yup';
|
15
|
+
import { Button } from '@akinon/next/components/button';
|
16
|
+
|
17
|
+
const gpayFormSchema = yup.object();
|
18
|
+
|
19
|
+
enum Elements {
|
20
|
+
title,
|
21
|
+
description,
|
22
|
+
button
|
23
|
+
}
|
24
|
+
|
25
|
+
type ElementClassKey = `${keyof typeof Elements}ClassName`;
|
26
|
+
|
27
|
+
type GpayOptionProps = {
|
28
|
+
[key in ElementClassKey]?: string;
|
29
|
+
} & {
|
30
|
+
translations?: {
|
31
|
+
[element in keyof typeof Elements]?: string | ReactNode;
|
32
|
+
};
|
33
|
+
};
|
34
|
+
|
35
|
+
export function GPayOption(props: GpayOptionProps) {
|
36
|
+
const [formError, setFormError] = useState(null);
|
37
|
+
|
38
|
+
const { preOrder } = useAppSelector((state: RootState) => state.checkout);
|
39
|
+
const isPaymentStepBusy = useAppSelector(
|
40
|
+
(state: RootState) => state.checkout.steps.payment.busy
|
41
|
+
);
|
42
|
+
|
43
|
+
const { handleSubmit } = useForm({
|
44
|
+
resolver: yupResolver(gpayFormSchema)
|
45
|
+
});
|
46
|
+
|
47
|
+
const [setPaymentOption] = useSetPaymentOptionMutation();
|
48
|
+
const [setGPayMethod] = useSetGPayMethodMutation();
|
49
|
+
const [setCompleteGPay] = useSetCompleteGPayMutation();
|
50
|
+
|
51
|
+
const onSubmit: SubmitHandler<null> = async () => {
|
52
|
+
if (isPaymentStepBusy) return;
|
53
|
+
|
54
|
+
setFormError([]);
|
55
|
+
|
56
|
+
await setGPayMethod();
|
57
|
+
|
58
|
+
const response = await setCompleteGPay().unwrap();
|
59
|
+
|
60
|
+
if (response?.errors?.non_field_errors) {
|
61
|
+
setFormError(response?.errors?.non_field_errors);
|
62
|
+
}
|
63
|
+
};
|
64
|
+
|
65
|
+
// this is necessary because we need to set the payment_option after the redirect
|
66
|
+
useEffect(() => {
|
67
|
+
setPaymentOption(preOrder.payment_option.pk);
|
68
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
69
|
+
}, []);
|
70
|
+
|
71
|
+
return (
|
72
|
+
<form
|
73
|
+
id="gpay_payment"
|
74
|
+
className="p-5 space-y-5 lg:p-10"
|
75
|
+
onSubmit={handleSubmit(onSubmit)}
|
76
|
+
>
|
77
|
+
<h1 className={twMerge('text-2xl font-bold', props.titleClassName)}>
|
78
|
+
{props.translations?.title ?? 'Pay with GarantiPay'}
|
79
|
+
</h1>
|
80
|
+
<div className={twMerge('text-sm', props.descriptionClassName)}>
|
81
|
+
{props.translations?.description ? (
|
82
|
+
props.translations.description
|
83
|
+
) : (
|
84
|
+
<>
|
85
|
+
<li>
|
86
|
+
Click on the “Pay with GarantiPay” button. Guarantee for payment
|
87
|
+
you will be redirected to the payment page.
|
88
|
+
</li>
|
89
|
+
<li>
|
90
|
+
Log in to your account with your username and password on the
|
91
|
+
Garanti Pay page. If you do not have a Garanti Pay membership,
|
92
|
+
create a new membership you can create.
|
93
|
+
</li>
|
94
|
+
<li>
|
95
|
+
Complete the payment process by selecting your card and payment
|
96
|
+
type.
|
97
|
+
</li>
|
98
|
+
</>
|
99
|
+
)}
|
100
|
+
</div>
|
101
|
+
<Button className={twMerge('w-full mt-3', props.buttonClassName)}>
|
102
|
+
{props.translations?.button ?? 'Pay with GarantiPay'}
|
103
|
+
</Button>
|
104
|
+
{formError && (
|
105
|
+
<div className="w-full text-xs text-start px-1 mt-3 text-error">
|
106
|
+
{formError}
|
107
|
+
</div>
|
108
|
+
)}
|
109
|
+
</form>
|
110
|
+
);
|
111
|
+
}
|