@12-apps/payments-frontend 3.30.0 → 3.31.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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@12-apps/payments-frontend",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.31.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.",
|
|
@@ -4,7 +4,7 @@ import QRCode from "react-qr-code";
|
|
|
4
4
|
|
|
5
5
|
import { useCheckoutCopy } from "./copy-context";
|
|
6
6
|
import { ContentCopyIcon } from "./icons";
|
|
7
|
-
import type { SettlingCopy } from "./screens-copy";
|
|
7
|
+
import type { PixPaneCopy, SettlingCopy } from "./screens-copy";
|
|
8
8
|
import { StalledWait } from "./stalled-wait";
|
|
9
9
|
import type { CheckoutOrder, OrderStatus, PixCharge } from "./types";
|
|
10
10
|
import { useCheckoutComponents } from "./ui";
|
|
@@ -163,14 +163,18 @@ function PixPollFooter({
|
|
|
163
163
|
error,
|
|
164
164
|
timedOut,
|
|
165
165
|
onCheckAgain,
|
|
166
|
+
manual,
|
|
166
167
|
}: {
|
|
167
168
|
error: string | null;
|
|
168
169
|
timedOut: boolean;
|
|
169
170
|
onCheckAgain: () => void;
|
|
171
|
+
/** The store confirms this Pix: the wait is for THEM, not for the bank. */
|
|
172
|
+
manual: boolean;
|
|
170
173
|
}): JSX.Element {
|
|
171
174
|
const { Text } = useCheckoutComponents();
|
|
172
175
|
const { pix, settling } = useCheckoutCopy().screens;
|
|
173
176
|
const panel = pixWaitPanel(settling, error, timedOut);
|
|
177
|
+
const awaiting = (manual ? pix.manual?.awaiting : undefined) ?? pix.awaiting;
|
|
174
178
|
if (panel) {
|
|
175
179
|
// The same panel the card and wallet panes show, held to the width of the
|
|
176
180
|
// copy-and-paste strip above it so the centred PIX column stays a column.
|
|
@@ -190,12 +194,23 @@ function PixPollFooter({
|
|
|
190
194
|
<Box sx={{ display: "flex", alignItems: "center", gap: 1, color: "text.secondary" }}>
|
|
191
195
|
<LoadingDot />
|
|
192
196
|
<Text variant="caption" size="xs" color="secondary" as="span" data-testid="pix-awaiting">
|
|
193
|
-
{
|
|
197
|
+
{awaiting}
|
|
194
198
|
</Text>
|
|
195
199
|
</Box>
|
|
196
200
|
);
|
|
197
201
|
}
|
|
198
202
|
|
|
203
|
+
/**
|
|
204
|
+
* The pane's two sentences that depend on who confirms. A store-confirmed Pix
|
|
205
|
+
* must not say "a confirmação é automática": nothing confirms it but the store.
|
|
206
|
+
*/
|
|
207
|
+
function pixSentences(
|
|
208
|
+
copy: PixPaneCopy,
|
|
209
|
+
manual: boolean,
|
|
210
|
+
): Pick<PixPaneCopy, "instructions" | "validUntil"> {
|
|
211
|
+
return (manual ? copy.manual : undefined) ?? copy;
|
|
212
|
+
}
|
|
213
|
+
|
|
199
214
|
export function PixView({
|
|
200
215
|
order,
|
|
201
216
|
onResolved,
|
|
@@ -243,6 +258,7 @@ export function PixView({
|
|
|
243
258
|
hour: "2-digit",
|
|
244
259
|
minute: "2-digit",
|
|
245
260
|
});
|
|
261
|
+
const sentences = pixSentences(copy, pix.confirmation === "MANUAL");
|
|
246
262
|
|
|
247
263
|
return (
|
|
248
264
|
<Box
|
|
@@ -253,7 +269,7 @@ export function PixView({
|
|
|
253
269
|
{copy.heading}
|
|
254
270
|
</Text>
|
|
255
271
|
<Text variant="body" size="sm" color="secondary" as="p">
|
|
256
|
-
{
|
|
272
|
+
{sentences.instructions(order.totalLabel)}
|
|
257
273
|
</Text>
|
|
258
274
|
|
|
259
275
|
<Box
|
|
@@ -268,10 +284,10 @@ export function PixView({
|
|
|
268
284
|
<PixCodeBox pix={pix} />
|
|
269
285
|
|
|
270
286
|
<Text variant="caption" size="xs" color="secondary" as="p" data-testid="pix-expiry">
|
|
271
|
-
{
|
|
287
|
+
{sentences.validUntil(validUntil)}
|
|
272
288
|
</Text>
|
|
273
289
|
|
|
274
|
-
<PixPollFooter error={error} timedOut={timedOut} onCheckAgain={checkAgain} />
|
|
290
|
+
<PixPollFooter error={error} timedOut={timedOut} onCheckAgain={checkAgain} manual={sentences !== copy} />
|
|
275
291
|
</Box>
|
|
276
292
|
);
|
|
277
293
|
}
|
|
@@ -107,6 +107,17 @@ export interface PixPaneCopy {
|
|
|
107
107
|
awaiting: string;
|
|
108
108
|
/** The order came back with no PIX charge on it — nothing to show. */
|
|
109
109
|
chargeMissing: string;
|
|
110
|
+
/**
|
|
111
|
+
* The same pane for a Pix the STORE confirms (`PixCharge.confirmation:
|
|
112
|
+
* 'MANUAL'`). Optional so a host's own table keeps compiling; absent, the
|
|
113
|
+
* automatic sentences are used — which promise "automática", so a host that
|
|
114
|
+
* enables a store-confirmed provider should set them.
|
|
115
|
+
*/
|
|
116
|
+
manual?: {
|
|
117
|
+
instructions(totalLabel: string): string;
|
|
118
|
+
validUntil(time: string): string;
|
|
119
|
+
awaiting: string;
|
|
120
|
+
};
|
|
110
121
|
}
|
|
111
122
|
|
|
112
123
|
/** The card pane's own heading. Everything else in it is {@link SettlingCopy}. */
|
|
@@ -51,6 +51,12 @@ export const EN_US_CHECKOUT_SCREENS_COPY: CheckoutScreensCopy = {
|
|
|
51
51
|
expiryLocale: 'en-US',
|
|
52
52
|
awaiting: 'Waiting for payment…',
|
|
53
53
|
chargeMissing: 'Could not generate the PIX code.',
|
|
54
|
+
manual: {
|
|
55
|
+
instructions: (totalLabel) =>
|
|
56
|
+
`Pay ${totalLabel} with the QR code or the code below. The store checks it arrived and confirms your order.`,
|
|
57
|
+
validUntil: (time) => `The store confirms the payment by ${time}.`,
|
|
58
|
+
awaiting: 'Waiting for the store to confirm the payment…',
|
|
59
|
+
},
|
|
54
60
|
},
|
|
55
61
|
card: {
|
|
56
62
|
heading: 'Pay by card',
|
|
@@ -40,6 +40,12 @@ export const PT_BR_CHECKOUT_SCREENS_COPY: CheckoutScreensCopy = {
|
|
|
40
40
|
expiryLocale: 'pt-BR',
|
|
41
41
|
awaiting: 'Aguardando pagamento…',
|
|
42
42
|
chargeMissing: 'Não foi possível gerar o código PIX.',
|
|
43
|
+
manual: {
|
|
44
|
+
instructions: (totalLabel) =>
|
|
45
|
+
`Pague ${totalLabel} com o QR code ou o código abaixo. A loja confere o recebimento e confirma o seu pedido.`,
|
|
46
|
+
validUntil: (time) => `A loja confirma o pagamento até ${time}.`,
|
|
47
|
+
awaiting: 'Aguardando a loja confirmar o pagamento…',
|
|
48
|
+
},
|
|
43
49
|
},
|
|
44
50
|
card: {
|
|
45
51
|
heading: 'Pague com cartão',
|
|
@@ -66,15 +66,15 @@ export interface BuyerInfo {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
|
-
* A raised PIX charge. `copyPaste` is the EMV "copia e cola" payload
|
|
70
|
-
*
|
|
71
|
-
* returns a provider QR image; the client renders its own QR from `copyPaste`, so
|
|
72
|
-
* no image URL is needed here.
|
|
69
|
+
* A raised PIX charge. `copyPaste` is the EMV "copia e cola" payload: what the
|
|
70
|
+
* QR encodes (rendered client-side, so no image URL) and what the button copies.
|
|
73
71
|
*/
|
|
74
72
|
export interface PixCharge {
|
|
75
73
|
copyPaste: string;
|
|
76
74
|
/** ISO-8601 instant when the charge expires. */
|
|
77
75
|
expiresAt: string;
|
|
76
|
+
/** `'MANUAL'`: only the store confirms it (`pixmanual`); absent is automatic. */
|
|
77
|
+
confirmation?: 'AUTOMATIC' | 'MANUAL';
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/**
|