commit 87ae2e9211053ea0b16bb1b33dfbc1231a51a2d2 parent 44f69e9dcfdca85b5c0d8b650f408a7603112f0c Author: Florian Dold <dold@taler.net> Date: Fri, 24 Jul 2026 11:49:06 +0200 harness: migrate test cases to preparePay...V2 Diffstat:
43 files changed, 962 insertions(+), 354 deletions(-)
diff --git a/packages/taler-harness/src/harness/environments.ts b/packages/taler-harness/src/harness/environments.ts @@ -43,7 +43,6 @@ import { Logger, NotificationType, PartialWalletRunConfig, - PreparePayResultType, signAmlDecision, succeedOrThrow, TalerCorebankApiClient, @@ -1194,18 +1193,23 @@ export async function makeTestPaymentV2( // Make wallet pay for the order const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); const r2 = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, + choiceIndex: 0, }); t.assertDeepEqual(r2.type, ConfirmPayResultType.Done); diff --git a/packages/taler-harness/src/integrationtests/test-claim-loop.ts b/packages/taler-harness/src/integrationtests/test-claim-loop.ts @@ -20,6 +20,8 @@ import { succeedOrThrow, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { URL } from "node:url"; @@ -82,8 +84,20 @@ export async function runClaimLoopTest(t: GlobalTestState) { // Make wallet claim the unpaid order. t.assertTrue(orderStatusBefore.order_status === "unpaid"); const talerPayUri = orderStatusBefore.taler_pay_uri; - await walletClient.call(WalletApiOperation.PreparePayForUri, { - talerPayUri, + const preparePayResult = await walletClient.call( + WalletApiOperation.PreparePayForUriV2, + { + talerPayUri, + }, + ); + + // The proposal is only claimed once the download task has run. + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, }); // Query private order status after claiming it. diff --git a/packages/taler-harness/src/integrationtests/test-denom-unoffered.ts b/packages/taler-harness/src/integrationtests/test-denom-unoffered.ts @@ -20,11 +20,11 @@ import { j2s, Logger, - PreparePayResultType, succeedOrThrow, TalerErrorCode, TalerMerchantInstanceHttpClient, TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { @@ -100,20 +100,25 @@ export async function runDenomUnofferedTest(t: GlobalTestState) { // Make wallet pay for the order const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); t.logStep("order prepared"); const confirmResp = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, + choiceIndex: 0, }); t.logStep("order confirmed"); diff --git a/packages/taler-harness/src/integrationtests/test-donau-idempotency.ts b/packages/taler-harness/src/integrationtests/test-donau-idempotency.ts @@ -26,10 +26,10 @@ import { MerchantContractVersion, OrderOutputType, OrderVersion, - PreparePayResultType, succeedOrThrow, TalerMerchantInstanceHttpClient, TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; @@ -192,23 +192,33 @@ export async function runDonauIdempotencyTest(t: GlobalTestState) { t.assertTrue(orderStatus.order_status === "unpaid"); const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - console.log(`preparePayResult: ${j2s(preparePayResult)}`); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); - t.assertTrue( - preparePayResult.status === PreparePayResultType.ChoiceSelection, + const choicesResult = await walletClient.call( + WalletApiOperation.GetChoicesForPayment, + { + transactionId: preparePayResult.transactionId, + }, ); - t.assertDeepEqual( - preparePayResult.contractTerms.version, - MerchantContractVersion.V1, - ); - const outTok = preparePayResult.contractTerms.choices[0].outputs[0]; + console.log(`choicesResult: ${j2s(choicesResult)}`); + + const contractTerms = choicesResult.contractTerms; + + t.assertDeepEqual(contractTerms.version, MerchantContractVersion.V1); + const outTok = contractTerms.choices[0].outputs[0]; t.assertDeepEqual(outTok.type, MerchantContractOutputType.TaxReceipt); t.assertDeepEqual(outTok.donau_urls, [donau.baseUrl]); diff --git a/packages/taler-harness/src/integrationtests/test-donau-keychange.ts b/packages/taler-harness/src/integrationtests/test-donau-keychange.ts @@ -27,9 +27,10 @@ import { MerchantContractVersion, OrderOutputType, OrderVersion, - PreparePayResultType, succeedOrThrow, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; @@ -198,23 +199,33 @@ export async function runDonauKeychangeTest(t: GlobalTestState) { t.assertTrue(orderStatus.order_status === "unpaid"); const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - console.log(`preparePayResult: ${j2s(preparePayResult)}`); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); - t.assertTrue( - preparePayResult.status === PreparePayResultType.ChoiceSelection, + const choicesResult = await walletClient.call( + WalletApiOperation.GetChoicesForPayment, + { + transactionId: preparePayResult.transactionId, + }, ); - t.assertDeepEqual( - preparePayResult.contractTerms.version, - MerchantContractVersion.V1, - ); - const outTok = preparePayResult.contractTerms.choices[0].outputs[0]; + console.log(`choicesResult: ${j2s(choicesResult)}`); + + const contractTerms = choicesResult.contractTerms; + + t.assertDeepEqual(contractTerms.version, MerchantContractVersion.V1); + const outTok = contractTerms.choices[0].outputs[0]; t.assertDeepEqual(outTok.type, MerchantContractOutputType.TaxReceipt); t.assertDeepEqual(outTok.donau_urls, [donau.baseUrl]); diff --git a/packages/taler-harness/src/integrationtests/test-donau-minus-t.ts b/packages/taler-harness/src/integrationtests/test-donau-minus-t.ts @@ -26,9 +26,10 @@ import { MerchantContractVersion, OrderOutputType, OrderVersion, - PreparePayResultType, succeedOrThrow, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; @@ -157,23 +158,33 @@ export async function runDonauMinusTTest(t: GlobalTestState) { }); const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - console.log(`preparePayResult: ${j2s(preparePayResult)}`); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); - t.assertTrue( - preparePayResult.status === PreparePayResultType.ChoiceSelection, + const choicesResult = await walletClient.call( + WalletApiOperation.GetChoicesForPayment, + { + transactionId: preparePayResult.transactionId, + }, ); - t.assertDeepEqual( - preparePayResult.contractTerms.version, - MerchantContractVersion.V1, - ); - const outTok = preparePayResult.contractTerms.choices[0].outputs[0]; + console.log(`choicesResult: ${j2s(choicesResult)}`); + + const contractTerms = choicesResult.contractTerms; + + t.assertDeepEqual(contractTerms.version, MerchantContractVersion.V1); + const outTok = contractTerms.choices[0].outputs[0]; t.assertDeepEqual(outTok.type, MerchantContractOutputType.TaxReceipt); t.assertDeepEqual(outTok.donau_urls, [donau.baseUrl]); diff --git a/packages/taler-harness/src/integrationtests/test-donau-multi.ts b/packages/taler-harness/src/integrationtests/test-donau-multi.ts @@ -27,9 +27,10 @@ import { MerchantContractVersion, OrderOutputType, OrderVersion, - PreparePayResultType, succeedOrThrow, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; @@ -222,23 +223,33 @@ export async function runDonauMultiTest(t: GlobalTestState) { t.assertTrue(orderStatus.order_status === "unpaid"); const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - console.log(`preparePayResult: ${j2s(preparePayResult)}`); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); - t.assertTrue( - preparePayResult.status === PreparePayResultType.ChoiceSelection, + const choicesResult = await walletClient.call( + WalletApiOperation.GetChoicesForPayment, + { + transactionId: preparePayResult.transactionId, + }, ); - t.assertDeepEqual( - preparePayResult.contractTerms.version, - MerchantContractVersion.V1, - ); - const outTok = preparePayResult.contractTerms.choices[0].outputs[0]; + console.log(`choicesResult: ${j2s(choicesResult)}`); + + const contractTerms = choicesResult.contractTerms; + + t.assertDeepEqual(contractTerms.version, MerchantContractVersion.V1); + const outTok = contractTerms.choices[0].outputs[0]; t.assertDeepEqual(outTok.type, MerchantContractOutputType.TaxReceipt); // t.assertTrue(!!outTok.amount); diff --git a/packages/taler-harness/src/integrationtests/test-donau.ts b/packages/taler-harness/src/integrationtests/test-donau.ts @@ -27,9 +27,10 @@ import { MerchantContractVersion, OrderOutputType, OrderVersion, - PreparePayResultType, succeedOrThrow, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; @@ -192,23 +193,33 @@ export async function runDonauTest(t: GlobalTestState) { t.assertTrue(orderStatus.order_status === "unpaid"); const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - console.log(`preparePayResult: ${j2s(preparePayResult)}`); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); - t.assertTrue( - preparePayResult.status === PreparePayResultType.ChoiceSelection, + const choicesResult = await walletClient.call( + WalletApiOperation.GetChoicesForPayment, + { + transactionId: preparePayResult.transactionId, + }, ); - t.assertDeepEqual( - preparePayResult.contractTerms.version, - MerchantContractVersion.V1, - ); - const outTok = preparePayResult.contractTerms.choices[0].outputs[0]; + console.log(`choicesResult: ${j2s(choicesResult)}`); + + const contractTerms = choicesResult.contractTerms; + + t.assertDeepEqual(contractTerms.version, MerchantContractVersion.V1); + const outTok = contractTerms.choices[0].outputs[0]; t.assertDeepEqual(outTok.type, MerchantContractOutputType.TaxReceipt); t.assertDeepEqual(outTok.donau_urls, [donau.baseUrl]); diff --git a/packages/taler-harness/src/integrationtests/test-merchant-acctsel.ts b/packages/taler-harness/src/integrationtests/test-merchant-acctsel.ts @@ -23,6 +23,8 @@ import { PaytoString, succeedOrThrow, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; @@ -135,8 +137,20 @@ export async function runMerchantAcctselTest(t: GlobalTestState) { t.assertDeepEqual(ordDet1.order_status, "unpaid"); - await walletClient.call(WalletApiOperation.PreparePayForUri, { - talerPayUri: ordDet1.taler_pay_uri, + const preparePayResult = await walletClient.call( + WalletApiOperation.PreparePayForUriV2, + { + talerPayUri: ordDet1.taler_pay_uri, + }, + ); + + // The order is only claimed once the download task has run. + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, }); const ordDet2 = succeedOrThrow( @@ -177,8 +191,20 @@ export async function runMerchantAcctselTest(t: GlobalTestState) { t.assertDeepEqual(ordDet1.order_status, "unpaid"); - await walletClient.call(WalletApiOperation.PreparePayForUri, { - talerPayUri: ordDet1.taler_pay_uri, + const preparePayResult = await walletClient.call( + WalletApiOperation.PreparePayForUriV2, + { + talerPayUri: ordDet1.taler_pay_uri, + }, + ); + + // The order is only claimed once the download task has run. + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, }); const ordDet2 = succeedOrThrow( diff --git a/packages/taler-harness/src/integrationtests/test-merchant-deposit-large.ts b/packages/taler-harness/src/integrationtests/test-merchant-deposit-large.ts @@ -19,12 +19,13 @@ import { ConfirmPayResultType, Duration, j2s, - PreparePayResultType, succeedOrThrow, TalerCoreBankHttpClient, TalerMerchantApi, TalerMerchantInstanceHttpClient, TalerProtocolTimestamp, + TransactionMajorState, + TransactionMinorState, UserAndToken, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; @@ -131,19 +132,30 @@ export async function runMerchantDepositLargeTest(t: GlobalTestState) { // Make wallet pay for the order const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.PaymentPossible, + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + + const choicesResult = await walletClient.call( + WalletApiOperation.GetChoicesForPayment, + { + transactionId: preparePayResult.transactionId, + }, ); const diff = AbsoluteTime.difference( AbsoluteTime.fromProtocolTimestamp( - preparePayResult.contractTerms.wire_transfer_deadline, + choicesResult.contractTerms.wire_transfer_deadline, ), AbsoluteTime.now(), ); @@ -152,6 +164,7 @@ export async function runMerchantDepositLargeTest(t: GlobalTestState) { const r2 = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, + choiceIndex: 0, }); t.assertDeepEqual(r2.type, ConfirmPayResultType.Done); diff --git a/packages/taler-harness/src/integrationtests/test-merchant-exchange-confusion.ts b/packages/taler-harness/src/integrationtests/test-merchant-exchange-confusion.ts @@ -21,11 +21,13 @@ import { codecForMerchantOrderStatusUnpaid, ConfirmPayResultType, j2s, - PreparePayResultType, succeedOrThrow, TalerCorebankApiClient, TalerErrorCode, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, + TransactionType, TypedTalerErrorDetail, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; @@ -252,21 +254,31 @@ export async function runMerchantExchangeConfusionTest(t: GlobalTestState) { console.log(pubUnpaidStatus); let preparePayResp = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: pubUnpaidStatus.taler_pay_uri, }, ); - t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResp.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); const proposalTransactionId = preparePayResp.transactionId; + const payTx = await walletClient.call(WalletApiOperation.GetTransactionById, { + transactionId: proposalTransactionId, + }); + + t.assertTrue(payTx.type === TransactionType.Payment); + t.assertTrue(payTx.info != null); + const orderUrlWithHash = new URL(publicOrderStatusUrl); - orderUrlWithHash.searchParams.set( - "h_contract", - preparePayResp.contractTermsHash, - ); + orderUrlWithHash.searchParams.set("h_contract", payTx.info.contractTermsHash); console.log("requesting", orderUrlWithHash.href); @@ -284,6 +296,7 @@ export async function runMerchantExchangeConfusionTest(t: GlobalTestState) { const confirmPayRes = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: proposalTransactionId, + choiceIndex: 0, }); t.assertTrue(confirmPayRes.type === ConfirmPayResultType.Pending); diff --git a/packages/taler-harness/src/integrationtests/test-merchant-longpolling.ts b/packages/taler-harness/src/integrationtests/test-merchant-longpolling.ts @@ -19,8 +19,10 @@ */ import { ConfirmPayResultType, - PreparePayResultType, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, + TransactionType, URL, codecForMerchantOrderStatusUnpaid, succeedOrThrow, @@ -136,26 +138,37 @@ export async function runMerchantLongpollingTest(t: GlobalTestState) { */ let preparePayResp = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: pubUnpaidStatus.taler_pay_uri, }, ); - t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResp.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + + const payTx = await walletClient.call(WalletApiOperation.GetTransactionById, { + transactionId: preparePayResp.transactionId, + }); + + t.assertTrue(payTx.type === TransactionType.Payment); + t.assertTrue(payTx.info != null); publicOrderStatusUrl.searchParams.set("timeout_ms", "5000"); publicOrderStatusUrl.searchParams.set( "h_contract", - preparePayResp.contractTermsHash, + payTx.info.contractTermsHash, ); let publicOrderStatusPromise = harnessHttpLib.fetch( publicOrderStatusUrl.href, ); - t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible); - const proposalTransactionId = preparePayResp.transactionId; publicOrderStatusResp = await publicOrderStatusPromise; @@ -172,6 +185,7 @@ export async function runMerchantLongpollingTest(t: GlobalTestState) { const confirmPayRes = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: proposalTransactionId, + choiceIndex: 0, }); t.assertTrue(confirmPayRes.type === ConfirmPayResultType.Done); diff --git a/packages/taler-harness/src/integrationtests/test-merchant-payto-reuse.ts b/packages/taler-harness/src/integrationtests/test-merchant-payto-reuse.ts @@ -28,11 +28,12 @@ import { MerchantAccountKycStatus, Paytos, Result, - PreparePayResultType, succeedOrThrow, TalerMerchantInstanceHttpClient, TalerProtocolDuration, TalerWireGatewayHttpClient, + TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { @@ -134,7 +135,9 @@ async function doAccountKycAuth( t.assertTrue( myRow?.payto_kycauths != null && myRow.payto_kycauths.length == 1, ); - const authTxPayto = Result.unpack(Paytos.fromString(myRow.payto_kycauths[0])); + const authTxPayto = Result.unpack( + Paytos.fromString(myRow.payto_kycauths[0]), + ); const authTxMessage = authTxPayto?.params["message"]; t.assertTrue(typeof authTxMessage === "string"); t.assertTrue(authTxMessage.startsWith("KYC:")); @@ -305,19 +308,23 @@ export async function runMerchantPaytoReuseTest(t: GlobalTestState) { // Make wallet pay for the order const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - t.assertDeepEqual( - preparePayResult.status, - PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); const r2 = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, + choiceIndex: 0, }); t.assertDeepEqual(r2.type, ConfirmPayResultType.Done); @@ -354,19 +361,23 @@ export async function runMerchantPaytoReuseTest(t: GlobalTestState) { // Make wallet pay for the order const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - t.assertDeepEqual( - preparePayResult.status, - PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); const r2 = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, + choiceIndex: 0, }); t.assertDeepEqual(r2.type, ConfirmPayResultType.Done); diff --git a/packages/taler-harness/src/integrationtests/test-merchant-refund-api.ts b/packages/taler-harness/src/integrationtests/test-merchant-refund-api.ts @@ -20,9 +20,11 @@ import { AccessToken, Duration, - PreparePayResultType, succeedOrThrow, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, + TransactionType, URL, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; @@ -82,18 +84,23 @@ async function testRefundApiWithFulfillmentUrl( // Make wallet pay for the order let preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, + choiceIndex: 0, }); // Check if payment was successful. @@ -108,15 +115,25 @@ async function testRefundApiWithFulfillmentUrl( t.assertTrue(orderStatus.order_status === "paid"); preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.AlreadyConfirmed, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + }); + + const payTx = await walletClient.call(WalletApiOperation.GetTransactionById, { + transactionId: preparePayResult.transactionId, + }); + + t.assertTrue(payTx.type === TransactionType.Payment); + t.assertTrue(payTx.info != null); await merchantClient.addRefund(merchantAdminAccessToken, orderResp.order_id, { refund: "TESTKUDOS:5", @@ -143,7 +160,7 @@ async function testRefundApiWithFulfillmentUrl( ); publicOrderStatusUrl.searchParams.set( "h_contract", - preparePayResult.contractTermsHash, + payTx.info.contractTermsHash, ); let publicOrderStatusResp = await harnessHttpLib.fetch( @@ -209,18 +226,23 @@ async function testRefundApiWithFulfillmentMessage( // Make wallet pay for the order let preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, + choiceIndex: 0, }); // Check if payment was successful. @@ -235,15 +257,25 @@ async function testRefundApiWithFulfillmentMessage( t.assertTrue(orderStatus.order_status === "paid"); preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.AlreadyConfirmed, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + }); + + const payTx = await walletClient.call(WalletApiOperation.GetTransactionById, { + transactionId: preparePayResult.transactionId, + }); + + t.assertTrue(payTx.type === TransactionType.Payment); + t.assertTrue(payTx.info != null); await merchantClient.addRefund(merchantAdminAccessToken, orderId, { refund: "TESTKUDOS:5", @@ -267,7 +299,7 @@ async function testRefundApiWithFulfillmentMessage( ); publicOrderStatusUrl.searchParams.set( "h_contract", - preparePayResult.contractTermsHash, + payTx.info.contractTermsHash, ); let publicOrderStatusResp = await harnessHttpLib.fetch( diff --git a/packages/taler-harness/src/integrationtests/test-merchant-refund-fees.ts b/packages/taler-harness/src/integrationtests/test-merchant-refund-fees.ts @@ -22,6 +22,7 @@ import { succeedOrThrow, TalerMerchantInstanceHttpClient, TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { @@ -80,13 +81,21 @@ export async function runMerchantRefundFeesTest(t: GlobalTestState) { t.assertDeepEqual(orderStatus.order_status, "unpaid"); const prepResp = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: prepResp.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: prepResp.transactionId, + choiceIndex: 0, }); await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { transactionId: prepResp.transactionId, diff --git a/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts b/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts @@ -20,9 +20,11 @@ import { AccessToken, ConfirmPayResultType, - PreparePayResultType, TalerCorebankApiClient, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, + TransactionType, URL, encodeCrock, getRandomBytes, @@ -121,14 +123,28 @@ async function testWithClaimToken( } const preparePayResp = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, ); - t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible); - const contractTermsHash = preparePayResp.contractTermsHash; + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResp.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + + const payTx = await walletClient.call(WalletApiOperation.GetTransactionById, { + transactionId: preparePayResp.transactionId, + }); + + t.assertTrue(payTx.type === TransactionType.Payment); + t.assertTrue(payTx.info != null); + + const contractTermsHash = payTx.info.contractTermsHash; const proposalTransactionId = preparePayResp.transactionId; // claimed, unpaid, access with wrong h_contract @@ -184,6 +200,7 @@ async function testWithClaimToken( const confirmPayRes = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: proposalTransactionId, + choiceIndex: 0, }); t.assertTrue(confirmPayRes.type === ConfirmPayResultType.Done); @@ -385,7 +402,7 @@ async function testWithoutClaimToken( } const preparePayResp = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, @@ -393,8 +410,22 @@ async function testWithoutClaimToken( console.log(preparePayResp); - t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible); - const contractTermsHash = preparePayResp.contractTermsHash; + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResp.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + + const payTx = await walletClient.call(WalletApiOperation.GetTransactionById, { + transactionId: preparePayResp.transactionId, + }); + + t.assertTrue(payTx.type === TransactionType.Payment); + t.assertTrue(payTx.info != null); + + const contractTermsHash = payTx.info.contractTermsHash; const proposalTransactionId = preparePayResp.transactionId; // claimed, unpaid, access with wrong h_contract @@ -452,6 +483,7 @@ async function testWithoutClaimToken( const confirmPayRes = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: proposalTransactionId, + choiceIndex: 0, }); t.assertTrue(confirmPayRes.type === ConfirmPayResultType.Done); diff --git a/packages/taler-harness/src/integrationtests/test-merchant-wire.ts b/packages/taler-harness/src/integrationtests/test-merchant-wire.ts @@ -21,9 +21,10 @@ import { AbsoluteTime, AmountString, Duration, - PreparePayResultType, TalerMerchantApi, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, j2s, succeedOrThrow, } from "@gnu-taler/taler-util"; @@ -100,20 +101,23 @@ export async function runMerchantWireTest(t: GlobalTestState) { t.assertTrue(orderStatus.order_status === "unpaid"); const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - t.assertDeepEqual( - preparePayResult.status, - PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); const confirmPayResult = await walletClient.call( WalletApiOperation.ConfirmPay, - { transactionId: preparePayResult.transactionId }, + { transactionId: preparePayResult.transactionId, choiceIndex: 0 }, ); console.log("confirm pay result:"); console.log(j2s(confirmPayResult)); diff --git a/packages/taler-harness/src/integrationtests/test-otp.ts b/packages/taler-harness/src/integrationtests/test-otp.ts @@ -20,9 +20,10 @@ import { ConfirmPayResultType, Duration, - PreparePayResultType, TalerMerchantInstanceHttpClient, TemplateType, + TransactionMajorState, + TransactionMinorState, TransactionType, j2s, randomRfc3548Base32Key, @@ -93,7 +94,7 @@ export async function runOtpTest(t: GlobalTestState) { await wres.withdrawalFinishedCond; const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForTemplate, + WalletApiOperation.PreparePayForTemplateV2, { talerPayTemplateUri: `taler+http://pay-template/localhost:${merchant.port}/tpl1`, templateParams: {}, @@ -102,14 +103,19 @@ export async function runOtpTest(t: GlobalTestState) { console.log(preparePayResult); - t.assertTrue( - preparePayResult.status === PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); // Pay for it const r2 = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, + choiceIndex: 0, }); t.assertTrue(r2.type === ConfirmPayResultType.Done); diff --git a/packages/taler-harness/src/integrationtests/test-pay-paid.ts b/packages/taler-harness/src/integrationtests/test-pay-paid.ts @@ -19,9 +19,11 @@ */ import { ConfirmPayResultType, - PreparePayResultType, TalerCorebankApiClient, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, + TransactionType, URL, codecForMerchantOrderStatusUnpaid, succeedOrThrow, @@ -122,13 +124,19 @@ export async function runPayPaidTest(t: GlobalTestState) { console.log(pubUnpaidStatus); let preparePayResp = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: pubUnpaidStatus.taler_pay_uri, }, ); - t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResp.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); const proposalTransactionId = preparePayResp.transactionId; @@ -146,6 +154,7 @@ export async function runPayPaidTest(t: GlobalTestState) { const confirmPayRes = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: proposalTransactionId, + choiceIndex: 0, }); t.assertTrue(confirmPayRes.type === ConfirmPayResultType.Done); @@ -226,14 +235,38 @@ export async function runPayPaidTest(t: GlobalTestState) { // have the new session ID! // Wallet should now automatically re-play payment. preparePayResp = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatusTwo.taler_pay_uri, }, ); - t.assertTrue(preparePayResp.status === PreparePayResultType.AlreadyConfirmed); - t.assertTrue(preparePayResp.paid); + // The wallet detects the repurchase and replays the payment of the + // original order under the new session ID. + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResp.transactionId, + txState: { + major: TransactionMajorState.Failed, + minor: TransactionMinorState.Repurchase, + }, + }); + + const repurchaseTx = await walletClient.call( + WalletApiOperation.GetTransactionById, + { + transactionId: preparePayResp.transactionId, + }, + ); + + t.assertTrue(repurchaseTx.type === TransactionType.Payment); + t.assertTrue(repurchaseTx.repurchaseTransactionId != null); + + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: repurchaseTx.repurchaseTransactionId, + txState: { + major: TransactionMajorState.Done, + }, + }); // Make sure the wallet is actually doing the replay properly. t.assertTrue(numPaidRequested == 1); diff --git a/packages/taler-harness/src/integrationtests/test-payment-abort.ts b/packages/taler-harness/src/integrationtests/test-payment-abort.ts @@ -19,11 +19,12 @@ */ import { ConfirmPayResultType, - PreparePayResultType, TalerCorebankApiClient, TalerErrorCode, TalerErrorDetail, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, URL, codecForMerchantOrderStatusUnpaid, j2s, @@ -107,13 +108,19 @@ export async function runPaymentAbortTest(t: GlobalTestState) { console.log(pubUnpaidStatus); let preparePayResp = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: pubUnpaidStatus.taler_pay_uri, }, ); - t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResp.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); publicOrderStatusResp = await harnessHttpLib.fetch(publicOrderStatusUrl); @@ -148,6 +155,7 @@ export async function runPaymentAbortTest(t: GlobalTestState) { WalletApiOperation.ConfirmPay, { transactionId: preparePayResp.transactionId, + choiceIndex: 0, }, ); diff --git a/packages/taler-harness/src/integrationtests/test-payment-claim.ts b/packages/taler-harness/src/integrationtests/test-payment-claim.ts @@ -19,10 +19,11 @@ */ import { j2s, - PreparePayResultType, succeedOrThrow, TalerErrorCode, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { @@ -92,26 +93,48 @@ export async function runPaymentClaimTest(t: GlobalTestState) { // Make wallet pay for the order const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); - const errOne = await t.assertThrowsTalerErrorAsync(async () => { - await w2.walletClient.call(WalletApiOperation.PreparePayForUri, { + // The second wallet can't claim the order anymore. + const claimOne = await w2.walletClient.call( + WalletApiOperation.PreparePayForUriV2, + { talerPayUri, - }); + }, + ); + + await w2.walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: claimOne.transactionId, + txState: { + major: TransactionMajorState.Failed, + minor: TransactionMinorState.ClaimProposal, + }, }); - console.log(errOne); + const claimOneTx = await w2.walletClient.call( + WalletApiOperation.GetTransactionById, + { + transactionId: claimOne.transactionId, + }, + ); + + console.log(j2s(claimOneTx.failReason)); await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, + choiceIndex: 0, }); // Check if payment was successful. @@ -127,13 +150,32 @@ export async function runPaymentClaimTest(t: GlobalTestState) { await w2.walletClient.call(WalletApiOperation.ClearDb, {}); - const err = await t.assertThrowsTalerErrorAsync(async () => { - await w2.walletClient.call(WalletApiOperation.PreparePayForUri, { + const claimTwo = await w2.walletClient.call( + WalletApiOperation.PreparePayForUriV2, + { talerPayUri, - }); + }, + ); + + await w2.walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: claimTwo.transactionId, + txState: { + major: TransactionMajorState.Failed, + minor: TransactionMinorState.ClaimProposal, + }, }); - t.assertTrue(err.hasErrorCode(TalerErrorCode.WALLET_ORDER_ALREADY_CLAIMED)); + const claimTwoTx = await w2.walletClient.call( + WalletApiOperation.GetTransactionById, + { + transactionId: claimTwo.transactionId, + }, + ); + + t.assertDeepEqual( + claimTwoTx.failReason?.code, + TalerErrorCode.WALLET_ORDER_ALREADY_CLAIMED, + ); const txn = await w2.walletClient.call(WalletApiOperation.GetTransactionsV2, { includeAll: true, diff --git a/packages/taler-harness/src/integrationtests/test-payment-deleted.ts b/packages/taler-harness/src/integrationtests/test-payment-deleted.ts @@ -19,8 +19,9 @@ */ import { ConfirmPayResultType, - PreparePayResultType, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, j2s, succeedOrThrow, } from "@gnu-taler/taler-util"; @@ -83,15 +84,19 @@ export async function runPaymentDeletedTest(t: GlobalTestState) { // Make wallet pay for the order const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); succeedOrThrow( await merchantClient.deleteOrder( @@ -103,6 +108,7 @@ export async function runPaymentDeletedTest(t: GlobalTestState) { const r2 = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, + choiceIndex: 0, }); t.assertTrue(r2.type === ConfirmPayResultType.Pending); diff --git a/packages/taler-harness/src/integrationtests/test-payment-expired.ts b/packages/taler-harness/src/integrationtests/test-payment-expired.ts @@ -20,10 +20,10 @@ import { AbsoluteTime, Duration, - PreparePayResultType, TalerMerchantApi, TalerMerchantInstanceHttpClient, TransactionMajorState, + TransactionMinorState, j2s, succeedOrThrow, } from "@gnu-taler/taler-util"; @@ -103,16 +103,19 @@ export async function runPaymentExpiredTest(t: GlobalTestState) { t.assertTrue(orderStatus.order_status === "unpaid"); const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - t.assertDeepEqual( - preparePayResult.status, - PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); // Do *not* time-travel the wallet await applyTimeTravelV2( @@ -122,7 +125,7 @@ export async function runPaymentExpiredTest(t: GlobalTestState) { const confirmPayResult = await walletClient.call( WalletApiOperation.ConfirmPay, - { transactionId: preparePayResult.transactionId }, + { transactionId: preparePayResult.transactionId, choiceIndex: 0 }, ); console.log("confirm pay result:"); console.log(j2s(confirmPayResult)); @@ -178,16 +181,19 @@ export async function runPaymentExpiredTest(t: GlobalTestState) { t.assertTrue(orderStatus.order_status === "unpaid"); const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - t.assertDeepEqual( - preparePayResult.status, - PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); await applyTimeTravelV2( Duration.toMilliseconds(Duration.fromSpec({ hours: 1 })), diff --git a/packages/taler-harness/src/integrationtests/test-payment-idempotency.ts b/packages/taler-harness/src/integrationtests/test-payment-idempotency.ts @@ -18,9 +18,10 @@ * Imports. */ import { - PreparePayResultType, succeedOrThrow, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { @@ -85,32 +86,40 @@ export async function runPaymentIdempotencyTest(t: GlobalTestState) { // Make wallet pay for the order const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); const preparePayResultRep = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.PaymentPossible, - ); - t.assertTrue( - preparePayResultRep.status === PreparePayResultType.PaymentPossible, + // Preparing the payment twice must return the same transaction. + t.assertDeepEqual( + preparePayResultRep.transactionId, + preparePayResult.transactionId, ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + const proposalTransactionId = preparePayResult.transactionId; const confirmPayResult = await walletClient.call( WalletApiOperation.ConfirmPay, { transactionId: proposalTransactionId, + choiceIndex: 0, }, ); @@ -130,7 +139,7 @@ export async function runPaymentIdempotencyTest(t: GlobalTestState) { t.assertTrue(orderStatus.order_status === "paid"); const preparePayResultAfter = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, @@ -138,10 +147,18 @@ export async function runPaymentIdempotencyTest(t: GlobalTestState) { console.log("result after:", preparePayResultAfter); - t.assertTrue( - preparePayResultAfter.status === PreparePayResultType.AlreadyConfirmed, + // Preparing an already paid order returns the existing, done transaction. + t.assertDeepEqual( + preparePayResultAfter.transactionId, + preparePayResult.transactionId, ); - t.assertTrue(preparePayResultAfter.paid === true); + + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResultAfter.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + }); await t.shutdown(); } diff --git a/packages/taler-harness/src/integrationtests/test-payment-multiple.ts b/packages/taler-harness/src/integrationtests/test-payment-multiple.ts @@ -22,6 +22,8 @@ import { succeedOrThrow, TalerCorebankApiClient, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { coin_ct10, coin_u1 } from "../harness/denomStructures.js"; @@ -194,12 +196,21 @@ export async function runPaymentMultipleTest(t: GlobalTestState) { // Make wallet pay for the order - const r1 = await walletClient.call(WalletApiOperation.PreparePayForUri, { + const r1 = await walletClient.call(WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: r1.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: r1.transactionId, + choiceIndex: 0, }); // Check if payment was successful. diff --git a/packages/taler-harness/src/integrationtests/test-payment-share-idempotency.ts b/packages/taler-harness/src/integrationtests/test-payment-share-idempotency.ts @@ -20,7 +20,6 @@ import { AmountString, ConfirmPayResultType, - PreparePayResultType, succeedOrThrow, TalerMerchantInstanceHttpClient, TransactionMajorState, @@ -120,13 +119,17 @@ export async function runPaymentShareIdempotencyTest(t: GlobalTestState) { const order = await createOrder("TESTKUDOS:5"); // Claim the order with the first wallet const claimFirstWallet = await firstWallet.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: order.uri }, ); - t.assertTrue( - claimFirstWallet.status === PreparePayResultType.PaymentPossible, - ); + await firstWallet.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: claimFirstWallet.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); t.logStep("w1-payment-possible"); @@ -143,14 +146,10 @@ export async function runPaymentShareIdempotencyTest(t: GlobalTestState) { // claim from the second wallet const claimSecondWallet = await secondWallet.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: privatePayUri }, ); - t.assertTrue( - claimSecondWallet.status === PreparePayResultType.PaymentPossible, - ); - await secondWallet.call(WalletApiOperation.TestingWaitTransactionState, { transactionId: claimSecondWallet.transactionId, txState: { @@ -163,19 +162,23 @@ export async function runPaymentShareIdempotencyTest(t: GlobalTestState) { // claim from the second wallet (again) const claimSecondWalletAgain = await secondWallet.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: privatePayUri }, ); - t.assertTrue( - claimSecondWalletAgain.status === PreparePayResultType.PaymentPossible, - ); - // Preparing the payment must return the same transaction ID here. t.assertTrue( claimSecondWallet.transactionId === claimSecondWalletAgain.transactionId, ); + await secondWallet.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: claimSecondWalletAgain.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + t.logStep("w2-claimed-again"); console.log(`confirming ${claimSecondWalletAgain.transactionId}`); @@ -183,6 +186,7 @@ export async function runPaymentShareIdempotencyTest(t: GlobalTestState) { // pay from the second wallet const r2 = await secondWallet.call(WalletApiOperation.ConfirmPay, { transactionId: claimSecondWalletAgain.transactionId, + choiceIndex: 0, }); t.logStep("w2-confirmed"); @@ -224,13 +228,17 @@ export async function runPaymentShareIdempotencyTest(t: GlobalTestState) { const order = await createOrder("TESTKUDOS:5"); // Claim the order with the first wallet const claimFirstWallet = await firstWallet.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: order.uri }, ); - t.assertTrue( - claimFirstWallet.status === PreparePayResultType.PaymentPossible, - ); + await firstWallet.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: claimFirstWallet.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); t.logStep("w1-payment-possible"); @@ -247,21 +255,26 @@ export async function runPaymentShareIdempotencyTest(t: GlobalTestState) { // claim from the second wallet const claimSecondWallet = await secondWallet.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: privatePayUri }, ); console.log(`second claim tx id: ${claimSecondWallet.transactionId}`); - t.assertTrue( - claimSecondWallet.status === PreparePayResultType.PaymentPossible, - ); + await secondWallet.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: claimSecondWallet.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); t.logStep("w2-claimed"); // pay from the second wallet const r2 = await secondWallet.call(WalletApiOperation.ConfirmPay, { transactionId: claimSecondWallet.transactionId, + choiceIndex: 0, }); t.assertTrue(r2.type === ConfirmPayResultType.Done); @@ -290,14 +303,10 @@ export async function runPaymentShareIdempotencyTest(t: GlobalTestState) { // claim from the second wallet (again) const claimSecondWalletAgain = await secondWallet.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: privatePayUri }, ); - t.assertTrue( - claimSecondWalletAgain.status === PreparePayResultType.AlreadyConfirmed, - ); - t.logStep("scenario-a-b-wait-done"); await secondWallet.call(WalletApiOperation.TestingWaitTransactionState, { diff --git a/packages/taler-harness/src/integrationtests/test-payment-share.ts b/packages/taler-harness/src/integrationtests/test-payment-share.ts @@ -20,7 +20,6 @@ import { AmountString, ConfirmPayResultType, - PreparePayResultType, succeedOrThrow, TalerMerchantInstanceHttpClient, TransactionMajorState, @@ -119,13 +118,17 @@ export async function runPaymentShareTest(t: GlobalTestState) { const order = await createOrder("TESTKUDOS:5"); // Claim the order with the first wallet const claimFirstWallet = await firstWallet.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: order.uri }, ); - t.assertTrue( - claimFirstWallet.status === PreparePayResultType.PaymentPossible, - ); + await firstWallet.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: claimFirstWallet.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); t.logStep("w1-payment-possible"); @@ -142,19 +145,24 @@ export async function runPaymentShareTest(t: GlobalTestState) { // claim from the second wallet const claimSecondWallet = await secondWallet.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: privatePayUri }, ); - t.assertTrue( - claimSecondWallet.status === PreparePayResultType.PaymentPossible, - ); + await secondWallet.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: claimSecondWallet.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); t.logStep("w2-claimed"); // pay from the second wallet const r2 = await secondWallet.call(WalletApiOperation.ConfirmPay, { transactionId: claimSecondWallet.transactionId, + choiceIndex: 0, }); t.assertTrue(r2.type === ConfirmPayResultType.Done); @@ -186,19 +194,23 @@ export async function runPaymentShareTest(t: GlobalTestState) { // ) // Claim the order with the first wallet const claimFirstWalletAgain = await firstWallet.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: order.uri }, ); - t.assertTrue( - claimFirstWalletAgain.status === PreparePayResultType.AlreadyConfirmed, - ); - t.assertTrue(claimFirstWalletAgain.paid); + await firstWallet.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: claimFirstWalletAgain.transactionId, + txState: { + major: TransactionMajorState.Failed, + minor: TransactionMinorState.PaidByOther, + }, + }); t.logStep("w1-prepared-again"); const r1 = await firstWallet.call(WalletApiOperation.ConfirmPay, { transactionId: claimFirstWallet.transactionId, + choiceIndex: 0, }); //t.assertTrue(r1.type === ConfirmPayResultType.Pending); @@ -237,13 +249,17 @@ export async function runPaymentShareTest(t: GlobalTestState) { const order = await createOrder("TESTKUDOS:3"); // Claim the order with the first wallet const claimFirstWallet = await firstWallet.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: order.uri }, ); - t.assertTrue( - claimFirstWallet.status === PreparePayResultType.PaymentPossible, - ); + await firstWallet.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: claimFirstWallet.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); t.logStep("case2-w1-claimed"); @@ -260,19 +276,24 @@ export async function runPaymentShareTest(t: GlobalTestState) { // claim from the second wallet const claimSecondWallet = await secondWallet.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: privatePayUri }, ); t.logStep("case2-w2-prepared"); - t.assertTrue( - claimSecondWallet.status === PreparePayResultType.PaymentPossible, - ); + await secondWallet.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: claimSecondWallet.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); // pay from the first wallet const r2 = await firstWallet.call(WalletApiOperation.ConfirmPay, { transactionId: claimFirstWallet.transactionId, + choiceIndex: 0, }); t.assertTrue(r2.type === ConfirmPayResultType.Done); @@ -297,7 +318,7 @@ export async function runPaymentShareTest(t: GlobalTestState) { // this might happen automatically via long-polling // in the dialog state. - await secondWallet.call(WalletApiOperation.PreparePayForUri, { + await secondWallet.call(WalletApiOperation.PreparePayForUriV2, { talerPayUri: order.uri, }); diff --git a/packages/taler-harness/src/integrationtests/test-payment-template.ts b/packages/taler-harness/src/integrationtests/test-payment-template.ts @@ -21,9 +21,10 @@ import { AmountString, ConfirmPayResultType, Duration, - PreparePayResultType, TalerMerchantInstanceHttpClient, TemplateType, + TransactionMajorState, + TransactionMinorState, j2s, succeedOrThrow, } from "@gnu-taler/taler-util"; @@ -101,7 +102,7 @@ export async function runPaymentTemplateTest(t: GlobalTestState) { // Request a template payment const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForTemplate, + WalletApiOperation.PreparePayForTemplateV2, { talerPayTemplateUri, templateParams: { @@ -112,14 +113,26 @@ export async function runPaymentTemplateTest(t: GlobalTestState) { console.log(preparePayResult); - t.assertTrue( - preparePayResult.status === PreparePayResultType.PaymentPossible, + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + + const choicesResult = await walletClient.call( + WalletApiOperation.GetChoicesForPayment, + { + transactionId: preparePayResult.transactionId, + }, ); // Pay for it const r2 = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, + choiceIndex: 0, }); t.assertTrue(r2.type === ConfirmPayResultType.Done); @@ -129,7 +142,7 @@ export async function runPaymentTemplateTest(t: GlobalTestState) { const orderStatus = succeedOrThrow( await merchantClient.getOrderDetails( merchantAdminAccessToken, - preparePayResult.contractTerms.order_id, + choicesResult.contractTerms.order_id, ), ); @@ -156,18 +169,28 @@ export async function runPaymentTemplateTest(t: GlobalTestState) { t.assertAmountEquals(tc.amount, "TESTKUDOS:5"); const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForTemplate, + WalletApiOperation.PreparePayForTemplateV2, { talerPayTemplateUri: talerPayTemplateUriAmt, }, ); - t.assertDeepEqual( - preparePayResult.status, - PreparePayResultType.PaymentPossible, + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + + const choicesResult = await walletClient.call( + WalletApiOperation.GetChoicesForPayment, + { + transactionId: preparePayResult.transactionId, + }, ); - t.assertAmountEquals(preparePayResult.contractTerms.amount, "TESTKUDOS:5"); + t.assertAmountEquals(choicesResult.choices[0].amountRaw, "TESTKUDOS:5"); } await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {}); diff --git a/packages/taler-harness/src/integrationtests/test-payment-transient.ts b/packages/taler-harness/src/integrationtests/test-payment-transient.ts @@ -19,12 +19,12 @@ */ import { ConfirmPayResultType, - PreparePayResultType, TalerCorebankApiClient, TalerErrorCode, TalerErrorDetail, TalerMerchantInstanceHttpClient, TransactionMajorState, + TransactionMinorState, URL, codecForMerchantOrderStatusUnpaid, succeedOrThrow, @@ -110,13 +110,19 @@ export async function runPaymentTransientTest(t: GlobalTestState) { console.log(pubUnpaidStatus); let preparePayResp = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: pubUnpaidStatus.taler_pay_uri, }, ); - t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResp.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); const proposalTransactionId = preparePayResp.transactionId; @@ -162,6 +168,7 @@ export async function runPaymentTransientTest(t: GlobalTestState) { WalletApiOperation.ConfirmPay, { transactionId: proposalTransactionId, + choiceIndex: 0, }, ); diff --git a/packages/taler-harness/src/integrationtests/test-paywall-flow.ts b/packages/taler-harness/src/integrationtests/test-paywall-flow.ts @@ -19,9 +19,10 @@ */ import { ConfirmPayResultType, - PreparePayResultType, TalerMerchantInstanceHttpClient, TransactionMajorState, + TransactionMinorState, + TransactionType, URL, codecForMerchantOrderStatusUnpaid, j2s, @@ -119,13 +120,19 @@ export async function runPaywallFlowTest(t: GlobalTestState) { console.log(pubUnpaidStatus); let preparePayResp = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: pubUnpaidStatus.taler_pay_uri, }, ); - t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResp.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); const proposalTransactionId = preparePayResp.transactionId; @@ -144,6 +151,7 @@ export async function runPaywallFlowTest(t: GlobalTestState) { const confirmPayRes = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: proposalTransactionId, + choiceIndex: 0, }); t.assertTrue(confirmPayRes.type === ConfirmPayResultType.Done); @@ -181,15 +189,12 @@ export async function runPaywallFlowTest(t: GlobalTestState) { // have the new session ID! // Wallet should now automatically re-play payment. preparePayResp = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: talerPayUriOne, }, ); - t.assertTrue(preparePayResp.status === PreparePayResultType.AlreadyConfirmed); - t.assertTrue(preparePayResp.paid); - await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { transactionId: preparePayResp.transactionId, txState: { @@ -236,18 +241,33 @@ export async function runPaywallFlowTest(t: GlobalTestState) { // and the wallet should re-pay for the old order // under the new session ID (mysession-three). preparePayResp = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - t.assertTrue(preparePayResp.status === PreparePayResultType.AlreadyConfirmed); - t.assertTrue(preparePayResp.paid); - await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { transactionId: preparePayResp.transactionId, txState: { + major: TransactionMajorState.Failed, + minor: TransactionMinorState.Repurchase, + }, + }); + + const repurchaseTx = await walletClient.call( + WalletApiOperation.GetTransactionById, + { + transactionId: preparePayResp.transactionId, + }, + ); + + t.assertTrue(repurchaseTx.type === TransactionType.Payment); + t.assertTrue(repurchaseTx.repurchaseTransactionId != null); + + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: repurchaseTx.repurchaseTransactionId, + txState: { major: TransactionMajorState.Done, }, }); diff --git a/packages/taler-harness/src/integrationtests/test-refund-auto.ts b/packages/taler-harness/src/integrationtests/test-refund-auto.ts @@ -92,12 +92,21 @@ export async function runRefundAutoTest(t: GlobalTestState) { // Make wallet pay for the order - const r1 = await walletClient.call(WalletApiOperation.PreparePayForUri, { + const r1 = await walletClient.call(WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: r1.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: r1.transactionId, + choiceIndex: 0, }); // Check if payment was successful. @@ -177,12 +186,21 @@ export async function runRefundAutoTest(t: GlobalTestState) { // Make wallet pay for the order - const r1 = await walletClient.call(WalletApiOperation.PreparePayForUri, { + const r1 = await walletClient.call(WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: r1.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: r1.transactionId, + choiceIndex: 0, }); // Check if payment was successful. diff --git a/packages/taler-harness/src/integrationtests/test-refund-gone.ts b/packages/taler-harness/src/integrationtests/test-refund-gone.ts @@ -23,6 +23,7 @@ import { succeedOrThrow, TalerMerchantInstanceHttpClient, TransactionMajorState, + TransactionMinorState, TransactionType, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; @@ -97,12 +98,21 @@ export async function runRefundGoneTest(t: GlobalTestState) { // Make wallet pay for the order - const r1 = await walletClient.call(WalletApiOperation.PreparePayForUri, { + const r1 = await walletClient.call(WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: r1.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + const r2 = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: r1.transactionId, + choiceIndex: 0, }); // Check if payment was successful. diff --git a/packages/taler-harness/src/integrationtests/test-refund-incremental.ts b/packages/taler-harness/src/integrationtests/test-refund-incremental.ts @@ -22,6 +22,8 @@ import { Duration, succeedOrThrow, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, TransactionType, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; @@ -86,12 +88,21 @@ export async function runRefundIncrementalTest(t: GlobalTestState) { // Make wallet pay for the order - const r1 = await walletClient.call(WalletApiOperation.PreparePayForUri, { + const r1 = await walletClient.call(WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: r1.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: r1.transactionId, + choiceIndex: 0, }); // Check if payment was successful. diff --git a/packages/taler-harness/src/integrationtests/test-refund.ts b/packages/taler-harness/src/integrationtests/test-refund.ts @@ -24,6 +24,7 @@ import { succeedOrThrow, TalerMerchantInstanceHttpClient, TransactionMajorState, + TransactionMinorState, TransactionType, WalletNotification, } from "@gnu-taler/taler-util"; @@ -91,12 +92,21 @@ export async function runRefundTest(t: GlobalTestState) { // Make wallet pay for the order - const r1 = await wallet.client.call(WalletApiOperation.PreparePayForUri, { + const r1 = await wallet.client.call(WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }); + await wallet.client.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: r1.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + await wallet.client.call(WalletApiOperation.ConfirmPay, { transactionId: r1.transactionId, + choiceIndex: 0, }); // Check if payment was successful. diff --git a/packages/taler-harness/src/integrationtests/test-repurchase-v1.ts b/packages/taler-harness/src/integrationtests/test-repurchase-v1.ts @@ -20,11 +20,11 @@ import { ConfirmPayResultType, j2s, - PreparePayResultType, succeedOrThrow, TalerCorebankApiClient, TalerMerchantInstanceHttpClient, TransactionMajorState, + TransactionMinorState, TransactionType, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; @@ -175,16 +175,20 @@ export async function runRepurchaseV1Test(t: GlobalTestState) { const longpollPromise = harnessHttpLib.fetch(orderLongpollUrl.href); const preparePayTwoResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderTwoStatus.taler_pay_uri, }, ); // Repurchase should be detected - t.assertTrue( - preparePayTwoResult.status === PreparePayResultType.AlreadyConfirmed, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayTwoResult.transactionId, + txState: { + major: TransactionMajorState.Failed, + minor: TransactionMinorState.Repurchase, + }, + }); t.logStep("start-wait-longpoll-promise"); await longpollPromise; @@ -251,16 +255,20 @@ export async function runRepurchaseV1Test(t: GlobalTestState) { t.assertTrue(orderThreeStatus.order_status === "unpaid"); const preparePayThreeResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderThreeStatus.taler_pay_uri, }, ); // Repurchase should be detected - t.assertTrue( - preparePayThreeResult.status === PreparePayResultType.AlreadyConfirmed, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayThreeResult.transactionId, + txState: { + major: TransactionMajorState.Failed, + minor: TransactionMinorState.Repurchase, + }, + }); await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {}); diff --git a/packages/taler-harness/src/integrationtests/test-repurchase.ts b/packages/taler-harness/src/integrationtests/test-repurchase.ts @@ -20,10 +20,11 @@ import { ConfirmPayResultType, j2s, - PreparePayResultType, succeedOrThrow, TalerCorebankApiClient, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, TransactionType, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; @@ -79,20 +80,25 @@ export async function runRepurchaseTest(t: GlobalTestState) { t.assertTrue(orderOneStatus.order_status === "unpaid"); const preparePayOneResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderOneStatus.taler_pay_uri, }, ); - t.assertTrue( - preparePayOneResult.status === PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayOneResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); const confirmPayResp = await walletClient.call( WalletApiOperation.ConfirmPay, { transactionId: preparePayOneResult.transactionId, + choiceIndex: 0, }, ); @@ -133,16 +139,20 @@ export async function runRepurchaseTest(t: GlobalTestState) { const longpollPromise = harnessHttpLib.fetch(orderLongpollUrl.href); const preparePayTwoResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderTwoStatus.taler_pay_uri, }, ); // Repurchase should be detected - t.assertTrue( - preparePayTwoResult.status === PreparePayResultType.AlreadyConfirmed, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayTwoResult.transactionId, + txState: { + major: TransactionMajorState.Failed, + minor: TransactionMinorState.Repurchase, + }, + }); t.logStep("start-wait-longpoll-promise"); await longpollPromise; @@ -174,16 +184,20 @@ export async function runRepurchaseTest(t: GlobalTestState) { t.assertTrue(orderThreeStatus.order_status === "unpaid"); const preparePayThreeResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderThreeStatus.taler_pay_uri, }, ); // Repurchase should be detected - t.assertTrue( - preparePayThreeResult.status === PreparePayResultType.AlreadyConfirmed, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayThreeResult.transactionId, + txState: { + major: TransactionMajorState.Failed, + minor: TransactionMinorState.Repurchase, + }, + }); await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {}); diff --git a/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts b/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts @@ -21,10 +21,10 @@ import { Duration, ExchangeUpdateStatus, NotificationType, - PreparePayResultType, TalerCorebankApiClient, TalerMerchantInstanceHttpClient, TransactionMajorState, + TransactionMinorState, j2s, succeedOrThrow, } from "@gnu-taler/taler-util"; @@ -270,16 +270,23 @@ export async function runTimetravelAutorefreshTest(t: GlobalTestState) { t.logStep("Preparing payment"); - const r = await walletClient.call(WalletApiOperation.PreparePayForUri, { + const r = await walletClient.call(WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }); console.log(r); - t.assertTrue(r.status === PreparePayResultType.PaymentPossible); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: r.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: r.transactionId, + choiceIndex: 0, }); await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { diff --git a/packages/taler-harness/src/integrationtests/test-wallet-balance.ts b/packages/taler-harness/src/integrationtests/test-wallet-balance.ts @@ -21,13 +21,15 @@ import { AccessToken, Amounts, BasicAuth, + ChoiceSelectionDetailType, Duration, j2s, - PreparePayResultType, succeedOrThrow, TalerCorebankApiClient, TalerMerchantApi, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; @@ -257,32 +259,43 @@ export async function runWalletBalanceTest(t: GlobalTestState) { // Make wallet pay for the order const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - console.log(j2s(preparePayResult)); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); - t.assertTrue( - preparePayResult.status === PreparePayResultType.InsufficientBalance, + const choicesResult = await walletClient.call( + WalletApiOperation.GetChoicesForPayment, + { + transactionId: preparePayResult.transactionId, + }, ); + console.log(j2s(choicesResult)); + + const choice = choicesResult.choices[0]; + t.assertDeepEqual( - preparePayResult.status, - PreparePayResultType.InsufficientBalance, + choice.status, + ChoiceSelectionDetailType.InsufficientBalance, ); - t.assertTrue( - Amounts.isNonZero( - preparePayResult.balanceDetails.balanceReceiverAcceptable, - ), - ); + const balanceDetails = choice.balanceDetails; - t.assertTrue( - Amounts.isZero(preparePayResult.balanceDetails.balanceReceiverDepositable), - ); + t.assertTrue(balanceDetails != null); + + t.assertTrue(Amounts.isNonZero(balanceDetails.balanceReceiverAcceptable)); + + t.assertTrue(Amounts.isZero(balanceDetails.balanceReceiverDepositable)); console.log("waiting for transactions to finalize"); diff --git a/packages/taler-harness/src/integrationtests/test-wallet-insufficient-balance.ts b/packages/taler-harness/src/integrationtests/test-wallet-insufficient-balance.ts @@ -20,13 +20,15 @@ import { AmountString, BasicAuth, + ChoiceSelectionDetailType, j2s, Logger, PaymentInsufficientBalanceDetails, - PreparePayResultType, succeedOrThrow, TalerErrorCode, TalerMerchantInstanceHttpClient, + TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js"; @@ -225,21 +227,44 @@ export async function runWalletInsufficientBalanceTest(t: GlobalTestState) { // Make wallet pay for the order - const res = await walletClient.call(WalletApiOperation.PreparePayForUri, { + const res = await walletClient.call(WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }); - t.assertDeepEqual(res.status, PreparePayResultType.InsufficientBalance); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: res.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); - const insufficientBalanceDetails: PaymentInsufficientBalanceDetails = - res.balanceDetails; + const choicesResult = await walletClient.call( + WalletApiOperation.GetChoicesForPayment, + { + transactionId: res.transactionId, + }, + ); + + const choice = choicesResult.choices[0]; + + t.assertDeepEqual( + choice.status, + ChoiceSelectionDetailType.InsufficientBalance, + ); + + const insufficientBalanceDetails: + | PaymentInsufficientBalanceDetails + | undefined = choice.balanceDetails; + + t.assertTrue(insufficientBalanceDetails != null); const perMyExchange = insufficientBalanceDetails.perExchange[exchange.baseUrl]; t.assertTrue(!!perMyExchange); - console.log(j2s(res)); + console.log(j2s(choicesResult)); t.assertAmountEquals( insufficientBalanceDetails.balanceAvailable, diff --git a/packages/taler-harness/src/integrationtests/test-wallet-tokens-discount.ts b/packages/taler-harness/src/integrationtests/test-wallet-tokens-discount.ts @@ -25,12 +25,13 @@ import { Order, OrderInputType, OrderOutputType, - PreparePayResultType, succeedOrThrow, TalerMerchantInstanceHttpClient, TalerProtocolTimestamp, TokenFamilyDetails, TokenFamilyKind, + TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; @@ -259,15 +260,19 @@ async function createAndPayOrder(req: { const talerPayUri = orderStatus.taler_pay_uri; const preparePayResult = await req.walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, ); - req.t.assertTrue( - preparePayResult.status === PreparePayResultType.ChoiceSelection, - ); + await req.walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); await req.walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, diff --git a/packages/taler-harness/src/integrationtests/test-wallet-tokens.ts b/packages/taler-harness/src/integrationtests/test-wallet-tokens.ts @@ -25,13 +25,13 @@ import { Order, OrderInputType, OrderOutputType, - PreparePayResultType, succeedOrThrow, TalerMerchantInstanceHttpClient, TalerProtocolTimestamp, TokenAvailabilityHint, TokenFamilyKind, TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; @@ -241,15 +241,19 @@ export async function runWalletTokensTest(t: GlobalTestState) { const orderId = orderResp.order_id; const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.ChoiceSelection, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, @@ -286,15 +290,19 @@ export async function runWalletTokensTest(t: GlobalTestState) { const orderId = orderResp.order_id; const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.ChoiceSelection, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); { const choicesRes = await walletClient.call( @@ -360,15 +368,19 @@ export async function runWalletTokensTest(t: GlobalTestState) { const orderId = orderResp.order_id; const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.ChoiceSelection, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); { const choicesRes = await walletClient.call( @@ -442,15 +454,19 @@ export async function runWalletTokensTest(t: GlobalTestState) { const orderId = orderResp.order_id; const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.ChoiceSelection, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); { const choicesRes = await walletClient.call( @@ -508,15 +524,19 @@ export async function runWalletTokensTest(t: GlobalTestState) { const orderId = orderResp.order_id; const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.ChoiceSelection, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, @@ -553,15 +573,19 @@ export async function runWalletTokensTest(t: GlobalTestState) { const orderId = orderResp.order_id; const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.ChoiceSelection, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); { const choicesRes = await walletClient.call( diff --git a/packages/taler-harness/src/integrationtests/test-wallet-wirefees.ts b/packages/taler-harness/src/integrationtests/test-wallet-wirefees.ts @@ -19,13 +19,14 @@ */ import { BasicAuth, + ChoiceSelectionDetailType, Duration, - PreparePayResultType, succeedOrThrow, TalerCorebankApiClient, TalerMerchantApi, TalerMerchantInstanceHttpClient, TransactionMajorState, + TransactionMinorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js"; @@ -193,22 +194,38 @@ export async function runWalletWirefeesTest(t: GlobalTestState) { // Make wallet pay for the order const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.PaymentPossible, + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + + const choicesResult = await walletClient.call( + WalletApiOperation.GetChoicesForPayment, + { + transactionId: preparePayResult.transactionId, + }, ); - console.log(`amountEffective: ${preparePayResult.amountEffective}`); + const choice = choicesResult.choices[0]; + + t.assertTrue(choice.status === ChoiceSelectionDetailType.PaymentPossible); + + console.log(`amountEffective: ${choice.amountEffective}`); - t.assertAmountEquals(preparePayResult.amountEffective, "TESTKUDOS:6.12"); + t.assertAmountEquals(choice.amountEffective, "TESTKUDOS:6.12"); await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, + choiceIndex: 0, }); await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {}); diff --git a/packages/taler-harness/src/integrationtests/test-wire-metadata.ts b/packages/taler-harness/src/integrationtests/test-wire-metadata.ts @@ -23,12 +23,13 @@ import { j2s, LoginTokenScope, MerchantAuthMethod, - PreparePayResultType, succeedOrThrow, TalerCoreBankHttpClient, TalerMerchantInstanceHttpClient, TalerMerchantManagementHttpClient, TalerProtocolTimestamp, + TransactionMajorState, + TransactionMinorState, UserAndToken, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; @@ -223,18 +224,23 @@ export async function runWireMetadataTest(t: GlobalTestState) { t.assertTrue(orderStatus.order_status === "unpaid"); const preparePayResult = await walletClient.call( - WalletApiOperation.PreparePayForUri, + WalletApiOperation.PreparePayForUriV2, { talerPayUri: orderStatus.taler_pay_uri, }, ); - t.assertTrue( - preparePayResult.status === PreparePayResultType.PaymentPossible, - ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePayResult.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); const r2 = await walletClient.call(WalletApiOperation.ConfirmPay, { transactionId: preparePayResult.transactionId, + choiceIndex: 0, }); t.assertDeepEqual(r2.type, ConfirmPayResultType.Done);