diff options
author | Florian Dold <florian@dold.me> | 2023-02-14 11:16:58 +0100 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2023-02-14 11:17:19 +0100 |
commit | 6a4da88719bc7a1506433c1117b2402d2bd48f36 (patch) | |
tree | 7094aed1a6a8e1fe85854225c8744c955d7d973c | |
parent | 6106caeba9e017242dfd334c34c8473aefb6ffb0 (diff) |
wallet-core: expose more info about refund query
6 files changed, 109 insertions, 12 deletions
diff --git a/packages/taler-harness/src/harness/helpers.ts b/packages/taler-harness/src/harness/helpers.ts index ad77ce6ca..c1ce463fa 100644 --- a/packages/taler-harness/src/harness/helpers.ts +++ b/packages/taler-harness/src/harness/helpers.ts @@ -29,6 +29,8 @@ import { MerchantContractTerms, Duration, PreparePayResultType, + NotificationType, + WithdrawalGroupFinishedNotification, } from "@gnu-taler/taler-util"; import { BankAccessApi, @@ -466,6 +468,53 @@ export async function startWithdrawViaBank( // Some tests rely on the final withdraw failing. } +export interface WithdrawViaBankResult { + withdrawalFinishedCond: Promise<WithdrawalGroupFinishedNotification>; +} + +export async function withdrawViaBankV2( + t: GlobalTestState, + p: { + walletClient: WalletClient; + bank: BankService; + exchange: ExchangeServiceInterface; + amount: AmountString; + restrictAge?: number; + }, +): Promise<WithdrawViaBankResult> { + const { walletClient: wallet, bank, exchange, amount } = p; + + const user = await BankApi.createRandomBankUser(bank); + const wop = await BankAccessApi.createWithdrawalOperation(bank, user, amount); + + // Hand it to the wallet + + await wallet.client.call(WalletApiOperation.GetWithdrawalDetailsForUri, { + talerWithdrawUri: wop.taler_withdraw_uri, + restrictAge: p.restrictAge, + }); + + const withdrawalFinishedCond = wallet.waitForNotificationCond((x) => + x.type === NotificationType.WithdrawGroupFinished ? x : false, + ); + + // Withdraw (AKA select) + + await wallet.client.call(WalletApiOperation.AcceptBankIntegratedWithdrawal, { + exchangeBaseUrl: exchange.baseUrl, + talerWithdrawUri: wop.taler_withdraw_uri, + restrictAge: p.restrictAge, + }); + + // Confirm it + + await BankApi.confirmWithdrawalOperation(bank, user, wop); + + return { + withdrawalFinishedCond, + }; +} + /** * Withdraw balance. */ diff --git a/packages/taler-harness/src/integrationtests/test-refund.ts b/packages/taler-harness/src/integrationtests/test-refund.ts index 93850769a..4ae45b8bf 100644 --- a/packages/taler-harness/src/integrationtests/test-refund.ts +++ b/packages/taler-harness/src/integrationtests/test-refund.ts @@ -17,12 +17,16 @@ /** * Imports. */ -import { Duration, durationFromSpec } from "@gnu-taler/taler-util"; +import { + Duration, + durationFromSpec, + NotificationType, +} from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js"; import { - createSimpleTestkudosEnvironment, - withdrawViaBank, + createSimpleTestkudosEnvironmentV2, + withdrawViaBankV2, } from "../harness/helpers.js"; /** @@ -31,12 +35,23 @@ import { export async function runRefundTest(t: GlobalTestState) { // Set up test environment - const { wallet, bank, exchange, merchant } = - await createSimpleTestkudosEnvironment(t); + const { + walletClient: wallet, + bank, + exchange, + merchant, + } = await createSimpleTestkudosEnvironmentV2(t); // Withdraw digital cash into the wallet. - await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" }); + const withdrawalRes = await withdrawViaBankV2(t, { + walletClient: wallet, + bank, + exchange, + amount: "TESTKUDOS:20", + }); + + await withdrawalRes.withdrawalFinishedCond; // Set up order. @@ -85,12 +100,15 @@ export async function runRefundTest(t: GlobalTestState) { console.log(ref); { + const refundFinishedCond = wallet.waitForNotificationCond( + (x) => x.type === NotificationType.RefundFinished, + ); const r = await wallet.client.call(WalletApiOperation.ApplyRefund, { talerRefundUri: ref.talerRefundUri, }); console.log(r); - await wallet.runUntilDone(); + await refundFinishedCond; } { @@ -103,6 +121,9 @@ export async function runRefundTest(t: GlobalTestState) { } { + const refundQueriedCond = wallet.waitForNotificationCond( + (x) => x.type === NotificationType.RefundQueried, + ); const r3 = await wallet.client.call( WalletApiOperation.ApplyRefundFromPurchaseId, { @@ -110,11 +131,8 @@ export async function runRefundTest(t: GlobalTestState) { }, ); console.log(r3); - - await wallet.runUntilDone(); + await refundQueriedCond; } - - await t.shutdown(); } runRefundTest.suites = ["wallet"]; diff --git a/packages/taler-util/src/notifications.ts b/packages/taler-util/src/notifications.ts index 823c4130d..55d838007 100644 --- a/packages/taler-util/src/notifications.ts +++ b/packages/taler-util/src/notifications.ts @@ -96,6 +96,10 @@ export interface RefundStartedNotification { export interface RefundQueriedNotification { type: NotificationType.RefundQueried; + /** + * Transaction ID of the purchase (NOT the refund transaction). + */ + transactionId: string; } export interface ProposalDownloadedNotification { @@ -171,6 +175,11 @@ export interface WaitingForRetryNotification { export interface RefundFinishedNotification { type: NotificationType.RefundFinished; + + /** + * Transaction ID of the purchase (NOT the refund transaction). + */ + transactionId: string; } export interface ExchangeAddedNotification { diff --git a/packages/taler-util/src/transactions-types.ts b/packages/taler-util/src/transactions-types.ts index d108d1a77..946f9dda9 100644 --- a/packages/taler-util/src/transactions-types.ts +++ b/packages/taler-util/src/transactions-types.ts @@ -395,6 +395,11 @@ export interface TransactionPayment extends TransactionCommon { * Reference to applied refunds */ refunds: RefundInfoShort[]; + + /** + * Is the wallet currently checking for a refund? + */ + refundQueryActive: boolean; } export interface OrderShortInfo { diff --git a/packages/taler-wallet-core/src/operations/pay-merchant.ts b/packages/taler-wallet-core/src/operations/pay-merchant.ts index 14d80d17a..2a89c59ed 100644 --- a/packages/taler-wallet-core/src/operations/pay-merchant.ts +++ b/packages/taler-wallet-core/src/operations/pay-merchant.ts @@ -2415,6 +2415,13 @@ async function acceptRefunds( p.purchaseStatus = PurchaseStatus.Paid; } logger.trace("refund query done"); + ws.notify({ + type: NotificationType.RefundFinished, + transactionId: makeTransactionId( + TransactionType.Payment, + p.proposalId, + ), + }); } else { // No error, but we need to try again! p.timestampLastRefundStatus = now; @@ -2426,6 +2433,7 @@ async function acceptRefunds( ws.notify({ type: NotificationType.RefundQueried, + transactionId: makeTransactionId(TransactionType.Payment, proposalId), }); } @@ -2694,6 +2702,13 @@ export async function processPurchaseQueryRefund( await tx.purchases.put(purchase); }); + // No new refunds, but we still need to notify + // the wallet client that the query finished. + ws.notify({ + type: NotificationType.RefundQueried, + transactionId: makeTransactionId(TransactionType.Payment, proposalId), + }); + return OperationAttemptResult.finishedEmpty(); } } diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts index c1b82f9c9..8aae2332c 100644 --- a/packages/taler-wallet-core/src/operations/transactions.ts +++ b/packages/taler-wallet-core/src/operations/transactions.ts @@ -58,7 +58,6 @@ import { WithdrawalGroupStatus, } from "../db.js"; import { InternalWalletState } from "../internal-wallet-state.js"; -import { assertUnreachable } from "../util/assertUnreachable.js"; import { checkDbInvariant } from "../util/invariants.js"; import { RetryTags } from "../util/retries.js"; import { @@ -846,6 +845,8 @@ async function buildTransactionForPurchase( ), proposalId: purchaseRecord.proposalId, info, + refundQueryActive: + purchaseRecord.purchaseStatus === PurchaseStatus.QueryingRefund, frozen: purchaseRecord.purchaseStatus === PurchaseStatus.PaymentAbortFinished ?? false, |