From a09359bd3930f2a4550de22bd018122a2c7846e6 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 24 Aug 2021 15:08:34 +0200 Subject: implement freezing for payments --- packages/taler-wallet-core/src/db.ts | 6 ++++++ packages/taler-wallet-core/src/operations/pay.ts | 21 +++++++++++++++++++++ .../taler-wallet-core/src/operations/pending.ts | 6 +++++- .../src/operations/transactions.ts | 6 ++++++ packages/taler-wallet-core/src/util/http.ts | 1 + 5 files changed, 39 insertions(+), 1 deletion(-) (limited to 'packages/taler-wallet-core') diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index ef6b45c11..66d79ebc0 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -1276,6 +1276,12 @@ export interface PurchaseRecord { * Continue querying the refund status until this deadline has expired. */ autoRefundDeadline: Timestamp | undefined; + + /** + * Is the payment frozen? I.e. did we encounter + * an error where it doesn't make sense to retry. + */ + payFrozen?: boolean; } export const WALLET_BACKUP_STATE_KEY = "walletBackupState"; diff --git a/packages/taler-wallet-core/src/operations/pay.ts b/packages/taler-wallet-core/src/operations/pay.ts index a201e6f8d..9a7b0d069 100644 --- a/packages/taler-wallet-core/src/operations/pay.ts +++ b/packages/taler-wallet-core/src/operations/pay.ts @@ -93,6 +93,7 @@ import { readSuccessResponseJsonOrErrorCode, readSuccessResponseJsonOrThrow, readTalerErrorResponse, + readUnexpectedResponseDetails, throwUnexpectedRequestError, } from "../util/http.js"; import { @@ -1209,6 +1210,26 @@ async function submitPay( }; } + if (resp.status === HttpResponseStatus.BadRequest) { + const errDetails = await readUnexpectedResponseDetails(resp); + logger.warn("unexpected 400 response for /pay"); + logger.warn(j2s(errDetails)); + await ws.db + .mktx((x) => ({ purchases: x.purchases })) + .runReadWrite(async (tx) => { + const purch = await tx.purchases.get(proposalId); + if (!purch) { + return; + } + purch.payFrozen = true; + purch.lastPayError = errDetails; + delete purch.payRetryInfo; + await tx.purchases.put(purch); + }); + // FIXME: Maybe introduce a new return type for this instead of throwing? + throw new OperationFailedAndReportedError(errDetails); + } + if (resp.status === HttpResponseStatus.Conflict) { const err = await readTalerErrorResponse(resp); if ( diff --git a/packages/taler-wallet-core/src/operations/pending.ts b/packages/taler-wallet-core/src/operations/pending.ts index a4ca972a7..a87b1c8b1 100644 --- a/packages/taler-wallet-core/src/operations/pending.ts +++ b/packages/taler-wallet-core/src/operations/pending.ts @@ -235,7 +235,11 @@ async function gatherPurchasePending( resp: PendingOperationsResponse, ): Promise { await tx.purchases.iter().forEach((pr) => { - if (pr.paymentSubmitPending && pr.abortStatus === AbortStatus.None) { + if ( + pr.paymentSubmitPending && + pr.abortStatus === AbortStatus.None && + !pr.payFrozen + ) { const timestampDue = pr.payRetryInfo?.nextRetry ?? getTimestampNow(); resp.pendingOperations.push({ type: PendingTaskType.Pay, diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts index a21dbe8b8..dc738b77f 100644 --- a/packages/taler-wallet-core/src/operations/transactions.ts +++ b/packages/taler-wallet-core/src/operations/transactions.ts @@ -168,6 +168,7 @@ export async function getTransactions( TransactionType.Withdrawal, wsr.withdrawalGroupId, ), + frozen: false, ...(wsr.lastError ? { error: wsr.lastError } : {}), }); }); @@ -215,6 +216,7 @@ export async function getTransactions( TransactionType.Withdrawal, r.initialWithdrawalGroupId, ), + frozen: false, ...(r.lastError ? { error: r.lastError } : {}), }); }); @@ -230,6 +232,7 @@ export async function getTransactions( amountRaw: Amounts.stringify(dg.effectiveDepositAmount), amountEffective: Amounts.stringify(dg.totalPayCost), pending: !dg.timestampFinished, + frozen: false, timestamp: dg.timestampCreated, targetPaytoUri: dg.wire.payto_uri, transactionId: makeEventId( @@ -288,6 +291,7 @@ export async function getTransactions( transactionId: paymentTransactionId, proposalId: pr.proposalId, info: info, + frozen: pr.payFrozen ?? false, ...(err ? { error: err } : {}), }); @@ -351,6 +355,7 @@ export async function getTransactions( amountEffective: Amounts.stringify(amountEffective), amountRaw: Amounts.stringify(amountRaw), pending: false, + frozen: false, }); } }); @@ -372,6 +377,7 @@ export async function getTransactions( amountEffective: Amounts.stringify(tipRecord.tipAmountEffective), amountRaw: Amounts.stringify(tipRecord.tipAmountRaw), pending: !tipRecord.pickedUpTimestamp, + frozen: false, timestamp: tipRecord.acceptedTimestamp, transactionId: makeEventId( TransactionType.Tip, diff --git a/packages/taler-wallet-core/src/util/http.ts b/packages/taler-wallet-core/src/util/http.ts index ce507465a..e056ffcee 100644 --- a/packages/taler-wallet-core/src/util/http.ts +++ b/packages/taler-wallet-core/src/util/http.ts @@ -64,6 +64,7 @@ export enum HttpResponseStatus { NoContent = 204, Gone = 210, NotModified = 304, + BadRequest = 400, PaymentRequired = 402, NotFound = 404, Conflict = 409, -- cgit v1.2.3