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:
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);
}
}