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