@infosoftas/s4-orders-js-sdk 0.0.1-alpha2c.1 → 0.0.1-beta1

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/.release-it.json CHANGED
@@ -1,6 +1,9 @@
1
- {
2
- "$schema": "https://unpkg.com/release-it/schema/release-it.json",
3
- "github": {
4
- "release": true
5
- }
1
+ {
2
+ "$schema": "https://unpkg.com/release-it/schema/release-it.json",
3
+ "git": {
4
+ "changelog" : ""
5
+ },
6
+ "github": {
7
+ "release": true
8
+ }
6
9
  }
package/package.json CHANGED
@@ -1,44 +1,44 @@
1
- {
2
- "name": "@infosoftas/s4-orders-js-sdk",
3
- "version": "0.0.1-alpha2c.1",
4
- "scripts": {
5
- "build": "rimraf lib && webpack --env mode=production",
6
- "release": "release-it"
7
- },
8
- "eslintConfig": {
9
- "extends": [
10
- "react-app"
11
- ]
12
- },
13
- "dependencies": {
14
- "prop-types": "^15.8.1",
15
- "react": "^18.3.1",
16
- "react-dom": "^18.3.1",
17
- "react-hook-form": "^7.53.0"
18
- },
19
- "devDependencies": {
20
- "@babel/core": "^7.24.3",
21
- "@babel/preset-env": "^7.18.10",
22
- "@babel/preset-react": "^7.18.6",
23
- "@babel/preset-typescript": "^7.24.7",
24
- "@types/react": "^18.0.17",
25
- "@types/react-dom": "^18.0.6",
26
- "babel-loader": "^8.3.0",
27
- "copy-webpack-plugin": "^12.0.2",
28
- "css-loader": "^7.1.2",
29
- "dotenv-webpack": "^8.1.0",
30
- "mini-css-extract-plugin": "^2.9.1",
31
- "release-it": "^17.10.0",
32
- "rimraf": "^6.0.1",
33
- "sass": "^1.79.2",
34
- "sass-loader": "^16.0.1",
35
- "style-loader": "^4.0.0",
36
- "ts-loader": "^9.5.1",
37
- "typescript": "^5.6.2",
38
- "webpack": "^5.95.0",
39
- "webpack-cli": "^5.1.4"
40
- },
41
- "publishConfig": {
42
- "access": "public"
43
- }
44
- }
1
+ {
2
+ "name": "@infosoftas/s4-orders-js-sdk",
3
+ "version": "0.0.1-beta1",
4
+ "scripts": {
5
+ "build": "rimraf lib && webpack --env mode=production",
6
+ "release": "release-it"
7
+ },
8
+ "eslintConfig": {
9
+ "extends": [
10
+ "react-app"
11
+ ]
12
+ },
13
+ "dependencies": {
14
+ "prop-types": "^15.8.1",
15
+ "react": "^18.3.1",
16
+ "react-dom": "^18.3.1",
17
+ "react-hook-form": "^7.53.0"
18
+ },
19
+ "devDependencies": {
20
+ "@babel/core": "^7.24.3",
21
+ "@babel/preset-env": "^7.18.10",
22
+ "@babel/preset-react": "^7.18.6",
23
+ "@babel/preset-typescript": "^7.24.7",
24
+ "@types/react": "^18.0.17",
25
+ "@types/react-dom": "^18.0.6",
26
+ "babel-loader": "^8.3.0",
27
+ "copy-webpack-plugin": "^12.0.2",
28
+ "css-loader": "^7.1.2",
29
+ "dotenv-webpack": "^8.1.0",
30
+ "mini-css-extract-plugin": "^2.9.1",
31
+ "release-it": "^17.10.0",
32
+ "rimraf": "^6.0.1",
33
+ "sass": "^1.79.2",
34
+ "sass-loader": "^16.0.1",
35
+ "style-loader": "^4.0.0",
36
+ "ts-loader": "^9.5.1",
37
+ "typescript": "^5.6.2",
38
+ "webpack": "^5.95.0",
39
+ "webpack-cli": "^5.1.4"
40
+ },
41
+ "publishConfig": {
42
+ "access": "public"
43
+ }
44
+ }
package/src/App.tsx CHANGED
@@ -13,7 +13,11 @@ import Loader from './components/Loader/Loader';
13
13
  import MainIframe from './components/MainIframe/MainIframe';
14
14
  import Alert from './components/Alert/Alert';
15
15
  import { ConfigType, ErrorsMsg } from './types/general';
16
- import { CompleteOrderParamsType, OrderInfoType } from './types/order';
16
+ import {
17
+ CompleteOrderParamsType,
18
+ OrderInfoType,
19
+ OrderFormInputsType,
20
+ } from './types/order';
17
21
  import { orderComplete, orderDelete } from './api/OrdersApi';
18
22
  import { prepareErrorMessage, prepareErrorsArrayMessage } from './utils/helper';
19
23
 
@@ -22,6 +26,7 @@ import ErrorBoundary from './ErrorBoundary';
22
26
  import './App.scss';
23
27
 
24
28
  const App: FC<ConfigType> = ({
29
+ submitStartCallback,
25
30
  moduleTitle,
26
31
  apiKey,
27
32
  apiUrl,
@@ -35,6 +40,7 @@ const App: FC<ConfigType> = ({
35
40
  paymentMethodsOptions,
36
41
  invoiceAddressSelection,
37
42
  availablePaymentMethods = [],
43
+ allowedPaymentMethods,
38
44
  language = 'en-US',
39
45
  merchantAgreementUrl = '',
40
46
  settings = {
@@ -44,8 +50,15 @@ const App: FC<ConfigType> = ({
44
50
  submitButtonText: 'Start',
45
51
  backButtonText: 'Back',
46
52
  verifyButtonText: 'Verify',
47
- organizationNumberLabel: 'CVR',
53
+ organizationNumberLabel: 'Organization Number',
54
+ paymentMethodLabel: '',
48
55
  glnLabel: 'GLN',
56
+ cvrLabel: 'CVR',
57
+ orderDefaultValues: undefined,
58
+ errorReqMsg: '',
59
+ errorInvalidEmailMsg: '',
60
+ errorInvalidPhoneMsg: '',
61
+ paymentMethodNotAllowedMsg: '',
49
62
  },
50
63
  }) => {
51
64
  const [loading, setLoading] = useState<boolean>(false);
@@ -58,6 +71,9 @@ const App: FC<ConfigType> = ({
58
71
  const [errorsMsg, setErrorsMsg] = useState<string[]>([]);
59
72
  const [orderInfo, setOrderInfo] = useState<OrderInfoType | null>(null);
60
73
  const [formType, setFormType] = useState(FormTypeEnum.ORDER);
74
+ const [orderFormValues, setOrderFormValues] = useState(
75
+ settings?.orderDefaultValues
76
+ );
61
77
 
62
78
  useEffect(() => {
63
79
  if (apiKey) {
@@ -190,6 +206,9 @@ const App: FC<ConfigType> = ({
190
206
  setIsFailed(false);
191
207
  setOrderId(data?.orderId || null);
192
208
  setOrderInfo(data || null);
209
+ if (data) {
210
+ setOrderFormValues(data as unknown as OrderFormInputsType);
211
+ }
193
212
  if (window === top) {
194
213
  top.postMessage(
195
214
  {
@@ -222,7 +241,10 @@ const App: FC<ConfigType> = ({
222
241
  return;
223
242
  }
224
243
 
225
- window.location.href = url;
244
+ setTimeout(() => {
245
+ window.location.href = url;
246
+ }, 300);
247
+
226
248
  return;
227
249
  }
228
250
 
@@ -267,10 +289,11 @@ const App: FC<ConfigType> = ({
267
289
  callback={handleInvoiceForm}
268
290
  backButtonText={settings?.backButtonText}
269
291
  verifyButtonText={settings?.verifyButtonText}
270
- organizationNumberLabel={
271
- settings?.organizationNumberLabel
272
- }
292
+ organizationNumberLabel={settings?.cvrLabel}
273
293
  glnLabel={settings?.glnLabel}
294
+ organizationNumber={
295
+ orderFormValues?.organizationNumber
296
+ }
274
297
  />
275
298
  )}
276
299
  {formType === FormTypeEnum.EHF && (
@@ -282,24 +305,34 @@ const App: FC<ConfigType> = ({
282
305
  organizationNumberLabel={
283
306
  settings?.organizationNumberLabel
284
307
  }
308
+ organizationNumber={
309
+ orderFormValues?.organizationNumber
310
+ }
285
311
  />
286
312
  )}
287
313
  {formType !== FormTypeEnum.OIO &&
288
314
  formType !== FormTypeEnum.EHF && (
289
315
  <OrderForm
290
316
  callback={handleForm}
317
+ submitStartCallback={submitStartCallback}
291
318
  templatePackageId={templatePackageId}
292
319
  subscriberId={subscriberId}
293
320
  userId={userId}
294
321
  identityProviderId={identityProviderId}
295
322
  organizationId={organizationId}
296
323
  paymentMethods={availablePaymentMethods}
324
+ allowedPaymentMethods={
325
+ allowedPaymentMethods
326
+ }
297
327
  submitButtonText={
298
328
  settings?.submitButtonText
299
329
  }
300
330
  paymentMethodLabel={
301
331
  settings?.paymentMethodLabel
302
332
  }
333
+ paymentMethodNotAllowedMsg={
334
+ settings?.paymentMethodNotAllowedMsg
335
+ }
303
336
  errorReqMsg={settings?.errorReqMsg}
304
337
  errorInvalidEmailMsg={
305
338
  settings?.errorInvalidEmailMsg
@@ -307,7 +340,7 @@ const App: FC<ConfigType> = ({
307
340
  errorInvalidPhoneMsg={
308
341
  settings?.errorInvalidPhoneMsg
309
342
  }
310
- defaultValues={settings?.orderDefaultValues}
343
+ defaultValues={orderFormValues}
311
344
  redirectUrl={redirectUrl}
312
345
  showIframe={showIframe}
313
346
  paymentMethodsOptions={
@@ -18,6 +18,7 @@ type Props = {
18
18
  backButtonText?: string;
19
19
  verifyButtonText?: string;
20
20
  organizationNumberLabel?: string;
21
+ organizationNumber?: string;
21
22
  className?: string;
22
23
  };
23
24
 
@@ -35,6 +36,7 @@ const EHFForm: FC<Props> = ({
35
36
  backButtonText = '',
36
37
  verifyButtonText = '',
37
38
  organizationNumberLabel = '',
39
+ organizationNumber = '',
38
40
  className = '',
39
41
  }) => {
40
42
  const [loading, setLoading] = useState<boolean>(false);
@@ -44,6 +46,7 @@ const EHFForm: FC<Props> = ({
44
46
  const methods = useForm<EHFFormInputsType>({
45
47
  defaultValues: {
46
48
  ...initialData,
49
+ organizationNumber,
47
50
  },
48
51
  });
49
52
 
@@ -18,6 +18,7 @@ type Props = {
18
18
  backButtonText?: string;
19
19
  verifyButtonText?: string;
20
20
  organizationNumberLabel?: string;
21
+ organizationNumber?: string;
21
22
  glnLabel?: string;
22
23
  className?: string;
23
24
  };
@@ -38,6 +39,7 @@ const EHFForm: FC<Props> = ({
38
39
  backButtonText = '',
39
40
  verifyButtonText = '',
40
41
  organizationNumberLabel = '',
42
+ organizationNumber = '',
41
43
  glnLabel = '',
42
44
  className = '',
43
45
  }) => {
@@ -48,6 +50,7 @@ const EHFForm: FC<Props> = ({
48
50
  const methods = useForm<OIOFormInputsType>({
49
51
  defaultValues: {
50
52
  ...initialData,
53
+ cvr: organizationNumber,
51
54
  },
52
55
  });
53
56
 
@@ -1,10 +1,14 @@
1
- import { FC, ChangeEvent, Suspense, useState } from 'react';
1
+ import { FC, ChangeEvent, Suspense, useState, useMemo } from 'react';
2
2
  import { FormProvider, useForm, SubmitHandler } from 'react-hook-form';
3
3
 
4
4
  import { createSubscriber, mapSubscriberToUser } from '../../api/SubscribeApi';
5
5
  import { orderStart } from '../../api/OrdersApi';
6
6
  import { PaymentMethodEnum } from '../../enums/general';
7
- import { WRONG_MSG, PAYMENT_METHOD_DEFAULT } from '../../constants/index';
7
+ import {
8
+ WRONG_MSG,
9
+ PAYMENT_METHOD_DEFAULT,
10
+ INVOICE_ALLOWED_PAYMENT_METHODS,
11
+ } from '../../constants/index';
8
12
  import Alert from '../Alert/Alert';
9
13
  import Button from '../Button/Button';
10
14
  import ToggleField from '../FormFields/ToggleFiled';
@@ -31,6 +35,7 @@ import './orderForm.scss';
31
35
 
32
36
  type Props = {
33
37
  callback: (url: string | null, orderInfo?: OrderInfoType | null) => void;
38
+ submitStartCallback?: (id: string) => void;
34
39
  templatePackageId: string;
35
40
  subscriberId?: string;
36
41
  userId?: string;
@@ -43,8 +48,10 @@ type Props = {
43
48
  paymentMethodsOptions?: PaymentMethodOptionsType;
44
49
  defaultValues?: OrderFormInputsType;
45
50
  paymentMethods?: { label: string; value: PaymentMethodEnum }[];
51
+ allowedPaymentMethods?: PaymentMethodEnum[];
46
52
  submitButtonText?: string;
47
53
  paymentMethodLabel?: string;
54
+ paymentMethodNotAllowedMsg?: string;
48
55
  errorReqMsg?: string;
49
56
  errorInvalidEmailMsg?: string;
50
57
  errorInvalidPhoneMsg?: string;
@@ -52,6 +59,7 @@ type Props = {
52
59
  enabled?: boolean;
53
60
  label?: string;
54
61
  fields?: OrderFormFiledType[];
62
+ paymentMethods?: PaymentMethodEnum[];
55
63
  };
56
64
  };
57
65
 
@@ -70,6 +78,7 @@ const initialData = {
70
78
 
71
79
  const OrderForm: FC<Props> = ({
72
80
  callback,
81
+ submitStartCallback,
73
82
  templatePackageId,
74
83
  subscriberId,
75
84
  userId,
@@ -82,9 +91,11 @@ const OrderForm: FC<Props> = ({
82
91
  language,
83
92
  merchantAgreementUrl,
84
93
  paymentMethods = [],
94
+ allowedPaymentMethods,
85
95
  invoiceAddressSelection,
86
96
  submitButtonText = 'Start',
87
97
  paymentMethodLabel = 'Select Payment Method',
98
+ paymentMethodNotAllowedMsg = 'This payment method not allowed!',
88
99
  errorReqMsg = '',
89
100
  errorInvalidEmailMsg = '',
90
101
  errorInvalidPhoneMsg = '',
@@ -109,6 +120,10 @@ const OrderForm: FC<Props> = ({
109
120
  const invoiceOrderFields =
110
121
  invoiceAddressSelection?.fields || orderInvoiceContactFields;
111
122
 
123
+ const invoicePaymentMethods =
124
+ invoiceAddressSelection?.paymentMethods ||
125
+ INVOICE_ALLOWED_PAYMENT_METHODS;
126
+
112
127
  const {
113
128
  register,
114
129
  handleSubmit,
@@ -118,6 +133,7 @@ const OrderForm: FC<Props> = ({
118
133
  } = methods;
119
134
 
120
135
  const invoiceAddressToggle = watch('invoiceAddressSelection');
136
+ const paymentMethodInput = watch('paymentMethod');
121
137
 
122
138
  const onSubmit: SubmitHandler<OrderFormInputsType> = async (
123
139
  data
@@ -143,6 +159,8 @@ const OrderForm: FC<Props> = ({
143
159
  }
144
160
  }
145
161
 
162
+ submitStartCallback?.(id as string);
163
+
146
164
  if (id) {
147
165
  const paymentMethod =
148
166
  data.paymentMethod || PAYMENT_METHOD_DEFAULT;
@@ -183,6 +201,7 @@ const OrderForm: FC<Props> = ({
183
201
  orderReference: data.orderReference || undefined,
184
202
  });
185
203
  callback(responseOrder.terminalRedirectUrl, {
204
+ ...(data || {}),
186
205
  orderId: responseOrder.id,
187
206
  subscriberId: id,
188
207
  paymentMethod: paymentMethod,
@@ -216,8 +235,29 @@ const OrderForm: FC<Props> = ({
216
235
  paymentMethodsOptions?.[e.target.value as PaymentMethodEnum]
217
236
  ?.orderFormFields ?? DEFAULT_ORDER_FORM_FIELDS;
218
237
  setOrderFields(orderFieldsLocal);
238
+ if (
239
+ !invoicePaymentMethods.includes(e.target.value as PaymentMethodEnum)
240
+ ) {
241
+ setValue('invoiceAddressSelection', false);
242
+ }
219
243
  };
220
244
 
245
+ const allowPaymentMethod = useMemo(() => {
246
+ if (!allowedPaymentMethods || allowedPaymentMethods?.length === 0) {
247
+ return true;
248
+ }
249
+
250
+ if (
251
+ allowedPaymentMethods.includes(
252
+ paymentMethodInput as PaymentMethodEnum
253
+ )
254
+ ) {
255
+ return true;
256
+ }
257
+
258
+ return false;
259
+ }, [allowedPaymentMethods, paymentMethodInput]);
260
+
221
261
  return (
222
262
  <FormProvider {...methods}>
223
263
  <form
@@ -258,7 +298,7 @@ const OrderForm: FC<Props> = ({
258
298
  )}
259
299
  </div>
260
300
  )}
261
- {orderFields?.length > 0 && (
301
+ {orderFields?.length > 0 && allowPaymentMethod && (
262
302
  <Suspense fallback={null}>
263
303
  {orderFields.map((field) => {
264
304
  const Component = formFieldsMapper[field.name];
@@ -279,42 +319,63 @@ const OrderForm: FC<Props> = ({
279
319
  })}
280
320
  </Suspense>
281
321
  )}
282
- {invoiceAddressSelection?.enabled && (
283
- <ToggleField
284
- name="invoiceAddressSelection"
285
- label={
286
- invoiceAddressSelection?.label ?? 'Invoice Address'
287
- }
288
- />
289
- )}
290
- {invoiceAddressToggle && invoiceOrderFields?.length > 0 && (
291
- <Suspense fallback={null}>
292
- {invoiceOrderFields.map((field) => {
293
- const Component = formFieldsMapper[field.name];
322
+ {invoiceAddressSelection?.enabled &&
323
+ allowPaymentMethod &&
324
+ invoicePaymentMethods.includes(
325
+ paymentMethodInput as PaymentMethodEnum
326
+ ) && (
327
+ <ToggleField
328
+ name="invoiceAddressSelection"
329
+ label={
330
+ invoiceAddressSelection?.label ??
331
+ 'Invoice Address'
332
+ }
333
+ />
334
+ )}
335
+ {invoiceAddressToggle &&
336
+ invoiceOrderFields?.length > 0 &&
337
+ allowPaymentMethod && (
338
+ <Suspense fallback={null}>
339
+ {invoiceOrderFields.map((field) => {
340
+ const Component = formFieldsMapper[field.name];
294
341
 
295
- return Component ? (
296
- <Component
297
- key={field.name}
298
- name={field.name}
299
- label={field.label}
300
- required={field.required || false}
301
- readOnly={field.readOnly || false}
302
- errors={errors}
303
- errorReqMsg={errorReqMsg}
304
- errorInvalidEmailMsg={errorInvalidEmailMsg}
305
- errorInvalidPhoneMsg={errorInvalidPhoneMsg}
306
- />
307
- ) : null;
308
- })}
309
- </Suspense>
342
+ return Component ? (
343
+ <Component
344
+ key={field.name}
345
+ name={field.name}
346
+ label={field.label}
347
+ required={field.required || false}
348
+ readOnly={field.readOnly || false}
349
+ errors={errors}
350
+ errorReqMsg={errorReqMsg}
351
+ errorInvalidEmailMsg={
352
+ errorInvalidEmailMsg
353
+ }
354
+ errorInvalidPhoneMsg={
355
+ errorInvalidPhoneMsg
356
+ }
357
+ />
358
+ ) : null;
359
+ })}
360
+ </Suspense>
361
+ )}
362
+ {allowPaymentMethod && (
363
+ <Button
364
+ type="submit"
365
+ loading={loading}
366
+ buttonText={submitButtonText}
367
+ />
310
368
  )}
311
- <Button
312
- type="submit"
313
- loading={loading}
314
- buttonText={submitButtonText}
369
+ <Alert
370
+ className="mt-2"
371
+ msg={
372
+ allowPaymentMethod
373
+ ? apiErrorMsg
374
+ : paymentMethodNotAllowedMsg
375
+ }
315
376
  />
316
- <Alert className="mt-2" msg={apiErrorMsg} />
317
377
  {errorsMsg?.length > 0 &&
378
+ allowPaymentMethod &&
318
379
  errorsMsg.map((i) => <Alert className="mt-2" msg={i} />)}
319
380
  </form>
320
381
  </FormProvider>
@@ -6,3 +6,8 @@ export const WRONG_MSG = 'Something went wrong!';
6
6
 
7
7
  export const PAYMENT_METHOD_DEFAULT: PaymentMethodEnum =
8
8
  PaymentMethodEnum.Vipps;
9
+
10
+ export const INVOICE_ALLOWED_PAYMENT_METHODS = [
11
+ PaymentMethodEnum.Email,
12
+ PaymentMethodEnum.Invoice,
13
+ ];
@@ -23,6 +23,7 @@ export type PaymentMethodOptionsType = {
23
23
  };
24
24
 
25
25
  export type ConfigType = {
26
+ submitStartCallback?: (subscriberId: string) => void;
26
27
  domElementId: string;
27
28
  moduleTitle?: string;
28
29
  templatePackageId: string;
@@ -35,6 +36,7 @@ export type ConfigType = {
35
36
  redirectUrl?: string;
36
37
  showIframe?: boolean;
37
38
  availablePaymentMethods?: { label: string; value: PaymentMethodEnum }[];
39
+ allowedPaymentMethods?: PaymentMethodEnum[];
38
40
  paymentMethodsOptions?: PaymentMethodOptionsType;
39
41
  language?: string;
40
42
  merchantAgreementUrl?: string;
@@ -50,12 +52,14 @@ export type ConfigType = {
50
52
  backButtonText?: string;
51
53
  verifyButtonText?: string;
52
54
  organizationNumberLabel?: string;
55
+ cvrLabel?: string;
53
56
  glnLabel?: string;
54
57
  orderDefaultValues?: OrderFormInputsType;
55
58
  paymentMethodLabel?: string;
56
59
  errorReqMsg?: string;
57
60
  errorInvalidEmailMsg?: string;
58
61
  errorInvalidPhoneMsg?: string;
62
+ paymentMethodNotAllowedMsg?: string;
59
63
  };
60
64
  };
61
65
 
@@ -10,6 +10,7 @@ export type OrderFormInputsType = {
10
10
  address?: string;
11
11
  zip?: string;
12
12
  careOf?: string;
13
+ organizationNumber?: string;
13
14
  invoiceAddressSelection?: boolean;
14
15
  orderReference?: string;
15
16
  invoiceName?: string;
@@ -29,6 +29,7 @@ export const prepareAgreementModel = ({
29
29
  };
30
30
  const existUrl = new URL(window.location.href);
31
31
  const journey = existUrl.searchParams.get('journey');
32
+ const hashToken = existUrl.searchParams.get('hashToken');
32
33
  const url = showIframe
33
34
  ? window.location.href.split('?')[0]
34
35
  : redirectUrl || window.location.href;
@@ -37,6 +38,9 @@ export const prepareAgreementModel = ({
37
38
  if (journey) {
38
39
  cancelUrl.searchParams.append('journey', journey);
39
40
  }
41
+ if (hashToken) {
42
+ cancelUrl.searchParams.append('hashToken', hashToken);
43
+ }
40
44
  const confirmUrl = new URL(url);
41
45
  confirmUrl.searchParams.append(
42
46
  'action',
@@ -45,6 +49,9 @@ export const prepareAgreementModel = ({
45
49
  if (journey) {
46
50
  confirmUrl.searchParams.append('journey', journey);
47
51
  }
52
+ if (hashToken) {
53
+ confirmUrl.searchParams.append('hashToken', hashToken);
54
+ }
48
55
 
49
56
  if (paymentMethod === PaymentMethodEnum.SwedbankPay) {
50
57
  model.swedbankPay = {