From b5312973a6f25ac73c8e29b659bf7ea23d77ac5e Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 18 Mar 2024 12:12:57 -0300 Subject: wip --- packages/taler-util/src/http-client/merchant.ts | 679 ++++++++++++++++++++++++ 1 file changed, 679 insertions(+) create mode 100644 packages/taler-util/src/http-client/merchant.ts (limited to 'packages/taler-util/src/http-client/merchant.ts') diff --git a/packages/taler-util/src/http-client/merchant.ts b/packages/taler-util/src/http-client/merchant.ts new file mode 100644 index 000000000..32384f8b4 --- /dev/null +++ b/packages/taler-util/src/http-client/merchant.ts @@ -0,0 +1,679 @@ +/* + This file is part of GNU Taler + (C) 2022-2024 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 + */ + +import { + HttpStatusCode, + LibtoolVersion, + MerchantApiClient, + TalerMerchantApi, + codecForMerchantConfig +} from "@gnu-taler/taler-util"; +import { + HttpRequestLibrary, + createPlatformHttpLib, +} from "@gnu-taler/taler-util/http"; +import { + FailCasesByMethod, + ResultByMethod, + opSuccessFromHttp, + opUnknownFailure, +} from "../operation.js"; +import { CacheEvictor, nullEvictor } from "./utils.js"; + +export enum TalerMerchantCacheEviction { + CREATE_ORDER, +} +/** + * Protocol version spoken with the core bank. + * + * Endpoint must be ordered in the same way that in the docs + * Response code (http and taler) must have the same order that in the docs + * That way is easier to see changes + * + * Uses libtool's current:revision:age versioning. + */ +class TalerMerchantInstanceHttpClient { + + readonly httpLib: HttpRequestLibrary; + readonly cacheEvictor: CacheEvictor; + + constructor( + readonly baseUrl: string, + httpClient?: HttpRequestLibrary, + cacheEvictor?: CacheEvictor, + ) { + this.httpLib = httpClient ?? createPlatformHttpLib(); + this.cacheEvictor = cacheEvictor ?? nullEvictor; + } + + // + // Wallet API + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-orders-$ORDER_ID-claim + */ + async claimOrder(orderId: string, body: TalerMerchantApi.ClaimRequest) { + const url = new URL(`orders/${orderId}/claim`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + // switch (resp.status) { + // case HttpStatusCode.Ok: + // return opSuccessFromHttp(resp, codecForClaimResponse()); + // case HttpStatusCode.Conflict: + // return opKnownHttpFailure(resp.status, resp) + // case HttpStatusCode.NotFound: + // return opKnownHttpFailure(resp.status, resp) + // default: + // return opUnknownFailure(resp, await resp.text()); + // } + } + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-orders-$ORDER_ID-pay + */ + async makePayment(orderId: string, body: TalerMerchantApi.PayRequest) { + const url = new URL(`orders/${orderId}/pay`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + + /// + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-orders-$ORDER_ID + */ + + async getPaymentStatus(orderId: string, params: TalerMerchantApi.PaymentStatusRequestParams = {}) { + const url = new URL(`orders/${orderId}`, this.baseUrl); + + if (params.allowRefundedForRepurchase !== undefined) { + url.searchParams.set("allow_refunded_for_repurchase", params.allowRefundedForRepurchase ? "YES" : "NO") + } + if (params.awaitRefundObtained !== undefined) { + url.searchParams.set("await_refund_obtained", params.allowRefundedForRepurchase ? "YES" : "NO") + } + if (params.claimToken !== undefined) { + url.searchParams.set("token", params.claimToken) + } + if (params.contractTermHash !== undefined) { + url.searchParams.set("h_contract", params.contractTermHash) + } + if (params.refund !== undefined) { + url.searchParams.set("refund", params.refund) + } + if (params.sessionId !== undefined) { + url.searchParams.set("session_id", params.sessionId) + } + if (params.timeout !== undefined) { + url.searchParams.set("timeout_ms", String(params.timeout)) + } + + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + // body, + }); + + /// + } + + /** + * https://docs.taler.net/core/api-merchant.html#demonstrating-payment + */ + async demostratePayment(orderId: string, body: TalerMerchantApi.PaidRequest) { + const url = new URL(`orders/${orderId}/paid`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#aborting-incomplete-payments + */ + async abortIncompletePayment(orderId: string, body: TalerMerchantApi.AbortRequest) { + const url = new URL(`orders/${orderId}/abort`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#obtaining-refunds + */ + async obtainRefund(orderId: string, body: TalerMerchantApi.WalletRefundRequest) { + const url = new URL(`orders/${orderId}/refund`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + } + + // + // Management + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-auth + */ + async updateCurrentInstanceAuthentication(body: TalerMerchantApi.InstanceAuthConfigurationMessage) { + const url = new URL(`private/auth`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + + // + } + + /** + * Get the auth api agaisnt the current instance + * + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-token + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-token + */ + getAuthenticationAPI(): URL { + return new URL(`/`, this.baseUrl); + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private + */ + async updateCurrentInstance(body: TalerMerchantApi.InstanceReconfigurationMessage) { + const url = new URL(`private`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "PATCH", + body, + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private + * + */ + async getCurrentInstance() { + const url = new URL(`private`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private + */ + async deleteCurrentInstance(params: { purge?: boolean }) { + const url = new URL(`private`, this.baseUrl); + + if (params.purge) { + url.searchParams.set("purge", "YES") + } + + const resp = await this.httpLib.fetch(url.href, { + method: "DELETE", + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#get--instances-$INSTANCE-private-kyc + */ + async getCurrentIntanceKycStatus(params: { wireHash?: string, exchangeURL?: string, timeout: number }) { + const url = new URL(`private/kyc`, this.baseUrl); + + if (params.wireHash) { + url.searchParams.set("h_wire", params.wireHash) + } + if (params.exchangeURL) { + url.searchParams.set("exchange_url", params.exchangeURL) + } + if (params.timeout) { + url.searchParams.set("timeout_ms", String(params.timeout)) + } + + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + }); + + } + + // + // Bank Accounts + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-accounts + */ + async addAccount(body: TalerMerchantApi.AccountAddDetails) { + const url = new URL(`private/accounts`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private-accounts-$H_WIRE + */ + async updateAccount(wireAccount: string, body: TalerMerchantApi.AccountPatchDetails) { + const url = new URL(`private/accounts/${wireAccount}`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "PATCH", + body, + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-accounts + */ + async listAccounts() { + const url = new URL(`private/accounts`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-accounts-$H_WIRE + */ + async getAccount(wireAccount: string) { + const url = new URL(`private/accounts/${wireAccount}`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-accounts-$H_WIRE + */ + async deleteAccount(wireAccount: string) { + const url = new URL(`private/accounts/${wireAccount}`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "DELETE", + }); + } + + // + // Inventory Management + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-products + */ + async addProduct() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private-products-$PRODUCT_ID + */ + async updateProduct() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-products + */ + async listProducts() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-products-$PRODUCT_ID + */ + async getProduct() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#reserving-inventory + */ + async lockProduct() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#removing-products-from-inventory + */ + async removeProduct() { + } + + // + // Payment processing + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-orders + */ + async createOrder() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#inspecting-orders + */ + async listOrders() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-orders-$ORDER_ID + */ + async getOrder() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#private-order-data-cleanup + */ + async forgetOrder() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-orders-$ORDER_ID + */ + async deleteOrder() { + } + + // + // Refunds + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-orders-$ORDER_ID-refund + */ + async addRefund() { + } + + // + // Wire Transfer + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-transfers + */ + async informWireTransfer() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-transfers + */ + async listWireTransfers() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-transfers-$TID + */ + async deleteWireTransfer() { + } + + // + // OTP Devices + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-otp-devices + */ + async addOtpDevice() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private-otp-devices-$DEVICE_ID + */ + async updateOtpDevice() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-otp-devices + */ + async listOtpDevices() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-otp-devices-$DEVICE_ID + */ + async getOtpDevice() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-otp-devices-$DEVICE_ID + */ + async deleteOtpDevice() { + } + + // + // Templates + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-templates + */ + async addTemplate() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private-templates-$TEMPLATE_ID + */ + async updateTemplate() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#inspecting-template + */ + async listTemplates() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-templates-$TEMPLATE_ID + */ + async getTemplate() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-templates-$TEMPLATE_ID + */ + async deleteTemplate() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCES]-templates-$TEMPLATE_ID + */ + async useTemplate() { + } + + // + // Webhooks + // + + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCES]-private-webhooks + */ + async addWebhook() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCES]-private-webhooks-$WEBHOOK_ID + */ + async updateWebhook() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-webhooks + */ + async listWebhooks() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-webhooks-$WEBHOOK_ID + */ + async getWebhook() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCES]-private-webhooks-$WEBHOOK_ID + */ + async removeWebhook() { + } + + // + // token families + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCES]-private-tokenfamilies + */ + async createTokenFamily() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCES]-private-tokenfamilies-$TOKEN_FAMILY_SLUG + */ + async updateTokenFamily() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-tokenfamilies + */ + async listTokenFamilies() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-tokenfamilies-$TOKEN_FAMILY_SLUG + */ + async getTokenFamily() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCES]-private-tokenfamilies-$TOKEN_FAMILY_SLUG + */ + async deleteTokenFamily() { + } + +} + +export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttpClient { + public readonly PROTOCOL_VERSION = "10:0:6"; + + httpLib: HttpRequestLibrary; + cacheEvictor: CacheEvictor; + constructor( + readonly baseUrl: string, + httpClient?: HttpRequestLibrary, + cacheEvictor?: CacheEvictor, + ) { + super(baseUrl, httpClient, cacheEvictor) + } + + isCompatible(version: string): boolean { + const compare = LibtoolVersion.compare(this.PROTOCOL_VERSION, version); + return compare?.compatible ?? false; + } + + /** + * https://docs.taler.net/core/api-merchant.html#get--config + * + */ + async getConfig() { + const url = new URL(`config`, this.baseUrl); + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + }); + switch (resp.status) { + case HttpStatusCode.Ok: + return opSuccessFromHttp(resp, codecForMerchantConfig()); + default: + return opUnknownFailure(resp, await resp.text()); + } + } + + + // + // Instance Management + // + + /** + * https://docs.taler.net/core/api-merchant.html#post--management-instances + */ + async createInstance(body: TalerMerchantApi.InstanceConfigurationMessage) { + const url = new URL(`management/instances`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + + // + } + + /** + * https://docs.taler.net/core/api-merchant.html#post--management-instances-$INSTANCE-auth + */ + async updateInstanceAuthentication(body: TalerMerchantApi.InstanceAuthConfigurationMessage) { + const url = new URL(`management/instances`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + + // + } + + + /** + * https://docs.taler.net/core/api-merchant.html#patch--management-instances-$INSTANCE + */ + async updateInstance() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get--management-instances + */ + async listInstances() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get--management-instances-$INSTANCE + * + */ + async getInstance() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete--management-instances-$INSTANCE + */ + async deleteInstance() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get--management-instances-$INSTANCE-kyc + */ + async getIntanceKycStatus() { + } + + + + +} -- cgit v1.2.3