summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations/testing.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/operations/testing.ts')
-rw-r--r--packages/taler-wallet-core/src/operations/testing.ts435
1 files changed, 0 insertions, 435 deletions
diff --git a/packages/taler-wallet-core/src/operations/testing.ts b/packages/taler-wallet-core/src/operations/testing.ts
deleted file mode 100644
index d2071cd53..000000000
--- a/packages/taler-wallet-core/src/operations/testing.ts
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- 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 { Logger } from "@gnu-taler/taler-util";
-import {
- HttpRequestLibrary,
- readSuccessResponseJsonOrThrow,
- checkSuccessResponseOrThrow,
-} from "../util/http.js";
-import {
- AmountString,
- codecForAny,
- CheckPaymentResponse,
- codecForCheckPaymentResponse,
- IntegrationTestArgs,
- Amounts,
- TestPayArgs,
- URL,
- PreparePayResultType,
-} from "@gnu-taler/taler-util";
-import { createTalerWithdrawReserve } from "./reserves.js";
-import { InternalWalletState } from "../common.js";
-import { confirmPay, preparePayForUri } from "./pay.js";
-import { getBalances } from "./balance.js";
-import { applyRefund } from "./refund.js";
-
-const logger = new Logger("operations/testing.ts");
-
-interface BankUser {
- username: string;
- password: string;
-}
-
-interface BankWithdrawalResponse {
- taler_withdraw_uri: string;
- withdrawal_id: string;
-}
-
-interface MerchantBackendInfo {
- baseUrl: string;
- authToken?: string;
-}
-
-/**
- * Generate a random alphanumeric ID. Does *not* use cryptographically
- * secure randomness.
- */
-function makeId(length: number): string {
- let result = "";
- const characters =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
- for (let i = 0; i < length; i++) {
- result += characters.charAt(Math.floor(Math.random() * characters.length));
- }
- return result;
-}
-
-/**
- * Helper function to generate the "Authorization" HTTP header.
- */
-function makeAuth(username: string, password: string): string {
- const auth = `${username}:${password}`;
- const authEncoded: string = Buffer.from(auth).toString("base64");
- return `Basic ${authEncoded}`;
-}
-
-export async function withdrawTestBalance(
- ws: InternalWalletState,
- amount = "TESTKUDOS:10",
- bankBaseUrl = "https://bank.test.taler.net/",
- exchangeBaseUrl = "https://exchange.test.taler.net/",
-): Promise<void> {
- const bankUser = await registerRandomBankUser(ws.http, bankBaseUrl);
- logger.trace(`Registered bank user ${JSON.stringify(bankUser)}`);
-
- const wresp = await createBankWithdrawalUri(
- ws.http,
- bankBaseUrl,
- bankUser,
- amount,
- );
-
- await createTalerWithdrawReserve(
- ws,
- wresp.taler_withdraw_uri,
- exchangeBaseUrl,
- );
-
- await confirmBankWithdrawalUri(
- ws.http,
- bankBaseUrl,
- bankUser,
- wresp.withdrawal_id,
- );
-}
-
-function getMerchantAuthHeader(m: MerchantBackendInfo): Record<string, string> {
- if (m.authToken) {
- return {
- Authorization: `Bearer ${m.authToken}`,
- };
- }
- return {};
-}
-
-async function createBankWithdrawalUri(
- http: HttpRequestLibrary,
- bankBaseUrl: string,
- bankUser: BankUser,
- amount: AmountString,
-): Promise<BankWithdrawalResponse> {
- const reqUrl = new URL(
- `accounts/${bankUser.username}/withdrawals`,
- bankBaseUrl,
- ).href;
- const resp = await http.postJson(
- reqUrl,
- {
- amount,
- },
- {
- headers: {
- Authorization: makeAuth(bankUser.username, bankUser.password),
- },
- },
- );
- const respJson = await readSuccessResponseJsonOrThrow(resp, codecForAny());
- return respJson;
-}
-
-async function confirmBankWithdrawalUri(
- http: HttpRequestLibrary,
- bankBaseUrl: string,
- bankUser: BankUser,
- withdrawalId: string,
-): Promise<void> {
- const reqUrl = new URL(
- `accounts/${bankUser.username}/withdrawals/${withdrawalId}/confirm`,
- bankBaseUrl,
- ).href;
- const resp = await http.postJson(
- reqUrl,
- {},
- {
- headers: {
- Authorization: makeAuth(bankUser.username, bankUser.password),
- },
- },
- );
- await readSuccessResponseJsonOrThrow(resp, codecForAny());
- return;
-}
-
-async function registerRandomBankUser(
- http: HttpRequestLibrary,
- bankBaseUrl: string,
-): Promise<BankUser> {
- const reqUrl = new URL("testing/register", bankBaseUrl).href;
- const randId = makeId(8);
- const bankUser: BankUser = {
- username: `testuser-${randId}`,
- password: `testpw-${randId}`,
- };
-
- const resp = await http.postJson(reqUrl, bankUser);
- await checkSuccessResponseOrThrow(resp);
- return bankUser;
-}
-
-async function refund(
- http: HttpRequestLibrary,
- merchantBackend: MerchantBackendInfo,
- orderId: string,
- reason: string,
- refundAmount: string,
-): Promise<string> {
- const reqUrl = new URL(
- `private/orders/${orderId}/refund`,
- merchantBackend.baseUrl,
- );
- const refundReq = {
- order_id: orderId,
- reason,
- refund: refundAmount,
- };
- const resp = await http.postJson(reqUrl.href, refundReq, {
- headers: getMerchantAuthHeader(merchantBackend),
- });
- const r = await readSuccessResponseJsonOrThrow(resp, codecForAny());
- const refundUri = r.taler_refund_uri;
- if (!refundUri) {
- throw Error("no refund URI in response");
- }
- return refundUri;
-}
-
-async function createOrder(
- http: HttpRequestLibrary,
- merchantBackend: MerchantBackendInfo,
- amount: string,
- summary: string,
- fulfillmentUrl: string,
-): Promise<{ orderId: string }> {
- const t = Math.floor(new Date().getTime() / 1000) + 15 * 60;
- const reqUrl = new URL("private/orders", merchantBackend.baseUrl).href;
- const orderReq = {
- order: {
- amount,
- summary,
- fulfillment_url: fulfillmentUrl,
- refund_deadline: { t_ms: t * 1000 },
- wire_transfer_deadline: { t_ms: t * 1000 },
- },
- };
- const resp = await http.postJson(reqUrl, orderReq, {
- headers: getMerchantAuthHeader(merchantBackend),
- });
- const r = await readSuccessResponseJsonOrThrow(resp, codecForAny());
- const orderId = r.order_id;
- if (!orderId) {
- throw Error("no order id in response");
- }
- return { orderId };
-}
-
-async function checkPayment(
- http: HttpRequestLibrary,
- merchantBackend: MerchantBackendInfo,
- orderId: string,
-): Promise<CheckPaymentResponse> {
- const reqUrl = new URL(`private/orders/${orderId}`, merchantBackend.baseUrl);
- reqUrl.searchParams.set("order_id", orderId);
- const resp = await http.get(reqUrl.href, {
- headers: getMerchantAuthHeader(merchantBackend),
- });
- return readSuccessResponseJsonOrThrow(resp, codecForCheckPaymentResponse());
-}
-
-interface BankUser {
- username: string;
- password: string;
-}
-
-interface BankWithdrawalResponse {
- taler_withdraw_uri: string;
- withdrawal_id: string;
-}
-
-async function makePayment(
- ws: InternalWalletState,
- merchant: MerchantBackendInfo,
- amount: string,
- summary: string,
-): Promise<{ orderId: string }> {
- const orderResp = await createOrder(
- ws.http,
- merchant,
- amount,
- summary,
- "taler://fulfillment-success/thx",
- );
-
- logger.trace("created order with orderId", orderResp.orderId);
-
- let paymentStatus = await checkPayment(ws.http, merchant, orderResp.orderId);
-
- logger.trace("payment status", paymentStatus);
-
- const talerPayUri = paymentStatus.taler_pay_uri;
- if (!talerPayUri) {
- throw Error("no taler://pay/ URI in payment response");
- }
-
- const preparePayResult = await preparePayForUri(ws, talerPayUri);
-
- logger.trace("prepare pay result", preparePayResult);
-
- if (preparePayResult.status != "payment-possible") {
- throw Error("payment not possible");
- }
-
- const confirmPayResult = await confirmPay(
- ws,
- preparePayResult.proposalId,
- undefined,
- );
-
- logger.trace("confirmPayResult", confirmPayResult);
-
- paymentStatus = await checkPayment(ws.http, merchant, orderResp.orderId);
-
- logger.trace("payment status after wallet payment:", paymentStatus);
-
- if (paymentStatus.order_status !== "paid") {
- throw Error("payment did not succeed");
- }
-
- return {
- orderId: orderResp.orderId,
- };
-}
-
-export async function runIntegrationTest(
- ws: InternalWalletState,
- args: IntegrationTestArgs,
-): Promise<void> {
- logger.info("running test with arguments", args);
-
- const parsedSpendAmount = Amounts.parseOrThrow(args.amountToSpend);
- const currency = parsedSpendAmount.currency;
-
- logger.info("withdrawing test balance");
- await withdrawTestBalance(
- ws,
- args.amountToWithdraw,
- args.bankBaseUrl,
- args.exchangeBaseUrl,
- );
- await ws.runUntilDone();
- logger.info("done withdrawing test balance");
-
- const balance = await getBalances(ws);
-
- logger.trace(JSON.stringify(balance, null, 2));
-
- const myMerchant: MerchantBackendInfo = {
- baseUrl: args.merchantBaseUrl,
- authToken: args.merchantAuthToken,
- };
-
- await makePayment(ws, myMerchant, args.amountToSpend, "hello world");
-
- // Wait until the refresh is done
- await ws.runUntilDone();
-
- logger.trace("withdrawing test balance for refund");
- const withdrawAmountTwo = Amounts.parseOrThrow(`${currency}:18`);
- const spendAmountTwo = Amounts.parseOrThrow(`${currency}:7`);
- const refundAmount = Amounts.parseOrThrow(`${currency}:6`);
- const spendAmountThree = Amounts.parseOrThrow(`${currency}:3`);
-
- await withdrawTestBalance(
- ws,
- Amounts.stringify(withdrawAmountTwo),
- args.bankBaseUrl,
- args.exchangeBaseUrl,
- );
-
- // Wait until the withdraw is done
- await ws.runUntilDone();
-
- const { orderId: refundOrderId } = await makePayment(
- ws,
- myMerchant,
- Amounts.stringify(spendAmountTwo),
- "order that will be refunded",
- );
-
- const refundUri = await refund(
- ws.http,
- myMerchant,
- refundOrderId,
- "test refund",
- Amounts.stringify(refundAmount),
- );
-
- logger.trace("refund URI", refundUri);
-
- await applyRefund(ws, refundUri);
-
- logger.trace("integration test: applied refund");
-
- // Wait until the refund is done
- await ws.runUntilDone();
-
- logger.trace("integration test: making payment after refund");
-
- await makePayment(
- ws,
- myMerchant,
- Amounts.stringify(spendAmountThree),
- "payment after refund",
- );
-
- logger.trace("integration test: make payment done");
-
- await ws.runUntilDone();
-
- logger.trace("integration test: all done!");
-}
-
-export async function testPay(ws: InternalWalletState, args: TestPayArgs) {
- logger.trace("creating order");
- const merchant = {
- authToken: args.merchantAuthToken,
- baseUrl: args.merchantBaseUrl,
- };
- const orderResp = await createOrder(
- ws.http,
- merchant,
- args.amount,
- args.summary,
- "taler://fulfillment-success/thank+you",
- );
- logger.trace("created new order with order ID", orderResp.orderId);
- const checkPayResp = await checkPayment(ws.http, merchant, orderResp.orderId);
- const talerPayUri = checkPayResp.taler_pay_uri;
- if (!talerPayUri) {
- console.error("fatal: no taler pay URI received from backend");
- process.exit(1);
- return;
- }
- logger.trace("taler pay URI:", talerPayUri);
- const result = await preparePayForUri(ws, talerPayUri);
- if (result.status !== PreparePayResultType.PaymentPossible) {
- throw Error(`unexpected prepare pay status: ${result.status}`);
- }
- await confirmPay(ws, result.proposalId, undefined);
-}