add prepareRefund operation to gather information about the refund before confirm
This commit is contained in:
parent
9996c27488
commit
e5c9f588e4
@ -276,6 +276,18 @@ export class ReturnCoinsRequest {
|
||||
static checked: (obj: any) => ReturnCoinsRequest;
|
||||
}
|
||||
|
||||
export interface PrepareRefundResult {
|
||||
proposalId: string;
|
||||
|
||||
applied: number;
|
||||
failed: number;
|
||||
total: number;
|
||||
|
||||
amountEffectivePaid: AmountString;
|
||||
|
||||
info: OrderShortInfo;
|
||||
}
|
||||
|
||||
export interface PrepareTipResult {
|
||||
/**
|
||||
* Unique ID for the tip assigned by the wallet.
|
||||
@ -1003,6 +1015,17 @@ export const codecForForceRefreshRequest = (): Codec<ForceRefreshRequest> =>
|
||||
.property("coinPubList", codecForList(codecForString()))
|
||||
.build("ForceRefreshRequest");
|
||||
|
||||
|
||||
|
||||
export interface PrepareRefundRequest {
|
||||
talerRefundUri: string;
|
||||
}
|
||||
|
||||
export const codecForPrepareRefundRequest = (): Codec<PrepareRefundRequest> =>
|
||||
buildCodecForObject<PrepareRefundRequest>()
|
||||
.property("talerRefundUri", codecForString())
|
||||
.build("PrepareRefundRequest");
|
||||
|
||||
export interface PrepareTipRequest {
|
||||
talerTipUri: string;
|
||||
}
|
||||
|
@ -46,6 +46,8 @@ import {
|
||||
AbsoluteTime,
|
||||
TalerProtocolTimestamp,
|
||||
Duration,
|
||||
PrepareRefundRequest,
|
||||
PrepareRefundResult,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import {
|
||||
AbortStatus,
|
||||
@ -69,6 +71,72 @@ import { guardOperationException } from "./common.js";
|
||||
|
||||
const logger = new Logger("refund.ts");
|
||||
|
||||
|
||||
export async function prepareRefund(
|
||||
ws: InternalWalletState,
|
||||
talerRefundUri: string,
|
||||
): Promise<PrepareRefundResult> {
|
||||
const parseResult = parseRefundUri(talerRefundUri);
|
||||
|
||||
logger.trace("preparing refund offer", parseResult);
|
||||
|
||||
if (!parseResult) {
|
||||
throw Error("invalid refund URI");
|
||||
}
|
||||
|
||||
const purchase = await ws.db
|
||||
.mktx((x) => ({
|
||||
purchases: x.purchases,
|
||||
}))
|
||||
.runReadOnly(async (tx) => {
|
||||
return tx.purchases.indexes.byMerchantUrlAndOrderId.get([
|
||||
parseResult.merchantBaseUrl,
|
||||
parseResult.orderId,
|
||||
]);
|
||||
});
|
||||
|
||||
if (!purchase) {
|
||||
throw Error(
|
||||
`no purchase for the taler://refund/ URI (${talerRefundUri}) was found`,
|
||||
);
|
||||
}
|
||||
|
||||
const proposalId = purchase.proposalId;
|
||||
const rfs = Object.values(purchase.refunds)
|
||||
|
||||
let applied = 0;
|
||||
let failed = 0;
|
||||
const total = rfs.length;
|
||||
rfs.forEach((refund) => {
|
||||
if (refund.type === RefundState.Failed) {
|
||||
failed = failed + 1;
|
||||
}
|
||||
if (refund.type === RefundState.Applied) {
|
||||
applied = applied + 1;
|
||||
}
|
||||
});
|
||||
|
||||
const { contractData: c } = purchase.download
|
||||
|
||||
return {
|
||||
proposalId,
|
||||
amountEffectivePaid: Amounts.stringify(purchase.totalPayCost),
|
||||
applied,
|
||||
failed,
|
||||
total,
|
||||
info: {
|
||||
contractTermsHash: c.contractTermsHash,
|
||||
merchant: c.merchant,
|
||||
orderId: c.orderId,
|
||||
products: c.products,
|
||||
summary: c.summary,
|
||||
fulfillmentMessage: c.fulfillmentMessage,
|
||||
summary_i18n: c.summaryI18n,
|
||||
fulfillmentMessage_i18n:
|
||||
c.fulfillmentMessageI18n,
|
||||
},
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Retry querying and applying refunds for an order later.
|
||||
*/
|
||||
|
@ -23,9 +23,7 @@
|
||||
* Imports.
|
||||
*/
|
||||
import {
|
||||
AcceptManualWithdrawalResult,
|
||||
AcceptWithdrawalResponse,
|
||||
AmountJson,
|
||||
AbsoluteTime, AcceptManualWithdrawalResult, AmountJson,
|
||||
Amounts,
|
||||
BalancesResponse,
|
||||
codecForAbortPayWithRefundRequest,
|
||||
@ -48,8 +46,7 @@ import {
|
||||
codecForImportDbRequest,
|
||||
codecForIntegrationTestArgs,
|
||||
codecForListKnownBankAccounts,
|
||||
codecForPreparePayRequest,
|
||||
codecForPrepareTipRequest,
|
||||
codecForPreparePayRequest, codecForPrepareRefundRequest, codecForPrepareTipRequest,
|
||||
codecForRetryTransactionRequest,
|
||||
codecForSetCoinSuspendedRequest,
|
||||
codecForSetWalletDeviceIdRequest,
|
||||
@ -59,8 +56,7 @@ import {
|
||||
codecForWithdrawFakebankRequest,
|
||||
codecForWithdrawTestBalance,
|
||||
CoinDumpJson,
|
||||
CoreApiResponse,
|
||||
durationFromSpec,
|
||||
CoreApiResponse, Duration, durationFromSpec,
|
||||
durationMin,
|
||||
ExchangeListItem,
|
||||
ExchangesListRespose,
|
||||
@ -73,14 +69,23 @@ import {
|
||||
parsePaytoUri,
|
||||
PaytoUri,
|
||||
RefreshReason,
|
||||
TalerErrorCode,
|
||||
AbsoluteTime,
|
||||
URL,
|
||||
WalletNotification,
|
||||
Duration,
|
||||
CancellationToken,
|
||||
TalerErrorCode, URL,
|
||||
WalletNotification
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { timeStamp } from "console";
|
||||
import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
|
||||
import {
|
||||
CryptoDispatcher,
|
||||
CryptoWorkerFactory
|
||||
} from "./crypto/workers/cryptoDispatcher.js";
|
||||
import {
|
||||
AuditorTrustRecord,
|
||||
CoinSourceType,
|
||||
exportDb,
|
||||
importDb,
|
||||
ReserveRecordStatus,
|
||||
WalletStoresV1
|
||||
} from "./db.js";
|
||||
import { getErrorDetailFromException, TalerError } from "./errors.js";
|
||||
import {
|
||||
DenomInfo,
|
||||
ExchangeOperations,
|
||||
@ -89,21 +94,8 @@ import {
|
||||
MerchantOperations,
|
||||
NotificationListener,
|
||||
RecoupOperations,
|
||||
ReserveOperations,
|
||||
ReserveOperations
|
||||
} from "./internal-wallet-state.js";
|
||||
import {
|
||||
CryptoDispatcher,
|
||||
CryptoWorkerFactory,
|
||||
} from "./crypto/workers/cryptoDispatcher.js";
|
||||
import {
|
||||
AuditorTrustRecord,
|
||||
CoinSourceType,
|
||||
exportDb,
|
||||
importDb,
|
||||
ReserveRecordStatus,
|
||||
WalletStoresV1,
|
||||
} from "./db.js";
|
||||
import { getErrorDetailFromException, TalerError } from "./errors.js";
|
||||
import { exportBackup } from "./operations/backup/export.js";
|
||||
import {
|
||||
addBackupProvider,
|
||||
@ -115,7 +107,7 @@ import {
|
||||
loadBackupRecovery,
|
||||
processBackupForProvider,
|
||||
removeBackupProvider,
|
||||
runBackupCycle,
|
||||
runBackupCycle
|
||||
} from "./operations/backup/index.js";
|
||||
import { setWalletDeviceId } from "./operations/backup/state.js";
|
||||
import { getBalances } from "./operations/balance.js";
|
||||
@ -123,7 +115,7 @@ import {
|
||||
createDepositGroup,
|
||||
getFeeForDeposit,
|
||||
processDepositGroup,
|
||||
trackDepositGroup,
|
||||
trackDepositGroup
|
||||
} from "./operations/deposits.js";
|
||||
import {
|
||||
acceptExchangeTermsOfService,
|
||||
@ -132,69 +124,69 @@ import {
|
||||
getExchangeRequestTimeout,
|
||||
getExchangeTrust,
|
||||
updateExchangeFromUrl,
|
||||
updateExchangeTermsOfService,
|
||||
updateExchangeTermsOfService
|
||||
} from "./operations/exchanges.js";
|
||||
import { getMerchantInfo } from "./operations/merchants.js";
|
||||
import {
|
||||
confirmPay,
|
||||
preparePayForUri,
|
||||
processDownloadProposal,
|
||||
processPurchasePay,
|
||||
processPurchasePay
|
||||
} from "./operations/pay.js";
|
||||
import { getPendingOperations } from "./operations/pending.js";
|
||||
import { createRecoupGroup, processRecoupGroup } from "./operations/recoup.js";
|
||||
import {
|
||||
autoRefresh,
|
||||
createRefreshGroup,
|
||||
processRefreshGroup,
|
||||
processRefreshGroup
|
||||
} from "./operations/refresh.js";
|
||||
import {
|
||||
abortFailedPayWithRefund,
|
||||
applyRefund,
|
||||
processPurchaseQueryRefund,
|
||||
prepareRefund,
|
||||
processPurchaseQueryRefund
|
||||
} from "./operations/refund.js";
|
||||
import {
|
||||
createReserve,
|
||||
createTalerWithdrawReserve,
|
||||
getFundingPaytoUris,
|
||||
processReserve,
|
||||
processReserve
|
||||
} from "./operations/reserves.js";
|
||||
import {
|
||||
runIntegrationTest,
|
||||
testPay,
|
||||
withdrawTestBalance,
|
||||
withdrawTestBalance
|
||||
} from "./operations/testing.js";
|
||||
import { acceptTip, prepareTip, processTip } from "./operations/tip.js";
|
||||
import {
|
||||
deleteTransaction,
|
||||
getTransactions,
|
||||
retryTransaction,
|
||||
retryTransaction
|
||||
} from "./operations/transactions.js";
|
||||
import {
|
||||
getExchangeWithdrawalInfo,
|
||||
getWithdrawalDetailsForUri,
|
||||
processWithdrawGroup,
|
||||
processWithdrawGroup
|
||||
} from "./operations/withdraw.js";
|
||||
import {
|
||||
PendingOperationsResponse,
|
||||
PendingTaskInfo,
|
||||
PendingTaskType,
|
||||
PendingTaskType
|
||||
} from "./pending-types.js";
|
||||
import { assertUnreachable } from "./util/assertUnreachable.js";
|
||||
import { AsyncOpMemoMap, AsyncOpMemoSingle } from "./util/asyncMemo.js";
|
||||
import {
|
||||
HttpRequestLibrary,
|
||||
readSuccessResponseJsonOrThrow,
|
||||
readSuccessResponseJsonOrThrow
|
||||
} from "./util/http.js";
|
||||
import {
|
||||
AsyncCondition,
|
||||
OpenedPromise,
|
||||
openPromise,
|
||||
openPromise
|
||||
} from "./util/promiseUtils.js";
|
||||
import { DbAccess, GetReadWriteAccess } from "./util/query.js";
|
||||
import { TimerAPI, TimerGroup } from "./util/timer.js";
|
||||
import { WalletCoreApiClient } from "./wallet-api-types.js";
|
||||
import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
|
||||
|
||||
const builtinAuditors: AuditorTrustRecord[] = [
|
||||
{
|
||||
@ -908,6 +900,10 @@ async function dispatchRequestInternal(
|
||||
const req = codecForPrepareTipRequest().decode(payload);
|
||||
return await prepareTip(ws, req.talerTipUri);
|
||||
}
|
||||
case "prepareRefund": {
|
||||
const req = codecForPrepareRefundRequest().decode(payload);
|
||||
return await prepareRefund(ws, req.talerRefundUri);
|
||||
}
|
||||
case "acceptTip": {
|
||||
const req = codecForAcceptTipRequest().decode(payload);
|
||||
await acceptTip(ws, req.walletTipId);
|
||||
|
Loading…
Reference in New Issue
Block a user