aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-harness
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-harness')
-rw-r--r--packages/taler-harness/src/harness/harness.ts6
-rw-r--r--packages/taler-harness/src/harness/helpers.ts19
-rw-r--r--packages/taler-harness/src/integrationtests/test-kyc.ts199
3 files changed, 196 insertions, 28 deletions
diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts
index 3659ea538..275592091 100644
--- a/packages/taler-harness/src/harness/harness.ts
+++ b/packages/taler-harness/src/harness/harness.ts
@@ -2028,9 +2028,9 @@ export class WalletClient {
return getClientFromRemoteWallet(this.remoteWallet);
}
- waitForNotificationCond(
- cond: (n: WalletNotification) => boolean,
- ): Promise<void> {
+ waitForNotificationCond<T>(
+ cond: (n: WalletNotification) => T | undefined | false,
+ ): Promise<T> {
return this.waiter.waitForNotificationCond(cond);
}
}
diff --git a/packages/taler-harness/src/harness/helpers.ts b/packages/taler-harness/src/harness/helpers.ts
index 59a37e4b8..4c2ca80a7 100644
--- a/packages/taler-harness/src/harness/helpers.ts
+++ b/packages/taler-harness/src/harness/helpers.ts
@@ -53,9 +53,14 @@ import {
MerchantServiceInterface,
setupDb,
WalletCli,
+ WalletClient,
+ WalletService,
WithAuthorization,
} from "./harness.js";
+/**
+ * @deprecated
+ */
export interface SimpleTestEnvironment {
commonDb: DbInfo;
bank: BankService;
@@ -65,6 +70,20 @@ export interface SimpleTestEnvironment {
wallet: WalletCli;
}
+/**
+ * Improved version of the simple test environment,
+ * with the daemonized wallet.
+ */
+export interface SimpleTestEnvironmentNg {
+ commonDb: DbInfo;
+ bank: BankService;
+ exchange: ExchangeService;
+ exchangeBankAccount: HarnessExchangeBankAccount;
+ merchant: MerchantService;
+ walletClient: WalletClient;
+ walletService: WalletService;
+}
+
export interface EnvOptions {
/**
* If provided, enable age restrictions with the specified age mask string.
diff --git a/packages/taler-harness/src/integrationtests/test-kyc.ts b/packages/taler-harness/src/integrationtests/test-kyc.ts
index c652c86fa..b08db66f7 100644
--- a/packages/taler-harness/src/integrationtests/test-kyc.ts
+++ b/packages/taler-harness/src/integrationtests/test-kyc.ts
@@ -17,7 +17,13 @@
/**
* Imports.
*/
-import { Duration } from "@gnu-taler/taler-util";
+import { Duration, j2s, NotificationType } from "@gnu-taler/taler-util";
+import {
+ BankAccessApi,
+ BankApi,
+ NodeHttpLib,
+ WalletApiOperation,
+} from "@gnu-taler/taler-wallet-core";
import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
import {
BankService,
@@ -26,20 +32,17 @@ import {
GlobalTestState,
MerchantService,
setupDb,
- WalletCli,
+ WalletClient,
+ WalletService,
} from "../harness/harness.js";
-import {
- withdrawViaBank,
- makeTestPayment,
- EnvOptions,
- SimpleTestEnvironment,
-} from "../harness/helpers.js";
+import { EnvOptions, SimpleTestEnvironmentNg } from "../harness/helpers.js";
+import * as http from "node:http";
export async function createKycTestkudosEnvironment(
t: GlobalTestState,
coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS")),
opts: EnvOptions = {},
-): Promise<SimpleTestEnvironment> {
+): Promise<SimpleTestEnvironmentNg> {
const db = await setupDb(t);
const bank = await BankService.create(t, {
@@ -117,11 +120,11 @@ export async function createKycTestkudosEnvironment(
config.setString(
myprov,
"kyc_oauth2_info_url",
- "http://localhost:6666/oauth/v2/login",
+ "http://localhost:6666/oauth/v2/info",
);
config.setString(myprov, "kyc_oauth2_client_id", "taler-exchange");
config.setString(myprov, "kyc_oauth2_client_secret", "exchange-secret");
- config.setString(myprov, "kyc_oauth2_post_url", "https://taler.com");
+ config.setString(myprov, "kyc_oauth2_post_url", "https://taler.net");
config.setString(
"kyc-legitimization-withdraw1",
@@ -167,40 +170,186 @@ export async function createKycTestkudosEnvironment(
),
});
- console.log("setup done!");
+ const walletService = new WalletService(t, {
+ name: "wallet",
+ useInMemoryDb: true,
+ });
+ await walletService.start();
+ await walletService.pingUntilAvailable();
- const wallet = new WalletCli(t);
+ const walletClient = new WalletClient({
+ unixPath: walletService.socketPath,
+ onNotification(n) {
+ console.log("got notification", n);
+ },
+ });
+ await walletClient.connect();
+ await walletClient.client.call(WalletApiOperation.InitWallet, {
+ skipDefaults: true,
+ });
+
+ console.log("setup done!");
return {
commonDb: db,
exchange,
merchant,
- wallet,
+ walletClient,
+ walletService,
bank,
exchangeBankAccount,
};
}
+interface TestfakeKycService {
+ stop: () => void;
+}
+
+function splitInTwoAt(s: string, separator: string): [string, string] {
+ const idx = s.indexOf(separator);
+ if (idx === -1) {
+ return [s, ""];
+ }
+ return [s.slice(0, idx), s.slice(idx + 1)];
+}
+
+/**
+ * Testfake for the kyc service that the exchange talks to.
+ */
+async function runTestfakeKycService(): Promise<TestfakeKycService> {
+ const server = http.createServer((req, res) => {
+ const requestUrl = req.url!;
+ console.log(`kyc: got ${req.method} request`, requestUrl);
+
+ const [path, query] = splitInTwoAt(requestUrl, "?");
+
+ const qp = new URLSearchParams(query);
+
+ if (path === "/oauth/v2/login") {
+ // Usually this would render some HTML page for the user to log in,
+ // but we return JSON here.
+ const redirUri = new URL(qp.get("redirect_uri")!);
+ redirUri.searchParams.set("code", "code_is_ok");
+ res.writeHead(200, { "Content-Type": "application/json" });
+ res.end(
+ JSON.stringify({
+ redirect_uri: redirUri.href,
+ }),
+ );
+ } else if (path === "/oauth/v2/token") {
+ let reqBody = "";
+ req.on("data", (x) => {
+ reqBody += x;
+ });
+
+ req.on("end", () => {
+ console.log("login request body:", reqBody);
+
+ res.writeHead(200, { "Content-Type": "application/json" });
+ // Normally, the access_token would also include which user we're trying
+ // to get info about, but we (for now) skip it in this test.
+ res.end(
+ JSON.stringify({
+ access_token: "exchange_access_token",
+ token_type: "Bearer",
+ }),
+ );
+ });
+ } else if (path === "/oauth/v2/info") {
+ console.log("authorization header:", req.headers.authorization);
+ res.writeHead(200, { "Content-Type": "application/json" });
+ res.end(
+ JSON.stringify({
+ status: "success",
+ data: {
+ id: "foobar",
+ },
+ }),
+ );
+ } else {
+ res.writeHead(400, { "Content-Type": "application/json" });
+ res.end(JSON.stringify({ code: 1, message: "bad request" }));
+ }
+ });
+ await new Promise<void>((resolve, reject) => {
+ server.listen(6666, () => resolve());
+ });
+ return {
+ stop() {
+ server.close();
+ },
+ };
+}
+
export async function runKycTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
+ const { walletClient, bank, exchange, merchant } =
await createKycTestkudosEnvironment(t);
+ const kycServer = await runTestfakeKycService();
+
// Withdraw digital cash into the wallet.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ const amount = "TESTKUDOS:20";
+ const user = await BankApi.createRandomBankUser(bank);
+ const wop = await BankAccessApi.createWithdrawalOperation(bank, user, amount);
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
+ // Hand it to the wallet
+
+ await walletClient.client.call(
+ WalletApiOperation.GetWithdrawalDetailsForUri,
+ {
+ talerWithdrawUri: wop.taler_withdraw_uri,
+ },
+ );
+
+ // Withdraw
+
+ const kycNotificationCond = walletClient.waitForNotificationCond((x) => {
+ if (x.type === NotificationType.WithdrawalKycRequested) {
+ return x;
+ }
+ return false;
+ });
+
+ const withdrawalDoneCond = walletClient.waitForNotificationCond(
+ (x) => x.type === NotificationType.WithdrawGroupFinished,
+ );
+
+ await walletClient.client.call(
+ WalletApiOperation.AcceptBankIntegratedWithdrawal,
+ {
+ exchangeBaseUrl: exchange.baseUrl,
+ talerWithdrawUri: wop.taler_withdraw_uri,
+ },
+ );
+
+ // Confirm it
+
+ await BankApi.confirmWithdrawalOperation(bank, user, wop);
+
+ const kycNotif = await kycNotificationCond;
+
+ console.log("got kyc notification:", j2s(kycNotif));
+
+ // We now simulate the user interacting with the KYC service,
+ // which would usually done in the browser.
+
+ const httpClient = new NodeHttpLib();
+ const kycServerResp = await httpClient.get(kycNotif.kycUrl);
+ const kycLoginResp = await kycServerResp.json();
+ console.log("kyc server resp:", j2s(kycLoginResp));
+ const kycProofUrl = kycLoginResp.redirect_uri;
+ const proofHttpResp = await httpClient.get(kycProofUrl);
+ console.log("proof resp status", proofHttpResp.status);
+ console.log("resp headers", proofHttpResp.headers.toJSON());
+
+ // Now that KYC is done, withdrawal should finally succeed.
+
+ await withdrawalDoneCond;
- await makeTestPayment(t, { wallet, merchant, order });
- await wallet.runUntilDone();
+ kycServer.stop();
}
runKycTest.suites = ["wallet"];
-// See bugs.taler.net/n/7599
-runKycTest.experimental = true;