@12-apps/payments-frontend 3.47.1 → 3.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/components/platform/HomologacaoEvidenceCard.tsx +27 -13
- package/src/components/platform/HomologacaoEvidenceProgress.tsx +120 -0
- package/src/components/platform/HomologacaoEvidenceWallets.tsx +13 -10
- package/src/components/platform/copy.ts +12 -1
- package/src/components/platform/en-US.ts +22 -3
- package/src/components/platform/pt-BR.ts +22 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@12-apps/payments-frontend",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.48.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "Browser half of the vendor-agnostic payments platform: plug-and-play MUI components for the per-provider settings page (credential form from each provider's schema, masked hints, verify/enable) and the checkout page (PIX QR + polling, card tokenization, hosted-checkout redirect), plus the headless hooks and fetch clients they build on. Talks only to the host's payments HTTP surface — never to a provider directly. Microfrontend-ready: no app coupling, host injects theme and auth.",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"storybook:build": "storybook build"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@12-apps/payments-backend": "^4.
|
|
26
|
+
"@12-apps/payments-backend": "^4.39.0",
|
|
27
27
|
"react-qr-code": "^2.2.0"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { Alert, Box, Button,
|
|
3
|
+
import { Alert, Box, Button, Stack, Typography } from '@mui/material';
|
|
4
4
|
import { useState, type ReactNode } from 'react';
|
|
5
5
|
|
|
6
6
|
import type {
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
BrowserCardResult,
|
|
9
9
|
BrowserWalletResult,
|
|
10
10
|
DebitTestData,
|
|
11
|
+
EvidenceRunSection,
|
|
11
12
|
EvidenceSummary,
|
|
12
13
|
EvidenceWalletsConfig,
|
|
13
14
|
PaymentEnvironment,
|
|
@@ -21,6 +22,7 @@ import type { GooglePayApi } from '../checkout/google-pay-button';
|
|
|
21
22
|
import { CARD_SX, TAP_SX } from './ConnectEnvironmentCard';
|
|
22
23
|
import type { PlatformHomologacaoCopy } from './copy';
|
|
23
24
|
import { PlatformCopyProvider, usePlatformCopy } from './copy-context';
|
|
25
|
+
import { EvidenceProgress, type EvidencePhase } from './HomologacaoEvidenceProgress';
|
|
24
26
|
import { EvidenceWalletBlock, useEvidenceWallets, type EvidenceWallets } from './HomologacaoEvidenceWallets';
|
|
25
27
|
|
|
26
28
|
/**
|
|
@@ -78,9 +80,15 @@ export interface HomologacaoEvidenceCardProps {
|
|
|
78
80
|
}>;
|
|
79
81
|
/**
|
|
80
82
|
* Phase 2 — raise the orders with the encrypted cards and, for each wallet,
|
|
81
|
-
* the token its sheet gave (or the code saying why there is none).
|
|
83
|
+
* the token its sheet gave (or the code saying why there is none). The host
|
|
84
|
+
* calls `onSection` as the server starts each section, for the step list.
|
|
82
85
|
*/
|
|
83
|
-
onRun: (
|
|
86
|
+
onRun: (
|
|
87
|
+
runId: string,
|
|
88
|
+
cards: BrowserCardResult[],
|
|
89
|
+
wallets: BrowserWalletResult[],
|
|
90
|
+
onSection: (section: EvidenceRunSection) => void,
|
|
91
|
+
) => Promise<void>;
|
|
84
92
|
/**
|
|
85
93
|
* The host's Apple Pay merchant validation (FUT-3755): exchange Apple's
|
|
86
94
|
* `validationURL` for a merchant session, server-side. Absent, the Apple Pay
|
|
@@ -93,8 +101,8 @@ export interface HomologacaoEvidenceCardProps {
|
|
|
93
101
|
onDownload: () => Promise<EvidenceSummary>;
|
|
94
102
|
}
|
|
95
103
|
|
|
96
|
-
type Phase = 'idle' |
|
|
97
|
-
type ActivePhase =
|
|
104
|
+
type Phase = 'idle' | EvidencePhase;
|
|
105
|
+
type ActivePhase = EvidencePhase;
|
|
98
106
|
|
|
99
107
|
type TestCard = typeof PAGBANK_3DS_TEST_CARD;
|
|
100
108
|
|
|
@@ -236,9 +244,17 @@ function useEvidenceRun(
|
|
|
236
244
|
const [phase, setPhase] = useState<Phase>('idle');
|
|
237
245
|
const [summary, setSummary] = useState<EvidenceSummary | null>(null);
|
|
238
246
|
const [failed, setFailed] = useState<ActivePhase | null>(null);
|
|
247
|
+
// What the step list draws: the server's section, and the tokens this run took.
|
|
248
|
+
const [section, setSection] = useState<EvidenceRunSection | null>(null);
|
|
249
|
+
const [scope, setScope] = useState<{ full: boolean; walletResults: BrowserWalletResult[] | null }>({
|
|
250
|
+
full: false,
|
|
251
|
+
walletResults: null,
|
|
252
|
+
});
|
|
239
253
|
const run = async (full: boolean): Promise<void> => {
|
|
240
254
|
setFailed(null);
|
|
241
255
|
setSummary(null);
|
|
256
|
+
setSection(null);
|
|
257
|
+
setScope({ full, walletResults: null });
|
|
242
258
|
// The phase that throws is the one the operator is told about.
|
|
243
259
|
let current: ActivePhase = full ? 'preparing' : 'downloading';
|
|
244
260
|
const enter = (next: ActivePhase): void => {
|
|
@@ -251,11 +267,12 @@ function useEvidenceRun(
|
|
|
251
267
|
// The sheets ran before this chain: what they answered, taken once.
|
|
252
268
|
const walletResults = wallets.collect();
|
|
253
269
|
wallets.reset();
|
|
270
|
+
setScope({ full, walletResults });
|
|
254
271
|
const prepared = await onPrepare();
|
|
255
272
|
enter('encrypting');
|
|
256
273
|
const cards = await prepareTestCards(prepared);
|
|
257
274
|
enter('running');
|
|
258
|
-
await onRun(prepared.runId, cards, walletResults);
|
|
275
|
+
await onRun(prepared.runId, cards, walletResults, setSection);
|
|
259
276
|
}
|
|
260
277
|
enter('downloading');
|
|
261
278
|
setSummary(await onDownload());
|
|
@@ -265,7 +282,7 @@ function useEvidenceRun(
|
|
|
265
282
|
setPhase('idle');
|
|
266
283
|
}
|
|
267
284
|
};
|
|
268
|
-
return { phase, busy: phase !== 'idle', summary, failed, run };
|
|
285
|
+
return { phase, section, scope, busy: phase !== 'idle', summary, failed, run };
|
|
269
286
|
}
|
|
270
287
|
|
|
271
288
|
/** How the last return from PagBank ended — with the recorded reason when it failed. */
|
|
@@ -290,7 +307,7 @@ function EvidenceBody(props: HomologacaoEvidenceCardProps): ReactNode {
|
|
|
290
307
|
validateApplePayMerchant: props.onValidateApplePayMerchant,
|
|
291
308
|
googlePayApi: props.googlePayApi,
|
|
292
309
|
});
|
|
293
|
-
const { phase, busy, summary, failed, run } = useEvidenceRun(props, wallets);
|
|
310
|
+
const { phase, section, scope, busy, summary, failed, run } = useEvidenceRun(props, wallets);
|
|
294
311
|
return (
|
|
295
312
|
<Stack spacing={1.5} data-testid="homologacao-evidence-card" sx={CARD_SX}>
|
|
296
313
|
<Typography variant="body2" fontWeight={600}>
|
|
@@ -324,11 +341,8 @@ function EvidenceBody(props: HomologacaoEvidenceCardProps): ReactNode {
|
|
|
324
341
|
{copy.downloadLatest}
|
|
325
342
|
</Button>
|
|
326
343
|
</Stack>
|
|
327
|
-
{
|
|
328
|
-
<
|
|
329
|
-
<Typography variant="body2">{copy.phases[phase as ActivePhase]}</Typography>
|
|
330
|
-
<LinearProgress />
|
|
331
|
-
</Stack>
|
|
344
|
+
{phase !== 'idle' ? (
|
|
345
|
+
<EvidenceProgress phase={phase} section={section} full={scope.full} walletResults={scope.walletResults} />
|
|
332
346
|
) : null}
|
|
333
347
|
<EvidenceResult summary={summary} failed={failed} />
|
|
334
348
|
</Stack>
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Box, CircularProgress, LinearProgress, Stack, SvgIcon, Typography } from '@mui/material';
|
|
4
|
+
import type { ReactNode } from 'react';
|
|
5
|
+
|
|
6
|
+
import type { BrowserWalletResult, EvidenceRunSection } from '@12-apps/payments-backend';
|
|
7
|
+
|
|
8
|
+
import { usePlatformCopy } from './copy-context';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The evidence run's progress, one line per step (FUT-3755): a run takes
|
|
12
|
+
* minutes — every cancel is retried while the sandbox answers 40008 — so the
|
|
13
|
+
* operator sees which step is done, which one is going, and which wallets this
|
|
14
|
+
* generation carries (their sheets were tapped BEFORE "generate", and the
|
|
15
|
+
* buttons reset once the tokens are taken).
|
|
16
|
+
*
|
|
17
|
+
* The sections come from the host as the server starts each one; the card
|
|
18
|
+
* never guesses one. A download-only press shows the file step alone.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export type EvidencePhase = 'preparing' | 'encrypting' | 'running' | 'downloading';
|
|
22
|
+
type EvidenceRunStep = 'prepare' | 'encrypt' | EvidenceRunSection | 'file';
|
|
23
|
+
|
|
24
|
+
// The server's section order (`EVIDENCE_RUN_SECTIONS`), spelled here: this
|
|
25
|
+
// package may import only types from the backend (ADOPTING.md §6).
|
|
26
|
+
const SECTIONS: readonly EvidenceRunSection[] = ['PIX', 'CARD', 'DEBIT', 'GOOGLE_PAY', 'APPLE_PAY'];
|
|
27
|
+
const FULL_RUN: readonly EvidenceRunStep[] = ['prepare', 'encrypt', ...SECTIONS, 'file'];
|
|
28
|
+
const DOWNLOAD_ONLY: readonly EvidenceRunStep[] = ['file'];
|
|
29
|
+
|
|
30
|
+
/** The step a phase — and, while running, the server's section — is on. */
|
|
31
|
+
function currentEvidenceStep(phase: EvidencePhase, section: EvidenceRunSection | null): EvidenceRunStep {
|
|
32
|
+
if (phase === 'preparing') return 'prepare';
|
|
33
|
+
if (phase === 'encrypting') return 'encrypt';
|
|
34
|
+
if (phase === 'running') return section ?? 'PIX';
|
|
35
|
+
return 'file';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface EvidenceProgressProps {
|
|
39
|
+
phase: EvidencePhase;
|
|
40
|
+
section: EvidenceRunSection | null;
|
|
41
|
+
/** False for "download the latest recorded": nothing is run. */
|
|
42
|
+
full: boolean;
|
|
43
|
+
/** What the wallet sheets answered for this run; null on a download-only press. */
|
|
44
|
+
walletResults: BrowserWalletResult[] | null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Material Symbols' check_circle and radio_button_unchecked, inline: the
|
|
48
|
+
// package takes no icons dependency (see `../checkout/icons.tsx`).
|
|
49
|
+
const DONE_PATH = 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8z';
|
|
50
|
+
const PENDING_PATH =
|
|
51
|
+
'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8';
|
|
52
|
+
|
|
53
|
+
/** Shape, not only colour, tells the three states apart. */
|
|
54
|
+
function StepMark({ state }: { state: 'done' | 'current' | 'pending' }): ReactNode {
|
|
55
|
+
if (state === 'current') return <CircularProgress size={18} thickness={5} />;
|
|
56
|
+
return (
|
|
57
|
+
<SvgIcon fontSize="small" color={state === 'done' ? 'success' : 'disabled'}>
|
|
58
|
+
<path d={state === 'done' ? DONE_PATH : PENDING_PATH} />
|
|
59
|
+
</SvgIcon>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Which wallets this run carries a token for, and which stay pending. */
|
|
64
|
+
function WalletsLine({ results }: { results: BrowserWalletResult[] }): ReactNode {
|
|
65
|
+
const copy = usePlatformCopy().evidence;
|
|
66
|
+
const names = copy.wallets.names;
|
|
67
|
+
const included = (['GOOGLE_PAY', 'APPLE_PAY'] as const).filter((type) =>
|
|
68
|
+
results.some((result) => result.type === type && result.token),
|
|
69
|
+
);
|
|
70
|
+
const left = (['GOOGLE_PAY', 'APPLE_PAY'] as const).filter((type) => !included.includes(type));
|
|
71
|
+
return (
|
|
72
|
+
<Typography variant="caption" component="p" data-testid="evidence-run-wallets">
|
|
73
|
+
{copy.steps.walletsInRun(
|
|
74
|
+
included.map((type) => names[type]),
|
|
75
|
+
left.map((type) => names[type]),
|
|
76
|
+
)}
|
|
77
|
+
</Typography>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function EvidenceProgress({ phase, section, full, walletResults }: EvidenceProgressProps): ReactNode {
|
|
82
|
+
const copy = usePlatformCopy().evidence;
|
|
83
|
+
const steps = full ? FULL_RUN : DOWNLOAD_ONLY;
|
|
84
|
+
const at = steps.indexOf(currentEvidenceStep(phase, section));
|
|
85
|
+
return (
|
|
86
|
+
<Stack spacing={1} role="status" aria-busy="true" data-testid="evidence-phase">
|
|
87
|
+
<Typography variant="body2">{copy.phases[phase]}</Typography>
|
|
88
|
+
<LinearProgress variant="determinate" value={(at / steps.length) * 100} aria-label={copy.steps.label} />
|
|
89
|
+
{full ? (
|
|
90
|
+
<Box component="ol" sx={{ m: 0, p: 0, listStyle: 'none', display: 'grid', gap: 0.5 }} data-testid="evidence-steps">
|
|
91
|
+
{steps.map((step, index) => {
|
|
92
|
+
const state = index < at ? 'done' : index === at ? 'current' : 'pending';
|
|
93
|
+
return (
|
|
94
|
+
<Stack
|
|
95
|
+
key={step}
|
|
96
|
+
component="li"
|
|
97
|
+
direction="row"
|
|
98
|
+
spacing={1}
|
|
99
|
+
sx={{ alignItems: 'center', minHeight: 24 }}
|
|
100
|
+
data-testid={`evidence-step-${step}`}
|
|
101
|
+
data-state={state}
|
|
102
|
+
aria-current={state === 'current' ? 'step' : undefined}
|
|
103
|
+
>
|
|
104
|
+
<StepMark state={state} />
|
|
105
|
+
<Typography
|
|
106
|
+
variant="body2"
|
|
107
|
+
fontWeight={state === 'current' ? 600 : 400}
|
|
108
|
+
color={state === 'pending' ? 'text.secondary' : 'text.primary'}
|
|
109
|
+
>
|
|
110
|
+
{copy.steps.names[step]}
|
|
111
|
+
</Typography>
|
|
112
|
+
</Stack>
|
|
113
|
+
);
|
|
114
|
+
})}
|
|
115
|
+
</Box>
|
|
116
|
+
) : null}
|
|
117
|
+
{walletResults ? <WalletsLine results={walletResults} /> : null}
|
|
118
|
+
</Stack>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
type GooglePaymentData,
|
|
26
26
|
type GooglePaymentsClient,
|
|
27
27
|
} from '../checkout/google-pay-button';
|
|
28
|
-
import type { HomologacaoEvidenceWalletsCopy } from './copy';
|
|
28
|
+
import type { AppleAbsence, HomologacaoEvidenceWalletsCopy } from './copy';
|
|
29
29
|
import { usePlatformCopy } from './copy-context';
|
|
30
30
|
|
|
31
31
|
/**
|
|
@@ -171,9 +171,10 @@ function notOffered(wallet: EvidenceWallet, input: EvidenceWalletsInput, googleR
|
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
/** Why Apple Pay has no button on a screen whose host carries wallets — null when it has one, or no wallets at all. */
|
|
174
|
-
function appleAbsence(input: EvidenceWalletsInput, offered: boolean):
|
|
174
|
+
function appleAbsence(input: EvidenceWalletsInput, offered: boolean): AppleAbsence | null {
|
|
175
175
|
if (offered || !input.config) return null;
|
|
176
|
-
|
|
176
|
+
const failure = notOffered('APPLE_PAY', input, false)?.failure;
|
|
177
|
+
return failure === 'NOT_CONFIGURED' || failure === 'NOT_AVAILABLE' || failure === 'MERCHANT_VALIDATION_FAILED' ? failure : null;
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
/** The wallet step's state: the sheets' answers, the presses that open them, and what phase 2 gets. */
|
|
@@ -216,7 +217,7 @@ function GooglePayMount({ client, onPress, locale }: { client: GooglePaymentsCli
|
|
|
216
217
|
element.replaceChildren(client.createButton({ onClick: () => latest.current(), buttonSizeMode: 'fill', buttonLocale: locale }));
|
|
217
218
|
return () => element.replaceChildren();
|
|
218
219
|
}, [client, locale]);
|
|
219
|
-
return <Box ref={mount} data-testid="evidence-google-pay" sx={{ minHeight: 40, width: 240, '& > *': { width: '100%' } }} />;
|
|
220
|
+
return <Box ref={mount} data-testid="evidence-google-pay" sx={{ minHeight: 40, width: { xs: '100%', sm: 240 }, '& > *': { width: '100%' } }} />;
|
|
220
221
|
}
|
|
221
222
|
|
|
222
223
|
/** Apple's button: Safari draws it (`-apple-pay-button`); elsewhere the name on a black pill. */
|
|
@@ -231,7 +232,7 @@ function ApplePayPress({ label, onPress }: { label: string; onPress: () => void
|
|
|
231
232
|
sx={{
|
|
232
233
|
WebkitAppearance: '-apple-pay-button',
|
|
233
234
|
height: 40,
|
|
234
|
-
width: 240,
|
|
235
|
+
width: { xs: '100%', sm: 240 },
|
|
235
236
|
border: 0,
|
|
236
237
|
borderRadius: 1,
|
|
237
238
|
cursor: 'pointer',
|
|
@@ -270,20 +271,22 @@ export function EvidenceWalletBlock({ wallets }: { wallets: EvidenceWallets }):
|
|
|
270
271
|
return result ? [result] : [];
|
|
271
272
|
});
|
|
272
273
|
return (
|
|
273
|
-
<Stack spacing={1} data-testid="evidence-wallets">
|
|
274
|
+
<Stack spacing={1} data-testid="evidence-wallets" sx={{ maxWidth: '72ch' }}>
|
|
274
275
|
<Typography variant="body2" fontWeight={600}>
|
|
275
276
|
{copy.heading}
|
|
276
277
|
</Typography>
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
278
|
+
{wallets.google || wallets.apple ? (
|
|
279
|
+
<Typography variant="caption" component="p" color="text.secondary">
|
|
280
|
+
{copy.hint}
|
|
281
|
+
</Typography>
|
|
282
|
+
) : null}
|
|
280
283
|
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={1}>
|
|
281
284
|
{wallets.google ? (
|
|
282
285
|
<GooglePayMount client={wallets.google.client} onPress={wallets.google.press} locale={copy.googlePayButtonLocale} />
|
|
283
286
|
) : null}
|
|
284
287
|
{wallets.apple ? <ApplePayPress label={copy.applePayButton} onPress={wallets.apple.press} /> : null}
|
|
285
288
|
</Stack>
|
|
286
|
-
{wallets.appleAbsent
|
|
289
|
+
{wallets.appleAbsent ? (
|
|
287
290
|
<Typography variant="caption" component="p" color="text.secondary" data-testid="evidence-apple-pay-absent">
|
|
288
291
|
{copy.applePayAbsent[wallets.appleAbsent]}
|
|
289
292
|
</Typography>
|
|
@@ -148,6 +148,14 @@ export interface HomologacaoEvidenceCardCopy {
|
|
|
148
148
|
generate: string;
|
|
149
149
|
downloadLatest: string;
|
|
150
150
|
phases: { preparing: string; encrypting: string; running: string; downloading: string };
|
|
151
|
+
/** The run's step list (FUT-3755): which step is done, which one is going. */
|
|
152
|
+
steps: {
|
|
153
|
+
/** The bar's accessible name. */
|
|
154
|
+
label: string;
|
|
155
|
+
names: Record<'prepare' | 'encrypt' | 'PIX' | 'CARD' | 'DEBIT' | 'GOOGLE_PAY' | 'APPLE_PAY' | 'file', string>;
|
|
156
|
+
/** Which wallets this generation carries a token for, and which stay pending. */
|
|
157
|
+
walletsInRun: (included: string[], pending: string[]) => string;
|
|
158
|
+
};
|
|
151
159
|
summary: (counts: { executed: number; failed: number; pending: number }) => string;
|
|
152
160
|
incomplete: string;
|
|
153
161
|
/** Which phase failed — and that the latest recorded file can still be downloaded. */
|
|
@@ -156,6 +164,9 @@ export interface HomologacaoEvidenceCardCopy {
|
|
|
156
164
|
wallets: HomologacaoEvidenceWalletsCopy;
|
|
157
165
|
}
|
|
158
166
|
|
|
167
|
+
/** Why Apple Pay has no button on the evidence card (FUT-3755). */
|
|
168
|
+
export type AppleAbsence = 'NOT_CONFIGURED' | 'NOT_AVAILABLE' | 'MERCHANT_VALIDATION_FAILED';
|
|
169
|
+
|
|
159
170
|
/** The Google Pay / Apple Pay step of the evidence card (FUT-3755). */
|
|
160
171
|
export interface HomologacaoEvidenceWalletsCopy {
|
|
161
172
|
heading: string;
|
|
@@ -174,7 +185,7 @@ export interface HomologacaoEvidenceWalletsCopy {
|
|
|
174
185
|
/** Apple Pay started and failed. */
|
|
175
186
|
applePayCannotComplete: string;
|
|
176
187
|
/** Why Apple Pay has no button here: the platform has no Apple Pay identity yet, or this browser has no sheet. */
|
|
177
|
-
applePayAbsent:
|
|
188
|
+
applePayAbsent: Record<AppleAbsence, string>;
|
|
178
189
|
/** A wallet holds its token: `card` is the network and last four the wallet showed — never the token. */
|
|
179
190
|
ready: (wallet: string, card: string) => string;
|
|
180
191
|
/** The sheet answered no token; pressing again retries. */
|
|
@@ -131,6 +131,26 @@ export const EN_US_PLATFORM_HOMOLOGACAO_COPY: PlatformHomologacaoCopy = {
|
|
|
131
131
|
running: 'Creating the Pix, credit, debit and wallet orders in the sandbox — this can take a few minutes…',
|
|
132
132
|
downloading: 'Building the file…',
|
|
133
133
|
},
|
|
134
|
+
steps: {
|
|
135
|
+
label: 'Generation progress',
|
|
136
|
+
names: {
|
|
137
|
+
prepare: 'Prepare (application, token, public key and 3DS session)',
|
|
138
|
+
encrypt: 'Encrypt the cards and authenticate the debit (3DS)',
|
|
139
|
+
PIX: 'Pix',
|
|
140
|
+
CARD: 'Credit card',
|
|
141
|
+
DEBIT: 'Debit with 3DS',
|
|
142
|
+
GOOGLE_PAY: 'Google Pay',
|
|
143
|
+
APPLE_PAY: 'Apple Pay',
|
|
144
|
+
file: 'Build the file',
|
|
145
|
+
},
|
|
146
|
+
walletsInRun: (included, pending) =>
|
|
147
|
+
[
|
|
148
|
+
included.length > 0 ? `In this generation: ${included.join(' and ')}.` : 'No wallet in this generation.',
|
|
149
|
+
pending.length > 0 ? `${pending.join(' and ')} ${pending.length === 1 ? 'stays' : 'stay'} pending.` : '',
|
|
150
|
+
]
|
|
151
|
+
.filter(Boolean)
|
|
152
|
+
.join(' '),
|
|
153
|
+
},
|
|
134
154
|
summary: ({ executed, failed, pending }) =>
|
|
135
155
|
`✓\u00a0${executed}\u00a0executed · ✗\u00a0${failed}\u00a0failed · ⧗\u00a0${pending}\u00a0pending`,
|
|
136
156
|
incomplete:
|
|
@@ -147,9 +167,7 @@ export const EN_US_PLATFORM_HOMOLOGACAO_COPY: PlatformHomologacaoCopy = {
|
|
|
147
167
|
wallets: {
|
|
148
168
|
heading: 'Digital wallets (before generating)',
|
|
149
169
|
names: { GOOGLE_PAY: 'Google Pay', APPLE_PAY: 'Apple Pay' },
|
|
150
|
-
hint:
|
|
151
|
-
'Google Pay and Apple Pay open their own sheet, and only on your tap. Tap each one before generating the file; ' +
|
|
152
|
-
"without it, the wallets' sections stay pending. Test only: nothing is charged.",
|
|
170
|
+
hint: "Tap each wallet before generating; without it, that wallet's section stays pending.",
|
|
153
171
|
googlePayButtonLocale: 'en',
|
|
154
172
|
applePayButton: 'Pay with Apple Pay',
|
|
155
173
|
applePaySheetTotal: 'Homologation test',
|
|
@@ -158,6 +176,7 @@ export const EN_US_PLATFORM_HOMOLOGACAO_COPY: PlatformHomologacaoCopy = {
|
|
|
158
176
|
applePayAbsent: {
|
|
159
177
|
NOT_CONFIGURED: 'Apple Pay: waiting for the Apple Developer account. Its section stays pending.',
|
|
160
178
|
NOT_AVAILABLE: 'Apple Pay: open this screen in Safari on an iPhone or Mac to test it.',
|
|
179
|
+
MERCHANT_VALIDATION_FAILED: "Apple Pay: the merchant validation is not set up. Its section stays pending.",
|
|
161
180
|
},
|
|
162
181
|
ready: (wallet, card) => `${wallet} ready${card ? ` — ${card}` : ''}. It will be used when the file is generated.`,
|
|
163
182
|
failed: (wallet) => `${wallet} returned no token. Tap again to retry.`,
|
|
@@ -112,6 +112,26 @@ export const PT_BR_PLATFORM_HOMOLOGACAO_COPY: PlatformHomologacaoCopy = {
|
|
|
112
112
|
running: 'Criando os pedidos Pix, crédito, débito e carteiras no sandbox — pode levar alguns minutos…',
|
|
113
113
|
downloading: 'Montando o arquivo…',
|
|
114
114
|
},
|
|
115
|
+
steps: {
|
|
116
|
+
label: 'Progresso da geração',
|
|
117
|
+
names: {
|
|
118
|
+
prepare: 'Preparar (aplicação, token, chave pública e sessão 3DS)',
|
|
119
|
+
encrypt: 'Criptografar os cartões e autenticar o débito (3DS)',
|
|
120
|
+
PIX: 'Pix',
|
|
121
|
+
CARD: 'Cartão de crédito',
|
|
122
|
+
DEBIT: 'Débito com 3DS',
|
|
123
|
+
GOOGLE_PAY: 'Google Pay',
|
|
124
|
+
APPLE_PAY: 'Apple Pay',
|
|
125
|
+
file: 'Montar o arquivo',
|
|
126
|
+
},
|
|
127
|
+
walletsInRun: (included, pending) =>
|
|
128
|
+
[
|
|
129
|
+
included.length > 0 ? `Nesta geração: ${included.join(' e ')}.` : 'Nenhuma carteira nesta geração.',
|
|
130
|
+
pending.length > 0 ? `${pending.join(' e ')} ${pending.length === 1 ? 'fica pendente' : 'ficam pendentes'}.` : '',
|
|
131
|
+
]
|
|
132
|
+
.filter(Boolean)
|
|
133
|
+
.join(' '),
|
|
134
|
+
},
|
|
115
135
|
summary: ({ executed, failed, pending }) =>
|
|
116
136
|
// Non-breaking inside each count, so only the separators may wrap.
|
|
117
137
|
`✓\u00a0${executed}\u00a0${executed === 1 ? 'executado' : 'executados'} · ` +
|
|
@@ -131,9 +151,7 @@ export const PT_BR_PLATFORM_HOMOLOGACAO_COPY: PlatformHomologacaoCopy = {
|
|
|
131
151
|
wallets: {
|
|
132
152
|
heading: 'Carteiras digitais (antes de gerar)',
|
|
133
153
|
names: { GOOGLE_PAY: 'Google Pay', APPLE_PAY: 'Apple Pay' },
|
|
134
|
-
hint:
|
|
135
|
-
'O Google Pay e o Apple Pay abrem a própria folha e só com o seu toque. Toque em cada um antes de gerar o arquivo; ' +
|
|
136
|
-
'sem isso, as seções das carteiras ficam pendentes. Somente teste: nada é cobrado.',
|
|
154
|
+
hint: 'Toque em cada carteira antes de gerar; sem isso, a seção dela fica pendente.',
|
|
137
155
|
googlePayButtonLocale: 'pt',
|
|
138
156
|
applePayButton: 'Pagar com Apple Pay',
|
|
139
157
|
applePaySheetTotal: 'Teste de homologação',
|
|
@@ -142,6 +160,7 @@ export const PT_BR_PLATFORM_HOMOLOGACAO_COPY: PlatformHomologacaoCopy = {
|
|
|
142
160
|
applePayAbsent: {
|
|
143
161
|
NOT_CONFIGURED: 'Apple Pay: aguardando a conta Apple Developer. A seção fica pendente.',
|
|
144
162
|
NOT_AVAILABLE: 'Apple Pay: abra esta tela no Safari de um iPhone ou Mac para testar.',
|
|
163
|
+
MERCHANT_VALIDATION_FAILED: 'Apple Pay: a validação do comerciante não está configurada. A seção fica pendente.',
|
|
145
164
|
},
|
|
146
165
|
ready: (wallet, card) => `${wallet} pronto${card ? ` — ${card}` : ''}. Será usado ao gerar o arquivo.`,
|
|
147
166
|
failed: (wallet) => `O ${wallet} não devolveu o token. Toque de novo para tentar.`,
|