@akinon/next 2.0.0-beta.12 → 2.0.0-beta.13
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 +282 -29
- package/api/auth.ts +99 -77
- package/api/cache.ts +41 -5
- package/api/client.ts +3 -3
- package/api/form.ts +85 -0
- package/api/image-proxy.ts +75 -0
- package/api/product-categories.ts +53 -0
- package/api/similar-product-list.ts +63 -0
- package/api/similar-products.ts +111 -0
- package/api/virtual-try-on.ts +382 -0
- package/bin/pz-generate-routes.js +105 -0
- package/bin/pz-prebuild.js +1 -1
- package/bin/pz-predev.js +1 -0
- package/components/accordion.tsx +21 -6
- package/components/button.tsx +1 -1
- package/components/file-input.tsx +65 -3
- package/components/input.tsx +2 -2
- package/components/modal.tsx +32 -16
- package/components/plugin-module.tsx +61 -3
- package/components/select.tsx +2 -2
- package/components/selected-payment-option-view.tsx +21 -0
- package/data/client/checkout.ts +130 -74
- package/data/server/category.ts +11 -9
- package/data/server/flatpage.ts +4 -1
- package/data/server/form.ts +4 -1
- package/data/server/landingpage.ts +4 -1
- package/data/server/list.ts +5 -4
- package/data/server/menu.ts +4 -1
- package/data/server/product.ts +97 -52
- package/data/server/seo.ts +4 -1
- package/data/server/special-page.ts +5 -4
- package/data/server/widget.ts +4 -1
- package/data/urls.ts +3 -2
- package/hocs/client/with-segment-defaults.tsx +2 -2
- package/hocs/server/with-segment-defaults.tsx +65 -20
- package/hooks/index.ts +1 -0
- package/hooks/use-loyalty-availability.ts +21 -0
- package/hooks/use-payment-options.ts +2 -1
- package/hooks/use-pz-params.ts +37 -0
- package/instrumentation/index.ts +0 -1
- package/instrumentation/node.ts +2 -20
- package/jest.config.js +7 -1
- package/lib/cache-handler.mjs +527 -15
- package/lib/cache.ts +260 -31
- package/localization/provider.tsx +2 -5
- package/middlewares/checkout-provider.ts +1 -1
- package/middlewares/complete-gpay.ts +33 -26
- package/middlewares/complete-masterpass.ts +34 -26
- package/middlewares/complete-wallet.ts +183 -0
- package/middlewares/default.ts +346 -235
- package/middlewares/index.ts +8 -2
- package/middlewares/locale.ts +0 -1
- package/middlewares/masterpass-rest-callback.ts +220 -0
- package/middlewares/pretty-url.ts +21 -8
- package/middlewares/redirection-payment.ts +33 -26
- package/middlewares/saved-card-redirection.ts +34 -26
- package/middlewares/three-d-redirection.ts +33 -26
- package/middlewares/url-redirection.ts +9 -15
- package/middlewares/wallet-complete-redirection.ts +207 -0
- package/package.json +20 -11
- package/plugins.d.ts +19 -4
- package/plugins.js +9 -1
- package/redux/actions.ts +47 -0
- package/redux/middlewares/checkout.ts +20 -8
- package/redux/middlewares/index.ts +12 -10
- package/redux/middlewares/pre-order/address.ts +1 -1
- package/redux/middlewares/pre-order/attribute-based-shipping-option.ts +1 -1
- package/redux/middlewares/pre-order/data-source-shipping-option.ts +1 -1
- package/redux/middlewares/pre-order/delivery-option.ts +1 -1
- package/redux/middlewares/pre-order/index.ts +3 -1
- package/redux/middlewares/pre-order/installment-option.ts +2 -1
- package/redux/middlewares/pre-order/payment-option-reset.ts +37 -0
- package/redux/middlewares/pre-order/payment-option.ts +1 -1
- package/redux/middlewares/pre-order/pre-order-validation.ts +4 -3
- package/redux/middlewares/pre-order/redirection.ts +2 -2
- package/redux/middlewares/pre-order/set-pre-order.ts +2 -2
- package/redux/middlewares/pre-order/shipping-option.ts +1 -1
- package/redux/middlewares/pre-order/shipping-step.ts +1 -1
- package/redux/reducers/checkout.ts +9 -1
- package/redux/reducers/index.ts +5 -1
- package/sentry/index.ts +54 -17
- package/types/commerce/checkout.ts +11 -1
- package/types/index.ts +96 -6
- package/types/next-auth.d.ts +2 -2
- package/utils/app-fetch.ts +2 -2
- package/utils/generate-commerce-search-params.ts +3 -2
- package/utils/get-checkout-path.ts +3 -0
- package/utils/index.ts +38 -11
- package/utils/override-middleware.ts +1 -0
- package/utils/pz-segments.ts +92 -0
- package/utils/redirect-ignore.ts +35 -0
- package/utils/redirect.ts +9 -3
- package/with-pz-config.js +10 -4
package/middlewares/locale.ts
CHANGED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { NextFetchEvent, NextMiddleware, NextResponse } from 'next/server';
|
|
2
|
+
import Settings from 'settings';
|
|
3
|
+
import logger from '../utils/log';
|
|
4
|
+
import { getUrlPathWithLocale } from '../utils/localization';
|
|
5
|
+
import { PzNextRequest } from '.';
|
|
6
|
+
import { getCheckoutPath } from '../utils';
|
|
7
|
+
|
|
8
|
+
const withMasterpassRestCallback =
|
|
9
|
+
(middleware: NextMiddleware) =>
|
|
10
|
+
async (req: PzNextRequest, event: NextFetchEvent) => {
|
|
11
|
+
const url = req.nextUrl.clone();
|
|
12
|
+
const ip = req.headers.get('x-forwarded-for') ?? '';
|
|
13
|
+
const sessionId = req.cookies.get('osessionid');
|
|
14
|
+
|
|
15
|
+
if (!url.pathname.includes('/orders/masterpass-rest-callback')) {
|
|
16
|
+
return middleware(req, event);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (req.method !== 'POST') {
|
|
20
|
+
logger.warn('Invalid request method for masterpass REST callback', {
|
|
21
|
+
middleware: 'masterpass-rest-callback',
|
|
22
|
+
method: req.method,
|
|
23
|
+
ip
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return NextResponse.redirect(
|
|
27
|
+
`${url.origin}${getUrlPathWithLocale(
|
|
28
|
+
'/orders/checkout/',
|
|
29
|
+
req.cookies.get('pz-locale')?.value
|
|
30
|
+
)}`,
|
|
31
|
+
303
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const responseCode = url.searchParams.get('responseCode');
|
|
36
|
+
const token = url.searchParams.get('token');
|
|
37
|
+
|
|
38
|
+
if (!responseCode || !token) {
|
|
39
|
+
logger.warn('Missing required parameters for masterpass REST callback', {
|
|
40
|
+
middleware: 'masterpass-rest-callback',
|
|
41
|
+
responseCode,
|
|
42
|
+
token,
|
|
43
|
+
ip
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return NextResponse.redirect(
|
|
47
|
+
`${url.origin}${getUrlPathWithLocale(
|
|
48
|
+
'/orders/checkout/',
|
|
49
|
+
req.cookies.get('pz-locale')?.value
|
|
50
|
+
)}`,
|
|
51
|
+
303
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const formData = await req.formData();
|
|
57
|
+
const body: Record<string, string> = {};
|
|
58
|
+
|
|
59
|
+
Array.from(formData.entries()).forEach(([key, value]) => {
|
|
60
|
+
body[key] = value.toString();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
if (!sessionId) {
|
|
64
|
+
logger.warn(
|
|
65
|
+
'Make sure that the SESSION_COOKIE_SAMESITE environment variable is set to None in Commerce.',
|
|
66
|
+
{
|
|
67
|
+
middleware: 'masterpass-rest-callback',
|
|
68
|
+
ip
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
return NextResponse.redirect(
|
|
73
|
+
`${url.origin}${getUrlPathWithLocale(
|
|
74
|
+
'/orders/checkout/',
|
|
75
|
+
req.cookies.get('pz-locale')?.value
|
|
76
|
+
)}`,
|
|
77
|
+
303
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const isPostCheckout = req.cookies.get('pz-post-checkout-flow')?.value === 'true';
|
|
82
|
+
const requestUrl = new URL(getCheckoutPath(isPostCheckout), Settings.commerceUrl);
|
|
83
|
+
requestUrl.searchParams.set('page', 'MasterpassRestCompletePage');
|
|
84
|
+
requestUrl.searchParams.set('responseCode', responseCode);
|
|
85
|
+
requestUrl.searchParams.set('token', token);
|
|
86
|
+
requestUrl.searchParams.set(
|
|
87
|
+
'three_d_secure',
|
|
88
|
+
body.transactionType?.includes('3D') ? 'true' : 'false'
|
|
89
|
+
);
|
|
90
|
+
requestUrl.searchParams.set(
|
|
91
|
+
'transactionType',
|
|
92
|
+
body.transactionType || ''
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const requestHeaders = {
|
|
96
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
97
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
98
|
+
Cookie: req.headers.get('cookie') ?? '',
|
|
99
|
+
'x-currency': req.cookies.get('pz-currency')?.value ?? '',
|
|
100
|
+
'x-forwarded-for': ip,
|
|
101
|
+
'User-Agent': req.headers.get('user-agent') ?? ''
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const request = await fetch(requestUrl.toString(), {
|
|
105
|
+
method: 'POST',
|
|
106
|
+
headers: requestHeaders,
|
|
107
|
+
body: new URLSearchParams(body)
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
logger.info('Masterpass REST callback request', {
|
|
111
|
+
requestUrl: requestUrl.toString(),
|
|
112
|
+
status: request.status,
|
|
113
|
+
requestHeaders,
|
|
114
|
+
ip
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const response = await request.json();
|
|
118
|
+
|
|
119
|
+
const { context_list: contextList, errors } = response;
|
|
120
|
+
|
|
121
|
+
let redirectUrl = response.redirect_url;
|
|
122
|
+
|
|
123
|
+
if (!redirectUrl && contextList && contextList.length > 0) {
|
|
124
|
+
for (const context of contextList) {
|
|
125
|
+
if (context.page_context && context.page_context.redirect_url) {
|
|
126
|
+
redirectUrl = context.page_context.redirect_url;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (errors && Object.keys(errors).length) {
|
|
133
|
+
logger.error('Error while processing masterpass REST callback', {
|
|
134
|
+
middleware: 'masterpass-rest-callback',
|
|
135
|
+
errors,
|
|
136
|
+
requestHeaders,
|
|
137
|
+
ip
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
return NextResponse.redirect(
|
|
141
|
+
`${url.origin}${getUrlPathWithLocale(
|
|
142
|
+
'/orders/checkout/',
|
|
143
|
+
req.cookies.get('pz-locale')?.value
|
|
144
|
+
)}`,
|
|
145
|
+
{
|
|
146
|
+
status: 303,
|
|
147
|
+
headers: {
|
|
148
|
+
'Set-Cookie': `pz-pos-error=${JSON.stringify(errors)}; path=/;`
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
logger.info('Masterpass REST callback response', {
|
|
155
|
+
middleware: 'masterpass-rest-callback',
|
|
156
|
+
contextList,
|
|
157
|
+
redirectUrl,
|
|
158
|
+
ip
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
if (!redirectUrl) {
|
|
162
|
+
logger.warn(
|
|
163
|
+
'No redirection url found in response. Redirecting to checkout page.',
|
|
164
|
+
{
|
|
165
|
+
middleware: 'masterpass-rest-callback',
|
|
166
|
+
requestHeaders,
|
|
167
|
+
response: JSON.stringify(response),
|
|
168
|
+
ip
|
|
169
|
+
}
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
const redirectUrlWithLocale = `${url.origin}${getUrlPathWithLocale(
|
|
173
|
+
'/orders/checkout/',
|
|
174
|
+
req.cookies.get('pz-locale')?.value
|
|
175
|
+
)}`;
|
|
176
|
+
|
|
177
|
+
return NextResponse.redirect(redirectUrlWithLocale, 303);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const redirectUrlWithLocale = `${url.origin}${getUrlPathWithLocale(
|
|
181
|
+
redirectUrl,
|
|
182
|
+
req.cookies.get('pz-locale')?.value
|
|
183
|
+
)}`;
|
|
184
|
+
|
|
185
|
+
logger.info('Redirecting after masterpass REST callback', {
|
|
186
|
+
middleware: 'masterpass-rest-callback',
|
|
187
|
+
redirectUrlWithLocale,
|
|
188
|
+
ip
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
const nextResponse = NextResponse.redirect(redirectUrlWithLocale, 303);
|
|
192
|
+
|
|
193
|
+
nextResponse.headers.set(
|
|
194
|
+
'Set-Cookie',
|
|
195
|
+
request.headers.get('set-cookie') ?? ''
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
return nextResponse;
|
|
199
|
+
} catch (error) {
|
|
200
|
+
logger.error('Error while processing masterpass REST callback', {
|
|
201
|
+
middleware: 'masterpass-rest-callback',
|
|
202
|
+
error,
|
|
203
|
+
requestHeaders: {
|
|
204
|
+
Cookie: req.headers.get('cookie') ?? '',
|
|
205
|
+
'x-currency': req.cookies.get('pz-currency')?.value ?? ''
|
|
206
|
+
},
|
|
207
|
+
ip
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
return NextResponse.redirect(
|
|
211
|
+
`${url.origin}${getUrlPathWithLocale(
|
|
212
|
+
'/orders/checkout/',
|
|
213
|
+
req.cookies.get('pz-locale')?.value
|
|
214
|
+
)}`,
|
|
215
|
+
303
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
export default withMasterpassRestCallback;
|
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
import { Cache, CacheKey } from '../lib/cache';
|
|
2
|
-
import { NextFetchEvent, NextMiddleware
|
|
3
|
-
import { ROUTES } from 'routes';
|
|
2
|
+
import { NextFetchEvent, NextMiddleware } from 'next/server';
|
|
4
3
|
import { URLS } from '../data/urls';
|
|
5
4
|
import Settings from 'settings';
|
|
6
5
|
import { urlLocaleMatcherRegex } from '../utils';
|
|
7
6
|
import { PzNextRequest } from '.';
|
|
8
7
|
import logger from '../utils/log';
|
|
8
|
+
import { ROUTES } from 'routes';
|
|
9
9
|
|
|
10
10
|
type PrettyUrlResult = {
|
|
11
11
|
matched: boolean;
|
|
12
12
|
path?: string;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
let APP_ROUTES: string[] = [];
|
|
16
|
+
|
|
17
|
+
const legacyRoutes = Object.values(ROUTES);
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const generatedRoutes = require('routes/generated-routes');
|
|
21
|
+
const allRoutes = [...legacyRoutes, ...(generatedRoutes || [])];
|
|
22
|
+
APP_ROUTES = Array.from(new Set(allRoutes));
|
|
23
|
+
logger.debug('Loaded merged routes (legacy + generated)', {
|
|
24
|
+
count: APP_ROUTES.length
|
|
25
|
+
});
|
|
26
|
+
} catch (error) {
|
|
27
|
+
APP_ROUTES = legacyRoutes;
|
|
28
|
+
logger.debug('Loaded only legacy routes', { count: APP_ROUTES.length });
|
|
29
|
+
}
|
|
30
|
+
|
|
15
31
|
const resolvePrettyUrlHandler =
|
|
16
32
|
(pathname: string, ip: string | null) => async () => {
|
|
17
33
|
let results = <{ old_path: string }[]>[];
|
|
@@ -53,7 +69,8 @@ const resolvePrettyUrl = async (
|
|
|
53
69
|
locale,
|
|
54
70
|
resolvePrettyUrlHandler(pathname, ip),
|
|
55
71
|
{
|
|
56
|
-
useProxy: true
|
|
72
|
+
useProxy: true,
|
|
73
|
+
compressed: true
|
|
57
74
|
}
|
|
58
75
|
);
|
|
59
76
|
};
|
|
@@ -73,9 +90,7 @@ const withPrettyUrl =
|
|
|
73
90
|
const isValidPrettyUrlPath = (pathname: string) => {
|
|
74
91
|
return (
|
|
75
92
|
new RegExp(/^\/[a-zA-Z0-9/]+(?:-[a-zA-Z0-9/]+)*$/).test(pathname) &&
|
|
76
|
-
!
|
|
77
|
-
new RegExp(`^${value}$`).test(pathname)
|
|
78
|
-
)
|
|
93
|
+
!APP_ROUTES.some((route) => new RegExp(`^${route}$`).test(pathname))
|
|
79
94
|
);
|
|
80
95
|
};
|
|
81
96
|
const ip = req.headers.get('x-forwarded-for') ?? '';
|
|
@@ -108,8 +123,6 @@ const withPrettyUrl =
|
|
|
108
123
|
return middleware(req, event);
|
|
109
124
|
}
|
|
110
125
|
|
|
111
|
-
req.middlewareParams.found = false;
|
|
112
|
-
|
|
113
126
|
return middleware(req, event);
|
|
114
127
|
};
|
|
115
128
|
|
|
@@ -4,6 +4,7 @@ import Settings from 'settings';
|
|
|
4
4
|
import logger from '../utils/log';
|
|
5
5
|
import { PzNextRequest } from '.';
|
|
6
6
|
import { getUrlPathWithLocale } from '../utils/localization';
|
|
7
|
+
import { getCheckoutPath } from '../utils';
|
|
7
8
|
|
|
8
9
|
const streamToString = async (stream: ReadableStream<Uint8Array> | null) => {
|
|
9
10
|
if (stream) {
|
|
@@ -35,18 +36,22 @@ const withRedirectionPayment =
|
|
|
35
36
|
const searchParams = new URLSearchParams(url.search);
|
|
36
37
|
const ip = req.headers.get('x-forwarded-for') ?? '';
|
|
37
38
|
const sessionId = req.cookies.get('osessionid');
|
|
39
|
+
const currentLocale = req.middlewareParams?.rewrites?.locale;
|
|
38
40
|
|
|
39
41
|
if (searchParams.get('page') !== 'RedirectionPageCompletePage') {
|
|
40
42
|
return middleware(req, event);
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
const
|
|
45
|
+
const isPostCheckout = req.cookies.get('pz-post-checkout-flow')?.value === 'true';
|
|
46
|
+
const requestUrl = `${Settings.commerceUrl}${getCheckoutPath(isPostCheckout)}${url.search}`;
|
|
44
47
|
const requestHeaders = {
|
|
45
48
|
'X-Requested-With': 'XMLHttpRequest',
|
|
46
49
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
47
50
|
Cookie: req.headers.get('cookie') ?? '',
|
|
48
51
|
'x-currency': req.cookies.get('pz-currency')?.value ?? '',
|
|
49
|
-
'x-forwarded-for': ip
|
|
52
|
+
'x-forwarded-for': ip,
|
|
53
|
+
'Accept-Language':
|
|
54
|
+
currentLocale ?? req.cookies.get('pz-locale')?.value ?? ''
|
|
50
55
|
};
|
|
51
56
|
|
|
52
57
|
try {
|
|
@@ -60,17 +65,9 @@ const withRedirectionPayment =
|
|
|
60
65
|
ip
|
|
61
66
|
}
|
|
62
67
|
);
|
|
63
|
-
|
|
64
|
-
return NextResponse.redirect(
|
|
65
|
-
`${url.origin}${getUrlPathWithLocale(
|
|
66
|
-
'/orders/checkout/',
|
|
67
|
-
req.cookies.get('pz-locale')?.value
|
|
68
|
-
)}`,
|
|
69
|
-
303
|
|
70
|
-
);
|
|
71
68
|
}
|
|
72
69
|
|
|
73
|
-
const
|
|
70
|
+
const fetchResponse = await fetch(requestUrl, {
|
|
74
71
|
method: 'POST',
|
|
75
72
|
headers: requestHeaders,
|
|
76
73
|
body
|
|
@@ -78,14 +75,14 @@ const withRedirectionPayment =
|
|
|
78
75
|
|
|
79
76
|
logger.info('Complete redirection payment request', {
|
|
80
77
|
requestUrl,
|
|
81
|
-
status:
|
|
78
|
+
status: fetchResponse.status,
|
|
82
79
|
requestHeaders,
|
|
83
80
|
ip
|
|
84
81
|
});
|
|
85
82
|
|
|
86
|
-
const
|
|
83
|
+
const responseData = await fetchResponse.json();
|
|
87
84
|
|
|
88
|
-
const { context_list: contextList, errors } =
|
|
85
|
+
const { context_list: contextList, errors } = responseData;
|
|
89
86
|
const redirectionContext = contextList?.find(
|
|
90
87
|
(context) => context.page_context?.redirect_url
|
|
91
88
|
);
|
|
@@ -99,18 +96,27 @@ const withRedirectionPayment =
|
|
|
99
96
|
ip
|
|
100
97
|
});
|
|
101
98
|
|
|
102
|
-
|
|
99
|
+
const errorResponse = NextResponse.redirect(
|
|
103
100
|
`${url.origin}${getUrlPathWithLocale(
|
|
104
101
|
'/orders/checkout/',
|
|
105
102
|
req.cookies.get('pz-locale')?.value
|
|
106
103
|
)}`,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
104
|
+
303
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// Forward set-cookie headers from the upstream response
|
|
108
|
+
const setCookies = fetchResponse.headers.getSetCookie?.() ?? [];
|
|
109
|
+
setCookies.forEach((cookie) => {
|
|
110
|
+
errorResponse.headers.append('Set-Cookie', cookie);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Add error cookie
|
|
114
|
+
errorResponse.headers.append(
|
|
115
|
+
'Set-Cookie',
|
|
116
|
+
`pz-pos-error=${JSON.stringify(errors)}; path=/;`
|
|
113
117
|
);
|
|
118
|
+
|
|
119
|
+
return errorResponse;
|
|
114
120
|
}
|
|
115
121
|
|
|
116
122
|
logger.info('Order success page context list', {
|
|
@@ -125,7 +131,7 @@ const withRedirectionPayment =
|
|
|
125
131
|
{
|
|
126
132
|
middleware: 'redirection-payment',
|
|
127
133
|
requestHeaders,
|
|
128
|
-
response: JSON.stringify(
|
|
134
|
+
response: JSON.stringify(responseData),
|
|
129
135
|
ip
|
|
130
136
|
}
|
|
131
137
|
);
|
|
@@ -153,10 +159,11 @@ const withRedirectionPayment =
|
|
|
153
159
|
// So we use 303 status code to change the method to GET
|
|
154
160
|
const nextResponse = NextResponse.redirect(redirectUrlWithLocale, 303);
|
|
155
161
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
162
|
+
// Forward all set-cookie headers from the upstream response
|
|
163
|
+
const setCookies = fetchResponse.headers.getSetCookie?.() ?? [];
|
|
164
|
+
setCookies.forEach((cookie) => {
|
|
165
|
+
nextResponse.headers.append('Set-Cookie', cookie);
|
|
166
|
+
});
|
|
160
167
|
|
|
161
168
|
return nextResponse;
|
|
162
169
|
} catch (error) {
|
|
@@ -4,6 +4,8 @@ import { Buffer } from 'buffer';
|
|
|
4
4
|
import logger from '../utils/log';
|
|
5
5
|
import { getUrlPathWithLocale } from '../utils/localization';
|
|
6
6
|
import { PzNextRequest } from '.';
|
|
7
|
+
import { ServerVariables } from '../utils/server-variables';
|
|
8
|
+
import { getCheckoutPath } from '../utils';
|
|
7
9
|
|
|
8
10
|
const streamToString = async (stream: ReadableStream<Uint8Array> | null) => {
|
|
9
11
|
if (stream) {
|
|
@@ -34,18 +36,22 @@ const withSavedCardRedirection =
|
|
|
34
36
|
const url = req.nextUrl.clone();
|
|
35
37
|
const ip = req.headers.get('x-forwarded-for') ?? '';
|
|
36
38
|
const sessionId = req.cookies.get('osessionid');
|
|
39
|
+
const currentLocale = req.middlewareParams?.rewrites?.locale;
|
|
37
40
|
|
|
38
41
|
if (url.search.indexOf('SavedCardThreeDSecurePage') === -1) {
|
|
39
42
|
return middleware(req, event);
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
const
|
|
45
|
+
const isPostCheckout = req.cookies.get('pz-post-checkout-flow')?.value === 'true';
|
|
46
|
+
const requestUrl = `${Settings.commerceUrl}${getCheckoutPath(isPostCheckout)}${url.search}`;
|
|
43
47
|
const requestHeaders = {
|
|
44
48
|
'X-Requested-With': 'XMLHttpRequest',
|
|
45
49
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
46
50
|
Cookie: req.headers.get('cookie') ?? '',
|
|
47
51
|
'x-currency': req.cookies.get('pz-currency')?.value ?? '',
|
|
48
|
-
'x-forwarded-for': ip
|
|
52
|
+
'x-forwarded-for': ip,
|
|
53
|
+
'Accept-Language':
|
|
54
|
+
currentLocale ?? req.cookies.get('pz-locale')?.value ?? ''
|
|
49
55
|
};
|
|
50
56
|
|
|
51
57
|
try {
|
|
@@ -59,17 +65,9 @@ const withSavedCardRedirection =
|
|
|
59
65
|
ip
|
|
60
66
|
}
|
|
61
67
|
);
|
|
62
|
-
|
|
63
|
-
return NextResponse.redirect(
|
|
64
|
-
`${url.origin}${getUrlPathWithLocale(
|
|
65
|
-
'/orders/checkout/',
|
|
66
|
-
req.cookies.get('pz-locale')?.value
|
|
67
|
-
)}`,
|
|
68
|
-
303
|
|
69
|
-
);
|
|
70
68
|
}
|
|
71
69
|
|
|
72
|
-
const
|
|
70
|
+
const fetchResponse = await fetch(requestUrl, {
|
|
73
71
|
method: 'POST',
|
|
74
72
|
headers: requestHeaders,
|
|
75
73
|
body
|
|
@@ -77,14 +75,14 @@ const withSavedCardRedirection =
|
|
|
77
75
|
|
|
78
76
|
logger.info('Complete 3D payment request', {
|
|
79
77
|
requestUrl,
|
|
80
|
-
status:
|
|
78
|
+
status: fetchResponse.status,
|
|
81
79
|
requestHeaders,
|
|
82
80
|
ip
|
|
83
81
|
});
|
|
84
82
|
|
|
85
|
-
const
|
|
83
|
+
const responseData = await fetchResponse.json();
|
|
86
84
|
|
|
87
|
-
const { context_list: contextList, errors } =
|
|
85
|
+
const { context_list: contextList, errors } = responseData;
|
|
88
86
|
const redirectionContext = contextList?.find(
|
|
89
87
|
(context) => context.page_context?.redirect_url
|
|
90
88
|
);
|
|
@@ -98,18 +96,27 @@ const withSavedCardRedirection =
|
|
|
98
96
|
ip
|
|
99
97
|
});
|
|
100
98
|
|
|
101
|
-
|
|
99
|
+
const errorResponse = NextResponse.redirect(
|
|
102
100
|
`${url.origin}${getUrlPathWithLocale(
|
|
103
101
|
'/orders/checkout/',
|
|
104
102
|
req.cookies.get('pz-locale')?.value
|
|
105
103
|
)}`,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
104
|
+
303
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// Forward set-cookie headers from the upstream response
|
|
108
|
+
const setCookies = fetchResponse.headers.getSetCookie?.() ?? [];
|
|
109
|
+
setCookies.forEach((cookie) => {
|
|
110
|
+
errorResponse.headers.append('Set-Cookie', cookie);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Add error cookie
|
|
114
|
+
errorResponse.headers.append(
|
|
115
|
+
'Set-Cookie',
|
|
116
|
+
`pz-pos-error=${JSON.stringify(errors)}; path=/;`
|
|
112
117
|
);
|
|
118
|
+
|
|
119
|
+
return errorResponse;
|
|
113
120
|
}
|
|
114
121
|
|
|
115
122
|
logger.info('Order success page context list', {
|
|
@@ -124,7 +131,7 @@ const withSavedCardRedirection =
|
|
|
124
131
|
{
|
|
125
132
|
middleware: 'saved-card-redirection',
|
|
126
133
|
requestHeaders,
|
|
127
|
-
response: JSON.stringify(
|
|
134
|
+
response: JSON.stringify(responseData),
|
|
128
135
|
ip
|
|
129
136
|
}
|
|
130
137
|
);
|
|
@@ -152,10 +159,11 @@ const withSavedCardRedirection =
|
|
|
152
159
|
// So we use 303 status code to change the method to GET
|
|
153
160
|
const nextResponse = NextResponse.redirect(redirectUrlWithLocale, 303);
|
|
154
161
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
162
|
+
// Forward all set-cookie headers from the upstream response
|
|
163
|
+
const setCookies = fetchResponse.headers.getSetCookie?.() ?? [];
|
|
164
|
+
setCookies.forEach((cookie) => {
|
|
165
|
+
nextResponse.headers.append('Set-Cookie', cookie);
|
|
166
|
+
});
|
|
159
167
|
|
|
160
168
|
return nextResponse;
|
|
161
169
|
} catch (error) {
|
|
@@ -4,6 +4,7 @@ import { Buffer } from 'buffer';
|
|
|
4
4
|
import logger from '../utils/log';
|
|
5
5
|
import { getUrlPathWithLocale } from '../utils/localization';
|
|
6
6
|
import { PzNextRequest } from '.';
|
|
7
|
+
import { getCheckoutPath } from '../utils';
|
|
7
8
|
|
|
8
9
|
const streamToString = async (stream: ReadableStream<Uint8Array> | null) => {
|
|
9
10
|
if (stream) {
|
|
@@ -34,18 +35,22 @@ const withThreeDRedirection =
|
|
|
34
35
|
const url = req.nextUrl.clone();
|
|
35
36
|
const ip = req.headers.get('x-forwarded-for') ?? '';
|
|
36
37
|
const sessionId = req.cookies.get('osessionid');
|
|
38
|
+
const currentLocale = req.middlewareParams?.rewrites?.locale;
|
|
37
39
|
|
|
38
40
|
if (url.search.indexOf('CreditCardThreeDSecurePage') === -1) {
|
|
39
41
|
return middleware(req, event);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
const
|
|
44
|
+
const isPostCheckout = req.cookies.get('pz-post-checkout-flow')?.value === 'true';
|
|
45
|
+
const requestUrl = `${Settings.commerceUrl}${getCheckoutPath(isPostCheckout)}${url.search}`;
|
|
43
46
|
const requestHeaders = {
|
|
44
47
|
'X-Requested-With': 'XMLHttpRequest',
|
|
45
48
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
46
49
|
Cookie: req.headers.get('cookie') ?? '',
|
|
47
50
|
'x-currency': req.cookies.get('pz-currency')?.value ?? '',
|
|
48
|
-
'x-forwarded-for': ip
|
|
51
|
+
'x-forwarded-for': ip,
|
|
52
|
+
'Accept-Language':
|
|
53
|
+
currentLocale ?? req.cookies.get('pz-locale')?.value ?? ''
|
|
49
54
|
};
|
|
50
55
|
|
|
51
56
|
try {
|
|
@@ -59,17 +64,9 @@ const withThreeDRedirection =
|
|
|
59
64
|
ip
|
|
60
65
|
}
|
|
61
66
|
);
|
|
62
|
-
|
|
63
|
-
return NextResponse.redirect(
|
|
64
|
-
`${url.origin}${getUrlPathWithLocale(
|
|
65
|
-
'/orders/checkout/',
|
|
66
|
-
req.cookies.get('pz-locale')?.value
|
|
67
|
-
)}`,
|
|
68
|
-
303
|
|
69
|
-
);
|
|
70
67
|
}
|
|
71
68
|
|
|
72
|
-
const
|
|
69
|
+
const fetchResponse = await fetch(requestUrl, {
|
|
73
70
|
method: 'POST',
|
|
74
71
|
headers: requestHeaders,
|
|
75
72
|
body
|
|
@@ -77,14 +74,14 @@ const withThreeDRedirection =
|
|
|
77
74
|
|
|
78
75
|
logger.info('Complete 3D payment request', {
|
|
79
76
|
requestUrl,
|
|
80
|
-
status:
|
|
77
|
+
status: fetchResponse.status,
|
|
81
78
|
requestHeaders,
|
|
82
79
|
ip
|
|
83
80
|
});
|
|
84
81
|
|
|
85
|
-
const
|
|
82
|
+
const responseData = await fetchResponse.json();
|
|
86
83
|
|
|
87
|
-
const { context_list: contextList, errors } =
|
|
84
|
+
const { context_list: contextList, errors } = responseData;
|
|
88
85
|
const redirectionContext = contextList?.find(
|
|
89
86
|
(context) => context.page_context?.redirect_url
|
|
90
87
|
);
|
|
@@ -98,18 +95,27 @@ const withThreeDRedirection =
|
|
|
98
95
|
ip
|
|
99
96
|
});
|
|
100
97
|
|
|
101
|
-
|
|
98
|
+
const errorResponse = NextResponse.redirect(
|
|
102
99
|
`${url.origin}${getUrlPathWithLocale(
|
|
103
100
|
'/orders/checkout/',
|
|
104
101
|
req.cookies.get('pz-locale')?.value
|
|
105
102
|
)}`,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
103
|
+
303
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
// Forward set-cookie headers from the upstream response
|
|
107
|
+
const setCookies = fetchResponse.headers.getSetCookie?.() ?? [];
|
|
108
|
+
setCookies.forEach((cookie) => {
|
|
109
|
+
errorResponse.headers.append('Set-Cookie', cookie);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Add error cookie
|
|
113
|
+
errorResponse.headers.append(
|
|
114
|
+
'Set-Cookie',
|
|
115
|
+
`pz-pos-error=${JSON.stringify(errors)}; path=/;`
|
|
112
116
|
);
|
|
117
|
+
|
|
118
|
+
return errorResponse;
|
|
113
119
|
}
|
|
114
120
|
|
|
115
121
|
logger.info('Order success page context list', {
|
|
@@ -124,7 +130,7 @@ const withThreeDRedirection =
|
|
|
124
130
|
{
|
|
125
131
|
middleware: 'three-d-redirection',
|
|
126
132
|
requestHeaders,
|
|
127
|
-
response: JSON.stringify(
|
|
133
|
+
response: JSON.stringify(responseData),
|
|
128
134
|
ip
|
|
129
135
|
}
|
|
130
136
|
);
|
|
@@ -152,10 +158,11 @@ const withThreeDRedirection =
|
|
|
152
158
|
// So we use 303 status code to change the method to GET
|
|
153
159
|
const nextResponse = NextResponse.redirect(redirectUrlWithLocale, 303);
|
|
154
160
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
161
|
+
// Forward all set-cookie headers from the upstream response
|
|
162
|
+
const setCookies = fetchResponse.headers.getSetCookie?.() ?? [];
|
|
163
|
+
setCookies.forEach((cookie) => {
|
|
164
|
+
nextResponse.headers.append('Set-Cookie', cookie);
|
|
165
|
+
});
|
|
159
166
|
|
|
160
167
|
return nextResponse;
|
|
161
168
|
} catch (error) {
|