@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.mjs CHANGED
@@ -348,6 +348,10 @@ var ApiResponse = class _ApiResponse {
348
348
  getData() {
349
349
  return this.data;
350
350
  }
351
+ /** Returns the same JSON data with business string literals opened to future values. */
352
+ getOpenData() {
353
+ return this.data;
354
+ }
351
355
  /**
352
356
  * Gets the error message.
353
357
  *
@@ -455,7 +459,7 @@ var HEADER_SDK_VERSION = "x-sdk-version";
455
459
  var HEADER_CONTENT_TYPE = "content-type";
456
460
  var CONTENT_TYPE_JSON = "application/json";
457
461
  var API_VERSION = "1.0.0";
458
- var SDK_VERSION = "waffo-node/3.0.1";
462
+ var SDK_VERSION = "waffo-node/3.2.0";
459
463
  var WaffoHttpClient = class {
460
464
  baseUrl;
461
465
  apiKey;
@@ -485,15 +489,16 @@ var WaffoHttpClient = class {
485
489
  * @param path - API endpoint path (e.g., "/order/create")
486
490
  * @param request - Request body
487
491
  * @param options - Per-request options
492
+ * @param merchantIdPath - Contract path for merchantId, null for no injection, or omitted for legacy inference
488
493
  * @returns API response
489
494
  * @throws WaffoUnknownStatusError for network errors or unknown status
490
495
  */
491
- async post(path, request, options) {
496
+ async post(path, request, options, merchantIdPath) {
492
497
  const url = this.baseUrl + path;
493
498
  const effectiveConnectTimeout = options?.connectTimeout ?? this.connectTimeout;
494
499
  const effectiveReadTimeout = options?.readTimeout ?? this.readTimeout;
495
500
  try {
496
- this.injectMerchantIdIfNeeded(request);
501
+ this.injectMerchantIdIfNeeded(request, merchantIdPath);
497
502
  const requestBody = JSON.stringify(request);
498
503
  const signature = RsaUtils.sign(requestBody, this.privateKey);
499
504
  this.logger?.debug(`Request URL: ${url}`);
@@ -586,9 +591,24 @@ var WaffoHttpClient = class {
586
591
  /**
587
592
  * Auto-injects merchantId into the request if configured.
588
593
  */
589
- injectMerchantIdIfNeeded(request) {
594
+ injectMerchantIdIfNeeded(request, merchantIdPath) {
590
595
  if (!this.merchantId) return;
591
596
  const req = request;
597
+ if (merchantIdPath === null) return;
598
+ if (merchantIdPath === "merchantInfo.merchantId") {
599
+ const merchantInfo = typeof req.merchantInfo === "object" && req.merchantInfo !== null ? req.merchantInfo : {};
600
+ if (!merchantInfo.merchantId) {
601
+ merchantInfo.merchantId = this.merchantId;
602
+ }
603
+ req.merchantInfo = merchantInfo;
604
+ return;
605
+ }
606
+ if (merchantIdPath === "merchantId") {
607
+ if (!req.merchantId) {
608
+ req.merchantId = this.merchantId;
609
+ }
610
+ return;
611
+ }
592
612
  if (typeof req.merchantInfo === "object" && req.merchantInfo !== null) {
593
613
  const info = req.merchantInfo;
594
614
  if (!info.merchantId) {
@@ -630,6 +650,7 @@ var WebhookHandler = class {
630
650
  subscriptionPaymentHandler;
631
651
  subscriptionPeriodChangedHandler;
632
652
  subscriptionChangeHandler;
653
+ customEventHandlers = /* @__PURE__ */ new Map();
633
654
  constructor(config) {
634
655
  this.waffoPublicKey = config.waffoPublicKey;
635
656
  this.privateKey = config.privateKey;
@@ -678,6 +699,20 @@ var WebhookHandler = class {
678
699
  this.subscriptionChangeHandler = handler;
679
700
  return this;
680
701
  }
702
+ /** Registers an exact custom event name before receiving webhooks. Later registration replaces the same name. */
703
+ onEvent(eventType, handler) {
704
+ if (typeof eventType !== "string" || !eventType.trim()) {
705
+ throw new WaffoError(WaffoErrorCode.UNEXPECTED, "Custom event name must not be blank");
706
+ }
707
+ if (typeof handler !== "function") {
708
+ throw new WaffoError(WaffoErrorCode.UNEXPECTED, "Custom event handler must be a function");
709
+ }
710
+ if (Object.values(WebhookEventType).some((known) => known === eventType)) {
711
+ throw new WaffoError(WaffoErrorCode.UNEXPECTED, `Use the dedicated handler for built-in event: ${eventType}`);
712
+ }
713
+ this.customEventHandlers.set(eventType, handler);
714
+ return this;
715
+ }
681
716
  /**
682
717
  * Processes a webhook notification.
683
718
  *
@@ -697,6 +732,9 @@ var WebhookHandler = class {
697
732
  return this.createFailedResult("Invalid signature");
698
733
  }
699
734
  const parsed = JSON.parse(body);
735
+ if (!parsed || typeof parsed.eventType !== "string") {
736
+ return this.createFailedResult("Unknown event type");
737
+ }
700
738
  const eventType = parsed.eventType;
701
739
  switch (eventType) {
702
740
  case "PAYMENT_NOTIFICATION" /* PAYMENT_NOTIFICATION */:
@@ -726,9 +764,15 @@ var WebhookHandler = class {
726
764
  await this.subscriptionChangeHandler(parsed);
727
765
  }
728
766
  break;
729
- default:
730
- this.logger?.warn(`Unknown webhook event type: ${eventType}`);
731
- return this.createFailedResult(`Unknown event type: ${eventType}`);
767
+ default: {
768
+ const handler = this.customEventHandlers.get(eventType);
769
+ if (!handler) {
770
+ this.logger?.warn(`Unknown webhook event type: ${eventType}`);
771
+ return this.createFailedResult(`Unknown event type: ${eventType}`);
772
+ }
773
+ await handler(parsed);
774
+ break;
775
+ }
732
776
  }
733
777
  return this.createSuccessResult();
734
778
  } catch (error) {
@@ -833,7 +877,8 @@ var OrderResource = class _OrderResource extends BaseResource {
833
877
  return this.httpClient.post(
834
878
  this.getPath(_OrderResource.PATH_CREATE),
835
879
  params,
836
- options
880
+ options,
881
+ "merchantInfo.merchantId"
837
882
  );
838
883
  }
839
884
  /**
@@ -848,7 +893,8 @@ var OrderResource = class _OrderResource extends BaseResource {
848
893
  return this.httpClient.post(
849
894
  this.getPath(_OrderResource.PATH_INQUIRY),
850
895
  params,
851
- options
896
+ options,
897
+ null
852
898
  );
853
899
  }
854
900
  /**
@@ -866,7 +912,8 @@ var OrderResource = class _OrderResource extends BaseResource {
866
912
  return this.httpClient.post(
867
913
  this.getPath(_OrderResource.PATH_CANCEL),
868
914
  params,
869
- options
915
+ options,
916
+ "merchantId"
870
917
  );
871
918
  }
872
919
  /**
@@ -884,7 +931,8 @@ var OrderResource = class _OrderResource extends BaseResource {
884
931
  return this.httpClient.post(
885
932
  this.getPath(_OrderResource.PATH_REFUND),
886
933
  params,
887
- options
934
+ options,
935
+ "merchantId"
888
936
  );
889
937
  }
890
938
  /**
@@ -902,7 +950,8 @@ var OrderResource = class _OrderResource extends BaseResource {
902
950
  return this.httpClient.post(
903
951
  this.getPath(_OrderResource.PATH_CAPTURE),
904
952
  params,
905
- options
953
+ options,
954
+ "merchantId"
906
955
  );
907
956
  }
908
957
  };
@@ -916,14 +965,6 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
916
965
  static PATH_UPDATE = "/update";
917
966
  static PATH_CHANGE = "/change";
918
967
  static PATH_CHANGE_INQUIRY = "/change/inquiry";
919
- /**
920
- * Creates a new subscription.
921
- *
922
- * @param params - Subscription creation parameters
923
- * @param options - Optional request options
924
- * @returns API response with subscription data
925
- * @throws WaffoUnknownStatusError for network errors
926
- */
927
968
  async create(params, options) {
928
969
  if (!params.requestedAt) {
929
970
  params.requestedAt = getCurrentTimestamp();
@@ -931,7 +972,8 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
931
972
  return this.httpClient.post(
932
973
  this.getPath(_SubscriptionResource.PATH_CREATE),
933
974
  params,
934
- options
975
+ options,
976
+ "merchantInfo.merchantId"
935
977
  );
936
978
  }
937
979
  /**
@@ -946,7 +988,8 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
946
988
  return this.httpClient.post(
947
989
  this.getPath(_SubscriptionResource.PATH_INQUIRY),
948
990
  params,
949
- options
991
+ options,
992
+ null
950
993
  );
951
994
  }
952
995
  /**
@@ -964,7 +1007,8 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
964
1007
  return this.httpClient.post(
965
1008
  this.getPath(_SubscriptionResource.PATH_CANCEL),
966
1009
  params,
967
- options
1010
+ options,
1011
+ "merchantId"
968
1012
  );
969
1013
  }
970
1014
  /**
@@ -979,7 +1023,8 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
979
1023
  return this.httpClient.post(
980
1024
  this.getPath(_SubscriptionResource.PATH_MANAGE),
981
1025
  params,
982
- options
1026
+ options,
1027
+ null
983
1028
  );
984
1029
  }
985
1030
  /**
@@ -997,50 +1042,10 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
997
1042
  return this.httpClient.post(
998
1043
  this.getPath(_SubscriptionResource.PATH_UPDATE),
999
1044
  params,
1000
- options
1045
+ options,
1046
+ null
1001
1047
  );
1002
1048
  }
1003
- /**
1004
- * Changes (upgrades/downgrades) an existing subscription.
1005
- *
1006
- * This method allows changing an active subscription to a new plan with different
1007
- * pricing, billing period, or other terms. The remaining amount from the original
1008
- * subscription can be applied to the new subscription.
1009
- *
1010
- * @param params - Subscription change parameters
1011
- * @param options - Optional request options
1012
- * @returns API response with change result
1013
- * @throws WaffoUnknownStatusError for network errors
1014
- *
1015
- * @example
1016
- * ```typescript
1017
- * const response = await waffo.subscription().change({
1018
- * subscriptionRequest: 'new-request-id',
1019
- * originSubscriptionRequest: 'original-request-id',
1020
- * remainingAmount: '50.00',
1021
- * currency: 'HKD',
1022
- * requestedAt: new Date().toISOString(),
1023
- * notifyUrl: 'https://example.com/webhook',
1024
- * productInfoList: [{
1025
- * description: 'Premium Monthly',
1026
- * periodType: 'MONTH',
1027
- * periodInterval: '1',
1028
- * amount: '199.00',
1029
- * }],
1030
- * userInfo: { userId: 'user-123', userEmail: 'user@example.com' },
1031
- * goodsInfo: { goodsId: 'premium', goodsName: 'Premium Plan' },
1032
- * paymentInfo: { productName: 'SUBSCRIPTION' },
1033
- * });
1034
- *
1035
- * if (response.isSuccess()) {
1036
- * const data = response.getData();
1037
- * if (data?.subscriptionChangeStatus === 'AUTHORIZATION_REQUIRED') {
1038
- * // Redirect user to authorization URL
1039
- * const webUrl = JSON.parse(data.subscriptionAction || '{}').webUrl;
1040
- * }
1041
- * }
1042
- * ```
1043
- */
1044
1049
  async change(params, options) {
1045
1050
  if (!params.requestedAt) {
1046
1051
  params.requestedAt = getCurrentTimestamp();
@@ -1048,7 +1053,8 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
1048
1053
  return this.httpClient.post(
1049
1054
  this.getPath(_SubscriptionResource.PATH_CHANGE),
1050
1055
  params,
1051
- options
1056
+ options,
1057
+ "merchantInfo.merchantId"
1052
1058
  );
1053
1059
  }
1054
1060
  /**
@@ -1079,11 +1085,16 @@ var SubscriptionResource = class _SubscriptionResource extends BaseResource {
1079
1085
  return await this.httpClient.post(
1080
1086
  this.getPath(_SubscriptionResource.PATH_CHANGE_INQUIRY),
1081
1087
  params,
1082
- options
1088
+ options,
1089
+ null
1083
1090
  );
1084
1091
  } catch (error) {
1085
1092
  if (error && typeof error === "object" && "errorCode" in error) {
1086
- return ApiResponse.error("E0001", String(error.message || "Unknown error"));
1093
+ const unknownStatus = error;
1094
+ return ApiResponse.error(
1095
+ String(unknownStatus.errorCode),
1096
+ String(unknownStatus.message || "Unknown error")
1097
+ );
1087
1098
  }
1088
1099
  throw error;
1089
1100
  }
@@ -1105,7 +1116,8 @@ var RefundResource = class _RefundResource extends BaseResource {
1105
1116
  return this.httpClient.post(
1106
1117
  this.getPath(_RefundResource.PATH_INQUIRY),
1107
1118
  params,
1108
- options
1119
+ options,
1120
+ null
1109
1121
  );
1110
1122
  }
1111
1123
  };
@@ -1125,7 +1137,8 @@ var MerchantConfigResource = class _MerchantConfigResource extends BaseResource
1125
1137
  return this.httpClient.post(
1126
1138
  this.getPath(_MerchantConfigResource.PATH_INQUIRY),
1127
1139
  params,
1128
- options
1140
+ options,
1141
+ "merchantId"
1129
1142
  );
1130
1143
  }
1131
1144
  };
@@ -1145,7 +1158,8 @@ var PayMethodConfigResource = class _PayMethodConfigResource extends BaseResourc
1145
1158
  return this.httpClient.post(
1146
1159
  this.getPath(_PayMethodConfigResource.PATH_INQUIRY),
1147
1160
  params,
1148
- options
1161
+ options,
1162
+ "merchantId"
1149
1163
  );
1150
1164
  }
1151
1165
  };
@@ -1165,7 +1179,8 @@ var WalletResource = class _WalletResource extends BaseResource {
1165
1179
  return this.httpClient.post(
1166
1180
  this.getPath(_WalletResource.PATH_INQUIRY),
1167
1181
  params,
1168
- options
1182
+ options,
1183
+ "merchantInfo.merchantId"
1169
1184
  );
1170
1185
  }
1171
1186
  };