mirror of
https://github.com/valitydev/checkout.git
synced 2024-11-06 02:25:18 +00:00
OPS-481: Invoice randomize amount (#313)
This commit is contained in:
parent
43a667f6a5
commit
0adbe879d6
@ -51,6 +51,7 @@
|
|||||||
"form.p2p.complete.button": "إكمال الدفع",
|
"form.p2p.complete.button": "إكمال الدفع",
|
||||||
"form.p2p.complete.loading": "يرجى الانتظار",
|
"form.p2p.complete.loading": "يرجى الانتظار",
|
||||||
"form.p2p.destination.amount": "المبلغ:",
|
"form.p2p.destination.amount": "المبلغ:",
|
||||||
|
"form.p2p.destination.randomizeAmountDescription": "لقد قمنا بتغيير مبلغ التحويل. يساعد ذلك في زيادة احتمال نجاح الدفع.",
|
||||||
"form.p2p.alert.li": ["حول المبلغ الدقيق", "قم بالتحويل كامل المبلغ في تحويلة واحدة"],
|
"form.p2p.alert.li": ["حول المبلغ الدقيق", "قم بالتحويل كامل المبلغ في تحويلة واحدة"],
|
||||||
"form.p2p.alert.p": "وإلا، لن يتم اعتماد الدفع.",
|
"form.p2p.alert.p": "وإلا، لن يتم اعتماد الدفع.",
|
||||||
"form.p2p.gateway.selector.heading": "اختر طريقة أو بنك",
|
"form.p2p.gateway.selector.heading": "اختر طريقة أو بنك",
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
"form.p2p.complete.button": "Köçürmə tamamlandı",
|
"form.p2p.complete.button": "Köçürmə tamamlandı",
|
||||||
"form.p2p.complete.loading": "Lütfən, gözləyin",
|
"form.p2p.complete.loading": "Lütfən, gözləyin",
|
||||||
"form.p2p.destination.amount": "Köçürmə məbləği:",
|
"form.p2p.destination.amount": "Köçürmə məbləği:",
|
||||||
|
"form.p2p.destination.randomizeAmountDescription": "Biz köçürmə məbləğini dəyişdik. Bu, ödənişin uğurlu olma ehtimalını artırır.",
|
||||||
"form.p2p.alert.li": ["Ərizədə göstərilən dəqiq məbləği köçürün", "Bütün məbləği bir köçürmədə ödəyin"],
|
"form.p2p.alert.li": ["Ərizədə göstərilən dəqiq məbləği köçürün", "Bütün məbləği bir köçürmədə ödəyin"],
|
||||||
"form.p2p.alert.p": "Əks halda ödəniş hesaba alınmayacaq.",
|
"form.p2p.alert.p": "Əks halda ödəniş hesaba alınmayacaq.",
|
||||||
"form.p2p.gateway.selector.heading": "Bir metod və ya bank seçin",
|
"form.p2p.gateway.selector.heading": "Bir metod və ya bank seçin",
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
"form.p2p.complete.button": "ট্রান্সফার সম্পন্ন",
|
"form.p2p.complete.button": "ট্রান্সফার সম্পন্ন",
|
||||||
"form.p2p.complete.loading": "অনুগ্রহ করে অপেক্ষা করুন",
|
"form.p2p.complete.loading": "অনুগ্রহ করে অপেক্ষা করুন",
|
||||||
"form.p2p.destination.amount": "পরিমাণ:",
|
"form.p2p.destination.amount": "পরিমাণ:",
|
||||||
|
"form.p2p.destination.randomizeAmountDescription": "আমরা স্থানান্তরের পরিমাণ পরিবর্তন করেছি। এটি সফল পেমেন্টের সম্ভাবনা বাড়াতে সাহায্য করে।",
|
||||||
"form.p2p.alert.li": ["অর্ডারে উল্লিখিত সঠিক পরিমাণ ট্রান্সফার করুন।", "পুরো পরিমাণ একবারে পরিশোধ করুন।"],
|
"form.p2p.alert.li": ["অর্ডারে উল্লিখিত সঠিক পরিমাণ ট্রান্সফার করুন।", "পুরো পরিমাণ একবারে পরিশোধ করুন।"],
|
||||||
"form.p2p.alert.p": "অন্যথায়, পেমেন্ট গৃহীত হবে না।",
|
"form.p2p.alert.p": "অন্যথায়, পেমেন্ট গৃহীত হবে না।",
|
||||||
"form.p2p.gateway.selector.heading": "একটি পদ্ধতি বা ব্যাংক চয়ন করুন",
|
"form.p2p.gateway.selector.heading": "একটি পদ্ধতি বা ব্যাংক চয়ন করুন",
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
"form.p2p.complete.button": "Complete payment",
|
"form.p2p.complete.button": "Complete payment",
|
||||||
"form.p2p.complete.loading": "Please, wait",
|
"form.p2p.complete.loading": "Please, wait",
|
||||||
"form.p2p.destination.amount": "Amount:",
|
"form.p2p.destination.amount": "Amount:",
|
||||||
|
"form.p2p.destination.randomizeAmountDescription": "We have adjusted the transfer amount. This helps increase the chance of a successful payment.",
|
||||||
"form.p2p.alert.li": ["Transfer the exact amount", "Transfer the entire amount in one transaction"],
|
"form.p2p.alert.li": ["Transfer the exact amount", "Transfer the entire amount in one transaction"],
|
||||||
"form.p2p.alert.p": "Otherwise, the payment will not be credited.",
|
"form.p2p.alert.p": "Otherwise, the payment will not be credited.",
|
||||||
"form.p2p.gateway.selector.heading": "Choose a method or bank",
|
"form.p2p.gateway.selector.heading": "Choose a method or bank",
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
"form.p2p.complete.button": "支払い完了",
|
"form.p2p.complete.button": "支払い完了",
|
||||||
"form.p2p.complete.loading": "読み込み中...",
|
"form.p2p.complete.loading": "読み込み中...",
|
||||||
"form.p2p.destination.amount": "金額:",
|
"form.p2p.destination.amount": "金額:",
|
||||||
|
"form.p2p.destination.randomizeAmountDescription": "送金額を変更しました。これにより、支払いが成功する可能性が高まります。",
|
||||||
"form.p2p.alert.li": ["正確な金額を振り込んでください", "全額を一回の取引で振り込んでください"],
|
"form.p2p.alert.li": ["正確な金額を振り込んでください", "全額を一回の取引で振り込んでください"],
|
||||||
"form.p2p.alert.p": "そうしない場合、支払いは認められません。",
|
"form.p2p.alert.p": "そうしない場合、支払いは認められません。",
|
||||||
"form.p2p.gateway.selector.heading": "方法または銀行を選択してください",
|
"form.p2p.gateway.selector.heading": "方法または銀行を選択してください",
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
"form.p2p.complete.button": "이체 완료",
|
"form.p2p.complete.button": "이체 완료",
|
||||||
"form.p2p.complete.loading": "기다려 주십시오",
|
"form.p2p.complete.loading": "기다려 주십시오",
|
||||||
"form.p2p.destination.amount": "금액:",
|
"form.p2p.destination.amount": "금액:",
|
||||||
|
"form.p2p.destination.randomizeAmountDescription": "송금 금액을 조정했습니다. 이는 성공적인 결제 가능성을 높이는 데 도움이 됩니다.",
|
||||||
"form.p2p.alert.li": ["요청한 정확한 금액을 이체하십시오.", "전체 금액을 한 번에 이체하십시오."],
|
"form.p2p.alert.li": ["요청한 정확한 금액을 이체하십시오.", "전체 금액을 한 번에 이체하십시오."],
|
||||||
"form.p2p.alert.p": "그렇지 않으면 결제가 인정되지 않습니다.",
|
"form.p2p.alert.p": "그렇지 않으면 결제가 인정되지 않습니다.",
|
||||||
"form.p2p.gateway.selector.heading": "방법 또는 은행 선택",
|
"form.p2p.gateway.selector.heading": "방법 또는 은행 선택",
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
"form.p2p.complete.button": "Transferência concluída",
|
"form.p2p.complete.button": "Transferência concluída",
|
||||||
"form.p2p.complete.loading": "Por favor, aguarde",
|
"form.p2p.complete.loading": "Por favor, aguarde",
|
||||||
"form.p2p.destination.amount": "Quantia:",
|
"form.p2p.destination.amount": "Quantia:",
|
||||||
|
"form.p2p.destination.randomizeAmountDescription": "Alteramos o valor da transferência. Isso ajuda a aumentar a probabilidade de um pagamento bem-sucedido.",
|
||||||
"form.p2p.alert.li": [
|
"form.p2p.alert.li": [
|
||||||
"Transfira a quantia exata especificada no pedido.",
|
"Transfira a quantia exata especificada no pedido.",
|
||||||
"Pague a quantia total em uma única transferência."
|
"Pague a quantia total em uma única transferência."
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
"form.p2p.complete.button": "Перевод выполнен",
|
"form.p2p.complete.button": "Перевод выполнен",
|
||||||
"form.p2p.complete.loading": "Пожалуйста, подождите",
|
"form.p2p.complete.loading": "Пожалуйста, подождите",
|
||||||
"form.p2p.destination.amount": "Сумма:",
|
"form.p2p.destination.amount": "Сумма:",
|
||||||
|
"form.p2p.destination.randomizeAmountDescription": "Мы изменили сумму перевода. Это помогает повысить вероятность успешного платежа.",
|
||||||
"form.p2p.alert.li": ["Переводите точную сумму, указанную в заявке.", "Оплачивайте всю сумму одним переводом."],
|
"form.p2p.alert.li": ["Переводите точную сумму, указанную в заявке.", "Оплачивайте всю сумму одним переводом."],
|
||||||
"form.p2p.alert.p": "В противном случае платеж не будет зачислен.",
|
"form.p2p.alert.p": "В противном случае платеж не будет зачислен.",
|
||||||
"form.p2p.gateway.selector.heading": "Выберите метод или банк",
|
"form.p2p.gateway.selector.heading": "Выберите метод или банк",
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
"form.p2p.complete.button": "Transfer tamamlandı",
|
"form.p2p.complete.button": "Transfer tamamlandı",
|
||||||
"form.p2p.complete.loading": "Lütfen bekleyin",
|
"form.p2p.complete.loading": "Lütfen bekleyin",
|
||||||
"form.p2p.destination.amount": "Miktar:",
|
"form.p2p.destination.amount": "Miktar:",
|
||||||
|
"form.p2p.destination.randomizeAmountDescription": "Transfer tutarını değiştirdik. Bu, başarılı bir ödeme olasılığını artırır.",
|
||||||
"form.p2p.alert.li": ["Talep edilen kesin miktarı transfer edin.", "Tüm miktarı tek bir transferde ödeyin."],
|
"form.p2p.alert.li": ["Talep edilen kesin miktarı transfer edin.", "Tüm miktarı tek bir transferde ödeyin."],
|
||||||
"form.p2p.alert.p": "Aksi takdirde ödeme alınmayacaktır.",
|
"form.p2p.alert.p": "Aksi takdirde ödeme alınmayacaktır.",
|
||||||
"form.p2p.gateway.selector.heading": "Bir yöntem veya banka seçin",
|
"form.p2p.gateway.selector.heading": "Bir yöntem veya banka seçin",
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
import { ServiceProviderMetadata } from './serviceProviderMetadata';
|
import { ServiceProviderMetadata } from './serviceProviderMetadata';
|
||||||
|
|
||||||
|
export type InvoiceAmountRandomized = {
|
||||||
|
original: number;
|
||||||
|
randomized: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type ClientInfo = {
|
export type ClientInfo = {
|
||||||
fingerprint: string;
|
fingerprint: string;
|
||||||
ip?: string;
|
ip?: string;
|
||||||
@ -275,4 +280,5 @@ export type Invoice = {
|
|||||||
reason: string;
|
reason: string;
|
||||||
cart: InvoiceLine[];
|
cart: InvoiceLine[];
|
||||||
externalID?: string;
|
externalID?: string;
|
||||||
|
amountRandomized?: InvoiceAmountRandomized;
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
import { isNil } from 'checkout/utils';
|
||||||
|
|
||||||
import { InvoiceAndToken } from '../backend/payments';
|
import { InvoiceAndToken } from '../backend/payments';
|
||||||
import { InvoiceContext } from '../paymentModel';
|
import { InvoiceContext } from '../paymentModel';
|
||||||
|
|
||||||
export const invoiceToInvoiceContext = ({
|
export const invoiceToInvoiceContext = ({
|
||||||
invoice: { id, externalID, dueDate, status },
|
invoice: { id, externalID, dueDate, status, amountRandomized },
|
||||||
invoiceAccessToken,
|
invoiceAccessToken,
|
||||||
}: InvoiceAndToken): InvoiceContext => ({
|
}: InvoiceAndToken): InvoiceContext => ({
|
||||||
type: 'InvoiceContext',
|
type: 'InvoiceContext',
|
||||||
@ -13,4 +15,5 @@ export const invoiceToInvoiceContext = ({
|
|||||||
externalID,
|
externalID,
|
||||||
dueDate,
|
dueDate,
|
||||||
status,
|
status,
|
||||||
|
isAmountRandomized: !isNil(amountRandomized),
|
||||||
});
|
});
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { isNil } from 'checkout/utils';
|
||||||
|
|
||||||
import { backendModelToPaymentAmount } from './backendModelToPaymentAmount';
|
import { backendModelToPaymentAmount } from './backendModelToPaymentAmount';
|
||||||
import { backendModelToPaymentMethods } from './backendModelToPaymentMethods';
|
import { backendModelToPaymentMethods } from './backendModelToPaymentMethods';
|
||||||
import { BackendModel, BackendModelInvoice, BackendModelInvoiceTemplate, getBackendModel } from './getBackendModel';
|
import { BackendModel, BackendModelInvoice, BackendModelInvoiceTemplate, getBackendModel } from './getBackendModel';
|
||||||
@ -8,13 +10,14 @@ import { InitParams } from '../init';
|
|||||||
|
|
||||||
const applyInvoice = (
|
const applyInvoice = (
|
||||||
{ invoiceParams, type }: Partial<InvoiceContext>,
|
{ invoiceParams, type }: Partial<InvoiceContext>,
|
||||||
{ invoice: { dueDate, externalID, status } }: BackendModelInvoice,
|
{ invoice: { dueDate, externalID, status, amountRandomized } }: BackendModelInvoice,
|
||||||
): InvoiceContext => ({
|
): InvoiceContext => ({
|
||||||
type,
|
type,
|
||||||
invoiceParams,
|
invoiceParams,
|
||||||
dueDate,
|
dueDate,
|
||||||
externalID,
|
externalID,
|
||||||
status,
|
status,
|
||||||
|
isAmountRandomized: !isNil(amountRandomized),
|
||||||
});
|
});
|
||||||
|
|
||||||
const applyInvoiceTemplate = (
|
const applyInvoiceTemplate = (
|
||||||
|
@ -83,6 +83,7 @@ export type InvoiceContext = {
|
|||||||
readonly dueDate: string;
|
readonly dueDate: string;
|
||||||
readonly status: InvoiceStatus;
|
readonly status: InvoiceStatus;
|
||||||
readonly externalID?: string;
|
readonly externalID?: string;
|
||||||
|
readonly isAmountRandomized: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PaymentModelInvoice = InvoiceContext & CommonPaymentModel;
|
export type PaymentModelInvoice = InvoiceContext & CommonPaymentModel;
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { VStack } from '@chakra-ui/react';
|
import { VStack, Alert, Text, Divider, AlertIcon } from '@chakra-ui/react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
|
|
||||||
import { Destination } from 'checkout/backend/p2p';
|
import { Destination } from 'checkout/backend/p2p';
|
||||||
import { LocaleContext, PaymentModelContext, ViewModelContext } from 'checkout/contexts';
|
import { LocaleContext, PaymentConditionsContext, PaymentModelContext, ViewModelContext } from 'checkout/contexts';
|
||||||
|
import { InvoiceDetermined, PaymentCondition } from 'checkout/paymentCondition';
|
||||||
|
|
||||||
import { DestinationBankAccountInfo } from './DestinationBankAccountInfo';
|
import { DestinationBankAccountInfo } from './DestinationBankAccountInfo';
|
||||||
import { InfoItem } from './InfoItem';
|
import { InfoItem } from './InfoItem';
|
||||||
@ -10,6 +11,9 @@ import { formatCardPan, formatPhoneNumber } from './utils';
|
|||||||
import { SBPIcon } from '../icons/SBPIcon';
|
import { SBPIcon } from '../icons/SBPIcon';
|
||||||
import { getGatewayIcon, mapGatewayName } from '../utils';
|
import { getGatewayIcon, mapGatewayName } from '../utils';
|
||||||
|
|
||||||
|
const isInvoiceDetermined = (condition: PaymentCondition): condition is InvoiceDetermined =>
|
||||||
|
condition.name === 'invoiceDetermined';
|
||||||
|
|
||||||
export type DestinationInfoProps = {
|
export type DestinationInfoProps = {
|
||||||
destination: Destination;
|
destination: Destination;
|
||||||
};
|
};
|
||||||
@ -17,16 +21,29 @@ export type DestinationInfoProps = {
|
|||||||
export function DestinationInfo({ destination }: DestinationInfoProps) {
|
export function DestinationInfo({ destination }: DestinationInfoProps) {
|
||||||
const { l } = useContext(LocaleContext);
|
const { l } = useContext(LocaleContext);
|
||||||
const { viewAmount } = useContext(ViewModelContext);
|
const { viewAmount } = useContext(ViewModelContext);
|
||||||
|
const { paymentModel } = useContext(PaymentModelContext);
|
||||||
|
const { conditions } = useContext(PaymentConditionsContext);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
paymentModel: {
|
invoiceContext: { isAmountRandomized },
|
||||||
paymentAmount: { currency },
|
} = conditions.find<InvoiceDetermined>(isInvoiceDetermined);
|
||||||
},
|
|
||||||
} = useContext(PaymentModelContext);
|
const {
|
||||||
|
paymentAmount: { currency },
|
||||||
|
} = paymentModel;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VStack align="stretch">
|
<VStack align="stretch">
|
||||||
<InfoItem label={l['form.p2p.destination.amount']} value={viewAmount} />
|
<VStack align="stretch">
|
||||||
|
{isAmountRandomized && (
|
||||||
|
<Alert borderRadius="xl" p={3} status="warning">
|
||||||
|
<AlertIcon />
|
||||||
|
<Text fontSize="sm">{l['form.p2p.destination.randomizeAmountDescription']}</Text>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
<InfoItem isDivider={false} label={l['form.p2p.destination.amount']} value={viewAmount} />
|
||||||
|
<Divider />
|
||||||
|
</VStack>
|
||||||
{destination.destinationType === 'BankCard' && (
|
{destination.destinationType === 'BankCard' && (
|
||||||
<InfoItem
|
<InfoItem
|
||||||
formatter={formatCardPan}
|
formatter={formatCardPan}
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import { VStack, Text, Flex, Spacer, Divider, useClipboard, useToast, IconButton, createIcon } from '@chakra-ui/react';
|
import { VStack, Text, Flex, Spacer, Divider, useClipboard, useToast, IconButton, createIcon } from '@chakra-ui/react';
|
||||||
import { ReactElement, cloneElement, useContext, useEffect, useState } from 'react';
|
import { ReactElement, cloneElement, useContext, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { LocaleContext } from 'checkout/contexts';
|
import { LocaleContext } from 'checkout/contexts';
|
||||||
|
import { isNil } from 'checkout/utils';
|
||||||
|
|
||||||
export type InfoItemProps = {
|
export type InfoItemProps = {
|
||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string;
|
||||||
icon?: ReactElement;
|
icon?: ReactElement;
|
||||||
isCopyable?: boolean;
|
isCopyable?: boolean;
|
||||||
|
isDivider?: boolean;
|
||||||
formatter?: (value: string) => Promise<string>;
|
formatter?: (value: string) => Promise<string>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -19,12 +21,19 @@ export const CopyIcon = createIcon({
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function InfoItem({ label, value, isCopyable, formatter, icon }: InfoItemProps) {
|
export function InfoItem({ label, value, isCopyable, formatter, icon, isDivider }: InfoItemProps) {
|
||||||
const { l } = useContext(LocaleContext);
|
const { l } = useContext(LocaleContext);
|
||||||
const { onCopy, hasCopied } = useClipboard(value);
|
const { onCopy, hasCopied } = useClipboard(value);
|
||||||
const [displayValue, setDisplayValue] = useState(value);
|
const [displayValue, setDisplayValue] = useState(value);
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
|
||||||
|
const isDividerVisible = useMemo(() => {
|
||||||
|
if (isNil(isDivider)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return isDivider;
|
||||||
|
}, [isDivider]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!formatter) return;
|
if (!formatter) return;
|
||||||
formatter(value).then(setDisplayValue);
|
formatter(value).then(setDisplayValue);
|
||||||
@ -63,7 +72,7 @@ export function InfoItem({ label, value, isCopyable, formatter, icon }: InfoItem
|
|||||||
{isCopyable && <IconButton aria-label="Copy" icon={<CopyIcon />} size="xs" onClick={onCopy} />}
|
{isCopyable && <IconButton aria-label="Copy" icon={<CopyIcon />} size="xs" onClick={onCopy} />}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Divider />
|
{isDividerVisible && <Divider />}
|
||||||
</VStack>
|
</VStack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user