commit 72f02e6816cfd5336c05b303265fb3cd0ed977d1
parent 43ff95dc1956d384164b75f30c84f16534de5c94
Author: Sebastian <sebasjm@taler-systems.com>
Date: Fri, 31 Jul 2026 12:51:07 -0300
fix #11625
Diffstat:
1 file changed, 189 insertions(+), 200 deletions(-)
diff --git a/packages/taler-merchant-webui/src/components/modal/index.tsx b/packages/taler-merchant-webui/src/components/modal/index.tsx
@@ -23,6 +23,7 @@ import {
Amounts,
assertUnreachable,
getQrCodesForPayto,
+ paytoFromTransferSubject,
Paytos,
PaytoType,
Result,
@@ -448,209 +449,197 @@ export function ValidBankAccount({
const [{ showDebugInfo }] = useCommonPreferences();
- switch (instructions.subject.type) {
- case "URI":
- return (
- <ConfirmModal
- title={i18n.str`Failed to get bank transfer instructions`}
- onCancel={onCancel}
- >
- <div>unsupported instructions URI</div>
- </ConfirmModal>
- );
- case "CH_QR_BILL":
- case "SIMPLE": {
- const sendAmount = Amounts.parseOrThrow(
- instructions.subject.credit_amount,
- );
- payto.params["message"] =
- instructions.subject.type === "SIMPLE"
- ? instructions.subject.subject
- : instructions.subject.qr_reference_number;
- payto.params["amount"] = instructions.subject.credit_amount;
- const strPayto = Paytos.toFullString(payto);
- const qrs = getQrCodesForPayto(strPayto);
- return (
- <ConfirmModal
- title={i18n.str`Validate bank account: ${from}`}
- onCancel={onCancel}
- confirm={
- all_ins.length > 1
- ? {
- label: i18n.str`See other option`,
- handler: simpleSafeHandler(() => {
- setTargetIndex((idx) => (idx + 1) % all_ins.length);
- }),
- }
- : undefined
- }
- >
- {!showDebugInfo ? undefined : (
- <pre>
- {JSON.stringify({ strPayto, payto, all_ins }, undefined, 2)}
- </pre>
+ const sendAmount = Amounts.parseOrThrow(instructions.subject.credit_amount);
+ const strPayto = paytoFromTransferSubject(
+ Paytos.toFullString(payto),
+ instructions.subject,
+ );
+ if (strPayto === undefined) {
+ return (
+ <ConfirmModal
+ title={i18n.str`Failed to get bank transfer instructions`}
+ onCancel={onCancel}
+ >
+ <div>unsupported instructions URI</div>
+ </ConfirmModal>
+ );
+ }
+ const qrs = getQrCodesForPayto(strPayto);
+
+ return (
+ <ConfirmModal
+ title={i18n.str`Validate bank account: ${from}`}
+ onCancel={onCancel}
+ confirm={
+ all_ins.length > 1
+ ? {
+ label: i18n.str`See other option`,
+ handler: simpleSafeHandler(() => {
+ setTargetIndex((idx) => (idx + 1) % all_ins.length);
+ }),
+ }
+ : undefined
+ }
+ >
+ {!showDebugInfo ? undefined : (
+ <pre>{JSON.stringify({ strPayto, payto, all_ins }, undefined, 2)}</pre>
+ )}
+ <p style={{ paddingTop: 0 }}>
+ <i18n.Translate>
+ In order to prove that you are the beneficial owner of the bank
+ account, you are required to wire a small amount to a specified bank
+ account with the subject below.
+ </i18n.Translate>
+ </p>
+ <tr>
+ <td colSpan={3}>
+ {!qrs.length ? undefined : (
+ <div style={{ overflowY: "auto", height: "95%", padding: 5 }}>
+ <p>
+ <i18n.Translate>
+ If your bank application allows you make a wire transfer using
+ standard QR codes then try scanning the following:
+ </i18n.Translate>
+ </p>
+ <table style={{ width: "100%" }}>
+ {qrs.map((q, idx) => {
+ return (
+ <tr key={idx}>
+ <td style={{}}>
+ {(function () {
+ switch (q.type) {
+ case "epc-qr":
+ return (
+ <QR_Bank
+ text={q.qrContent}
+ label={i18n.str`Bank app`}
+ />
+ );
+ case "spc":
+ return <QR_SwissBank text={q.qrContent} />;
+
+ default:
+ assertUnreachable(q.type);
+ }
+ })()}
+ </td>
+ </tr>
+ );
+ })}
+ </table>
+ </div>
)}
- <p style={{ paddingTop: 0 }}>
- <i18n.Translate>
- In order to prove that you are the beneficial owner of the bank
- account, you are required to wire a small amount to a specified
- bank account with the subject below.
- </i18n.Translate>
- </p>
- <tr>
- <td colSpan={3}>
- {!qrs.length ? undefined : (
- <div style={{ overflowY: "auto", height: "95%", padding: 5 }}>
- <p>
- <i18n.Translate>
- If your bank application allows you make a wire transfer
- using standard QR codes then try scanning the following:
- </i18n.Translate>
- </p>
- <table style={{ width: "100%" }}>
- {qrs.map((q, idx) => {
- return (
- <tr key={idx}>
- <td style={{}}>
- {(function () {
- switch (q.type) {
- case "epc-qr":
- return (
- <QR_Bank
- text={q.qrContent}
- label={i18n.str`Bank app`}
- />
- );
- case "spc":
- return <QR_SwissBank text={q.qrContent} />;
-
- default:
- assertUnreachable(q.type);
- }
- })()}
- </td>
- </tr>
- );
- })}
- </table>
- </div>
- )}
- </td>
- </tr>
- <div class="">
- <table>
- <tbody>
- <tr>
- <td colSpan={3}>
- <i18n.Translate>Step 1:</i18n.Translate>
-
- <i18n.Translate>
- Copy and paste this IBAN and the legal name of the
- beneficial owner into the respective fields in your
- preferred banking app or online banking website.
- </i18n.Translate>
- </td>
- </tr>
- {accountPart}
- {receiverName ? (
- <Row name={i18n.str`Beneficiary`} value={receiverName} />
- ) : undefined}
- <Row
- name={i18n.str`Amount`}
- value={
- <RenderAmountBulma
- value={sendAmount}
- specMap={config.currencies}
- />
- }
+ </td>
+ </tr>
+ <div class="">
+ <table>
+ <tbody>
+ <tr>
+ <td colSpan={3}>
+ <i18n.Translate>Step 1:</i18n.Translate>
+
+ <i18n.Translate>
+ Copy and paste this IBAN and the legal name of the beneficial
+ owner into the respective fields in your preferred banking app
+ or online banking website.
+ </i18n.Translate>
+ </td>
+ </tr>
+ {accountPart}
+ {receiverName ? (
+ <Row name={i18n.str`Beneficiary`} value={receiverName} />
+ ) : undefined}
+ <Row
+ name={i18n.str`Amount`}
+ value={
+ <RenderAmountBulma
+ value={sendAmount}
+ specMap={config.currencies}
/>
- <tr>
- <td colSpan={3}>
- <i18n.Translate>Step 2:</i18n.Translate>
-
- <i18n.Translate>
- Copy this string and paste it into the 'Subject' or
- 'Purpose' field in your preferred banking app or online
- banking website.
- </i18n.Translate>
- </td>
- </tr>
- {instructions.subject.type === "CH_QR_BILL" ? (
- <Row
- name={i18n.str`Reference`}
- value={instructions.subject.qr_reference_number}
- literal
- />
- ) : undefined}
- {instructions.subject.type === "SIMPLE" ? (
- <Row
- name={i18n.str`Subject`}
- value={instructions.subject.subject}
- literal
- />
- ) : undefined}
- {receiverPostalCode ? (
- <Row
- name={i18n.str`Receiver postal code`}
- value={receiverPostalCode}
- />
- ) : undefined}
- {receiverTown ? (
- <Row name={i18n.str`Receiver town`} value={receiverTown} />
- ) : undefined}
+ }
+ />
+ <tr>
+ <td colSpan={3}>
+ <i18n.Translate>Step 2:</i18n.Translate>
+
+ <i18n.Translate>
+ Copy this string and paste it into the 'Subject' or 'Purpose'
+ field in your preferred banking app or online banking website.
+ </i18n.Translate>
+ </td>
+ </tr>
+ {instructions.subject.type === "CH_QR_BILL" ? (
+ <Row
+ name={i18n.str`Reference`}
+ value={instructions.subject.qr_reference_number}
+ literal
+ />
+ ) : undefined}
+ {instructions.subject.type === "SIMPLE" ? (
+ <Row
+ name={i18n.str`Subject`}
+ value={instructions.subject.subject}
+ literal
+ />
+ ) : undefined}
+ {receiverPostalCode ? (
+ <Row
+ name={i18n.str`Receiver postal code`}
+ value={receiverPostalCode}
+ />
+ ) : undefined}
+ {receiverTown ? (
+ <Row name={i18n.str`Receiver town`} value={receiverTown} />
+ ) : undefined}
- <tr>
- <td colSpan={3}>
- <i18n.Translate>Step 3:</i18n.Translate>
-
- <i18n.Translate>
- Select the smallest possible amount for a wire transfer in
- your preferred banking app or online banking website.
- </i18n.Translate>
- </td>
- </tr>
- <tr>
- <td colSpan={3}>
- <b>
- <i18n.Translate>
- Make sure ALL data is correct, especially the subject,
- and that you are choosing the bank account from which
- you definitely want to make the wire transfer. You can
- use the copy buttons (<CopyIcon />) to avoid typos or
- make use of the PayTo URI below to copy just one value.
- </i18n.Translate>
- </b>
- </td>
- </tr>
- <tr>
- <td colSpan={2} width="100%">
- <i18n.Translate>
- As an alternative, in case your bank already supports the{" "}
- <a
- target="_blank"
- rel="noreferrer"
- title="RFC 8905 for designating targets for payments"
- href="https://tools.ietf.org/html/rfc8905"
- >
- PayTo URI standard
- </a>
- , you can use this <a href={strPayto}>PayTo URI</a> link
- instead.
- </i18n.Translate>
- </td>
- <td>
- <CopyButton getContent={() => strPayto} />
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </ConfirmModal>
- );
- }
- default:
- assertUnreachable(instructions.subject);
- }
+ <tr>
+ <td colSpan={3}>
+ <i18n.Translate>Step 3:</i18n.Translate>
+
+ <i18n.Translate>
+ Select the smallest possible amount for a wire transfer in
+ your preferred banking app or online banking website.
+ </i18n.Translate>
+ </td>
+ </tr>
+ <tr>
+ <td colSpan={3}>
+ <b>
+ <i18n.Translate>
+ Make sure ALL data is correct, especially the subject, and
+ that you are choosing the bank account from which you
+ definitely want to make the wire transfer. You can use the
+ copy buttons (<CopyIcon />) to avoid typos or make use of
+ the PayTo URI below to copy just one value.
+ </i18n.Translate>
+ </b>
+ </td>
+ </tr>
+ <tr>
+ <td colSpan={2} width="100%">
+ <i18n.Translate>
+ As an alternative, in case your bank already supports the{" "}
+ <a
+ target="_blank"
+ rel="noreferrer"
+ title="RFC 8905 for designating targets for payments"
+ href="https://tools.ietf.org/html/rfc8905"
+ >
+ PayTo URI standard
+ </a>
+ , you can use this <a href={strPayto}>PayTo URI</a> link
+ instead.
+ </i18n.Translate>
+ </td>
+ <td>
+ <CopyButton getContent={() => strPayto} />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </ConfirmModal>
+ );
}
function Accordion({