@tapsilat/tapsilat-js 1.0.7 → 2025.11.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -258,7 +258,7 @@ class InterceptorManager {
258
258
  try {
259
259
  return await interceptor(error, request);
260
260
  }
261
- catch (interceptorError) {
261
+ catch {
262
262
  // Continue to next interceptor if this one fails
263
263
  continue;
264
264
  }
@@ -365,15 +365,10 @@ class HttpClient {
365
365
  }
366
366
  }
367
367
  // Execute error interceptors as last resort
368
- try {
369
- return await this.interceptors.executeErrorInterceptors(lastError, {
370
- url: interceptedUrl,
371
- options: interceptedOptions,
372
- });
373
- }
374
- catch (finalError) {
375
- throw finalError;
376
- }
368
+ return this.interceptors.executeErrorInterceptors(lastError, {
369
+ url: interceptedUrl,
370
+ options: interceptedOptions,
371
+ });
377
372
  }
378
373
  /**
379
374
  * @category HTTP Client Internals
@@ -434,7 +429,7 @@ class HttpClient {
434
429
  responseData = await response.text();
435
430
  }
436
431
  }
437
- catch (parseError) {
432
+ catch {
438
433
  throw new TapsilatError("Failed to parse response body", "PARSE_ERROR");
439
434
  }
440
435
  // Handle successful responses
@@ -476,11 +471,12 @@ class HttpClient {
476
471
  return new TapsilatValidationError(errorMessage || "Invalid request data");
477
472
  case 422:
478
473
  return new TapsilatValidationError(errorMessage || "Validation failed", this.extractValidationDetails(data));
479
- case 429:
474
+ case 429: {
480
475
  const rateLimitInfo = this.extractRateLimitInfo(response);
481
476
  return new TapsilatRateLimitError(errorMessage || "Rate limit exceeded", rateLimitInfo.resetTime
482
477
  ? Math.floor((rateLimitInfo.resetTime.getTime() - Date.now()) / 1000)
483
478
  : undefined);
479
+ }
484
480
  case 404:
485
481
  return new TapsilatError(errorMessage || "Resource not found", "NOT_FOUND");
486
482
  case 500:
@@ -1017,6 +1013,186 @@ function sanitizeMetadata(metadata) {
1017
1013
  }
1018
1014
  return sanitized;
1019
1015
  }
1016
+ // GSM NUMBER VALIDATION
1017
+ // Summary: Validates and cleans Turkish GSM phone numbers
1018
+ // Description: Supports multiple phone number formats and automatically cleans formatting
1019
+ /**
1020
+ * Validates and cleans GSM phone numbers
1021
+ *
1022
+ * @summary Validates and cleans Turkish GSM phone numbers
1023
+ * @description
1024
+ * Supports multiple phone number formats including international (+90), national (0),
1025
+ * and local formats. Automatically removes formatting characters and validates
1026
+ * against Turkish mobile number patterns.
1027
+ *
1028
+ * Supported formats:
1029
+ * - +90 5XX XXX XX XX
1030
+ * - 0 5XX XXX XX XX
1031
+ * - 5XX XXX XX XX
1032
+ * - Various formatting with spaces, dashes, parentheses
1033
+ *
1034
+ * @param {string | number} gsmNumber - GSM number to validate and clean
1035
+ * @returns {GsmValidationResult} Validation result with cleaned number or error
1036
+ */
1037
+ function validateGsmNumber(gsmNumber) {
1038
+ const originalNumber = String(gsmNumber);
1039
+ // Basic validation
1040
+ if (!originalNumber || typeof originalNumber !== 'string') {
1041
+ return {
1042
+ isValid: false,
1043
+ error: "GSM number must be a non-empty string",
1044
+ originalNumber
1045
+ };
1046
+ }
1047
+ // Clean the number - remove all non-digit characters
1048
+ let cleanedNumber = originalNumber.replace(/[^\d]/g, '');
1049
+ // Handle different formats
1050
+ if (cleanedNumber.startsWith('90')) {
1051
+ // International format +90 or 90
1052
+ cleanedNumber = cleanedNumber.substring(2);
1053
+ }
1054
+ else if (cleanedNumber.startsWith('0')) {
1055
+ // National format 0
1056
+ cleanedNumber = cleanedNumber.substring(1);
1057
+ }
1058
+ // Validate Turkish mobile number pattern
1059
+ // Turkish mobile numbers start with 5 and are 10 digits total
1060
+ const turkishMobilePattern = /^5[0-9]{9}$/;
1061
+ if (!turkishMobilePattern.test(cleanedNumber)) {
1062
+ return {
1063
+ isValid: false,
1064
+ error: "Invalid Turkish GSM number format. Must be 10 digits starting with 5",
1065
+ originalNumber
1066
+ };
1067
+ }
1068
+ // Additional validation for known Turkish mobile operators
1069
+ const operatorPrefixes = ['50', '51', '52', '53', '54', '55', '56', '57', '58', '59'];
1070
+ const prefix = cleanedNumber.substring(0, 2);
1071
+ if (!operatorPrefixes.includes(prefix)) {
1072
+ return {
1073
+ isValid: false,
1074
+ error: "Invalid Turkish mobile operator prefix",
1075
+ originalNumber
1076
+ };
1077
+ }
1078
+ return {
1079
+ isValid: true,
1080
+ cleanedNumber: `+90${cleanedNumber}`,
1081
+ originalNumber
1082
+ };
1083
+ }
1084
+ // INSTALLMENTS VALIDATION
1085
+ // Summary: Validates installment values and converts to standardized format
1086
+ // Description: Handles various input formats and validates against business rules
1087
+ /**
1088
+ * Validates installment values and converts to standardized format
1089
+ *
1090
+ * @summary Validates installment values and converts to standardized format
1091
+ * @description
1092
+ * Handles various input formats (string, number, array) and validates against
1093
+ * business rules. Converts single installment values to arrays and validates
1094
+ * that installment numbers are within acceptable ranges.
1095
+ *
1096
+ * Supported inputs:
1097
+ * - Single number: 3 -> [3]
1098
+ * - Comma-separated string: "1,3,6" -> [1,3,6]
1099
+ * - Array of numbers: [1,3,6,12] -> [1,3,6,12]
1100
+ * - Empty/null values default to [1]
1101
+ *
1102
+ * @param {string | number | number[]} installments - Installment values to validate
1103
+ * @returns {InstallmentsValidationResult} Validation result with standardized array
1104
+ */
1105
+ function validateInstallments(installments) {
1106
+ const originalInput = installments;
1107
+ // Handle empty/null/undefined - default to single installment
1108
+ if (!installments || installments === '' || installments === null || installments === undefined || installments === 0) {
1109
+ return {
1110
+ isValid: true,
1111
+ validatedInstallments: [1],
1112
+ originalInput: String(originalInput)
1113
+ };
1114
+ }
1115
+ let installmentArray = [];
1116
+ try {
1117
+ if (typeof installments === 'number') {
1118
+ // Single number
1119
+ installmentArray = [installments];
1120
+ }
1121
+ else if (typeof installments === 'string') {
1122
+ // Handle comma-separated string
1123
+ if (installments.includes(',')) {
1124
+ installmentArray = installments
1125
+ .split(',')
1126
+ .map(item => {
1127
+ const num = parseInt(item.trim(), 10);
1128
+ if (isNaN(num)) {
1129
+ throw new Error(`Invalid installment value: ${item.trim()}`);
1130
+ }
1131
+ return num;
1132
+ });
1133
+ }
1134
+ else {
1135
+ // Single string number
1136
+ const num = parseInt(installments.trim(), 10);
1137
+ if (isNaN(num)) {
1138
+ throw new Error(`Invalid installment value: ${installments}`);
1139
+ }
1140
+ installmentArray = [num];
1141
+ }
1142
+ }
1143
+ else if (Array.isArray(installments)) {
1144
+ // Array of numbers
1145
+ installmentArray = installments.map((item, index) => {
1146
+ if (typeof item !== 'number' || isNaN(item)) {
1147
+ throw new Error(`Invalid installment value at index ${index}: ${item}`);
1148
+ }
1149
+ return item;
1150
+ });
1151
+ }
1152
+ else {
1153
+ return {
1154
+ isValid: false,
1155
+ validatedInstallments: [1],
1156
+ error: "Installments must be a number, string, or array of numbers",
1157
+ originalInput: String(originalInput)
1158
+ };
1159
+ }
1160
+ // Validate installment values
1161
+ for (const installment of installmentArray) {
1162
+ if (!Number.isInteger(installment) || installment < 1) {
1163
+ return {
1164
+ isValid: false,
1165
+ validatedInstallments: [1],
1166
+ error: `Installment values must be positive integers, got: ${installment}`,
1167
+ originalInput: String(originalInput)
1168
+ };
1169
+ }
1170
+ if (installment > 36) {
1171
+ return {
1172
+ isValid: false,
1173
+ validatedInstallments: [1],
1174
+ error: `Installment values cannot exceed 36, got: ${installment}`,
1175
+ originalInput: String(originalInput)
1176
+ };
1177
+ }
1178
+ }
1179
+ // Remove duplicates and sort
1180
+ const uniqueInstallments = [...new Set(installmentArray)].sort((a, b) => a - b);
1181
+ return {
1182
+ isValid: true,
1183
+ validatedInstallments: uniqueInstallments,
1184
+ originalInput: String(originalInput)
1185
+ };
1186
+ }
1187
+ catch (error) {
1188
+ return {
1189
+ isValid: false,
1190
+ validatedInstallments: [1],
1191
+ error: error instanceof Error ? error.message : "Unknown validation error",
1192
+ originalInput: String(originalInput)
1193
+ };
1194
+ }
1195
+ }
1020
1196
 
