From a9540de313506200105f8c75ac219ffeb7622d78 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 22 Mar 2024 09:16:23 -0300 Subject: revert c09caa5fd which removed minimum_age from contract terms --- packages/taler-util/src/MerchantApiClient.ts | 2 +- packages/taler-util/src/http-client/README.md | 31 ++--- packages/taler-util/src/http-client/merchant.ts | 80 +++++++------ packages/taler-util/src/http-client/types.ts | 153 ++++++++++++------------ packages/taler-util/src/http-client/utils.ts | 6 +- packages/taler-util/src/merchant-api-types.ts | 1 - packages/taler-util/src/observability.ts | 2 +- packages/taler-util/src/taler-types.ts | 12 +- packages/taler-util/src/wallet-types.ts | 13 +- packages/taler-wallet-core/src/pay-merchant.ts | 9 +- 10 files changed, 158 insertions(+), 151 deletions(-) (limited to 'packages') diff --git a/packages/taler-util/src/MerchantApiClient.ts b/packages/taler-util/src/MerchantApiClient.ts index 65827849d..fa9a00176 100644 --- a/packages/taler-util/src/MerchantApiClient.ts +++ b/packages/taler-util/src/MerchantApiClient.ts @@ -34,7 +34,7 @@ import { MerchantPostOrderRequest, MerchantPostOrderResponse, MerchantTemplateAddDetails, - codecForMerchantPostOrderResponse + codecForMerchantPostOrderResponse, } from "./merchant-api-types.js"; import { FailCasesByMethod, diff --git a/packages/taler-util/src/http-client/README.md b/packages/taler-util/src/http-client/README.md index 5af5d48a7..33d1a8645 100644 --- a/packages/taler-util/src/http-client/README.md +++ b/packages/taler-util/src/http-client/README.md @@ -1,24 +1,19 @@ -HTTP Cclients -------------- +## HTTP Cclients This folder contain class or function specifically designed to facilitate HTTP client -interactions with a the core systems. +interactions with a the core systems. These API defines: -1. **API Communication**: Handle communication with the component API, -abstracting away the details of HTTP requests and responses. -This includes making GET, POST, PUT, and DELETE requests to the servers. - -2. **Data Formatting**: Responsible for formatting requests to the API in a -way that's expected by the servers (JSON) and parsing the responses back -into formats usable by the client. - -3. **Authentication and Security**: Handling authentication with the server API, -which could involve sending API keys, client credentials, or managing tokens. -It might also implement security features to ensure data integrity and confidentiality during transit. - -4. **Error Handling**: Providing robust error handling and retry mechanisms -for failed HTTP requests, including logging and potentially user notifications for critical failures. - +1. **API Communication**: Handle communication with the component API, + abstracting away the details of HTTP requests and responses. + This includes making GET, POST, PUT, and DELETE requests to the servers. +2. **Data Formatting**: Responsible for formatting requests to the API in a + way that's expected by the servers (JSON) and parsing the responses back + into formats usable by the client. +3. **Authentication and Security**: Handling authentication with the server API, + which could involve sending API keys, client credentials, or managing tokens. + It might also implement security features to ensure data integrity and confidentiality during transit. +4. **Error Handling**: Providing robust error handling and retry mechanisms + for failed HTTP requests, including logging and potentially user notifications for critical failures. 5. **Data Validation**: Before sending requests, it could validate the data to ensure it meets the API's expected format, types, and value ranges, reducing the likelihood of errors and improving system reliability. diff --git a/packages/taler-util/src/http-client/merchant.ts b/packages/taler-util/src/http-client/merchant.ts index 1cc410191..0fe9973bb 100644 --- a/packages/taler-util/src/http-client/merchant.ts +++ b/packages/taler-util/src/http-client/merchant.ts @@ -53,7 +53,7 @@ import { codecForWebhookSummaryResponse, opEmptySuccess, opKnownAlternativeFailure, - opKnownHttpFailure + opKnownHttpFailure, } from "@gnu-taler/taler-util"; import { HttpRequestLibrary, @@ -61,7 +61,11 @@ import { createPlatformHttpLib, } from "@gnu-taler/taler-util/http"; import { opSuccessFromHttp, opUnknownFailure } from "../operation.js"; -import { CacheEvictor, addMerchantPaginationParams, nullEvictor } from "./utils.js"; +import { + CacheEvictor, + addMerchantPaginationParams, + nullEvictor, +} from "./utils.js"; export enum TalerMerchantCacheEviction { CREATE_ORDER, @@ -681,7 +685,7 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.NoContent: - return opEmptySuccess(resp) + return opEmptySuccess(resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Gone: @@ -703,7 +707,7 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.NoContent: - return opEmptySuccess(resp) + return opEmptySuccess(resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: @@ -727,19 +731,23 @@ export class TalerMerchantInstanceHttpClient { method: "POST", body, }); - return TalerMerchantInstanceHttpClient.procesOrderCreationResponse(resp) + return TalerMerchantInstanceHttpClient.procesOrderCreationResponse(resp); } private static async procesOrderCreationResponse(resp: HttpResponse) { switch (resp.status) { case HttpStatusCode.Ok: - return opSuccessFromHttp(resp, codecForPostOrderResponse()) + return opSuccessFromHttp(resp, codecForPostOrderResponse()); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Gone: - return opKnownAlternativeFailure(resp, resp.status, codecForOutOfStockResponse()); + return opKnownAlternativeFailure( + resp, + resp.status, + codecForOutOfStockResponse(), + ); default: return opUnknownFailure(resp, await resp.text()); } @@ -772,7 +780,7 @@ export class TalerMerchantInstanceHttpClient { if (params.wired) { url.searchParams.set("wired", "YES"); } - addMerchantPaginationParams(url, params) + addMerchantPaginationParams(url, params); const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -780,7 +788,7 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: - return opSuccessFromHttp(resp, codecForOrderHistory()) + return opSuccessFromHttp(resp, codecForOrderHistory()); default: return opUnknownFailure(resp, await resp.text()); } @@ -811,17 +819,23 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: - return opSuccessFromHttp(resp, codecForMerchantOrderPrivateStatusResponse()) + return opSuccessFromHttp( + resp, + codecForMerchantOrderPrivateStatusResponse(), + ); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.BadGateway: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.GatewayTimeout: - return opKnownAlternativeFailure(resp, resp.status, codecForOutOfStockResponse()); + return opKnownAlternativeFailure( + resp, + resp.status, + codecForOutOfStockResponse(), + ); default: return opUnknownFailure(resp, await resp.text()); } - } /** @@ -837,9 +851,9 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: - return opEmptySuccess(resp) + return opEmptySuccess(resp); case HttpStatusCode.NoContent: - return opEmptySuccess(resp) + return opEmptySuccess(resp); case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: @@ -863,7 +877,7 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.NoContent: - return opEmptySuccess(resp) + return opEmptySuccess(resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: @@ -890,7 +904,7 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: - return opSuccessFromHttp(resp, codecForMerchantRefundResponse()) + return opSuccessFromHttp(resp, codecForMerchantRefundResponse()); case HttpStatusCode.Forbidden: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: @@ -921,7 +935,7 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.NoContent: - return opEmptySuccess(resp) + return opEmptySuccess(resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: @@ -951,7 +965,7 @@ export class TalerMerchantInstanceHttpClient { if (params.verified) { url.searchParams.set("verified", "YES"); } - addMerchantPaginationParams(url, params) + addMerchantPaginationParams(url, params); const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -959,7 +973,7 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: - return opSuccessFromHttp(resp, codecForTansferList()) + return opSuccessFromHttp(resp, codecForTansferList()); default: return opUnknownFailure(resp, await resp.text()); } @@ -977,7 +991,7 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.NoContent: - return opEmptySuccess(resp) + return opEmptySuccess(resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: @@ -1004,7 +1018,7 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.NoContent: - return opEmptySuccess(resp) + return opEmptySuccess(resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: @@ -1027,7 +1041,7 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { case HttpStatusCode.NoContent: - return opEmptySuccess(resp) + return opEmptySuccess(resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: @@ -1048,7 +1062,7 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { case HttpStatusCode.Ok: - return opSuccessFromHttp(resp, codecForOtpDeviceSummaryResponse()) + return opSuccessFromHttp(resp, codecForOtpDeviceSummaryResponse()); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: @@ -1077,7 +1091,7 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: - return opSuccessFromHttp(resp, codecForOtpDeviceDetails()) + return opSuccessFromHttp(resp, codecForOtpDeviceDetails()); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: @@ -1243,7 +1257,7 @@ export class TalerMerchantInstanceHttpClient { body, }); - return TalerMerchantInstanceHttpClient.procesOrderCreationResponse(resp) + return TalerMerchantInstanceHttpClient.procesOrderCreationResponse(resp); } // @@ -1263,13 +1277,12 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.NoContent: - return opEmptySuccess(resp) + return opEmptySuccess(resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()); } - } /** @@ -1288,7 +1301,7 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.NoContent: - return opEmptySuccess(resp) + return opEmptySuccess(resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: @@ -1296,7 +1309,6 @@ export class TalerMerchantInstanceHttpClient { default: return opUnknownFailure(resp, await resp.text()); } - } /** @@ -1311,13 +1323,12 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.NoContent: - return opSuccessFromHttp(resp, codecForWebhookSummaryResponse()) + return opSuccessFromHttp(resp, codecForWebhookSummaryResponse()); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()); } - } /** @@ -1331,7 +1342,7 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { case HttpStatusCode.NoContent: - return opSuccessFromHttp(resp, codecForWebhookDetails()) + return opSuccessFromHttp(resp, codecForWebhookDetails()); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: @@ -1356,7 +1367,6 @@ export class TalerMerchantInstanceHttpClient { default: return opUnknownFailure(resp, await resp.text()); } - } // @@ -1563,7 +1573,7 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp switch (resp.status) { case HttpStatusCode.Ok: - return opSuccessFromHttp(resp, codecForInstancesResponse()) + return opSuccessFromHttp(resp, codecForInstancesResponse()); default: return opUnknownFailure(resp, await resp.text()); } @@ -1582,7 +1592,7 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp switch (resp.status) { case HttpStatusCode.Ok: - return opSuccessFromHttp(resp, codecForQueryInstancesResponse()) + return opSuccessFromHttp(resp, codecForQueryInstancesResponse()); default: return opUnknownFailure(resp, await resp.text()); } diff --git a/packages/taler-util/src/http-client/types.ts b/packages/taler-util/src/http-client/types.ts index 5fa3d0e7a..e3d25b888 100644 --- a/packages/taler-util/src/http-client/types.ts +++ b/packages/taler-util/src/http-client/types.ts @@ -572,11 +572,10 @@ export const codecForOutOfStockResponse = .property("restock_expected", codecForTimestamp) .build("TalerMerchantApi.OutOfStockResponse"); -export const codecForOrderHistory = - (): Codec => - buildCodecForObject() - .property("orders", codecForList(codecForOrderHistoryEntry())) - .build("TalerMerchantApi.OrderHistory"); +export const codecForOrderHistory = (): Codec => + buildCodecForObject() + .property("orders", codecForList(codecForOrderHistoryEntry())) + .build("TalerMerchantApi.OrderHistory"); export const codecForOrderHistoryEntry = (): Codec => @@ -590,7 +589,6 @@ export const codecForOrderHistoryEntry = .property("paid", codecForBoolean()) .build("TalerMerchantApi.OrderHistoryEntry"); - export const codecForMerchant = (): Codec => buildCodecForObject() .property("name", codecForString()) @@ -608,36 +606,40 @@ export const codecForExchange = (): Codec => .property("url", codecForString()) .build("TalerMerchantApi.Exchange"); -export const codecForContractTerms = (): Codec => - buildCodecForObject() - .property("order_id", codecForString()) - .property("fulfillment_url", codecOptional(codecForString())) - .property("fulfillment_message", codecOptional(codecForString())) - .property( - "fulfillment_message_i18n", - codecOptional(codecForInternationalizedString()), - ) - .property("merchant_base_url", codecForString()) - .property("h_wire", codecForString()) - .property("auto_refund", codecOptional(codecForDuration)) - .property("wire_method", codecForString()) - .property("summary", codecForString()) - .property("summary_i18n", codecOptional(codecForInternationalizedString())) - .property("nonce", codecForString()) - .property("amount", codecForAmountString()) - .property("pay_deadline", codecForTimestamp) - .property("refund_deadline", codecForTimestamp) - .property("wire_transfer_deadline", codecForTimestamp) - .property("timestamp", codecForTimestamp) - .property("delivery_location", codecOptional(codecForLocation())) - .property("delivery_date", codecOptional(codecForTimestamp)) - .property("max_fee", codecForAmountString()) - .property("merchant", codecForMerchant()) - .property("merchant_pub", codecForString()) - .property("exchanges", codecForList(codecForExchange())) - .property("products", codecForList(codecForProduct())) - .property("extra", codecForAny()) - .build("TalerMerchantApi.ContractTerms"); +export const codecForContractTerms = + (): Codec => + buildCodecForObject() + .property("order_id", codecForString()) + .property("fulfillment_url", codecOptional(codecForString())) + .property("fulfillment_message", codecOptional(codecForString())) + .property( + "fulfillment_message_i18n", + codecOptional(codecForInternationalizedString()), + ) + .property("merchant_base_url", codecForString()) + .property("h_wire", codecForString()) + .property("auto_refund", codecOptional(codecForDuration)) + .property("wire_method", codecForString()) + .property("summary", codecForString()) + .property( + "summary_i18n", + codecOptional(codecForInternationalizedString()), + ) + .property("nonce", codecForString()) + .property("amount", codecForAmountString()) + .property("pay_deadline", codecForTimestamp) + .property("refund_deadline", codecForTimestamp) + .property("wire_transfer_deadline", codecForTimestamp) + .property("timestamp", codecForTimestamp) + .property("delivery_location", codecOptional(codecForLocation())) + .property("delivery_date", codecOptional(codecForTimestamp)) + .property("max_fee", codecForAmountString()) + .property("merchant", codecForMerchant()) + .property("merchant_pub", codecForString()) + .property("exchanges", codecForList(codecForExchange())) + .property("products", codecForList(codecForProduct())) + .property("extra", codecForAny()) + .build("TalerMerchantApi.ContractTerms"); export const codecForProduct = (): Codec => buildCodecForObject() @@ -655,8 +657,6 @@ export const codecForProduct = (): Codec => .property("delivery_date", codecOptional(codecForTimestamp)) .build("TalerMerchantApi.Product"); - - export const codecForCheckPaymentPaidResponse = (): Codec => buildCodecForObject() @@ -704,8 +704,6 @@ export const codecForMerchantOrderPrivateStatusResponse = .alternative("claimed", codecForCheckPaymentClaimedResponse()) .build("TalerMerchantApi.MerchantOrderStatusResponse"); - - export const codecForRefundDetails = (): Codec => buildCodecForObject() @@ -742,11 +740,10 @@ export const codecForMerchantRefundResponse = .property("h_contract", codecForString()) .build("TalerMerchantApi.MerchantRefundResponse"); -export const codecForTansferList = - (): Codec => - buildCodecForObject() - .property("transfers", codecForList(codecForTransferDetails())) - .build("TalerMerchantApi.TransferList"); +export const codecForTansferList = (): Codec => + buildCodecForObject() + .property("transfers", codecForList(codecForTransferDetails())) + .build("TalerMerchantApi.TransferList"); export const codecForTransferDetails = (): Codec => @@ -784,7 +781,6 @@ export const codecForOtpDeviceDetails = .property("otp_code", codecOptional(codecForString())) .build("TalerMerchantApi.OtpDeviceDetails"); - export const codecForTemplateSummaryResponse = (): Codec => buildCodecForObject() @@ -822,19 +818,17 @@ export const codecForWalletTemplateDetails = .property("template_contract", codecForTemplateContractDetails()) .build("TalerMerchantApi.WalletTemplateDetails"); - export const codecForWebhookSummaryResponse = (): Codec => buildCodecForObject() .property("webhooks", codecForList(codecForWebhookEntry())) .build("TalerMerchantApi.WebhookSummaryResponse"); -export const codecForWebhookEntry = - (): Codec => - buildCodecForObject() - .property("webhook_id", codecForString()) - .property("event_type", codecForString()) - .build("TalerMerchantApi.WebhookEntry"); +export const codecForWebhookEntry = (): Codec => + buildCodecForObject() + .property("webhook_id", codecForString()) + .property("event_type", codecForString()) + .build("TalerMerchantApi.WebhookEntry"); export const codecForWebhookDetails = (): Codec => @@ -851,21 +845,20 @@ export const codecForTokenFamilyKind = codecForEither( codecForConstString("discount"), codecForConstString("subscription"), - ) as any //FIXME: create a codecForEnum - ; + ) as any; //FIXME: create a codecForEnum export const codecForTokenFamilyDetails = (): Codec => buildCodecForObject() .property("slug", codecForString()) .property("name", codecForString()) .property("description", codecForString()) - .property("description_i18n", (codecForInternationalizedString())) - .property("valid_after", (codecForTimestamp)) - .property("valid_before", (codecForTimestamp)) - .property("duration", (codecForDuration)) + .property("description_i18n", codecForInternationalizedString()) + .property("valid_after", codecForTimestamp) + .property("valid_before", codecForTimestamp) + .property("duration", codecForDuration) .property("kind", codecForTokenFamilyKind()) - .property("issued", (codecForNumber())) - .property("redeemed", (codecForNumber())) + .property("issued", codecForNumber()) + .property("redeemed", codecForNumber()) .build("TalerMerchantApi.TokenFamilyDetails"); export const codecForTokenFamiliesList = @@ -884,25 +877,23 @@ export const codecForTokenFamilySummary = .property("kind", codecForTokenFamilyKind()) .build("TalerMerchantApi.TokenFamilySummary"); - export const codecForInstancesResponse = (): Codec => buildCodecForObject() .property("instances", codecForList(codecForInstance())) .build("TalerMerchantApi.InstancesResponse"); -export const codecForInstance = - (): Codec => - buildCodecForObject() - .property("name", codecForString()) - .property("user_type", codecForString()) - .property("website", codecOptional(codecForString())) - .property("logo", codecOptional(codecForString())) - .property("id", codecForString()) - .property("merchant_pub", codecForString()) - .property("payment_targets", codecForList(codecForString())) - .property("deleted", codecForBoolean()) - .build("TalerMerchantApi.Instance"); +export const codecForInstance = (): Codec => + buildCodecForObject() + .property("name", codecForString()) + .property("user_type", codecForString()) + .property("website", codecOptional(codecForString())) + .property("logo", codecOptional(codecForString())) + .property("id", codecForString()) + .property("merchant_pub", codecForString()) + .property("payment_targets", codecForList(codecForString())) + .property("deleted", codecForBoolean()) + .build("TalerMerchantApi.Instance"); export const codecForExchangeConfig = (): Codec => @@ -3177,15 +3168,15 @@ export namespace TalerMerchantApi { // use “all”) to see all orders regardless of wire transfer // status. wired?: boolean; - // At most return the given number of results. Negative - // for descending by row ID, positive for ascending by + // At most return the given number of results. Negative + // for descending by row ID, positive for ascending by // row ID. Default is 20. Since protocol v12. limit?: number; // Non-negative date in seconds after the UNIX Epoc, see delta // for its interpretation. If not specified, we default to the // oldest or most recent entry, depending on delta. date?: AbsoluteTime; - // Starting product_serial_id for an iteration. + // Starting product_serial_id for an iteration. // Since protocol v12. offset?: string; // Timeout in milliseconds to wait for additional orders if the @@ -4610,7 +4601,6 @@ export namespace TalerMerchantApi { } export interface WalletTemplateDetails { - // Hard-coded information about the contrac terms // for this template. template_contract: TemplateContractDetails; @@ -4931,6 +4921,13 @@ export namespace TalerMerchantApi { // Useful when the merchant needs to store extra information on a // contract without storing it separately in their database. extra?: any; + + // Minimum age the buyer must have (in years). Default is 0. + // This value is at least as large as the maximum over all + // mimimum age requirements of the products in this contract. + // It might also be set independent of any product, due to + // legal requirements. + minimum_age?: Integer; } export interface Product { diff --git a/packages/taler-util/src/http-client/utils.ts b/packages/taler-util/src/http-client/utils.ts index dbfe64796..d6623cf00 100644 --- a/packages/taler-util/src/http-client/utils.ts +++ b/packages/taler-util/src/http-client/utils.ts @@ -59,7 +59,10 @@ export function addPaginationParams(url: URL, pagination?: PaginationParams) { url.searchParams.set("delta", String(order * limit)); } -export function addMerchantPaginationParams(url: URL, pagination?: PaginationParams) { +export function addMerchantPaginationParams( + url: URL, + pagination?: PaginationParams, +) { if (!pagination) return; if (pagination.offset) { url.searchParams.set("offset", pagination.offset); @@ -73,7 +76,6 @@ export function addMerchantPaginationParams(url: URL, pagination?: PaginationPar url.searchParams.set("limit", String(order * limit)); } - export function addLongPollingParam(url: URL, param?: LongPollParams) { if (!param) return; if (param.timeoutMs) { diff --git a/packages/taler-util/src/merchant-api-types.ts b/packages/taler-util/src/merchant-api-types.ts index 6d5570b61..639ae8d13 100644 --- a/packages/taler-util/src/merchant-api-types.ts +++ b/packages/taler-util/src/merchant-api-types.ts @@ -114,7 +114,6 @@ export const codecForMerchantCheckPaymentPaidResponse = .property("refund_details", codecForAny()) .build("CheckPaymentPaidResponse"); - export type MerchantOrderPrivateStatusResponse = | MerchantCheckPaymentPaidResponse | CheckPaymentUnpaidResponse diff --git a/packages/taler-util/src/observability.ts b/packages/taler-util/src/observability.ts index 70391cbcd..0171142c8 100644 --- a/packages/taler-util/src/observability.ts +++ b/packages/taler-util/src/observability.ts @@ -92,7 +92,7 @@ export class ObservableHttpClientLibrary implements HttpRequestLibrary { }); throw e; } finally { - this.cancelatorById.delete(id) + this.cancelatorById.delete(id); } } } diff --git a/packages/taler-util/src/taler-types.ts b/packages/taler-util/src/taler-types.ts index bad9186dc..419aeb159 100644 --- a/packages/taler-util/src/taler-types.ts +++ b/packages/taler-util/src/taler-types.ts @@ -564,6 +564,13 @@ export interface MerchantContractTerms { // contract without storing it separately in their database. // Must really be an Object (not a string, integer, float or array). extra?: any; + + // Minimum age the buyer must have (in years). Default is 0. + // This value is at least as large as the maximum over all + // mimimum age requirements of the products in this contract. + // It might also be set independent of any product, due to + // legal requirements. + minimum_age?: Integer; } /** @@ -617,7 +624,6 @@ export interface MerchantAbortPayRefundDetails { exchange_http_status: number; } - /** * Planchet detail sent to the merchant. */ @@ -1394,11 +1400,9 @@ export const codecForMerchantInfo = (): Codec => .property("jurisdiction", codecOptional(codecForLocation())) .build("MerchantInfo"); - export const codecForInternationalizedString = (): Codec => codecForMap(codecForString()); - export const codecForMerchantContractTerms = (): Codec => buildCodecForObject() .property("order_id", codecForString()) @@ -1615,7 +1619,6 @@ export const codecForMerchantOrderStatusPaid = .property("refunded", codecForBoolean()) .build("MerchantOrderStatusPaid"); - export const codecForMerchantOrderStatusUnpaid = (): Codec => buildCodecForObject() @@ -1653,7 +1656,6 @@ export interface AbortResponse { refunds: MerchantAbortPayRefundStatus[]; } - export type MerchantAbortPayRefundStatus = | MerchantAbortPayRefundSuccessStatus | MerchantAbortPayRefundFailureStatus; diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts index 61b9e1b59..92a902eca 100644 --- a/packages/taler-util/src/wallet-types.ts +++ b/packages/taler-util/src/wallet-types.ts @@ -628,11 +628,11 @@ export interface CoinDumpJson { withdrawal_reserve_pub: string | undefined; coin_status: CoinStatus; spend_allocation: - | { - id: string; - amount: AmountString; - } - | undefined; + | { + id: string; + amount: AmountString; + } + | undefined; /** * Information about the age restriction */ @@ -831,7 +831,7 @@ export const codecForPreparePayResultPaymentPossible = ) .build("PreparePayResultPaymentPossible"); -export interface BalanceDetails { } +export interface BalanceDetails {} /** * Detailed reason for why the wallet's balance is insufficient. @@ -2954,6 +2954,7 @@ export interface WalletContractData { wireMethod: string; wireInfoHash: string; maxDepositFee: AmountString; + minimumAge?: number; } export interface TestingWaitTransactionRequest { diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts index e473566b0..562cee4a6 100644 --- a/packages/taler-wallet-core/src/pay-merchant.ts +++ b/packages/taler-wallet-core/src/pay-merchant.ts @@ -590,6 +590,7 @@ export function extractContractData( maxDepositFee: Amounts.stringify(parsedContractTerms.max_fee), merchant: parsedContractTerms.merchant, summaryI18n: parsedContractTerms.summary_i18n, + minimumAge: parsedContractTerms.minimum_age, }; } @@ -1147,7 +1148,7 @@ async function handleInsufficientFunds( depositFeeLimit: Amounts.parseOrThrow(contractData.maxDepositFee), wireFeeAmortization: 1, // FIXME #8653 prevPayCoins, - requiredMinimumAge: undefined, // FIXME #8653 + requiredMinimumAge: contractData.minimumAge, }); if (res.type !== "success") { @@ -1276,7 +1277,7 @@ async function checkPaymentByProposalId( depositFeeLimit: Amounts.parseOrThrow(contractData.maxDepositFee), wireFeeAmortization: 1, // FIXME #8653 prevPayCoins: [], - requiredMinimumAge: undefined, // FIXME #8653 + requiredMinimumAge: contractData.minimumAge, restrictWireMethod: contractData.wireMethod, }); @@ -1630,7 +1631,7 @@ export async function generateDepositPermissions( timestamp: contractData.timestamp, wireInfoHash, ageCommitmentProof: coin.ageCommitmentProof, - requiredMinimumAge: undefined,// FIXME #8653 + requiredMinimumAge: contractData.minimumAge, }); depositPermissions.push(dp); } @@ -1815,7 +1816,7 @@ export async function confirmPay( depositFeeLimit: Amounts.parseOrThrow(contractData.maxDepositFee), wireFeeAmortization: 1, // FIXME #8653 prevPayCoins: [], - requiredMinimumAge: undefined, // FIXME #8653 + requiredMinimumAge: contractData.minimumAge, forcedSelection: forcedCoinSel, }); -- cgit v1.2.3