taler-typescript-core

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

commit 0101e703dfb8a4280f8c416db25b333aa64fc6e3
parent 1c92825ed08f60f9c60ed018b73b94e1d843a3ba
Author: Florian Dold <florian@dold.me>
Date:   Mon, 28 Apr 2025 02:25:23 +0200

harness: restore old test assertion in denom-unoffered, simplify

Diffstat:
Mpackages/taler-harness/src/integrationtests/test-denom-unoffered.ts | 55++++++++++++++++++++++++++++++-------------------------
Mpackages/taler-wallet-core/src/pay-merchant.ts | 24++++++++++++++++++++++++
2 files changed, 54 insertions(+), 25 deletions(-)

diff --git a/packages/taler-harness/src/integrationtests/test-denom-unoffered.ts b/packages/taler-harness/src/integrationtests/test-denom-unoffered.ts @@ -18,14 +18,15 @@ * Imports. */ import { + codecForTalerErrorDetail, Duration, j2s, Logger, PreparePayResultType, succeedOrThrow, TalerErrorCode, + TalerErrorDetail, TalerMerchantInstanceHttpClient, - TransactionType, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { @@ -123,20 +124,26 @@ export async function runDenomUnofferedTest(t: GlobalTestState) { logger.info(`tx error: ${j2s(tx.error)}`); - const merchantErrorCode = (tx.error as any).requestError.errorResponse.code; - - switch (merchantErrorCode) { - case TalerErrorCode.MERCHANT_GENERIC_EXCHANGE_TIMEOUT: - // Merchant didn't receive/process the keys from the exchange yet, - // merchant's response indicates "timeout" from the exchange - // request, but in fact the merchant is throttling the request. - break; - case TalerErrorCode.MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_NOT_FOUND: - // Merchant already managed to re-contact the exchange. - break; - default: - t.fail(`unexpected error code: ${merchantErrorCode}`); - } + t.assertDeepEqual((tx.error as any).requestError.httpStatusCode, 502); + + const merchantErrorResp: TalerErrorDetail = (tx.error as any).requestError + .errorResponse; + + t.assertDeepEqual(merchantErrorResp.exchange_http_status, 404); + + t.assertDeepEqual( + merchantErrorResp.code, + TalerErrorCode.MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS, + ); + + const exchangeResp = codecForTalerErrorDetail().decode( + merchantErrorResp.exchange_reply, + ); + + t.assertDeepEqual( + exchangeResp.code, + TalerErrorCode.EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN, + ); // Force updating the exchange entry so that the wallet knows about the new denominations. await walletClient.call(WalletApiOperation.UpdateExchangeEntry, { @@ -144,10 +151,6 @@ export async function runDenomUnofferedTest(t: GlobalTestState) { force: true, }); - // await walletClient.call(WalletApiOperation.DeleteTransaction, { - // transactionId: confirmResp.transactionId, - // }); - logger.info(`withdrawing (with new denoms)`); // Now withdrawal should work again. @@ -183,15 +186,17 @@ export async function runDenomUnofferedTest(t: GlobalTestState) { const txs = await walletClient.call(WalletApiOperation.GetTransactions, { sort: "stable-ascending", - includeRefreshes: true, }); console.log(JSON.stringify(txs, undefined, 2)); - t.assertDeepEqual(txs.transactions[0].type, TransactionType.Withdrawal); - t.assertDeepEqual(txs.transactions[1].type, TransactionType.Refresh); - t.assertDeepEqual(txs.transactions[2].type, TransactionType.Payment); - t.assertDeepEqual(txs.transactions[3].type, TransactionType.DenomLoss); - t.assertDeepEqual(txs.transactions[4].type, TransactionType.Withdrawal); + const txTypes = txs.transactions.map((x) => x.type); + + t.assertDeepEqual(txTypes, [ + "withdrawal", + "payment", + "denom-loss", + "withdrawal", + ]); } runDenomUnofferedTest.suites = ["wallet"]; diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts @@ -1674,6 +1674,7 @@ async function handleInsufficientFunds( await ctx.abortTransaction({ code: TalerErrorCode.WALLET_TRANSACTION_PROTOCOL_VIOLATION, message: "Denomination used in payment became invalid.", + errorDetails: err, }); return TaskRunResult.progress(); } else { @@ -3407,6 +3408,29 @@ async function processPurchasePay( } } + if (resp.status === HttpStatusCode.BadGateway) { + const err = await readTalerErrorResponse(resp); + switch (err.code) { + case TalerErrorCode.MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS: { + const exchangeEc = (err.exchange_reply as any)?.code; + switch (exchangeEc) { + case TalerErrorCode.EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN: + // We might want to handle this in the future by re-denomination, + // for now we just abort. + await ctx.abortTransaction({ + code: TalerErrorCode.WALLET_TRANSACTION_PROTOCOL_VIOLATION, + message: "Denomination used in payment became invalid.", + errorDetails: err, + }); + return TaskRunResult.progress(); + } + break; + } + } + // We don't know the specific error, so it's safer to retry. + return throwUnexpectedRequestError(resp, err); + } + if (resp.status === HttpStatusCode.UnavailableForLegalReasons) { logger.warn(`pay transaction aborted, merchant has KYC problems`); await ctx.abortTransaction(