diff options
Diffstat (limited to 'packages/taler-integrationtests/src')
-rw-r--r-- | packages/taler-integrationtests/src/harness.ts | 67 | ||||
-rw-r--r-- | packages/taler-integrationtests/src/merchantApiTypes.ts | 60 | ||||
-rw-r--r-- | packages/taler-integrationtests/src/test-tipping.ts | 106 |
3 files changed, 229 insertions, 4 deletions
diff --git a/packages/taler-integrationtests/src/harness.ts b/packages/taler-integrationtests/src/harness.ts index 620b89e76..e40798b4b 100644 --- a/packages/taler-integrationtests/src/harness.ts +++ b/packages/taler-integrationtests/src/harness.ts @@ -72,6 +72,10 @@ import { CoinDumpJson, ForceExchangeUpdateRequest, ForceRefreshRequest, + PrepareTipResult, + PrepareTipRequest, + codecForPrepareTipResult, + AcceptTipRequest, } from "taler-wallet-core"; import { URL } from "url"; import axios, { AxiosError } from "axios"; @@ -81,6 +85,9 @@ import { PostOrderRequest, PostOrderResponse, MerchantOrderPrivateStatusResponse, + TippingReserveStatus, + TipCreateConfirmation, + TipCreateRequest, } from "./merchantApiTypes"; import { ApplyRefundResponse } from "taler-wallet-core"; import { PendingOperationsResponse } from "taler-wallet-core"; @@ -1216,10 +1223,46 @@ export namespace MerchantPrivateApi { }; } - export async function createTippingReserve(merchantService: MerchantServiceInterface, - + export async function createTippingReserve( + merchantService: MerchantServiceInterface, + instance: string, req: CreateMerchantTippingReserveRequest, - ): Promise<CreateMerchantTippingReserveConfirmation> {} + ): Promise<CreateMerchantTippingReserveConfirmation> { + const reqUrl = new URL( + `private/reserves`, + merchantService.makeInstanceBaseUrl(instance), + ); + const resp = await axios.post(reqUrl.href, req); + // FIXME: validate + return resp.data; + } + + export async function queryTippingReserves( + merchantService: MerchantServiceInterface, + instance: string, + ): Promise<TippingReserveStatus> { + const reqUrl = new URL( + `private/reserves`, + merchantService.makeInstanceBaseUrl(instance), + ); + const resp = await axios.get(reqUrl.href); + // FIXME: validate + return resp.data; + } + + export async function giveTip( + merchantService: MerchantServiceInterface, + instance: string, + req: TipCreateRequest, + ): Promise<TipCreateConfirmation> { + const reqUrl = new URL( + `private/tips`, + merchantService.makeInstanceBaseUrl(instance), + ); + const resp = await axios.post(reqUrl.href, req); + // FIXME: validate + return resp.data; + } } export interface CreateMerchantTippingReserveRequest { @@ -1238,7 +1281,7 @@ export interface CreateMerchantTippingReserveConfirmation { reserve_pub: string; // Wire account of the exchange where to transfer the funds - payto_url: string; + payto_uri: string; } export class MerchantService implements MerchantServiceInterface { @@ -1594,6 +1637,22 @@ export class WalletCli { throw new OperationFailedError(resp.error); } + async prepareTip(req: PrepareTipRequest): Promise<PrepareTipResult> { + const resp = await this.apiRequest("prepareTip", req); + if (resp.type === "response") { + return codecForPrepareTipResult().decode(resp.result); + } + throw new OperationFailedError(resp.error); + } + + async acceptTip(req: AcceptTipRequest): Promise<void> { + const resp = await this.apiRequest("acceptTip", req); + if (resp.type === "response") { + return; + } + throw new OperationFailedError(resp.error); + } + async dumpCoins(): Promise<CoinDumpJson> { const resp = await this.apiRequest("dumpCoins", {}); if (resp.type === "response") { diff --git a/packages/taler-integrationtests/src/merchantApiTypes.ts b/packages/taler-integrationtests/src/merchantApiTypes.ts index 550c5e90c..e89e32642 100644 --- a/packages/taler-integrationtests/src/merchantApiTypes.ts +++ b/packages/taler-integrationtests/src/merchantApiTypes.ts @@ -223,3 +223,63 @@ export interface TransactionWireReport { // Public key of the coin for which we got the exchange error. coin_pub: CoinPublicKeyString; } + +export interface TippingReserveStatus { + // Array of all known reserves (possibly empty!) + reserves: ReserveStatusEntry[]; +} + +export interface ReserveStatusEntry { + // Public key of the reserve + reserve_pub: string; + + // Timestamp when it was established + creation_time: Timestamp; + + // Timestamp when it expires + expiration_time: Timestamp; + + // Initial amount as per reserve creation call + merchant_initial_amount: AmountString; + + // Initial amount as per exchange, 0 if exchange did + // not confirm reserve creation yet. + exchange_initial_amount: AmountString; + + // Amount picked up so far. + pickup_amount: AmountString; + + // Amount approved for tips that exceeds the pickup_amount. + committed_amount: AmountString; + + // Is this reserve active (false if it was deleted but not purged) + active: boolean; +} + + +export interface TipCreateConfirmation { + // Unique tip identifier for the tip that was created. + tip_id: string; + + // taler://tip URI for the tip + taler_tip_uri: string; + + // URL that will directly trigger processing + // the tip when the browser is redirected to it + tip_status_url: string; + + // when does the tip expire + tip_expiration: Timestamp; +} + +export interface TipCreateRequest { + // Amount that the customer should be tipped + amount: AmountString; + + // Justification for giving the tip + justification: string; + + // URL that the user should be directed to after tipping, + // will be included in the tip_token. + next_url: string; +}
\ No newline at end of file diff --git a/packages/taler-integrationtests/src/test-tipping.ts b/packages/taler-integrationtests/src/test-tipping.ts new file mode 100644 index 000000000..ddf56c0e0 --- /dev/null +++ b/packages/taler-integrationtests/src/test-tipping.ts @@ -0,0 +1,106 @@ +/* + 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 { + runTest, + GlobalTestState, + MerchantPrivateApi, + BankAccessApi, + BankApi, +} from "./harness"; +import { createSimpleTestkudosEnvironment, withdrawViaBank } from "./helpers"; + +/** + * Run test for basic, bank-integrated withdrawal. + */ +runTest(async (t: GlobalTestState) => { + // Set up test environment + + const { + wallet, + bank, + exchange, + merchant, + exchangeBankAccount, + } = await createSimpleTestkudosEnvironment(t); + + const mbu = await BankApi.createRandomBankUser(bank); + + const tipReserveResp = await MerchantPrivateApi.createTippingReserve( + merchant, + "default", + { + exchange_url: exchange.baseUrl, + initial_balance: "TESTKUDOS:10", + wire_method: "x-taler-bank", + }, + ); + + console.log("tipReserveResp:", tipReserveResp); + + t.assertDeepEqual( + tipReserveResp.payto_uri, + exchangeBankAccount.accountPaytoUri, + ); + + await BankApi.adminAddIncoming(bank, { + amount: "TESTKUDOS:10", + debitAccountPayto: mbu.accountPaytoUri, + exchangeBankAccount, + reservePub: tipReserveResp.reserve_pub, + }); + + await exchange.runWirewatchOnce(); + await merchant.stop(); + await merchant.start(); + await merchant.pingUntilAvailable(); + + const r = await MerchantPrivateApi.queryTippingReserves(merchant, "default"); + console.log("tipping reserves:", JSON.stringify(r, undefined, 2)); + + t.assertTrue(r.reserves.length === 1); + t.assertDeepEqual( + r.reserves[0].exchange_initial_amount, + r.reserves[0].merchant_initial_amount, + ); + + const tip = await MerchantPrivateApi.giveTip(merchant, "default", { + amount: "TESTKUDOS:5", + justification: "why not?", + next_url: "https://example.com/after-tip", + }); + + console.log("created tip", tip); + + const ptr = await wallet.prepareTip({ + talerTipUri: tip.taler_tip_uri, + }); + + console.log(ptr); + + await wallet.acceptTip({ + walletTipId: ptr.walletTipId, + }); + + await wallet.runUntilDone(); + + const bal = await wallet.getBalances(); + + console.log(bal); +}); |