taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 16765d1477999b3d513e265c1e465a825d1face2
parent 29118e7c544af1a90465050e1f25da2a1451edd1
Author: Florian Dold <dold@taler.net>
Date:   Tue, 21 Jul 2026 01:57:11 +0200

util: normalize x-taler-bank paytos like the C exchange

Diffstat:
Mpackages/taler-util/src/payto.ts | 24+++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/packages/taler-util/src/payto.ts b/packages/taler-util/src/payto.ts @@ -225,8 +225,10 @@ export namespace Paytos { // An unsupported target type keeps the raw value in `target`, since it is // by definition not a member of PaytoType. const target = p.targetType ?? (p as PaytoUnsupported).target; - const url = new URL(`${PAYTO_PREFIX}${target}/${p.normalizedPath}`); - return url.href as NormalizedPaytoString; + // Concatenate directly rather than via a URL parser: normalizedPath is + // already canonical, and passing it through `new URL` would resolve dot + // segments, diverging from the C normalizer and thus from H_PAYTO. + return `${PAYTO_PREFIX}${target}/${p.normalizedPath}` as NormalizedPaytoString; } /** * A **full** payto-URI is not expected to have a canonical form for @@ -487,17 +489,28 @@ export namespace Paytos { url: HostPortPath, account: string, params: Record<string, string> = {}, + rawSegments?: string[], ): PaytoTalerBank { const path = withoutScheme(url); const host = path.endsWith("/") ? path.substring(0, path.length - 1) : path; + // Match normalize_payto_x_taler_bank in the C exchange: lowercase only the + // host, preserve the case of the account path, and do not resolve dot + // segments. Both forms are built from the raw segments so that going + // through a URL parser (which would lowercase or resolve) cannot change + // H_PAYTO. + const segments = rawSegments ?? [host, account]; + const normalizedPath = `${segments[0].toLowerCase()}/${segments + .slice(1) + .join("/")}`; + const fullPath = segments.join("/"); return { targetType: PaytoType.TalerBank, host, url, account, params, - normalizedPath: `${path.toLowerCase()}${account}`, - fullPath: `${path}${account}`, + normalizedPath, + fullPath, displayName: `${account}@${url}`, }; } @@ -729,8 +742,9 @@ export namespace Paytos { return Result.of( createTalerBank( host ?? (cs[0] as HostPortPath), - account ?? cs[1], + account ?? cs[cs.length - 1], params, + cs, ), ); }