mirror of
https://github.com/valitydev/checkout.git
synced 2024-11-06 10:35:20 +00:00
Move old backend model to new format (#284)
This commit is contained in:
parent
67746f9556
commit
6a6d7e025f
130
package-lock.json
generated
130
package-lock.json
generated
@ -11,8 +11,8 @@
|
||||
"dependencies": {
|
||||
"@dinero.js/currencies": "2.0.0-alpha.1",
|
||||
"@fingerprintjs/fingerprintjs": "3.4.2",
|
||||
"@sentry/integrations": "7.57.0",
|
||||
"@sentry/react": "7.57.0",
|
||||
"@sentry/integrations": "7.106.1",
|
||||
"@sentry/react": "7.106.1",
|
||||
"card-validator": "8.1.1",
|
||||
"credit-card-type": "9.1.0",
|
||||
"framer-motion": "10.12.18",
|
||||
@ -2761,68 +2761,99 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/tracing": {
|
||||
"version": "7.57.0",
|
||||
"license": "MIT",
|
||||
"node_modules/@sentry-internal/feedback": {
|
||||
"version": "7.106.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.106.1.tgz",
|
||||
"integrity": "sha512-udYR7rQnnQJ0q4PP3R7lTFx7cUz3SB4ghm8T/fJzdItrk+Puv6y8VqI19SFfDgvwgStInEzE5yys6SUQcXLBtA==",
|
||||
"dependencies": {
|
||||
"@sentry/core": "7.57.0",
|
||||
"@sentry/types": "7.57.0",
|
||||
"@sentry/utils": "7.57.0",
|
||||
"tslib": "^2.4.1 || ^1.9.3"
|
||||
"@sentry/core": "7.106.1",
|
||||
"@sentry/types": "7.106.1",
|
||||
"@sentry/utils": "7.106.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay-canvas": {
|
||||
"version": "7.106.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.106.1.tgz",
|
||||
"integrity": "sha512-r+nhLrQuTQih93gZ08F6MLdmaoBy/bQFcVt/2ZVqe1SkDY+MxRlXxq8ydo3FfgEjMRHdody3yT1dj6E174h23w==",
|
||||
"dependencies": {
|
||||
"@sentry/core": "7.106.1",
|
||||
"@sentry/replay": "7.106.1",
|
||||
"@sentry/types": "7.106.1",
|
||||
"@sentry/utils": "7.106.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/tracing": {
|
||||
"version": "7.106.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.106.1.tgz",
|
||||
"integrity": "sha512-Ui9zSmW88jTdmNnNBLYYpNoAi31esX5/auysC3v7+SpwxIsC3AGLFvXs4EPziyz8d0F62Ji0fNQZ96ui4fO6BQ==",
|
||||
"dependencies": {
|
||||
"@sentry/core": "7.106.1",
|
||||
"@sentry/types": "7.106.1",
|
||||
"@sentry/utils": "7.106.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/browser": {
|
||||
"version": "7.57.0",
|
||||
"license": "MIT",
|
||||
"version": "7.106.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.106.1.tgz",
|
||||
"integrity": "sha512-+Yp7OUx78ZwFFYfIvOKZGjMPW7Ds3zZSO8dsMxvDRzkA9NyyAmYMZ/dNTcsGb+PssgkCasF2XA07f6WgkNW92A==",
|
||||
"dependencies": {
|
||||
"@sentry-internal/tracing": "7.57.0",
|
||||
"@sentry/core": "7.57.0",
|
||||
"@sentry/replay": "7.57.0",
|
||||
"@sentry/types": "7.57.0",
|
||||
"@sentry/utils": "7.57.0",
|
||||
"tslib": "^2.4.1 || ^1.9.3"
|
||||
"@sentry-internal/feedback": "7.106.1",
|
||||
"@sentry-internal/replay-canvas": "7.106.1",
|
||||
"@sentry-internal/tracing": "7.106.1",
|
||||
"@sentry/core": "7.106.1",
|
||||
"@sentry/replay": "7.106.1",
|
||||
"@sentry/types": "7.106.1",
|
||||
"@sentry/utils": "7.106.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "7.57.0",
|
||||
"license": "MIT",
|
||||
"version": "7.106.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.106.1.tgz",
|
||||
"integrity": "sha512-cwCd66wkbutXCI8j14JLkyod9RHtqSNfzGpx/ieBE+N786jX+Yj1DiaZJ6ZYjKQpnToipFnacEakCd9Vc9oePA==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "7.57.0",
|
||||
"@sentry/utils": "7.57.0",
|
||||
"tslib": "^2.4.1 || ^1.9.3"
|
||||
"@sentry/types": "7.106.1",
|
||||
"@sentry/utils": "7.106.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/integrations": {
|
||||
"version": "7.57.0",
|
||||
"license": "MIT",
|
||||
"version": "7.106.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.106.1.tgz",
|
||||
"integrity": "sha512-2wIDaHGWE5QOnTAkQe5itH32K3gcZ5rluAWxcq+hG+xZd7JA6EDGnDEMHieGweFbkYazBteSE8qaxjDUAGYYJA==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "7.57.0",
|
||||
"@sentry/utils": "7.57.0",
|
||||
"localforage": "^1.8.1",
|
||||
"tslib": "^2.4.1 || ^1.9.3"
|
||||
"@sentry/core": "7.106.1",
|
||||
"@sentry/types": "7.106.1",
|
||||
"@sentry/utils": "7.106.1",
|
||||
"localforage": "^1.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/react": {
|
||||
"version": "7.57.0",
|
||||
"license": "MIT",
|
||||
"version": "7.106.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.106.1.tgz",
|
||||
"integrity": "sha512-XcvjXGist0vLapzxZxdbPSdLC4drhGOETtlA/kO+KrIKqlqRKuYw+kieU+YeyF9A/L8uSVvbj9rpjl5WVUTdIw==",
|
||||
"dependencies": {
|
||||
"@sentry/browser": "7.57.0",
|
||||
"@sentry/types": "7.57.0",
|
||||
"@sentry/utils": "7.57.0",
|
||||
"hoist-non-react-statics": "^3.3.2",
|
||||
"tslib": "^2.4.1 || ^1.9.3"
|
||||
"@sentry/browser": "7.106.1",
|
||||
"@sentry/core": "7.106.1",
|
||||
"@sentry/types": "7.106.1",
|
||||
"@sentry/utils": "7.106.1",
|
||||
"hoist-non-react-statics": "^3.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@ -2832,30 +2863,33 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/replay": {
|
||||
"version": "7.57.0",
|
||||
"license": "MIT",
|
||||
"version": "7.106.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.106.1.tgz",
|
||||
"integrity": "sha512-UnuY6bj7v7CVv3T1sbLHjLutSG4hzcQQj6CjEB2NUpM+QAIguFrwAcYG4U42iNg4Qeg5q4kHi1rPpdpvh6unSA==",
|
||||
"dependencies": {
|
||||
"@sentry/core": "7.57.0",
|
||||
"@sentry/types": "7.57.0",
|
||||
"@sentry/utils": "7.57.0"
|
||||
"@sentry-internal/tracing": "7.106.1",
|
||||
"@sentry/core": "7.106.1",
|
||||
"@sentry/types": "7.106.1",
|
||||
"@sentry/utils": "7.106.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/types": {
|
||||
"version": "7.57.0",
|
||||
"license": "MIT",
|
||||
"version": "7.106.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.106.1.tgz",
|
||||
"integrity": "sha512-g3OcyAHGugBwkQP4fZYCCZqF2ng9K7yQc9FVngKq/y7PwHm84epXdYYGDGgfQOIC1d5/GMaPxmzI5IIrZexzkg==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/utils": {
|
||||
"version": "7.57.0",
|
||||
"license": "MIT",
|
||||
"version": "7.106.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.106.1.tgz",
|
||||
"integrity": "sha512-NIeuvB9MeDwrObbi6W5xRrNTcQj8klVvwWWYQB0zotY/LDjyl+c+cZzUshFOxBTp9ljVnYzWqZ7J8x/i4baj7w==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "7.57.0",
|
||||
"tslib": "^2.4.1 || ^1.9.3"
|
||||
"@sentry/types": "7.106.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@ -9072,10 +9106,6 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "1.14.1",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.3.2",
|
||||
"dev": true,
|
||||
|
@ -18,8 +18,8 @@
|
||||
"dependencies": {
|
||||
"@dinero.js/currencies": "2.0.0-alpha.1",
|
||||
"@fingerprintjs/fingerprintjs": "3.4.2",
|
||||
"@sentry/integrations": "7.57.0",
|
||||
"@sentry/react": "7.57.0",
|
||||
"@sentry/integrations": "7.106.1",
|
||||
"@sentry/react": "7.106.1",
|
||||
"card-validator": "8.1.1",
|
||||
"credit-card-type": "9.1.0",
|
||||
"framer-motion": "10.12.18",
|
||||
|
@ -35,7 +35,7 @@ creditCardType.addCard({
|
||||
});
|
||||
|
||||
const initSentry = async (dsn: string) => {
|
||||
const { init, BrowserTracing, Replay } = await import('@sentry/react');
|
||||
const { init, BrowserTracing } = await import('@sentry/react');
|
||||
const { CaptureConsole } = await import('@sentry/integrations');
|
||||
const env = await getEnv();
|
||||
init({
|
||||
@ -44,14 +44,11 @@ const initSentry = async (dsn: string) => {
|
||||
integrations: [
|
||||
new BrowserTracing(),
|
||||
new CaptureConsole({
|
||||
levels: ['error'],
|
||||
levels: ['error', 'warn'],
|
||||
}),
|
||||
new Replay(),
|
||||
],
|
||||
tracesSampleRate: 0.1,
|
||||
release: env.version,
|
||||
replaysOnErrorSampleRate: 1.0,
|
||||
replaysSessionSampleRate: 0.1,
|
||||
});
|
||||
};
|
||||
|
||||
|
19
src/common/backend/payments/createInvoiceWithTemplate.ts
Normal file
19
src/common/backend/payments/createInvoiceWithTemplate.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { InvoiceAndToken } from './types';
|
||||
import { fetchApi } from '../../../common/utils';
|
||||
|
||||
export type InvoiceParamsWithTemplate = {
|
||||
amount: number;
|
||||
currency: string;
|
||||
metadata: object;
|
||||
};
|
||||
|
||||
export const createInvoiceWithTemplate = async (
|
||||
capiEndpoint: string,
|
||||
accessToken: string,
|
||||
invoiceTemplateID: string,
|
||||
params: InvoiceParamsWithTemplate,
|
||||
): Promise<InvoiceAndToken> => {
|
||||
const path = `v2/processing/invoice-templates/${invoiceTemplateID}/invoices`;
|
||||
const response = await fetchApi(capiEndpoint, accessToken, 'POST', path, params);
|
||||
return response.json();
|
||||
};
|
12
src/common/backend/payments/getInvoiceByID.ts
Normal file
12
src/common/backend/payments/getInvoiceByID.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Invoice } from './types';
|
||||
import { fetchApi } from '../../../common/utils';
|
||||
|
||||
export const getInvoiceByID = async (
|
||||
capiEndpoint: string,
|
||||
accessToken: string,
|
||||
invoiceID: string,
|
||||
): Promise<Invoice> => {
|
||||
const path = `v2/processing/invoices/${invoiceID}`;
|
||||
const response = await fetchApi(capiEndpoint, accessToken, 'GET', path);
|
||||
return response.json();
|
||||
};
|
20
src/common/backend/payments/getInvoiceEvents.ts
Normal file
20
src/common/backend/payments/getInvoiceEvents.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { InvoiceEvent } from './types';
|
||||
import { fetchApi, isNil } from '../../../common/utils';
|
||||
|
||||
export const getInvoiceEvents = async (
|
||||
capiEndpoint: string,
|
||||
accessToken: string,
|
||||
invoiceID: string,
|
||||
limit: number,
|
||||
eventID?: number,
|
||||
): Promise<InvoiceEvent[]> => {
|
||||
const queryParams = new URLSearchParams({
|
||||
limit: limit.toString(),
|
||||
});
|
||||
if (!isNil(eventID)) {
|
||||
queryParams.append('eventID', eventID.toString());
|
||||
}
|
||||
const path = `v2/processing/invoices/${invoiceID}/events?${queryParams.toString()}`;
|
||||
const response = await fetchApi(capiEndpoint, accessToken, 'GET', path);
|
||||
return response.json();
|
||||
};
|
12
src/common/backend/payments/getInvoicePaymentMethods.ts
Normal file
12
src/common/backend/payments/getInvoicePaymentMethods.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { PaymentMethod } from './types';
|
||||
import { fetchApi } from '../../../common/utils';
|
||||
|
||||
export const getInvoicePaymentMethods = async (
|
||||
capiEndpoint: string,
|
||||
accessToken: string,
|
||||
invoiceID: string,
|
||||
): Promise<PaymentMethod[]> => {
|
||||
const path = `v2/processing/invoices/${invoiceID}/payment-methods`;
|
||||
const response = await fetchApi(capiEndpoint, accessToken, 'GET', path);
|
||||
return response.json();
|
||||
};
|
@ -0,0 +1,12 @@
|
||||
import { PaymentMethod } from './types';
|
||||
import { fetchApi } from '../../../common/utils';
|
||||
|
||||
export const getInvoicePaymentMethodsByTemplateID = async (
|
||||
capiEndpoint: string,
|
||||
accessToken: string,
|
||||
invoiceTemplateID: string,
|
||||
): Promise<PaymentMethod[]> => {
|
||||
const path = `v2/processing/invoice-templates/${invoiceTemplateID}/payment-methods`;
|
||||
const response = await fetchApi(capiEndpoint, accessToken, 'GET', path);
|
||||
return response.json();
|
||||
};
|
12
src/common/backend/payments/getInvoiceTemplateByID.ts
Normal file
12
src/common/backend/payments/getInvoiceTemplateByID.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { InvoiceTemplate } from './types';
|
||||
import { fetchApi } from '../../../common/utils';
|
||||
|
||||
export const getInvoiceTemplateByID = async (
|
||||
capiEndpoint: string,
|
||||
accessToken: string,
|
||||
invoiceTemplateID: string,
|
||||
): Promise<InvoiceTemplate> => {
|
||||
const path = `v2/processing/invoice-templates/${invoiceTemplateID}`;
|
||||
const response = await fetchApi(capiEndpoint, accessToken, 'GET', path);
|
||||
return response.json();
|
||||
};
|
12
src/common/backend/payments/getServiceProviderByID.ts
Normal file
12
src/common/backend/payments/getServiceProviderByID.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { ServiceProvider } from './types';
|
||||
import { fetchApi } from '../../../common/utils';
|
||||
|
||||
export const getServiceProviderByID = async (
|
||||
capiEndpoint: string,
|
||||
accessToken: string,
|
||||
serviceProviderID: string,
|
||||
): Promise<ServiceProvider> => {
|
||||
const path = `v2/processing/service-providers/${serviceProviderID}`;
|
||||
const response = await fetchApi(capiEndpoint, accessToken, 'GET', path);
|
||||
return response.json();
|
||||
};
|
38
src/common/backend/payments/index.ts
Normal file
38
src/common/backend/payments/index.ts
Normal file
@ -0,0 +1,38 @@
|
||||
export { getInvoiceByID } from './getInvoiceByID';
|
||||
export { getInvoicePaymentMethods } from './getInvoicePaymentMethods';
|
||||
export { getServiceProviderByID } from './getServiceProviderByID';
|
||||
export { getInvoiceTemplateByID } from './getInvoiceTemplateByID';
|
||||
export { getInvoicePaymentMethodsByTemplateID } from './getInvoicePaymentMethodsByTemplateID';
|
||||
export { getInvoiceEvents } from './getInvoiceEvents';
|
||||
export { createInvoiceWithTemplate } from './createInvoiceWithTemplate';
|
||||
|
||||
export type {
|
||||
Invoice,
|
||||
InvoiceAndToken,
|
||||
InvoiceStatus,
|
||||
InvoiceEvent,
|
||||
InvoiceChangeType,
|
||||
PaymentMethod,
|
||||
ServiceProvider,
|
||||
Payment,
|
||||
PaymentStatus,
|
||||
PaymentError,
|
||||
InvoiceTemplate,
|
||||
InvoiceTemplateMultiLine,
|
||||
InvoiceTemplateSingleLine,
|
||||
InvoiceTemplateLineCostFixed,
|
||||
PaymentStarted,
|
||||
UserInteraction,
|
||||
BrowserRequest,
|
||||
BrowserGetRequest,
|
||||
BrowserPostRequest,
|
||||
UserInteractionForm,
|
||||
} from './types';
|
||||
|
||||
export type {
|
||||
ServiceProviderMetadata,
|
||||
CheckoutServiceProviderMetadata,
|
||||
ServiceProviderContactInfo,
|
||||
ServiceProviderMetadataField,
|
||||
METADATA_NAMESPACE,
|
||||
} from './serviceProviderMetadata';
|
96
src/common/backend/payments/serviceProviderMetadata.ts
Normal file
96
src/common/backend/payments/serviceProviderMetadata.ts
Normal file
@ -0,0 +1,96 @@
|
||||
export const METADATA_NAMESPACE = 'dev.vality.checkout';
|
||||
|
||||
export type MetadataTextLocalization = {
|
||||
ja?: string;
|
||||
en?: string;
|
||||
ru?: string;
|
||||
pt?: string;
|
||||
};
|
||||
|
||||
export type MetadataFieldFormatter = {
|
||||
type: 'numbersOnly';
|
||||
maxLength?: number;
|
||||
};
|
||||
|
||||
export type AttributeType = JSX.IntrinsicElements['input']['type'];
|
||||
export type AttributeInputMode = JSX.IntrinsicElements['input']['inputMode'];
|
||||
|
||||
export type ServiceProviderMetadataField = {
|
||||
type: AttributeType;
|
||||
name: string;
|
||||
required: boolean;
|
||||
pattern?: string;
|
||||
localization?: MetadataTextLocalization;
|
||||
index?: number;
|
||||
formatter?: MetadataFieldFormatter;
|
||||
inputMode?: AttributeInputMode;
|
||||
addon?: 'vpa';
|
||||
replaceValuePattern?: string;
|
||||
};
|
||||
|
||||
export type MetadataSelectSource = {
|
||||
type: 'countrySubdivisions';
|
||||
countryCode?: string;
|
||||
};
|
||||
|
||||
export type ServiceProviderMetadataSelect = {
|
||||
type: 'select';
|
||||
name: string;
|
||||
required: boolean;
|
||||
src: MetadataSelectSource;
|
||||
localization?: MetadataTextLocalization;
|
||||
index?: number;
|
||||
};
|
||||
|
||||
export type ServiceProviderIconMetadata = {
|
||||
src: string;
|
||||
width: string;
|
||||
height: string;
|
||||
};
|
||||
|
||||
export type ServiceProviderTitleMetadata = {
|
||||
icon: 'wallets' | 'online-banking' | 'bank-card';
|
||||
localization?: MetadataTextLocalization;
|
||||
};
|
||||
|
||||
export type ServiceProviderContactInfo = {
|
||||
email: boolean;
|
||||
phoneNumber: boolean;
|
||||
};
|
||||
|
||||
export type UserInteractionMetadata = {
|
||||
type: 'frame' | 'self';
|
||||
};
|
||||
|
||||
export type QrCodeFormMetadata = {
|
||||
isCopyCodeBlock: boolean;
|
||||
qrCodeRedirect: 'mobile' | 'none';
|
||||
};
|
||||
|
||||
export type PaymentSessionInfoMetadata = {
|
||||
redirectUrlInfo: {
|
||||
type: 'self' | 'outer';
|
||||
};
|
||||
};
|
||||
|
||||
export type PrefilledMetadataValues = {
|
||||
[key: string]: string | number | boolean;
|
||||
};
|
||||
|
||||
export type ServiceProviderMetadataForm = ServiceProviderMetadataField[] | ServiceProviderMetadataSelect[];
|
||||
|
||||
export type CheckoutServiceProviderMetadata = {
|
||||
form?: ServiceProviderMetadataForm;
|
||||
logo?: ServiceProviderIconMetadata;
|
||||
title?: ServiceProviderTitleMetadata;
|
||||
signUpLink?: string;
|
||||
contactInfo?: ServiceProviderContactInfo;
|
||||
userInteraction?: UserInteractionMetadata;
|
||||
qrCodeForm?: QrCodeFormMetadata;
|
||||
paymentSessionInfo?: PaymentSessionInfoMetadata;
|
||||
prefilledMetadataValues?: PrefilledMetadataValues;
|
||||
};
|
||||
|
||||
export type ServiceProviderMetadata = {
|
||||
[METADATA_NAMESPACE]: CheckoutServiceProviderMetadata;
|
||||
};
|
264
src/common/backend/payments/types.ts
Normal file
264
src/common/backend/payments/types.ts
Normal file
@ -0,0 +1,264 @@
|
||||
import { ServiceProviderMetadata } from './serviceProviderMetadata';
|
||||
|
||||
export type PaymentError = {
|
||||
code: string;
|
||||
subError?: PaymentError;
|
||||
};
|
||||
|
||||
export type PaymentFlowInstant = {
|
||||
type: 'PaymentFlowInstant';
|
||||
};
|
||||
|
||||
export type PaymentFlowHold = {
|
||||
type: 'PaymentFlowHold';
|
||||
onHoldExpiration: 'cancel' | 'capture';
|
||||
heldUntil?: string;
|
||||
};
|
||||
|
||||
export type PaymentFlow = PaymentFlowInstant | PaymentFlowHold;
|
||||
|
||||
export type ContactInfo = {
|
||||
email: string;
|
||||
phoneNumber: string;
|
||||
};
|
||||
|
||||
export type PaymentToolDetailsBankCard = {
|
||||
detailsType: 'PaymentToolDetailsBankCard';
|
||||
cardNumberMask: string;
|
||||
first6: string;
|
||||
last4: string;
|
||||
paymentSystem: string;
|
||||
};
|
||||
|
||||
export type PaymentToolDetailsPaymentTerminal = {
|
||||
detailsType: 'PaymentToolDetailsPaymentTerminal';
|
||||
provider: string;
|
||||
};
|
||||
|
||||
export type PaymentToolDetails = PaymentToolDetailsBankCard | PaymentToolDetailsPaymentTerminal;
|
||||
|
||||
export type PaymentResourcePayer = {
|
||||
payerType: 'PaymentResourcePayer';
|
||||
contactInfo: ContactInfo;
|
||||
paymentToolToken?: string;
|
||||
paymentSession?: string;
|
||||
sessionInfo?: {
|
||||
redirectUrl: string;
|
||||
};
|
||||
paymentToolDetails?: PaymentToolDetails;
|
||||
};
|
||||
|
||||
export type Payer = PaymentResourcePayer;
|
||||
|
||||
export type Payment = {
|
||||
id: string;
|
||||
invoiceID: string;
|
||||
createdAt: string;
|
||||
amount: number;
|
||||
currency: string;
|
||||
flow: PaymentFlow;
|
||||
payer: Payer;
|
||||
status: PaymentStatus;
|
||||
error: PaymentError;
|
||||
externalID: string;
|
||||
};
|
||||
|
||||
export type PaymentStatus = 'processed' | 'failed' | 'cancelled' | 'pending' | 'captured' | 'refunded';
|
||||
|
||||
export type UserInteractionForm = {
|
||||
key: string;
|
||||
template: string;
|
||||
};
|
||||
|
||||
export type BrowserGetRequest = {
|
||||
requestType: 'BrowserGetRequest';
|
||||
uriTemplate: string;
|
||||
};
|
||||
|
||||
export type BrowserPostRequest = {
|
||||
requestType: 'BrowserPostRequest';
|
||||
uriTemplate: string;
|
||||
form: UserInteractionForm[];
|
||||
};
|
||||
|
||||
export type BrowserRequest = BrowserGetRequest | BrowserPostRequest;
|
||||
|
||||
export type ApiExtensionRequest = {
|
||||
interactionType: 'ApiExtensionRequest';
|
||||
apiType: string;
|
||||
};
|
||||
|
||||
export type QrCodeDisplayRequest = {
|
||||
interactionType: 'QrCodeDisplayRequest';
|
||||
qrCode: string;
|
||||
};
|
||||
|
||||
export type Redirect = {
|
||||
interactionType: 'Redirect';
|
||||
request: BrowserRequest;
|
||||
};
|
||||
|
||||
export type UserInteraction = ApiExtensionRequest | QrCodeDisplayRequest | Redirect;
|
||||
|
||||
export type PaymentInteractionRequested = {
|
||||
changeType: 'PaymentInteractionRequested';
|
||||
paymentID: string;
|
||||
userInteraction: UserInteraction;
|
||||
};
|
||||
|
||||
export type PaymentInteractionCompleted = {
|
||||
changeType: 'PaymentInteractionCompleted';
|
||||
paymentID: string;
|
||||
userInteraction?: UserInteraction;
|
||||
};
|
||||
|
||||
export type PaymentStatusChanged = {
|
||||
changeType: 'PaymentStatusChanged';
|
||||
status: PaymentStatus;
|
||||
paymentID: string;
|
||||
error?: PaymentError;
|
||||
};
|
||||
|
||||
export type PaymentStarted = {
|
||||
changeType: 'PaymentStarted';
|
||||
payment: Payment;
|
||||
};
|
||||
|
||||
export type InvoiceStatusChanged = {
|
||||
changeType: 'InvoiceStatusChanged';
|
||||
status: InvoiceStatus;
|
||||
reason?: string;
|
||||
};
|
||||
|
||||
export type InvoiceCreated = {
|
||||
changeType: 'InvoiceCreated';
|
||||
invoice: Invoice;
|
||||
};
|
||||
|
||||
export type InvoiceChangeType =
|
||||
| 'InvoiceCreated'
|
||||
| 'InvoiceStatusChanged'
|
||||
| 'PaymentStatusChanged'
|
||||
| 'PaymentStarted'
|
||||
| 'PaymentInteractionRequested'
|
||||
| 'PaymentInteractionCompleted';
|
||||
|
||||
export type InvoiceChange =
|
||||
| InvoiceCreated
|
||||
| InvoiceStatusChanged
|
||||
| PaymentStatusChanged
|
||||
| PaymentStarted
|
||||
| PaymentInteractionRequested
|
||||
| PaymentInteractionCompleted;
|
||||
|
||||
export type InvoiceEvent = {
|
||||
id: number;
|
||||
createdAt: string;
|
||||
changes: InvoiceChange[];
|
||||
};
|
||||
|
||||
type LifetimeInterval = {
|
||||
days: number;
|
||||
months: number;
|
||||
years: number;
|
||||
};
|
||||
|
||||
type InvoiceLine = {
|
||||
product: string;
|
||||
quantity: number;
|
||||
price: number;
|
||||
cost: number;
|
||||
};
|
||||
|
||||
type CostAmountRange = {
|
||||
lowerBound: number;
|
||||
upperBound: number;
|
||||
};
|
||||
|
||||
export type InvoiceTemplateLineCostUnlim = {
|
||||
costType: 'InvoiceTemplateLineCostUnlim';
|
||||
};
|
||||
|
||||
export type InvoiceTemplateLineCostRange = {
|
||||
costType: 'InvoiceTemplateLineCostRange';
|
||||
range: CostAmountRange;
|
||||
currency: string;
|
||||
};
|
||||
|
||||
export type InvoiceTemplateLineCostFixed = {
|
||||
costType: 'InvoiceTemplateLineCostFixed';
|
||||
amount: number;
|
||||
currency: string;
|
||||
};
|
||||
|
||||
export type InvoiceTemplateSingleLine = {
|
||||
templateType: 'InvoiceTemplateSingleLine';
|
||||
product: string;
|
||||
price: InvoiceTemplateLineCostFixed | InvoiceTemplateLineCostRange | InvoiceTemplateLineCostUnlim;
|
||||
};
|
||||
|
||||
export type InvoiceTemplateMultiLine = {
|
||||
templateType: 'InvoiceTemplateMultiLine';
|
||||
cart: InvoiceLine[];
|
||||
currency: string;
|
||||
};
|
||||
|
||||
export type InvoiceTemplate = {
|
||||
id: string;
|
||||
shopID: string;
|
||||
product: string;
|
||||
description: string;
|
||||
lifetime: LifetimeInterval;
|
||||
details: InvoiceTemplateMultiLine | InvoiceTemplateSingleLine;
|
||||
metadata: object;
|
||||
};
|
||||
|
||||
export type ServiceProvider = {
|
||||
id: string;
|
||||
brandName: string;
|
||||
category: string;
|
||||
metadata?: ServiceProviderMetadata;
|
||||
};
|
||||
|
||||
export type PaymentTerminal = {
|
||||
method: 'PaymentTerminal';
|
||||
providers: string[];
|
||||
};
|
||||
|
||||
export type DigitalWallet = {
|
||||
method: 'DigitalWallet';
|
||||
providers: string[];
|
||||
};
|
||||
|
||||
export type BankCard = {
|
||||
method: 'BankCard';
|
||||
paymentSystems: string[];
|
||||
};
|
||||
|
||||
export type PaymentMethod = PaymentTerminal | BankCard | DigitalWallet;
|
||||
|
||||
export type InvoiceStatus = 'unpaid' | 'cancelled' | 'paid' | 'fulfilled';
|
||||
|
||||
export type InvoiceAndToken = {
|
||||
invoice: Invoice;
|
||||
invoiceAccessToken: {
|
||||
payload: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type Invoice = {
|
||||
id: string;
|
||||
shopID: string;
|
||||
invoiceTemplateID: string;
|
||||
createdAt: string;
|
||||
dueDate: string;
|
||||
amount: number;
|
||||
currency: string;
|
||||
metadata: object;
|
||||
product: string;
|
||||
description: string;
|
||||
status: InvoiceStatus;
|
||||
reason: string;
|
||||
cart: InvoiceLine[];
|
||||
externalID: string;
|
||||
};
|
@ -1,14 +1,8 @@
|
||||
import {
|
||||
InvoiceStatuses,
|
||||
ServiceProviderContactInfo,
|
||||
ServiceProviderMetadataField,
|
||||
getInvoiceEvents,
|
||||
} from 'checkout/backend';
|
||||
|
||||
import { PaymentCondition } from './types';
|
||||
import { invoiceEventsToConditions, provideInstantPayment } from './utils';
|
||||
import { ServiceProviderContactInfo, ServiceProviderMetadataField, getInvoiceEvents } from '../backend/payments';
|
||||
import { InitContext, PaymentModel, PaymentModelInvoice, PaymentTerminal } from '../paymentModel';
|
||||
import { extractError, isNil, last } from '../utils';
|
||||
import { extractError, isNil, last, withRetry } from '../utils';
|
||||
import { findMetadata } from '../utils/findMetadata';
|
||||
|
||||
/*
|
||||
@ -94,7 +88,8 @@ const provideInvoiceUnpaid = async (model: PaymentModelInvoice): Promise<Payment
|
||||
apiEndpoint,
|
||||
initContext: { skipUserInteraction },
|
||||
} = model;
|
||||
const events = await getInvoiceEvents(
|
||||
const getInvoiceEventsWithRetry = withRetry(getInvoiceEvents);
|
||||
const events = await getInvoiceEventsWithRetry(
|
||||
apiEndpoint,
|
||||
invoiceParams.invoiceAccessToken,
|
||||
invoiceParams.invoiceID,
|
||||
@ -125,12 +120,11 @@ const provideInvoiceUnpaid = async (model: PaymentModelInvoice): Promise<Payment
|
||||
|
||||
const provideInvoice = async (model: PaymentModelInvoice): Promise<PaymentCondition[]> => {
|
||||
switch (model.status) {
|
||||
case InvoiceStatuses.cancelled:
|
||||
case InvoiceStatuses.fulfilled:
|
||||
case InvoiceStatuses.paid:
|
||||
case InvoiceStatuses.refunded:
|
||||
case 'cancelled':
|
||||
case 'fulfilled':
|
||||
case 'paid':
|
||||
return [{ name: 'invoiceStatusChanged', status: model.status }];
|
||||
case InvoiceStatuses.unpaid:
|
||||
case 'unpaid':
|
||||
return provideInvoiceUnpaid(model);
|
||||
}
|
||||
};
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { BrowserRequest, InvoiceStatuses, PaymentError, PaymentStatuses } from 'checkout/backend';
|
||||
|
||||
import { BrowserRequest, InvoiceStatus, PaymentError, PaymentStatus } from '../backend/payments';
|
||||
import { InvoiceContext } from '../paymentModel';
|
||||
|
||||
export type InvoiceDetermined = {
|
||||
@ -29,7 +28,7 @@ export type PaymentStatusChanged = {
|
||||
name: 'paymentStatusChanged';
|
||||
eventId: number;
|
||||
paymentId: string;
|
||||
status: PaymentStatuses;
|
||||
status: PaymentStatus;
|
||||
error?: PaymentError;
|
||||
};
|
||||
|
||||
@ -39,7 +38,7 @@ export type PaymentStatusUnknown = {
|
||||
|
||||
export type InvoiceStatusChanged = {
|
||||
name: 'invoiceStatusChanged';
|
||||
status: InvoiceStatuses;
|
||||
status: InvoiceStatus;
|
||||
};
|
||||
|
||||
export type PaymentInteractionRedirectType = 'frame' | 'self';
|
||||
|
@ -1,47 +1,31 @@
|
||||
import {
|
||||
InteractionType,
|
||||
InvoiceChangeType,
|
||||
InvoiceEvent,
|
||||
PaymentInteractionCompleted,
|
||||
PaymentInteractionRequested,
|
||||
PaymentResourcePayer,
|
||||
PaymentStarted,
|
||||
PaymentStatusChanged,
|
||||
PaymentToolDetailsPaymentTerminal,
|
||||
PaymentToolDetailsType,
|
||||
QrCodeDisplayRequest,
|
||||
Redirect,
|
||||
UserInteraction,
|
||||
} from 'checkout/backend';
|
||||
|
||||
import { InvoiceEvent, PaymentStarted, UserInteraction } from '../../../common/backend/payments';
|
||||
import { isNil } from '../../../common/utils';
|
||||
import { Interaction, PaymentCondition } from '../types';
|
||||
|
||||
const getProvider = (started: PaymentStarted): string | null => {
|
||||
const payer = (started as PaymentStarted).payment.payer;
|
||||
const paymentToolDetails = (payer as PaymentResourcePayer).paymentToolDetails;
|
||||
if (paymentToolDetails.detailsType === PaymentToolDetailsType.PaymentToolDetailsPaymentTerminal) {
|
||||
return (paymentToolDetails as PaymentToolDetailsPaymentTerminal).provider;
|
||||
const paymentToolDetails = started.payment.payer.paymentToolDetails;
|
||||
if (paymentToolDetails.detailsType === 'PaymentToolDetailsPaymentTerminal') {
|
||||
return paymentToolDetails.provider;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const toInteraction = (userInteraction: UserInteraction, skipUserInteraction: boolean): Interaction | null => {
|
||||
switch (userInteraction.interactionType) {
|
||||
case InteractionType.Redirect:
|
||||
case 'Redirect':
|
||||
if (skipUserInteraction) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
type: 'PaymentInteractionRedirect',
|
||||
request: (userInteraction as Redirect).request,
|
||||
request: userInteraction.request,
|
||||
};
|
||||
case InteractionType.QrCodeDisplayRequest:
|
||||
case 'QrCodeDisplayRequest':
|
||||
return {
|
||||
type: 'PaymentInteractionQRCode',
|
||||
qrCode: (userInteraction as QrCodeDisplayRequest).qrCode,
|
||||
qrCode: userInteraction.qrCode,
|
||||
};
|
||||
case InteractionType.ApiExtensionRequest:
|
||||
case 'ApiExtensionRequest':
|
||||
return {
|
||||
type: 'PaymentInteractionApiExtension',
|
||||
};
|
||||
@ -52,34 +36,31 @@ export const invoiceEventsToConditions = (events: InvoiceEvent[], skipUserIntera
|
||||
return events.reduce((result, { changes, id }) => {
|
||||
const conditions = changes.reduce((acc, change) => {
|
||||
switch (change.changeType) {
|
||||
case InvoiceChangeType.PaymentStarted: {
|
||||
const started = change as PaymentStarted;
|
||||
case 'PaymentStarted': {
|
||||
return [
|
||||
...acc,
|
||||
{
|
||||
name: 'paymentStarted',
|
||||
eventId: id,
|
||||
provider: getProvider(started),
|
||||
paymentId: started.payment.id,
|
||||
provider: getProvider(change),
|
||||
paymentId: change.payment.id,
|
||||
},
|
||||
];
|
||||
}
|
||||
case InvoiceChangeType.PaymentStatusChanged: {
|
||||
const statusChanged = change as PaymentStatusChanged;
|
||||
case 'PaymentStatusChanged': {
|
||||
return [
|
||||
...acc,
|
||||
{
|
||||
name: 'paymentStatusChanged',
|
||||
eventId: id,
|
||||
status: statusChanged.status,
|
||||
paymentId: statusChanged.paymentID,
|
||||
error: statusChanged?.error,
|
||||
status: change.status,
|
||||
paymentId: change.paymentID,
|
||||
error: change?.error,
|
||||
},
|
||||
];
|
||||
}
|
||||
case InvoiceChangeType.PaymentInteractionRequested: {
|
||||
const interactionRequested = change as PaymentInteractionRequested;
|
||||
const interaction = toInteraction(interactionRequested.userInteraction, skipUserInteraction);
|
||||
case 'PaymentInteractionRequested': {
|
||||
const interaction = toInteraction(change.userInteraction, skipUserInteraction);
|
||||
if (isNil(interaction)) {
|
||||
return acc;
|
||||
}
|
||||
@ -88,19 +69,18 @@ export const invoiceEventsToConditions = (events: InvoiceEvent[], skipUserIntera
|
||||
{
|
||||
name: 'interactionRequested',
|
||||
eventId: id,
|
||||
interaction: toInteraction(interactionRequested.userInteraction, skipUserInteraction),
|
||||
paymentId: interactionRequested.paymentID,
|
||||
interaction: toInteraction(change.userInteraction, skipUserInteraction),
|
||||
paymentId: change.paymentID,
|
||||
},
|
||||
];
|
||||
}
|
||||
case InvoiceChangeType.PaymentInteractionCompleted: {
|
||||
const interactionCompleted = change as PaymentInteractionCompleted;
|
||||
case 'PaymentInteractionCompleted': {
|
||||
return [
|
||||
...acc,
|
||||
{
|
||||
name: 'interactionCompleted',
|
||||
eventId: id,
|
||||
paymentId: interactionCompleted.paymentID,
|
||||
paymentId: change.paymentID,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { createInvoiceWithTemplate as request } from 'checkout/backend';
|
||||
|
||||
import { invoiceToInvoiceContext } from './invoiceToInvoiceContext';
|
||||
import { createInvoiceWithTemplate as request } from '../backend/payments';
|
||||
import { InvoiceContext, PaymentModelInvoiceTemplate } from '../paymentModel';
|
||||
|
||||
export const createInvoiceWithTemplate = async (model: PaymentModelInvoiceTemplate): Promise<InvoiceContext> => {
|
||||
|
@ -1,19 +1,16 @@
|
||||
import { InvoiceAndToken } from 'checkout/backend';
|
||||
|
||||
import { InvoiceAndToken } from '../backend/payments';
|
||||
import { InvoiceContext } from '../paymentModel';
|
||||
|
||||
export const invoiceToInvoiceContext = ({
|
||||
invoice: { id, externalID, dueDate, status },
|
||||
invoiceAccessToken,
|
||||
}: InvoiceAndToken): InvoiceContext => {
|
||||
return {
|
||||
type: 'InvoiceContext',
|
||||
invoiceParams: {
|
||||
invoiceID: id,
|
||||
invoiceAccessToken: invoiceAccessToken.payload,
|
||||
},
|
||||
externalID,
|
||||
dueDate,
|
||||
status,
|
||||
};
|
||||
};
|
||||
}: InvoiceAndToken): InvoiceContext => ({
|
||||
type: 'InvoiceContext',
|
||||
invoiceParams: {
|
||||
invoiceID: id,
|
||||
invoiceAccessToken: invoiceAccessToken.payload,
|
||||
},
|
||||
externalID,
|
||||
dueDate,
|
||||
status,
|
||||
});
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { InvoiceChangeType, InvoiceEvent, getInvoiceEvents } from 'checkout/backend';
|
||||
|
||||
import { delay, isNil, last } from '../utils';
|
||||
import { InvoiceChangeType, InvoiceEvent, getInvoiceEvents } from '../backend/payments';
|
||||
import { delay, extractError, isNil, last } from '../utils';
|
||||
|
||||
const GET_INVOICE_EVENTS_LIMIT = 20;
|
||||
|
||||
@ -16,9 +15,24 @@ const isChangeFound = (event: InvoiceEvent | undefined, stopPollingTypes: Invoic
|
||||
}, false);
|
||||
};
|
||||
|
||||
const fetchInvoiceEventsSafe = async (
|
||||
capiEndpoint: string,
|
||||
accessToken: string,
|
||||
invoiceID: string,
|
||||
limit: number,
|
||||
eventID?: number,
|
||||
): Promise<InvoiceEvent[]> => {
|
||||
try {
|
||||
return await getInvoiceEvents(capiEndpoint, accessToken, invoiceID, limit, eventID);
|
||||
} catch (exception) {
|
||||
console.warn(`Failed to fetch invoice events. ${extractError(exception)}`);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const fetchEvents = async (params: PollInvoiceEventsParams, isStop: () => boolean): Promise<PollingResult> => {
|
||||
const { apiEndpoint, invoiceAccessToken, invoiceID, startFromEventID, stopPollingTypes, delays } = params;
|
||||
const events = await getInvoiceEvents(
|
||||
const events = await fetchInvoiceEventsSafe(
|
||||
apiEndpoint,
|
||||
invoiceAccessToken,
|
||||
invoiceID,
|
||||
|
@ -1,13 +1,6 @@
|
||||
import {
|
||||
CostType,
|
||||
InvoiceTemplateLineCostFixed,
|
||||
InvoiceTemplateMultiLine,
|
||||
InvoiceTemplateSingleLine,
|
||||
TemplateType,
|
||||
} from 'checkout/backend';
|
||||
|
||||
import { BackendModel, BackendModelInvoice, BackendModelInvoiceTemplate } from './getBackendModel';
|
||||
import { PaymentAmount } from './types';
|
||||
import { InvoiceTemplateLineCostFixed, InvoiceTemplateMultiLine, InvoiceTemplateSingleLine } from '../backend/payments';
|
||||
|
||||
const fromInvoiceTemplateMultiLine = (details: InvoiceTemplateMultiLine): PaymentAmount => ({
|
||||
value: details.cart.reduce((p, c) => p + c.price * c.quantity, 0),
|
||||
@ -22,10 +15,10 @@ const fromInvoiceTemplateLineCostFixed = (fixed: InvoiceTemplateLineCostFixed):
|
||||
export const fromInvoiceTemplateSingleLine = (details: InvoiceTemplateSingleLine): PaymentAmount => {
|
||||
const price = details.price;
|
||||
switch (price.costType) {
|
||||
case CostType.InvoiceTemplateLineCostFixed:
|
||||
case 'InvoiceTemplateLineCostFixed':
|
||||
return fromInvoiceTemplateLineCostFixed(price as InvoiceTemplateLineCostFixed);
|
||||
case CostType.InvoiceTemplateLineCostRange:
|
||||
case CostType.InvoiceTemplateLineCostUnlim:
|
||||
case 'InvoiceTemplateLineCostRange':
|
||||
case 'InvoiceTemplateLineCostUnlim':
|
||||
throw new Error(`Unsupported invoice template cost type: ${price.costType}`);
|
||||
}
|
||||
};
|
||||
@ -33,9 +26,9 @@ export const fromInvoiceTemplateSingleLine = (details: InvoiceTemplateSingleLine
|
||||
const fromInvoiceTemplate = ({ invoiceTemplate }: BackendModelInvoiceTemplate): PaymentAmount => {
|
||||
const details = invoiceTemplate.details;
|
||||
switch (details.templateType) {
|
||||
case TemplateType.InvoiceTemplateMultiLine:
|
||||
case 'InvoiceTemplateMultiLine':
|
||||
return fromInvoiceTemplateMultiLine(details as InvoiceTemplateMultiLine);
|
||||
case TemplateType.InvoiceTemplateSingleLine:
|
||||
case 'InvoiceTemplateSingleLine':
|
||||
return fromInvoiceTemplateSingleLine(details as InvoiceTemplateSingleLine);
|
||||
}
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { PaymentMethodName, PaymentTerminal, ServiceProvider } from 'checkout/backend';
|
||||
|
||||
import { BackendModel } from './getBackendModel';
|
||||
import { KnownProviderCategory, PaymentMethod } from './types';
|
||||
import { ServiceProvider } from '../backend/payments';
|
||||
import { assertUnreachable, groupBy } from '../utils';
|
||||
|
||||
const categoryReducer = (
|
||||
@ -47,11 +46,10 @@ const fromPaymentTerminal = (terminalProviderIDs: string[], serviceProviders: Se
|
||||
export const backendModelToPaymentMethods = (model: BackendModel): PaymentMethod[] => {
|
||||
return model.paymentMethods.reduce((result, backendPaymentMethod) => {
|
||||
switch (backendPaymentMethod.method) {
|
||||
case PaymentMethodName.BankCard:
|
||||
case 'BankCard':
|
||||
return result.concat([{ methodName: 'BankCard' }]);
|
||||
case PaymentMethodName.PaymentTerminal:
|
||||
const terminal = backendPaymentMethod as PaymentTerminal;
|
||||
return result.concat(fromPaymentTerminal(terminal.providers, model.serviceProviders));
|
||||
case 'PaymentTerminal':
|
||||
return result.concat(fromPaymentTerminal(backendPaymentMethod.providers, model.serviceProviders));
|
||||
default:
|
||||
return result;
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { getServiceProviders } from './getServiceProviders';
|
||||
import { InvoiceContext, InvoiceParams, InvoiceTemplateContext, InvoiceTemplateParams } from './types';
|
||||
import {
|
||||
Invoice,
|
||||
InvoiceTemplate,
|
||||
@ -7,10 +9,8 @@ import {
|
||||
getInvoicePaymentMethods,
|
||||
getInvoicePaymentMethodsByTemplateID,
|
||||
getInvoiceTemplateByID,
|
||||
} from 'checkout/backend';
|
||||
|
||||
import { getServiceProviders } from './getServiceProviders';
|
||||
import { InvoiceContext, InvoiceParams, InvoiceTemplateContext, InvoiceTemplateParams } from './types';
|
||||
} from '../backend/payments';
|
||||
import { withRetry } from '../utils';
|
||||
|
||||
type CommonBackendModel = {
|
||||
paymentMethods: PaymentMethod[];
|
||||
@ -33,9 +33,11 @@ const getInvoiceTemplateModel = async (
|
||||
apiEndpoint: string,
|
||||
{ invoiceTemplateID, invoiceTemplateAccessToken }: InvoiceTemplateParams,
|
||||
): Promise<BackendModelInvoiceTemplate> => {
|
||||
const getInvoiceTemplateByIDWithRetry = withRetry(getInvoiceTemplateByID);
|
||||
const getInvoicePaymentMethodsByTemplateIDWithRetry = withRetry(getInvoicePaymentMethodsByTemplateID);
|
||||
const [invoiceTemplate, paymentMethods] = await Promise.all([
|
||||
getInvoiceTemplateByID(apiEndpoint, invoiceTemplateAccessToken, invoiceTemplateID),
|
||||
getInvoicePaymentMethodsByTemplateID(apiEndpoint, invoiceTemplateAccessToken, invoiceTemplateID),
|
||||
getInvoiceTemplateByIDWithRetry(apiEndpoint, invoiceTemplateAccessToken, invoiceTemplateID),
|
||||
getInvoicePaymentMethodsByTemplateIDWithRetry(apiEndpoint, invoiceTemplateAccessToken, invoiceTemplateID),
|
||||
]);
|
||||
const serviceProviders = await getServiceProviders(paymentMethods, apiEndpoint, invoiceTemplateAccessToken);
|
||||
return { type: 'BackendModelInvoiceTemplate', paymentMethods, invoiceTemplate, serviceProviders };
|
||||
@ -45,9 +47,11 @@ const getInvoiceModel = async (
|
||||
apiEndpoint: string,
|
||||
{ invoiceID, invoiceAccessToken }: InvoiceParams,
|
||||
): Promise<BackendModelInvoice> => {
|
||||
const getInvoiceByIDWithRetry = withRetry(getInvoiceByID);
|
||||
const getInvoicePaymentMethodsWithRetry = withRetry(getInvoicePaymentMethods);
|
||||
const [invoice, paymentMethods] = await Promise.all([
|
||||
getInvoiceByID(apiEndpoint, invoiceAccessToken, invoiceID),
|
||||
getInvoicePaymentMethods(apiEndpoint, invoiceAccessToken, invoiceID),
|
||||
getInvoiceByIDWithRetry(apiEndpoint, invoiceAccessToken, invoiceID),
|
||||
getInvoicePaymentMethodsWithRetry(apiEndpoint, invoiceAccessToken, invoiceID),
|
||||
]);
|
||||
const serviceProviders = await getServiceProviders(paymentMethods, apiEndpoint, invoiceAccessToken);
|
||||
return { type: 'BackendModelInvoice', paymentMethods, invoice, serviceProviders };
|
||||
|
@ -1,33 +1,12 @@
|
||||
import {
|
||||
getServiceProviderByID,
|
||||
PaymentMethod,
|
||||
PaymentMethodName,
|
||||
PaymentTerminal,
|
||||
ServiceProvider,
|
||||
} from 'checkout/backend';
|
||||
|
||||
import { isNil } from '../utils';
|
||||
|
||||
export async function getServiceProviderOrNull(
|
||||
endpoint: string,
|
||||
accessToken: string,
|
||||
id: string,
|
||||
): Promise<ServiceProvider | null> {
|
||||
try {
|
||||
return await getServiceProviderByID(endpoint, accessToken, id);
|
||||
} catch (err) {
|
||||
console.error(`Failed to load provider "${id}".`, err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
import { PaymentMethod, ServiceProvider, getServiceProviderByID } from '../backend/payments';
|
||||
import { isNil, withRetry } from '../utils';
|
||||
|
||||
const providerIDsReducer = (result: string[], method: PaymentMethod): string[] => {
|
||||
switch (method.method) {
|
||||
case PaymentMethodName.PaymentTerminal:
|
||||
case PaymentMethodName.DigitalWallet:
|
||||
const terminalMethod = method as PaymentTerminal;
|
||||
if (!isNil(terminalMethod.providers)) {
|
||||
return result.concat(terminalMethod.providers);
|
||||
case 'PaymentTerminal':
|
||||
case 'DigitalWallet':
|
||||
if (!isNil(method.providers)) {
|
||||
return result.concat(method.providers);
|
||||
}
|
||||
return result;
|
||||
default:
|
||||
@ -35,6 +14,8 @@ const providerIDsReducer = (result: string[], method: PaymentMethod): string[] =
|
||||
}
|
||||
};
|
||||
|
||||
const getServiceProviderByIDWithRetry = withRetry(getServiceProviderByID);
|
||||
|
||||
export const getServiceProviders = async (
|
||||
paymentMethods: PaymentMethod[],
|
||||
endpoint: string,
|
||||
@ -42,7 +23,7 @@ export const getServiceProviders = async (
|
||||
): Promise<ServiceProvider[]> => {
|
||||
const providerIDs = paymentMethods.reduce(providerIDsReducer, []);
|
||||
const serviceProvidersOrNull = await Promise.all(
|
||||
providerIDs.map((id) => getServiceProviderOrNull(endpoint, accessToken, id)),
|
||||
providerIDs.map((id) => getServiceProviderByIDWithRetry(endpoint, accessToken, id)),
|
||||
);
|
||||
return serviceProvidersOrNull.filter((provider): provider is ServiceProvider => !isNil(provider));
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { InvoiceStatuses, ServiceProviderMetadata } from 'checkout/backend';
|
||||
import { InvoiceStatus, ServiceProviderMetadata } from '../backend/payments';
|
||||
|
||||
export type PaymentAmount = {
|
||||
readonly value: number;
|
||||
@ -81,7 +81,7 @@ export type InvoiceContext = {
|
||||
readonly invoiceParams: InvoiceParams;
|
||||
readonly dueDate: string;
|
||||
readonly externalID: string;
|
||||
readonly status: InvoiceStatuses;
|
||||
readonly status: InvoiceStatus;
|
||||
};
|
||||
|
||||
export type PaymentModelInvoice = InvoiceContext & CommonPaymentModel;
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { useCallback, useReducer } from 'react';
|
||||
import { extractError } from 'src/common/utils';
|
||||
|
||||
import { InitParams } from 'checkout/initialize';
|
||||
|
||||
import { initPaymentCondition, PaymentCondition } from '../../common/paymentCondition';
|
||||
import { initPaymentModel, PaymentModel } from '../../common/paymentModel';
|
||||
import { extractError } from '../../common/utils';
|
||||
|
||||
type ModelsStateData = {
|
||||
paymentModel: PaymentModel;
|
||||
@ -61,7 +61,7 @@ export const useInitModels = () => {
|
||||
payload: { paymentModel, conditions },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`useInitModels error: ${extractError(error)}`, error);
|
||||
console.error(`useInitModels error. ${extractError(error)}`);
|
||||
dispatch({ type: 'INIT_FAILED', error });
|
||||
}
|
||||
})();
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { useContext, useEffect, useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { BrowserRequest } from 'checkout/backend';
|
||||
|
||||
import { prepareForm } from './utils';
|
||||
import { BrowserRequest } from '../../common/backend/payments';
|
||||
import { PaymentContext } from '../../common/contexts';
|
||||
import { device, isNil } from '../../common/utils';
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { BrowserRequest } from 'checkout/backend';
|
||||
|
||||
import { prepareForm } from './utils';
|
||||
import { BrowserRequest } from '../../common/backend/payments';
|
||||
import { LayoutLoader } from '../legacy';
|
||||
|
||||
const RedirectContainer = styled.div`
|
||||
|
@ -1,22 +1,21 @@
|
||||
import { BrowserPostRequest, BrowserRequest, RequestType } from 'checkout/backend';
|
||||
|
||||
import { toGetFormInputs } from './toGetFormInputs';
|
||||
import { toPostFormInputs } from './toPostFormInputs';
|
||||
import { BrowserRequest } from '../../../common/backend/payments';
|
||||
|
||||
const toInputs = (origin: string, request: BrowserRequest): HTMLInputElement[] => {
|
||||
switch (request.requestType) {
|
||||
case RequestType.BrowserPostRequest:
|
||||
return toPostFormInputs(origin, (request as BrowserPostRequest).form);
|
||||
case RequestType.BrowserGetRequest:
|
||||
case 'BrowserPostRequest':
|
||||
return toPostFormInputs(origin, request.form);
|
||||
case 'BrowserGetRequest':
|
||||
return toGetFormInputs(origin, request);
|
||||
}
|
||||
};
|
||||
|
||||
const toMethod = (request: BrowserRequest): 'POST' | 'GET' => {
|
||||
switch (request.requestType) {
|
||||
case RequestType.BrowserPostRequest:
|
||||
case 'BrowserPostRequest':
|
||||
return 'POST';
|
||||
case RequestType.BrowserGetRequest:
|
||||
case 'BrowserGetRequest':
|
||||
return 'GET';
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BrowserGetRequest } from 'checkout/backend';
|
||||
|
||||
import { expandWithRedirect, hasTerminationUriTemplate } from './expandWithRedirect';
|
||||
import { BrowserGetRequest } from '../../../common/backend/payments';
|
||||
import { getEncodedUrlParams } from '../../../common/utils';
|
||||
|
||||
const createInput = (name: string, value: any): HTMLInputElement => {
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { FormField } from 'checkout/backend';
|
||||
|
||||
import { expandWithRedirect } from './expandWithRedirect';
|
||||
import { UserInteractionForm } from '../../../common/backend/payments';
|
||||
|
||||
const createInput = (origin: string, formField: FormField): HTMLInputElement => {
|
||||
const createInput = (origin: string, formField: UserInteractionForm): HTMLInputElement => {
|
||||
const formParam = document.createElement('input');
|
||||
formParam.name = formField.key;
|
||||
formField.key === 'TermUrl'
|
||||
@ -11,5 +10,5 @@ const createInput = (origin: string, formField: FormField): HTMLInputElement =>
|
||||
return formParam;
|
||||
};
|
||||
|
||||
export const toPostFormInputs = (origin: string, form: FormField[]): HTMLInputElement[] =>
|
||||
export const toPostFormInputs = (origin: string, form: UserInteractionForm[]): HTMLInputElement[] =>
|
||||
form.map((field) => createInput(origin, field));
|
||||
|
@ -1,59 +1,52 @@
|
||||
import { InvoiceStatuses, PaymentStatuses } from 'checkout/backend';
|
||||
|
||||
import { InvoiceStatusChanged, PaymentCondition, PaymentStatusChanged } from '../../../../common/paymentCondition';
|
||||
import { ResultInfo } from '../types';
|
||||
|
||||
const fromInvoiceStatusChanged = (condition: InvoiceStatusChanged): ResultInfo => {
|
||||
switch (condition.status) {
|
||||
case InvoiceStatuses.paid:
|
||||
case 'paid':
|
||||
return {
|
||||
iconName: 'SuccessIcon',
|
||||
label: 'form.header.final.invoice.paid.label',
|
||||
};
|
||||
case InvoiceStatuses.cancelled:
|
||||
case 'cancelled':
|
||||
return {
|
||||
iconName: 'WarningIcon',
|
||||
label: 'form.header.final.invoice.cancelled.label',
|
||||
};
|
||||
case InvoiceStatuses.fulfilled:
|
||||
case 'fulfilled':
|
||||
return {
|
||||
iconName: 'WarningIcon',
|
||||
label: 'form.header.final.invoice.fulfilled.label',
|
||||
};
|
||||
case InvoiceStatuses.refunded:
|
||||
return {
|
||||
iconName: 'WarningIcon',
|
||||
label: 'form.header.final.invoice.refunded.label',
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const fromPaymentStatusChanged = (condition: PaymentStatusChanged): ResultInfo => {
|
||||
switch (condition.status) {
|
||||
case PaymentStatuses.captured:
|
||||
case PaymentStatuses.processed:
|
||||
case 'captured':
|
||||
case 'processed':
|
||||
return {
|
||||
iconName: 'SuccessIcon',
|
||||
label: 'form.header.final.success.label',
|
||||
};
|
||||
case PaymentStatuses.cancelled:
|
||||
case 'cancelled':
|
||||
return {
|
||||
iconName: 'WarningIcon',
|
||||
label: 'form.header.final.cancelled.label',
|
||||
};
|
||||
case PaymentStatuses.refunded:
|
||||
case 'refunded':
|
||||
return {
|
||||
iconName: 'WarningIcon',
|
||||
label: 'form.header.final.refunded.label',
|
||||
};
|
||||
case PaymentStatuses.pending:
|
||||
case 'pending':
|
||||
return {
|
||||
iconName: 'WarningIcon',
|
||||
label: 'form.header.final.pending.label',
|
||||
description: 'form.header.final.pending.description',
|
||||
hasActions: true,
|
||||
};
|
||||
case PaymentStatuses.failed:
|
||||
case 'failed':
|
||||
const error = condition.error;
|
||||
return {
|
||||
iconName: 'ErrorIcon',
|
||||
|
Loading…
Reference in New Issue
Block a user