diff --git a/README.md b/README.md index a2b7b13a..00600bf7 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,40 @@ craftgate.payment().createPayment(request) }); ``` +## Idempotency + +Mutating operations accept an optional idempotency key. Set it on the request object and the client sends it as the `x-idempotency-key` header, so a request can be safely retried (e.g. after a timeout) without the operation being performed twice — the server returns the result of the first request when it sees a repeated key. + +Every request type includes `BaseRequest`, so the key is available on any request: + +```javascript +const { randomUUID } = require('crypto'); + +craftgate.payment().createPayment({ + price: 100.0, + paidPrice: 100.0, + currency: Craftgate.Model.Currency.Turkish_Lira, + paymentGroup: Craftgate.Model.PaymentGroup.ListingOrSubscription, + idempotencyKey: randomUUID(), + // ... other fields +}); +``` + +Operations whose parameters live in the URL path take a request object as well, so they can carry a key too: + +```javascript +craftgate.payment().expireCheckoutPayment({ + token: '456d1297-908e-4bd6-a13b-4be31a6e47d5', + idempotencyKey: randomUUID() +}); +``` + +> Use a fresh key per distinct operation, and reuse the same key when retrying that operation. + +> The API honours the key on `POST`, `PATCH` and `DELETE` only. It is ignored on `PUT` endpoints, so retrying one of those is not de-duplicated. + +The key is sent as a header only — it never appears in the request body, the query string, or the request signature. Your request object is not modified, so you can pass the very same object again to retry. + ## Development To contribute to the project, please see our guidelines at [CONTRIBUTING](./CONTRIBUTING.md). By participating in this project, you agree to abide by our [Code of Conduct](CODE_OF_CONDUCT.md). diff --git a/samples/fraud/DeleteFraudValueList.js b/samples/fraud/DeleteFraudValueList.js index 8c0e437f..ecccbcc1 100644 --- a/samples/fraud/DeleteFraudValueList.js +++ b/samples/fraud/DeleteFraudValueList.js @@ -7,6 +7,6 @@ const craftgate = new Craftgate.Client({ baseUrl: 'https://sandbox-api.craftgate.io' }); -craftgate.fraud().deleteValueList("ipList") +craftgate.fraud().deleteValueList({listName: "ipList"}) .then(() => console.info('Fraud value list deleted')) .catch(err => console.error('Failed to delete fraud value list', err)); diff --git a/samples/fraud/RemoveValueFromFraudValueList.js b/samples/fraud/RemoveValueFromFraudValueList.js index 532cf172..5f5f3102 100644 --- a/samples/fraud/RemoveValueFromFraudValueList.js +++ b/samples/fraud/RemoveValueFromFraudValueList.js @@ -7,6 +7,9 @@ const craftgate = new Craftgate.Client({ baseUrl: 'https://sandbox-api.craftgate.io' }); -craftgate.fraud().removeValueFromValueList("ipList", "5758a029-4a82-4e47-a0cf-36d34052b8e5") +craftgate.fraud().removeValueFromValueList({ + listName: "ipList", + valueId: "5758a029-4a82-4e47-a0cf-36d34052b8e5" +}) .then(() => console.info('Value removed from fraud value list')) .catch(err => console.error('Failed to remove value from fraud value list', err)); diff --git a/samples/fraud/UpdateFraudCheckStatus.js b/samples/fraud/UpdateFraudCheckStatus.js index 4c1f7466..be7a392c 100644 --- a/samples/fraud/UpdateFraudCheckStatus.js +++ b/samples/fraud/UpdateFraudCheckStatus.js @@ -7,6 +7,9 @@ const craftgate = new Craftgate.Client({ baseUrl: 'https://sandbox-api.craftgate.io' }); -craftgate.fraud().updateFraudCheckStatus(257, Craftgate.Model.FraudCheckStatus.Fraud) +craftgate.fraud().updateFraudCheckStatus({ + id: 257, + checkStatus: Craftgate.Model.FraudCheckStatus.Fraud +}) .then(() => console.info('Fraud check status updated')) .catch(err => console.error('Failed to update fraud check status', err)); diff --git a/samples/merchant/DeleteMerchantPos.js b/samples/merchant/DeleteMerchantPos.js index b6ca703f..2ddabc96 100644 --- a/samples/merchant/DeleteMerchantPos.js +++ b/samples/merchant/DeleteMerchantPos.js @@ -6,6 +6,6 @@ const craftgate = new Craftgate.Client({ baseUrl: 'https://sandbox-api.craftgate.io' }); -craftgate.merchant().deleteMerchantPos(10) +craftgate.merchant().deleteMerchantPos({merchantPosId: 10}) .then(result => console.info("Merchant pos deleted")) .catch(err => console.error("Failed to delete merchant pos", err)); \ No newline at end of file diff --git a/samples/merchant/UpdateMerchantPosStatus.js b/samples/merchant/UpdateMerchantPosStatus.js index 480709e3..c09c2aaa 100644 --- a/samples/merchant/UpdateMerchantPosStatus.js +++ b/samples/merchant/UpdateMerchantPosStatus.js @@ -6,6 +6,9 @@ const craftgate = new Craftgate.Client({ baseUrl: 'https://sandbox-api.craftgate.io' }); -craftgate.merchant().updateMerchantPosStatus(11, Craftgate.Model.PosStatus.Passive) +craftgate.merchant().updateMerchantPosStatus({ + merchantPosId: 11, + posStatus: Craftgate.Model.PosStatus.Passive +}) .then(result => console.info("Merchant pos status updated")) .catch(err => console.error("Failed to update merchant pos status", err)); \ No newline at end of file diff --git a/samples/payByLink/DeleteProduct.js b/samples/payByLink/DeleteProduct.js index be382068..227f3361 100644 --- a/samples/payByLink/DeleteProduct.js +++ b/samples/payByLink/DeleteProduct.js @@ -6,6 +6,6 @@ const craftgate = new Craftgate.Client({ baseUrl: "https://sandbox-api.craftgate.io" }); -craftgate.payByLink().deleteProduct(1) +craftgate.payByLink().deleteProduct({id: 1}) .then(result => console.info("Product successfully deleted")) .catch(err => console.error("Delete product failed", err)); diff --git a/samples/payment/ApproveBnplPayment.js b/samples/payment/ApproveBnplPayment.js index d84013a6..b449c06b 100644 --- a/samples/payment/ApproveBnplPayment.js +++ b/samples/payment/ApproveBnplPayment.js @@ -6,6 +6,6 @@ const craftgate = new Craftgate.Client({ baseUrl: 'https://sandbox-api.craftgate.io' }); -craftgate.payment().approveBnplPayment(1) +craftgate.payment().approveBnplPayment({paymentId: 1}) .then(results => console.info('Approve bnpl payment response ', results)) .catch(err => console.error('Failed to approve bnpl payment', err)); diff --git a/samples/payment/ExpireCheckoutPayment.js b/samples/payment/ExpireCheckoutPayment.js index f46ce29f..6d396e56 100644 --- a/samples/payment/ExpireCheckoutPayment.js +++ b/samples/payment/ExpireCheckoutPayment.js @@ -7,6 +7,6 @@ const craftgate = new Craftgate.Client({ }); // change checkout payment token below with a valid one -craftgate.payment().expireCheckoutPayment('456d1297-908e-4bd6-a13b-4be31a6e47d5') +craftgate.payment().expireCheckoutPayment({token: '456d1297-908e-4bd6-a13b-4be31a6e47d5'}) .then(() => console.info('Checkout payment token expired')) .catch(err => console.error('Failed to retrieve checkout payment', err)); diff --git a/samples/payment/VerifyBnplPayment.js b/samples/payment/VerifyBnplPayment.js index 7e7dee23..8850f5e3 100644 --- a/samples/payment/VerifyBnplPayment.js +++ b/samples/payment/VerifyBnplPayment.js @@ -6,6 +6,6 @@ const craftgate = new Craftgate.Client({ baseUrl: 'https://sandbox-api.craftgate.io' }); -craftgate.payment().verifyBnplPayment(1) +craftgate.payment().verifyBnplPayment({paymentId: 1}) .then(results => console.info('Verify bnpl payment response ', results)) .catch(err => console.error('Failed to verify bnpl payment', err)); diff --git a/samples/settlement/DeletePayoutAccount.js b/samples/settlement/DeletePayoutAccount.js index 1c9794f5..83ba0cd0 100644 --- a/samples/settlement/DeletePayoutAccount.js +++ b/samples/settlement/DeletePayoutAccount.js @@ -6,5 +6,5 @@ const craftgate = new Craftgate.Client({ baseUrl: 'https://sandbox-api.craftgate.io' }); -craftgate.settlement().deletePayoutAccount(11) +craftgate.settlement().deletePayoutAccount({id: 11}) .catch(err => console.error('Failed to delete payout account', err)); diff --git a/samples/wallet/CancelWithdraw.js b/samples/wallet/CancelWithdraw.js index 41671915..75edca2c 100644 --- a/samples/wallet/CancelWithdraw.js +++ b/samples/wallet/CancelWithdraw.js @@ -7,6 +7,6 @@ const craftgate = new Craftgate.Client({ }); // change withdraw id below with valid withdraw id -craftgate.wallet().cancelWithdraw(1) +craftgate.wallet().cancelWithdraw({withdrawId: 1}) .then(result => console.info("Withdraw cancelled", result)) .catch(err => console.error("Failed to cancel withdraw", err)); diff --git a/src/adapter/FraudAdapter.ts b/src/adapter/FraudAdapter.ts index 8ea93de0..cca4ca27 100644 --- a/src/adapter/FraudAdapter.ts +++ b/src/adapter/FraudAdapter.ts @@ -1,11 +1,13 @@ -import {ClientCreationOptions} from '../lib/HttpClient'; -import FraudCheckStatus from '../model/FraudCheckStatus'; +import {ClientCreationOptions, requestScopedConfig} from '../lib/HttpClient'; import FraudValueType from '../model/FraudValueType'; import AddCardFingerprintFraudValueListRequest from '../request/AddFraudValueListRequest'; +import DeleteValueListRequest from '../request/DeleteValueListRequest'; import FraudValueListRequest from '../request/FraudValueListRequest'; +import RemoveValueFromValueListRequest from '../request/RemoveValueFromValueListRequest'; import SearchFraudChecksRequest from '../request/SearchFraudChecksRequest'; import SearchFraudRuleRequest from '../request/SearchFraudRuleRequest'; +import UpdateFraudCheckStatusRequest from '../request/UpdateFraudCheckStatusRequest'; import FraudAllValueListsResponse from '../response/FraudAllValueListsResponse'; import FraudCheckListResponse from '../response/FraudCheckListResponse'; @@ -27,8 +29,8 @@ export default class FraudAdapter extends BaseAdapter { return this._client.get('/fraud/v1/rules', request); } - async updateFraudCheckStatus(id: number, fraudCheckStatus: FraudCheckStatus): Promise { - await this._client.put(`/fraud/v1/fraud-checks/${id}/check-status`, {checkStatus: fraudCheckStatus}); + async updateFraudCheckStatus(request: UpdateFraudCheckStatusRequest): Promise { + await this._client.put(`/fraud/v1/fraud-checks/${request.id}/check-status`, {checkStatus: request.checkStatus}, requestScopedConfig(request)); } async retrieveAllValueLists(): Promise { @@ -46,8 +48,8 @@ export default class FraudAdapter extends BaseAdapter { }); } - async deleteValueList(listName: string): Promise { - await this._client.delete(`/fraud/v1/value-lists/${listName}`); + async deleteValueList(request: DeleteValueListRequest): Promise { + await this._client.delete(`/fraud/v1/value-lists/${request.listName}`, undefined, requestScopedConfig(request)); } async addValueToValueList(request: FraudValueListRequest): Promise { @@ -58,7 +60,7 @@ export default class FraudAdapter extends BaseAdapter { await this._client.post(`/fraud/v1/value-lists/${listName}/card-fingerprints`, request); } - async removeValueFromValueList(listName: string, valueId: string): Promise { - await this._client.delete(`/fraud/v1/value-lists/${listName}/values/${valueId}`); + async removeValueFromValueList(request: RemoveValueFromValueListRequest): Promise { + await this._client.delete(`/fraud/v1/value-lists/${request.listName}/values/${request.valueId}`, undefined, requestScopedConfig(request)); } } diff --git a/src/adapter/MerchantAdapter.ts b/src/adapter/MerchantAdapter.ts index f804e911..d0280f31 100644 --- a/src/adapter/MerchantAdapter.ts +++ b/src/adapter/MerchantAdapter.ts @@ -1,10 +1,11 @@ -import {ClientCreationOptions} from '../lib/HttpClient'; -import PosStatus from '../model/PosStatus'; +import {ClientCreationOptions, requestScopedConfig} from '../lib/HttpClient'; import CreateMerchantPosRequest from '../request/CreateMerchantPosRequest'; +import DeleteMerchantPosRequest from '../request/DeleteMerchantPosRequest'; import SearchMerchantPosRequest from '../request/SearchMerchantPosRequest'; import UpdateMerchantPosCommissionRequest from '../request/UpdateMerchantPosCommissionRequest'; import UpdateMerchantPosRequest from '../request/UpdateMerchantPosRequest'; +import UpdateMerchantPosStatusRequest from '../request/UpdateMerchantPosStatusRequest'; import DataResponse from '../response/DataResponse'; import MerchantPosCommissionResponse from '../response/MerchantPosCommissionResponse'; @@ -25,12 +26,12 @@ export default class MerchantAdapter extends BaseAdapter { return this._client.get(`/merchant/v1/merchant-poses/${id}`); } - async deleteMerchantPos(id: number): Promise { - return this._client.delete(`/merchant/v1/merchant-poses/${id}`); + async deleteMerchantPos(request: DeleteMerchantPosRequest): Promise { + return this._client.delete(`/merchant/v1/merchant-poses/${request.merchantPosId}`, undefined, requestScopedConfig(request)); } - async updateMerchantPosStatus(id: number, status: PosStatus): Promise { - return this._client.put(`/merchant/v1/merchant-poses/${id}/status/${status}`); + async updateMerchantPosStatus(request: UpdateMerchantPosStatusRequest): Promise { + return this._client.put(`/merchant/v1/merchant-poses/${request.merchantPosId}/status/${request.posStatus}`, undefined, requestScopedConfig(request)); } async updateMerchantPos(id: number, request: UpdateMerchantPosRequest): Promise { diff --git a/src/adapter/PayByLinkApiAdapter.ts b/src/adapter/PayByLinkApiAdapter.ts index 29f8a204..4f015af3 100644 --- a/src/adapter/PayByLinkApiAdapter.ts +++ b/src/adapter/PayByLinkApiAdapter.ts @@ -1,6 +1,7 @@ -import {ClientCreationOptions} from '../lib/HttpClient'; +import {ClientCreationOptions, requestScopedConfig} from '../lib/HttpClient'; import CreateProductRequest from '../request/CreateProductRequest'; +import DeleteProductRequest from '../request/DeleteProductRequest'; import SearchProductsRequest from '../request/SearchProductsRequest'; import UpdateProductRequest from '../request/UpdateProductRequest'; @@ -26,8 +27,8 @@ export default class PayByLinkApiAdapter extends BaseAdapter { return this._client.get(`/craftlink/v1/products/${productId}`); } - async deleteProduct(productId: number): Promise { - await this._client.delete(`/craftlink/v1/products/${productId}`); + async deleteProduct(request: DeleteProductRequest): Promise { + await this._client.delete(`/craftlink/v1/products/${request.id}`, undefined, requestScopedConfig(request)); } async searchProducts(request: SearchProductsRequest): Promise> { diff --git a/src/adapter/PaymentAdapter.ts b/src/adapter/PaymentAdapter.ts index 7e10107b..85e1a30f 100644 --- a/src/adapter/PaymentAdapter.ts +++ b/src/adapter/PaymentAdapter.ts @@ -1,7 +1,8 @@ -import {ClientCreationOptions} from '../lib/HttpClient'; +import {ClientCreationOptions, requestScopedConfig} from '../lib/HttpClient'; import {calculateHash} from '../lib/utils'; import ApplePayMerchantSessionCreateRequest from '../request/ApplePayMerchantSessionCreateRequest'; +import ApproveBnplPaymentRequest from '../request/ApproveBnplPaymentRequest'; import ApprovePaymentTransactionsRequest from '../request/ApprovePaymentTransactionsRequest'; import BnplPaymentOfferRequest from '../request/BnplPaymentOfferRequest'; import CloneCardRequest from '../request/CloneCardRequest'; @@ -15,6 +16,7 @@ import CreateFundTransferDepositPaymentRequest from '../request/CreateFundTransf import CreatePaymentRequest from '../request/CreatePaymentRequest'; import DeleteStoredCardRequest from '../request/DeleteStoredCardRequest'; import DisapprovePaymentTransactionsRequest from '../request/DisapprovePaymentTransactionsRequest'; +import ExpireCheckoutPaymentRequest from '../request/ExpireCheckoutPaymentRequest'; import InitApmDepositPaymentRequest from '../request/InitApmDepositPaymentRequest'; import InitApmPaymentRequest from '../request/InitApmPaymentRequest'; import InitBnplLimitInquiryRequest from '../request/InitBnplLimitInquiryRequest'; @@ -37,6 +39,7 @@ import SearchStoredCardsRequest from '../request/SearchStoredCardsRequest'; import StoreCardRequest from '../request/StoreCardRequest'; import UpdateCardRequest from '../request/UpdateCardRequest'; import UpdatePaymentTransactionRequest from '../request/UpdatePaymentTransactionRequest'; +import VerifyBnplPaymentRequest from '../request/VerifyBnplPaymentRequest'; import VerifyCardRequest from '../request/VerifyCardRequest'; import ApmDepositPaymentResponse from '../response/ApmDepositPaymentResponse'; @@ -113,8 +116,8 @@ export default class PaymentAdapter extends BaseAdapter { return this._client.get(`/payment/v1/checkout-payments/${token}`); } - async expireCheckoutPayment(token: string): Promise { - await this._client.delete(`/payment/v1/checkout-payments/${token}`); + async expireCheckoutPayment(request: ExpireCheckoutPaymentRequest): Promise { + await this._client.delete(`/payment/v1/checkout-payments/${request.token}`, undefined, requestScopedConfig(request)); } async createDepositPayment(request: CreateDepositPaymentRequest): Promise { @@ -241,12 +244,12 @@ export default class PaymentAdapter extends BaseAdapter { return this._client.post(`/payment/v1/bnpl-payments/init`, request); } - async approveBnplPayment(paymentId: number): Promise { - return this._client.post(`/payment/v1/bnpl-payments/${paymentId}/approve`); + async approveBnplPayment(request: ApproveBnplPaymentRequest): Promise { + return this._client.post(`/payment/v1/bnpl-payments/${request.paymentId}/approve`, undefined, requestScopedConfig(request)); } - async verifyBnplPayment(paymentId: number): Promise { - return this._client.post(`/payment/v1/bnpl-payments/${paymentId}/verify`); + async verifyBnplPayment(request: VerifyBnplPaymentRequest): Promise { + return this._client.post(`/payment/v1/bnpl-payments/${request.paymentId}/verify`, undefined, requestScopedConfig(request)); } async bnplLimitInquiryInit(request: InitBnplLimitInquiryRequest): Promise { diff --git a/src/adapter/SettlementAdapter.ts b/src/adapter/SettlementAdapter.ts index fb2190ac..74f4c235 100644 --- a/src/adapter/SettlementAdapter.ts +++ b/src/adapter/SettlementAdapter.ts @@ -1,7 +1,8 @@ -import {ClientCreationOptions} from '../lib/HttpClient'; +import {ClientCreationOptions, requestScopedConfig} from '../lib/HttpClient'; import CreateInstantWalletSettlementRequest from '../request/CreateInstantWalletSettlementRequest'; import CreatePayoutAccountRequest from '../request/CreatePayoutAccountRequest'; +import DeletePayoutAccountRequest from '../request/DeletePayoutAccountRequest'; import SearchPayoutAccountRequest from '../request/SearchPayoutAccountRequest'; import UpdatePayoutAccountRequest from '../request/UpdatePayoutAccountRequest'; @@ -28,8 +29,8 @@ export default class SettlementAdapter extends BaseAdapter { await this._client.put(`/settlement/v1/payout-accounts/${id}`, request); } - async deletePayoutAccount(id: number): Promise { - await this._client.delete(`/settlement/v1/payout-accounts/${id}`); + async deletePayoutAccount(request: DeletePayoutAccountRequest): Promise { + await this._client.delete(`/settlement/v1/payout-accounts/${request.id}`, undefined, requestScopedConfig(request)); } async searchPayoutAccount(request: SearchPayoutAccountRequest): Promise> { diff --git a/src/adapter/WalletAdapter.ts b/src/adapter/WalletAdapter.ts index 9357f8a5..35bb5da9 100644 --- a/src/adapter/WalletAdapter.ts +++ b/src/adapter/WalletAdapter.ts @@ -1,5 +1,6 @@ -import {ClientCreationOptions} from '../lib/HttpClient'; +import {ClientCreationOptions, requestScopedConfig} from '../lib/HttpClient'; +import CancelWithdrawRequest from '../request/CancelWithdrawRequest'; import CreateMemberWalletRequest from '../request/CreateMemberWalletRequest'; import CreateRemittanceRequest from '../request/CreateRemittanceRequest'; import CreateWithdrawRequest from '../request/CreateWithdrawRequest'; @@ -77,8 +78,8 @@ export default class WalletAdapter extends BaseAdapter { return this._client.post('/wallet/v1/withdraws', request); } - async cancelWithdraw(withdrawId: number): Promise { - return this._client.post(`/wallet/v1/withdraws/${withdrawId}/cancel`); + async cancelWithdraw(request: CancelWithdrawRequest): Promise { + return this._client.post(`/wallet/v1/withdraws/${request.withdrawId}/cancel`, undefined, requestScopedConfig(request)); } async retrieveWithdraw(withdrawId: number): Promise { diff --git a/src/lib/HttpClient.ts b/src/lib/HttpClient.ts index 6afbecf6..56546e0d 100644 --- a/src/lib/HttpClient.ts +++ b/src/lib/HttpClient.ts @@ -2,7 +2,7 @@ import axios, {AxiosInstance, AxiosRequestConfig, AxiosResponse} from 'axios'; import CraftgateError from '../CraftgateError'; -import {calculateSignature, generateRandomString, serializeParams} from './utils'; +import {calculateSignature, generateRandomString, omitRequestScopedOptions, REQUEST_SCOPED_HEADERS, serializeParams} from './utils'; export type ClientOptions = { apiKey: string; @@ -30,6 +30,25 @@ const CLIENT_VERSION_HEADER_NAME = 'x-client-version'; const SIGNATURE_HEADER_NAME = 'x-signature'; const LANGUAGE_HEADER_NAME = 'lang'; +function requestScopedHeadersOf(source: any): Record { + const headers: Record = {}; + if (!source || typeof source !== 'object') { + return headers; + } + + Object.keys(REQUEST_SCOPED_HEADERS).forEach((key: string) => { + if (source[key]) { + headers[REQUEST_SCOPED_HEADERS[key]] = source[key]; + } + }); + return headers; +} + +export function requestScopedConfig(request?: any): AxiosRequestConfig { + const headers = requestScopedHeadersOf(request); + return Object.keys(headers).length > 0 ? {headers} : {}; +} + export class HttpClient { private readonly _client: AxiosInstance; private readonly _options: ClientOptions; @@ -82,6 +101,14 @@ export class HttpClient { private _injectHeaders(config: AxiosRequestConfig): AxiosRequestConfig { const randomStr: string = generateRandomString(); + const scopedHeaders: Record = { + ...requestScopedHeadersOf(config.params), + ...requestScopedHeadersOf(config.data) + }; + Object.keys(scopedHeaders).forEach((name: string) => { + config.headers[name] = scopedHeaders[name]; + }); + config.headers[API_KEY_HEADER_NAME] = this._options.apiKey; config.headers[RANDOM_HEADER_NAME] = randomStr; config.headers[AUTH_VERSION_HEADER_NAME] = '1'; @@ -91,7 +118,7 @@ export class HttpClient { } config.maxRedirects = 0; - const requestBody: string | null = config.data ? JSON.stringify(config.data, null, 0) : null; + const requestBody: string | null = config.data ? JSON.stringify(omitRequestScopedOptions(config.data), null, 0) : null; if (!config.paramsSerializer) { config.paramsSerializer = { diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 2792739d..afb87be1 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -74,6 +74,20 @@ export function getEncodedStringValue(value: any): string { return encodeURIComponent(value); } +export const REQUEST_SCOPED_HEADERS: Record = { + idempotencyKey: 'x-idempotency-key' +}; + +export function omitRequestScopedOptions(data: any): any { + if (data === null || typeof data !== 'object' || Array.isArray(data)) { + return data; + } + + const rest = {...data}; + Object.keys(REQUEST_SCOPED_HEADERS).forEach((key: string) => delete rest[key]); + return rest; +} + /** * Serializes an object as a query string, using unbracketed keys for array values. * @@ -81,6 +95,7 @@ export function getEncodedStringValue(value: any): string { */ export function serializeParams(params: any): string { return Object.keys(params) + .filter((key: string) => !(key in REQUEST_SCOPED_HEADERS)) .reduce((acc: Array, key: string) => { const value: any = params[key]; const encodedKey = encodeURIComponent(key); diff --git a/src/request/AddFraudValueListRequest.ts b/src/request/AddFraudValueListRequest.ts index 75250876..2e92741f 100644 --- a/src/request/AddFraudValueListRequest.ts +++ b/src/request/AddFraudValueListRequest.ts @@ -1,6 +1,8 @@ import FraudOperation from '../model/FraudOperation'; -type AddCardFingerprintFraudValueListRequest = { +import BaseRequest from './BaseRequest'; + +type AddCardFingerprintFraudValueListRequest = BaseRequest & { label?: string; durationInSeconds?: number; operationId?: string; diff --git a/src/request/ApplePayMerchantSessionCreateRequest.ts b/src/request/ApplePayMerchantSessionCreateRequest.ts index 5543e44e..12c37b02 100644 --- a/src/request/ApplePayMerchantSessionCreateRequest.ts +++ b/src/request/ApplePayMerchantSessionCreateRequest.ts @@ -1,4 +1,6 @@ -type ApplePayMerchantSessionCreateRequest = { +import BaseRequest from './BaseRequest'; + +type ApplePayMerchantSessionCreateRequest = BaseRequest & { merchantIdentifier: string; displayName: string; initiative: string; diff --git a/src/request/ApproveBnplPaymentRequest.ts b/src/request/ApproveBnplPaymentRequest.ts new file mode 100644 index 00000000..d9274f08 --- /dev/null +++ b/src/request/ApproveBnplPaymentRequest.ts @@ -0,0 +1,7 @@ +import BaseRequest from './BaseRequest'; + +type ApproveBnplPaymentRequest = BaseRequest & { + paymentId: number; +}; + +export default ApproveBnplPaymentRequest; diff --git a/src/request/ApprovePaymentTransactionsRequest.ts b/src/request/ApprovePaymentTransactionsRequest.ts index f57266d6..9e8d22e3 100644 --- a/src/request/ApprovePaymentTransactionsRequest.ts +++ b/src/request/ApprovePaymentTransactionsRequest.ts @@ -1,4 +1,6 @@ -type ApprovePaymentTransactionsRequest = { +import BaseRequest from './BaseRequest'; + +type ApprovePaymentTransactionsRequest = BaseRequest & { paymentTransactionIds: number[]; isTransactional?: boolean; }; diff --git a/src/request/BaseRequest.ts b/src/request/BaseRequest.ts new file mode 100644 index 00000000..af27ec5c --- /dev/null +++ b/src/request/BaseRequest.ts @@ -0,0 +1,5 @@ +type BaseRequest = { + idempotencyKey?: string; +}; + +export default BaseRequest; diff --git a/src/request/BnplPaymentOfferRequest.ts b/src/request/BnplPaymentOfferRequest.ts index 69b33b74..11c6fc87 100644 --- a/src/request/BnplPaymentOfferRequest.ts +++ b/src/request/BnplPaymentOfferRequest.ts @@ -1,9 +1,10 @@ import ApmType from '../model/ApmType'; import Currency from '../model/Currency'; +import BaseRequest from './BaseRequest'; import BnplPaymentCartItem from './dto/BnplPaymentCartItem'; -type BnplPaymentOfferRequest = { +type BnplPaymentOfferRequest = BaseRequest & { apmType: ApmType; merchantApmId: number; price: number; diff --git a/src/request/CancelWithdrawRequest.ts b/src/request/CancelWithdrawRequest.ts new file mode 100644 index 00000000..da5799fb --- /dev/null +++ b/src/request/CancelWithdrawRequest.ts @@ -0,0 +1,7 @@ +import BaseRequest from './BaseRequest'; + +type CancelWithdrawRequest = BaseRequest & { + withdrawId: number; +}; + +export default CancelWithdrawRequest; diff --git a/src/request/CheckMasterpassUserRequest.ts b/src/request/CheckMasterpassUserRequest.ts index 2940a19d..4bb218e9 100644 --- a/src/request/CheckMasterpassUserRequest.ts +++ b/src/request/CheckMasterpassUserRequest.ts @@ -1,4 +1,6 @@ -type CheckMasterpassUserRequest = { +import BaseRequest from './BaseRequest'; + +type CheckMasterpassUserRequest = BaseRequest & { masterpassGsmNumber: string; }; diff --git a/src/request/CloneCardRequest.ts b/src/request/CloneCardRequest.ts index b5335650..2ce76c97 100644 --- a/src/request/CloneCardRequest.ts +++ b/src/request/CloneCardRequest.ts @@ -1,4 +1,6 @@ -type CloneCardRequest = { +import BaseRequest from './BaseRequest'; + +type CloneCardRequest = BaseRequest & { sourceCardUserKey: string; sourceCardToken: string; targetCardUserKey: string; diff --git a/src/request/CompleteApmPaymentRequest.ts b/src/request/CompleteApmPaymentRequest.ts index b888ba18..bade7bcc 100644 --- a/src/request/CompleteApmPaymentRequest.ts +++ b/src/request/CompleteApmPaymentRequest.ts @@ -1,4 +1,6 @@ -type CompleteApmPaymentRequest = { +import BaseRequest from './BaseRequest'; + +type CompleteApmPaymentRequest = BaseRequest & { paymentId: number; additionalParams?: Record; }; diff --git a/src/request/CompleteBkmExpressRequest.ts b/src/request/CompleteBkmExpressRequest.ts index b47d3824..f36e9e52 100644 --- a/src/request/CompleteBkmExpressRequest.ts +++ b/src/request/CompleteBkmExpressRequest.ts @@ -1,4 +1,6 @@ -type CompleteBkmExpressRequest = { +import BaseRequest from './BaseRequest'; + +type CompleteBkmExpressRequest = BaseRequest & { status: boolean; message: string; ticketId?: string; diff --git a/src/request/CompleteBnplLimitInquiryRequest.ts b/src/request/CompleteBnplLimitInquiryRequest.ts index 459f2ef8..ffa85770 100644 --- a/src/request/CompleteBnplLimitInquiryRequest.ts +++ b/src/request/CompleteBnplLimitInquiryRequest.ts @@ -1,6 +1,8 @@ import ApmType from '../model/ApmType'; -type CompleteBnplLimitInquiryRequest = { +import BaseRequest from './BaseRequest'; + +type CompleteBnplLimitInquiryRequest = BaseRequest & { apmType: ApmType; merchantApmId: number; additionalParams: { diff --git a/src/request/CompletePosApmPaymentRequest.ts b/src/request/CompletePosApmPaymentRequest.ts index 9004efe0..0ded9642 100644 --- a/src/request/CompletePosApmPaymentRequest.ts +++ b/src/request/CompletePosApmPaymentRequest.ts @@ -1,4 +1,6 @@ -type CompletePosApmPaymentRequest = { +import BaseRequest from './BaseRequest'; + +type CompletePosApmPaymentRequest = BaseRequest & { paymentId: number; additionalParams?: Record; }; diff --git a/src/request/CompleteThreeDSPaymentRequest.ts b/src/request/CompleteThreeDSPaymentRequest.ts index df84d4fd..e34fb2fd 100644 --- a/src/request/CompleteThreeDSPaymentRequest.ts +++ b/src/request/CompleteThreeDSPaymentRequest.ts @@ -1,4 +1,6 @@ -type CompleteThreeDSPaymentRequest = { +import BaseRequest from './BaseRequest'; + +type CompleteThreeDSPaymentRequest = BaseRequest & { paymentId: number; }; diff --git a/src/request/CreateApmPaymentRequest.ts b/src/request/CreateApmPaymentRequest.ts index 510ddd4b..1a8d02c7 100644 --- a/src/request/CreateApmPaymentRequest.ts +++ b/src/request/CreateApmPaymentRequest.ts @@ -2,9 +2,10 @@ import ApmType from '../model/ApmType'; import Currency from '../model/Currency'; import PaymentGroup from '../model/PaymentGroup'; +import BaseRequest from './BaseRequest'; import PaymentItem from './dto/PaymentItem'; -type CreateApmPaymentRequest = { +type CreateApmPaymentRequest = BaseRequest & { apmType: ApmType; price: number; paidPrice: number; diff --git a/src/request/CreateDepositPaymentRequest.ts b/src/request/CreateDepositPaymentRequest.ts index 9ec4362a..f4f1c4d8 100644 --- a/src/request/CreateDepositPaymentRequest.ts +++ b/src/request/CreateDepositPaymentRequest.ts @@ -1,9 +1,10 @@ import Currency from '../model/Currency'; +import BaseRequest from './BaseRequest'; import {Card} from './dto/Card'; import RoutingOptions from './dto/RoutingOptions'; -type CreateDepositPaymentRequest = { +type CreateDepositPaymentRequest = BaseRequest & { buyerMemberId: number; price: number; currency: Currency; diff --git a/src/request/CreateFundTransferDepositPaymentRequest.ts b/src/request/CreateFundTransferDepositPaymentRequest.ts index 2dea6cfc..147c2e69 100644 --- a/src/request/CreateFundTransferDepositPaymentRequest.ts +++ b/src/request/CreateFundTransferDepositPaymentRequest.ts @@ -1,4 +1,6 @@ -type CreateFundTransferDepositPaymentRequest = { +import BaseRequest from './BaseRequest'; + +type CreateFundTransferDepositPaymentRequest = BaseRequest & { price: number; buyerMemberId: number; conversationId?: string; diff --git a/src/request/CreateInstantWalletSettlementRequest.ts b/src/request/CreateInstantWalletSettlementRequest.ts index a2cab686..90437076 100644 --- a/src/request/CreateInstantWalletSettlementRequest.ts +++ b/src/request/CreateInstantWalletSettlementRequest.ts @@ -1,4 +1,6 @@ -type CreateInstantWalletSettlementRequest = { +import BaseRequest from './BaseRequest'; + +type CreateInstantWalletSettlementRequest = BaseRequest & { excludedSubMerchantMemberIds: number[]; }; diff --git a/src/request/CreateMemberRequest.ts b/src/request/CreateMemberRequest.ts index 7f803b58..b595911d 100644 --- a/src/request/CreateMemberRequest.ts +++ b/src/request/CreateMemberRequest.ts @@ -1,7 +1,9 @@ import MemberType from '../model/MemberType'; import SettlementEarningsDestination from '../model/SettlementEarningsDestination'; -type CreateMemberRequest = { +import BaseRequest from './BaseRequest'; + +type CreateMemberRequest = BaseRequest & { isBuyer?: boolean; isSubMerchant?: boolean; memberType?: MemberType; diff --git a/src/request/CreateMemberWalletRequest.ts b/src/request/CreateMemberWalletRequest.ts index 68ee2554..e8d123f7 100644 --- a/src/request/CreateMemberWalletRequest.ts +++ b/src/request/CreateMemberWalletRequest.ts @@ -1,6 +1,8 @@ import Currency from '../model/Currency'; -type CreateMemberWalletRequest = { +import BaseRequest from './BaseRequest'; + +type CreateMemberWalletRequest = BaseRequest & { negativeAmountLimit: number; currency: Currency; }; diff --git a/src/request/CreateMerchantPosRequest.ts b/src/request/CreateMerchantPosRequest.ts index 0d3294df..e0da4080 100644 --- a/src/request/CreateMerchantPosRequest.ts +++ b/src/request/CreateMerchantPosRequest.ts @@ -4,7 +4,9 @@ import PaymentAuthenticationType from '../model/PaymentAuthenticationType'; import PosIntegrator from '../model/PosIntegrator'; import PosStatus from '../model/PosStatus'; -type CreateMerchantPosRequest = { +import BaseRequest from './BaseRequest'; + +type CreateMerchantPosRequest = BaseRequest & { status: PosStatus; name: string; clientId?: string; diff --git a/src/request/CreateMerchantRequest.ts b/src/request/CreateMerchantRequest.ts index 9f0e6c8b..80aeba50 100644 --- a/src/request/CreateMerchantRequest.ts +++ b/src/request/CreateMerchantRequest.ts @@ -1,4 +1,6 @@ -type CreateMerchantRequest = { +import BaseRequest from './BaseRequest'; + +type CreateMerchantRequest = BaseRequest & { name: string; legalCompanyTitle: string; email: string; diff --git a/src/request/CreatePaymentRequest.ts b/src/request/CreatePaymentRequest.ts index 6f48f5ac..2b8f7760 100644 --- a/src/request/CreatePaymentRequest.ts +++ b/src/request/CreatePaymentRequest.ts @@ -3,12 +3,13 @@ import Installment from '../model/Installment'; import PaymentGroup from '../model/PaymentGroup'; import PaymentPhase from '../model/PaymentPhase'; +import BaseRequest from './BaseRequest'; import {Card} from './dto/Card'; import FraudCheckParameters from './dto/FraudCheckParameters'; import PaymentItem from './dto/PaymentItem'; import RoutingOptions from './dto/RoutingOptions'; -type CreatePaymentRequest = { +type CreatePaymentRequest = BaseRequest & { price: number; paidPrice: number; walletPrice: number; diff --git a/src/request/CreatePayoutAccountRequest.ts b/src/request/CreatePayoutAccountRequest.ts index c91e2252..ffd871c9 100644 --- a/src/request/CreatePayoutAccountRequest.ts +++ b/src/request/CreatePayoutAccountRequest.ts @@ -2,7 +2,9 @@ import AccountOwner from '../model/AccountOwner'; import Currency from '../model/Currency'; import PayoutAccountType from '../model/PayoutAccountType'; -type CreatePayoutAccountRequest = { +import BaseRequest from './BaseRequest'; + +type CreatePayoutAccountRequest = BaseRequest & { type: PayoutAccountType; externalAccountId: string; currency: Currency; diff --git a/src/request/CreateProductRequest.ts b/src/request/CreateProductRequest.ts index 53bf7e75..9fad98e3 100644 --- a/src/request/CreateProductRequest.ts +++ b/src/request/CreateProductRequest.ts @@ -1,6 +1,8 @@ import Currency from '../model/Currency'; -type CreateProductRequest = { +import BaseRequest from './BaseRequest'; + +type CreateProductRequest = BaseRequest & { name: string; channel: string; orderId: string; diff --git a/src/request/CreateRemittanceRequest.ts b/src/request/CreateRemittanceRequest.ts index 4aa86bbe..2cc255ec 100644 --- a/src/request/CreateRemittanceRequest.ts +++ b/src/request/CreateRemittanceRequest.ts @@ -1,7 +1,9 @@ import Currency from '../model/Currency'; import RemittanceReasonType from '../model/RemittanceReasonType'; -type CreateRemittanceRequest = { +import BaseRequest from './BaseRequest'; + +type CreateRemittanceRequest = BaseRequest & { memberId: string; price: number; currency: Currency; diff --git a/src/request/CreateReportRequest.ts b/src/request/CreateReportRequest.ts index edd07b34..6d3d486e 100644 --- a/src/request/CreateReportRequest.ts +++ b/src/request/CreateReportRequest.ts @@ -1,6 +1,8 @@ import ReportPeriod from '../model/ReportPeriod'; import ReportType from '../model/ReportType'; -declare type CreateReportRequest = { + +import BaseRequest from './BaseRequest'; +declare type CreateReportRequest = BaseRequest & { startDate: Date; endDate: Date; reportType: ReportType; diff --git a/src/request/CreateWithdrawRequest.ts b/src/request/CreateWithdrawRequest.ts index f7c7776a..e06abfcd 100644 --- a/src/request/CreateWithdrawRequest.ts +++ b/src/request/CreateWithdrawRequest.ts @@ -1,6 +1,8 @@ import Currency from '../model/Currency'; -type CreateWithdrawRequest = { +import BaseRequest from './BaseRequest'; + +type CreateWithdrawRequest = BaseRequest & { price: number; memberId: number; description: string; diff --git a/src/request/DeleteMerchantPosRequest.ts b/src/request/DeleteMerchantPosRequest.ts new file mode 100644 index 00000000..221d9c75 --- /dev/null +++ b/src/request/DeleteMerchantPosRequest.ts @@ -0,0 +1,7 @@ +import BaseRequest from './BaseRequest'; + +type DeleteMerchantPosRequest = BaseRequest & { + merchantPosId: number; +}; + +export default DeleteMerchantPosRequest; diff --git a/src/request/DeletePayoutAccountRequest.ts b/src/request/DeletePayoutAccountRequest.ts new file mode 100644 index 00000000..7c598e64 --- /dev/null +++ b/src/request/DeletePayoutAccountRequest.ts @@ -0,0 +1,7 @@ +import BaseRequest from './BaseRequest'; + +type DeletePayoutAccountRequest = BaseRequest & { + id: number; +}; + +export default DeletePayoutAccountRequest; diff --git a/src/request/DeleteProductRequest.ts b/src/request/DeleteProductRequest.ts new file mode 100644 index 00000000..9b16ad12 --- /dev/null +++ b/src/request/DeleteProductRequest.ts @@ -0,0 +1,7 @@ +import BaseRequest from './BaseRequest'; + +type DeleteProductRequest = BaseRequest & { + id: number; +}; + +export default DeleteProductRequest; diff --git a/src/request/DeleteStoredCardRequest.ts b/src/request/DeleteStoredCardRequest.ts index b1fe7898..7a6e40f8 100644 --- a/src/request/DeleteStoredCardRequest.ts +++ b/src/request/DeleteStoredCardRequest.ts @@ -1,4 +1,6 @@ -type DeleteStoredCardRequest = { +import BaseRequest from './BaseRequest'; + +type DeleteStoredCardRequest = BaseRequest & { cardUserKey: string; cardToken: string; }; diff --git a/src/request/DeleteValueListRequest.ts b/src/request/DeleteValueListRequest.ts new file mode 100644 index 00000000..4df68e71 --- /dev/null +++ b/src/request/DeleteValueListRequest.ts @@ -0,0 +1,7 @@ +import BaseRequest from './BaseRequest'; + +type DeleteValueListRequest = BaseRequest & { + listName: string; +}; + +export default DeleteValueListRequest; diff --git a/src/request/DisapprovePaymentTransactionsRequest.ts b/src/request/DisapprovePaymentTransactionsRequest.ts index e8a4873f..636dbc5c 100644 --- a/src/request/DisapprovePaymentTransactionsRequest.ts +++ b/src/request/DisapprovePaymentTransactionsRequest.ts @@ -1,4 +1,6 @@ -type DisapprovePaymentTransactionsRequest = { +import BaseRequest from './BaseRequest'; + +type DisapprovePaymentTransactionsRequest = BaseRequest & { paymentTransactionIds: number[]; isTransactional?: boolean; }; diff --git a/src/request/ExpireCheckoutPaymentRequest.ts b/src/request/ExpireCheckoutPaymentRequest.ts new file mode 100644 index 00000000..ea28ded8 --- /dev/null +++ b/src/request/ExpireCheckoutPaymentRequest.ts @@ -0,0 +1,7 @@ +import BaseRequest from './BaseRequest'; + +type ExpireCheckoutPaymentRequest = BaseRequest & { + token: string; +}; + +export default ExpireCheckoutPaymentRequest; diff --git a/src/request/FraudValueListRequest.ts b/src/request/FraudValueListRequest.ts index e6102872..1bbd7060 100644 --- a/src/request/FraudValueListRequest.ts +++ b/src/request/FraudValueListRequest.ts @@ -1,6 +1,8 @@ import FraudValueType from '../model/FraudValueType'; -type FraudValueListRequest = { +import BaseRequest from './BaseRequest'; + +type FraudValueListRequest = BaseRequest & { listName: string; type: FraudValueType; label?: string; diff --git a/src/request/InitApmDepositPaymentRequest.ts b/src/request/InitApmDepositPaymentRequest.ts index c76a1969..736c6a08 100644 --- a/src/request/InitApmDepositPaymentRequest.ts +++ b/src/request/InitApmDepositPaymentRequest.ts @@ -1,7 +1,9 @@ import ApmType from '../model/ApmType'; import Currency from '../model/Currency'; -type InitApmDepositPaymentRequest = { +import BaseRequest from './BaseRequest'; + +type InitApmDepositPaymentRequest = BaseRequest & { apmType: ApmType; merchantApmId: number; price: number; diff --git a/src/request/InitApmPaymentRequest.ts b/src/request/InitApmPaymentRequest.ts index 5119c575..0e5e6820 100644 --- a/src/request/InitApmPaymentRequest.ts +++ b/src/request/InitApmPaymentRequest.ts @@ -2,9 +2,10 @@ import ApmType from '../model/ApmType'; import Currency from '../model/Currency'; import PaymentGroup from '../model/PaymentGroup'; +import BaseRequest from './BaseRequest'; import PaymentItem from './dto/PaymentItem'; -type InitApmPaymentRequest = { +type InitApmPaymentRequest = BaseRequest & { apmType: ApmType; merchantApmId: number; price: number; diff --git a/src/request/InitBkmExpressRequest.ts b/src/request/InitBkmExpressRequest.ts index 3ea61376..14f6b8e5 100644 --- a/src/request/InitBkmExpressRequest.ts +++ b/src/request/InitBkmExpressRequest.ts @@ -2,9 +2,10 @@ import Currency from '../model/Currency'; import PaymentGroup from '../model/PaymentGroup'; import PaymentPhase from '../model/PaymentPhase'; +import BaseRequest from './BaseRequest'; import PaymentItem from './dto/PaymentItem'; -type InitBkmExpressRequest = { +type InitBkmExpressRequest = BaseRequest & { price: number; paidPrice: number; buyerMemberId?: number; diff --git a/src/request/InitBnplLimitInquiryRequest.ts b/src/request/InitBnplLimitInquiryRequest.ts index 497a10a0..59209ef4 100644 --- a/src/request/InitBnplLimitInquiryRequest.ts +++ b/src/request/InitBnplLimitInquiryRequest.ts @@ -1,6 +1,8 @@ import ApmType from '../model/ApmType'; -type InitBnplLimitInquiryRequest = { +import BaseRequest from './BaseRequest'; + +type InitBnplLimitInquiryRequest = BaseRequest & { apmType: ApmType; merchantApmId: number; additionalParams: { diff --git a/src/request/InitCheckoutCardVerifyRequest.ts b/src/request/InitCheckoutCardVerifyRequest.ts index 8d5fa626..9b8233ab 100644 --- a/src/request/InitCheckoutCardVerifyRequest.ts +++ b/src/request/InitCheckoutCardVerifyRequest.ts @@ -1,7 +1,9 @@ import CardVerificationAuthType from '../model/CardVerificationAuthType'; import Currency from '../model/Currency'; -type InitCheckoutCardVerifyRequest = { +import BaseRequest from './BaseRequest'; + +type InitCheckoutCardVerifyRequest = BaseRequest & { verificationPrice: number; currency: Currency; conversationId?: string; diff --git a/src/request/InitCheckoutPaymentRequest.ts b/src/request/InitCheckoutPaymentRequest.ts index d280cdd5..d30b40aa 100644 --- a/src/request/InitCheckoutPaymentRequest.ts +++ b/src/request/InitCheckoutPaymentRequest.ts @@ -3,12 +3,13 @@ import PaymentGroup from '../model/PaymentGroup'; import PaymentMethod from '../model/PaymentMethod'; import PaymentPhase from '../model/PaymentPhase'; +import BaseRequest from './BaseRequest'; import CustomInstallment from './dto/CustomInstallment'; import FraudCheckParameters from './dto/FraudCheckParameters'; import PaymentItem from './dto/PaymentItem'; import RoutingOptions from './dto/RoutingOptions'; -type InitCheckoutPaymentRequest = { +type InitCheckoutPaymentRequest = BaseRequest & { price: number; paidPrice: number; buyerMemberId?: number; diff --git a/src/request/InitGarantiPayPaymentRequest.ts b/src/request/InitGarantiPayPaymentRequest.ts index 5d19c791..e273dfbc 100644 --- a/src/request/InitGarantiPayPaymentRequest.ts +++ b/src/request/InitGarantiPayPaymentRequest.ts @@ -1,10 +1,11 @@ import Currency from '../model/Currency'; import PaymentGroup from '../model/PaymentGroup'; +import BaseRequest from './BaseRequest'; import GarantiPayInstallment from './dto/GarantiPayInstallment'; import PaymentItem from './dto/PaymentItem'; -type InitGarantiPayPaymentRequest = { +type InitGarantiPayPaymentRequest = BaseRequest & { price: number; paidPrice: number; installments: GarantiPayInstallment[]; diff --git a/src/request/InitJuzdanPaymentRequest.ts b/src/request/InitJuzdanPaymentRequest.ts index 4c09d564..96ce323c 100644 --- a/src/request/InitJuzdanPaymentRequest.ts +++ b/src/request/InitJuzdanPaymentRequest.ts @@ -3,9 +3,10 @@ import Currency from '../model/Currency'; import PaymentGroup from '../model/PaymentGroup'; import PaymentPhase from '../model/PaymentPhase'; +import BaseRequest from './BaseRequest'; import PaymentItem from './dto/PaymentItem'; -type InitJuzdanPaymentRequest = { +type InitJuzdanPaymentRequest = BaseRequest & { price: number; paidPrice: number; currency: Currency; diff --git a/src/request/InitMealVoucherCardTokenizationRequest.ts b/src/request/InitMealVoucherCardTokenizationRequest.ts index b0c4779e..fd8de567 100644 --- a/src/request/InitMealVoucherCardTokenizationRequest.ts +++ b/src/request/InitMealVoucherCardTokenizationRequest.ts @@ -1,8 +1,9 @@ import ApmType from '../model/ApmType'; +import BaseRequest from './BaseRequest'; import MealVoucherCardTokenizationData from './dto/MealVoucherCardTokenizationData'; -type InitMealVoucherCardTokenizationRequest = { +type InitMealVoucherCardTokenizationRequest = BaseRequest & { apmType: ApmType; mealVoucherCardTokenizationData: MealVoucherCardTokenizationData; }; diff --git a/src/request/InitMultiPaymentRequest.ts b/src/request/InitMultiPaymentRequest.ts index 09f6b10b..1af36c1b 100644 --- a/src/request/InitMultiPaymentRequest.ts +++ b/src/request/InitMultiPaymentRequest.ts @@ -2,9 +2,10 @@ import Currency from '../model/Currency'; import PaymentGroup from '../model/PaymentGroup'; import PaymentMethod from '../model/PaymentMethod'; +import BaseRequest from './BaseRequest'; import PaymentItem from './dto/PaymentItem'; -type InitMultiPaymentRequest = { +type InitMultiPaymentRequest = BaseRequest & { price: number; currency: Currency; paymentGroup: PaymentGroup; diff --git a/src/request/InitPosApmPaymentRequest.ts b/src/request/InitPosApmPaymentRequest.ts index b02c0c47..400913ee 100644 --- a/src/request/InitPosApmPaymentRequest.ts +++ b/src/request/InitPosApmPaymentRequest.ts @@ -3,11 +3,12 @@ import PaymentGroup from '../model/PaymentGroup'; import PaymentPhase from '../model/PaymentPhase'; import PosApmPaymentProvider from '../model/PosApmPaymentProvider'; +import BaseRequest from './BaseRequest'; import FraudCheckParameters from './dto/FraudCheckParameters'; import PaymentItem from './dto/PaymentItem'; import PosApmInstallment from './dto/PosApmInstallment'; -type InitPosApmPaymentRequest = { +type InitPosApmPaymentRequest = BaseRequest & { price: number; paidPrice: number; posAlias: string; diff --git a/src/request/MasterpassPaymentCompleteRequest.ts b/src/request/MasterpassPaymentCompleteRequest.ts index ce9104e1..582962b3 100644 --- a/src/request/MasterpassPaymentCompleteRequest.ts +++ b/src/request/MasterpassPaymentCompleteRequest.ts @@ -1,4 +1,6 @@ -type MasterpassPaymentCompleteRequest = { +import BaseRequest from './BaseRequest'; + +type MasterpassPaymentCompleteRequest = BaseRequest & { referenceId: string; token: string; }; diff --git a/src/request/MasterpassPaymentThreeDSCompleteRequest.ts b/src/request/MasterpassPaymentThreeDSCompleteRequest.ts index 9d5cb710..f13f4b80 100644 --- a/src/request/MasterpassPaymentThreeDSCompleteRequest.ts +++ b/src/request/MasterpassPaymentThreeDSCompleteRequest.ts @@ -1,4 +1,6 @@ -type MasterpassPaymentThreeDSCompleteRequest = { +import BaseRequest from './BaseRequest'; + +type MasterpassPaymentThreeDSCompleteRequest = BaseRequest & { paymentId: number; }; diff --git a/src/request/MasterpassPaymentThreeDSInitRequest.ts b/src/request/MasterpassPaymentThreeDSInitRequest.ts index b1249213..a7440cf7 100644 --- a/src/request/MasterpassPaymentThreeDSInitRequest.ts +++ b/src/request/MasterpassPaymentThreeDSInitRequest.ts @@ -1,4 +1,6 @@ -type MasterpassPaymentThreeDSInitRequest = { +import BaseRequest from './BaseRequest'; + +type MasterpassPaymentThreeDSInitRequest = BaseRequest & { referenceId: string; callbackUrl: string; }; diff --git a/src/request/MasterpassPaymentTokenGenerateRequest.ts b/src/request/MasterpassPaymentTokenGenerateRequest.ts index bd7ceb4f..bd1de097 100644 --- a/src/request/MasterpassPaymentTokenGenerateRequest.ts +++ b/src/request/MasterpassPaymentTokenGenerateRequest.ts @@ -1,9 +1,10 @@ import {Loyalty} from '../model/Loyalty'; import MasterpassValidationType from '../model/MasterpassValidationType'; +import BaseRequest from './BaseRequest'; import MasterpassCreatePayment from './dto/MasterpassCreatePayment'; -type MasterpassPaymentTokenGenerateRequest = { +type MasterpassPaymentTokenGenerateRequest = BaseRequest & { msisdn: string; userId: string; binNumber: string; diff --git a/src/request/MasterpassRetrieveLoyaltiesRequest.ts b/src/request/MasterpassRetrieveLoyaltiesRequest.ts index 291b6b84..530b0330 100644 --- a/src/request/MasterpassRetrieveLoyaltiesRequest.ts +++ b/src/request/MasterpassRetrieveLoyaltiesRequest.ts @@ -1,4 +1,6 @@ -type MasterpassRetrieveLoyaltiesRequest = { +import BaseRequest from './BaseRequest'; + +type MasterpassRetrieveLoyaltiesRequest = BaseRequest & { msisdn: string; binNumber: string; cardName: string; diff --git a/src/request/MealVoucherCardTokenizationCompleteRequest.ts b/src/request/MealVoucherCardTokenizationCompleteRequest.ts index a61e9320..5f458e76 100644 --- a/src/request/MealVoucherCardTokenizationCompleteRequest.ts +++ b/src/request/MealVoucherCardTokenizationCompleteRequest.ts @@ -1,4 +1,6 @@ -type MealVoucherCardTokenizationCompleteRequest = { +import BaseRequest from './BaseRequest'; + +type MealVoucherCardTokenizationCompleteRequest = BaseRequest & { validationCode?: string; }; diff --git a/src/request/MealVoucherCardTokenizationRegenerateRequest.ts b/src/request/MealVoucherCardTokenizationRegenerateRequest.ts index effe6d63..dc4ae3a9 100644 --- a/src/request/MealVoucherCardTokenizationRegenerateRequest.ts +++ b/src/request/MealVoucherCardTokenizationRegenerateRequest.ts @@ -1,6 +1,7 @@ +import BaseRequest from './BaseRequest'; import MealVoucherCardTokenizationData from './dto/MealVoucherCardTokenizationData'; -type MealVoucherCardTokenizationRegenerateRequest = { +type MealVoucherCardTokenizationRegenerateRequest = BaseRequest & { mealVoucherCardTokenizationData: MealVoucherCardTokenizationData; }; diff --git a/src/request/PostAuthPaymentRequest.ts b/src/request/PostAuthPaymentRequest.ts index 5fd5a220..ce4e42d4 100644 --- a/src/request/PostAuthPaymentRequest.ts +++ b/src/request/PostAuthPaymentRequest.ts @@ -1,4 +1,6 @@ -type PostAuthPaymentRequest = { +import BaseRequest from './BaseRequest'; + +type PostAuthPaymentRequest = BaseRequest & { paidPrice?: number; }; diff --git a/src/request/RefundPaymentRequest.ts b/src/request/RefundPaymentRequest.ts index 4edda645..a7a42e37 100644 --- a/src/request/RefundPaymentRequest.ts +++ b/src/request/RefundPaymentRequest.ts @@ -1,6 +1,8 @@ import RefundDestinationType from '../model/RefundDestinationType'; -type RefundPaymentRequest = { +import BaseRequest from './BaseRequest'; + +type RefundPaymentRequest = BaseRequest & { paymentId: number; conversationId?: string; refundDestinationType?: RefundDestinationType; diff --git a/src/request/RefundPaymentTransactionMarkAsRefundedRequest.ts b/src/request/RefundPaymentTransactionMarkAsRefundedRequest.ts index e923ab81..e9107752 100644 --- a/src/request/RefundPaymentTransactionMarkAsRefundedRequest.ts +++ b/src/request/RefundPaymentTransactionMarkAsRefundedRequest.ts @@ -1,4 +1,6 @@ -type RefundPaymentTransactionMarkAsRefundedRequest = { +import BaseRequest from './BaseRequest'; + +type RefundPaymentTransactionMarkAsRefundedRequest = BaseRequest & { paymentTransactionId: number; conversationId?: string; refundPrice: number; diff --git a/src/request/RefundPaymentTransactionRequest.ts b/src/request/RefundPaymentTransactionRequest.ts index 670e324c..c24ffade 100644 --- a/src/request/RefundPaymentTransactionRequest.ts +++ b/src/request/RefundPaymentTransactionRequest.ts @@ -1,6 +1,8 @@ import RefundDestinationType from '../model/RefundDestinationType'; -type RefundPaymentTransactionRequest = { +import BaseRequest from './BaseRequest'; + +type RefundPaymentTransactionRequest = BaseRequest & { paymentTransactionId: number; conversationId?: string; refundPrice?: number; diff --git a/src/request/RefundWaitingPaymentRequest.ts b/src/request/RefundWaitingPaymentRequest.ts index e560183f..d51ddc1a 100644 --- a/src/request/RefundWaitingPaymentRequest.ts +++ b/src/request/RefundWaitingPaymentRequest.ts @@ -1,4 +1,6 @@ -type RefundWaitingPaymentRequest = { +import BaseRequest from './BaseRequest'; + +type RefundWaitingPaymentRequest = BaseRequest & { paymentId: number; }; diff --git a/src/request/RefundWalletTransactionRequest.ts b/src/request/RefundWalletTransactionRequest.ts index f70b30c2..d584593a 100644 --- a/src/request/RefundWalletTransactionRequest.ts +++ b/src/request/RefundWalletTransactionRequest.ts @@ -1,4 +1,6 @@ -type RefundWalletTransactionRequest = { +import BaseRequest from './BaseRequest'; + +type RefundWalletTransactionRequest = BaseRequest & { refundPrice: number; }; diff --git a/src/request/RemoveValueFromValueListRequest.ts b/src/request/RemoveValueFromValueListRequest.ts new file mode 100644 index 00000000..ce2017fe --- /dev/null +++ b/src/request/RemoveValueFromValueListRequest.ts @@ -0,0 +1,8 @@ +import BaseRequest from './BaseRequest'; + +type RemoveValueFromValueListRequest = BaseRequest & { + listName: string; + valueId: string; +}; + +export default RemoveValueFromValueListRequest; diff --git a/src/request/ResetMerchantMemberWalletBalanceRequest.ts b/src/request/ResetMerchantMemberWalletBalanceRequest.ts index ab4c2e51..f4f28b57 100644 --- a/src/request/ResetMerchantMemberWalletBalanceRequest.ts +++ b/src/request/ResetMerchantMemberWalletBalanceRequest.ts @@ -1,4 +1,6 @@ -type ResetMerchantMemberWalletBalanceRequest = { +import BaseRequest from './BaseRequest'; + +type ResetMerchantMemberWalletBalanceRequest = BaseRequest & { walletAmount: number; }; diff --git a/src/request/RetrieveCardFromIvrRequest.ts b/src/request/RetrieveCardFromIvrRequest.ts index 2703dac7..10143de8 100644 --- a/src/request/RetrieveCardFromIvrRequest.ts +++ b/src/request/RetrieveCardFromIvrRequest.ts @@ -1,4 +1,6 @@ -type RetrieveCardFromIvrRequest = { +import BaseRequest from './BaseRequest'; + +type RetrieveCardFromIvrRequest = BaseRequest & { callToken: string; cardUserKey: string; }; diff --git a/src/request/RetrieveDailyPaymentReportRequest.ts b/src/request/RetrieveDailyPaymentReportRequest.ts index 28b993a5..6e47bff7 100644 --- a/src/request/RetrieveDailyPaymentReportRequest.ts +++ b/src/request/RetrieveDailyPaymentReportRequest.ts @@ -1,6 +1,8 @@ import ReportFileType from '../model/ReportFileType'; -type RetrieveDailyPaymentReportRequest = { +import BaseRequest from './BaseRequest'; + +type RetrieveDailyPaymentReportRequest = BaseRequest & { reportDate: string; fileType: ReportFileType; }; diff --git a/src/request/RetrieveDailyTransactionReportRequest.ts b/src/request/RetrieveDailyTransactionReportRequest.ts index 71d81721..18624166 100644 --- a/src/request/RetrieveDailyTransactionReportRequest.ts +++ b/src/request/RetrieveDailyTransactionReportRequest.ts @@ -1,6 +1,8 @@ import ReportFileType from '../model/ReportFileType'; -type RetrieveDailyTransactionReportRequest = { +import BaseRequest from './BaseRequest'; + +type RetrieveDailyTransactionReportRequest = BaseRequest & { reportDate: string; fileType: ReportFileType; }; diff --git a/src/request/RetrieveLoyaltiesRequest.ts b/src/request/RetrieveLoyaltiesRequest.ts index b6e764cc..64989b7c 100644 --- a/src/request/RetrieveLoyaltiesRequest.ts +++ b/src/request/RetrieveLoyaltiesRequest.ts @@ -1,3 +1,4 @@ +import BaseRequest from './BaseRequest'; import FraudCheckParameters from './dto/FraudCheckParameters'; type ExplicitCardInfo = { @@ -18,6 +19,6 @@ type FraudCheckInfo = { fraudParams?: FraudCheckParameters; }; -type RetrieveLoyaltiesRequest = ExplicitCardInfo | StoredCardInfo | FraudCheckInfo; +type RetrieveLoyaltiesRequest = BaseRequest & (ExplicitCardInfo | StoredCardInfo | FraudCheckInfo); export default RetrieveLoyaltiesRequest; diff --git a/src/request/RetrieveProviderCardRequest.ts b/src/request/RetrieveProviderCardRequest.ts index 3178de2b..e3509124 100644 --- a/src/request/RetrieveProviderCardRequest.ts +++ b/src/request/RetrieveProviderCardRequest.ts @@ -1,6 +1,8 @@ import CardProvider from '../model/CardProvider'; -type RetrieveProviderCardRequest = { +import BaseRequest from './BaseRequest'; + +type RetrieveProviderCardRequest = BaseRequest & { providerCardToken: string; externalId: string; providerCardUserId: string; diff --git a/src/request/RetrieveReportRequest.ts b/src/request/RetrieveReportRequest.ts index 0ff7ac84..dbef2844 100644 --- a/src/request/RetrieveReportRequest.ts +++ b/src/request/RetrieveReportRequest.ts @@ -1,6 +1,8 @@ import ReportFileType from '../model/ReportFileType'; -type RetrieveReportRequest = { +import BaseRequest from './BaseRequest'; + +type RetrieveReportRequest = BaseRequest & { fileType: ReportFileType; }; diff --git a/src/request/SearchBankAccountTrackingRecordsRequest.ts b/src/request/SearchBankAccountTrackingRecordsRequest.ts index 85d53ef4..9f940db2 100644 --- a/src/request/SearchBankAccountTrackingRecordsRequest.ts +++ b/src/request/SearchBankAccountTrackingRecordsRequest.ts @@ -1,6 +1,8 @@ import Currency from '../model/Currency'; -type SearchBankAccountTrackingRecordsRequest = { +import BaseRequest from './BaseRequest'; + +type SearchBankAccountTrackingRecordsRequest = BaseRequest & { senderName?: string; senderIban?: string; description?: string; diff --git a/src/request/SearchFraudChecksRequest.ts b/src/request/SearchFraudChecksRequest.ts index 66e4267c..443e85ff 100644 --- a/src/request/SearchFraudChecksRequest.ts +++ b/src/request/SearchFraudChecksRequest.ts @@ -2,7 +2,9 @@ import FraudAction from '../model/FraudAction'; import FraudCheckStatus from '../model/FraudCheckStatus'; import PaymentStatus from '../model/PaymentStatus'; -type SearchFraudChecksRequest = { +import BaseRequest from './BaseRequest'; + +type SearchFraudChecksRequest = BaseRequest & { page?: number; size?: number; action?: FraudAction; diff --git a/src/request/SearchFraudRuleRequest.ts b/src/request/SearchFraudRuleRequest.ts index 66312059..f4654eba 100644 --- a/src/request/SearchFraudRuleRequest.ts +++ b/src/request/SearchFraudRuleRequest.ts @@ -1,7 +1,9 @@ import FraudAction from '../model/FraudAction'; import FraudOperation from '../model/FraudOperation'; -type SearchFraudRuleRequest = { +import BaseRequest from './BaseRequest'; + +type SearchFraudRuleRequest = BaseRequest & { name?: string; minCreatedDate?: Date; maxCreatedDate?: Date; diff --git a/src/request/SearchInstallmentsRequest.ts b/src/request/SearchInstallmentsRequest.ts index 824f9ec6..7c977351 100644 --- a/src/request/SearchInstallmentsRequest.ts +++ b/src/request/SearchInstallmentsRequest.ts @@ -1,6 +1,8 @@ import Currency from '../model/Currency'; -type SearchInstallmentsRequest = { +import BaseRequest from './BaseRequest'; + +type SearchInstallmentsRequest = BaseRequest & { binNumber?: string; price: number; currency?: Currency; diff --git a/src/request/SearchMembersRequest.ts b/src/request/SearchMembersRequest.ts index 538658a4..bd36bc20 100644 --- a/src/request/SearchMembersRequest.ts +++ b/src/request/SearchMembersRequest.ts @@ -1,6 +1,8 @@ import MemberType from '../model/MemberType'; -type SearchMembersRequest = { +import BaseRequest from './BaseRequest'; + +type SearchMembersRequest = BaseRequest & { isBuyer?: boolean; isSubMerchant?: boolean; name?: string; diff --git a/src/request/SearchMerchantPosRequest.ts b/src/request/SearchMerchantPosRequest.ts index ebb9d067..fe06ae29 100644 --- a/src/request/SearchMerchantPosRequest.ts +++ b/src/request/SearchMerchantPosRequest.ts @@ -1,6 +1,8 @@ import Currency from '../model/Currency'; -type SearchMerchantPosRequest = { +import BaseRequest from './BaseRequest'; + +type SearchMerchantPosRequest = BaseRequest & { name?: string; alias?: string; currency?: Currency; diff --git a/src/request/SearchPaymentRefundsRequest.ts b/src/request/SearchPaymentRefundsRequest.ts index e9a2c502..b912746b 100644 --- a/src/request/SearchPaymentRefundsRequest.ts +++ b/src/request/SearchPaymentRefundsRequest.ts @@ -1,7 +1,9 @@ import Currency from '../model/Currency'; import RefundStatus from '../model/RefundStatus'; -type SearchPaymentRefundsRequest = { +import BaseRequest from './BaseRequest'; + +type SearchPaymentRefundsRequest = BaseRequest & { page?: number; size?: number; id?: number; diff --git a/src/request/SearchPaymentTransactionRefundsRequest.ts b/src/request/SearchPaymentTransactionRefundsRequest.ts index 92ecae2b..6a8ebabd 100644 --- a/src/request/SearchPaymentTransactionRefundsRequest.ts +++ b/src/request/SearchPaymentTransactionRefundsRequest.ts @@ -1,7 +1,9 @@ import Currency from '../model/Currency'; import RefundStatus from '../model/RefundStatus'; -type SearchPaymentTransactionRefundsRequest = { +import BaseRequest from './BaseRequest'; + +type SearchPaymentTransactionRefundsRequest = BaseRequest & { page?: number; size?: number; id?: number; diff --git a/src/request/SearchPaymentsRequest.ts b/src/request/SearchPaymentsRequest.ts index 40853920..92c1767f 100644 --- a/src/request/SearchPaymentsRequest.ts +++ b/src/request/SearchPaymentsRequest.ts @@ -1,7 +1,9 @@ import Currency from '../model/Currency'; import Installment from '../model/Installment'; -type SearchPaymentsRequest = { +import BaseRequest from './BaseRequest'; + +type SearchPaymentsRequest = BaseRequest & { page?: number; size?: number; paymentId?: number; diff --git a/src/request/SearchPayoutAccountRequest.ts b/src/request/SearchPayoutAccountRequest.ts index 46f7313a..e7d54707 100644 --- a/src/request/SearchPayoutAccountRequest.ts +++ b/src/request/SearchPayoutAccountRequest.ts @@ -1,7 +1,9 @@ import AccountOwner from '../model/AccountOwner'; import Currency from '../model/Currency'; -type SearchPayoutAccountRequest = { +import BaseRequest from './BaseRequest'; + +type SearchPayoutAccountRequest = BaseRequest & { page?: number; size?: number; currency?: Currency; diff --git a/src/request/SearchPayoutBouncedTransactionsRequest.ts b/src/request/SearchPayoutBouncedTransactionsRequest.ts index a32eb5b3..1a84aff3 100644 --- a/src/request/SearchPayoutBouncedTransactionsRequest.ts +++ b/src/request/SearchPayoutBouncedTransactionsRequest.ts @@ -1,4 +1,6 @@ -type SearchPayoutBouncedTransactionsRequest = { +import BaseRequest from './BaseRequest'; + +type SearchPayoutBouncedTransactionsRequest = BaseRequest & { endDate: Date; startDate: Date; }; diff --git a/src/request/SearchPayoutCompletedTransactionsRequest.ts b/src/request/SearchPayoutCompletedTransactionsRequest.ts index 7f7060d1..247745ed 100644 --- a/src/request/SearchPayoutCompletedTransactionsRequest.ts +++ b/src/request/SearchPayoutCompletedTransactionsRequest.ts @@ -1,6 +1,8 @@ import SettlementType from '../model/SettlementType'; -type SearchPayoutCompletedTransactionsRequest = { +import BaseRequest from './BaseRequest'; + +type SearchPayoutCompletedTransactionsRequest = BaseRequest & { settlementFileId?: number; settlementType?: SettlementType; endDate: Date; diff --git a/src/request/SearchPayoutRowsRequest.ts b/src/request/SearchPayoutRowsRequest.ts index 19823160..799261d1 100644 --- a/src/request/SearchPayoutRowsRequest.ts +++ b/src/request/SearchPayoutRowsRequest.ts @@ -1,6 +1,8 @@ import FileStatus from '../model/FileStatus'; -type SearchPayoutRowsRequest = { +import BaseRequest from './BaseRequest'; + +type SearchPayoutRowsRequest = BaseRequest & { page: number; size: number; fileStatus: FileStatus; diff --git a/src/request/SearchProductsRequest.ts b/src/request/SearchProductsRequest.ts index 9cb71121..9c87031f 100644 --- a/src/request/SearchProductsRequest.ts +++ b/src/request/SearchProductsRequest.ts @@ -1,6 +1,8 @@ import Currency from '../model/Currency'; -type SearchProductsRequest = { +import BaseRequest from './BaseRequest'; + +type SearchProductsRequest = BaseRequest & { id: number; name?: string; orderId: string; diff --git a/src/request/SearchStoredCardsRequest.ts b/src/request/SearchStoredCardsRequest.ts index 4a37804e..1a4e9cfb 100644 --- a/src/request/SearchStoredCardsRequest.ts +++ b/src/request/SearchStoredCardsRequest.ts @@ -2,7 +2,9 @@ import CardAssociation from '../model/CardAssociation'; import CardExpiryStatus from '../model/CardExpiryStatus'; import CardType from '../model/CardType'; -type SearchStoredCardsRequest = { +import BaseRequest from './BaseRequest'; + +type SearchStoredCardsRequest = BaseRequest & { cardAlias?: string; cardBrand?: string; cardType?: CardType; diff --git a/src/request/SearchWalletTransactionsRequest.ts b/src/request/SearchWalletTransactionsRequest.ts index 2786f1d6..4aa00899 100644 --- a/src/request/SearchWalletTransactionsRequest.ts +++ b/src/request/SearchWalletTransactionsRequest.ts @@ -1,6 +1,8 @@ import WalletTransactionType from '../model/WalletTransactionType'; -type SearchWalletTransactionsRequest = { +import BaseRequest from './BaseRequest'; + +type SearchWalletTransactionsRequest = BaseRequest & { walletTransactionTypes: WalletTransactionType[]; minCreatedDate?: Date; maxCreatedDate?: Date; diff --git a/src/request/SearchWithdrawsRequest.ts b/src/request/SearchWithdrawsRequest.ts index 925a8ffd..71f91107 100644 --- a/src/request/SearchWithdrawsRequest.ts +++ b/src/request/SearchWithdrawsRequest.ts @@ -1,7 +1,9 @@ import Currency from '../model/Currency'; import TransactionPayoutStatus from '../model/TransactionPayoutStatus'; -type SearchWithdrawsRequest = { +import BaseRequest from './BaseRequest'; + +type SearchWithdrawsRequest = BaseRequest & { memberId?: number; currency?: Currency; payoutStatus?: TransactionPayoutStatus; diff --git a/src/request/StoreCardRequest.ts b/src/request/StoreCardRequest.ts index a35729c6..d710bb90 100644 --- a/src/request/StoreCardRequest.ts +++ b/src/request/StoreCardRequest.ts @@ -1,6 +1,7 @@ +import BaseRequest from './BaseRequest'; import {EncryptedCard} from './dto/EncryptedCard'; -type StoreCardRequest = { +type StoreCardRequest = BaseRequest & { cardHolderName: string; cardNumber: string; expireYear: string; diff --git a/src/request/UpdateCardRequest.ts b/src/request/UpdateCardRequest.ts index 443e4f5b..79f50688 100644 --- a/src/request/UpdateCardRequest.ts +++ b/src/request/UpdateCardRequest.ts @@ -1,4 +1,6 @@ -type UpdateCardRequest = { +import BaseRequest from './BaseRequest'; + +type UpdateCardRequest = BaseRequest & { cardUserKey: string; cardToken: string; expireYear: string; diff --git a/src/request/UpdateFraudCheckStatusRequest.ts b/src/request/UpdateFraudCheckStatusRequest.ts new file mode 100644 index 00000000..3aab2bb0 --- /dev/null +++ b/src/request/UpdateFraudCheckStatusRequest.ts @@ -0,0 +1,10 @@ +import FraudCheckStatus from '../model/FraudCheckStatus'; + +import BaseRequest from './BaseRequest'; + +type UpdateFraudCheckStatusRequest = BaseRequest & { + id: number; + checkStatus: FraudCheckStatus; +}; + +export default UpdateFraudCheckStatusRequest; diff --git a/src/request/UpdateMemberRequest.ts b/src/request/UpdateMemberRequest.ts index 0730cf60..cd79be58 100644 --- a/src/request/UpdateMemberRequest.ts +++ b/src/request/UpdateMemberRequest.ts @@ -1,7 +1,9 @@ import MemberType from '../model/MemberType'; import SettlementEarningsDestination from '../model/SettlementEarningsDestination'; -type UpdateMemberRequest = { +import BaseRequest from './BaseRequest'; + +type UpdateMemberRequest = BaseRequest & { isBuyer?: boolean; isSubMerchant?: boolean; memberType?: MemberType; diff --git a/src/request/UpdateMemberWalletRequest.ts b/src/request/UpdateMemberWalletRequest.ts index 0945f4fb..936230c3 100644 --- a/src/request/UpdateMemberWalletRequest.ts +++ b/src/request/UpdateMemberWalletRequest.ts @@ -1,4 +1,6 @@ -type UpdateMemberWalletRequest = { +import BaseRequest from './BaseRequest'; + +type UpdateMemberWalletRequest = BaseRequest & { negativeAmountLimit: number; }; diff --git a/src/request/UpdateMerchantPosCommissionRequest.ts b/src/request/UpdateMerchantPosCommissionRequest.ts index 39b2bfeb..1d47e847 100644 --- a/src/request/UpdateMerchantPosCommissionRequest.ts +++ b/src/request/UpdateMerchantPosCommissionRequest.ts @@ -1,6 +1,8 @@ import UpdateMerchantPosCommission from '../model/UpdateMerchantPosCommission'; -type UpdateMerchantPosCommissionRequest = { +import BaseRequest from './BaseRequest'; + +type UpdateMerchantPosCommissionRequest = BaseRequest & { commissions: UpdateMerchantPosCommission[]; }; diff --git a/src/request/UpdateMerchantPosRequest.ts b/src/request/UpdateMerchantPosRequest.ts index a86ce60c..991c6928 100644 --- a/src/request/UpdateMerchantPosRequest.ts +++ b/src/request/UpdateMerchantPosRequest.ts @@ -2,7 +2,9 @@ import CardAssociation from '../model/CardAssociation'; import PaymentAuthenticationType from '../model/PaymentAuthenticationType'; import UpdateMerchantPosUser from '../model/UpdateMerchantPosUser'; -type UpdateMerchantPosRequest = { +import BaseRequest from './BaseRequest'; + +type UpdateMerchantPosRequest = BaseRequest & { name: string; hostname: string; clientId?: string; diff --git a/src/request/UpdateMerchantPosStatusRequest.ts b/src/request/UpdateMerchantPosStatusRequest.ts new file mode 100644 index 00000000..fd3dee96 --- /dev/null +++ b/src/request/UpdateMerchantPosStatusRequest.ts @@ -0,0 +1,10 @@ +import PosStatus from '../model/PosStatus'; + +import BaseRequest from './BaseRequest'; + +type UpdateMerchantPosStatusRequest = BaseRequest & { + merchantPosId: number; + posStatus: PosStatus; +}; + +export default UpdateMerchantPosStatusRequest; diff --git a/src/request/UpdatePaymentTransactionRequest.ts b/src/request/UpdatePaymentTransactionRequest.ts index c26fa6b9..dd67469c 100644 --- a/src/request/UpdatePaymentTransactionRequest.ts +++ b/src/request/UpdatePaymentTransactionRequest.ts @@ -1,4 +1,6 @@ -type UpdatePaymentTransactionRequest = { +import BaseRequest from './BaseRequest'; + +type UpdatePaymentTransactionRequest = BaseRequest & { subMerchantMemberPrice: number; subMerchantMemberId: number; blockageResolvedDate?: Date; diff --git a/src/request/UpdatePayoutAccountRequest.ts b/src/request/UpdatePayoutAccountRequest.ts index 964fc701..a5588edf 100644 --- a/src/request/UpdatePayoutAccountRequest.ts +++ b/src/request/UpdatePayoutAccountRequest.ts @@ -1,6 +1,8 @@ import PayoutAccountType from '../model/PayoutAccountType'; -type UpdatePayoutAccountRequest = { +import BaseRequest from './BaseRequest'; + +type UpdatePayoutAccountRequest = BaseRequest & { type: PayoutAccountType; externalAccountId: string; }; diff --git a/src/request/UpdateProductRequest.ts b/src/request/UpdateProductRequest.ts index 41465c47..9480dedb 100644 --- a/src/request/UpdateProductRequest.ts +++ b/src/request/UpdateProductRequest.ts @@ -1,7 +1,9 @@ import Currency from '../model/Currency'; import Status from '../model/Status'; -type UpdateProductRequest = { +import BaseRequest from './BaseRequest'; + +type UpdateProductRequest = BaseRequest & { status: Status; name: string; channel: string; diff --git a/src/request/VerifyBnplPaymentRequest.ts b/src/request/VerifyBnplPaymentRequest.ts new file mode 100644 index 00000000..0036a074 --- /dev/null +++ b/src/request/VerifyBnplPaymentRequest.ts @@ -0,0 +1,7 @@ +import BaseRequest from './BaseRequest'; + +type VerifyBnplPaymentRequest = BaseRequest & { + paymentId: number; +}; + +export default VerifyBnplPaymentRequest; diff --git a/src/request/VerifyCardRequest.ts b/src/request/VerifyCardRequest.ts index e91191a2..1618c511 100644 --- a/src/request/VerifyCardRequest.ts +++ b/src/request/VerifyCardRequest.ts @@ -1,9 +1,10 @@ import CardVerificationAuthType from '../model/CardVerificationAuthType'; import Currency from '../model/Currency'; +import BaseRequest from './BaseRequest'; import VerifyCard from './dto/VerifyCard'; -type VerifyCardRequest = { +type VerifyCardRequest = BaseRequest & { card: VerifyCard; paymentAuthenticationType: CardVerificationAuthType; verificationPrice: number; diff --git a/test/lib/Idempotency.test.js b/test/lib/Idempotency.test.js new file mode 100644 index 00000000..1f61fbda --- /dev/null +++ b/test/lib/Idempotency.test.js @@ -0,0 +1,182 @@ +const test = require('ava'); +const MockAdapter = require('axios-mock-adapter'); + +const utils = require('../../dist/lib/utils'); + +const originalGenerateRandomString = utils.generateRandomString; + +const { HttpClient, requestScopedConfig } = require('../../dist/lib/HttpClient'); + +const IDEMPOTENCY_KEY_HEADER_NAME = 'x-idempotency-key'; + +const newClient = () => + new HttpClient({ + apiKey: 'dummy', + secretKey: 'dummy', + baseUrl: 'http://localhost:8000' + }); + +const capture = (client, method, path) => { + const mock = new MockAdapter(client._client); + const seen = {}; + + mock[`on${method}`](path).reply(config => { + seen.headers = config.headers; + seen.data = config.data; + seen.params = config.params; + return [200, { data: 'ok' }]; + }); + + return seen; +}; + +test('post() sends the idempotency key from the body as a header', async t => { + const client = newClient(); + const seen = capture(client, 'Post', '/foo'); + + await client.post('/foo', { foo: 42, idempotencyKey: 'idempotency-key-1' }); + + t.is(seen.headers[IDEMPOTENCY_KEY_HEADER_NAME], 'idempotency-key-1'); +}); + +test('post() omits the header when no key is set', async t => { + const client = newClient(); + const seen = capture(client, 'Post', '/foo'); + + await client.post('/foo', { foo: 42 }); + + t.false(Object.prototype.hasOwnProperty.call(seen.headers, IDEMPOTENCY_KEY_HEADER_NAME)); +}); + +test('post() strips the key from the serialized body', async t => { + const client = newClient(); + const seen = capture(client, 'Post', '/foo'); + + await client.post('/foo', { foo: 42, idempotencyKey: 'idempotency-key-1' }); + + t.is(seen.data, JSON.stringify({ foo: 42 })); + t.false(seen.data.includes('idempotencyKey')); + t.false(seen.data.includes('idempotency-key-1')); +}); + +test('post() strips only the top-level key, leaving nested caller data untouched', async t => { + const client = newClient(); + const seen = capture(client, 'Post', '/foo'); + + await client.post('/foo', { + foo: 42, + idempotencyKey: 'idempotency-key-1', + additionalParams: { idempotencyKey: 'provider-side-key' } + }); + + t.is(seen.headers[IDEMPOTENCY_KEY_HEADER_NAME], 'idempotency-key-1'); + t.is(seen.data, JSON.stringify({ foo: 42, additionalParams: { idempotencyKey: 'provider-side-key' } })); + t.false(seen.data.includes('idempotency-key-1')); +}); + +test('post() signs the same body with and without a key', async t => { + utils.generateRandomString = () => 'foo'; + try { + const withKey = newClient(); + const seenWithKey = capture(withKey, 'Post', '/foo'); + await withKey.post('/foo', { foo: 42, idempotencyKey: 'idempotency-key-1' }); + + const withoutKey = newClient(); + const seenWithoutKey = capture(withoutKey, 'Post', '/foo'); + await withoutKey.post('/foo', { foo: 42 }); + + t.is(seenWithKey.headers['x-signature'], seenWithoutKey.headers['x-signature']); + t.is(seenWithKey.headers['x-signature'], '5PmVYuEmz1ueo49ta5QraJUrtUcDr0RKGwT+ZlmJqmM='); + } finally { + utils.generateRandomString = originalGenerateRandomString; + } +}); + +test('get() sends the key as a header and keeps it out of the query string', async t => { + const client = newClient(); + const seen = capture(client, 'Get', '/foo'); + + await client.get('/foo', { foo: 42, idempotencyKey: 'idempotency-key-1' }); + + t.is(seen.headers[IDEMPOTENCY_KEY_HEADER_NAME], 'idempotency-key-1'); + t.is(utils.serializeParams({ foo: 42, idempotencyKey: 'idempotency-key-1' }), 'foo=42'); +}); + +test('serializeParams omits the reserved key', t => { + t.is(utils.serializeParams({ idempotencyKey: 'idempotency-key-1' }), ''); + t.is(utils.serializeParams({ a: 1, idempotencyKey: 'idempotency-key-1', b: 2 }), 'a=1&b=2'); +}); + +test('get() signs the same URL with and without a key', async t => { + utils.generateRandomString = () => 'foo'; + try { + const withKey = newClient(); + const seenWithKey = capture(withKey, 'Get', '/foo'); + await withKey.get('/foo', { foo: 42, idempotencyKey: 'idempotency-key-1' }); + + const withoutKey = newClient(); + const seenWithoutKey = capture(withoutKey, 'Get', '/foo'); + await withoutKey.get('/foo', { foo: 42 }); + + t.is(seenWithKey.headers['x-signature'], seenWithoutKey.headers['x-signature']); + t.is(seenWithKey.headers['x-signature'], 'tf0w4o41UCEreJKeQZRHDmJlZr1K2IxG67dMZE5+0gc='); + } finally { + utils.generateRandomString = originalGenerateRandomString; + } +}); + +test('delete() with requestScopedConfig sends the header and no body', async t => { + const client = newClient(); + const seen = capture(client, 'Delete', '/foo'); + + await client.delete('/foo', undefined, requestScopedConfig({ idempotencyKey: 'idempotency-key-1' })); + + t.is(seen.headers[IDEMPOTENCY_KEY_HEADER_NAME], 'idempotency-key-1'); + t.is(typeof seen.data, 'undefined'); + t.is(typeof seen.params, 'undefined'); +}); + +test('delete() signature is unchanged by the key', async t => { + utils.generateRandomString = () => 'foo'; + try { + const withKey = newClient(); + const seenWithKey = capture(withKey, 'Delete', '/foo'); + await withKey.delete('/foo', undefined, requestScopedConfig({ idempotencyKey: 'idempotency-key-1' })); + + const withoutKey = newClient(); + const seenWithoutKey = capture(withoutKey, 'Delete', '/foo'); + await withoutKey.delete('/foo'); + + t.is(seenWithKey.headers['x-signature'], seenWithoutKey.headers['x-signature']); + } finally { + utils.generateRandomString = originalGenerateRandomString; + } +}); + +test('requestScopedConfig returns an empty config when no option is set', t => { + t.deepEqual(requestScopedConfig(undefined), {}); + t.deepEqual(requestScopedConfig({}), {}); + t.deepEqual(requestScopedConfig({ idempotencyKey: undefined }), {}); +}); + +test('the caller request object is not mutated, so it can be reused to retry', async t => { + const client = newClient(); + capture(client, 'Post', '/foo'); + + const request = { foo: 42, idempotencyKey: 'idempotency-key-1' }; + await client.post('/foo', request); + + t.is(request.idempotencyKey, 'idempotency-key-1'); + t.deepEqual(request, { foo: 42, idempotencyKey: 'idempotency-key-1' }); +}); + +test('a second call with the same object still sends the key', async t => { + const client = newClient(); + const seen = capture(client, 'Post', '/foo'); + const request = { foo: 42, idempotencyKey: 'idempotency-key-1' }; + + await client.post('/foo', request); + await client.post('/foo', request); + + t.is(seen.headers[IDEMPOTENCY_KEY_HEADER_NAME], 'idempotency-key-1'); +});