@akinon/pz-bkm 1.0.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/.gitattributes +15 -0
- package/.prettierrc +13 -0
- package/package.json +23 -0
- package/readme.md +36 -0
- package/src/endpoints.ts +60 -0
- package/src/index.tsx +1 -0
- package/src/views/bkm-option.tsx +147 -0
package/.gitattributes
ADDED
@@ -0,0 +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
|
+
|
package/.prettierrc
ADDED
@@ -0,0 +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
|
+
}
|
package/package.json
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
{
|
2
|
+
"name": "@akinon/pz-bkm",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"license": "MIT",
|
5
|
+
"main": "src/index.tsx",
|
6
|
+
"peerDependencies": {
|
7
|
+
"react": "^18.0.0",
|
8
|
+
"react-dom": "^18.0.0"
|
9
|
+
},
|
10
|
+
"devDependencies": {
|
11
|
+
"@types/node": "^18.7.8",
|
12
|
+
"@types/react": "^18.0.17",
|
13
|
+
"@types/react-dom": "^18.0.6",
|
14
|
+
"react": "^18.2.0",
|
15
|
+
"react-dom": "^18.2.0",
|
16
|
+
"typescript": "5.2.2"
|
17
|
+
},
|
18
|
+
"dependencies": {
|
19
|
+
"@hookform/resolvers": "2.9.0",
|
20
|
+
"react-hook-form": "7.31.3",
|
21
|
+
"yup": "0.32.11"
|
22
|
+
}
|
23
|
+
}
|
package/readme.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# pz-bkm
|
2
|
+
|
3
|
+
### Install the npm package
|
4
|
+
|
5
|
+
```bash
|
6
|
+
# For latest version
|
7
|
+
yarn add git+ssh://git@bitbucket.org:akinonteam/pz-bkm.git
|
8
|
+
|
9
|
+
# For specific version
|
10
|
+
yarn add git+ssh://git@bitbucket.org:akinonteam/pz-bkm.git#eX4mPl3
|
11
|
+
```
|
12
|
+
|
13
|
+
### Example Usage
|
14
|
+
##### File Path: src/views/checkout/steps/payment/options/bkm.tsx
|
15
|
+
|
16
|
+
```javascript
|
17
|
+
import { BKMOption } from 'pz-bkm';
|
18
|
+
|
19
|
+
export default function BKM() {
|
20
|
+
return (
|
21
|
+
<BKMOption
|
22
|
+
translations={{
|
23
|
+
title: 'Pay with BKM Express',
|
24
|
+
description: `When paying with BKM Express, you will be redirected to www.bkmexpress.com.tr.`,
|
25
|
+
button: 'Pay Now'
|
26
|
+
}}
|
27
|
+
/>
|
28
|
+
);
|
29
|
+
}
|
30
|
+
```
|
31
|
+
|
32
|
+
### Props
|
33
|
+
| Property | Type | Description |
|
34
|
+
|----------------|-----------|--------------------------------------------------|
|
35
|
+
| `translations` | `object` | Object containing translation strings. |
|
36
|
+
| `classes` | `object` | Object containing custom CSS class names. |
|
package/src/endpoints.ts
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
import {
|
2
|
+
CheckoutContext as BaseCheckoutContext,
|
3
|
+
PreOrder
|
4
|
+
} from '@akinon/next/types';
|
5
|
+
import { setPaymentStepBusy } from '@akinon/next/redux/reducers/checkout';
|
6
|
+
import { api } from '@akinon/next/data/client/api';
|
7
|
+
import { buildClientRequestUrl } from '@akinon/next/utils';
|
8
|
+
|
9
|
+
type CheckoutContext = BaseCheckoutContext & {
|
10
|
+
page_context?: {
|
11
|
+
transaction_id?: string;
|
12
|
+
path?: string;
|
13
|
+
token?: string;
|
14
|
+
};
|
15
|
+
};
|
16
|
+
|
17
|
+
interface CheckoutResponse {
|
18
|
+
pre_order?: PreOrder;
|
19
|
+
errors: {
|
20
|
+
non_field_errors: string;
|
21
|
+
};
|
22
|
+
context_list?: CheckoutContext[];
|
23
|
+
template_name?: string;
|
24
|
+
redirect_url?: string;
|
25
|
+
}
|
26
|
+
|
27
|
+
export const bkmApi = api.injectEndpoints({
|
28
|
+
endpoints: (build) => ({
|
29
|
+
setBkm: build.mutation<CheckoutResponse, boolean>({
|
30
|
+
query: (agreement: boolean) => ({
|
31
|
+
url: buildClientRequestUrl('/orders/checkout/?page=BexSelectionPage', {
|
32
|
+
useFormData: true
|
33
|
+
}),
|
34
|
+
method: 'POST',
|
35
|
+
body: {
|
36
|
+
agreement
|
37
|
+
}
|
38
|
+
}),
|
39
|
+
async onQueryStarted(arg, { dispatch, queryFulfilled }) {
|
40
|
+
dispatch(setPaymentStepBusy(true));
|
41
|
+
await queryFulfilled;
|
42
|
+
dispatch(setPaymentStepBusy(false));
|
43
|
+
}
|
44
|
+
}),
|
45
|
+
completeBkm: build.mutation<CheckoutResponse, void>({
|
46
|
+
query: () => ({
|
47
|
+
url: buildClientRequestUrl('/orders/checkout/?page=BexCompletePage'),
|
48
|
+
method: 'POST'
|
49
|
+
}),
|
50
|
+
async onQueryStarted(arg, { dispatch, queryFulfilled }) {
|
51
|
+
dispatch(setPaymentStepBusy(true));
|
52
|
+
await queryFulfilled;
|
53
|
+
dispatch(setPaymentStepBusy(false));
|
54
|
+
}
|
55
|
+
})
|
56
|
+
}),
|
57
|
+
overrideExisting: false
|
58
|
+
});
|
59
|
+
|
60
|
+
export const { useSetBkmMutation, useCompleteBkmMutation } = bkmApi;
|
package/src/index.tsx
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export * from './views/bkm-option';
|
@@ -0,0 +1,147 @@
|
|
1
|
+
import React, { ReactElement, useId } from 'react';
|
2
|
+
import Script from 'next/script';
|
3
|
+
import * as yup from 'yup';
|
4
|
+
import { yupResolver } from '@hookform/resolvers/yup';
|
5
|
+
import { SubmitHandler, useForm } from 'react-hook-form';
|
6
|
+
import { Button } from '@akinon/next/components';
|
7
|
+
import { useCompleteBkmMutation, useSetBkmMutation } from '../endpoints';
|
8
|
+
import { twMerge } from 'tailwind-merge';
|
9
|
+
|
10
|
+
type BKMOptionProps = {
|
11
|
+
translations?: {
|
12
|
+
title?: string;
|
13
|
+
description?: string;
|
14
|
+
button?: string;
|
15
|
+
required?: string;
|
16
|
+
};
|
17
|
+
classes?: {
|
18
|
+
description?: string;
|
19
|
+
button?: string;
|
20
|
+
};
|
21
|
+
agreementCheckbox?: ReactElement;
|
22
|
+
};
|
23
|
+
|
24
|
+
const formSchema = (requiredText?: string) =>
|
25
|
+
yup.object().shape({
|
26
|
+
agreement: yup
|
27
|
+
.boolean()
|
28
|
+
.oneOf([true], requiredText ?? 'This field is required.')
|
29
|
+
});
|
30
|
+
|
31
|
+
const BKMOption = ({
|
32
|
+
translations,
|
33
|
+
classes,
|
34
|
+
agreementCheckbox
|
35
|
+
}: BKMOptionProps) => {
|
36
|
+
const id = useId();
|
37
|
+
const {
|
38
|
+
handleSubmit,
|
39
|
+
control,
|
40
|
+
formState: { errors },
|
41
|
+
getValues
|
42
|
+
} = useForm({
|
43
|
+
resolver: yupResolver(formSchema(translations?.required))
|
44
|
+
});
|
45
|
+
const [setBkm] = useSetBkmMutation();
|
46
|
+
const [completeBkm] = useCompleteBkmMutation();
|
47
|
+
|
48
|
+
const onSubmit: SubmitHandler<null> = async () => {
|
49
|
+
const response = await setBkm(getValues('agreement')).unwrap();
|
50
|
+
|
51
|
+
const bexContext = response.context_list.find(
|
52
|
+
(context) => context.page_name === 'BexBinNumberPage'
|
53
|
+
);
|
54
|
+
|
55
|
+
if (!bexContext) {
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
|
59
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
60
|
+
// @ts-ignore
|
61
|
+
window.Bex.init(
|
62
|
+
{
|
63
|
+
id: bexContext.page_context.transaction_id,
|
64
|
+
path: bexContext.page_context.path,
|
65
|
+
token: bexContext.page_context.token
|
66
|
+
},
|
67
|
+
'modal',
|
68
|
+
{
|
69
|
+
container: `js-bkm-frame-${id}`,
|
70
|
+
buttonSize: [500, 500],
|
71
|
+
skipButton: true,
|
72
|
+
onComplete: async (status) => {
|
73
|
+
if (status == 'success') {
|
74
|
+
const data = await completeBkm().unwrap();
|
75
|
+
const redirectUrl =
|
76
|
+
data.context_list?.[0]?.page_context?.redirect_url;
|
77
|
+
|
78
|
+
if (!redirectUrl) {
|
79
|
+
return;
|
80
|
+
}
|
81
|
+
|
82
|
+
window.location.href = redirectUrl;
|
83
|
+
}
|
84
|
+
}
|
85
|
+
}
|
86
|
+
);
|
87
|
+
};
|
88
|
+
|
89
|
+
return (
|
90
|
+
<>
|
91
|
+
<form className="flex flex-col w-full" onSubmit={handleSubmit(onSubmit)}>
|
92
|
+
<div className="flex justify-start items-center border-solid border-gray-400 px-4 py-2 sm:px-6 sm:py-3 sm:min-h-15">
|
93
|
+
<span className="text-black-800 text-lg font-medium sm:text-2xl">
|
94
|
+
{translations?.title ?? 'BKM Express'}
|
95
|
+
</span>
|
96
|
+
</div>
|
97
|
+
|
98
|
+
<div className="w-full bg-white">
|
99
|
+
<div className="text-black-800 px-4 sm:px-6">
|
100
|
+
<p className={twMerge('text-sm w-full mb-2', classes?.description)}>
|
101
|
+
{translations?.description ?? (
|
102
|
+
<>
|
103
|
+
When paying with BKM Express, you will be redirected to
|
104
|
+
www.bkmexpress.com.tr. <br />
|
105
|
+
You need to log in to the application with the username and
|
106
|
+
password you used when signing up to BKM Express. You can
|
107
|
+
easily pay by selecting the card you want to make a
|
108
|
+
transaction and the payment method from the payment screen
|
109
|
+
that appears. After completing your shopping, you will
|
110
|
+
automatically return to site.
|
111
|
+
</>
|
112
|
+
)}
|
113
|
+
</p>
|
114
|
+
</div>
|
115
|
+
</div>
|
116
|
+
|
117
|
+
<div className="px-4 sm:px-6">
|
118
|
+
<div className="flex items-start flex-col border-t border-solid border-gray-400 py-4 space-y-4">
|
119
|
+
{agreementCheckbox &&
|
120
|
+
React.cloneElement(agreementCheckbox, {
|
121
|
+
control: control,
|
122
|
+
error: errors.agreement,
|
123
|
+
fieldId: 'agreement'
|
124
|
+
})}
|
125
|
+
<Button
|
126
|
+
className={twMerge(
|
127
|
+
'group uppercase mt-4 inline-flex items-center justify-center w-full',
|
128
|
+
classes?.button
|
129
|
+
)}
|
130
|
+
type="submit"
|
131
|
+
data-testid="checkout-bank-account-place-order"
|
132
|
+
>
|
133
|
+
<span>{translations?.button ?? 'Pay with BKM Express'}</span>
|
134
|
+
</Button>
|
135
|
+
</div>
|
136
|
+
</div>
|
137
|
+
</form>
|
138
|
+
<div
|
139
|
+
id={`js-bkm-frame-${id}`}
|
140
|
+
className="bkm-frame !flex justify-center items-center !pt-0"
|
141
|
+
></div>
|
142
|
+
<Script src="https://js.bkmexpress.com.tr/v1/javascripts/bex.js" defer />
|
143
|
+
</>
|
144
|
+
);
|
145
|
+
};
|
146
|
+
|
147
|
+
export { BKMOption };
|