1021
1197
  /**
1022
1198
  * @category Configuration
@@ -1213,7 +1389,7 @@ class TapsilatSDK {
1213
1389
  *
1214
1390
  * @param {TapsilatConfig} config - SDK configuration options
1215
1391
  * @param {string} config.bearerToken - API authentication token (required)
1216
- * @param {string} [config.baseURL='https://api.tapsilat.com/v1'] - API base URL
1392
+ * @param {string} [config.baseURL='https://panel.tapsilat.dev/v1'] - API base URL
1217
1393
  * @param {number} [config.timeout=30000] - Request timeout in milliseconds
1218
1394
  * @param {number} [config.maxRetries=3] - Maximum number of retry attempts
1219
1395
  * @param {number} [config.retryDelay=1000] - Delay between retries in milliseconds
@@ -1234,71 +1410,65 @@ class TapsilatSDK {
1234
1410
  /**
1235
1411
  * Creates a new order and returns a checkout URL
1236
1412
  *
1237
- * @summary Initiates a new payment order with buyer information and generates checkout URL
1413
+ * @summary Initiates a new payment order with comprehensive order details
1238
1414
  * @description
1239
1415
  * Creates a new payment order in the Tapsilat system with the provided order details.
1240
1416
  * This method performs comprehensive validation of all input parameters, creates the order
1241
- * on the payment platform, and returns a checkout URL that customers can use to complete
1242
- * their payment. The method supports multiple currencies, locales, and comprehensive
1243
- * buyer information for compliance and fraud prevention.
1417
+ * on the payment platform, and returns order identifiers including reference_id and order_id.
1418
+ * The method supports multiple currencies, locales, payment options, basket items,
1419
+ * and comprehensive buyer information for compliance and fraud prevention.
1244
1420
  *
1245
- * The returned checkout URL is valid for a limited time (typically 24 hours) and should
1246
- * be presented to the customer immediately. The order status can be tracked using the
1247
- * returned reference ID through the getOrderStatus method.
1421
+ * The returned order_id and reference_id can be used to track order status through
1422
+ * the getOrderStatus method.
1248
1423
  *
1249
1424
  * @param {OrderCreateRequest} orderRequest - Complete order information
1250
1425
  * @param {number} orderRequest.amount - Payment amount (must be positive, max 2 decimal places)
1426
+ * @param {number} [orderRequest.tax_amount] - Tax amount included in total
1251
1427
  * @param {Currency} orderRequest.currency - Payment currency ('TRY', 'USD', 'EUR', 'GBP')
1252
1428
  * @param {Locale} orderRequest.locale - Display language ('tr' for Turkish, 'en' for English)
1429
+ * @param {boolean} [orderRequest.three_d_force] - Force 3D Secure authentication
1430
+ * @param {Address} [orderRequest.shipping_address] - Shipping address for delivery
1431
+ * @param {BasketItem[]} orderRequest.basket_items - Array of items in the order
1432
+ * @param {BillingAddress} orderRequest.billing_address - Billing address with tax information
1253
1433
  * @param {Buyer} orderRequest.buyer - Customer information for payment processing
1254
- * @param {string} orderRequest.buyer.name - Customer's first name (required)
1255
- * @param {string} orderRequest.buyer.surname - Customer's last name (required)
1256
- * @param {string} orderRequest.buyer.email - Customer's email address (required, validated)
1257
- * @param {string} [orderRequest.buyer.phone] - Customer's phone number
1258
- * @param {string} [orderRequest.buyer.identityNumber] - National ID or tax number
1259
- * @param {Address} [orderRequest.buyer.shippingAddress] - Shipping address for physical goods
1260
- * @param {Address} [orderRequest.buyer.billingAddress] - Billing address for invoicing
1261
- * @param {string} [orderRequest.description] - Order description for customer reference
1262
- * @param {string} [orderRequest.callbackUrl] - URL to redirect after payment completion
1263
- * @param {string} [orderRequest.conversationId] - Custom tracking ID for your system
1434
+ * @param {string} [orderRequest.conversation_id] - Custom tracking ID for your system
1435
+ * @param {boolean} [orderRequest.partial_payment] - Enable partial payment
1436
+ * @param {boolean} [orderRequest.payment_methods] - Enable payment method selection
1437
+ * @param {PaymentOption[]} [orderRequest.payment_options] - Available payment options
1438
+ * @param {string} [orderRequest.payment_success_url] - URL to redirect after successful payment
1439
+ * @param {string} [orderRequest.payment_failure_url] - URL to redirect after failed payment
1440
+ * @param {number[]} [orderRequest.enabled_installments] - Allowed installment counts
1264
1441
  * @param {Record<string, unknown>} [orderRequest.metadata] - Additional custom data
1265
1442
  *
1266
1443
  * @returns {Promise<OrderCreateResponse>} Promise resolving to order creation response
1267
- * @returns {string} OrderCreateResponse.referenceId - Unique order identifier for tracking
1268
- * @returns {string} OrderCreateResponse.conversationId - Echo of provided conversation ID
1269
- * @returns {string} OrderCreateResponse.checkoutUrl - Payment page URL for customer
1270
- * @returns {string} OrderCreateResponse.status - Initial order status (typically 'CREATED')
1271
- * @returns {string} [OrderCreateResponse.qrCodeUrl] - QR code URL for mobile payments
1444
+ * @returns {string} OrderCreateResponse.order_id - Internal order identifier
1445
+ * @returns {string} OrderCreateResponse.reference_id - Unique order reference for tracking
1446
+ * @returns {string} [OrderCreateResponse.checkout_url] - Payment page URL for customer
1447
+ * @returns {string} [OrderCreateResponse.conversation_id] - Echo of provided conversation ID
1448
+ * @returns {string} [OrderCreateResponse.status] - Initial order status
1449
+ * @returns {string} [OrderCreateResponse.qr_code_url] - QR code URL for mobile payments
1272
1450
  *
1273
1451
  * @throws {TapsilatValidationError} When input validation fails:
1274
1452
  * - Amount is not positive or has more than 2 decimal places
1275
1453
  * - Currency is not supported
1276
1454
  * - Buyer information is incomplete or invalid
1277
- * - Email format is invalid
1455
+ * - Basket items are missing or invalid
1456
+ * - Billing address is missing
1278
1457
  * - Required fields are missing
1279
- * @throws {TapsilatNetworkError} When network request fails:
1280
- * - Connection timeout
1281
- * - DNS resolution failure
1282
- * - Network connectivity issues
1283
- * @throws {TapsilatError} When API returns business logic errors:
1284
- * - Insufficient merchant balance
1285
- * - Currency not enabled for merchant
1286
- * - Buyer blocked due to fraud detection
1287
- * - Rate limiting exceeded
1458
+ * @throws {TapsilatNetworkError} When network request fails
1459
+ * @throws {TapsilatError} When API returns business logic errors
1288
1460
  */
