diff options
Diffstat (limited to 'packages/taler-harness/src/integrationtests/test-merchant-refund-api.ts')
-rw-r--r-- | packages/taler-harness/src/integrationtests/test-merchant-refund-api.ts | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/packages/taler-harness/src/integrationtests/test-merchant-refund-api.ts b/packages/taler-harness/src/integrationtests/test-merchant-refund-api.ts new file mode 100644 index 000000000..7ee4c977b --- /dev/null +++ b/packages/taler-harness/src/integrationtests/test-merchant-refund-api.ts @@ -0,0 +1,307 @@ +/* + This file is part of GNU Taler + (C) 2020 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. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** + * Imports. + */ +import { + Duration, + MerchantApiClient, + PreparePayResultType, + URL, +} from "@gnu-taler/taler-util"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; +import { + BankServiceHandle, + ExchangeServiceInterface, + GlobalTestState, + MerchantServiceInterface, + WalletClient, + harnessHttpLib, +} from "../harness/harness.js"; +import { + createSimpleTestkudosEnvironmentV2, + withdrawViaBankV2, +} from "../harness/helpers.js"; + +async function testRefundApiWithFulfillmentUrl( + t: GlobalTestState, + env: { + merchant: MerchantServiceInterface; + bank: BankServiceHandle; + walletClient: WalletClient; + exchange: ExchangeServiceInterface; + }, +): Promise<void> { + const { walletClient, merchant } = env; + + const merchantClient = new MerchantApiClient(merchant.makeInstanceBaseUrl()); + + // Set up order. + const orderResp = await merchantClient.createOrder({ + order: { + summary: "Buy me!", + amount: "TESTKUDOS:5", + fulfillment_url: "https://example.com/fulfillment", + }, + refund_delay: Duration.toTalerProtocolDuration( + Duration.fromSpec({ minutes: 5 }), + ), + }); + + let orderStatus = await merchantClient.queryPrivateOrderStatus({ + orderId: orderResp.order_id, + }); + + t.assertTrue(orderStatus.order_status === "unpaid"); + + const talerPayUri = orderStatus.taler_pay_uri; + const orderId = orderResp.order_id; + + // Make wallet pay for the order + + let preparePayResult = await walletClient.call( + WalletApiOperation.PreparePayForUri, + { + talerPayUri, + }, + ); + + t.assertTrue( + preparePayResult.status === PreparePayResultType.PaymentPossible, + ); + + await walletClient.call(WalletApiOperation.ConfirmPay, { + proposalId: preparePayResult.proposalId, + }); + + // Check if payment was successful. + + orderStatus = await merchantClient.queryPrivateOrderStatus({ + orderId: orderResp.order_id, + }); + + t.assertTrue(orderStatus.order_status === "paid"); + + preparePayResult = await walletClient.call( + WalletApiOperation.PreparePayForUri, + { + talerPayUri, + }, + ); + + t.assertTrue( + preparePayResult.status === PreparePayResultType.AlreadyConfirmed, + ); + + await merchantClient.giveRefund({ + amount: "TESTKUDOS:5", + instance: "default", + justification: "foo", + orderId: orderResp.order_id, + }); + + orderStatus = await merchantClient.queryPrivateOrderStatus({ + orderId: orderResp.order_id, + }); + + t.assertTrue(orderStatus.order_status === "paid"); + + t.assertAmountEquals(orderStatus.refund_amount, "TESTKUDOS:5"); + + // Now test what the merchant gives as a response for various requests to the + // public order status URL! + + let publicOrderStatusUrl = new URL( + `orders/${orderId}`, + merchant.makeInstanceBaseUrl(), + ); + publicOrderStatusUrl.searchParams.set( + "h_contract", + preparePayResult.contractTermsHash, + ); + + let publicOrderStatusResp = await harnessHttpLib.fetch( + publicOrderStatusUrl.href, + ); + const respData = await publicOrderStatusResp.json(); + t.assertTrue(publicOrderStatusResp.status === 200); + t.assertAmountEquals(respData.refund_amount, "TESTKUDOS:5"); + + publicOrderStatusUrl = new URL( + `orders/${orderId}`, + merchant.makeInstanceBaseUrl(), + ); + console.log(`requesting order status via '${publicOrderStatusUrl.href}'`); + publicOrderStatusResp = await harnessHttpLib.fetch(publicOrderStatusUrl.href); + console.log(publicOrderStatusResp.status); + console.log(await publicOrderStatusResp.json()); + // We didn't give any authentication, so we should get a fulfillment URL back + t.assertTrue(publicOrderStatusResp.status === 403); +} + +async function testRefundApiWithFulfillmentMessage( + t: GlobalTestState, + env: { + merchant: MerchantServiceInterface; + bank: BankServiceHandle; + walletClient: WalletClient; + exchange: ExchangeServiceInterface; + }, +): Promise<void> { + const { walletClient, merchant } = env; + + const merchantClient = new MerchantApiClient(merchant.makeInstanceBaseUrl()); + + // Set up order. + const orderResp = await merchantClient.createOrder({ + order: { + summary: "Buy me!", + amount: "TESTKUDOS:5", + fulfillment_message: "Thank you for buying foobar", + }, + refund_delay: Duration.toTalerProtocolDuration( + Duration.fromSpec({ minutes: 5 }), + ), + }); + + let orderStatus = await merchantClient.queryPrivateOrderStatus({ + orderId: orderResp.order_id, + }); + + t.assertTrue(orderStatus.order_status === "unpaid"); + + const talerPayUri = orderStatus.taler_pay_uri; + const orderId = orderResp.order_id; + + // Make wallet pay for the order + + let preparePayResult = await walletClient.call( + WalletApiOperation.PreparePayForUri, + { + talerPayUri, + }, + ); + + t.assertTrue( + preparePayResult.status === PreparePayResultType.PaymentPossible, + ); + + await walletClient.call(WalletApiOperation.ConfirmPay, { + proposalId: preparePayResult.proposalId, + }); + + // Check if payment was successful. + + orderStatus = await merchantClient.queryPrivateOrderStatus({ + orderId: orderResp.order_id, + }); + + t.assertTrue(orderStatus.order_status === "paid"); + + preparePayResult = await walletClient.call( + WalletApiOperation.PreparePayForUri, + { + talerPayUri, + }, + ); + + t.assertTrue( + preparePayResult.status === PreparePayResultType.AlreadyConfirmed, + ); + + await merchantClient.giveRefund({ + amount: "TESTKUDOS:5", + instance: "default", + justification: "foo", + orderId: orderResp.order_id, + }); + + orderStatus = await merchantClient.queryPrivateOrderStatus({ + orderId: orderResp.order_id, + }); + + t.assertTrue(orderStatus.order_status === "paid"); + + t.assertAmountEquals(orderStatus.refund_amount, "TESTKUDOS:5"); + + // Now test what the merchant gives as a response for various requests to the + // public order status URL! + + let publicOrderStatusUrl = new URL( + `orders/${orderId}`, + merchant.makeInstanceBaseUrl(), + ); + publicOrderStatusUrl.searchParams.set( + "h_contract", + preparePayResult.contractTermsHash, + ); + + let publicOrderStatusResp = await harnessHttpLib.fetch( + publicOrderStatusUrl.href, + ); + let respData = await publicOrderStatusResp.json(); + console.log(respData); + t.assertTrue(publicOrderStatusResp.status === 200); + t.assertAmountEquals(respData.refund_amount, "TESTKUDOS:5"); + + publicOrderStatusUrl = new URL( + `orders/${orderId}`, + merchant.makeInstanceBaseUrl(), + ); + + publicOrderStatusResp = await harnessHttpLib.fetch(publicOrderStatusUrl.href); + respData = await publicOrderStatusResp.json(); + console.log(respData); + // We didn't give any authentication, so we should get a fulfillment URL back + t.assertTrue(publicOrderStatusResp.status === 403); +} + +/** + * Test case for the refund API of the merchant backend. + */ +export async function runMerchantRefundApiTest(t: GlobalTestState) { + // Set up test environment + + const { walletClient, bank, exchange, merchant } = + await createSimpleTestkudosEnvironmentV2(t); + + // Withdraw digital cash into the wallet. + + const wres = await withdrawViaBankV2(t, { + walletClient, + bank, + exchange, + amount: "TESTKUDOS:20", + }); + await wres.withdrawalFinishedCond; + + await testRefundApiWithFulfillmentUrl(t, { + walletClient, + bank, + exchange, + merchant, + }); + + await testRefundApiWithFulfillmentMessage(t, { + walletClient, + bank, + exchange, + merchant, + }); +} + +runMerchantRefundApiTest.suites = ["merchant"]; |