@waffo/waffo-node 3.0.1 → 3.2.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
@@ -370,6 +370,10 @@ var ApiResponse = class _ApiResponse {
370
370
  getData() {
371
371
  return this.data;
372
372
  }
373
+ /** Returns the same JSON data with business string literals opened to future values. */
374
+ getOpenData() {
375
+ return this.data;
376
+ }
373
377
  /**
374
378
  * Gets the error message.
375
379
  *
@@ -477,7 +481,7 @@ var HEADER_SDK_VERSION = "x-sdk-version";
477
481
  var HEADER_CONTENT_TYPE = "content-type";
478
482
  var CONTENT_TYPE_JSON = "application/json";
479
483
  var API_VERSION = "1.0.0";
480
- var SDK_VERSION = "waffo-node/3.0.1";
484
+ var SDK_VERSION = "waffo-node/3.2.0";
481
485
  var WaffoHttpClient = class {
482
486
  baseUrl;
483
487
  apiKey;
@@ -507,15 +511,16 @@ var WaffoHttpClient = class {
507
511
  * @param path - API endpoint path (e.g., "/order/create")
508
512
  * @param request - Request body
509
513
  * @param options - Per-request options
514
+ * @param merchantIdPath - Contract path for merchantId, null for no injection, or omitted for legacy inference
510
515
  * @returns API response
511
516
  * @throws WaffoUnknownStatusError for network errors or unknown status
512
517
  */
513
- async post(path, request, options) {
518
+ async post(path, request, options, merchantIdPath) {
514
519
  const url = this.baseUrl + path;
515
520
  const effectiveConnectTimeout = options?.connectTimeout ?? this.connectTimeout;
516
521
  const effectiveReadTimeout = options?.readTimeout ?? this.readTimeout;
517
522
  try {
518
- this.injectMerchantIdIfNeeded(request);
523
+ this.injectMerchantIdIfNeeded(request, merchantIdPath);
519
524
  const requestBody = JSON.stringify(request);
520
525
  const signature = RsaUtils.sign(requestBody, this.privateKey);
521
526
  this.logger?.debug(`Request URL: ${url}`);
@@ -608,9 +613,24 @@ var WaffoHttpClient = class {
608
613
  /**
609
614
  * Auto-injects merchantId into the request if configured.
610
615
  */
611
- injectMerchantIdIfNeeded(request) {
616
+ injectMerchantIdIfNeeded(request, merchantIdPath) {
612
617
  if (!this.merchantId) return;
613
618
  const req = request;
619
+ if (merchantIdPath === null) return;
620
+ if (merchantIdPath === "merchantInfo.merchantId") {
621
+ const merchantInfo = typeof req.merchantInfo === "object" && req.merchantInfo !== null ? req.merchantInfo : {};
622
+ if (!merchantInfo.merchantId) {
623
+ merchantInfo.merchantId = this.merchantId;
624
+ }
625
+ req.merchantInfo = merchantInfo;
626
+ return;
627
+ }
628
+ if (merchantIdPath === "merchantId") {
629
+ if (!req.merchantId) {
630
+ req.merchantId = this.merchantId;
631
+ }
632
+ return;
633
+ }
614
634
  if (typeof req.merchantInfo === "object" && req.merchantInfo !== null) {
615
635
  const info = req.merchantInfo;
616
636
  if (!info.merchantId) {
@@ -652,6 +672,7 @@ var WebhookHandler = class {
652
672
  subscriptionPaymentHandler;
653
673
  subscriptionPeriodChangedHandler;
654
674
  subscriptionChangeHandler;
675
+ customEventHandlers = /* @__PURE__ */ new Map();
655
676
  constructor(config) {
656
677
  this.waffoPublicKey = config.waffoPublicKey;
657
678
  this.privateKey = config.privateKey;
@@ -700,6 +721,20 @@ var WebhookHandler = class {
700
721
  this.subscriptionChangeHandler = handler;
701
722
  return this;
702
723
  }
724
+ /** Registers an exact custom event name before receiving webhooks. Later registration replaces the same name. */
725
+ onEvent(eventType, handler) {
726
+ if (typeof eventType !== "string" || !eventType.trim()) {
727
+ throw new WaffoError(WaffoErrorCode.UNEXPECTED, "Custom event name must not be blank");
728
+ }
729
+ if (typeof handler !== "function") {
730
+ throw new WaffoError(WaffoErrorCode.UNEXPECTED, "Custom event handler must be a function");
731
+ }
732
+ if (Object.values(WebhookEventType).some((known) => known === eventType)) {
733
+ throw new WaffoError(WaffoErrorCode.UNEXPECTED, `Use the dedicated handler for built-in event: ${eventType}`);
734
+ }
735
+ this.customEventHandlers.set(eventType, handler);
736
+ return this;
737
+ }
703
738
  /**
704
739
  * Processes a webhook notification.
705
740
  *
@@ -719,6 +754,9 @@ var WebhookHandler = class {
719
754
  return this.createFailedResult("Invalid signature");
720
755
  }
721
756
  const parsed = JSON.parse(body);
757
+ if (!parsed || typeof parsed.eventType !== "string") {
758
+ return this.createFailedResult("Unknown event type");
759
+ }
722
760
  const eventType = parsed.eventType;
723
761
  switch (eventType) {
724
762
  case "PAYMENT_NOTIFICATION" /* PAYMENT_NOTIFICATION */:
@@ -748,9 +786,15 @@ var WebhookHandler = class {
748
786
  await this.subscriptionChangeHandler(parsed);
749
787
  }
750
788
  break;
751
- default:
752
- this.logger?.warn(`Unknown webhook event type: ${eventType}`);
753
- return this.createFailedResult(`Unknown event type: ${eventType}`);
789
+ default: {
790
+ const handler = this.customEventHandlers.get(eventType);
791
+ if (!handler) {
792
+ this.logger?.warn(`Unknown webhook event type: ${eventType}`);
793
+ return this.createFailedResult(`Unknown event type: ${eventType}`);
794
+ }
795
+ await handler(parsed);
796
+ break;
797
+ }
754
798
  }
755
799
  return this.createSuccessResult();
756
800
  } catch (error) {
@@ -855,7 +899,8 @@ var OrderResource = class _OrderResource extends BaseResource {
855
899
  return this.httpClient.post(
856
900
  this.getPath(_OrderResource.PATH_CREATE),
857
901
  params,
858
- options
902
+ options,
903
+ "merchantInfo.merchantId"
859
904
  );
860
905
  }
861
906
  /**
@@ -870,7 +915,8 @@ var OrderResource = class _OrderResource extends BaseResource {
870
915
  return this.httpClient.post(
871
916
  this.getPath(_OrderResource.PATH_INQUIRY),
872
917
  params,
873
- options
918
+ options,
919
+ null
874
920
  );
875
921
  }
876
922
  /**
@@ -888,7 +934,8 @@ var OrderResource = class _OrderResource extends BaseResource {
888
934
  return this.httpClient.post(
889
935
  this.getPath(_OrderResource.PATH_CANCEL),
890
936
  params,
891
- options
937
+ options,
938
+ "merchantId"
892
939
  );
893
940
  }
894
941
  /**
@@ -906,7 +953,8 @@ var OrderResource = class _OrderResource extends BaseResource {
906
953
  return this.httpClient.post(
907
954
  this.getPath(_OrderResource.PATH_REFUND),
908
955
  params,
909
- options
956
+ options,
957
+ "merchantId"
910
958
  );
911
959
  }
912
960
  /**
@@ -924,7 +972,8 @@ var OrderResource = class _OrderResource extends BaseResource {
924
972
  return this.httpClient.post(
925
973
  this.getPath(_OrderResource.PATH_CAPTURE),
926
974
  params,
927
- options
975
+ options,
976
+ "merchantId"
928
977
  );
929
978
  }
930
979
  };
@@ -938,14 +987,6 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
938
987
  static PATH_UPDATE = "/update";
939
988
  static PATH_CHANGE = "/change";
940
989
  static PATH_CHANGE_INQUIRY = "/change/inquiry";
941
- /**
942
- * Creates a new subscription.
943
- *
944
- * @param params - Subscription creation parameters
945
- * @param options - Optional request options
946
- * @returns API response with subscription data
947
- * @throws WaffoUnknownStatusError for network errors
948
- */
949
990
  async create(params, options) {
950
991
  if (!params.requestedAt) {
951
992
  params.requestedAt = getCurrentTimestamp();
@@ -953,7 +994,8 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
953
994
  return this.httpClient.post(
954
995
  this.getPath(_SubscriptionResource.PATH_CREATE),
955
996
  params,
956
- options
997
+ options,
998
+ "merchantInfo.merchantId"
957
999
  );
958
1000
  }
959
1001
  /**
@@ -968,7 +1010,8 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
968
1010
  return this.httpClient.post(
969
1011
  this.getPath(_SubscriptionResource.PATH_INQUIRY),
970
1012
  params,
971
- options
1013
+ options,
1014
+ null
972
1015
  );
973
1016
  }
974
1017
  /**
@@ -986,7 +1029,8 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
986
1029
  return this.httpClient.post(
987
1030
  this.getPath(_SubscriptionResource.PATH_CANCEL),
988
1031
  params,
989
- options
1032
+ options,
1033
+ "merchantId"
990
1034
  );
991
1035
  }
992
1036
  /**
@@ -1001,7 +1045,8 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
1001
1045
  return this.httpClient.post(
1002
1046
  this.getPath(_SubscriptionResource.PATH_MANAGE),
1003
1047
  params,
1004
- options
1048
+ options,
1049
+ null
1005
1050
  );
1006
1051
  }
1007
1052
  /**
@@ -1019,50 +1064,10 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
1019
1064
  return this.httpClient.post(
1020
1065
  this.getPath(_SubscriptionResource.PATH_UPDATE),
1021
1066
  params,
1022
- options
1067
+ options,
1068
+ null
1023
1069
  );
1024
1070
  }
1025
- /**
1026
- * Changes (upgrades/downgrades) an existing subscription.
1027
- *
1028
- * This method allows changing an active subscription to a new plan with different
1029
- * pricing, billing period, or other terms. The remaining amount from the original
1030
- * subscription can be applied to the new subscription.
1031
- *
1032
- * @param params - Subscription change parameters
1033
- * @param options - Optional request options
1034
- * @returns API response with change result
1035
- * @throws WaffoUnknownStatusError for network errors
1036
- *
1037
- * @example
1038
- * ```typescript
1039
- * const response = await waffo.subscription().change({
1040
- * subscriptionRequest: 'new-request-id',
1041
- * originSubscriptionRequest: 'original-request-id',
1042
- * remainingAmount: '50.00',
1043
- * currency: 'HKD',
1044
- * requestedAt: new Date().toISOString(),
1045
- * notifyUrl: 'https://example.com/webhook',
1046
- * productInfoList: [{
1047
- * description: 'Premium Monthly',
1048
- * periodType: 'MONTH',
1049
- * periodInterval: '1',
1050
- * amount: '199.00',
1051
- * }],
1052
- * userInfo: { userId: 'user-123', userEmail: 'user@example.com' },
1053
- * goodsInfo: { goodsId: 'premium', goodsName: 'Premium Plan' },
1054
- * paymentInfo: { productName: 'SUBSCRIPTION' },
1055
- * });
1056
- *
1057
- * if (response.isSuccess()) {
1058
- * const data = response.getData();
1059
- * if (data?.subscriptionChangeStatus === 'AUTHORIZATION_REQUIRED') {
1060
- * // Redirect user to authorization URL
1061
- * const webUrl = JSON.parse(data.subscriptionAction || '{}').webUrl;
1062
- * }
1063
- * }
1064
- * ```
1065
- */
1066
1071
  async change(params, options) {
1067
1072
  if (!params.requestedAt) {
1068
1073
  params.requestedAt = getCurrentTimestamp();
@@ -1070,7 +1075,8 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
1070
1075
  return this.httpClient.post(
1071
1076
  this.getPath(_SubscriptionResource.PATH_CHANGE),
1072
1077
  params,
1073
- options
1078
+ options,
1079
+ "merchantInfo.merchantId"
1074
1080
  );
1075
1081
  }
1076
1082
  /**
@@ -1101,11 +1107,16 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
1101
1107
  return await this.httpClient.post(
1102
1108
  this.getPath(_SubscriptionResource.PATH_CHANGE_INQUIRY),
1103
1109
  params,
1104
- options
1110
+ options,
1111
+ null
1105
1112
  );
1106
1113
  } catch (error) {
1107
1114
  if (error && typeof error === "object" && "errorCode" in error) {
1108
- return ApiResponse.error("E0001", String(error.message || "Unknown error"));
1115
+ const unknownStatus = error;
1116
+ return ApiResponse.error(
1117
+ String(unknownStatus.errorCode),
1118
+ String(unknownStatus.message || "Unknown error")
1119
+ );
1109
1120
  }
1110
1121
  throw error;
1111
1122
  }
@@ -1127,7 +1138,8 @@ var RefundResource = class _RefundResource extends BaseResource {
1127
1138
  return this.httpClient.post(
1128
1139
  this.getPath(_RefundResource.PATH_INQUIRY),
1129
1140
  params,
1130
- options
1141
+ options,
1142
+ null
1131
1143
  );
1132
1144
  }
1133
1145
  };
@@ -1147,7 +1159,8 @@ var MerchantConfigResource = class _MerchantConfigResource extends BaseResource
1147
1159
  return this.httpClient.post(
1148
1160
  this.getPath(_MerchantConfigResource.PATH_INQUIRY),
1149
1161
  params,
1150
- options
1162
+ options,
1163
+ "merchantId"
1151
1164
  );
1152
1165
  }
1153
1166
  };
@@ -1167,7 +1180,8 @@ var PayMethodConfigResource = class _PayMethodConfigResource extends BaseResourc
1167
1180
  return this.httpClient.post(
1168
1181
  this.getPath(_PayMethodConfigResource.PATH_INQUIRY),
1169
1182
  params,
1170
- options
1183
+ options,
1184
+ "merchantId"
1171
1185
  );
1172
1186
  }
1173
1187
  };
@@ -1187,7 +1201,8 @@ var WalletResource = class _WalletResource extends BaseResource {
1187
1201
  return this.httpClient.post(
1188
1202
  this.getPath(_WalletResource.PATH_INQUIRY),
1189
1203
  params,
1190
- options
1204
+ options,
1205
+ "merchantInfo.merchantId"
1191
1206
  );
1192
1207
  }
1193
1208
  };