From dc2361edb3f401731f2099526ed93a6e963ecc45 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 19 Feb 2024 00:09:09 +0100 Subject: improve error message for templates with currency-only amount --- packages/taler-util/src/amounts.ts | 13 ++++++++--- packages/taler-util/src/taleruri.ts | 7 +++++- packages/taler-util/src/wallet-types.ts | 8 +++++-- .../src/operations/pay-merchant.ts | 27 +++++++++++++++------- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/packages/taler-util/src/amounts.ts b/packages/taler-util/src/amounts.ts index c3770a393..16774f376 100644 --- a/packages/taler-util/src/amounts.ts +++ b/packages/taler-util/src/amounts.ts @@ -22,12 +22,12 @@ * Imports. */ import { - buildCodecForObject, - codecForString, - codecForNumber, Codec, Context, DecodingError, + buildCodecForObject, + codecForNumber, + codecForString, renderContext, } from "./codec.js"; import { CurrencySpecification } from "./index.js"; @@ -368,6 +368,13 @@ export class Amounts { return a.value === 0 && a.fraction === 0; } + /** + * Check whether a string is a valid currency for a Taler amount. + */ + static isCurrency(s: string): boolean { + return /^[a-zA-Z]{1,11}/.test(s); + } + /** * Parse an amount like 'EUR:20.5' for 20 Euros and 50 ct. * diff --git a/packages/taler-util/src/taleruri.ts b/packages/taler-util/src/taleruri.ts index 22846c7a4..db21f0ad6 100644 --- a/packages/taler-util/src/taleruri.ts +++ b/packages/taler-util/src/taleruri.ts @@ -75,11 +75,16 @@ export interface PayUriResult { noncePriv?: string; } +export type TemplateParams = { + amount?: string; + summary?: string; +} + export interface PayTemplateUriResult { type: TalerUriAction.PayTemplate; merchantBaseUrl: string; templateId: string; - templateParams: Record; + templateParams: TemplateParams; } export interface WithdrawUriResult { diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts index e6a66ac9d..4e3e8ac30 100644 --- a/packages/taler-util/src/wallet-types.ts +++ b/packages/taler-util/src/wallet-types.ts @@ -46,7 +46,11 @@ import { codecOptional, renderContext, } from "./codec.js"; -import { CurrencySpecification, WithdrawalOperationStatus } from "./index.js"; +import { + CurrencySpecification, + TemplateParams, + WithdrawalOperationStatus, +} from "./index.js"; import { VersionMatchResult } from "./libtool-version.js"; import { PaytoUri } from "./payto.js"; import { AgeCommitmentProof } from "./taler-crypto.js"; @@ -1927,7 +1931,7 @@ export const codecForSharePaymentResult = (): Codec => export interface PreparePayTemplateRequest { talerPayTemplateUri: string; - templateParams?: Record; + templateParams?: TemplateParams; } export const codecForPreparePayTemplateRequest = diff --git a/packages/taler-wallet-core/src/operations/pay-merchant.ts b/packages/taler-wallet-core/src/operations/pay-merchant.ts index 63bef3add..1039ac95e 100644 --- a/packages/taler-wallet-core/src/operations/pay-merchant.ts +++ b/packages/taler-wallet-core/src/operations/pay-merchant.ts @@ -640,7 +640,8 @@ async function processDownloadProposal( if (proposal.purchaseStatus != PurchaseStatus.PendingDownloadingProposal) { logger.error( - `unexpected state ${proposal.purchaseStatus}/${PurchaseStatus[proposal.purchaseStatus] + `unexpected state ${proposal.purchaseStatus}/${ + PurchaseStatus[proposal.purchaseStatus] } for ${ctx.transactionId} in processDownloadProposal`, ); return TaskRunResult.finished(); @@ -899,7 +900,8 @@ async function createOrReusePurchase( oldProposal.claimToken === claimToken ) { logger.info( - `Found old proposal (status=${PurchaseStatus[oldProposal.purchaseStatus] + `Found old proposal (status=${ + PurchaseStatus[oldProposal.purchaseStatus] }) for order ${orderId} at ${merchantBaseUrl}`, ); if (oldProposal.purchaseStatus === PurchaseStatus.DialogShared) { @@ -1567,12 +1569,21 @@ export async function preparePayForTemplate( throw Error("invalid taler-template URI"); } logger.trace(`parsed URI: ${j2s(parsedUri)}`); - if ( - parsedUri.templateParams.amount !== undefined && - typeof parsedUri.templateParams.amount === "string" - ) { - templateDetails.amount = (req.templateParams?.amount ?? - parsedUri.templateParams.amount) as AmountString | undefined; + + const amountFromUri = parsedUri.templateParams.amount; + if (amountFromUri != null) { + const templateParamsAmount = req.templateParams?.amount; + if (templateParamsAmount != null) { + templateDetails.amount = templateParamsAmount as AmountString; + } else { + if (Amounts.isCurrency(amountFromUri)) { + throw Error( + "Amount from template URI only has a currency without value. The value must be provided in the templateParams.", + ); + } else { + templateDetails.amount = amountFromUri as AmountString; + } + } } if ( parsedUri.templateParams.summary !== undefined && -- cgit v1.2.3