summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2024-03-01 11:56:12 -0300
committerSebastian <sebasjm@gmail.com>2024-03-01 11:56:15 -0300
commit4d0bd5958690000a508c946b6d64819d55231375 (patch)
tree3c09c5833fd59201bfed62541826ea4580ebdad5
parent1facde4ab16c8d943f16f7cb0ded8dc9104dacfd (diff)
downloadwallet-core-4d0bd5958690000a508c946b6d64819d55231375.tar.gz
wallet-core-4d0bd5958690000a508c946b6d64819d55231375.tar.bz2
wallet-core-4d0bd5958690000a508c946b6d64819d55231375.zip
notify the UI about order paid by another wallet
After the request about the status of a shared payment returns "PAID = true" save the information in the database and use it to notify that the order is already-paid with paid:true If the order is already-aid with paid:false the UI will show claim-by-another-wallet which is not wrong but for this use case the other-wallet intentionally paid in the same session and is expected to be redirected to the purchased fulfillment url. note that the purchase does not create a transaction yet, since the payment is not made in the first wallet. And we should also take into account how this interacts with the repurchase detection.
-rw-r--r--packages/taler-wallet-core/src/db.ts6
-rw-r--r--packages/taler-wallet-core/src/pay-merchant.ts24
2 files changed, 25 insertions, 5 deletions
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index 9efc9fbe0..7e4f9fa4a 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -1326,6 +1326,12 @@ export interface PurchaseRecord {
* did not picked up yet
*/
refundAmountAwaiting: AmountString | undefined;
+
+ /**
+ * When the purchase has been shared to other wallet
+ * and the other wallet completed before this one.
+ */
+ paidByOther: boolean | undefined;
}
export enum ConfigRecordKey {
diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts
index e92156572..405ec14d7 100644
--- a/packages/taler-wallet-core/src/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/pay-merchant.ts
@@ -880,7 +880,7 @@ async function createOrReusePurchase(
);
if (oldProposal.purchaseStatus === PurchaseStatus.DialogShared) {
const download = await expectProposalDownload(wex, oldProposal);
- const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData);
+ const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData, false);
logger.info(`old proposal paid: ${paid}`);
if (paid) {
// if this transaction was shared and the order is paid then it
@@ -895,6 +895,7 @@ async function createOrReusePurchase(
}
const oldTxState = computePayMerchantTransactionState(p);
p.purchaseStatus = PurchaseStatus.FailedClaim;
+ p.paidByOther = true;
const newTxState = computePayMerchantTransactionState(p);
await tx.purchases.put(p);
return { oldTxState, newTxState };
@@ -942,6 +943,7 @@ async function createOrReusePurchase(
lastSessionId: undefined,
merchantPaySig: undefined,
payInfo: undefined,
+ paidByOther: undefined,
refundAmountAwaiting: undefined,
timestampAccept: undefined,
timestampFirstSuccessfulPay: undefined,
@@ -1377,7 +1379,7 @@ async function checkPaymentByProposalId(
status: PreparePayResultType.AlreadyConfirmed,
contractTerms: download.contractTermsRaw,
contractTermsHash: download.contractData.contractTermsHash,
- paid: false,
+ paid: purchase.paidByOther === true,
amountRaw: Amounts.stringify(download.contractData.amount),
amountEffective: purchase.payInfo
? Amounts.stringify(purchase.payInfo.totalPayCost)
@@ -2011,7 +2013,7 @@ async function processPurchasePay(
const download = await expectProposalDownload(wex, purchase);
if (purchase.shared) {
- const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData);
+ const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData, false);
if (paid) {
const transitionInfo = await wex.db.runReadWriteTx(
@@ -2024,6 +2026,7 @@ async function processPurchasePay(
}
const oldTxState = computePayMerchantTransactionState(p);
p.purchaseStatus = PurchaseStatus.FailedClaim;
+ p.paidByOther = true;
const newTxState = computePayMerchantTransactionState(p);
await tx.purchases.put(p);
return { oldTxState, newTxState };
@@ -2469,6 +2472,7 @@ export async function sharePayment(
}
return {
+ proposalId: p.proposalId,
nonce: p.noncePriv,
session: p.lastSessionId ?? p.downloadSessionId,
token: p.claimToken,
@@ -2478,6 +2482,11 @@ export async function sharePayment(
if (result === undefined) {
throw Error("This purchase can't be shared");
}
+
+ // schedule a task to watch for the status
+ const ctx = new PayMerchantTransactionContext(wex, result.proposalId);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
+
const privatePayUri = stringifyPayUri({
merchantBaseUrl,
orderId,
@@ -2485,12 +2494,14 @@ export async function sharePayment(
noncePriv: result.nonce,
claimToken: result.token,
});
+
return { privatePayUri };
}
async function checkIfOrderIsAlreadyPaid(
wex: WalletExecutionContext,
contract: WalletContractData,
+ doLongPolling: boolean,
) {
const requestUrl = new URL(
`orders/${contract.orderId}`,
@@ -2498,7 +2509,9 @@ async function checkIfOrderIsAlreadyPaid(
);
requestUrl.searchParams.set("h_contract", contract.contractTermsHash);
- requestUrl.searchParams.set("timeout_ms", "1000");
+ if (doLongPolling) {
+ requestUrl.searchParams.set("timeout_ms", "30000");
+ }
const resp = await wex.http.fetch(requestUrl.href, {
cancellationToken: wex.cancellationToken,
@@ -2528,7 +2541,7 @@ async function processPurchaseDialogShared(
return TaskRunResult.finished();
}
- const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData);
+ const paid = await checkIfOrderIsAlreadyPaid(wex, download.contractData, true);
if (paid) {
const transitionInfo = await wex.db.runReadWriteTx(
["purchases"],
@@ -2540,6 +2553,7 @@ async function processPurchaseDialogShared(
}
const oldTxState = computePayMerchantTransactionState(p);
p.purchaseStatus = PurchaseStatus.FailedClaim;
+ p.paidByOther = true
const newTxState = computePayMerchantTransactionState(p);
await tx.purchases.put(p);
return { oldTxState, newTxState };