1289
1461
  async createOrder(orderRequest) {
1290
- // Validate the order request directly
1291
- // Check if request is null/undefined
1462
+ // Validate the order request
1292
1463
  if (!orderRequest) {
1293
1464
  throw new TapsilatValidationError("Order request cannot be null or undefined");
1294
1465
  }
1295
- // Validate amount - check if positive
1466
+ // Validate amount
1296
1467
  if (!isPositiveNumber(orderRequest.amount)) {
1297
1468
  throw new TapsilatValidationError("Amount must be a positive number", {
1298
1469
  provided: orderRequest.amount,
1299
1470
  });
1300
1471
  }
1301
- // Validate amount - check decimal places
1302
1472
  if (!hasValidDecimalPlaces(orderRequest.amount)) {
1303
1473
  throw new TapsilatValidationError("Amount must have maximum 2 decimal places", { provided: orderRequest.amount });
1304
1474
  }
@@ -1306,6 +1476,10 @@ class TapsilatSDK {
1306
1476
  if (!isNonEmptyString(orderRequest.currency)) {
1307
1477
  throw new TapsilatValidationError("Currency is required and must be a non-empty string", { provided: orderRequest.currency });
1308
1478
  }
1479
+ // Validate locale
1480
+ if (!isNonEmptyString(orderRequest.locale)) {
1481
+ throw new TapsilatValidationError("Locale is required and must be a non-empty string", { provided: orderRequest.locale });
1482
+ }
1309
1483
  // Validate buyer information
1310
1484
  if (!orderRequest.buyer) {
1311
1485
  throw new TapsilatValidationError("Buyer information is required");
@@ -1317,14 +1491,20 @@ class TapsilatSDK {
1317
1491
  if (!isNonEmptyString(buyer.surname)) {
1318
1492
  throw new TapsilatValidationError("Buyer surname is required and must be a non-empty string", { provided: buyer.surname });
1319
1493
  }
1320
- // Validate buyer email - check if provided
1321
1494
  if (!isNonEmptyString(buyer.email)) {
1322
1495
  throw new TapsilatValidationError("Buyer email is required and must be a non-empty string", { provided: buyer.email });
1323
1496
  }
1324
- // Validate buyer email - check format
1325
1497
  if (!isValidEmail(buyer.email)) {
1326
1498
  throw new TapsilatValidationError("Buyer email must be a valid email address", { provided: buyer.email });
1327
1499
  }
1500
+ // Validate basket items
1501
+ if (!orderRequest.basket_items || !Array.isArray(orderRequest.basket_items) || orderRequest.basket_items.length === 0) {
1502
+ throw new TapsilatValidationError("Basket items are required and must be a non-empty array");
1503
+ }
1504
+ // Validate billing address
1505
+ if (!orderRequest.billing_address) {
1506
+ throw new TapsilatValidationError("Billing address is required");
1507
+ }
1328
1508
  try {
1329
1509
  // Make the API request
1330
1510
  const createOrderResponse = await this.httpClient.post("/order/create", orderRequest);
@@ -1764,7 +1944,261 @@ class TapsilatSDK {
1764
1944
  getConfigManager() {
1765
1945
  return this.configManager;
1766
1946
  }
1947
+ // PAYMENT TERM MANAGEMENT
1948
+ // Summary: Create, update, delete, and manage payment terms for orders
1949
+ // Description: Full lifecycle management of payment terms including installments and refunds
1950
+ /**
1951
+ * Creates a new payment term for an existing order
1952
+ *
1953
+ * @summary Create payment term for installment or partial payment
1954
+ * @description
1955
+ * Creates a new payment term for an existing order, enabling installment payments
1956
+ * or partial payment collection. Payment terms allow splitting order amounts
1957
+ * across multiple payments with specific due dates and requirements.
1958
+ *
1959
+ * @param {OrderPaymentTermCreateDTO} termData - Payment term creation data
1960
+ * @param {string} termData.order_id - Reference ID of the existing order
1961
+ * @param {string} termData.term_reference_id - Unique identifier for this payment term
1962
+ * @param {number} termData.amount - Amount for this payment term
1963
+ * @param {string} termData.due_date - Due date for this payment (ISO 8601 format)
1964
+ * @param {number} termData.term_sequence - Sequence number for this term
1965
+ * @param {boolean} termData.required - Whether this payment term is required
1966
+ * @param {string} termData.status - Initial status of the payment term
1967
+ * @param {string} [termData.data] - Additional metadata for the term
1968
+ * @param {string} [termData.paid_date] - Date when payment was completed
1969
+ *
1970
+ * @returns {Promise<PaymentTermResponse>} Promise resolving to created payment term details
1971
+ * @throws {TapsilatValidationError} When input validation fails
1972
+ * @throws {TapsilatError} When API returns an error response
1973
+ */
1974
+ async createOrderTerm(termData) {
1975
+ // Validate required fields
1976
+ if (!isNonEmptyString(termData.order_id)) {
1977
+ throw new TapsilatValidationError("Order ID is required and must be a non-empty string", { provided: termData.order_id });
1978
+ }
1979
+ if (!isNonEmptyString(termData.term_reference_id)) {
1980
+ throw new TapsilatValidationError("Term reference ID is required and must be a non-empty string", { provided: termData.term_reference_id });
1981
+ }
1982
+ if (!isPositiveNumber(termData.amount)) {
1983
+ throw new TapsilatValidationError("Amount must be a positive number", {
1984
+ provided: termData.amount,
1985
+ });
1986
+ }
1987
+ if (!hasValidDecimalPlaces(termData.amount)) {
1988
+ throw new TapsilatValidationError("Amount must have maximum 2 decimal places", { provided: termData.amount });
1989
+ }
1990
+ if (!isNonEmptyString(termData.due_date)) {
1991
+ throw new TapsilatValidationError("Due date is required and must be a non-empty string", { provided: termData.due_date });
1992
+ }
1993
+ if (!isInteger(termData.term_sequence)) {
1994
+ throw new TapsilatValidationError("Term sequence must be an integer", {
1995
+ provided: termData.term_sequence,
1996
+ });
1997
+ }
1998
+ if (typeof termData.required !== "boolean") {
1999
+ throw new TapsilatValidationError("Required field must be a boolean", {
2000
+ provided: termData.required,
2001
+ });
2002
+ }
2003
+ if (!isNonEmptyString(termData.status)) {
2004
+ throw new TapsilatValidationError("Status is required and must be a non-empty string", { provided: termData.status });
2005
+ }
2006
+ try {
2007
+ const createTermResponse = await this.httpClient.post("/order/term/create", termData);
2008
+ return handleResponse(createTermResponse, "Payment term creation");
2009
+ }
2010
+ catch (error) {
2011
+ return handleError(error, "payment term creation");
2012
+ }
2013
+ }
2014
+ /**
2015
+ * Updates an existing payment term
2016
+ *
2017
+ * @summary Update payment term details
2018
+ * @description
2019
+ * Updates an existing payment term with new information such as amount,
2020
+ * due date, status, or other metadata. This allows for flexible management
2021
+ * of installment payments and payment schedules.
2022
+ *
2023
+ * @param {OrderPaymentTermUpdateDTO} updateData - Payment term update data
2024
+ * @param {string} updateData.term_reference_id - Reference ID of the term to update
2025
+ * @param {number} [updateData.amount] - New amount for the payment term
2026
+ * @param {string} [updateData.due_date] - New due date (ISO 8601 format)
2027
+ * @param {string} [updateData.paid_date] - Date when payment was completed
2028
+ * @param {boolean} [updateData.required] - Whether this payment term is required
2029
+ * @param {string} [updateData.status] - New status of the payment term
2030
+ * @param {number} [updateData.term_sequence] - New sequence number
2031
+ *
2032
+ * @returns {Promise<PaymentTermResponse>} Promise resolving to updated payment term details
2033
+ * @throws {TapsilatValidationError} When input validation fails
2034
+ * @throws {TapsilatError} When API returns an error response
2035
+ */
2036
+ async updateOrderTerm(updateData) {
2037
+ // Validate required fields
2038
+ if (!isNonEmptyString(updateData.term_reference_id)) {
2039
+ throw new TapsilatValidationError("Term reference ID is required and must be a non-empty string", { provided: updateData.term_reference_id });
2040
+ }
2041
+ // Validate optional amount if provided
2042
+ if (updateData.amount !== undefined) {
2043
+ if (!isPositiveNumber(updateData.amount)) {
2044
+ throw new TapsilatValidationError("Amount must be a positive number", {
2045
+ provided: updateData.amount,
2046
+ });
2047
+ }
2048
+ if (!hasValidDecimalPlaces(updateData.amount)) {
2049
+ throw new TapsilatValidationError("Amount must have maximum 2 decimal places", { provided: updateData.amount });
2050
+ }
2051
+ }
2052
+ // Validate optional term sequence if provided
2053
+ if (updateData.term_sequence !== undefined) {
2054
+ if (!isInteger(updateData.term_sequence)) {
2055
+ throw new TapsilatValidationError("Term sequence must be an integer", {
2056
+ provided: updateData.term_sequence,
2057
+ });
2058
+ }
2059
+ }
2060
+ // Validate optional required field if provided
2061
+ if (updateData.required !== undefined &&
2062
+ typeof updateData.required !== "boolean") {
2063
+ throw new TapsilatValidationError("Required field must be a boolean", {
2064
+ provided: updateData.required,
2065
+ });
2066
+ }
2067
+ try {
2068
+ const updateTermResponse = await this.httpClient.post("/order/term/update", updateData);
2069
+ return handleResponse(updateTermResponse, "Payment term update");
2070
+ }
2071
+ catch (error) {
2072
+ return handleError(error, "payment term update");
2073
+ }
2074
+ }
2075
+ /**
2076
+ * Deletes a payment term
2077
+ *
2078
+ * @summary Delete payment term
2079
+ * @description
2080
+ * Permanently deletes a payment term from an order. This action cannot be undone.
2081
+ * Only unpaid payment terms can be deleted.
2082
+ *
2083
+ * @param {PaymentTermDeleteRequest} deleteData - Payment term deletion data
2084
+ * @param {string} deleteData.term_reference_id - Reference ID of the term to delete
2085
+ *
2086
+ * @returns {Promise<PaymentTermResponse>} Promise resolving to deleted payment term details
2087
+ * @throws {TapsilatValidationError} When input validation fails
2088
+ * @throws {TapsilatError} When API returns an error response
2089
+ */
2090
+ async deleteOrderTerm(deleteData) {
2091
+ // Validate required fields
2092
+ if (!isNonEmptyString(deleteData.term_reference_id)) {
2093
+ throw new TapsilatValidationError("Term reference ID is required and must be a non-empty string", { provided: deleteData.term_reference_id });
2094
+ }
2095
+ try {
2096
+ const deleteTermResponse = await this.httpClient.post("/order/term/delete", deleteData);
2097
+ return handleResponse(deleteTermResponse, "Payment term deletion");
2098
+ }
2099
+ catch (error) {
2100
+ return handleError(error, "payment term deletion");
2101
+ }
2102
+ }
2103
+ /**
2104
+ * Refunds a specific payment term
2105
+ *
2106
+ * @summary Refund payment term
2107
+ * @description
2108
+ * Processes a refund for a specific payment term. This allows partial refunds
2109
+ * at the payment term level rather than the entire order level.
2110
+ *
2111
+ * @param {OrderTermRefundRequest} refundData - Payment term refund data
2112
+ * @param {string} refundData.term_id - ID of the term to refund
2113
+ * @param {number} refundData.amount - Amount to refund
2114
+ * @param {string} [refundData.reference_id] - Optional reference ID
2115
+ * @param {string} [refundData.term_payment_id] - Optional term payment ID
2116
+ *
2117
+ * @returns {Promise<PaymentTermRefundResponse>} Promise resolving to refund details
2118
+ * @throws {TapsilatValidationError} When input validation fails
2119
+ * @throws {TapsilatError} When API returns an error response
2120
+ */
2121
+ async refundOrderTerm(refundData) {
2122
+ // Validate required fields
2123
+ if (!isNonEmptyString(refundData.term_id)) {
2124
+ throw new TapsilatValidationError("Term ID is required and must be a non-empty string", { provided: refundData.term_id });
2125
+ }
2126
+ if (!isPositiveNumber(refundData.amount)) {
2127
+ throw new TapsilatValidationError("Amount must be a positive number", {
2128
+ provided: refundData.amount,
2129
+ });
2130
+ }
2131
+ if (!hasValidDecimalPlaces(refundData.amount)) {
2132
+ throw new TapsilatValidationError("Amount must have maximum 2 decimal places", { provided: refundData.amount });
2133
+ }
2134
+ try {
2135
+ const refundTermResponse = await this.httpClient.post("/order/term/refund", refundData);
2136
+ return handleResponse(refundTermResponse, "Payment term refund");
2137
+ }
2138
+ catch (error) {
2139
+ return handleError(error, "payment term refund");
2140
+ }
2141
+ }
2142
+ /**
2143
+ * Terminates a payment term
2144
+ *
2145
+ * @summary Terminate payment term
2146
+ * @description
2147
+ * Terminates an active payment term, preventing further payments.
2148
+ * This is useful for canceling installment plans or payment schedules.
2149
+ *
2150
+ * @param {PaymentTermTerminateRequest} terminateData - Payment term termination data
2151
+ * @param {string} terminateData.term_reference_id - Reference ID of the term to terminate
2152
+ * @param {string} [terminateData.reason] - Optional reason for termination
2153
+ *
2154
+ * @returns {Promise<PaymentTermResponse>} Promise resolving to terminated term details
2155
+ * @throws {TapsilatValidationError} When input validation fails
2156
+ * @throws {TapsilatError} When API returns an error response
2157
+ */
2158
+ async terminateOrderTerm(terminateData) {
2159
+ // Validate required fields
2160
+ if (!isNonEmptyString(terminateData.term_reference_id)) {
2161
+ throw new TapsilatValidationError("Term reference ID is required and must be a non-empty string", { provided: terminateData.term_reference_id });
2162
+ }
2163
+ try {
2164
+ const terminateTermResponse = await this.httpClient.post("/order/term/terminate", terminateData);
2165
+ return handleResponse(terminateTermResponse, "Payment term termination");
2166
+ }
2167
+ catch (error) {
2168
+ return handleError(error, "payment term termination");
2169
+ }
2170
+ }
2171
+ /**
2172
+ * Terminates an entire order
2173
+ *
2174
+ * @summary Terminate order
2175
+ * @description
2176
+ * Terminates an entire order, canceling all associated payment terms and
2177
+ * preventing any further payment processing. This is a more comprehensive
2178
+ * action than canceling individual payment terms.
2179
+ *
2180
+ * @param {OrderTerminateRequest} terminateData - Order termination data
2181
+ * @param {string} terminateData.reference_id - Reference ID of the order to terminate
2182
+ * @param {string} [terminateData.reason] - Optional reason for termination
2183
+ *
2184
+ * @returns {Promise<OrderTerminateResponse>} Promise resolving to terminated order details
2185
+ * @throws {TapsilatValidationError} When input validation fails
2186
+ * @throws {TapsilatError} When API returns an error response
2187
+ */
2188
+ async terminateOrder(terminateData) {
2189
+ // Validate required fields
2190
+ if (!isNonEmptyString(terminateData.reference_id)) {
2191
+ throw new TapsilatValidationError("Reference ID is required and must be a non-empty string", { provided: terminateData.reference_id });
2192
+ }
2193
+ try {
2194
+ const terminateOrderResponse = await this.httpClient.post("/order/terminate", terminateData);
2195
+ return handleResponse(terminateOrderResponse, "Order termination");
2196
+ }
2197
+ catch (error) {
2198
+ return handleError(error, "order termination");
2199
+ }
2200
+ }
1767
2201
  }
1768
2202
 
1769
- export { ConfigManager, TapsilatAuthenticationError, TapsilatError, TapsilatNetworkError, TapsilatRateLimitError, TapsilatSDK, TapsilatValidationError, isValidCurrency, isValidPaymentMethod, isValidUrl, sanitizeMetadata, validateEmail, validatePaymentRequest };
2203
+ export { ConfigManager, TapsilatAuthenticationError, TapsilatError, TapsilatNetworkError, TapsilatRateLimitError, TapsilatSDK, TapsilatValidationError, isValidCurrency, isValidPaymentMethod, isValidUrl, sanitizeMetadata, validateEmail, validateGsmNumber, validateInstallments, validatePaymentRequest };
1770
2204
  //# sourceMappingURL=index.esm.js.map