@waffo/waffo-node 2.1.0 → 2.3.0

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
@@ -463,7 +463,7 @@ var HEADER_SDK_VERSION = "x-sdk-version";
463
463
  var HEADER_CONTENT_TYPE = "content-type";
464
464
  var CONTENT_TYPE_JSON = "application/json";
465
465
  var API_VERSION = "1.0.0";
466
- var SDK_VERSION = "waffo-node/2.1.0";
466
+ var SDK_VERSION = "waffo-node/2.3.0";
467
467
  var WaffoHttpClient = class {
468
468
  baseUrl;
469
469
  apiKey;
@@ -595,10 +595,17 @@ var WaffoHttpClient = class {
595
595
  injectMerchantIdIfNeeded(request) {
596
596
  if (!this.merchantId) return;
597
597
  const req = request;
598
- if (typeof req.merchantInfo === "object" && req.merchantInfo !== null && !("merchantId" in req.merchantInfo && req.merchantInfo.merchantId)) {
599
- req.merchantInfo.merchantId = this.merchantId;
600
- } else if ("merchantId" in req && !req.merchantId) {
601
- req.merchantId = this.merchantId;
598
+ if (typeof req.merchantInfo === "object" && req.merchantInfo !== null) {
599
+ const info = req.merchantInfo;
600
+ if (!info.merchantId) {
601
+ info.merchantId = this.merchantId;
602
+ }
603
+ } else if ("merchantId" in req) {
604
+ if (!req.merchantId) {
605
+ req.merchantId = this.merchantId;
606
+ }
607
+ } else {
608
+ req.merchantInfo = { merchantId: this.merchantId };
602
609
  }
603
610
  }
604
611
  /**
@@ -616,7 +623,6 @@ var WebhookEventType = /* @__PURE__ */ ((WebhookEventType2) => {
616
623
  WebhookEventType2["PAYMENT_NOTIFICATION"] = "PAYMENT_NOTIFICATION";
617
624
  WebhookEventType2["REFUND_NOTIFICATION"] = "REFUND_NOTIFICATION";
618
625
  WebhookEventType2["SUBSCRIPTION_STATUS_NOTIFICATION"] = "SUBSCRIPTION_STATUS_NOTIFICATION";
619
- WebhookEventType2["SUBSCRIPTION_PAYMENT_NOTIFICATION"] = "SUBSCRIPTION_PAYMENT_NOTIFICATION";
620
626
  WebhookEventType2["SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION"] = "SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION";
621
627
  return WebhookEventType2;
622
628
  })(WebhookEventType || {});
@@ -656,7 +662,8 @@ var WebhookHandler = class {
656
662
  return this;
657
663
  }
658
664
  /**
659
- * Registers a handler for subscription payment notifications.
665
+ * Registers a fallback handler for SUBSCRIPTION_STATUS_NOTIFICATION events.
666
+ * Only called when onSubscriptionStatus handler is not registered.
660
667
  */
661
668
  onSubscriptionPayment(handler) {
662
669
  this.subscriptionPaymentHandler = handler;
@@ -703,10 +710,7 @@ var WebhookHandler = class {
703
710
  case "SUBSCRIPTION_STATUS_NOTIFICATION" /* SUBSCRIPTION_STATUS_NOTIFICATION */:
704
711
  if (this.subscriptionStatusHandler) {
705
712
  await this.subscriptionStatusHandler(parsed);
706
- }
707
- break;
708
- case "SUBSCRIPTION_PAYMENT_NOTIFICATION" /* SUBSCRIPTION_PAYMENT_NOTIFICATION */:
709
- if (this.subscriptionPaymentHandler) {
713
+ } else if (this.subscriptionPaymentHandler) {
710
714
  await this.subscriptionPaymentHandler(parsed);
711
715
  }
712
716
  break;
@@ -791,6 +795,15 @@ var BaseResource = class {
791
795
  }
792
796
  };
793
797
 
798
+ // src/utils/time-utils.ts
799
+ function formatTimestamp(date) {
800
+ const isoString = date.toISOString();
801
+ return isoString;
802
+ }
803
+ function getCurrentTimestamp() {
804
+ return formatTimestamp(/* @__PURE__ */ new Date());
805
+ }
806
+
794
807
  // src/resources/order-resource.ts
795
808
  var OrderResource = class _OrderResource extends BaseResource {
796
809
  static PATH_CREATE = "/create";
@@ -807,6 +820,9 @@ var OrderResource = class _OrderResource extends BaseResource {
807
820
  * @throws WaffoUnknownStatusError for network errors
808
821
  */
809
822
  async create(params, options) {
823
+ if (!params.orderRequestedAt) {
824
+ params.orderRequestedAt = getCurrentTimestamp();
825
+ }
810
826
  return this.httpClient.post(
811
827
  this.getPath(_OrderResource.PATH_CREATE),
812
828
  params,
@@ -837,6 +853,9 @@ var OrderResource = class _OrderResource extends BaseResource {
837
853
  * @throws WaffoUnknownStatusError for network errors
838
854
  */
839
855
  async cancel(params, options) {
856
+ if (!params.orderRequestedAt) {
857
+ params.orderRequestedAt = getCurrentTimestamp();
858
+ }
840
859
  return this.httpClient.post(
841
860
  this.getPath(_OrderResource.PATH_CANCEL),
842
861
  params,
@@ -892,6 +911,9 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
892
911
  * @throws WaffoUnknownStatusError for network errors
893
912
  */
894
913
  async create(params, options) {
914
+ if (!params.requestedAt) {
915
+ params.requestedAt = getCurrentTimestamp();
916
+ }
895
917
  return this.httpClient.post(
896
918
  this.getPath(_SubscriptionResource.PATH_CREATE),
897
919
  params,
@@ -922,6 +944,9 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
922
944
  * @throws WaffoUnknownStatusError for network errors
923
945
  */
924
946
  async cancel(params, options) {
947
+ if (!params.requestedAt) {
948
+ params.requestedAt = getCurrentTimestamp();
949
+ }
925
950
  return this.httpClient.post(
926
951
  this.getPath(_SubscriptionResource.PATH_CANCEL),
927
952
  params,
@@ -985,6 +1010,9 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
985
1010
  * ```
986
1011
  */
987
1012
  async change(params, options) {
1013
+ if (!params.requestedAt) {
1014
+ params.requestedAt = getCurrentTimestamp();
1015
+ }
988
1016
  return this.httpClient.post(
989
1017
  this.getPath(_SubscriptionResource.PATH_CHANGE),
990
1018
  params,
@@ -1193,13 +1221,13 @@ var Waffo = class _Waffo {
1193
1221
  * // Setup webhook handler
1194
1222
  * const handler = waffo.webhook()
1195
1223
  * .onPayment((notification) => {
1196
- * console.log('Payment:', notification.orderStatus);
1224
+ * console.log('Payment:', notification.result?.orderStatus);
1197
1225
  * })
1198
1226
  * .onRefund((notification) => {
1199
- * console.log('Refund:', notification.refundStatus);
1227
+ * console.log('Refund:', notification.result?.refundStatus);
1200
1228
  * })
1201
1229
  * .onSubscriptionStatus((notification) => {
1202
- * console.log('Subscription:', notification.subscriptionStatus);
1230
+ * console.log('Subscription:', notification.result?.subscriptionStatus);
1203
1231
  * });
1204
1232
  *
1205
1233
  * // In Express.js route handler
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/config/environment.ts","../src/errors/waffo-error.ts","../src/errors/waffo-unknown-status-error.ts","../src/utils/rsa-utils.ts","../src/types/config/waffo-config.ts","../src/types/api-response.ts","../src/net/default-http-transport.ts","../src/core/waffo-http-client.ts","../src/core/webhook-handler.ts","../src/resources/base-resource.ts","../src/resources/order-resource.ts","../src/resources/subscription-resource.ts","../src/resources/refund-resource.ts","../src/resources/merchant-config-resource.ts","../src/resources/pay-method-config-resource.ts","../src/waffo.ts"],"names":["Environment","crypto","WebhookEventType"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Waffo API environment.\n */\nexport enum Environment {\n /** Sandbox environment for testing */\n SANDBOX = 'SANDBOX',\n /** Production environment for live transactions */\n PRODUCTION = 'PRODUCTION',\n}\n\n/**\n * Base URLs for each environment.\n */\nexport const EnvironmentBaseUrl: Record<Environment, string> = {\n [Environment.SANDBOX]: 'https://api-sandbox.waffo.com/api/v1',\n [Environment.PRODUCTION]: 'https://api.waffo.com/api/v1',\n};\n","/**\n * Base error class for client-side errors in the Waffo SDK.\n *\n * This error is thrown for configuration errors, serialization failures,\n * signature errors, and other client-side issues.\n *\n * @example\n * ```typescript\n * try {\n * const response = await waffo.order().create(params);\n * } catch (error) {\n * if (error instanceof WaffoError) {\n * console.error(`Error [${error.errorCode}]: ${error.message}`);\n * }\n * }\n * ```\n */\nexport class WaffoError extends Error {\n /** Error code identifying the type of error */\n readonly errorCode: string;\n\n /** The underlying error that caused this error, if any */\n readonly cause?: Error;\n\n /**\n * Creates a new WaffoError.\n *\n * @param errorCode - The error code (e.g., \"S0003\" for signing failure)\n * @param message - Human-readable error message\n * @param cause - The underlying error that caused this error\n */\n constructor(errorCode: string, message: string, cause?: Error) {\n super(message);\n this.name = 'WaffoError';\n this.errorCode = errorCode;\n this.cause = cause;\n\n // Maintains proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, WaffoError);\n }\n }\n\n /**\n * Returns a string representation of the error.\n */\n override toString(): string {\n return `[${this.errorCode}] ${this.message}`;\n }\n}\n\n/**\n * Error codes used by WaffoError.\n */\nexport const WaffoErrorCode = {\n /** Invalid public key */\n INVALID_PUBLIC_KEY: 'S0002',\n /** Failed to sign data */\n SIGN_FAILED: 'S0003',\n /** Response signature verification failed */\n VERIFY_FAILED: 'S0004',\n /** Request serialization failed */\n SERIALIZE_FAILED: 'S0005',\n /** Unexpected error */\n UNEXPECTED: 'S0006',\n /** Invalid private key */\n INVALID_PRIVATE_KEY: 'S0007',\n} as const;\n","/**\n * Error thrown when the payment status is unknown due to network errors\n * or server issues.\n *\n * **IMPORTANT**: When this error is thrown for a payment request,\n * you MUST NOT assume the payment failed. The payment may have been processed\n * successfully. Always use the inquiry API to check the actual payment status.\n *\n * @example\n * ```typescript\n * try {\n * const response = await waffo.order().create(params);\n * } catch (error) {\n * if (error instanceof WaffoUnknownStatusError) {\n * // Payment may have been processed - check status\n * const inquiry = await waffo.order().inquiry({\n * paymentRequestId: params.paymentRequestId\n * });\n * // Handle based on inquiry result\n * }\n * }\n * ```\n */\nexport class WaffoUnknownStatusError extends Error {\n /** Error code for network errors */\n static readonly CODE_NETWORK_ERROR = 'S0001';\n\n /** Error code for unknown server status */\n static readonly CODE_UNKNOWN_STATUS = 'E0001';\n\n /** Error code identifying the type of error */\n readonly errorCode: string;\n\n /** The underlying error that caused this error, if any */\n readonly cause?: Error;\n\n /**\n * Creates a new WaffoUnknownStatusError.\n *\n * @param errorCode - The error code (e.g., \"S0001\" for network error)\n * @param message - Human-readable error message\n * @param cause - The underlying error that caused this error\n */\n constructor(errorCode: string, message: string, cause?: Error) {\n super(message);\n this.name = 'WaffoUnknownStatusError';\n this.errorCode = errorCode;\n this.cause = cause;\n\n // Maintains proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, WaffoUnknownStatusError);\n }\n }\n\n /**\n * Returns a string representation of the error.\n */\n override toString(): string {\n return `[${this.errorCode}] ${this.message}`;\n }\n}\n","import * as crypto from 'crypto';\nimport { WaffoError, WaffoErrorCode } from '../errors';\n\n/**\n * RSA cryptographic utilities for signing and verification.\n *\n * Uses SHA256withRSA algorithm with 2048-bit key size.\n *\n * **Key Formats:**\n * - Private Key: PKCS#8 DER encoded, Base64 string\n * - Public Key: X.509 SubjectPublicKeyInfo DER encoded, Base64 string\n *\n * **Security Best Practices:**\n *\n * When verifying Waffo's response signature fails:\n * 1. Stop sending new transactions to Waffo until the issue is resolved\n * 2. Investigate the cause and contact Waffo support\n * 3. Note: Waffo may have already processed your request, but you failed to\n * process the response due to signature verification failure\n */\n\nconst ALGORITHM = 'RSA-SHA256';\nconst KEY_SIZE = 2048;\n\n/**\n * Result of key pair generation.\n */\nexport interface KeyPairResult {\n /** Base64 encoded PKCS8 private key */\n privateKey: string;\n /** Base64 encoded X509 public key */\n publicKey: string;\n}\n\n/**\n * Signs data using RSA-SHA256.\n *\n * @param data - The data to sign (UTF-8 string)\n * @param base64PrivateKey - Base64 encoded PKCS8 private key\n * @returns Base64 encoded signature\n * @throws WaffoError if signing fails (S0003)\n *\n * @example\n * ```typescript\n * const signature = sign('{\"amount\":\"100.00\"}', privateKey);\n * ```\n */\nexport function sign(data: string, base64PrivateKey: string): string {\n try {\n const privateKeyBuffer = Buffer.from(base64PrivateKey, 'base64');\n const signer = crypto.createSign(ALGORITHM);\n signer.update(data, 'utf8');\n\n const signature = signer.sign({\n key: privateKeyBuffer,\n format: 'der',\n type: 'pkcs8',\n });\n\n return signature.toString('base64');\n } catch (error) {\n throw new WaffoError(\n WaffoErrorCode.SIGN_FAILED,\n `Failed to sign data: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Verifies a signature using RSA-SHA256.\n *\n * @param data - The original data (UTF-8 string)\n * @param base64Signature - Base64 encoded signature\n * @param base64PublicKey - Base64 encoded X509 public key\n * @returns true if signature is valid, false otherwise\n *\n * @example\n * ```typescript\n * const isValid = verify(responseBody, signature, waffoPublicKey);\n * if (!isValid) {\n * // Handle signature verification failure\n * }\n * ```\n */\nexport function verify(\n data: string,\n base64Signature: string,\n base64PublicKey: string\n): boolean {\n try {\n const publicKeyBuffer = Buffer.from(base64PublicKey, 'base64');\n const signatureBuffer = Buffer.from(base64Signature, 'base64');\n\n const verifier = crypto.createVerify(ALGORITHM);\n verifier.update(data, 'utf8');\n\n return verifier.verify(\n {\n key: publicKeyBuffer,\n format: 'der',\n type: 'spki',\n },\n signatureBuffer\n );\n } catch {\n // Invalid key or signature format - return false instead of throwing\n return false;\n }\n}\n\n/**\n * Validates a Base64 encoded PKCS8 private key.\n *\n * This method attempts to parse the key to ensure it's a valid RSA private key.\n * Use this at startup to fail fast if the private key is invalid.\n *\n * @param base64PrivateKey - Base64 encoded PKCS8 private key\n * @throws WaffoError if the key is invalid (S0007)\n *\n * @example\n * ```typescript\n * // Validate at initialization\n * validatePrivateKey(config.privateKey);\n * ```\n */\nexport function validatePrivateKey(base64PrivateKey: string): void {\n if (!base64PrivateKey || base64PrivateKey.trim() === '') {\n throw new WaffoError(\n WaffoErrorCode.INVALID_PRIVATE_KEY,\n 'Private key is null or empty'\n );\n }\n\n try {\n const keyBuffer = Buffer.from(base64PrivateKey, 'base64');\n crypto.createPrivateKey({\n key: keyBuffer,\n format: 'der',\n type: 'pkcs8',\n });\n } catch (error) {\n if (error instanceof WaffoError) throw error;\n\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes('bad base64')) {\n throw new WaffoError(\n WaffoErrorCode.INVALID_PRIVATE_KEY,\n 'Invalid private key: not valid Base64 encoding',\n error instanceof Error ? error : undefined\n );\n }\n throw new WaffoError(\n WaffoErrorCode.INVALID_PRIVATE_KEY,\n `Invalid private key: ${message}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Validates a Base64 encoded X509 public key.\n *\n * This method attempts to parse the key to ensure it's a valid RSA public key.\n * Use this at startup to fail fast if the public key is invalid.\n *\n * @param base64PublicKey - Base64 encoded X509 public key\n * @throws WaffoError if the key is invalid (S0002)\n *\n * @example\n * ```typescript\n * // Validate at initialization\n * validatePublicKey(config.waffoPublicKey);\n * ```\n */\nexport function validatePublicKey(base64PublicKey: string): void {\n if (!base64PublicKey || base64PublicKey.trim() === '') {\n throw new WaffoError(\n WaffoErrorCode.INVALID_PUBLIC_KEY,\n 'Public key is null or empty'\n );\n }\n\n try {\n const keyBuffer = Buffer.from(base64PublicKey, 'base64');\n crypto.createPublicKey({\n key: keyBuffer,\n format: 'der',\n type: 'spki',\n });\n } catch (error) {\n if (error instanceof WaffoError) throw error;\n\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes('bad base64')) {\n throw new WaffoError(\n WaffoErrorCode.INVALID_PUBLIC_KEY,\n 'Invalid public key: not valid Base64 encoding',\n error instanceof Error ? error : undefined\n );\n }\n throw new WaffoError(\n WaffoErrorCode.INVALID_PUBLIC_KEY,\n `Invalid public key: ${message}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Generates a new RSA key pair for testing or merchant key generation.\n *\n * @returns A new KeyPairResult containing Base64 encoded keys\n *\n * @example\n * ```typescript\n * const keyPair = generateKeyPair();\n * console.log('Private Key:', keyPair.privateKey);\n * console.log('Public Key:', keyPair.publicKey);\n * ```\n */\nexport function generateKeyPair(): KeyPairResult {\n try {\n const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {\n modulusLength: KEY_SIZE,\n publicKeyEncoding: {\n type: 'spki',\n format: 'der',\n },\n privateKeyEncoding: {\n type: 'pkcs8',\n format: 'der',\n },\n });\n\n return {\n privateKey: privateKey.toString('base64'),\n publicKey: publicKey.toString('base64'),\n };\n } catch (error) {\n throw new WaffoError(\n WaffoErrorCode.SIGN_FAILED,\n `Failed to generate key pair: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * RsaUtils namespace for backward compatibility.\n * @deprecated Use direct function imports instead.\n */\nexport const RsaUtils = {\n sign,\n verify,\n validatePrivateKey,\n validatePublicKey,\n generateKeyPair,\n};\n","import { Environment } from './environment';\nimport type { HttpTransport } from '../../net/http-transport';\nimport { RsaUtils } from '../../utils/rsa-utils';\n\n/**\n * Logger interface for SDK debugging.\n */\nexport interface WaffoLogger {\n debug(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\n/**\n * Configuration for the Waffo SDK.\n *\n * @example\n * ```typescript\n * const config: WaffoConfig = {\n * apiKey: 'your-api-key',\n * privateKey: 'base64-private-key',\n * waffoPublicKey: 'base64-public-key',\n * environment: Environment.SANDBOX,\n * merchantId: 'your-merchant-id',\n * };\n *\n * const waffo = new Waffo(config);\n * ```\n */\nexport interface WaffoConfig {\n /** API key provided by Waffo */\n apiKey: string;\n\n /** Merchant's private key for signing requests (Base64 encoded PKCS8) */\n privateKey: string;\n\n /** Waffo's public key for verifying responses (Base64 encoded X509) */\n waffoPublicKey: string;\n\n /** API environment (SANDBOX or PRODUCTION) */\n environment: Environment;\n\n /**\n * Merchant ID (required).\n * This will be automatically injected into requests that require merchantId.\n */\n merchantId: string;\n\n /** Connect timeout in milliseconds (default: 10000) */\n connectTimeout?: number;\n\n /** Read timeout in milliseconds (default: 30000) */\n readTimeout?: number;\n\n /** Optional logger for debugging */\n logger?: WaffoLogger;\n\n /**\n * Custom HTTP transport implementation.\n * If not set, the SDK uses the default fetch-based transport.\n */\n httpTransport?: HttpTransport;\n}\n\n/**\n * Environment variable names for configuration.\n */\nexport const WaffoConfigEnvVars = {\n API_KEY: 'WAFFO_API_KEY',\n PRIVATE_KEY: 'WAFFO_PRIVATE_KEY',\n PUBLIC_KEY: 'WAFFO_PUBLIC_KEY',\n MERCHANT_ID: 'WAFFO_MERCHANT_ID',\n ENVIRONMENT: 'WAFFO_ENVIRONMENT',\n} as const;\n\n/**\n * Default timeout values.\n */\nexport const WaffoConfigDefaults = {\n CONNECT_TIMEOUT: 10000,\n READ_TIMEOUT: 30000,\n} as const;\n\n/**\n * Creates and validates a WaffoConfig.\n *\n * @param config - Configuration options\n * @returns Validated configuration with defaults applied\n * @throws WaffoError if required fields are missing or keys are invalid\n *\n * @example\n * ```typescript\n * const config = createWaffoConfig({\n * apiKey: 'your-api-key',\n * privateKey: 'base64-private-key',\n * waffoPublicKey: 'base64-public-key',\n * environment: Environment.SANDBOX,\n * });\n * ```\n */\nexport function createWaffoConfig(config: WaffoConfig): WaffoConfig {\n // Validate required fields\n if (!config.apiKey) {\n throw new Error('apiKey is required');\n }\n if (!config.privateKey) {\n throw new Error('privateKey is required');\n }\n if (!config.waffoPublicKey) {\n throw new Error('waffoPublicKey is required');\n }\n if (!config.environment) {\n throw new Error('environment is required (SANDBOX or PRODUCTION)');\n }\n if (!config.merchantId) {\n throw new Error('merchantId is required');\n }\n\n // Validate keys\n RsaUtils.validatePrivateKey(config.privateKey);\n RsaUtils.validatePublicKey(config.waffoPublicKey);\n\n return {\n ...config,\n connectTimeout: config.connectTimeout ?? WaffoConfigDefaults.CONNECT_TIMEOUT,\n readTimeout: config.readTimeout ?? WaffoConfigDefaults.READ_TIMEOUT,\n };\n}\n\n/**\n * Creates a WaffoConfig from environment variables.\n *\n * Required environment variables:\n * - WAFFO_API_KEY\n * - WAFFO_PRIVATE_KEY\n * - WAFFO_PUBLIC_KEY\n * - WAFFO_ENVIRONMENT (SANDBOX or PRODUCTION)\n *\n * Optional:\n * - WAFFO_MERCHANT_ID\n *\n * @returns Configuration from environment variables\n * @throws Error if required environment variables are not set\n *\n * @example\n * ```typescript\n * // Set environment variables:\n * // export WAFFO_API_KEY=your-api-key\n * // export WAFFO_PRIVATE_KEY=base64-private-key\n * // export WAFFO_PUBLIC_KEY=base64-public-key\n * // export WAFFO_ENVIRONMENT=SANDBOX\n *\n * const config = WaffoConfig.fromEnv();\n * ```\n */\nexport function fromEnv(): WaffoConfig {\n const getEnv = (name: string, required = true): string => {\n const value = process.env[name];\n if (required && (!value || value.trim() === '')) {\n throw new Error(`Required environment variable ${name} is not set`);\n }\n return value || '';\n };\n\n const apiKey = getEnv(WaffoConfigEnvVars.API_KEY);\n const privateKey = getEnv(WaffoConfigEnvVars.PRIVATE_KEY);\n const waffoPublicKey = getEnv(WaffoConfigEnvVars.PUBLIC_KEY);\n const envStr = getEnv(WaffoConfigEnvVars.ENVIRONMENT);\n const merchantId = getEnv(WaffoConfigEnvVars.MERCHANT_ID);\n\n const environment = envStr.toUpperCase() as Environment;\n if (environment !== Environment.SANDBOX && environment !== Environment.PRODUCTION) {\n throw new Error(\n `Invalid ${WaffoConfigEnvVars.ENVIRONMENT} value: ${envStr}. Must be SANDBOX or PRODUCTION`\n );\n }\n\n return createWaffoConfig({\n apiKey,\n privateKey,\n waffoPublicKey,\n environment,\n merchantId,\n });\n}\n","/**\n * Generic API response wrapper.\n *\n * All API responses are wrapped in this class for consistent handling.\n *\n * @example\n * ```typescript\n * const response = await waffo.order().create(params);\n *\n * if (response.isSuccess()) {\n * const data = response.getData();\n * console.log('Order ID:', data?.acquiringOrderId);\n * } else {\n * console.error(`Error [${response.code}]: ${response.getMessage()}`);\n * }\n * ```\n */\nexport class ApiResponse<T> {\n /** Response code. \"0\" indicates success, other values indicate errors. */\n readonly code: string;\n\n /** Response data (present when code is \"0\") */\n readonly data?: T;\n\n /** Error message (present when code is not \"0\") */\n readonly message?: string;\n\n private constructor(code: string, data?: T, message?: string) {\n this.code = code;\n this.data = data;\n this.message = message;\n }\n\n /**\n * Creates a successful response.\n *\n * @param data - The response data\n */\n static success<T>(data?: T): ApiResponse<T> {\n return new ApiResponse('0', data);\n }\n\n /**\n * Creates an error response.\n *\n * @param code - The error code\n * @param message - The error message\n */\n static error<T>(code: string, message?: string): ApiResponse<T> {\n return new ApiResponse<T>(code, undefined, message);\n }\n\n /**\n * Checks if the response indicates success.\n *\n * @returns true if the response code is \"0\"\n */\n isSuccess(): boolean {\n return this.code === '0';\n }\n\n /**\n * Gets the response data.\n *\n * @returns The response data, or undefined if the response is an error\n */\n getData(): T | undefined {\n return this.data;\n }\n\n /**\n * Gets the error message.\n *\n * @returns The error message, or undefined if the response is successful\n */\n getMessage(): string | undefined {\n return this.message;\n }\n\n /**\n * Gets the response code.\n *\n * @returns The response code\n */\n getCode(): string {\n return this.code;\n }\n\n /**\n * Gets the response data or throws an error.\n *\n * @returns The response data\n * @throws Error if the response is not successful or data is undefined\n */\n getDataOrThrow(): T {\n if (!this.isSuccess()) {\n throw new Error(`[${this.code}] ${this.message ?? 'API error'}`);\n }\n if (this.data === undefined) {\n throw new Error('Response data is undefined');\n }\n return this.data;\n }\n}\n","import type { HttpTransport } from './http-transport';\nimport type { HttpRequest } from './http-request';\nimport type { HttpResponse } from './http-response';\n\n/**\n * Default HTTP transport implementation using Node.js native fetch.\n *\n * Requires Node.js 18+ for native fetch support.\n *\n * Features:\n * - TLS 1.2+ enforced by default\n * - Separate connectTimeout and readTimeout\n * - Proper error handling for network errors\n *\n * Timeout behavior:\n * - connectTimeout: Maximum time to establish connection and receive response headers\n * - readTimeout: Maximum time to read the response body after connection is established\n *\n * @example\n * ```typescript\n * const transport = new DefaultHttpTransport();\n * const response = await transport.send({\n * url: 'https://api.example.com/endpoint',\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: '{\"key\":\"value\"}',\n * connectTimeout: 10000,\n * readTimeout: 30000,\n * });\n * ```\n */\nexport class DefaultHttpTransport implements HttpTransport {\n /**\n * Sends an HTTP request using native fetch.\n *\n * @param request - The HTTP request to send\n * @returns The HTTP response\n * @throws Error if the request fails (network error, timeout, etc.)\n */\n async send(request: HttpRequest): Promise<HttpResponse> {\n // Create abort controller for connection phase\n const connectController = new AbortController();\n let connectTimeoutId: ReturnType<typeof setTimeout> | undefined;\n let readTimeoutId: ReturnType<typeof setTimeout> | undefined;\n let timeoutPhase: 'connect' | 'read' = 'connect';\n\n try {\n // Phase 1: Connection timeout - applies to fetch() until we get response headers\n connectTimeoutId = setTimeout(() => {\n connectController.abort();\n }, request.connectTimeout);\n\n const response = await fetch(request.url, {\n method: request.method,\n headers: request.headers,\n body: request.body,\n signal: connectController.signal,\n });\n\n // Connection established, clear connect timeout\n clearTimeout(connectTimeoutId);\n connectTimeoutId = undefined;\n\n // Phase 2: Read timeout - applies to reading the response body\n timeoutPhase = 'read';\n const readController = new AbortController();\n readTimeoutId = setTimeout(() => {\n readController.abort();\n }, request.readTimeout);\n\n // Read response body with read timeout\n // Note: We need to race between body reading and timeout\n // since response.text() doesn't accept AbortSignal directly\n const body = await Promise.race([\n response.text(),\n new Promise<never>((_, reject) => {\n readController.signal.addEventListener('abort', () => {\n reject(new Error('AbortError'));\n });\n }),\n ]);\n\n clearTimeout(readTimeoutId);\n readTimeoutId = undefined;\n\n // Extract headers (convert to lowercase keys)\n const headers: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n headers[key.toLowerCase()] = value;\n });\n\n return {\n statusCode: response.status,\n headers,\n body,\n };\n } catch (error) {\n // Re-throw with more descriptive message\n if (error instanceof Error) {\n if (error.name === 'AbortError' || error.message === 'AbortError') {\n const timeout = timeoutPhase === 'connect' ? request.connectTimeout : request.readTimeout;\n throw new Error(`Request ${timeoutPhase} timeout after ${timeout}ms`);\n }\n throw error;\n }\n throw new Error(`HTTP request failed: ${String(error)}`);\n } finally {\n if (connectTimeoutId) clearTimeout(connectTimeoutId);\n if (readTimeoutId) clearTimeout(readTimeoutId);\n }\n }\n}\n","import type { WaffoConfig, WaffoLogger, RequestOptions } from '../types/config';\nimport { EnvironmentBaseUrl, WaffoConfigDefaults } from '../types/config';\nimport { ApiResponse } from '../types/api-response';\nimport type { HttpTransport } from '../net/http-transport';\nimport { DefaultHttpTransport } from '../net/default-http-transport';\nimport { RsaUtils } from '../utils/rsa-utils';\nimport { WaffoErrorCode } from '../errors/waffo-error';\nimport { WaffoUnknownStatusError } from '../errors/waffo-unknown-status-error';\n\n// HTTP Headers\nconst HEADER_API_KEY = 'x-api-key';\nconst HEADER_SIGNATURE = 'x-signature';\nconst HEADER_API_VERSION = 'x-api-version';\nconst HEADER_SDK_VERSION = 'x-sdk-version';\nconst HEADER_CONTENT_TYPE = 'content-type';\nconst CONTENT_TYPE_JSON = 'application/json';\n\n// Version info\nconst API_VERSION = '1.0.0';\nconst SDK_VERSION = 'waffo-node/2.1.0';\n\n/**\n * HTTP client for making requests to the Waffo API.\n *\n * Handles:\n * - Request signing with merchant's private key\n * - Response signature verification with Waffo's public key\n * - MerchantId auto-injection\n * - Error handling and timeout management\n */\nexport class WaffoHttpClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly privateKey: string;\n private readonly waffoPublicKey: string;\n private readonly merchantId: string;\n private readonly connectTimeout: number;\n private readonly readTimeout: number;\n private readonly logger?: WaffoLogger;\n private readonly httpTransport: HttpTransport;\n\n constructor(config: WaffoConfig) {\n this.baseUrl = EnvironmentBaseUrl[config.environment];\n this.apiKey = config.apiKey;\n this.privateKey = config.privateKey;\n this.waffoPublicKey = config.waffoPublicKey;\n this.merchantId = config.merchantId;\n this.connectTimeout = config.connectTimeout ?? WaffoConfigDefaults.CONNECT_TIMEOUT;\n this.readTimeout = config.readTimeout ?? WaffoConfigDefaults.READ_TIMEOUT;\n this.logger = config.logger;\n this.httpTransport = config.httpTransport ?? new DefaultHttpTransport();\n }\n\n /**\n * Sends a POST request to the Waffo API.\n *\n * @param path - API endpoint path (e.g., \"/order/create\")\n * @param request - Request body\n * @param options - Per-request options\n * @returns API response\n * @throws WaffoUnknownStatusError for network errors or unknown status\n */\n async post<T extends object, R>(\n path: string,\n request: T,\n options?: RequestOptions\n ): Promise<ApiResponse<R>> {\n const url = this.baseUrl + path;\n const effectiveConnectTimeout = options?.connectTimeout ?? this.connectTimeout;\n const effectiveReadTimeout = options?.readTimeout ?? this.readTimeout;\n\n try {\n // Auto-inject merchantId if configured\n this.injectMerchantIdIfNeeded(request);\n\n // Serialize request\n const requestBody = JSON.stringify(request);\n\n // Sign the request\n const signature = RsaUtils.sign(requestBody, this.privateKey);\n\n this.logger?.debug(`Request URL: ${url}`);\n this.logger?.debug(`Request Body: ${requestBody}`);\n\n // Build and send HTTP request\n const httpResponse = await this.httpTransport.send({\n url,\n method: 'POST',\n headers: {\n [HEADER_CONTENT_TYPE]: CONTENT_TYPE_JSON,\n [HEADER_API_KEY]: this.apiKey,\n [HEADER_SIGNATURE]: signature,\n [HEADER_API_VERSION]: API_VERSION,\n [HEADER_SDK_VERSION]: SDK_VERSION,\n },\n body: requestBody,\n connectTimeout: effectiveConnectTimeout,\n readTimeout: effectiveReadTimeout,\n });\n\n this.logger?.debug(`Response Status: ${httpResponse.statusCode}`);\n this.logger?.debug(`Response Body: ${httpResponse.body}`);\n\n // Verify response signature\n const responseSignature = httpResponse.headers[HEADER_SIGNATURE];\n if (responseSignature) {\n const isValid = RsaUtils.verify(\n httpResponse.body,\n responseSignature,\n this.waffoPublicKey\n );\n if (!isValid) {\n this.logger?.error('Response signature verification failed');\n return ApiResponse.error(\n WaffoErrorCode.VERIFY_FAILED,\n 'Response signature verification failed'\n );\n }\n }\n\n // Parse response\n const response = this.parseResponse<R>(httpResponse.body);\n\n // Check for E0001 (unknown status)\n if (response.code === 'E0001') {\n throw new WaffoUnknownStatusError(\n WaffoUnknownStatusError.CODE_UNKNOWN_STATUS,\n response.getMessage() ?? 'Unknown status from server'\n );\n }\n\n return response;\n } catch (error) {\n // Re-throw WaffoUnknownStatusError\n if (error instanceof WaffoUnknownStatusError) {\n throw error;\n }\n\n // Handle network errors\n if (this.isNetworkError(error)) {\n this.logger?.error('Network error', error);\n throw new WaffoUnknownStatusError(\n WaffoUnknownStatusError.CODE_NETWORK_ERROR,\n `Network error, payment status unknown: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n\n // Handle serialization errors\n if (error instanceof SyntaxError) {\n this.logger?.error('JSON serialization error', error);\n return ApiResponse.error(\n WaffoErrorCode.SERIALIZE_FAILED,\n `Request serialization failed: ${error.message}`\n );\n }\n\n this.logger?.error('Unexpected error', error);\n return ApiResponse.error(\n WaffoErrorCode.UNEXPECTED,\n `Unexpected error: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Parses the API response body.\n */\n private parseResponse<R>(responseBody: string): ApiResponse<R> {\n try {\n const parsed = JSON.parse(responseBody) as {\n code?: string;\n msg?: string;\n data?: R;\n };\n\n const { code, msg, data } = parsed;\n\n if (code === '0') {\n return ApiResponse.success(data);\n } else {\n return ApiResponse.error(code ?? 'UNKNOWN', msg);\n }\n } catch (error) {\n this.logger?.error('Failed to parse response', error);\n return ApiResponse.error(\n 'C0001',\n `Failed to parse response: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Auto-injects merchantId into the request if configured.\n */\n private injectMerchantIdIfNeeded<T extends object>(request: T): void {\n if (!this.merchantId) return;\n\n const req = request as Record<string, unknown>;\n\n // Check merchantInfo.merchantId\n if (\n typeof req.merchantInfo === 'object' &&\n req.merchantInfo !== null &&\n !('merchantId' in req.merchantInfo && (req.merchantInfo as Record<string, unknown>).merchantId)\n ) {\n (req.merchantInfo as Record<string, unknown>).merchantId = this.merchantId;\n }\n // Check top-level merchantId\n else if ('merchantId' in req && !req.merchantId) {\n req.merchantId = this.merchantId;\n }\n }\n\n /**\n * Checks if the error is a network-related error.\n */\n private isNetworkError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n\n const message = error.message.toLowerCase();\n return (\n error.name === 'AbortError' ||\n message.includes('timeout') ||\n message.includes('econnrefused') ||\n message.includes('enotfound') ||\n message.includes('network') ||\n message.includes('socket') ||\n message.includes('connection')\n );\n }\n}\n","import type { WaffoConfig, WaffoLogger } from '../types/config';\nimport { RsaUtils } from '../utils/rsa-utils';\n\n/**\n * Webhook event types sent by Waffo.\n */\nexport enum WebhookEventType {\n PAYMENT_NOTIFICATION = 'PAYMENT_NOTIFICATION',\n REFUND_NOTIFICATION = 'REFUND_NOTIFICATION',\n SUBSCRIPTION_STATUS_NOTIFICATION = 'SUBSCRIPTION_STATUS_NOTIFICATION',\n SUBSCRIPTION_PAYMENT_NOTIFICATION = 'SUBSCRIPTION_PAYMENT_NOTIFICATION',\n SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION = 'SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION',\n}\n\n/**\n * Result of webhook handling.\n */\nexport interface WebhookResult {\n /** Whether the webhook was processed successfully */\n success: boolean;\n /** Response body to send back to Waffo */\n responseBody: string;\n /** Signature for the response body */\n responseSignature: string;\n /** Error message if processing failed */\n error?: string;\n}\n\n/**\n * Base notification interface.\n */\nexport interface BaseNotification {\n eventType: string;\n}\n\n/**\n * Payment notification from Waffo.\n */\nexport interface PaymentNotification extends BaseNotification {\n eventType: 'PAYMENT_NOTIFICATION';\n acquiringOrderId?: string;\n merchantOrderId?: string;\n paymentRequestId?: string;\n orderStatus?: string;\n orderAmount?: string;\n orderCurrency?: string;\n finalDealAmount?: string;\n [key: string]: unknown;\n}\n\n/**\n * Refund notification from Waffo.\n */\nexport interface RefundNotification extends BaseNotification {\n eventType: 'REFUND_NOTIFICATION';\n acquiringRefundOrderId?: string;\n refundRequestId?: string;\n refundStatus?: string;\n refundAmount?: string;\n [key: string]: unknown;\n}\n\n/**\n * Subscription status notification from Waffo.\n */\nexport interface SubscriptionStatusNotification extends BaseNotification {\n eventType: 'SUBSCRIPTION_STATUS_NOTIFICATION';\n subscriptionId?: string;\n subscriptionStatus?: string;\n [key: string]: unknown;\n}\n\n/**\n * Subscription payment notification from Waffo.\n */\nexport interface SubscriptionPaymentNotification extends BaseNotification {\n eventType: 'SUBSCRIPTION_PAYMENT_NOTIFICATION';\n subscriptionId?: string;\n acquiringOrderId?: string;\n orderStatus?: string;\n [key: string]: unknown;\n}\n\n/**\n * Subscription period changed notification from Waffo.\n */\nexport interface SubscriptionPeriodChangedNotification extends BaseNotification {\n eventType: 'SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION';\n subscriptionId?: string;\n [key: string]: unknown;\n}\n\n// Handler types\ntype PaymentHandler = (notification: PaymentNotification) => void | Promise<void>;\ntype RefundHandler = (notification: RefundNotification) => void | Promise<void>;\ntype SubscriptionStatusHandler = (notification: SubscriptionStatusNotification) => void | Promise<void>;\ntype SubscriptionPaymentHandler = (notification: SubscriptionPaymentNotification) => void | Promise<void>;\ntype SubscriptionPeriodChangedHandler = (notification: SubscriptionPeriodChangedNotification) => void | Promise<void>;\n\n/**\n * Webhook handler for processing Waffo webhook notifications.\n *\n * @example\n * ```typescript\n * // Setup handler\n * const handler = waffo.webhook()\n * .onPayment((notification) => {\n * console.log('Payment:', notification.orderStatus);\n * })\n * .onRefund((notification) => {\n * console.log('Refund:', notification.refundStatus);\n * });\n *\n * // Process webhook (e.g., in Express.js)\n * app.post('/webhook', async (req, res) => {\n * const body = req.body.toString();\n * const signature = req.headers['x-signature'];\n * const result = await handler.handleWebhook(body, signature);\n *\n * res.setHeader('X-SIGNATURE', result.responseSignature);\n * res.status(200).send(result.responseBody);\n * });\n * ```\n */\nexport class WebhookHandler {\n private readonly waffoPublicKey: string;\n private readonly privateKey: string;\n private readonly logger?: WaffoLogger;\n\n private paymentHandler?: PaymentHandler;\n private refundHandler?: RefundHandler;\n private subscriptionStatusHandler?: SubscriptionStatusHandler;\n private subscriptionPaymentHandler?: SubscriptionPaymentHandler;\n private subscriptionPeriodChangedHandler?: SubscriptionPeriodChangedHandler;\n\n constructor(config: WaffoConfig) {\n this.waffoPublicKey = config.waffoPublicKey;\n this.privateKey = config.privateKey;\n this.logger = config.logger;\n }\n\n /**\n * Registers a handler for payment notifications.\n */\n onPayment(handler: PaymentHandler): this {\n this.paymentHandler = handler;\n return this;\n }\n\n /**\n * Registers a handler for refund notifications.\n */\n onRefund(handler: RefundHandler): this {\n this.refundHandler = handler;\n return this;\n }\n\n /**\n * Registers a handler for subscription status notifications.\n */\n onSubscriptionStatus(handler: SubscriptionStatusHandler): this {\n this.subscriptionStatusHandler = handler;\n return this;\n }\n\n /**\n * Registers a handler for subscription payment notifications.\n */\n onSubscriptionPayment(handler: SubscriptionPaymentHandler): this {\n this.subscriptionPaymentHandler = handler;\n return this;\n }\n\n /**\n * Registers a handler for subscription period changed notifications.\n */\n onSubscriptionPeriodChanged(handler: SubscriptionPeriodChangedHandler): this {\n this.subscriptionPeriodChangedHandler = handler;\n return this;\n }\n\n /**\n * Processes a webhook notification.\n *\n * @param body - The raw webhook body\n * @param signature - The X-SIGNATURE header value\n * @returns Result with response body and signature\n */\n async handleWebhook(body: string, signature: string): Promise<WebhookResult> {\n try {\n // Verify signature\n if (!signature) {\n this.logger?.warn('Missing webhook signature');\n return this.createFailedResult('Missing signature');\n }\n\n const isValid = RsaUtils.verify(body, signature, this.waffoPublicKey);\n if (!isValid) {\n this.logger?.error('Invalid webhook signature');\n return this.createFailedResult('Invalid signature');\n }\n\n // Parse and route event\n const parsed = JSON.parse(body) as BaseNotification;\n const eventType = parsed.eventType as WebhookEventType;\n\n switch (eventType) {\n case WebhookEventType.PAYMENT_NOTIFICATION:\n if (this.paymentHandler) {\n await this.paymentHandler(parsed as PaymentNotification);\n }\n break;\n\n case WebhookEventType.REFUND_NOTIFICATION:\n if (this.refundHandler) {\n await this.refundHandler(parsed as RefundNotification);\n }\n break;\n\n case WebhookEventType.SUBSCRIPTION_STATUS_NOTIFICATION:\n if (this.subscriptionStatusHandler) {\n await this.subscriptionStatusHandler(parsed as SubscriptionStatusNotification);\n }\n break;\n\n case WebhookEventType.SUBSCRIPTION_PAYMENT_NOTIFICATION:\n if (this.subscriptionPaymentHandler) {\n await this.subscriptionPaymentHandler(parsed as SubscriptionPaymentNotification);\n }\n break;\n\n case WebhookEventType.SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION:\n if (this.subscriptionPeriodChangedHandler) {\n await this.subscriptionPeriodChangedHandler(parsed as SubscriptionPeriodChangedNotification);\n }\n break;\n\n default:\n this.logger?.warn(`Unknown webhook event type: ${eventType}`);\n return this.createFailedResult(`Unknown event type: ${eventType}`);\n }\n\n return this.createSuccessResult();\n } catch (error) {\n this.logger?.error('Error handling webhook', error);\n return this.createFailedResult(\n `Error handling webhook: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Verifies a webhook signature.\n *\n * @param body - The raw webhook body\n * @param signature - The X-SIGNATURE header value\n * @returns true if signature is valid\n */\n verifySignature(body: string, signature: string): boolean {\n return RsaUtils.verify(body, signature, this.waffoPublicKey);\n }\n\n /**\n * Builds a success response with signature.\n */\n buildSuccessResponse(): { body: string; signature: string } {\n const body = JSON.stringify({ status: 'success' });\n const signature = RsaUtils.sign(body, this.privateKey);\n return { body, signature };\n }\n\n /**\n * Builds a failed response with signature.\n */\n buildFailedResponse(message: string): { body: string; signature: string } {\n const body = JSON.stringify({ status: 'failed', message });\n const signature = RsaUtils.sign(body, this.privateKey);\n return { body, signature };\n }\n\n private createSuccessResult(): WebhookResult {\n const { body, signature } = this.buildSuccessResponse();\n return {\n success: true,\n responseBody: body,\n responseSignature: signature,\n };\n }\n\n private createFailedResult(error: string): WebhookResult {\n const { body, signature } = this.buildFailedResponse(error);\n return {\n success: false,\n responseBody: body,\n responseSignature: signature,\n error,\n };\n }\n}\n","import { WaffoHttpClient } from '../core/waffo-http-client';\n\n/**\n * Base class for API resources.\n */\nexport abstract class BaseResource {\n protected readonly httpClient: WaffoHttpClient;\n protected readonly basePath: string;\n\n constructor(httpClient: WaffoHttpClient, basePath: string) {\n this.httpClient = httpClient;\n this.basePath = basePath;\n }\n\n /**\n * Gets the full path for an endpoint.\n *\n * @param endpoint - The endpoint (e.g., \"/create\")\n * @returns Full path (e.g., \"/order/create\")\n */\n protected getPath(endpoint: string): string {\n return this.basePath + endpoint;\n }\n}\n","import { BaseResource } from './base-resource';\nimport { ApiResponse } from '../types/api-response';\nimport type { RequestOptions } from '../types/config';\nimport type {\n CreateOrderParams,\n CreateOrderData,\n InquiryOrderParams,\n InquiryOrderData,\n CancelOrderParams,\n CancelOrderData,\n RefundOrderParams,\n RefundOrderData,\n CaptureOrderParams,\n CaptureOrderData,\n} from '../types/order';\n\n/**\n * Order resource for managing payment orders.\n *\n * @example\n * ```typescript\n * // Create an order\n * const response = await waffo.order().create({\n * paymentRequestId: 'unique-request-id',\n * merchantOrderId: 'order-123',\n * orderCurrency: 'USD',\n * orderAmount: '10.00',\n * orderDescription: 'Test order',\n * notifyUrl: 'https://example.com/webhook',\n * userInfo: {\n * userId: 'user-123',\n * userEmail: 'user@example.com',\n * },\n * paymentInfo: {\n * productName: 'Test Product',\n * },\n * });\n *\n * if (response.isSuccess()) {\n * console.log('Order created:', response.getData());\n * }\n * ```\n */\nexport class OrderResource extends BaseResource {\n private static readonly PATH_CREATE = '/create';\n private static readonly PATH_INQUIRY = '/inquiry';\n private static readonly PATH_CANCEL = '/cancel';\n private static readonly PATH_REFUND = '/refund';\n private static readonly PATH_CAPTURE = '/capture';\n\n /**\n * Creates a new payment order.\n *\n * @param params - Order creation parameters\n * @param options - Optional request options\n * @returns API response with order data\n * @throws WaffoUnknownStatusError for network errors\n */\n async create(\n params: CreateOrderParams,\n options?: RequestOptions\n ): Promise<ApiResponse<CreateOrderData>> {\n return this.httpClient.post<CreateOrderParams, CreateOrderData>(\n this.getPath(OrderResource.PATH_CREATE),\n params,\n options\n );\n }\n\n /**\n * Queries an existing order.\n *\n * @param params - Order inquiry parameters\n * @param options - Optional request options\n * @returns API response with order data\n * @throws WaffoUnknownStatusError for network errors\n */\n async inquiry(\n params: InquiryOrderParams,\n options?: RequestOptions\n ): Promise<ApiResponse<InquiryOrderData>> {\n return this.httpClient.post<InquiryOrderParams, InquiryOrderData>(\n this.getPath(OrderResource.PATH_INQUIRY),\n params,\n options\n );\n }\n\n /**\n * Cancels an existing order.\n *\n * @param params - Order cancellation parameters\n * @param options - Optional request options\n * @returns API response with cancellation result\n * @throws WaffoUnknownStatusError for network errors\n */\n async cancel(\n params: CancelOrderParams,\n options?: RequestOptions\n ): Promise<ApiResponse<CancelOrderData>> {\n return this.httpClient.post<CancelOrderParams, CancelOrderData>(\n this.getPath(OrderResource.PATH_CANCEL),\n params,\n options\n );\n }\n\n /**\n * Refunds an existing order.\n *\n * @param params - Order refund parameters\n * @param options - Optional request options\n * @returns API response with refund result\n * @throws WaffoUnknownStatusError for network errors\n */\n async refund(\n params: RefundOrderParams,\n options?: RequestOptions\n ): Promise<ApiResponse<RefundOrderData>> {\n return this.httpClient.post<RefundOrderParams, RefundOrderData>(\n this.getPath(OrderResource.PATH_REFUND),\n params,\n options\n );\n }\n\n /**\n * Captures an authorized order.\n *\n * @param params - Order capture parameters\n * @param options - Optional request options\n * @returns API response with capture result\n * @throws WaffoUnknownStatusError for network errors\n */\n async capture(\n params: CaptureOrderParams,\n options?: RequestOptions\n ): Promise<ApiResponse<CaptureOrderData>> {\n return this.httpClient.post<CaptureOrderParams, CaptureOrderData>(\n this.getPath(OrderResource.PATH_CAPTURE),\n params,\n options\n );\n }\n}\n","import { BaseResource } from './base-resource';\nimport { ApiResponse } from '../types/api-response';\nimport type { RequestOptions } from '../types/config';\nimport type {\n CreateSubscriptionParams,\n CreateSubscriptionData,\n InquirySubscriptionParams,\n InquirySubscriptionData,\n CancelSubscriptionParams,\n CancelSubscriptionData,\n ManageSubscriptionParams,\n ManageSubscriptionData,\n SubscriptionChangeParams,\n SubscriptionChangeData,\n SubscriptionChangeInquiryParams,\n SubscriptionChangeInquiryData,\n} from '../types/subscription';\n\n/**\n * Subscription resource for managing recurring payments.\n *\n * @example\n * ```typescript\n * // Create a subscription\n * const response = await waffo.subscription().create({\n * subscriptionRequestId: 'unique-request-id',\n * merchantSubscriptionId: 'sub-123',\n * orderCurrency: 'USD',\n * orderAmount: '9.99',\n * orderDescription: 'Monthly subscription',\n * notifyUrl: 'https://example.com/webhook',\n * productInfo: {\n * productId: 'product-123',\n * productName: 'Premium Plan',\n * periodType: 'MONTH',\n * periodValue: 1,\n * },\n * userInfo: {\n * userId: 'user-123',\n * userEmail: 'user@example.com',\n * },\n * paymentInfo: {\n * productName: 'Premium Plan',\n * },\n * });\n *\n * if (response.isSuccess()) {\n * console.log('Subscription created:', response.getData());\n * }\n * ```\n */\nexport class SubscriptionResource extends BaseResource {\n private static readonly PATH_CREATE = '/create';\n private static readonly PATH_INQUIRY = '/inquiry';\n private static readonly PATH_CANCEL = '/cancel';\n private static readonly PATH_MANAGE = '/manage';\n private static readonly PATH_CHANGE = '/change';\n private static readonly PATH_CHANGE_INQUIRY = '/change/inquiry';\n\n /**\n * Creates a new subscription.\n *\n * @param params - Subscription creation parameters\n * @param options - Optional request options\n * @returns API response with subscription data\n * @throws WaffoUnknownStatusError for network errors\n */\n async create(\n params: CreateSubscriptionParams,\n options?: RequestOptions\n ): Promise<ApiResponse<CreateSubscriptionData>> {\n return this.httpClient.post<CreateSubscriptionParams, CreateSubscriptionData>(\n this.getPath(SubscriptionResource.PATH_CREATE),\n params,\n options\n );\n }\n\n /**\n * Queries an existing subscription.\n *\n * @param params - Subscription inquiry parameters\n * @param options - Optional request options\n * @returns API response with subscription data\n * @throws WaffoUnknownStatusError for network errors\n */\n async inquiry(\n params: InquirySubscriptionParams,\n options?: RequestOptions\n ): Promise<ApiResponse<InquirySubscriptionData>> {\n return this.httpClient.post<InquirySubscriptionParams, InquirySubscriptionData>(\n this.getPath(SubscriptionResource.PATH_INQUIRY),\n params,\n options\n );\n }\n\n /**\n * Cancels an existing subscription.\n *\n * @param params - Subscription cancellation parameters\n * @param options - Optional request options\n * @returns API response with cancellation result\n * @throws WaffoUnknownStatusError for network errors\n */\n async cancel(\n params: CancelSubscriptionParams,\n options?: RequestOptions\n ): Promise<ApiResponse<CancelSubscriptionData>> {\n return this.httpClient.post<CancelSubscriptionParams, CancelSubscriptionData>(\n this.getPath(SubscriptionResource.PATH_CANCEL),\n params,\n options\n );\n }\n\n /**\n * Manages an existing subscription (pause, resume, update).\n *\n * @param params - Subscription management parameters\n * @param options - Optional request options\n * @returns API response with management result\n * @throws WaffoUnknownStatusError for network errors\n */\n async manage(\n params: ManageSubscriptionParams,\n options?: RequestOptions\n ): Promise<ApiResponse<ManageSubscriptionData>> {\n return this.httpClient.post<ManageSubscriptionParams, ManageSubscriptionData>(\n this.getPath(SubscriptionResource.PATH_MANAGE),\n params,\n options\n );\n }\n\n /**\n * Changes (upgrades/downgrades) an existing subscription.\n *\n * This method allows changing an active subscription to a new plan with different\n * pricing, billing period, or other terms. The remaining amount from the original\n * subscription can be applied to the new subscription.\n *\n * @param params - Subscription change parameters\n * @param options - Optional request options\n * @returns API response with change result\n * @throws WaffoUnknownStatusError for network errors\n *\n * @example\n * ```typescript\n * const response = await waffo.subscription().change({\n * subscriptionRequest: 'new-request-id',\n * originSubscriptionRequest: 'original-request-id',\n * remainingAmount: '50.00',\n * currency: 'HKD',\n * requestedAt: new Date().toISOString(),\n * notifyUrl: 'https://example.com/webhook',\n * productInfoList: [{\n * description: 'Premium Monthly',\n * periodType: 'MONTH',\n * periodInterval: '1',\n * amount: '199.00',\n * }],\n * userInfo: { userId: 'user-123', userEmail: 'user@example.com' },\n * goodsInfo: { goodsId: 'premium', goodsName: 'Premium Plan' },\n * paymentInfo: { productName: 'SUBSCRIPTION' },\n * });\n *\n * if (response.isSuccess()) {\n * const data = response.getData();\n * if (data?.subscriptionChangeStatus === 'AUTHORIZATION_REQUIRED') {\n * // Redirect user to authorization URL\n * const webUrl = JSON.parse(data.subscriptionAction || '{}').webUrl;\n * }\n * }\n * ```\n */\n async change(\n params: SubscriptionChangeParams,\n options?: RequestOptions\n ): Promise<ApiResponse<SubscriptionChangeData>> {\n return this.httpClient.post<SubscriptionChangeParams, SubscriptionChangeData>(\n this.getPath(SubscriptionResource.PATH_CHANGE),\n params,\n options\n );\n }\n\n /**\n * Queries the status of a subscription change.\n *\n * Use this method to check the current status of a subscription change operation,\n * especially after network errors or when status is uncertain.\n *\n * @param params - Change inquiry parameters\n * @param options - Optional request options\n * @returns API response with change inquiry data\n *\n * @example\n * ```typescript\n * const response = await waffo.subscription().changeInquiry({\n * subscriptionRequest: 'new-request-id',\n * originSubscriptionRequest: 'original-request-id',\n * });\n *\n * if (response.isSuccess()) {\n * const data = response.getData();\n * console.log('Change status:', data?.subscriptionChangeStatus);\n * }\n * ```\n */\n async changeInquiry(\n params: SubscriptionChangeInquiryParams,\n options?: RequestOptions\n ): Promise<ApiResponse<SubscriptionChangeInquiryData>> {\n try {\n return await this.httpClient.post<SubscriptionChangeInquiryParams, SubscriptionChangeInquiryData>(\n this.getPath(SubscriptionResource.PATH_CHANGE_INQUIRY),\n params,\n options\n );\n } catch (error) {\n // For inquiry operations, catch unknown status errors and return error response\n if (error && typeof error === 'object' && 'errorCode' in error) {\n return ApiResponse.error('E0001', String((error as { message?: string }).message || 'Unknown error'));\n }\n throw error;\n }\n }\n}\n","import { BaseResource } from './base-resource';\nimport { ApiResponse } from '../types/api-response';\nimport type { RequestOptions } from '../types/config';\nimport type { InquiryRefundParams, InquiryRefundData } from '../types/refund';\n\n/**\n * Refund resource for querying refund status.\n *\n * Note: To initiate a refund, use `waffo.order().refund()` instead.\n *\n * @example\n * ```typescript\n * // Query refund status\n * const response = await waffo.refund().inquiry({\n * refundRequestId: 'refund-request-123',\n * });\n *\n * if (response.isSuccess()) {\n * const data = response.getData();\n * console.log('Refund status:', data?.refundStatus);\n * }\n * ```\n */\nexport class RefundResource extends BaseResource {\n private static readonly PATH_INQUIRY = '/inquiry';\n\n /**\n * Queries the status of a refund.\n *\n * @param params - Refund inquiry parameters\n * @param options - Optional request options\n * @returns API response with refund data\n * @throws WaffoUnknownStatusError for network errors\n */\n async inquiry(\n params: InquiryRefundParams,\n options?: RequestOptions\n ): Promise<ApiResponse<InquiryRefundData>> {\n return this.httpClient.post<InquiryRefundParams, InquiryRefundData>(\n this.getPath(RefundResource.PATH_INQUIRY),\n params,\n options\n );\n }\n}\n","import { BaseResource } from './base-resource';\nimport { ApiResponse } from '../types/api-response';\nimport type { RequestOptions } from '../types/config';\nimport type {\n InquiryMerchantConfigParams,\n InquiryMerchantConfigData,\n} from '../types/merchant';\n\n/**\n * Merchant config resource for querying merchant configuration.\n *\n * @example\n * ```typescript\n * // Query merchant config\n * const response = await waffo.merchantConfig().inquiry({\n * merchantId: 'merchant-123',\n * });\n *\n * if (response.isSuccess()) {\n * const data = response.getData();\n * console.log('Merchant status:', data?.merchantStatus);\n * console.log('Supported currencies:', data?.supportedCurrencies);\n * }\n * ```\n */\nexport class MerchantConfigResource extends BaseResource {\n private static readonly PATH_INQUIRY = '/inquiry';\n\n /**\n * Queries merchant configuration.\n *\n * @param params - Merchant config inquiry parameters\n * @param options - Optional request options\n * @returns API response with merchant config data\n * @throws WaffoUnknownStatusError for network errors\n */\n async inquiry(\n params: InquiryMerchantConfigParams,\n options?: RequestOptions\n ): Promise<ApiResponse<InquiryMerchantConfigData>> {\n return this.httpClient.post<InquiryMerchantConfigParams, InquiryMerchantConfigData>(\n this.getPath(MerchantConfigResource.PATH_INQUIRY),\n params,\n options\n );\n }\n}\n","import { BaseResource } from './base-resource';\nimport { ApiResponse } from '../types/api-response';\nimport type { RequestOptions } from '../types/config';\nimport type {\n InquiryPayMethodConfigParams,\n InquiryPayMethodConfigData,\n} from '../types/merchant';\n\n/**\n * Pay method config resource for querying available payment methods.\n *\n * @example\n * ```typescript\n * // Query available payment methods\n * const response = await waffo.payMethodConfig().inquiry({\n * merchantId: 'merchant-123',\n * });\n *\n * if (response.isSuccess()) {\n * const data = response.getData();\n * data?.payMethods?.forEach(method => {\n * console.log(`${method.payMethodName}: ${method.payMethodStatus}`);\n * });\n * }\n * ```\n */\nexport class PayMethodConfigResource extends BaseResource {\n private static readonly PATH_INQUIRY = '/inquiry';\n\n /**\n * Queries available payment methods.\n *\n * @param params - Pay method config inquiry parameters\n * @param options - Optional request options\n * @returns API response with pay method config data\n * @throws WaffoUnknownStatusError for network errors\n */\n async inquiry(\n params: InquiryPayMethodConfigParams,\n options?: RequestOptions\n ): Promise<ApiResponse<InquiryPayMethodConfigData>> {\n return this.httpClient.post<InquiryPayMethodConfigParams, InquiryPayMethodConfigData>(\n this.getPath(PayMethodConfigResource.PATH_INQUIRY),\n params,\n options\n );\n }\n}\n","import type { WaffoConfig } from './types/config';\nimport { fromEnv } from './types/config';\nimport { WaffoHttpClient } from './core/waffo-http-client';\nimport { WebhookHandler } from './core/webhook-handler';\nimport { OrderResource } from './resources/order-resource';\nimport { SubscriptionResource } from './resources/subscription-resource';\nimport { RefundResource } from './resources/refund-resource';\nimport { MerchantConfigResource } from './resources/merchant-config-resource';\nimport { PayMethodConfigResource } from './resources/pay-method-config-resource';\n\n/**\n * Main entry point for the Waffo SDK.\n *\n * @example\n * ```typescript\n * import { Waffo, Environment } from '@waffo/waffo-node';\n *\n * // Create SDK instance\n * const waffo = new Waffo({\n * apiKey: 'your-api-key',\n * privateKey: 'your-base64-private-key',\n * waffoPublicKey: 'waffo-base64-public-key',\n * environment: Environment.SANDBOX,\n * merchantId: 'your-merchant-id', // required, auto-injected into requests\n * });\n *\n * // Create an order\n * const response = await waffo.order().create({\n * paymentRequestId: 'unique-request-id',\n * merchantOrderId: 'order-123',\n * orderCurrency: 'USD',\n * orderAmount: '10.00',\n * orderDescription: 'Test order',\n * notifyUrl: 'https://example.com/webhook',\n * userInfo: {\n * userId: 'user-123',\n * userEmail: 'user@example.com',\n * },\n * paymentInfo: {\n * productName: 'Test Product',\n * },\n * });\n *\n * if (response.isSuccess()) {\n * console.log('Order created:', response.getData());\n * } else {\n * console.error('Failed:', response.getCode(), response.getMessage());\n * }\n * ```\n */\nexport class Waffo {\n private readonly config: WaffoConfig;\n private readonly httpClient: WaffoHttpClient;\n\n // Lazy-initialized resources\n private _order?: OrderResource;\n private _subscription?: SubscriptionResource;\n private _refund?: RefundResource;\n private _merchantConfig?: MerchantConfigResource;\n private _payMethodConfig?: PayMethodConfigResource;\n\n /**\n * Creates a new Waffo SDK instance.\n *\n * @param config - SDK configuration\n */\n constructor(config: WaffoConfig) {\n this.config = config;\n this.httpClient = new WaffoHttpClient(config);\n }\n\n /**\n * Creates a Waffo SDK instance from environment variables.\n *\n * Required environment variables:\n * - WAFFO_API_KEY\n * - WAFFO_PRIVATE_KEY\n * - WAFFO_PUBLIC_KEY\n * - WAFFO_ENVIRONMENT (SANDBOX or PRODUCTION)\n *\n * Optional environment variables:\n * - WAFFO_MERCHANT_ID\n * - WAFFO_CONNECT_TIMEOUT\n * - WAFFO_READ_TIMEOUT\n *\n * @returns Waffo SDK instance\n */\n static fromEnv(): Waffo {\n return new Waffo(fromEnv());\n }\n\n /**\n * Returns the order resource for managing payment orders.\n *\n * @returns Order resource\n */\n order(): OrderResource {\n if (!this._order) {\n this._order = new OrderResource(this.httpClient, '/order');\n }\n return this._order;\n }\n\n /**\n * Returns the subscription resource for managing recurring payments.\n *\n * @returns Subscription resource\n */\n subscription(): SubscriptionResource {\n if (!this._subscription) {\n this._subscription = new SubscriptionResource(this.httpClient, '/subscription');\n }\n return this._subscription;\n }\n\n /**\n * Returns the refund resource for querying refund status.\n *\n * @returns Refund resource\n */\n refund(): RefundResource {\n if (!this._refund) {\n this._refund = new RefundResource(this.httpClient, '/refund');\n }\n return this._refund;\n }\n\n /**\n * Returns the merchant config resource.\n *\n * @returns Merchant config resource\n */\n merchantConfig(): MerchantConfigResource {\n if (!this._merchantConfig) {\n this._merchantConfig = new MerchantConfigResource(this.httpClient, '/merchant/config');\n }\n return this._merchantConfig;\n }\n\n /**\n * Returns the pay method config resource.\n *\n * @returns Pay method config resource\n */\n payMethodConfig(): PayMethodConfigResource {\n if (!this._payMethodConfig) {\n this._payMethodConfig = new PayMethodConfigResource(this.httpClient, '/paymethod/config');\n }\n return this._payMethodConfig;\n }\n\n /**\n * Creates a webhook handler for processing Waffo webhook notifications.\n *\n * @returns Webhook handler\n *\n * @example\n * ```typescript\n * // Setup webhook handler\n * const handler = waffo.webhook()\n * .onPayment((notification) => {\n * console.log('Payment:', notification.orderStatus);\n * })\n * .onRefund((notification) => {\n * console.log('Refund:', notification.refundStatus);\n * })\n * .onSubscriptionStatus((notification) => {\n * console.log('Subscription:', notification.subscriptionStatus);\n * });\n *\n * // In Express.js route handler\n * app.post('/webhook', async (req, res) => {\n * const body = req.body.toString();\n * const signature = req.headers['x-signature'] as string;\n * const result = await handler.handleWebhook(body, signature);\n *\n * res.setHeader('X-SIGNATURE', result.responseSignature);\n * res.status(200).send(result.responseBody);\n * });\n * ```\n */\n webhook(): WebhookHandler {\n return new WebhookHandler(this.config);\n }\n\n /**\n * Returns the current configuration.\n *\n * @returns SDK configuration (with sensitive data)\n */\n getConfig(): WaffoConfig {\n return this.config;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/types/config/environment.ts","../src/errors/waffo-error.ts","../src/errors/waffo-unknown-status-error.ts","../src/utils/rsa-utils.ts","../src/types/config/waffo-config.ts","../src/types/api-response.ts","../src/net/default-http-transport.ts","../src/core/waffo-http-client.ts","../src/core/webhook-handler.ts","../src/resources/base-resource.ts","../src/utils/time-utils.ts","../src/resources/order-resource.ts","../src/resources/subscription-resource.ts","../src/resources/refund-resource.ts","../src/resources/merchant-config-resource.ts","../src/resources/pay-method-config-resource.ts","../src/waffo.ts"],"names":["Environment","crypto","WebhookEventType"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Waffo API environment.\n */\nexport enum Environment {\n /** Sandbox environment for testing */\n SANDBOX = 'SANDBOX',\n /** Production environment for live transactions */\n PRODUCTION = 'PRODUCTION',\n}\n\n/**\n * Base URLs for each environment.\n */\nexport const EnvironmentBaseUrl: Record<Environment, string> = {\n [Environment.SANDBOX]: 'https://api-sandbox.waffo.com/api/v1',\n [Environment.PRODUCTION]: 'https://api.waffo.com/api/v1',\n};\n","/**\n * Base error class for client-side errors in the Waffo SDK.\n *\n * This error is thrown for configuration errors, serialization failures,\n * signature errors, and other client-side issues.\n *\n * @example\n * ```typescript\n * try {\n * const response = await waffo.order().create(params);\n * } catch (error) {\n * if (error instanceof WaffoError) {\n * console.error(`Error [${error.errorCode}]: ${error.message}`);\n * }\n * }\n * ```\n */\nexport class WaffoError extends Error {\n /** Error code identifying the type of error */\n readonly errorCode: string;\n\n /** The underlying error that caused this error, if any */\n readonly cause?: Error;\n\n /**\n * Creates a new WaffoError.\n *\n * @param errorCode - The error code (e.g., \"S0003\" for signing failure)\n * @param message - Human-readable error message\n * @param cause - The underlying error that caused this error\n */\n constructor(errorCode: string, message: string, cause?: Error) {\n super(message);\n this.name = 'WaffoError';\n this.errorCode = errorCode;\n this.cause = cause;\n\n // Maintains proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, WaffoError);\n }\n }\n\n /**\n * Returns a string representation of the error.\n */\n override toString(): string {\n return `[${this.errorCode}] ${this.message}`;\n }\n}\n\n/**\n * Error codes used by WaffoError.\n */\nexport const WaffoErrorCode = {\n /** Invalid public key */\n INVALID_PUBLIC_KEY: 'S0002',\n /** Failed to sign data */\n SIGN_FAILED: 'S0003',\n /** Response signature verification failed */\n VERIFY_FAILED: 'S0004',\n /** Request serialization failed */\n SERIALIZE_FAILED: 'S0005',\n /** Unexpected error */\n UNEXPECTED: 'S0006',\n /** Invalid private key */\n INVALID_PRIVATE_KEY: 'S0007',\n} as const;\n","/**\n * Error thrown when the payment status is unknown due to network errors\n * or server issues.\n *\n * **IMPORTANT**: When this error is thrown for a payment request,\n * you MUST NOT assume the payment failed. The payment may have been processed\n * successfully. Always use the inquiry API to check the actual payment status.\n *\n * @example\n * ```typescript\n * try {\n * const response = await waffo.order().create(params);\n * } catch (error) {\n * if (error instanceof WaffoUnknownStatusError) {\n * // Payment may have been processed - check status\n * const inquiry = await waffo.order().inquiry({\n * paymentRequestId: params.paymentRequestId\n * });\n * // Handle based on inquiry result\n * }\n * }\n * ```\n */\nexport class WaffoUnknownStatusError extends Error {\n /** Error code for network errors */\n static readonly CODE_NETWORK_ERROR = 'S0001';\n\n /** Error code for unknown server status */\n static readonly CODE_UNKNOWN_STATUS = 'E0001';\n\n /** Error code identifying the type of error */\n readonly errorCode: string;\n\n /** The underlying error that caused this error, if any */\n readonly cause?: Error;\n\n /**\n * Creates a new WaffoUnknownStatusError.\n *\n * @param errorCode - The error code (e.g., \"S0001\" for network error)\n * @param message - Human-readable error message\n * @param cause - The underlying error that caused this error\n */\n constructor(errorCode: string, message: string, cause?: Error) {\n super(message);\n this.name = 'WaffoUnknownStatusError';\n this.errorCode = errorCode;\n this.cause = cause;\n\n // Maintains proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, WaffoUnknownStatusError);\n }\n }\n\n /**\n * Returns a string representation of the error.\n */\n override toString(): string {\n return `[${this.errorCode}] ${this.message}`;\n }\n}\n","import * as crypto from 'crypto';\nimport { WaffoError, WaffoErrorCode } from '../errors';\n\n/**\n * RSA cryptographic utilities for signing and verification.\n *\n * Uses SHA256withRSA algorithm with 2048-bit key size.\n *\n * **Key Formats:**\n * - Private Key: PKCS#8 DER encoded, Base64 string\n * - Public Key: X.509 SubjectPublicKeyInfo DER encoded, Base64 string\n *\n * **Security Best Practices:**\n *\n * When verifying Waffo's response signature fails:\n * 1. Stop sending new transactions to Waffo until the issue is resolved\n * 2. Investigate the cause and contact Waffo support\n * 3. Note: Waffo may have already processed your request, but you failed to\n * process the response due to signature verification failure\n */\n\nconst ALGORITHM = 'RSA-SHA256';\nconst KEY_SIZE = 2048;\n\n/**\n * Result of key pair generation.\n */\nexport interface KeyPairResult {\n /** Base64 encoded PKCS8 private key */\n privateKey: string;\n /** Base64 encoded X509 public key */\n publicKey: string;\n}\n\n/**\n * Signs data using RSA-SHA256.\n *\n * @param data - The data to sign (UTF-8 string)\n * @param base64PrivateKey - Base64 encoded PKCS8 private key\n * @returns Base64 encoded signature\n * @throws WaffoError if signing fails (S0003)\n *\n * @example\n * ```typescript\n * const signature = sign('{\"amount\":\"100.00\"}', privateKey);\n * ```\n */\nexport function sign(data: string, base64PrivateKey: string): string {\n try {\n const privateKeyBuffer = Buffer.from(base64PrivateKey, 'base64');\n const signer = crypto.createSign(ALGORITHM);\n signer.update(data, 'utf8');\n\n const signature = signer.sign({\n key: privateKeyBuffer,\n format: 'der',\n type: 'pkcs8',\n });\n\n return signature.toString('base64');\n } catch (error) {\n throw new WaffoError(\n WaffoErrorCode.SIGN_FAILED,\n `Failed to sign data: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Verifies a signature using RSA-SHA256.\n *\n * @param data - The original data (UTF-8 string)\n * @param base64Signature - Base64 encoded signature\n * @param base64PublicKey - Base64 encoded X509 public key\n * @returns true if signature is valid, false otherwise\n *\n * @example\n * ```typescript\n * const isValid = verify(responseBody, signature, waffoPublicKey);\n * if (!isValid) {\n * // Handle signature verification failure\n * }\n * ```\n */\nexport function verify(\n data: string,\n base64Signature: string,\n base64PublicKey: string\n): boolean {\n try {\n const publicKeyBuffer = Buffer.from(base64PublicKey, 'base64');\n const signatureBuffer = Buffer.from(base64Signature, 'base64');\n\n const verifier = crypto.createVerify(ALGORITHM);\n verifier.update(data, 'utf8');\n\n return verifier.verify(\n {\n key: publicKeyBuffer,\n format: 'der',\n type: 'spki',\n },\n signatureBuffer\n );\n } catch {\n // Invalid key or signature format - return false instead of throwing\n return false;\n }\n}\n\n/**\n * Validates a Base64 encoded PKCS8 private key.\n *\n * This method attempts to parse the key to ensure it's a valid RSA private key.\n * Use this at startup to fail fast if the private key is invalid.\n *\n * @param base64PrivateKey - Base64 encoded PKCS8 private key\n * @throws WaffoError if the key is invalid (S0007)\n *\n * @example\n * ```typescript\n * // Validate at initialization\n * validatePrivateKey(config.privateKey);\n * ```\n */\nexport function validatePrivateKey(base64PrivateKey: string): void {\n if (!base64PrivateKey || base64PrivateKey.trim() === '') {\n throw new WaffoError(\n WaffoErrorCode.INVALID_PRIVATE_KEY,\n 'Private key is null or empty'\n );\n }\n\n try {\n const keyBuffer = Buffer.from(base64PrivateKey, 'base64');\n crypto.createPrivateKey({\n key: keyBuffer,\n format: 'der',\n type: 'pkcs8',\n });\n } catch (error) {\n if (error instanceof WaffoError) throw error;\n\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes('bad base64')) {\n throw new WaffoError(\n WaffoErrorCode.INVALID_PRIVATE_KEY,\n 'Invalid private key: not valid Base64 encoding',\n error instanceof Error ? error : undefined\n );\n }\n throw new WaffoError(\n WaffoErrorCode.INVALID_PRIVATE_KEY,\n `Invalid private key: ${message}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Validates a Base64 encoded X509 public key.\n *\n * This method attempts to parse the key to ensure it's a valid RSA public key.\n * Use this at startup to fail fast if the public key is invalid.\n *\n * @param base64PublicKey - Base64 encoded X509 public key\n * @throws WaffoError if the key is invalid (S0002)\n *\n * @example\n * ```typescript\n * // Validate at initialization\n * validatePublicKey(config.waffoPublicKey);\n * ```\n */\nexport function validatePublicKey(base64PublicKey: string): void {\n if (!base64PublicKey || base64PublicKey.trim() === '') {\n throw new WaffoError(\n WaffoErrorCode.INVALID_PUBLIC_KEY,\n 'Public key is null or empty'\n );\n }\n\n try {\n const keyBuffer = Buffer.from(base64PublicKey, 'base64');\n crypto.createPublicKey({\n key: keyBuffer,\n format: 'der',\n type: 'spki',\n });\n } catch (error) {\n if (error instanceof WaffoError) throw error;\n\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes('bad base64')) {\n throw new WaffoError(\n WaffoErrorCode.INVALID_PUBLIC_KEY,\n 'Invalid public key: not valid Base64 encoding',\n error instanceof Error ? error : undefined\n );\n }\n throw new WaffoError(\n WaffoErrorCode.INVALID_PUBLIC_KEY,\n `Invalid public key: ${message}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Generates a new RSA key pair for testing or merchant key generation.\n *\n * @returns A new KeyPairResult containing Base64 encoded keys\n *\n * @example\n * ```typescript\n * const keyPair = generateKeyPair();\n * console.log('Private Key:', keyPair.privateKey);\n * console.log('Public Key:', keyPair.publicKey);\n * ```\n */\nexport function generateKeyPair(): KeyPairResult {\n try {\n const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {\n modulusLength: KEY_SIZE,\n publicKeyEncoding: {\n type: 'spki',\n format: 'der',\n },\n privateKeyEncoding: {\n type: 'pkcs8',\n format: 'der',\n },\n });\n\n return {\n privateKey: privateKey.toString('base64'),\n publicKey: publicKey.toString('base64'),\n };\n } catch (error) {\n throw new WaffoError(\n WaffoErrorCode.SIGN_FAILED,\n `Failed to generate key pair: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * RsaUtils namespace for backward compatibility.\n * @deprecated Use direct function imports instead.\n */\nexport const RsaUtils = {\n sign,\n verify,\n validatePrivateKey,\n validatePublicKey,\n generateKeyPair,\n};\n","import { Environment } from './environment';\nimport type { HttpTransport } from '../../net/http-transport';\nimport { RsaUtils } from '../../utils/rsa-utils';\n\n/**\n * Logger interface for SDK debugging.\n */\nexport interface WaffoLogger {\n debug(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\n/**\n * Configuration for the Waffo SDK.\n *\n * @example\n * ```typescript\n * const config: WaffoConfig = {\n * apiKey: 'your-api-key',\n * privateKey: 'base64-private-key',\n * waffoPublicKey: 'base64-public-key',\n * environment: Environment.SANDBOX,\n * merchantId: 'your-merchant-id',\n * };\n *\n * const waffo = new Waffo(config);\n * ```\n */\nexport interface WaffoConfig {\n /** API key provided by Waffo */\n apiKey: string;\n\n /** Merchant's private key for signing requests (Base64 encoded PKCS8) */\n privateKey: string;\n\n /** Waffo's public key for verifying responses (Base64 encoded X509) */\n waffoPublicKey: string;\n\n /** API environment (SANDBOX or PRODUCTION) */\n environment: Environment;\n\n /**\n * Merchant ID (required).\n * This will be automatically injected into requests that require merchantId.\n */\n merchantId: string;\n\n /** Connect timeout in milliseconds (default: 10000) */\n connectTimeout?: number;\n\n /** Read timeout in milliseconds (default: 30000) */\n readTimeout?: number;\n\n /** Optional logger for debugging */\n logger?: WaffoLogger;\n\n /**\n * Custom HTTP transport implementation.\n * If not set, the SDK uses the default fetch-based transport.\n */\n httpTransport?: HttpTransport;\n}\n\n/**\n * Environment variable names for configuration.\n */\nexport const WaffoConfigEnvVars = {\n API_KEY: 'WAFFO_API_KEY',\n PRIVATE_KEY: 'WAFFO_PRIVATE_KEY',\n PUBLIC_KEY: 'WAFFO_PUBLIC_KEY',\n MERCHANT_ID: 'WAFFO_MERCHANT_ID',\n ENVIRONMENT: 'WAFFO_ENVIRONMENT',\n} as const;\n\n/**\n * Default timeout values.\n */\nexport const WaffoConfigDefaults = {\n CONNECT_TIMEOUT: 10000,\n READ_TIMEOUT: 30000,\n} as const;\n\n/**\n * Creates and validates a WaffoConfig.\n *\n * @param config - Configuration options\n * @returns Validated configuration with defaults applied\n * @throws WaffoError if required fields are missing or keys are invalid\n *\n * @example\n * ```typescript\n * const config = createWaffoConfig({\n * apiKey: 'your-api-key',\n * privateKey: 'base64-private-key',\n * waffoPublicKey: 'base64-public-key',\n * environment: Environment.SANDBOX,\n * });\n * ```\n */\nexport function createWaffoConfig(config: WaffoConfig): WaffoConfig {\n // Validate required fields\n if (!config.apiKey) {\n throw new Error('apiKey is required');\n }\n if (!config.privateKey) {\n throw new Error('privateKey is required');\n }\n if (!config.waffoPublicKey) {\n throw new Error('waffoPublicKey is required');\n }\n if (!config.environment) {\n throw new Error('environment is required (SANDBOX or PRODUCTION)');\n }\n if (!config.merchantId) {\n throw new Error('merchantId is required');\n }\n\n // Validate keys\n RsaUtils.validatePrivateKey(config.privateKey);\n RsaUtils.validatePublicKey(config.waffoPublicKey);\n\n return {\n ...config,\n connectTimeout: config.connectTimeout ?? WaffoConfigDefaults.CONNECT_TIMEOUT,\n readTimeout: config.readTimeout ?? WaffoConfigDefaults.READ_TIMEOUT,\n };\n}\n\n/**\n * Creates a WaffoConfig from environment variables.\n *\n * Required environment variables:\n * - WAFFO_API_KEY\n * - WAFFO_PRIVATE_KEY\n * - WAFFO_PUBLIC_KEY\n * - WAFFO_ENVIRONMENT (SANDBOX or PRODUCTION)\n *\n * Optional:\n * - WAFFO_MERCHANT_ID\n *\n * @returns Configuration from environment variables\n * @throws Error if required environment variables are not set\n *\n * @example\n * ```typescript\n * // Set environment variables:\n * // export WAFFO_API_KEY=your-api-key\n * // export WAFFO_PRIVATE_KEY=base64-private-key\n * // export WAFFO_PUBLIC_KEY=base64-public-key\n * // export WAFFO_ENVIRONMENT=SANDBOX\n *\n * const config = WaffoConfig.fromEnv();\n * ```\n */\nexport function fromEnv(): WaffoConfig {\n const getEnv = (name: string, required = true): string => {\n const value = process.env[name];\n if (required && (!value || value.trim() === '')) {\n throw new Error(`Required environment variable ${name} is not set`);\n }\n return value || '';\n };\n\n const apiKey = getEnv(WaffoConfigEnvVars.API_KEY);\n const privateKey = getEnv(WaffoConfigEnvVars.PRIVATE_KEY);\n const waffoPublicKey = getEnv(WaffoConfigEnvVars.PUBLIC_KEY);\n const envStr = getEnv(WaffoConfigEnvVars.ENVIRONMENT);\n const merchantId = getEnv(WaffoConfigEnvVars.MERCHANT_ID);\n\n const environment = envStr.toUpperCase() as Environment;\n if (environment !== Environment.SANDBOX && environment !== Environment.PRODUCTION) {\n throw new Error(\n `Invalid ${WaffoConfigEnvVars.ENVIRONMENT} value: ${envStr}. Must be SANDBOX or PRODUCTION`\n );\n }\n\n return createWaffoConfig({\n apiKey,\n privateKey,\n waffoPublicKey,\n environment,\n merchantId,\n });\n}\n","/**\n * Generic API response wrapper.\n *\n * All API responses are wrapped in this class for consistent handling.\n *\n * @example\n * ```typescript\n * const response = await waffo.order().create(params);\n *\n * if (response.isSuccess()) {\n * const data = response.getData();\n * console.log('Order ID:', data?.acquiringOrderId);\n * } else {\n * console.error(`Error [${response.code}]: ${response.getMessage()}`);\n * }\n * ```\n */\nexport class ApiResponse<T> {\n /** Response code. \"0\" indicates success, other values indicate errors. */\n readonly code: string;\n\n /** Response data (present when code is \"0\") */\n readonly data?: T;\n\n /** Error message (present when code is not \"0\") */\n readonly message?: string;\n\n private constructor(code: string, data?: T, message?: string) {\n this.code = code;\n this.data = data;\n this.message = message;\n }\n\n /**\n * Creates a successful response.\n *\n * @param data - The response data\n */\n static success<T>(data?: T): ApiResponse<T> {\n return new ApiResponse('0', data);\n }\n\n /**\n * Creates an error response.\n *\n * @param code - The error code\n * @param message - The error message\n */\n static error<T>(code: string, message?: string): ApiResponse<T> {\n return new ApiResponse<T>(code, undefined, message);\n }\n\n /**\n * Checks if the response indicates success.\n *\n * @returns true if the response code is \"0\"\n */\n isSuccess(): boolean {\n return this.code === '0';\n }\n\n /**\n * Gets the response data.\n *\n * @returns The response data, or undefined if the response is an error\n */\n getData(): T | undefined {\n return this.data;\n }\n\n /**\n * Gets the error message.\n *\n * @returns The error message, or undefined if the response is successful\n */\n getMessage(): string | undefined {\n return this.message;\n }\n\n /**\n * Gets the response code.\n *\n * @returns The response code\n */\n getCode(): string {\n return this.code;\n }\n\n /**\n * Gets the response data or throws an error.\n *\n * @returns The response data\n * @throws Error if the response is not successful or data is undefined\n */\n getDataOrThrow(): T {\n if (!this.isSuccess()) {\n throw new Error(`[${this.code}] ${this.message ?? 'API error'}`);\n }\n if (this.data === undefined) {\n throw new Error('Response data is undefined');\n }\n return this.data;\n }\n}\n","import type { HttpTransport } from './http-transport';\nimport type { HttpRequest } from './http-request';\nimport type { HttpResponse } from './http-response';\n\n/**\n * Default HTTP transport implementation using Node.js native fetch.\n *\n * Requires Node.js 18+ for native fetch support.\n *\n * Features:\n * - TLS 1.2+ enforced by default\n * - Separate connectTimeout and readTimeout\n * - Proper error handling for network errors\n *\n * Timeout behavior:\n * - connectTimeout: Maximum time to establish connection and receive response headers\n * - readTimeout: Maximum time to read the response body after connection is established\n *\n * @example\n * ```typescript\n * const transport = new DefaultHttpTransport();\n * const response = await transport.send({\n * url: 'https://api.example.com/endpoint',\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: '{\"key\":\"value\"}',\n * connectTimeout: 10000,\n * readTimeout: 30000,\n * });\n * ```\n */\nexport class DefaultHttpTransport implements HttpTransport {\n /**\n * Sends an HTTP request using native fetch.\n *\n * @param request - The HTTP request to send\n * @returns The HTTP response\n * @throws Error if the request fails (network error, timeout, etc.)\n */\n async send(request: HttpRequest): Promise<HttpResponse> {\n // Create abort controller for connection phase\n const connectController = new AbortController();\n let connectTimeoutId: ReturnType<typeof setTimeout> | undefined;\n let readTimeoutId: ReturnType<typeof setTimeout> | undefined;\n let timeoutPhase: 'connect' | 'read' = 'connect';\n\n try {\n // Phase 1: Connection timeout - applies to fetch() until we get response headers\n connectTimeoutId = setTimeout(() => {\n connectController.abort();\n }, request.connectTimeout);\n\n const response = await fetch(request.url, {\n method: request.method,\n headers: request.headers,\n body: request.body,\n signal: connectController.signal,\n });\n\n // Connection established, clear connect timeout\n clearTimeout(connectTimeoutId);\n connectTimeoutId = undefined;\n\n // Phase 2: Read timeout - applies to reading the response body\n timeoutPhase = 'read';\n const readController = new AbortController();\n readTimeoutId = setTimeout(() => {\n readController.abort();\n }, request.readTimeout);\n\n // Read response body with read timeout\n // Note: We need to race between body reading and timeout\n // since response.text() doesn't accept AbortSignal directly\n const body = await Promise.race([\n response.text(),\n new Promise<never>((_, reject) => {\n readController.signal.addEventListener('abort', () => {\n reject(new Error('AbortError'));\n });\n }),\n ]);\n\n clearTimeout(readTimeoutId);\n readTimeoutId = undefined;\n\n // Extract headers (convert to lowercase keys)\n const headers: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n headers[key.toLowerCase()] = value;\n });\n\n return {\n statusCode: response.status,\n headers,\n body,\n };\n } catch (error) {\n // Re-throw with more descriptive message\n if (error instanceof Error) {\n if (error.name === 'AbortError' || error.message === 'AbortError') {\n const timeout = timeoutPhase === 'connect' ? request.connectTimeout : request.readTimeout;\n throw new Error(`Request ${timeoutPhase} timeout after ${timeout}ms`);\n }\n throw error;\n }\n throw new Error(`HTTP request failed: ${String(error)}`);\n } finally {\n if (connectTimeoutId) clearTimeout(connectTimeoutId);\n if (readTimeoutId) clearTimeout(readTimeoutId);\n }\n }\n}\n","import type { WaffoConfig, WaffoLogger, RequestOptions } from '../types/config';\nimport { EnvironmentBaseUrl, WaffoConfigDefaults } from '../types/config';\nimport { ApiResponse } from '../types/api-response';\nimport type { HttpTransport } from '../net/http-transport';\nimport { DefaultHttpTransport } from '../net/default-http-transport';\nimport { RsaUtils } from '../utils/rsa-utils';\nimport { WaffoErrorCode } from '../errors/waffo-error';\nimport { WaffoUnknownStatusError } from '../errors/waffo-unknown-status-error';\n\n// HTTP Headers\nconst HEADER_API_KEY = 'x-api-key';\nconst HEADER_SIGNATURE = 'x-signature';\nconst HEADER_API_VERSION = 'x-api-version';\nconst HEADER_SDK_VERSION = 'x-sdk-version';\nconst HEADER_CONTENT_TYPE = 'content-type';\nconst CONTENT_TYPE_JSON = 'application/json';\n\n// Version info\nconst API_VERSION = '1.0.0';\nconst SDK_VERSION = 'waffo-node/2.3.0';\n\n/**\n * HTTP client for making requests to the Waffo API.\n *\n * Handles:\n * - Request signing with merchant's private key\n * - Response signature verification with Waffo's public key\n * - MerchantId auto-injection\n * - Error handling and timeout management\n */\nexport class WaffoHttpClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly privateKey: string;\n private readonly waffoPublicKey: string;\n private readonly merchantId: string;\n private readonly connectTimeout: number;\n private readonly readTimeout: number;\n private readonly logger?: WaffoLogger;\n private readonly httpTransport: HttpTransport;\n\n constructor(config: WaffoConfig) {\n this.baseUrl = EnvironmentBaseUrl[config.environment];\n this.apiKey = config.apiKey;\n this.privateKey = config.privateKey;\n this.waffoPublicKey = config.waffoPublicKey;\n this.merchantId = config.merchantId;\n this.connectTimeout = config.connectTimeout ?? WaffoConfigDefaults.CONNECT_TIMEOUT;\n this.readTimeout = config.readTimeout ?? WaffoConfigDefaults.READ_TIMEOUT;\n this.logger = config.logger;\n this.httpTransport = config.httpTransport ?? new DefaultHttpTransport();\n }\n\n /**\n * Sends a POST request to the Waffo API.\n *\n * @param path - API endpoint path (e.g., \"/order/create\")\n * @param request - Request body\n * @param options - Per-request options\n * @returns API response\n * @throws WaffoUnknownStatusError for network errors or unknown status\n */\n async post<T extends object, R>(\n path: string,\n request: T,\n options?: RequestOptions\n ): Promise<ApiResponse<R>> {\n const url = this.baseUrl + path;\n const effectiveConnectTimeout = options?.connectTimeout ?? this.connectTimeout;\n const effectiveReadTimeout = options?.readTimeout ?? this.readTimeout;\n\n try {\n // Auto-inject merchantId if configured\n this.injectMerchantIdIfNeeded(request);\n\n // Serialize request\n const requestBody = JSON.stringify(request);\n\n // Sign the request\n const signature = RsaUtils.sign(requestBody, this.privateKey);\n\n this.logger?.debug(`Request URL: ${url}`);\n this.logger?.debug(`Request Body: ${requestBody}`);\n\n // Build and send HTTP request\n const httpResponse = await this.httpTransport.send({\n url,\n method: 'POST',\n headers: {\n [HEADER_CONTENT_TYPE]: CONTENT_TYPE_JSON,\n [HEADER_API_KEY]: this.apiKey,\n [HEADER_SIGNATURE]: signature,\n [HEADER_API_VERSION]: API_VERSION,\n [HEADER_SDK_VERSION]: SDK_VERSION,\n },\n body: requestBody,\n connectTimeout: effectiveConnectTimeout,\n readTimeout: effectiveReadTimeout,\n });\n\n this.logger?.debug(`Response Status: ${httpResponse.statusCode}`);\n this.logger?.debug(`Response Body: ${httpResponse.body}`);\n\n // Verify response signature\n const responseSignature = httpResponse.headers[HEADER_SIGNATURE];\n if (responseSignature) {\n const isValid = RsaUtils.verify(\n httpResponse.body,\n responseSignature,\n this.waffoPublicKey\n );\n if (!isValid) {\n this.logger?.error('Response signature verification failed');\n return ApiResponse.error(\n WaffoErrorCode.VERIFY_FAILED,\n 'Response signature verification failed'\n );\n }\n }\n\n // Parse response\n const response = this.parseResponse<R>(httpResponse.body);\n\n // Check for E0001 (unknown status)\n if (response.code === 'E0001') {\n throw new WaffoUnknownStatusError(\n WaffoUnknownStatusError.CODE_UNKNOWN_STATUS,\n response.getMessage() ?? 'Unknown status from server'\n );\n }\n\n return response;\n } catch (error) {\n // Re-throw WaffoUnknownStatusError\n if (error instanceof WaffoUnknownStatusError) {\n throw error;\n }\n\n // Handle network errors\n if (this.isNetworkError(error)) {\n this.logger?.error('Network error', error);\n throw new WaffoUnknownStatusError(\n WaffoUnknownStatusError.CODE_NETWORK_ERROR,\n `Network error, payment status unknown: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n\n // Handle serialization errors\n if (error instanceof SyntaxError) {\n this.logger?.error('JSON serialization error', error);\n return ApiResponse.error(\n WaffoErrorCode.SERIALIZE_FAILED,\n `Request serialization failed: ${error.message}`\n );\n }\n\n this.logger?.error('Unexpected error', error);\n return ApiResponse.error(\n WaffoErrorCode.UNEXPECTED,\n `Unexpected error: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Parses the API response body.\n */\n private parseResponse<R>(responseBody: string): ApiResponse<R> {\n try {\n const parsed = JSON.parse(responseBody) as {\n code?: string;\n msg?: string;\n data?: R;\n };\n\n const { code, msg, data } = parsed;\n\n if (code === '0') {\n return ApiResponse.success(data);\n } else {\n return ApiResponse.error(code ?? 'UNKNOWN', msg);\n }\n } catch (error) {\n this.logger?.error('Failed to parse response', error);\n return ApiResponse.error(\n 'C0001',\n `Failed to parse response: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Auto-injects merchantId into the request if configured.\n */\n private injectMerchantIdIfNeeded<T extends object>(request: T): void {\n if (!this.merchantId) return;\n\n const req = request as Record<string, unknown>;\n\n if (typeof req.merchantInfo === 'object' && req.merchantInfo !== null) {\n // merchantInfo already exists → inject merchantId if missing\n const info = req.merchantInfo as Record<string, unknown>;\n if (!info.merchantId) {\n info.merchantId = this.merchantId;\n }\n } else if ('merchantId' in req) {\n // Top-level merchantId (CancelSubscriptionParams etc.)\n if (!req.merchantId) {\n req.merchantId = this.merchantId;\n }\n } else {\n // merchantInfo not set (user didn't pass it) → create and inject\n req.merchantInfo = { merchantId: this.merchantId };\n }\n }\n\n /**\n * Checks if the error is a network-related error.\n */\n private isNetworkError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n\n const message = error.message.toLowerCase();\n return (\n error.name === 'AbortError' ||\n message.includes('timeout') ||\n message.includes('econnrefused') ||\n message.includes('enotfound') ||\n message.includes('network') ||\n message.includes('socket') ||\n message.includes('connection')\n );\n }\n}\n","import type { WaffoConfig, WaffoLogger } from '../types/config';\nimport type { SubscriptionInfo } from '../types/subscription';\nimport { RsaUtils } from '../utils/rsa-utils';\n\n/**\n * Webhook event types sent by Waffo.\n */\nexport enum WebhookEventType {\n PAYMENT_NOTIFICATION = 'PAYMENT_NOTIFICATION',\n REFUND_NOTIFICATION = 'REFUND_NOTIFICATION',\n SUBSCRIPTION_STATUS_NOTIFICATION = 'SUBSCRIPTION_STATUS_NOTIFICATION',\n SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION = 'SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION',\n}\n\n/**\n * Result of webhook handling.\n */\nexport interface WebhookResult {\n /** Whether the webhook was processed successfully */\n success: boolean;\n /** Response body to send back to Waffo */\n responseBody: string;\n /** Signature for the response body */\n responseSignature: string;\n /** Error message if processing failed */\n error?: string;\n}\n\n/**\n * Base notification interface.\n */\nexport interface BaseNotification {\n eventType: string;\n}\n\n// ─── Result Interfaces (nested payload, aligned with Java SDK) ───\n\n/**\n * Payment notification result payload (21 fields).\n */\nexport interface PaymentNotificationResult {\n paymentRequestId?: string;\n merchantOrderId?: string;\n acquiringOrderId?: string;\n orderStatus?: string;\n orderAction?: string;\n orderCurrency?: string;\n orderAmount?: string;\n userCurrency?: string;\n finalDealAmount?: string;\n orderDescription?: string;\n merchantInfo?: Record<string, unknown>;\n userInfo?: Record<string, unknown>;\n goodsInfo?: Record<string, unknown>;\n addressInfo?: Record<string, unknown>;\n paymentInfo?: Record<string, unknown>;\n orderRequestedAt?: string;\n orderExpiredAt?: string;\n orderUpdatedAt?: string;\n orderCompletedAt?: string;\n orderFailedReason?: Record<string, unknown>;\n extendInfo?: string;\n /**\n * The associated subscription info.\n */\n subscriptionInfo?: SubscriptionInfo;\n /**\n * Refund expiry time (ISO 8601 format).\n */\n refundExpiryAt?: string;\n /**\n * The address of the merchant page to redirect to when user cancels the payment.\n */\n cancelRedirectUrl?: string;\n [key: string]: unknown;\n}\n\n/**\n * Refund notification result payload (17 fields).\n */\nexport interface RefundNotificationResult {\n refundRequestId?: string;\n merchantRefundOrderId?: string;\n acquiringOrderId?: string;\n acquiringRefundOrderId?: string;\n origPaymentRequestId?: string;\n refundAmount?: string;\n refundStatus?: string;\n remainingRefundAmount?: string;\n userCurrency?: string;\n finalDealAmount?: string;\n refundReason?: string;\n refundRequestedAt?: string;\n refundUpdatedAt?: string;\n refundCompletedAt?: string;\n refundFailedReason?: Record<string, unknown>;\n userInfo?: Record<string, unknown>;\n extendInfo?: string;\n /**\n * Refund source. Possible values: MERCHANT, RDR, ETHOCA.\n */\n refundSource?: string;\n [key: string]: unknown;\n}\n\n/**\n * Subscription notification result payload (20 fields).\n * Shared by SubscriptionStatusNotification and SubscriptionPeriodChangedNotification.\n */\nexport interface SubscriptionNotificationResult {\n subscriptionRequest?: string;\n merchantSubscriptionId?: string;\n subscriptionId?: string;\n /**\n * Payment method's subscription id.\n */\n payMethodSubscriptionId?: string;\n subscriptionStatus?: string;\n subscriptionAction?: string;\n currency?: string;\n amount?: string;\n userCurrency?: string;\n productInfo?: Record<string, unknown>;\n merchantInfo?: Record<string, unknown>;\n userInfo?: Record<string, unknown>;\n goodsInfo?: Record<string, unknown>;\n addressInfo?: Record<string, unknown>;\n paymentInfo?: Record<string, unknown>;\n requestedAt?: string;\n updatedAt?: string;\n failedReason?: Record<string, unknown>;\n extendInfo?: string;\n subscriptionManagementUrl?: string;\n paymentDetails?: Record<string, unknown>[];\n [key: string]: unknown;\n}\n\n// ─── Notification Interfaces (nested structure: { eventType, result }) ───\n\n/**\n * Payment notification from Waffo.\n */\nexport interface PaymentNotification extends BaseNotification {\n eventType: 'PAYMENT_NOTIFICATION';\n result?: PaymentNotificationResult;\n [key: string]: unknown;\n}\n\n/**\n * Refund notification from Waffo.\n */\nexport interface RefundNotification extends BaseNotification {\n eventType: 'REFUND_NOTIFICATION';\n result?: RefundNotificationResult;\n [key: string]: unknown;\n}\n\n/**\n * Subscription status notification from Waffo.\n */\nexport interface SubscriptionStatusNotification extends BaseNotification {\n eventType: 'SUBSCRIPTION_STATUS_NOTIFICATION';\n result?: SubscriptionNotificationResult;\n [key: string]: unknown;\n}\n\n/**\n * Subscription period changed notification from Waffo.\n */\nexport interface SubscriptionPeriodChangedNotification extends BaseNotification {\n eventType: 'SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION';\n result?: SubscriptionNotificationResult;\n [key: string]: unknown;\n}\n\n// Handler types\ntype PaymentHandler = (notification: PaymentNotification) => void | Promise<void>;\ntype RefundHandler = (notification: RefundNotification) => void | Promise<void>;\ntype SubscriptionStatusHandler = (notification: SubscriptionStatusNotification) => void | Promise<void>;\ntype SubscriptionPaymentHandler = (notification: SubscriptionStatusNotification) => void | Promise<void>;\ntype SubscriptionPeriodChangedHandler = (notification: SubscriptionPeriodChangedNotification) => void | Promise<void>;\n\n/**\n * Webhook handler for processing Waffo webhook notifications.\n *\n * @example\n * ```typescript\n * // Setup handler\n * const handler = waffo.webhook()\n * .onPayment((notification) => {\n * console.log('Payment:', notification.result?.orderStatus);\n * })\n * .onRefund((notification) => {\n * console.log('Refund:', notification.result?.refundStatus);\n * });\n *\n * // Process webhook (e.g., in Express.js)\n * app.post('/webhook', async (req, res) => {\n * const body = req.body.toString();\n * const signature = req.headers['x-signature'];\n * const result = await handler.handleWebhook(body, signature);\n *\n * res.setHeader('X-SIGNATURE', result.responseSignature);\n * res.status(200).send(result.responseBody);\n * });\n * ```\n */\nexport class WebhookHandler {\n private readonly waffoPublicKey: string;\n private readonly privateKey: string;\n private readonly logger?: WaffoLogger;\n\n private paymentHandler?: PaymentHandler;\n private refundHandler?: RefundHandler;\n private subscriptionStatusHandler?: SubscriptionStatusHandler;\n private subscriptionPaymentHandler?: SubscriptionPaymentHandler;\n private subscriptionPeriodChangedHandler?: SubscriptionPeriodChangedHandler;\n\n constructor(config: WaffoConfig) {\n this.waffoPublicKey = config.waffoPublicKey;\n this.privateKey = config.privateKey;\n this.logger = config.logger;\n }\n\n /**\n * Registers a handler for payment notifications.\n */\n onPayment(handler: PaymentHandler): this {\n this.paymentHandler = handler;\n return this;\n }\n\n /**\n * Registers a handler for refund notifications.\n */\n onRefund(handler: RefundHandler): this {\n this.refundHandler = handler;\n return this;\n }\n\n /**\n * Registers a handler for subscription status notifications.\n */\n onSubscriptionStatus(handler: SubscriptionStatusHandler): this {\n this.subscriptionStatusHandler = handler;\n return this;\n }\n\n /**\n * Registers a fallback handler for SUBSCRIPTION_STATUS_NOTIFICATION events.\n * Only called when onSubscriptionStatus handler is not registered.\n */\n onSubscriptionPayment(handler: SubscriptionPaymentHandler): this {\n this.subscriptionPaymentHandler = handler;\n return this;\n }\n\n /**\n * Registers a handler for subscription period changed notifications.\n */\n onSubscriptionPeriodChanged(handler: SubscriptionPeriodChangedHandler): this {\n this.subscriptionPeriodChangedHandler = handler;\n return this;\n }\n\n /**\n * Processes a webhook notification.\n *\n * @param body - The raw webhook body\n * @param signature - The X-SIGNATURE header value\n * @returns Result with response body and signature\n */\n async handleWebhook(body: string, signature: string): Promise<WebhookResult> {\n try {\n // Verify signature\n if (!signature) {\n this.logger?.warn('Missing webhook signature');\n return this.createFailedResult('Missing signature');\n }\n\n const isValid = RsaUtils.verify(body, signature, this.waffoPublicKey);\n if (!isValid) {\n this.logger?.error('Invalid webhook signature');\n return this.createFailedResult('Invalid signature');\n }\n\n // Parse and route event\n const parsed = JSON.parse(body) as BaseNotification;\n const eventType = parsed.eventType as WebhookEventType;\n\n switch (eventType) {\n case WebhookEventType.PAYMENT_NOTIFICATION:\n if (this.paymentHandler) {\n await this.paymentHandler(parsed as PaymentNotification);\n }\n break;\n\n case WebhookEventType.REFUND_NOTIFICATION:\n if (this.refundHandler) {\n await this.refundHandler(parsed as RefundNotification);\n }\n break;\n\n case WebhookEventType.SUBSCRIPTION_STATUS_NOTIFICATION:\n // Priority: subscriptionStatusHandler > subscriptionPaymentHandler (fallback)\n if (this.subscriptionStatusHandler) {\n await this.subscriptionStatusHandler(parsed as SubscriptionStatusNotification);\n } else if (this.subscriptionPaymentHandler) {\n await this.subscriptionPaymentHandler(parsed as SubscriptionStatusNotification);\n }\n break;\n\n case WebhookEventType.SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION:\n if (this.subscriptionPeriodChangedHandler) {\n await this.subscriptionPeriodChangedHandler(parsed as SubscriptionPeriodChangedNotification);\n }\n break;\n\n default:\n this.logger?.warn(`Unknown webhook event type: ${eventType}`);\n return this.createFailedResult(`Unknown event type: ${eventType}`);\n }\n\n return this.createSuccessResult();\n } catch (error) {\n this.logger?.error('Error handling webhook', error);\n return this.createFailedResult(\n `Error handling webhook: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Verifies a webhook signature.\n *\n * @param body - The raw webhook body\n * @param signature - The X-SIGNATURE header value\n * @returns true if signature is valid\n */\n verifySignature(body: string, signature: string): boolean {\n return RsaUtils.verify(body, signature, this.waffoPublicKey);\n }\n\n /**\n * Builds a success response with signature.\n */\n buildSuccessResponse(): { body: string; signature: string } {\n const body = JSON.stringify({ status: 'success' });\n const signature = RsaUtils.sign(body, this.privateKey);\n return { body, signature };\n }\n\n /**\n * Builds a failed response with signature.\n */\n buildFailedResponse(message: string): { body: string; signature: string } {\n const body = JSON.stringify({ status: 'failed', message });\n const signature = RsaUtils.sign(body, this.privateKey);\n return { body, signature };\n }\n\n private createSuccessResult(): WebhookResult {\n const { body, signature } = this.buildSuccessResponse();\n return {\n success: true,\n responseBody: body,\n responseSignature: signature,\n };\n }\n\n private createFailedResult(error: string): WebhookResult {\n const { body, signature } = this.buildFailedResponse(error);\n return {\n success: false,\n responseBody: body,\n responseSignature: signature,\n error,\n };\n }\n}\n","import { WaffoHttpClient } from '../core/waffo-http-client';\n\n/**\n * Base class for API resources.\n */\nexport abstract class BaseResource {\n protected readonly httpClient: WaffoHttpClient;\n protected readonly basePath: string;\n\n constructor(httpClient: WaffoHttpClient, basePath: string) {\n this.httpClient = httpClient;\n this.basePath = basePath;\n }\n\n /**\n * Gets the full path for an endpoint.\n *\n * @param endpoint - The endpoint (e.g., \"/create\")\n * @returns Full path (e.g., \"/order/create\")\n */\n protected getPath(endpoint: string): string {\n return this.basePath + endpoint;\n }\n}\n","/**\n * Time formatting utilities for Waffo SDK.\n *\n * All timestamp fields use ISO 8601 format with exactly 3-digit milliseconds:\n * Pattern: yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\n *\n * @see sdk-spec/TIME_FORMAT.md\n */\n\n/**\n * Format a Date to ISO 8601 string with exactly 3-digit milliseconds.\n *\n * @example\n * formatTimestamp(new Date('2024-01-17T10:30:45.123Z'))\n * // Returns: '2024-01-17T10:30:45.123Z'\n *\n * @example\n * formatTimestamp(new Date('2024-01-17T10:30:45Z'))\n * // Returns: '2024-01-17T10:30:45.000Z'\n */\nexport function formatTimestamp(date: Date): string {\n const isoString = date.toISOString();\n // toISOString() already returns 3-digit milliseconds, but we ensure consistency\n // Format: YYYY-MM-DDTHH:mm:ss.sssZ\n return isoString;\n}\n\n/**\n * Get current timestamp in ISO 8601 format with 3-digit milliseconds.\n *\n * @example\n * getCurrentTimestamp()\n * // Returns: '2024-01-17T10:30:45.123Z'\n */\nexport function getCurrentTimestamp(): string {\n return formatTimestamp(new Date());\n}\n\n/**\n * Parse an ISO 8601 timestamp string to Date.\n *\n * @param timestamp - ISO 8601 timestamp string\n * @returns Date object\n * @throws Error if the timestamp is invalid\n */\nexport function parseTimestamp(timestamp: string): Date {\n const date = new Date(timestamp);\n if (isNaN(date.getTime())) {\n throw new Error(`Invalid timestamp: ${timestamp}`);\n }\n return date;\n}\n\n/**\n * TimeUtils class for static access to time formatting functions.\n */\nexport class TimeUtils {\n /**\n * Format a Date to ISO 8601 string with exactly 3-digit milliseconds.\n */\n static format(date: Date): string {\n return formatTimestamp(date);\n }\n\n /**\n * Get current timestamp in ISO 8601 format.\n */\n static now(): string {\n return getCurrentTimestamp();\n }\n\n /**\n * Parse an ISO 8601 timestamp string to Date.\n */\n static parse(timestamp: string): Date {\n return parseTimestamp(timestamp);\n }\n}\n","import { BaseResource } from './base-resource';\nimport { ApiResponse } from '../types/api-response';\nimport type { RequestOptions } from '../types/config';\nimport { getCurrentTimestamp } from '../utils/time-utils';\nimport type {\n CreateOrderParams,\n CreateOrderData,\n InquiryOrderParams,\n InquiryOrderData,\n CancelOrderParams,\n CancelOrderData,\n RefundOrderParams,\n RefundOrderData,\n CaptureOrderParams,\n CaptureOrderData,\n} from '../types/order';\n\n/**\n * Order resource for managing payment orders.\n *\n * @example\n * ```typescript\n * // Create an order\n * const response = await waffo.order().create({\n * paymentRequestId: 'unique-request-id',\n * merchantOrderId: 'order-123',\n * orderCurrency: 'USD',\n * orderAmount: '10.00',\n * orderDescription: 'Test order',\n * notifyUrl: 'https://example.com/webhook',\n * userInfo: {\n * userId: 'user-123',\n * userEmail: 'user@example.com',\n * },\n * paymentInfo: {\n * productName: 'Test Product',\n * },\n * });\n *\n * if (response.isSuccess()) {\n * console.log('Order created:', response.getData());\n * }\n * ```\n */\nexport class OrderResource extends BaseResource {\n private static readonly PATH_CREATE = '/create';\n private static readonly PATH_INQUIRY = '/inquiry';\n private static readonly PATH_CANCEL = '/cancel';\n private static readonly PATH_REFUND = '/refund';\n private static readonly PATH_CAPTURE = '/capture';\n\n /**\n * Creates a new payment order.\n *\n * @param params - Order creation parameters\n * @param options - Optional request options\n * @returns API response with order data\n * @throws WaffoUnknownStatusError for network errors\n */\n async create(\n params: CreateOrderParams,\n options?: RequestOptions\n ): Promise<ApiResponse<CreateOrderData>> {\n if (!params.orderRequestedAt) {\n params.orderRequestedAt = getCurrentTimestamp();\n }\n return this.httpClient.post<CreateOrderParams, CreateOrderData>(\n this.getPath(OrderResource.PATH_CREATE),\n params,\n options\n );\n }\n\n /**\n * Queries an existing order.\n *\n * @param params - Order inquiry parameters\n * @param options - Optional request options\n * @returns API response with order data\n * @throws WaffoUnknownStatusError for network errors\n */\n async inquiry(\n params: InquiryOrderParams,\n options?: RequestOptions\n ): Promise<ApiResponse<InquiryOrderData>> {\n return this.httpClient.post<InquiryOrderParams, InquiryOrderData>(\n this.getPath(OrderResource.PATH_INQUIRY),\n params,\n options\n );\n }\n\n /**\n * Cancels an existing order.\n *\n * @param params - Order cancellation parameters\n * @param options - Optional request options\n * @returns API response with cancellation result\n * @throws WaffoUnknownStatusError for network errors\n */\n async cancel(\n params: CancelOrderParams,\n options?: RequestOptions\n ): Promise<ApiResponse<CancelOrderData>> {\n if (!params.orderRequestedAt) {\n params.orderRequestedAt = getCurrentTimestamp();\n }\n return this.httpClient.post<CancelOrderParams, CancelOrderData>(\n this.getPath(OrderResource.PATH_CANCEL),\n params,\n options\n );\n }\n\n /**\n * Refunds an existing order.\n *\n * @param params - Order refund parameters\n * @param options - Optional request options\n * @returns API response with refund result\n * @throws WaffoUnknownStatusError for network errors\n */\n async refund(\n params: RefundOrderParams,\n options?: RequestOptions\n ): Promise<ApiResponse<RefundOrderData>> {\n return this.httpClient.post<RefundOrderParams, RefundOrderData>(\n this.getPath(OrderResource.PATH_REFUND),\n params,\n options\n );\n }\n\n /**\n * Captures an authorized order.\n *\n * @param params - Order capture parameters\n * @param options - Optional request options\n * @returns API response with capture result\n * @throws WaffoUnknownStatusError for network errors\n */\n async capture(\n params: CaptureOrderParams,\n options?: RequestOptions\n ): Promise<ApiResponse<CaptureOrderData>> {\n return this.httpClient.post<CaptureOrderParams, CaptureOrderData>(\n this.getPath(OrderResource.PATH_CAPTURE),\n params,\n options\n );\n }\n}\n","import { BaseResource } from './base-resource';\nimport { ApiResponse } from '../types/api-response';\nimport type { RequestOptions } from '../types/config';\nimport { getCurrentTimestamp } from '../utils/time-utils';\nimport type {\n CreateSubscriptionParams,\n CreateSubscriptionData,\n InquirySubscriptionParams,\n InquirySubscriptionData,\n CancelSubscriptionParams,\n CancelSubscriptionData,\n ManageSubscriptionParams,\n ManageSubscriptionData,\n SubscriptionChangeParams,\n SubscriptionChangeData,\n SubscriptionChangeInquiryParams,\n SubscriptionChangeInquiryData,\n} from '../types/subscription';\n\n/**\n * Subscription resource for managing recurring payments.\n *\n * @example\n * ```typescript\n * // Create a subscription\n * const response = await waffo.subscription().create({\n * subscriptionRequestId: 'unique-request-id',\n * merchantSubscriptionId: 'sub-123',\n * orderCurrency: 'USD',\n * orderAmount: '9.99',\n * orderDescription: 'Monthly subscription',\n * notifyUrl: 'https://example.com/webhook',\n * productInfo: {\n * productId: 'product-123',\n * productName: 'Premium Plan',\n * periodType: 'MONTH',\n * periodValue: 1,\n * },\n * userInfo: {\n * userId: 'user-123',\n * userEmail: 'user@example.com',\n * },\n * paymentInfo: {\n * productName: 'Premium Plan',\n * },\n * });\n *\n * if (response.isSuccess()) {\n * console.log('Subscription created:', response.getData());\n * }\n * ```\n */\nexport class SubscriptionResource extends BaseResource {\n private static readonly PATH_CREATE = '/create';\n private static readonly PATH_INQUIRY = '/inquiry';\n private static readonly PATH_CANCEL = '/cancel';\n private static readonly PATH_MANAGE = '/manage';\n private static readonly PATH_CHANGE = '/change';\n private static readonly PATH_CHANGE_INQUIRY = '/change/inquiry';\n\n /**\n * Creates a new subscription.\n *\n * @param params - Subscription creation parameters\n * @param options - Optional request options\n * @returns API response with subscription data\n * @throws WaffoUnknownStatusError for network errors\n */\n async create(\n params: CreateSubscriptionParams,\n options?: RequestOptions\n ): Promise<ApiResponse<CreateSubscriptionData>> {\n if (!params.requestedAt) {\n params.requestedAt = getCurrentTimestamp();\n }\n return this.httpClient.post<CreateSubscriptionParams, CreateSubscriptionData>(\n this.getPath(SubscriptionResource.PATH_CREATE),\n params,\n options\n );\n }\n\n /**\n * Queries an existing subscription.\n *\n * @param params - Subscription inquiry parameters\n * @param options - Optional request options\n * @returns API response with subscription data\n * @throws WaffoUnknownStatusError for network errors\n */\n async inquiry(\n params: InquirySubscriptionParams,\n options?: RequestOptions\n ): Promise<ApiResponse<InquirySubscriptionData>> {\n return this.httpClient.post<InquirySubscriptionParams, InquirySubscriptionData>(\n this.getPath(SubscriptionResource.PATH_INQUIRY),\n params,\n options\n );\n }\n\n /**\n * Cancels an existing subscription.\n *\n * @param params - Subscription cancellation parameters\n * @param options - Optional request options\n * @returns API response with cancellation result\n * @throws WaffoUnknownStatusError for network errors\n */\n async cancel(\n params: CancelSubscriptionParams,\n options?: RequestOptions\n ): Promise<ApiResponse<CancelSubscriptionData>> {\n if (!params.requestedAt) {\n params.requestedAt = getCurrentTimestamp();\n }\n return this.httpClient.post<CancelSubscriptionParams, CancelSubscriptionData>(\n this.getPath(SubscriptionResource.PATH_CANCEL),\n params,\n options\n );\n }\n\n /**\n * Manages an existing subscription (pause, resume, update).\n *\n * @param params - Subscription management parameters\n * @param options - Optional request options\n * @returns API response with management result\n * @throws WaffoUnknownStatusError for network errors\n */\n async manage(\n params: ManageSubscriptionParams,\n options?: RequestOptions\n ): Promise<ApiResponse<ManageSubscriptionData>> {\n return this.httpClient.post<ManageSubscriptionParams, ManageSubscriptionData>(\n this.getPath(SubscriptionResource.PATH_MANAGE),\n params,\n options\n );\n }\n\n /**\n * Changes (upgrades/downgrades) an existing subscription.\n *\n * This method allows changing an active subscription to a new plan with different\n * pricing, billing period, or other terms. The remaining amount from the original\n * subscription can be applied to the new subscription.\n *\n * @param params - Subscription change parameters\n * @param options - Optional request options\n * @returns API response with change result\n * @throws WaffoUnknownStatusError for network errors\n *\n * @example\n * ```typescript\n * const response = await waffo.subscription().change({\n * subscriptionRequest: 'new-request-id',\n * originSubscriptionRequest: 'original-request-id',\n * remainingAmount: '50.00',\n * currency: 'HKD',\n * requestedAt: new Date().toISOString(),\n * notifyUrl: 'https://example.com/webhook',\n * productInfoList: [{\n * description: 'Premium Monthly',\n * periodType: 'MONTH',\n * periodInterval: '1',\n * amount: '199.00',\n * }],\n * userInfo: { userId: 'user-123', userEmail: 'user@example.com' },\n * goodsInfo: { goodsId: 'premium', goodsName: 'Premium Plan' },\n * paymentInfo: { productName: 'SUBSCRIPTION' },\n * });\n *\n * if (response.isSuccess()) {\n * const data = response.getData();\n * if (data?.subscriptionChangeStatus === 'AUTHORIZATION_REQUIRED') {\n * // Redirect user to authorization URL\n * const webUrl = JSON.parse(data.subscriptionAction || '{}').webUrl;\n * }\n * }\n * ```\n */\n async change(\n params: SubscriptionChangeParams,\n options?: RequestOptions\n ): Promise<ApiResponse<SubscriptionChangeData>> {\n if (!params.requestedAt) {\n params.requestedAt = getCurrentTimestamp();\n }\n return this.httpClient.post<SubscriptionChangeParams, SubscriptionChangeData>(\n this.getPath(SubscriptionResource.PATH_CHANGE),\n params,\n options\n );\n }\n\n /**\n * Queries the status of a subscription change.\n *\n * Use this method to check the current status of a subscription change operation,\n * especially after network errors or when status is uncertain.\n *\n * @param params - Change inquiry parameters\n * @param options - Optional request options\n * @returns API response with change inquiry data\n *\n * @example\n * ```typescript\n * const response = await waffo.subscription().changeInquiry({\n * subscriptionRequest: 'new-request-id',\n * originSubscriptionRequest: 'original-request-id',\n * });\n *\n * if (response.isSuccess()) {\n * const data = response.getData();\n * console.log('Change status:', data?.subscriptionChangeStatus);\n * }\n * ```\n */\n async changeInquiry(\n params: SubscriptionChangeInquiryParams,\n options?: RequestOptions\n ): Promise<ApiResponse<SubscriptionChangeInquiryData>> {\n try {\n return await this.httpClient.post<SubscriptionChangeInquiryParams, SubscriptionChangeInquiryData>(\n this.getPath(SubscriptionResource.PATH_CHANGE_INQUIRY),\n params,\n options\n );\n } catch (error) {\n // For inquiry operations, catch unknown status errors and return error response\n if (error && typeof error === 'object' && 'errorCode' in error) {\n return ApiResponse.error('E0001', String((error as { message?: string }).message || 'Unknown error'));\n }\n throw error;\n }\n }\n}\n","import { BaseResource } from './base-resource';\nimport { ApiResponse } from '../types/api-response';\nimport type { RequestOptions } from '../types/config';\nimport type { InquiryRefundParams, InquiryRefundData } from '../types/refund';\n\n/**\n * Refund resource for querying refund status.\n *\n * Note: To initiate a refund, use `waffo.order().refund()` instead.\n *\n * @example\n * ```typescript\n * // Query refund status\n * const response = await waffo.refund().inquiry({\n * refundRequestId: 'refund-request-123',\n * });\n *\n * if (response.isSuccess()) {\n * const data = response.getData();\n * console.log('Refund status:', data?.refundStatus);\n * }\n * ```\n */\nexport class RefundResource extends BaseResource {\n private static readonly PATH_INQUIRY = '/inquiry';\n\n /**\n * Queries the status of a refund.\n *\n * @param params - Refund inquiry parameters\n * @param options - Optional request options\n * @returns API response with refund data\n * @throws WaffoUnknownStatusError for network errors\n */\n async inquiry(\n params: InquiryRefundParams,\n options?: RequestOptions\n ): Promise<ApiResponse<InquiryRefundData>> {\n return this.httpClient.post<InquiryRefundParams, InquiryRefundData>(\n this.getPath(RefundResource.PATH_INQUIRY),\n params,\n options\n );\n }\n}\n","import { BaseResource } from './base-resource';\nimport { ApiResponse } from '../types/api-response';\nimport type { RequestOptions } from '../types/config';\nimport type {\n InquiryMerchantConfigParams,\n InquiryMerchantConfigData,\n} from '../types/merchant';\n\n/**\n * Merchant config resource for querying merchant configuration.\n *\n * @example\n * ```typescript\n * // Query merchant config\n * const response = await waffo.merchantConfig().inquiry({\n * merchantId: 'merchant-123',\n * });\n *\n * if (response.isSuccess()) {\n * const data = response.getData();\n * console.log('Merchant status:', data?.merchantStatus);\n * console.log('Supported currencies:', data?.supportedCurrencies);\n * }\n * ```\n */\nexport class MerchantConfigResource extends BaseResource {\n private static readonly PATH_INQUIRY = '/inquiry';\n\n /**\n * Queries merchant configuration.\n *\n * @param params - Merchant config inquiry parameters\n * @param options - Optional request options\n * @returns API response with merchant config data\n * @throws WaffoUnknownStatusError for network errors\n */\n async inquiry(\n params: InquiryMerchantConfigParams,\n options?: RequestOptions\n ): Promise<ApiResponse<InquiryMerchantConfigData>> {\n return this.httpClient.post<InquiryMerchantConfigParams, InquiryMerchantConfigData>(\n this.getPath(MerchantConfigResource.PATH_INQUIRY),\n params,\n options\n );\n }\n}\n","import { BaseResource } from './base-resource';\nimport { ApiResponse } from '../types/api-response';\nimport type { RequestOptions } from '../types/config';\nimport type {\n InquiryPayMethodConfigParams,\n InquiryPayMethodConfigData,\n} from '../types/merchant';\n\n/**\n * Pay method config resource for querying available payment methods.\n *\n * @example\n * ```typescript\n * // Query available payment methods\n * const response = await waffo.payMethodConfig().inquiry({\n * merchantId: 'merchant-123',\n * });\n *\n * if (response.isSuccess()) {\n * const data = response.getData();\n * data?.payMethods?.forEach(method => {\n * console.log(`${method.payMethodName}: ${method.payMethodStatus}`);\n * });\n * }\n * ```\n */\nexport class PayMethodConfigResource extends BaseResource {\n private static readonly PATH_INQUIRY = '/inquiry';\n\n /**\n * Queries available payment methods.\n *\n * @param params - Pay method config inquiry parameters\n * @param options - Optional request options\n * @returns API response with pay method config data\n * @throws WaffoUnknownStatusError for network errors\n */\n async inquiry(\n params: InquiryPayMethodConfigParams,\n options?: RequestOptions\n ): Promise<ApiResponse<InquiryPayMethodConfigData>> {\n return this.httpClient.post<InquiryPayMethodConfigParams, InquiryPayMethodConfigData>(\n this.getPath(PayMethodConfigResource.PATH_INQUIRY),\n params,\n options\n );\n }\n}\n","import type { WaffoConfig } from './types/config';\nimport { fromEnv } from './types/config';\nimport { WaffoHttpClient } from './core/waffo-http-client';\nimport { WebhookHandler } from './core/webhook-handler';\nimport { OrderResource } from './resources/order-resource';\nimport { SubscriptionResource } from './resources/subscription-resource';\nimport { RefundResource } from './resources/refund-resource';\nimport { MerchantConfigResource } from './resources/merchant-config-resource';\nimport { PayMethodConfigResource } from './resources/pay-method-config-resource';\n\n/**\n * Main entry point for the Waffo SDK.\n *\n * @example\n * ```typescript\n * import { Waffo, Environment } from '@waffo/waffo-node';\n *\n * // Create SDK instance\n * const waffo = new Waffo({\n * apiKey: 'your-api-key',\n * privateKey: 'your-base64-private-key',\n * waffoPublicKey: 'waffo-base64-public-key',\n * environment: Environment.SANDBOX,\n * merchantId: 'your-merchant-id', // required, auto-injected into requests\n * });\n *\n * // Create an order\n * const response = await waffo.order().create({\n * paymentRequestId: 'unique-request-id',\n * merchantOrderId: 'order-123',\n * orderCurrency: 'USD',\n * orderAmount: '10.00',\n * orderDescription: 'Test order',\n * notifyUrl: 'https://example.com/webhook',\n * userInfo: {\n * userId: 'user-123',\n * userEmail: 'user@example.com',\n * },\n * paymentInfo: {\n * productName: 'Test Product',\n * },\n * });\n *\n * if (response.isSuccess()) {\n * console.log('Order created:', response.getData());\n * } else {\n * console.error('Failed:', response.getCode(), response.getMessage());\n * }\n * ```\n */\nexport class Waffo {\n private readonly config: WaffoConfig;\n private readonly httpClient: WaffoHttpClient;\n\n // Lazy-initialized resources\n private _order?: OrderResource;\n private _subscription?: SubscriptionResource;\n private _refund?: RefundResource;\n private _merchantConfig?: MerchantConfigResource;\n private _payMethodConfig?: PayMethodConfigResource;\n\n /**\n * Creates a new Waffo SDK instance.\n *\n * @param config - SDK configuration\n */\n constructor(config: WaffoConfig) {\n this.config = config;\n this.httpClient = new WaffoHttpClient(config);\n }\n\n /**\n * Creates a Waffo SDK instance from environment variables.\n *\n * Required environment variables:\n * - WAFFO_API_KEY\n * - WAFFO_PRIVATE_KEY\n * - WAFFO_PUBLIC_KEY\n * - WAFFO_ENVIRONMENT (SANDBOX or PRODUCTION)\n *\n * Optional environment variables:\n * - WAFFO_MERCHANT_ID\n * - WAFFO_CONNECT_TIMEOUT\n * - WAFFO_READ_TIMEOUT\n *\n * @returns Waffo SDK instance\n */\n static fromEnv(): Waffo {\n return new Waffo(fromEnv());\n }\n\n /**\n * Returns the order resource for managing payment orders.\n *\n * @returns Order resource\n */\n order(): OrderResource {\n if (!this._order) {\n this._order = new OrderResource(this.httpClient, '/order');\n }\n return this._order;\n }\n\n /**\n * Returns the subscription resource for managing recurring payments.\n *\n * @returns Subscription resource\n */\n subscription(): SubscriptionResource {\n if (!this._subscription) {\n this._subscription = new SubscriptionResource(this.httpClient, '/subscription');\n }\n return this._subscription;\n }\n\n /**\n * Returns the refund resource for querying refund status.\n *\n * @returns Refund resource\n */\n refund(): RefundResource {\n if (!this._refund) {\n this._refund = new RefundResource(this.httpClient, '/refund');\n }\n return this._refund;\n }\n\n /**\n * Returns the merchant config resource.\n *\n * @returns Merchant config resource\n */\n merchantConfig(): MerchantConfigResource {\n if (!this._merchantConfig) {\n this._merchantConfig = new MerchantConfigResource(this.httpClient, '/merchant/config');\n }\n return this._merchantConfig;\n }\n\n /**\n * Returns the pay method config resource.\n *\n * @returns Pay method config resource\n */\n payMethodConfig(): PayMethodConfigResource {\n if (!this._payMethodConfig) {\n this._payMethodConfig = new PayMethodConfigResource(this.httpClient, '/paymethod/config');\n }\n return this._payMethodConfig;\n }\n\n /**\n * Creates a webhook handler for processing Waffo webhook notifications.\n *\n * @returns Webhook handler\n *\n * @example\n * ```typescript\n * // Setup webhook handler\n * const handler = waffo.webhook()\n * .onPayment((notification) => {\n * console.log('Payment:', notification.result?.orderStatus);\n * })\n * .onRefund((notification) => {\n * console.log('Refund:', notification.result?.refundStatus);\n * })\n * .onSubscriptionStatus((notification) => {\n * console.log('Subscription:', notification.result?.subscriptionStatus);\n * });\n *\n * // In Express.js route handler\n * app.post('/webhook', async (req, res) => {\n * const body = req.body.toString();\n * const signature = req.headers['x-signature'] as string;\n * const result = await handler.handleWebhook(body, signature);\n *\n * res.setHeader('X-SIGNATURE', result.responseSignature);\n * res.status(200).send(result.responseBody);\n * });\n * ```\n */\n webhook(): WebhookHandler {\n return new WebhookHandler(this.config);\n }\n\n /**\n * Returns the current configuration.\n *\n * @returns SDK configuration (with sensitive data)\n */\n getConfig(): WaffoConfig {\n return this.config;\n }\n}\n"]}