taler-typescript-core

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

commit def199019fab39b492b668c668a80877f672196d
parent 9c9b8edabdf8a408da3ee15d280a5f96147c5e8b
Author: Florian Dold <dold@taler.net>
Date:   Thu, 23 Jul 2026 02:46:47 +0200

wallet: use typed merchant client for pay-template; wire merchant timeout/cancel

Diffstat:
Mpackages/taler-util/src/http-client/merchant.ts | 21++++++++++++++++++++-
Mpackages/taler-wallet-core/src/pay-template.ts | 22++++++++--------------
Mpackages/taler-wallet-core/src/wallet.ts | 2++
3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/packages/taler-util/src/http-client/merchant.ts b/packages/taler-util/src/http-client/merchant.ts @@ -197,16 +197,19 @@ export class TalerMerchantInstanceHttpClient { readonly httpLib: HttpRequestLibrary; readonly cacheEvictor: CacheEvictor<TalerMerchantInstanceCacheEviction>; readonly cancellationToken: CancellationToken | undefined; + readonly timeout: Duration | undefined; constructor( readonly baseUrl: string, httpClient?: HttpRequestLibrary, cacheEvictor?: CacheEvictor<TalerMerchantInstanceCacheEviction>, cancellationToken?: CancellationToken, + timeout?: Duration, ) { this.httpLib = httpClient ?? createPlatformHttpLib(); this.cacheEvictor = cacheEvictor ?? nullEvictor; this.cancellationToken = cancellationToken; + this.timeout = timeout; } static isCompatible(version: string): boolean { @@ -453,6 +456,8 @@ export class TalerMerchantInstanceHttpClient { const resp = await this.httpLib.fetch(url.href, { method: "POST", body, + cancellationToken: this.cancellationToken, + timeout: this.timeout, }); switch (resp.status) { @@ -533,7 +538,8 @@ export class TalerMerchantInstanceHttpClient { const resp = await this.httpLib.fetch(url.href, { method: "GET", - // body, + cancellationToken: this.cancellationToken, + timeout: this.timeout, }); switch (resp.status) { @@ -621,6 +627,8 @@ export class TalerMerchantInstanceHttpClient { const resp = await this.httpLib.fetch(url.href, { method: "POST", body, + cancellationToken: this.cancellationToken, + timeout: this.timeout, }); switch (resp.status) { @@ -630,6 +638,11 @@ export class TalerMerchantInstanceHttpClient { ); return opSuccessFromHttp(resp, codecForPaidRefundStatusResponse()); } + case HttpStatusCode.NoContent: + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_ORDER, + ); + return opEmptySuccess(resp); case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Forbidden: @@ -653,6 +666,8 @@ export class TalerMerchantInstanceHttpClient { const resp = await this.httpLib.fetch(url.href, { method: "POST", body, + cancellationToken: this.cancellationToken, + timeout: this.timeout, }); switch (resp.status) { @@ -685,6 +700,8 @@ export class TalerMerchantInstanceHttpClient { const resp = await this.httpLib.fetch(url.href, { method: "POST", body, + cancellationToken: this.cancellationToken, + timeout: this.timeout, }); switch (resp.status) { @@ -2598,6 +2615,8 @@ export class TalerMerchantInstanceHttpClient { const resp = await this.httpLib.fetch(url.href, { method: "POST", body, + cancellationToken: this.cancellationToken, + timeout: this.timeout, }); return this.procesOrderCreationResponse(resp); diff --git a/packages/taler-wallet-core/src/pay-template.ts b/packages/taler-wallet-core/src/pay-template.ts @@ -20,7 +20,6 @@ import { assertUnreachable, CheckPayTemplateReponse, CheckPayTemplateRequest, - codecForPostOrderResponse, HostPortPath, j2s, Logger, @@ -38,8 +37,6 @@ import { TemplateType, UsingTemplateDetailsRequest, } from "@gnu-taler/taler-util"; -import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http"; -import { cancelableFetch } from "./common.js"; import { runWithMaybeProgressContext, runWithProgressRetries, @@ -299,20 +296,17 @@ export async function instantiateTemplateRaw( req.templateParams ?? {}, ); - const reqUrl = new URL( - `templates/${parsedUri.templateId}`, - parsedUri.merchantBaseUrl, - ); // Retried under a progress context. Instantiating a template creates a // fresh order server-side, so a retry after a failure just starts another // one; the order the wallet ends up paying is the one this call returns. - const resp = await runWithProgressRetries(wex, async () => { - const httpReq = await cancelableFetch(wex, reqUrl, { - method: "POST", - body: templateDetails, - }); - return readSuccessResponseJsonOrThrow(httpReq, codecForPostOrderResponse()); - }); + const resp = await runWithProgressRetries(wex, async () => + succeedOrThrow( + await merchantApi.useTemplateCreateOrder( + parsedUri.templateId, + templateDetails, + ), + ), + ); return { merchantBaseUrl: parsedUri.merchantBaseUrl, diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts @@ -157,12 +157,14 @@ export function walletBankIntegrationClient( export function walletMerchantClient( baseUrl: string, wex: WalletExecutionContext, + timeout?: Duration, ): TalerMerchantInstanceHttpClient { return new TalerMerchantInstanceHttpClient( baseUrl, wex.http, undefined, wex.cancellationToken, + timeout, ); }