taler-typescript-core

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

commit 9d69f4e407c382c05d9f89dea82724021bc53e0b
parent 193d93545ee3cebef77e55deabd5931a4bc49706
Author: Iván Ávalos <avalos@disroot.org>
Date:   Tue,  1 Jul 2025 14:32:41 +0200

wallet-core: handle retry of token validation

Diffstat:
Mpackages/taler-wallet-core/src/db.ts | 6++++++
Mpackages/taler-wallet-core/src/pay-merchant.ts | 37++++++++++++++++++++++++++++---------
2 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts @@ -57,6 +57,7 @@ import { MerchantContractTokenKind, RefreshReason, ScopeInfo, + SignedTokenEnvelope, TalerErrorDetail, TalerPreciseTimestamp, TalerProtocolDuration, @@ -1410,6 +1411,11 @@ export interface PurchasePayInfo { payTokenSelection?: DbTokenSelection; /** + * Token signatures from merchant. + */ + slateTokenSigs?: SignedTokenEnvelope[]; + + /** * Whether token selection should be forced * e.g. when merchant URL is not in `expected_domains' */ diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts @@ -3357,17 +3357,36 @@ async function processPurchasePay( throw Error("merchant payment signature invalid"); } - const slatesLen = slates?.length ?? 0; - const sigsLen = merchantResp.token_sigs?.length ?? 0; - logger.trace(`received ${sigsLen} token signatures from merchant`); - if (slatesLen !== sigsLen) { - throw Error( - `merchant returned mismatching number of token signatures (${slatesLen} vs ${sigsLen})`, - ); - } else if (slates && merchantResp.token_sigs) { + let tokenSigs; + if (payInfo.slateTokenSigs) { + tokenSigs = payInfo.slateTokenSigs; + } else { + const slatesLen = slates?.length ?? 0; + const sigsLen = merchantResp.token_sigs?.length ?? 0; + logger.trace(`received ${sigsLen} token signatures from merchant`); + if (slatesLen !== sigsLen) { + throw Error( + `merchant returned mismatching number of token signatures (${slatesLen} vs ${sigsLen})`, + ); + } else if (merchantResp.token_sigs) { + tokenSigs = merchantResp.token_sigs; + } + } + + if (tokenSigs) { + await wex.db.runReadWriteTx({ + storeNames: ["purchases"], + }, async (tx) => { + if (!purchase.payInfo) { return; } + purchase.payInfo.slateTokenSigs = tokenSigs; + tx.purchases.put(purchase); + }); + } + + if (slates && tokenSigs) { for (let i = 0; i < slates.length; i++) { const slate = slates[i]; - const sigEv = merchantResp.token_sigs[i]; + const sigEv = tokenSigs[i]; await validateAndStoreToken(wex, slate, sigEv); } }