taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 5bdfa4e17b22ae6addecda805e57e6790289e307
parent 57892a485b04987f05854615cceb15054646c654
Author: Florian Dold <dold@taler.net>
Date:   Sat, 29 Aug 2026 17:19:19 +0200

taler-harness: cover merchant session status endpoint

Diffstat:
Apackages/taler-harness/src/integrationtests/test-merchant-sessions.ts | 134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpackages/taler-harness/src/integrationtests/testrunner.ts | 2++
2 files changed, 136 insertions(+), 0 deletions(-)

diff --git a/packages/taler-harness/src/integrationtests/test-merchant-sessions.ts b/packages/taler-harness/src/integrationtests/test-merchant-sessions.ts @@ -0,0 +1,134 @@ +/* + This file is part of GNU Taler + (C) 2026 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. +*/ + +import { + ConfirmPayResultType, + HttpStatusCode, + succeedOrThrow, + TalerMerchantInstanceHttpClient, + TemplateType, + TransactionMajorState, + TransactionMinorState, +} from "@gnu-taler/taler-util"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; +import { + createSimpleTestkudosEnvironmentV3, + withdrawViaBankV3, +} from "../harness/environments.js"; +import { GlobalTestState, harnessHttpLib } from "../harness/harness.js"; + +/** + * Verify the public session-status endpoint used by Paivana, including its + * unknown-to-paid long-poll transition. + */ +export async function runMerchantSessionsTest(t: GlobalTestState) { + const { + bankClient, + walletClient, + exchange, + merchant, + merchantAdminAccessToken, + } = await createSimpleTestkudosEnvironmentV3(t); + + const withdrawal = await withdrawViaBankV3(t, { + walletClient, + bankClient, + exchange, + amount: "TESTKUDOS:10", + }); + await withdrawal.withdrawalFinishedCond; + + const merchantClient = new TalerMerchantInstanceHttpClient( + merchant.makeInstanceBaseUrl(), + ); + const sessionId = + "4321-6hvIP7UnmNDVjp5Intuf9jFK7MzW0ycEyxf5Mszl3xs="; + const fulfillmentUrl = "https://example.com/protected-article"; + + const missingFulfillmentUrl = new URL( + `sessions/${sessionId}`, + merchant.makeInstanceBaseUrl(), + ); + const missingFulfillmentResp = await harnessHttpLib.fetch( + missingFulfillmentUrl.href, + ); + t.assertDeepEqual(missingFulfillmentResp.status, HttpStatusCode.BadRequest); + + const unknownSession = await merchantClient.getOrderIdForSessionAndUrl( + sessionId, + fulfillmentUrl, + ); + t.assertTrue(unknownSession.type === "fail"); + t.assertDeepEqual(unknownSession.response.status, HttpStatusCode.NotFound); + + succeedOrThrow( + await merchantClient.addTemplate(merchantAdminAccessToken, { + template_id: "paivana-access", + template_description: "Paivana access", + template_contract: { + template_type: TemplateType.PAIVANA, + summary: "Paivana access", + website_regex: "https://example.com/.*", + choices: [{ amount: "TESTKUDOS:5" }], + }, + }), + ); + + // Paivana starts polling before the wallet instantiates the template, so + // the endpoint must also wake when the session is initially unknown. + const paidSessionPromise = merchantClient.getOrderIdForSessionAndUrl( + sessionId, + fulfillmentUrl, + { timeout: 10_000 }, + ); + const talerPayTemplateUri = + `taler+http://pay-template/localhost:${merchant.port}/paivana-access` + + `?session_id=${encodeURIComponent(sessionId)}` + + `&fulfillment_url=${encodeURIComponent(fulfillmentUrl)}`; + + const preparePay = await walletClient.call( + WalletApiOperation.PreparePayForTemplateV2, + { talerPayTemplateUri }, + ); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: preparePay.transactionId, + txState: { + major: TransactionMajorState.Dialog, + minor: TransactionMinorState.Proposed, + }, + }); + + const choices = await walletClient.call( + WalletApiOperation.GetChoicesForPayment, + { transactionId: preparePay.transactionId }, + ); + + const wrongFulfillment = await merchantClient.getOrderIdForSessionAndUrl( + sessionId, + "https://example.com/different-article", + ); + t.assertTrue(wrongFulfillment.type === "fail"); + t.assertDeepEqual(wrongFulfillment.response.status, HttpStatusCode.NotFound); + + const confirmPay = await walletClient.call(WalletApiOperation.ConfirmPay, { + transactionId: preparePay.transactionId, + choiceIndex: 0, + }); + t.assertTrue(confirmPay.type === ConfirmPayResultType.Done); + + const paidSession = succeedOrThrow(await paidSessionPromise); + t.assertDeepEqual(paidSession.paid, true); + t.assertDeepEqual(paidSession.order_id, choices.contractTerms.order_id); +} + +runMerchantSessionsTest.suites = ["merchant"]; diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts @@ -130,6 +130,7 @@ import { runMerchantPaytoReuseTest } from "./test-merchant-payto-reuse.js"; import { runMerchantRefundApiTest } from "./test-merchant-refund-api.js"; import { runMerchantRefundFeesTest } from "./test-merchant-refund-fees.js"; import { runMerchantReportsTest } from "./test-merchant-reports.js"; +import { runMerchantSessionsTest } from "./test-merchant-sessions.js"; import { runMerchantSelfProvisionActivationTest } from "./test-merchant-self-provision-activation.js"; import { runMerchantSelfProvisionInactiveAccountPermissionsTest } from "./test-merchant-self-provision-inactive-account-permissions.js"; import { runMerchantSpecPublicOrdersTest } from "./test-merchant-spec-public-orders.js"; @@ -332,6 +333,7 @@ const allTests: TestMainFunction[] = [ runMerchantInstanceCasingTest, runMerchantInstancesTest, runMerchantLongpollingTest, + runMerchantSessionsTest, runMerchantRefundApiTest, runMerchantSpecPublicOrdersTest, runPaymentClaimTest,