aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-02-14 11:16:58 +0100
committerFlorian Dold <florian@dold.me>2023-02-14 11:17:19 +0100
commit6a4da88719bc7a1506433c1117b2402d2bd48f36 (patch)
tree7094aed1a6a8e1fe85854225c8744c955d7d973c
parent6106caeba9e017242dfd334c34c8473aefb6ffb0 (diff)
wallet-core: expose more info about refund query
-rw-r--r--packages/taler-harness/src/harness/helpers.ts49
-rw-r--r--packages/taler-harness/src/integrationtests/test-refund.ts40
-rw-r--r--packages/taler-util/src/notifications.ts9
-rw-r--r--packages/taler-util/src/transactions-types.ts5
-rw-r--r--packages/taler-wallet-core/src/operations/pay-merchant.ts15
-rw-r--r--packages/taler-wallet-core/src/operations/transactions.ts3
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,