@apps-in-toss/native-modules 1.1.1 โ†’ 1.1.3

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.cjs CHANGED
@@ -50,11 +50,14 @@ __export(index_exports, {
50
50
  getSchemeUri: () => getSchemeUri,
51
51
  getTossAppVersion: () => getTossAppVersion,
52
52
  getTossShareLink: () => getTossShareLink,
53
+ iapCreateOneTimePurchaseOrder: () => iapCreateOneTimePurchaseOrder,
53
54
  isMinVersionSupported: () => isMinVersionSupported,
54
55
  onVisibilityChangedByTransparentServiceWeb: () => onVisibilityChangedByTransparentServiceWeb,
55
56
  openCamera: () => openCamera,
56
57
  openGameCenterLeaderboard: () => openGameCenterLeaderboard,
57
58
  openURL: () => openURL2,
59
+ processProductGrant: () => processProductGrant,
60
+ requestOneTimePurchase: () => requestOneTimePurchase,
58
61
  saveBase64Data: () => saveBase64Data,
59
62
  setClipboardText: () => setClipboardText,
60
63
  setDeviceOrientation: () => setDeviceOrientation,
@@ -68,22 +71,11 @@ __export(index_exports, {
68
71
  module.exports = __toCommonJS(index_exports);
69
72
 
70
73
  // src/AppsInTossModule/native-event-emitter/appsInTossEvent.ts
71
- var import_react_native9 = require("@granite-js/react-native");
72
-
73
- // src/AppsInTossModule/native-event-emitter/event-plugins/BackButtonClickHandleEvent.ts
74
- var import_react_native = require("@granite-js/react-native");
75
- var BackButtonClickHandleEvent = class extends import_react_native.GraniteEventDefinition {
76
- name = "backButtonClickEvent";
77
- remove() {
78
- }
79
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
80
- listener(_) {
81
- }
82
- };
74
+ var import_react_native7 = require("@granite-js/react-native");
83
75
 
84
76
  // src/AppsInTossModule/native-event-emitter/event-plugins/EntryMessageExitedEvent.ts
85
- var import_react_native2 = require("@granite-js/react-native");
86
- var EntryMessageExitedEvent = class extends import_react_native2.GraniteEventDefinition {
77
+ var import_react_native = require("@granite-js/react-native");
78
+ var EntryMessageExitedEvent = class extends import_react_native.GraniteEventDefinition {
87
79
  name = "entryMessageExited";
88
80
  remove() {
89
81
  }
@@ -92,24 +84,13 @@ var EntryMessageExitedEvent = class extends import_react_native2.GraniteEventDef
92
84
  }
93
85
  };
94
86
 
95
- // src/AppsInTossModule/native-event-emitter/event-plugins/HomeIconButtonClickHandleEvent.ts
96
- var import_react_native3 = require("@granite-js/react-native");
97
- var HomeIconButtonClickHandleEvent = class extends import_react_native3.GraniteEventDefinition {
98
- name = "homeIconButtonClickEvent";
99
- remove() {
100
- }
101
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
102
- listener(_) {
103
- }
104
- };
105
-
106
87
  // src/AppsInTossModule/native-event-emitter/event-plugins/UpdateLocationEvent.ts
107
88
  var import_types = require("@apps-in-toss/types");
108
- var import_react_native6 = require("@granite-js/react-native");
89
+ var import_react_native4 = require("@granite-js/react-native");
109
90
 
110
91
  // src/AppsInTossModule/native-modules/AppsInTossModule.ts
111
- var import_react_native4 = require("react-native");
112
- var Module = import_react_native4.TurboModuleRegistry.getEnforcing("AppsInTossModule");
92
+ var import_react_native2 = require("react-native");
93
+ var Module = import_react_native2.TurboModuleRegistry.getEnforcing("AppsInTossModule");
113
94
  var AppsInTossModuleInstance = Module;
114
95
  var AppsInTossModule = Module;
115
96
 
@@ -136,11 +117,11 @@ async function requestPermission(permission) {
136
117
  }
137
118
 
138
119
  // src/AppsInTossModule/native-event-emitter/nativeEventEmitter.ts
139
- var import_react_native5 = require("react-native");
140
- var nativeEventEmitter = new import_react_native5.NativeEventEmitter(AppsInTossModuleInstance);
120
+ var import_react_native3 = require("react-native");
121
+ var nativeEventEmitter = new import_react_native3.NativeEventEmitter(AppsInTossModuleInstance);
141
122
 
142
123
  // src/AppsInTossModule/native-event-emitter/event-plugins/UpdateLocationEvent.ts
143
- var UpdateLocationEvent = class extends import_react_native6.GraniteEventDefinition {
124
+ var UpdateLocationEvent = class extends import_react_native4.GraniteEventDefinition {
144
125
  name = "updateLocationEvent";
145
126
  subscriptionCount = 0;
146
127
  ref = {
@@ -170,7 +151,7 @@ var UpdateLocationEvent = class extends import_react_native6.GraniteEventDefinit
170
151
  };
171
152
 
172
153
  // src/AppsInTossModule/native-event-emitter/internal/AppBridgeCallbackEvent.ts
173
- var import_react_native7 = require("@granite-js/react-native");
154
+ var import_react_native5 = require("@granite-js/react-native");
174
155
 
175
156
  // src/utils/generateUUID.ts
176
157
  function generateUUID(placeholder) {
@@ -232,7 +213,7 @@ var INTERNAL__appBridgeHandler = {
232
213
 
233
214
  // src/AppsInTossModule/native-event-emitter/internal/AppBridgeCallbackEvent.ts
234
215
  var UNSAFE__nativeEventEmitter = nativeEventEmitter;
235
- var AppBridgeCallbackEvent = class _AppBridgeCallbackEvent extends import_react_native7.GraniteEventDefinition {
216
+ var AppBridgeCallbackEvent = class _AppBridgeCallbackEvent extends import_react_native5.GraniteEventDefinition {
236
217
  static INTERNAL__appBridgeSubscription;
237
218
  name = "appBridgeCallbackEvent";
238
219
  constructor() {
@@ -262,8 +243,8 @@ var AppBridgeCallbackEvent = class _AppBridgeCallbackEvent extends import_react_
262
243
  };
263
244
 
264
245
  // src/AppsInTossModule/native-event-emitter/internal/VisibilityChangedByTransparentServiceWebEvent.ts
265
- var import_react_native8 = require("@granite-js/react-native");
266
- var VisibilityChangedByTransparentServiceWebEvent = class extends import_react_native8.GraniteEventDefinition {
246
+ var import_react_native6 = require("@granite-js/react-native");
247
+ var VisibilityChangedByTransparentServiceWebEvent = class extends import_react_native6.GraniteEventDefinition {
267
248
  name = "onVisibilityChangedByTransparentServiceWeb";
268
249
  subscription = null;
269
250
  remove() {
@@ -288,12 +269,9 @@ var VisibilityChangedByTransparentServiceWebEvent = class extends import_react_n
288
269
  };
289
270
 
290
271
  // src/AppsInTossModule/native-event-emitter/appsInTossEvent.ts
291
- var appsInTossEvent = new import_react_native9.GraniteEvent([
272
+ var appsInTossEvent = new import_react_native7.GraniteEvent([
292
273
  new UpdateLocationEvent(),
293
274
  new EntryMessageExitedEvent(),
294
- // Navigation Bar events
295
- new HomeIconButtonClickHandleEvent(),
296
- new BackButtonClickHandleEvent(),
297
275
  // Internal events
298
276
  new AppBridgeCallbackEvent(),
299
277
  new VisibilityChangedByTransparentServiceWebEvent()
@@ -308,7 +286,7 @@ function getOperationalEnvironment() {
308
286
  }
309
287
 
310
288
  // src/AppsInTossModule/native-modules/isMinVersionSupported.ts
311
- var import_react_native10 = require("react-native");
289
+ var import_react_native8 = require("react-native");
312
290
 
313
291
  // src/utils/compareVersion.ts
314
292
  var SEMVER_REGEX = /^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\\-]+(?:\.[\da-z\\-]+)*))?(?:\+[\da-z\\-]+(?:\.[\da-z\\-]+)*)?)?)?$/i;
@@ -384,7 +362,7 @@ function isMinVersionSupported(minVersions) {
384
362
  return true;
385
363
  }
386
364
  const currentVersion = AppsInTossModule.tossAppVersion;
387
- const isIOS = import_react_native10.Platform.OS === "ios";
365
+ const isIOS = import_react_native8.Platform.OS === "ios";
388
366
  const minVersion = isIOS ? minVersions.ios : minVersions.android;
389
367
  if (minVersion === void 0) {
390
368
  return false;
@@ -734,15 +712,80 @@ async function getTossShareLink(path) {
734
712
  }
735
713
 
736
714
  // src/AppsInTossModule/native-modules/iap.ts
737
- async function createOneTimePurchaseOrder(params) {
738
- const isSupported = isMinVersionSupported({
715
+ var import_es_toolkit3 = require("es-toolkit");
716
+ function iapCreateOneTimePurchaseOrder(params) {
717
+ const sku = params.sku ?? params.productId;
718
+ return AppsInTossModule.iapCreateOneTimePurchaseOrder({ productId: sku });
719
+ }
720
+ function processProductGrant(params) {
721
+ return AppsInTossModule.processProductGrant({ orderId: params.orderId, isProductGranted: params.isProductGranted });
722
+ }
723
+ function requestOneTimePurchase(params) {
724
+ const { options, onEvent, onError } = params;
725
+ const sku = options.sku ?? options.productId;
726
+ const unregisterCallbacks = INTERNAL__appBridgeHandler.invokeAppBridgeMethod(
727
+ "requestOneTimePurchase",
728
+ { sku },
729
+ {
730
+ onPurchased: (params2) => {
731
+ onEvent({ type: "purchased", data: params2 });
732
+ },
733
+ onSuccess: (result) => {
734
+ onEvent({ type: "success", data: result });
735
+ },
736
+ onError: (error) => {
737
+ onError(error);
738
+ }
739
+ }
740
+ );
741
+ return unregisterCallbacks;
742
+ }
743
+ function createOneTimePurchaseOrder(params) {
744
+ const isIAPSupported = isMinVersionSupported({
739
745
  android: "5.219.0",
740
746
  ios: "5.219.0"
741
747
  });
742
- if (!isSupported) {
743
- return;
748
+ if (!isIAPSupported) {
749
+ return import_es_toolkit3.noop;
750
+ }
751
+ const isProcessProductGrantSupported = isMinVersionSupported({
752
+ android: "5.230.0",
753
+ ios: "5.230.0"
754
+ });
755
+ const { options, onEvent, onError } = params;
756
+ const sku = options.sku ?? options.productId;
757
+ if (!isProcessProductGrantSupported) {
758
+ const v1 = () => {
759
+ AppsInTossModule.iapCreateOneTimePurchaseOrder({ productId: sku }).then((response) => {
760
+ Promise.resolve(options.processProductGrant({ orderId: response.orderId })).then(() => {
761
+ onEvent({ type: "success", data: response });
762
+ }).catch((error) => {
763
+ onError(error);
764
+ });
765
+ }).catch((error) => {
766
+ onError(error);
767
+ });
768
+ return import_es_toolkit3.noop;
769
+ };
770
+ return v1();
744
771
  }
745
- return AppsInTossModule.iapCreateOneTimePurchaseOrder(params);
772
+ const unregisterCallbacks = INTERNAL__appBridgeHandler.invokeAppBridgeMethod(
773
+ "requestOneTimePurchase",
774
+ { sku },
775
+ {
776
+ onPurchased: async (params2) => {
777
+ const isProductGranted = await options.processProductGrant(params2);
778
+ await AppsInTossModule.processProductGrant({ orderId: params2.orderId, isProductGranted });
779
+ },
780
+ onSuccess: (result) => {
781
+ onEvent({ type: "success", data: result });
782
+ },
783
+ onError: (error) => {
784
+ onError(error);
785
+ }
786
+ }
787
+ );
788
+ return unregisterCallbacks;
746
789
  }
747
790
  async function getProductItemList() {
748
791
  const isSupported = isMinVersionSupported({
@@ -808,7 +851,7 @@ var Storage = {
808
851
  };
809
852
 
810
853
  // src/AppsInTossModule/native-modules/openGameCenterLeaderboard.ts
811
- var import_react_native11 = require("@granite-js/react-native");
854
+ var import_react_native9 = require("@granite-js/react-native");
812
855
 
813
856
  // src/AppsInTossModule/constants.ts
814
857
  var GAME_CENTER_MIN_VERSION = {
@@ -828,7 +871,7 @@ async function openGameCenterLeaderboard() {
828
871
  const url = new URL("servicetoss://game-center/leaderboard?_navbar=hide");
829
872
  url.searchParams.set("appName", appName);
830
873
  url.searchParams.set("referrer", `appsintoss.${appName}`);
831
- return (0, import_react_native11.openURL)(url.toString());
874
+ return (0, import_react_native9.openURL)(url.toString());
832
875
  }
833
876
 
834
877
  // src/AppsInTossModule/native-modules/getGameCenterGameProfile.ts
@@ -901,8 +944,8 @@ function onVisibilityChangedByTransparentServiceWeb(eventParams) {
901
944
  }
902
945
 
903
946
  // src/BedrockModule/native-modules/natives/BedrockModule.ts
904
- var import_react_native12 = require("react-native");
905
- var BedrockModule = import_react_native12.NativeModules.BedrockModule;
947
+ var import_react_native10 = require("react-native");
948
+ var BedrockModule = import_react_native10.NativeModules.BedrockModule;
906
949
 
907
950
  // src/BedrockModule/native-modules/natives/closeView.ts
908
951
  async function closeView() {
@@ -910,10 +953,10 @@ async function closeView() {
910
953
  }
911
954
 
912
955
  // src/BedrockModule/native-modules/natives/getLocale.ts
913
- var import_react_native13 = require("react-native");
956
+ var import_react_native11 = require("react-native");
914
957
  function getLocale() {
915
958
  const locale = BedrockModule?.DeviceInfo?.locale ?? "ko-KR";
916
- if (import_react_native13.Platform.OS === "android") {
959
+ if (import_react_native11.Platform.OS === "android") {
917
960
  return replaceUnderbarToHypen(locale);
918
961
  }
919
962
  return locale;
@@ -961,24 +1004,24 @@ async function setIosSwipeGestureEnabled(options) {
961
1004
  }
962
1005
 
963
1006
  // src/BedrockModule/native-modules/natives/openURL.ts
964
- var import_react_native14 = require("react-native");
1007
+ var import_react_native12 = require("react-native");
965
1008
  function openURL2(url) {
966
- return import_react_native14.Linking.openURL(url);
1009
+ return import_react_native12.Linking.openURL(url);
967
1010
  }
968
1011
 
969
1012
  // src/BedrockModule/native-modules/natives/getPlatformOS.ts
970
- var import_react_native15 = require("react-native");
1013
+ var import_react_native13 = require("react-native");
971
1014
  function getPlatformOS() {
972
- return import_react_native15.Platform.OS;
1015
+ return import_react_native13.Platform.OS;
973
1016
  }
974
1017
 
975
1018
  // src/BedrockModule/native-modules/core/BedrockCoreModule.ts
976
- var import_react_native16 = require("react-native");
977
- var BedrockCoreModule = import_react_native16.NativeModules.BedrockCoreModule;
1019
+ var import_react_native14 = require("react-native");
1020
+ var BedrockCoreModule = import_react_native14.NativeModules.BedrockCoreModule;
978
1021
 
979
1022
  // src/AppsInTossModule/native-modules/tossCore.ts
980
- var import_react_native17 = require("react-native");
981
- var TossCoreModule = import_react_native17.NativeModules.TossCoreModule;
1023
+ var import_react_native15 = require("react-native");
1024
+ var TossCoreModule = import_react_native15.NativeModules.TossCoreModule;
982
1025
  function tossCoreEventLog(params) {
983
1026
  const supported = isMinVersionSupported({ ios: "5.210.0", android: "5.210.0" });
984
1027
  const isSandbox = getOperationalEnvironment() === "sandbox";
@@ -1030,11 +1073,14 @@ var INTERNAL__module = {
1030
1073
  getSchemeUri,
1031
1074
  getTossAppVersion,
1032
1075
  getTossShareLink,
1076
+ iapCreateOneTimePurchaseOrder,
1033
1077
  isMinVersionSupported,
1034
1078
  onVisibilityChangedByTransparentServiceWeb,
1035
1079
  openCamera,
1036
1080
  openGameCenterLeaderboard,
1037
1081
  openURL,
1082
+ processProductGrant,
1083
+ requestOneTimePurchase,
1038
1084
  saveBase64Data,
1039
1085
  setClipboardText,
1040
1086
  setDeviceOrientation,
package/dist/index.d.cts CHANGED
@@ -231,24 +231,12 @@ interface ContactsViralParams {
231
231
  */
232
232
  declare function contactsViral(params: ContactsViralParams): () => void;
233
233
 
234
- declare class BackButtonClickHandleEvent extends GraniteEventDefinition<undefined, undefined> {
235
- name: "backButtonClickEvent";
236
- remove(): void;
237
- listener(_: undefined): void;
238
- }
239
-
240
234
  declare class EntryMessageExitedEvent extends GraniteEventDefinition<undefined, undefined> {
241
235
  name: "entryMessageExited";
242
236
  remove(): void;
243
237
  listener(_: undefined): void;
244
238
  }
245
239
 
246
- declare class HomeIconButtonClickHandleEvent extends GraniteEventDefinition<undefined, undefined> {
247
- name: "homeIconButtonClickEvent";
248
- remove(): void;
249
- listener(_: undefined): void;
250
- }
251
-
252
240
  interface StartUpdateLocationOptions {
253
241
  /**
254
242
  * ์œ„์น˜ ์ •ํ™•๋„๋ฅผ ์„ค์ •ํ•ด์š”.
@@ -298,7 +286,7 @@ declare class VisibilityChangedByTransparentServiceWebEvent extends GraniteEvent
298
286
  private isVisibilityChangedByTransparentServiceWebResult;
299
287
  }
300
288
 
301
- declare const appsInTossEvent: GraniteEvent<BackButtonClickHandleEvent | EntryMessageExitedEvent | HomeIconButtonClickHandleEvent | UpdateLocationEvent | AppBridgeCallbackEvent | VisibilityChangedByTransparentServiceWebEvent>;
289
+ declare const appsInTossEvent: GraniteEvent<EntryMessageExitedEvent | UpdateLocationEvent | AppBridgeCallbackEvent | VisibilityChangedByTransparentServiceWebEvent>;
302
290
 
303
291
  declare function onVisibilityChangedByTransparentServiceWeb(eventParams: {
304
292
  options: {
@@ -1423,16 +1411,16 @@ type GameCenterGameProfileResponse = {
1423
1411
  */
1424
1412
  declare function getGameCenterGameProfile(): Promise<GameCenterGameProfileResponse | undefined>;
1425
1413
 
1426
- /**
1427
- * @public
1428
- * @category ์ธ์•ฑ๊ฒฐ์ œ
1429
- * @name IapCreateOneTimePurchaseOrderOptions
1430
- * @description ์ธ์•ฑ๊ฒฐ์ œ 1๊ฑด์„ ์š”์ฒญํ•  ๋•Œ ํ•„์š”ํ•œ ์ •๋ณด์˜ˆ์š”.
1431
- * @property {string} productId - ์ฃผ๋ฌธํ•  ์ƒํ’ˆ์˜ ID์˜ˆ์š”.
1432
- */
1433
- interface IapCreateOneTimePurchaseOrderOptions {
1414
+ type Sku = {
1415
+ /**
1416
+ * @deprecated `productId`๋Š” ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„์š”. ๋Œ€์‹  `sku`๋ฅผ ์‚ฌ์šฉํ•ด์š”.
1417
+ */
1434
1418
  productId: string;
1435
- }
1419
+ sku?: string;
1420
+ } | {
1421
+ productId?: never;
1422
+ sku: string;
1423
+ };
1436
1424
  /**
1437
1425
  * @public
1438
1426
  * @category ์ธ์•ฑ๊ฒฐ์ œ
@@ -1455,15 +1443,54 @@ interface IapCreateOneTimePurchaseOrderResult {
1455
1443
  fraction: number;
1456
1444
  miniAppIconUrl: string | null;
1457
1445
  }
1446
+ interface SuccessEvent {
1447
+ type: 'success';
1448
+ data: IapCreateOneTimePurchaseOrderResult;
1449
+ }
1450
+ interface PurchasedEvent {
1451
+ type: 'purchased';
1452
+ data: {
1453
+ orderId: string;
1454
+ };
1455
+ }
1456
+ /**
1457
+ * @public
1458
+ * @category ์ธ์•ฑ๊ฒฐ์ œ
1459
+ * @name IapCreateOneTimePurchaseOrderOptions
1460
+ * @property {Sku} options - ๊ฒฐ์ œํ•  ์ƒํ’ˆ์˜ ์ •๋ณด์˜ˆ์š”.
1461
+ * @property {string} options.sku - ์ฃผ๋ฌธํ•  ์ƒํ’ˆ์˜ ๊ณ ์œ  ID์˜ˆ์š”.
1462
+ * @property {(params: { orderId: string }) => boolean | Promise<boolean>} processProductGrant - ์ฃผ๋ฌธ์ด ๋งŒ๋“ค์–ด์ง„ ๋’ค ์‹ค์ œ๋กœ ์ƒํ’ˆ์„ ์ง€๊ธ‰ํ•  ๋•Œ ํ˜ธ์ถœํ•ด์š”. `orderId`๋ฅผ ๋ฐ›์•„์„œ ์ง€๊ธ‰ ์„ฑ๊ณต ์—ฌ๋ถ€๋ฅผ `true` ๋˜๋Š” `Promise<true>`๋กœ ๋ฐ˜ํ™˜ํ•ด์š”. ์ง€๊ธ‰์— ์‹คํŒจํ•˜๋ฉด `false`๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”.
1463
+ * @property {(event: SuccessEvent) => void | Promise<void>} onEvent - ๊ฒฐ์ œ๊ฐ€ ์„ฑ๊ณตํ–ˆ์„ ๋•Œ ํ˜ธ์ถœํ•ด์š”. `event.type`์ด `'success'`์ด๊ณ , `event.data`์— `IapCreateOneTimePurchaseOrderResult`๊ฐ€ ๋“ค์–ด ์žˆ์–ด์š”.
1464
+ * @property {(error: unknown) => void | Promise<void>} onError - ๊ฒฐ์ œ ๊ณผ์ •์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํ˜ธ์ถœํ•ด์š”. ์—๋Ÿฌ ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„์„œ ๋กœ๊น…ํ•˜๊ฑฐ๋‚˜ ๋ณต๊ตฌ ์ ˆ์ฐจ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด์š”.
1465
+ */
1466
+ interface IapCreateOneTimePurchaseOrderOptions {
1467
+ options: Sku & {
1468
+ processProductGrant: (params: {
1469
+ orderId: string;
1470
+ }) => boolean | Promise<boolean>;
1471
+ };
1472
+ onEvent: (event: SuccessEvent) => void | Promise<void>;
1473
+ onError: (error: unknown) => void | Promise<void>;
1474
+ }
1475
+ interface IapRequestOneTimePurchaseOptions {
1476
+ options: Sku;
1477
+ onEvent: (event: PurchasedEvent | SuccessEvent) => void | Promise<void>;
1478
+ onError: (error: unknown) => void | Promise<void>;
1479
+ }
1480
+ declare function iapCreateOneTimePurchaseOrder(params: Sku): Promise<IapCreateOneTimePurchaseOrderResult>;
1481
+ declare function processProductGrant(params: {
1482
+ orderId: string;
1483
+ isProductGranted: boolean;
1484
+ }): Promise<void>;
1485
+ declare function requestOneTimePurchase(params: IapRequestOneTimePurchaseOptions): () => void;
1458
1486
  /**
1459
1487
  * @public
1460
1488
  * @category ์ธ์•ฑ๊ฒฐ์ œ
1461
- * @name iapCreateOneTimePurchaseOrder
1489
+ * @name createOneTimePurchaseOrder
1462
1490
  * @description
1463
1491
  * ํŠน์ • ์ธ์•ฑ๊ฒฐ์ œ ์ฃผ๋ฌธ์„œ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ด์š”. ์‚ฌ์šฉ์ž๊ฐ€ ์ƒํ’ˆ ๊ตฌ๋งค ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋Š” ์ƒํ™ฉ ๋“ฑ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ์‚ฌ์šฉ์ž์˜ ๊ฒฐ์ œ๋Š” ์ด๋™ํ•œ ํŽ˜์ด์ง€์—์„œ ์ง„ํ–‰๋ผ์š”. ๋งŒ์•ฝ ๊ฒฐ์ œ ์ค‘์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์—๋Ÿฌ ์œ ํ˜•์— ๋”ฐ๋ผ ์—๋Ÿฌ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ด์š”.
1464
1492
  * @param {IapCreateOneTimePurchaseOrderOptions} params - ์ธ์•ฑ๊ฒฐ์ œ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ•„์š”ํ•œ ์ •๋ณด์˜ˆ์š”.
1465
- * @param {string} params.productId - ์ฃผ๋ฌธํ•  ์ƒํ’ˆ์˜ ID์˜ˆ์š”.
1466
- * @returns {Promise<IapCreateOneTimePurchaseOrderResult | undefined>} ๊ฒฐ์ œ์— ์„ฑ๊ณตํ•˜๋ฉด ๊ฒฐ์ œ ๊ฒฐ๊ณผ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”. ์•ฑ ๋ฒ„์ „์ด ์ตœ์†Œ ์ง€์› ๋ฒ„์ „(์•ˆ๋“œ๋กœ์ด๋“œ 5.219.0, iOS 5.219.0)๋ณด๋‹ค ๋‚ฎ์œผ๋ฉด ์ธ์•ฑ๊ฒฐ์ œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์—†์–ด์„œ `undefined`๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”.
1493
+ * @returns {() => void} ์•ฑ๋ธŒ๋ฆฟ์ง€ cleanup ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”. ์ธ์•ฑ๊ฒฐ์ œ ๊ธฐ๋Šฅ์ด ๋๋‚˜๋ฉด ๋ฐ˜๋“œ์‹œ ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด์ œํ•ด์•ผ ํ•ด์š”.
1467
1494
  *
1468
1495
  * @throw {code: "INVALID_PRODUCT_ID"} - ์œ ํšจํ•˜์ง€ ์•Š์€ ์ƒํ’ˆ ID์ด๊ฑฐ๋‚˜, ํ•ด๋‹น ์ƒํ’ˆ์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
1469
1496
  * @throw {code: "PAYMENT_PENDING"} - ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•œ ๊ฒฐ์ œ๊ฐ€ ์•„์ง ์Šน์ธ์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
@@ -1475,6 +1502,7 @@ interface IapCreateOneTimePurchaseOrderResult {
1475
1502
  * @throw {code: "INTERNAL_ERROR"} - ์„œ๋ฒ„ ๋‚ด๋ถ€ ๋ฌธ์ œ๋กœ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
1476
1503
  * @throw {code: "KOREAN_ACCOUNT_ONLY"} - iOS ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉ์ž์˜ ๊ณ„์ •์ด ํ•œ๊ตญ ๊ณ„์ •์ด ์•„๋‹ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
1477
1504
  * @throw {code: "USER_CANCELED"} - ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒฐ์ œ๋ฅผ ์™„๋ฃŒํ•˜์ง€ ์•Š๊ณ  ์ฃผ๋ฌธ์„œ ํŽ˜์ด์ง€๋ฅผ ์ดํƒˆํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
1505
+ * @throw {code: "PRODUCT_NOT_GRANTED_BY_PARTNER"} - ํŒŒํŠธ๋„ˆ์‚ฌ์˜ ์ƒํ’ˆ ์ง€๊ธ‰์ด ์‹คํŒจํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
1478
1506
  *
1479
1507
  * @example
1480
1508
  * ### ํŠน์ • ์ธ์•ฑ๊ฒฐ์ œ ์ฃผ๋ฌธ์„œ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๊ธฐ
@@ -1482,28 +1510,39 @@ interface IapCreateOneTimePurchaseOrderResult {
1482
1510
  * ```tsx
1483
1511
  * import { IAP } from "@apps-in-toss/web-framework";
1484
1512
  * import { Button } from "@toss-design-system/react-native";
1513
+ * import { useCallback } from "react";
1485
1514
  *
1486
1515
  * interface Props {
1487
- * productId: string;
1516
+ * sku: string;
1488
1517
  * }
1489
1518
  *
1490
- * function IapCreateOneTimePurchaseOrderButton({ productId }: Props) {
1491
- * async function handleClick() {
1492
- * try {
1493
- * await IAP.createOneTimePurchaseOrder({
1494
- * productId,
1495
- * });
1496
- * console.error("์ธ์•ฑ๊ฒฐ์ œ์— ์„ฑ๊ณตํ–ˆ์–ด์š”");
1497
- * } catch (error) {
1498
- * console.error('์ธ์•ฑ๊ฒฐ์ œ์— ์‹คํŒจํ–ˆ์–ด์š”:', error);
1499
- * }
1500
- * }
1519
+ * function IapCreateOneTimePurchaseOrderButton({ sku }: Props) {
1520
+ * const handleClick = useCallback(async () => {
1521
+ *
1522
+ * const cleanup = await IAP.createOneTimePurchaseOrder({
1523
+ * options: {
1524
+ * sku,
1525
+ * processProductGrant: ({ orderId }) => {
1526
+ * // ์ƒํ’ˆ ์ง€๊ธ‰ ๋กœ์ง ์ž‘์„ฑ
1527
+ * return true; // ์ƒํ’ˆ ์ง€๊ธ‰ ์—ฌ๋ถ€
1528
+ * }
1529
+ * },
1530
+ * onEvent: (event) => {
1531
+ * console.log(event);
1532
+ * },
1533
+ * onError: (error) => {
1534
+ * console.error(error);
1535
+ * },
1536
+ * });
1537
+ *
1538
+ * return cleanup;
1539
+ * }, []);
1501
1540
  *
1502
1541
  * return <Button onClick={handleClick}>๊ตฌ๋งคํ•˜๊ธฐ</Button>;
1503
1542
  * }
1504
1543
  * ```
1505
1544
  */
1506
- declare function createOneTimePurchaseOrder(params: IapCreateOneTimePurchaseOrderOptions): Promise<IapCreateOneTimePurchaseOrderResult | undefined>;
1545
+ declare function createOneTimePurchaseOrder(params: IapCreateOneTimePurchaseOrderOptions): () => void;
1507
1546
  /**
1508
1547
  * @public
1509
1548
  * @category ์ธ์•ฑ๊ฒฐ์ œ
@@ -1525,7 +1564,7 @@ interface IapProductListItem {
1525
1564
  /**
1526
1565
  * @public
1527
1566
  * @category ์ธ์•ฑ๊ฒฐ์ œ
1528
- * @name iapGetProductItemList
1567
+ * @name getProductItemList
1529
1568
  * @description ์ธ์•ฑ๊ฒฐ์ œ๋กœ ๊ตฌ๋งคํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํ’ˆ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์™€์š”. ์ƒํ’ˆ ๋ชฉ๋ก ํ™”๋ฉด์— ์ง„์ž…ํ•  ๋•Œ ํ˜ธ์ถœํ•ด์š”.
1530
1569
  * @returns {Promise<{ products: IapProductListItem[] } | undefined>} ์ƒํ’ˆ ๋ชฉ๋ก์„ ํฌํ•จํ•œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”. ์•ฑ ๋ฒ„์ „์ด ์ตœ์†Œ ์ง€์› ๋ฒ„์ „(์•ˆ๋“œ๋กœ์ด๋“œ 5.219.0, iOS 5.219.0)๋ณด๋‹ค ๋‚ฎ์œผ๋ฉด `undefined`๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”.
1531
1570
  *
@@ -1773,10 +1812,24 @@ interface Spec extends TurboModule {
1773
1812
  }) => Promise<void>;
1774
1813
  saveBase64Data: (params: SaveBase64DataParams) => Promise<void>;
1775
1814
  /** IAP */
1776
- iapCreateOneTimePurchaseOrder: (params: IapCreateOneTimePurchaseOrderOptions) => Promise<IapCreateOneTimePurchaseOrderResult>;
1777
1815
  iapGetProductItemList: (arg: CompatiblePlaceholderArgument) => Promise<{
1778
1816
  products: IapProductListItem[];
1779
1817
  }>;
1818
+ /** @deprecated `requestOneTimePurchase`๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”. */
1819
+ iapCreateOneTimePurchaseOrder: (params: {
1820
+ productId: string;
1821
+ }) => Promise<IapCreateOneTimePurchaseOrderResult>;
1822
+ requestOneTimePurchase: (params: {
1823
+ sku: string;
1824
+ }, fallbacks: {
1825
+ onPurchased: (params: {
1826
+ orderId: string;
1827
+ }) => void;
1828
+ }) => () => void;
1829
+ processProductGrant: (params: {
1830
+ orderId: string;
1831
+ isProductGranted: boolean;
1832
+ }) => Promise<void>;
1780
1833
  getGameCenterGameProfile: (params: CompatiblePlaceholderArgument) => Promise<GameCenterGameProfileResponse>;
1781
1834
  submitGameCenterLeaderBoardScore: (params: {
1782
1835
  score: string;
@@ -3195,4 +3248,4 @@ declare const INTERNAL__module: {
3195
3248
  tossCoreEventLog: typeof tossCoreEventLog;
3196
3249
  };
3197
3250
 
3198
- export { AppsInTossModule, BedrockCoreModule, BedrockModule, type CheckoutPaymentOptions, type CheckoutPaymentResult, type ContactsViralParams, type EventLogParams, type GameCenterGameProfileResponse, GoogleAdMob, type HapticFeedbackType, IAP, AppsInTossModuleInstance as INTERNAL__AppsInTossModule, INTERNAL__appBridgeHandler, INTERNAL__module, type IapCreateOneTimePurchaseOrderOptions, type IapCreateOneTimePurchaseOrderResult, type IapProductListItem, type LoadAdMobEvent, type LoadAdMobInterstitialAdEvent, type LoadAdMobInterstitialAdOptions, type LoadAdMobOptions, type LoadAdMobParams, type LoadAdMobRewardedAdEvent, type LoadAdMobRewardedAdOptions, type NetworkStatus, type Primitive, type SaveBase64DataParams, type ShowAdMobEvent, type ShowAdMobInterstitialAdEvent, type ShowAdMobInterstitialAdOptions, type ShowAdMobOptions, type ShowAdMobParams, type ShowAdMobRewardedAdEvent, type ShowAdMobRewardedAdOptions, Storage, type SubmitGameCenterLeaderBoardScoreResponse, TossPay, type UpdateLocationEventEmitter, appLogin, appsInTossEvent, closeView, contactsViral, eventLog, fetchAlbumPhotos, fetchContacts, generateHapticFeedback, getClipboardText, getCurrentLocation, getDeviceId, getGameCenterGameProfile, getLocale, getNetworkStatus, getOperationalEnvironment, getPlatformOS, getSchemeUri, getTossAppVersion, getTossShareLink, isMinVersionSupported, onVisibilityChangedByTransparentServiceWeb, openCamera, openGameCenterLeaderboard, openURL, saveBase64Data, setClipboardText, setDeviceOrientation, setIosSwipeGestureEnabled, setScreenAwakeMode, setSecureScreen, share, startUpdateLocation, submitGameCenterLeaderBoardScore };
3251
+ export { AppsInTossModule, BedrockCoreModule, BedrockModule, type CheckoutPaymentOptions, type CheckoutPaymentResult, type ContactsViralParams, type EventLogParams, type GameCenterGameProfileResponse, GoogleAdMob, type HapticFeedbackType, IAP, AppsInTossModuleInstance as INTERNAL__AppsInTossModule, INTERNAL__appBridgeHandler, INTERNAL__module, type IapCreateOneTimePurchaseOrderOptions, type IapCreateOneTimePurchaseOrderResult, type IapProductListItem, type LoadAdMobEvent, type LoadAdMobInterstitialAdEvent, type LoadAdMobInterstitialAdOptions, type LoadAdMobOptions, type LoadAdMobParams, type LoadAdMobRewardedAdEvent, type LoadAdMobRewardedAdOptions, type NetworkStatus, type Primitive, type SaveBase64DataParams, type ShowAdMobEvent, type ShowAdMobInterstitialAdEvent, type ShowAdMobInterstitialAdOptions, type ShowAdMobOptions, type ShowAdMobParams, type ShowAdMobRewardedAdEvent, type ShowAdMobRewardedAdOptions, Storage, type SubmitGameCenterLeaderBoardScoreResponse, TossPay, type UpdateLocationEventEmitter, appLogin, appsInTossEvent, closeView, contactsViral, eventLog, fetchAlbumPhotos, fetchContacts, generateHapticFeedback, getClipboardText, getCurrentLocation, getDeviceId, getGameCenterGameProfile, getLocale, getNetworkStatus, getOperationalEnvironment, getPlatformOS, getSchemeUri, getTossAppVersion, getTossShareLink, iapCreateOneTimePurchaseOrder, isMinVersionSupported, onVisibilityChangedByTransparentServiceWeb, openCamera, openGameCenterLeaderboard, openURL, processProductGrant, requestOneTimePurchase, saveBase64Data, setClipboardText, setDeviceOrientation, setIosSwipeGestureEnabled, setScreenAwakeMode, setSecureScreen, share, startUpdateLocation, submitGameCenterLeaderBoardScore };
package/dist/index.d.ts CHANGED
@@ -231,24 +231,12 @@ interface ContactsViralParams {
231
231
  */
232
232
  declare function contactsViral(params: ContactsViralParams): () => void;
233
233
 
234
- declare class BackButtonClickHandleEvent extends GraniteEventDefinition<undefined, undefined> {
235
- name: "backButtonClickEvent";
236
- remove(): void;
237
- listener(_: undefined): void;
238
- }
239
-
240
234
  declare class EntryMessageExitedEvent extends GraniteEventDefinition<undefined, undefined> {
241
235
  name: "entryMessageExited";
242
236
  remove(): void;
243
237
  listener(_: undefined): void;
244
238
  }
245
239
 
246
- declare class HomeIconButtonClickHandleEvent extends GraniteEventDefinition<undefined, undefined> {
247
- name: "homeIconButtonClickEvent";
248
- remove(): void;
249
- listener(_: undefined): void;
250
- }
251
-
252
240
  interface StartUpdateLocationOptions {
253
241
  /**
254
242
  * ์œ„์น˜ ์ •ํ™•๋„๋ฅผ ์„ค์ •ํ•ด์š”.
@@ -298,7 +286,7 @@ declare class VisibilityChangedByTransparentServiceWebEvent extends GraniteEvent
298
286
  private isVisibilityChangedByTransparentServiceWebResult;
299
287
  }
300
288
 
301
- declare const appsInTossEvent: GraniteEvent<BackButtonClickHandleEvent | EntryMessageExitedEvent | HomeIconButtonClickHandleEvent | UpdateLocationEvent | AppBridgeCallbackEvent | VisibilityChangedByTransparentServiceWebEvent>;
289
+ declare const appsInTossEvent: GraniteEvent<EntryMessageExitedEvent | UpdateLocationEvent | AppBridgeCallbackEvent | VisibilityChangedByTransparentServiceWebEvent>;
302
290
 
303
291
  declare function onVisibilityChangedByTransparentServiceWeb(eventParams: {
304
292
  options: {
@@ -1423,16 +1411,16 @@ type GameCenterGameProfileResponse = {
1423
1411
  */
1424
1412
  declare function getGameCenterGameProfile(): Promise<GameCenterGameProfileResponse | undefined>;
1425
1413
 
1426
- /**
1427
- * @public
1428
- * @category ์ธ์•ฑ๊ฒฐ์ œ
1429
- * @name IapCreateOneTimePurchaseOrderOptions
1430
- * @description ์ธ์•ฑ๊ฒฐ์ œ 1๊ฑด์„ ์š”์ฒญํ•  ๋•Œ ํ•„์š”ํ•œ ์ •๋ณด์˜ˆ์š”.
1431
- * @property {string} productId - ์ฃผ๋ฌธํ•  ์ƒํ’ˆ์˜ ID์˜ˆ์š”.
1432
- */
1433
- interface IapCreateOneTimePurchaseOrderOptions {
1414
+ type Sku = {
1415
+ /**
1416
+ * @deprecated `productId`๋Š” ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„์š”. ๋Œ€์‹  `sku`๋ฅผ ์‚ฌ์šฉํ•ด์š”.
1417
+ */
1434
1418
  productId: string;
1435
- }
1419
+ sku?: string;
1420
+ } | {
1421
+ productId?: never;
1422
+ sku: string;
1423
+ };
1436
1424
  /**
1437
1425
  * @public
1438
1426
  * @category ์ธ์•ฑ๊ฒฐ์ œ
@@ -1455,15 +1443,54 @@ interface IapCreateOneTimePurchaseOrderResult {
1455
1443
  fraction: number;
1456
1444
  miniAppIconUrl: string | null;
1457
1445
  }
1446
+ interface SuccessEvent {
1447
+ type: 'success';
1448
+ data: IapCreateOneTimePurchaseOrderResult;
1449
+ }
1450
+ interface PurchasedEvent {
1451
+ type: 'purchased';
1452
+ data: {
1453
+ orderId: string;
1454
+ };
1455
+ }
1456
+ /**
1457
+ * @public
1458
+ * @category ์ธ์•ฑ๊ฒฐ์ œ
1459
+ * @name IapCreateOneTimePurchaseOrderOptions
1460
+ * @property {Sku} options - ๊ฒฐ์ œํ•  ์ƒํ’ˆ์˜ ์ •๋ณด์˜ˆ์š”.
1461
+ * @property {string} options.sku - ์ฃผ๋ฌธํ•  ์ƒํ’ˆ์˜ ๊ณ ์œ  ID์˜ˆ์š”.
1462
+ * @property {(params: { orderId: string }) => boolean | Promise<boolean>} processProductGrant - ์ฃผ๋ฌธ์ด ๋งŒ๋“ค์–ด์ง„ ๋’ค ์‹ค์ œ๋กœ ์ƒํ’ˆ์„ ์ง€๊ธ‰ํ•  ๋•Œ ํ˜ธ์ถœํ•ด์š”. `orderId`๋ฅผ ๋ฐ›์•„์„œ ์ง€๊ธ‰ ์„ฑ๊ณต ์—ฌ๋ถ€๋ฅผ `true` ๋˜๋Š” `Promise<true>`๋กœ ๋ฐ˜ํ™˜ํ•ด์š”. ์ง€๊ธ‰์— ์‹คํŒจํ•˜๋ฉด `false`๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”.
1463
+ * @property {(event: SuccessEvent) => void | Promise<void>} onEvent - ๊ฒฐ์ œ๊ฐ€ ์„ฑ๊ณตํ–ˆ์„ ๋•Œ ํ˜ธ์ถœํ•ด์š”. `event.type`์ด `'success'`์ด๊ณ , `event.data`์— `IapCreateOneTimePurchaseOrderResult`๊ฐ€ ๋“ค์–ด ์žˆ์–ด์š”.
1464
+ * @property {(error: unknown) => void | Promise<void>} onError - ๊ฒฐ์ œ ๊ณผ์ •์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํ˜ธ์ถœํ•ด์š”. ์—๋Ÿฌ ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„์„œ ๋กœ๊น…ํ•˜๊ฑฐ๋‚˜ ๋ณต๊ตฌ ์ ˆ์ฐจ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด์š”.
1465
+ */
1466
+ interface IapCreateOneTimePurchaseOrderOptions {
1467
+ options: Sku & {
1468
+ processProductGrant: (params: {
1469
+ orderId: string;
1470
+ }) => boolean | Promise<boolean>;
1471
+ };
1472
+ onEvent: (event: SuccessEvent) => void | Promise<void>;
1473
+ onError: (error: unknown) => void | Promise<void>;
1474
+ }
1475
+ interface IapRequestOneTimePurchaseOptions {
1476
+ options: Sku;
1477
+ onEvent: (event: PurchasedEvent | SuccessEvent) => void | Promise<void>;
1478
+ onError: (error: unknown) => void | Promise<void>;
1479
+ }
1480
+ declare function iapCreateOneTimePurchaseOrder(params: Sku): Promise<IapCreateOneTimePurchaseOrderResult>;
1481
+ declare function processProductGrant(params: {
1482
+ orderId: string;
1483
+ isProductGranted: boolean;
1484
+ }): Promise<void>;
1485
+ declare function requestOneTimePurchase(params: IapRequestOneTimePurchaseOptions): () => void;
1458
1486
  /**
1459
1487
  * @public
1460
1488
  * @category ์ธ์•ฑ๊ฒฐ์ œ
1461
- * @name iapCreateOneTimePurchaseOrder
1489
+ * @name createOneTimePurchaseOrder
1462
1490
  * @description
1463
1491
  * ํŠน์ • ์ธ์•ฑ๊ฒฐ์ œ ์ฃผ๋ฌธ์„œ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ด์š”. ์‚ฌ์šฉ์ž๊ฐ€ ์ƒํ’ˆ ๊ตฌ๋งค ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋Š” ์ƒํ™ฉ ๋“ฑ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ์‚ฌ์šฉ์ž์˜ ๊ฒฐ์ œ๋Š” ์ด๋™ํ•œ ํŽ˜์ด์ง€์—์„œ ์ง„ํ–‰๋ผ์š”. ๋งŒ์•ฝ ๊ฒฐ์ œ ์ค‘์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์—๋Ÿฌ ์œ ํ˜•์— ๋”ฐ๋ผ ์—๋Ÿฌ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ด์š”.
1464
1492
  * @param {IapCreateOneTimePurchaseOrderOptions} params - ์ธ์•ฑ๊ฒฐ์ œ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ•„์š”ํ•œ ์ •๋ณด์˜ˆ์š”.
1465
- * @param {string} params.productId - ์ฃผ๋ฌธํ•  ์ƒํ’ˆ์˜ ID์˜ˆ์š”.
1466
- * @returns {Promise<IapCreateOneTimePurchaseOrderResult | undefined>} ๊ฒฐ์ œ์— ์„ฑ๊ณตํ•˜๋ฉด ๊ฒฐ์ œ ๊ฒฐ๊ณผ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”. ์•ฑ ๋ฒ„์ „์ด ์ตœ์†Œ ์ง€์› ๋ฒ„์ „(์•ˆ๋“œ๋กœ์ด๋“œ 5.219.0, iOS 5.219.0)๋ณด๋‹ค ๋‚ฎ์œผ๋ฉด ์ธ์•ฑ๊ฒฐ์ œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์—†์–ด์„œ `undefined`๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”.
1493
+ * @returns {() => void} ์•ฑ๋ธŒ๋ฆฟ์ง€ cleanup ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”. ์ธ์•ฑ๊ฒฐ์ œ ๊ธฐ๋Šฅ์ด ๋๋‚˜๋ฉด ๋ฐ˜๋“œ์‹œ ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด์ œํ•ด์•ผ ํ•ด์š”.
1467
1494
  *
1468
1495
  * @throw {code: "INVALID_PRODUCT_ID"} - ์œ ํšจํ•˜์ง€ ์•Š์€ ์ƒํ’ˆ ID์ด๊ฑฐ๋‚˜, ํ•ด๋‹น ์ƒํ’ˆ์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
1469
1496
  * @throw {code: "PAYMENT_PENDING"} - ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•œ ๊ฒฐ์ œ๊ฐ€ ์•„์ง ์Šน์ธ์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
@@ -1475,6 +1502,7 @@ interface IapCreateOneTimePurchaseOrderResult {
1475
1502
  * @throw {code: "INTERNAL_ERROR"} - ์„œ๋ฒ„ ๋‚ด๋ถ€ ๋ฌธ์ œ๋กœ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
1476
1503
  * @throw {code: "KOREAN_ACCOUNT_ONLY"} - iOS ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉ์ž์˜ ๊ณ„์ •์ด ํ•œ๊ตญ ๊ณ„์ •์ด ์•„๋‹ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
1477
1504
  * @throw {code: "USER_CANCELED"} - ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒฐ์ œ๋ฅผ ์™„๋ฃŒํ•˜์ง€ ์•Š๊ณ  ์ฃผ๋ฌธ์„œ ํŽ˜์ด์ง€๋ฅผ ์ดํƒˆํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
1505
+ * @throw {code: "PRODUCT_NOT_GRANTED_BY_PARTNER"} - ํŒŒํŠธ๋„ˆ์‚ฌ์˜ ์ƒํ’ˆ ์ง€๊ธ‰์ด ์‹คํŒจํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
1478
1506
  *
1479
1507
  * @example
1480
1508
  * ### ํŠน์ • ์ธ์•ฑ๊ฒฐ์ œ ์ฃผ๋ฌธ์„œ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๊ธฐ
@@ -1482,28 +1510,39 @@ interface IapCreateOneTimePurchaseOrderResult {
1482
1510
  * ```tsx
1483
1511
  * import { IAP } from "@apps-in-toss/web-framework";
1484
1512
  * import { Button } from "@toss-design-system/react-native";
1513
+ * import { useCallback } from "react";
1485
1514
  *
1486
1515
  * interface Props {
1487
- * productId: string;
1516
+ * sku: string;
1488
1517
  * }
1489
1518
  *
1490
- * function IapCreateOneTimePurchaseOrderButton({ productId }: Props) {
1491
- * async function handleClick() {
1492
- * try {
1493
- * await IAP.createOneTimePurchaseOrder({
1494
- * productId,
1495
- * });
1496
- * console.error("์ธ์•ฑ๊ฒฐ์ œ์— ์„ฑ๊ณตํ–ˆ์–ด์š”");
1497
- * } catch (error) {
1498
- * console.error('์ธ์•ฑ๊ฒฐ์ œ์— ์‹คํŒจํ–ˆ์–ด์š”:', error);
1499
- * }
1500
- * }
1519
+ * function IapCreateOneTimePurchaseOrderButton({ sku }: Props) {
1520
+ * const handleClick = useCallback(async () => {
1521
+ *
1522
+ * const cleanup = await IAP.createOneTimePurchaseOrder({
1523
+ * options: {
1524
+ * sku,
1525
+ * processProductGrant: ({ orderId }) => {
1526
+ * // ์ƒํ’ˆ ์ง€๊ธ‰ ๋กœ์ง ์ž‘์„ฑ
1527
+ * return true; // ์ƒํ’ˆ ์ง€๊ธ‰ ์—ฌ๋ถ€
1528
+ * }
1529
+ * },
1530
+ * onEvent: (event) => {
1531
+ * console.log(event);
1532
+ * },
1533
+ * onError: (error) => {
1534
+ * console.error(error);
1535
+ * },
1536
+ * });
1537
+ *
1538
+ * return cleanup;
1539
+ * }, []);
1501
1540
  *
1502
1541
  * return <Button onClick={handleClick}>๊ตฌ๋งคํ•˜๊ธฐ</Button>;
1503
1542
  * }
1504
1543
  * ```
1505
1544
  */
1506
- declare function createOneTimePurchaseOrder(params: IapCreateOneTimePurchaseOrderOptions): Promise<IapCreateOneTimePurchaseOrderResult | undefined>;
1545
+ declare function createOneTimePurchaseOrder(params: IapCreateOneTimePurchaseOrderOptions): () => void;
1507
1546
  /**
1508
1547
  * @public
1509
1548
  * @category ์ธ์•ฑ๊ฒฐ์ œ
@@ -1525,7 +1564,7 @@ interface IapProductListItem {
1525
1564
  /**
1526
1565
  * @public
1527
1566
  * @category ์ธ์•ฑ๊ฒฐ์ œ
1528
- * @name iapGetProductItemList
1567
+ * @name getProductItemList
1529
1568
  * @description ์ธ์•ฑ๊ฒฐ์ œ๋กœ ๊ตฌ๋งคํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํ’ˆ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์™€์š”. ์ƒํ’ˆ ๋ชฉ๋ก ํ™”๋ฉด์— ์ง„์ž…ํ•  ๋•Œ ํ˜ธ์ถœํ•ด์š”.
1530
1569
  * @returns {Promise<{ products: IapProductListItem[] } | undefined>} ์ƒํ’ˆ ๋ชฉ๋ก์„ ํฌํ•จํ•œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”. ์•ฑ ๋ฒ„์ „์ด ์ตœ์†Œ ์ง€์› ๋ฒ„์ „(์•ˆ๋“œ๋กœ์ด๋“œ 5.219.0, iOS 5.219.0)๋ณด๋‹ค ๋‚ฎ์œผ๋ฉด `undefined`๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”.
1531
1570
  *
@@ -1773,10 +1812,24 @@ interface Spec extends TurboModule {
1773
1812
  }) => Promise<void>;
1774
1813
  saveBase64Data: (params: SaveBase64DataParams) => Promise<void>;
1775
1814
  /** IAP */
1776
- iapCreateOneTimePurchaseOrder: (params: IapCreateOneTimePurchaseOrderOptions) => Promise<IapCreateOneTimePurchaseOrderResult>;
1777
1815
  iapGetProductItemList: (arg: CompatiblePlaceholderArgument) => Promise<{
1778
1816
  products: IapProductListItem[];
1779
1817
  }>;
1818
+ /** @deprecated `requestOneTimePurchase`๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”. */
1819
+ iapCreateOneTimePurchaseOrder: (params: {
1820
+ productId: string;
1821
+ }) => Promise<IapCreateOneTimePurchaseOrderResult>;
1822
+ requestOneTimePurchase: (params: {
1823
+ sku: string;
1824
+ }, fallbacks: {
1825
+ onPurchased: (params: {
1826
+ orderId: string;
1827
+ }) => void;
1828
+ }) => () => void;
1829
+ processProductGrant: (params: {
1830
+ orderId: string;
1831
+ isProductGranted: boolean;
1832
+ }) => Promise<void>;
1780
1833
  getGameCenterGameProfile: (params: CompatiblePlaceholderArgument) => Promise<GameCenterGameProfileResponse>;
1781
1834
  submitGameCenterLeaderBoardScore: (params: {
1782
1835
  score: string;
@@ -3195,4 +3248,4 @@ declare const INTERNAL__module: {
3195
3248
  tossCoreEventLog: typeof tossCoreEventLog;
3196
3249
  };
3197
3250
 
3198
- export { AppsInTossModule, BedrockCoreModule, BedrockModule, type CheckoutPaymentOptions, type CheckoutPaymentResult, type ContactsViralParams, type EventLogParams, type GameCenterGameProfileResponse, GoogleAdMob, type HapticFeedbackType, IAP, AppsInTossModuleInstance as INTERNAL__AppsInTossModule, INTERNAL__appBridgeHandler, INTERNAL__module, type IapCreateOneTimePurchaseOrderOptions, type IapCreateOneTimePurchaseOrderResult, type IapProductListItem, type LoadAdMobEvent, type LoadAdMobInterstitialAdEvent, type LoadAdMobInterstitialAdOptions, type LoadAdMobOptions, type LoadAdMobParams, type LoadAdMobRewardedAdEvent, type LoadAdMobRewardedAdOptions, type NetworkStatus, type Primitive, type SaveBase64DataParams, type ShowAdMobEvent, type ShowAdMobInterstitialAdEvent, type ShowAdMobInterstitialAdOptions, type ShowAdMobOptions, type ShowAdMobParams, type ShowAdMobRewardedAdEvent, type ShowAdMobRewardedAdOptions, Storage, type SubmitGameCenterLeaderBoardScoreResponse, TossPay, type UpdateLocationEventEmitter, appLogin, appsInTossEvent, closeView, contactsViral, eventLog, fetchAlbumPhotos, fetchContacts, generateHapticFeedback, getClipboardText, getCurrentLocation, getDeviceId, getGameCenterGameProfile, getLocale, getNetworkStatus, getOperationalEnvironment, getPlatformOS, getSchemeUri, getTossAppVersion, getTossShareLink, isMinVersionSupported, onVisibilityChangedByTransparentServiceWeb, openCamera, openGameCenterLeaderboard, openURL, saveBase64Data, setClipboardText, setDeviceOrientation, setIosSwipeGestureEnabled, setScreenAwakeMode, setSecureScreen, share, startUpdateLocation, submitGameCenterLeaderBoardScore };
3251
+ export { AppsInTossModule, BedrockCoreModule, BedrockModule, type CheckoutPaymentOptions, type CheckoutPaymentResult, type ContactsViralParams, type EventLogParams, type GameCenterGameProfileResponse, GoogleAdMob, type HapticFeedbackType, IAP, AppsInTossModuleInstance as INTERNAL__AppsInTossModule, INTERNAL__appBridgeHandler, INTERNAL__module, type IapCreateOneTimePurchaseOrderOptions, type IapCreateOneTimePurchaseOrderResult, type IapProductListItem, type LoadAdMobEvent, type LoadAdMobInterstitialAdEvent, type LoadAdMobInterstitialAdOptions, type LoadAdMobOptions, type LoadAdMobParams, type LoadAdMobRewardedAdEvent, type LoadAdMobRewardedAdOptions, type NetworkStatus, type Primitive, type SaveBase64DataParams, type ShowAdMobEvent, type ShowAdMobInterstitialAdEvent, type ShowAdMobInterstitialAdOptions, type ShowAdMobOptions, type ShowAdMobParams, type ShowAdMobRewardedAdEvent, type ShowAdMobRewardedAdOptions, Storage, type SubmitGameCenterLeaderBoardScoreResponse, TossPay, type UpdateLocationEventEmitter, appLogin, appsInTossEvent, closeView, contactsViral, eventLog, fetchAlbumPhotos, fetchContacts, generateHapticFeedback, getClipboardText, getCurrentLocation, getDeviceId, getGameCenterGameProfile, getLocale, getNetworkStatus, getOperationalEnvironment, getPlatformOS, getSchemeUri, getTossAppVersion, getTossShareLink, iapCreateOneTimePurchaseOrder, isMinVersionSupported, onVisibilityChangedByTransparentServiceWeb, openCamera, openGameCenterLeaderboard, openURL, processProductGrant, requestOneTimePurchase, saveBase64Data, setClipboardText, setDeviceOrientation, setIosSwipeGestureEnabled, setScreenAwakeMode, setSecureScreen, share, startUpdateLocation, submitGameCenterLeaderBoardScore };
package/dist/index.js CHANGED
@@ -1,20 +1,9 @@
1
1
  // src/AppsInTossModule/native-event-emitter/appsInTossEvent.ts
2
2
  import { GraniteEvent } from "@granite-js/react-native";
3
3
 
4
- // src/AppsInTossModule/native-event-emitter/event-plugins/BackButtonClickHandleEvent.ts
5
- import { GraniteEventDefinition } from "@granite-js/react-native";
6
- var BackButtonClickHandleEvent = class extends GraniteEventDefinition {
7
- name = "backButtonClickEvent";
8
- remove() {
9
- }
10
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
11
- listener(_) {
12
- }
13
- };
14
-
15
4
  // src/AppsInTossModule/native-event-emitter/event-plugins/EntryMessageExitedEvent.ts
16
- import { GraniteEventDefinition as GraniteEventDefinition2 } from "@granite-js/react-native";
17
- var EntryMessageExitedEvent = class extends GraniteEventDefinition2 {
5
+ import { GraniteEventDefinition } from "@granite-js/react-native";
6
+ var EntryMessageExitedEvent = class extends GraniteEventDefinition {
18
7
  name = "entryMessageExited";
19
8
  remove() {
20
9
  }
@@ -23,20 +12,9 @@ var EntryMessageExitedEvent = class extends GraniteEventDefinition2 {
23
12
  }
24
13
  };
25
14
 
26
- // src/AppsInTossModule/native-event-emitter/event-plugins/HomeIconButtonClickHandleEvent.ts
27
- import { GraniteEventDefinition as GraniteEventDefinition3 } from "@granite-js/react-native";
28
- var HomeIconButtonClickHandleEvent = class extends GraniteEventDefinition3 {
29
- name = "homeIconButtonClickEvent";
30
- remove() {
31
- }
32
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
33
- listener(_) {
34
- }
35
- };
36
-
37
15
  // src/AppsInTossModule/native-event-emitter/event-plugins/UpdateLocationEvent.ts
38
16
  import { GetCurrentLocationPermissionError } from "@apps-in-toss/types";
39
- import { GraniteEventDefinition as GraniteEventDefinition4 } from "@granite-js/react-native";
17
+ import { GraniteEventDefinition as GraniteEventDefinition2 } from "@granite-js/react-native";
40
18
 
41
19
  // src/AppsInTossModule/native-modules/AppsInTossModule.ts
42
20
  import { TurboModuleRegistry } from "react-native";
@@ -71,7 +49,7 @@ import { NativeEventEmitter } from "react-native";
71
49
  var nativeEventEmitter = new NativeEventEmitter(AppsInTossModuleInstance);
72
50
 
73
51
  // src/AppsInTossModule/native-event-emitter/event-plugins/UpdateLocationEvent.ts
74
- var UpdateLocationEvent = class extends GraniteEventDefinition4 {
52
+ var UpdateLocationEvent = class extends GraniteEventDefinition2 {
75
53
  name = "updateLocationEvent";
76
54
  subscriptionCount = 0;
77
55
  ref = {
@@ -101,7 +79,7 @@ var UpdateLocationEvent = class extends GraniteEventDefinition4 {
101
79
  };
102
80
 
103
81
  // src/AppsInTossModule/native-event-emitter/internal/AppBridgeCallbackEvent.ts
104
- import { GraniteEventDefinition as GraniteEventDefinition5 } from "@granite-js/react-native";
82
+ import { GraniteEventDefinition as GraniteEventDefinition3 } from "@granite-js/react-native";
105
83
 
106
84
  // src/utils/generateUUID.ts
107
85
  function generateUUID(placeholder) {
@@ -163,7 +141,7 @@ var INTERNAL__appBridgeHandler = {
163
141
 
164
142
  // src/AppsInTossModule/native-event-emitter/internal/AppBridgeCallbackEvent.ts
165
143
  var UNSAFE__nativeEventEmitter = nativeEventEmitter;
166
- var AppBridgeCallbackEvent = class _AppBridgeCallbackEvent extends GraniteEventDefinition5 {
144
+ var AppBridgeCallbackEvent = class _AppBridgeCallbackEvent extends GraniteEventDefinition3 {
167
145
  static INTERNAL__appBridgeSubscription;
168
146
  name = "appBridgeCallbackEvent";
169
147
  constructor() {
@@ -193,8 +171,8 @@ var AppBridgeCallbackEvent = class _AppBridgeCallbackEvent extends GraniteEventD
193
171
  };
194
172
 
195
173
  // src/AppsInTossModule/native-event-emitter/internal/VisibilityChangedByTransparentServiceWebEvent.ts
196
- import { GraniteEventDefinition as GraniteEventDefinition6 } from "@granite-js/react-native";
197
- var VisibilityChangedByTransparentServiceWebEvent = class extends GraniteEventDefinition6 {
174
+ import { GraniteEventDefinition as GraniteEventDefinition4 } from "@granite-js/react-native";
175
+ var VisibilityChangedByTransparentServiceWebEvent = class extends GraniteEventDefinition4 {
198
176
  name = "onVisibilityChangedByTransparentServiceWeb";
199
177
  subscription = null;
200
178
  remove() {
@@ -222,9 +200,6 @@ var VisibilityChangedByTransparentServiceWebEvent = class extends GraniteEventDe
222
200
  var appsInTossEvent = new GraniteEvent([
223
201
  new UpdateLocationEvent(),
224
202
  new EntryMessageExitedEvent(),
225
- // Navigation Bar events
226
- new HomeIconButtonClickHandleEvent(),
227
- new BackButtonClickHandleEvent(),
228
203
  // Internal events
229
204
  new AppBridgeCallbackEvent(),
230
205
  new VisibilityChangedByTransparentServiceWebEvent()
@@ -665,15 +640,80 @@ async function getTossShareLink(path) {
665
640
  }
666
641
 
667
642
  // src/AppsInTossModule/native-modules/iap.ts
668
- async function createOneTimePurchaseOrder(params) {
669
- const isSupported = isMinVersionSupported({
643
+ import { noop as noop3 } from "es-toolkit";
644
+ function iapCreateOneTimePurchaseOrder(params) {
645
+ const sku = params.sku ?? params.productId;
646
+ return AppsInTossModule.iapCreateOneTimePurchaseOrder({ productId: sku });
647
+ }
648
+ function processProductGrant(params) {
649
+ return AppsInTossModule.processProductGrant({ orderId: params.orderId, isProductGranted: params.isProductGranted });
650
+ }
651
+ function requestOneTimePurchase(params) {
652
+ const { options, onEvent, onError } = params;
653
+ const sku = options.sku ?? options.productId;
654
+ const unregisterCallbacks = INTERNAL__appBridgeHandler.invokeAppBridgeMethod(
655
+ "requestOneTimePurchase",
656
+ { sku },
657
+ {
658
+ onPurchased: (params2) => {
659
+ onEvent({ type: "purchased", data: params2 });
660
+ },
661
+ onSuccess: (result) => {
662
+ onEvent({ type: "success", data: result });
663
+ },
664
+ onError: (error) => {
665
+ onError(error);
666
+ }
667
+ }
668
+ );
669
+ return unregisterCallbacks;
670
+ }
671
+ function createOneTimePurchaseOrder(params) {
672
+ const isIAPSupported = isMinVersionSupported({
670
673
  android: "5.219.0",
671
674
  ios: "5.219.0"
672
675
  });
673
- if (!isSupported) {
674
- return;
676
+ if (!isIAPSupported) {
677
+ return noop3;
675
678
  }
676
- return AppsInTossModule.iapCreateOneTimePurchaseOrder(params);
679
+ const isProcessProductGrantSupported = isMinVersionSupported({
680
+ android: "5.230.0",
681
+ ios: "5.230.0"
682
+ });
683
+ const { options, onEvent, onError } = params;
684
+ const sku = options.sku ?? options.productId;
685
+ if (!isProcessProductGrantSupported) {
686
+ const v1 = () => {
687
+ AppsInTossModule.iapCreateOneTimePurchaseOrder({ productId: sku }).then((response) => {
688
+ Promise.resolve(options.processProductGrant({ orderId: response.orderId })).then(() => {
689
+ onEvent({ type: "success", data: response });
690
+ }).catch((error) => {
691
+ onError(error);
692
+ });
693
+ }).catch((error) => {
694
+ onError(error);
695
+ });
696
+ return noop3;
697
+ };
698
+ return v1();
699
+ }
700
+ const unregisterCallbacks = INTERNAL__appBridgeHandler.invokeAppBridgeMethod(
701
+ "requestOneTimePurchase",
702
+ { sku },
703
+ {
704
+ onPurchased: async (params2) => {
705
+ const isProductGranted = await options.processProductGrant(params2);
706
+ await AppsInTossModule.processProductGrant({ orderId: params2.orderId, isProductGranted });
707
+ },
708
+ onSuccess: (result) => {
709
+ onEvent({ type: "success", data: result });
710
+ },
711
+ onError: (error) => {
712
+ onError(error);
713
+ }
714
+ }
715
+ );
716
+ return unregisterCallbacks;
677
717
  }
678
718
  async function getProductItemList() {
679
719
  const isSupported = isMinVersionSupported({
@@ -960,11 +1000,14 @@ export {
960
1000
  getSchemeUri,
961
1001
  getTossAppVersion,
962
1002
  getTossShareLink,
1003
+ iapCreateOneTimePurchaseOrder,
963
1004
  isMinVersionSupported,
964
1005
  onVisibilityChangedByTransparentServiceWeb,
965
1006
  openCamera,
966
1007
  openGameCenterLeaderboard,
967
1008
  openURL2 as openURL,
1009
+ processProductGrant,
1010
+ requestOneTimePurchase,
968
1011
  saveBase64Data,
969
1012
  setClipboardText,
970
1013
  setDeviceOrientation,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@apps-in-toss/native-modules",
3
3
  "type": "module",
4
- "version": "1.1.1",
4
+ "version": "1.1.3",
5
5
  "description": "Native Modules for Apps In Toss",
6
6
  "scripts": {
7
7
  "prepack": "yarn build",
@@ -43,7 +43,7 @@
43
43
  "vitest": "^3.2.4"
44
44
  },
45
45
  "dependencies": {
46
- "@apps-in-toss/types": "^1.1.1",
46
+ "@apps-in-toss/types": "^1.1.3",
47
47
  "es-toolkit": "^1.39.3"
48
48
  },
49
49
  "peerDependencies": {
@@ -54,5 +54,5 @@
54
54
  "publishConfig": {
55
55
  "access": "public"
56
56
  },
57
- "gitHead": "0e0af7d44ed8ad2615a237650b9682c68ab5861e"
57
+ "gitHead": "0c80b4a0b49ec85f9f042909c7e9762c25425573"
58
58
  }
@@ -1,7 +1,5 @@
1
1
  import { GraniteEvent } from '@granite-js/react-native';
2
- import { BackButtonClickHandleEvent } from './event-plugins/BackButtonClickHandleEvent';
3
2
  import { EntryMessageExitedEvent } from './event-plugins/EntryMessageExitedEvent';
4
- import { HomeIconButtonClickHandleEvent } from './event-plugins/HomeIconButtonClickHandleEvent';
5
3
  import { UpdateLocationEvent } from './event-plugins/UpdateLocationEvent';
6
4
  import { AppBridgeCallbackEvent } from './internal/AppBridgeCallbackEvent';
7
5
  import { VisibilityChangedByTransparentServiceWebEvent } from './internal/VisibilityChangedByTransparentServiceWebEvent';
@@ -10,10 +8,6 @@ export const appsInTossEvent = new GraniteEvent([
10
8
  new UpdateLocationEvent(),
11
9
  new EntryMessageExitedEvent(),
12
10
 
13
- // Navigation Bar events
14
- new HomeIconButtonClickHandleEvent(),
15
- new BackButtonClickHandleEvent(),
16
-
17
11
  // Internal events
18
12
  new AppBridgeCallbackEvent(),
19
13
  new VisibilityChangedByTransparentServiceWebEvent(),
@@ -15,11 +15,7 @@ import type {
15
15
  import { TurboModuleRegistry, type TurboModule as __TurboModule } from 'react-native';
16
16
  import type { CheckoutPaymentOptions, CheckoutPaymentResult } from './checkoutPayment';
17
17
  import type { GameCenterGameProfileResponse } from './getGameCenterGameProfile';
18
- import type {
19
- IapCreateOneTimePurchaseOrderOptions,
20
- IapCreateOneTimePurchaseOrderResult,
21
- IapProductListItem,
22
- } from './iap';
18
+ import { IapCreateOneTimePurchaseOrderResult, IapProductListItem } from './iap';
23
19
  import type { SaveBase64DataParams } from './saveBase64Data';
24
20
  import type { SubmitGameCenterLeaderBoardScoreResponse } from './submitGameCenterLeaderBoardScore';
25
21
  import type { ContactsViralParams } from '../native-event-emitter/contactsViral';
@@ -68,10 +64,15 @@ interface Spec extends __TurboModule {
68
64
  saveBase64Data: (params: SaveBase64DataParams) => Promise<void>;
69
65
 
70
66
  /** IAP */
71
- iapCreateOneTimePurchaseOrder: (
72
- params: IapCreateOneTimePurchaseOrderOptions
73
- ) => Promise<IapCreateOneTimePurchaseOrderResult>;
74
67
  iapGetProductItemList: (arg: CompatiblePlaceholderArgument) => Promise<{ products: IapProductListItem[] }>;
68
+ /** @deprecated `requestOneTimePurchase`๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”. */
69
+ iapCreateOneTimePurchaseOrder: (params: { productId: string }) => Promise<IapCreateOneTimePurchaseOrderResult>;
70
+ requestOneTimePurchase: (
71
+ params: { sku: string },
72
+ fallbacks: { onPurchased: (params: { orderId: string }) => void }
73
+ ) => () => void;
74
+ processProductGrant: (params: { orderId: string; isProductGranted: boolean }) => Promise<void>;
75
+
75
76
  getGameCenterGameProfile: (params: CompatiblePlaceholderArgument) => Promise<GameCenterGameProfileResponse>;
76
77
  submitGameCenterLeaderBoardScore: (params: { score: string }) => Promise<SubmitGameCenterLeaderBoardScoreResponse>;
77
78
 
@@ -1,16 +1,20 @@
1
+ import { noop } from 'es-toolkit';
1
2
  import { AppsInTossModule } from './AppsInTossModule';
2
3
  import { isMinVersionSupported } from './isMinVersionSupported';
4
+ import { INTERNAL__appBridgeHandler } from '../native-event-emitter/internal/appBridge';
3
5
 
4
- /**
5
- * @public
6
- * @category ์ธ์•ฑ๊ฒฐ์ œ
7
- * @name IapCreateOneTimePurchaseOrderOptions
8
- * @description ์ธ์•ฑ๊ฒฐ์ œ 1๊ฑด์„ ์š”์ฒญํ•  ๋•Œ ํ•„์š”ํ•œ ์ •๋ณด์˜ˆ์š”.
9
- * @property {string} productId - ์ฃผ๋ฌธํ•  ์ƒํ’ˆ์˜ ID์˜ˆ์š”.
10
- */
11
- export interface IapCreateOneTimePurchaseOrderOptions {
12
- productId: string;
13
- }
6
+ type Sku =
7
+ | {
8
+ /**
9
+ * @deprecated `productId`๋Š” ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„์š”. ๋Œ€์‹  `sku`๋ฅผ ์‚ฌ์šฉํ•ด์š”.
10
+ */
11
+ productId: string;
12
+ sku?: string;
13
+ }
14
+ | {
15
+ productId?: never;
16
+ sku: string;
17
+ };
14
18
 
15
19
  /**
16
20
  * @public
@@ -35,15 +39,78 @@ export interface IapCreateOneTimePurchaseOrderResult {
35
39
  miniAppIconUrl: string | null;
36
40
  }
37
41
 
42
+ interface SuccessEvent {
43
+ type: 'success';
44
+ data: IapCreateOneTimePurchaseOrderResult;
45
+ }
46
+
47
+ interface PurchasedEvent {
48
+ type: 'purchased';
49
+ data: { orderId: string };
50
+ }
51
+
38
52
  /**
39
53
  * @public
40
54
  * @category ์ธ์•ฑ๊ฒฐ์ œ
41
- * @name iapCreateOneTimePurchaseOrder
55
+ * @name IapCreateOneTimePurchaseOrderOptions
56
+ * @property {Sku} options - ๊ฒฐ์ œํ•  ์ƒํ’ˆ์˜ ์ •๋ณด์˜ˆ์š”.
57
+ * @property {string} options.sku - ์ฃผ๋ฌธํ•  ์ƒํ’ˆ์˜ ๊ณ ์œ  ID์˜ˆ์š”.
58
+ * @property {(params: { orderId: string }) => boolean | Promise<boolean>} processProductGrant - ์ฃผ๋ฌธ์ด ๋งŒ๋“ค์–ด์ง„ ๋’ค ์‹ค์ œ๋กœ ์ƒํ’ˆ์„ ์ง€๊ธ‰ํ•  ๋•Œ ํ˜ธ์ถœํ•ด์š”. `orderId`๋ฅผ ๋ฐ›์•„์„œ ์ง€๊ธ‰ ์„ฑ๊ณต ์—ฌ๋ถ€๋ฅผ `true` ๋˜๋Š” `Promise<true>`๋กœ ๋ฐ˜ํ™˜ํ•ด์š”. ์ง€๊ธ‰์— ์‹คํŒจํ•˜๋ฉด `false`๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”.
59
+ * @property {(event: SuccessEvent) => void | Promise<void>} onEvent - ๊ฒฐ์ œ๊ฐ€ ์„ฑ๊ณตํ–ˆ์„ ๋•Œ ํ˜ธ์ถœํ•ด์š”. `event.type`์ด `'success'`์ด๊ณ , `event.data`์— `IapCreateOneTimePurchaseOrderResult`๊ฐ€ ๋“ค์–ด ์žˆ์–ด์š”.
60
+ * @property {(error: unknown) => void | Promise<void>} onError - ๊ฒฐ์ œ ๊ณผ์ •์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํ˜ธ์ถœํ•ด์š”. ์—๋Ÿฌ ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„์„œ ๋กœ๊น…ํ•˜๊ฑฐ๋‚˜ ๋ณต๊ตฌ ์ ˆ์ฐจ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด์š”.
61
+ */
62
+ export interface IapCreateOneTimePurchaseOrderOptions {
63
+ options: Sku & { processProductGrant: (params: { orderId: string }) => boolean | Promise<boolean> };
64
+ onEvent: (event: SuccessEvent) => void | Promise<void>;
65
+ onError: (error: unknown) => void | Promise<void>;
66
+ }
67
+
68
+ interface IapRequestOneTimePurchaseOptions {
69
+ options: Sku;
70
+ onEvent: (event: PurchasedEvent | SuccessEvent) => void | Promise<void>;
71
+ onError: (error: unknown) => void | Promise<void>;
72
+ }
73
+
74
+ export function iapCreateOneTimePurchaseOrder(params: Sku) {
75
+ const sku = (params.sku ?? params.productId) as string;
76
+ return AppsInTossModule.iapCreateOneTimePurchaseOrder({ productId: sku });
77
+ }
78
+
79
+ export function processProductGrant(params: { orderId: string; isProductGranted: boolean }) {
80
+ return AppsInTossModule.processProductGrant({ orderId: params.orderId, isProductGranted: params.isProductGranted });
81
+ }
82
+
83
+ export function requestOneTimePurchase(params: IapRequestOneTimePurchaseOptions) {
84
+ const { options, onEvent, onError } = params;
85
+ const sku = (options.sku ?? options.productId) as string;
86
+
87
+ const unregisterCallbacks = INTERNAL__appBridgeHandler.invokeAppBridgeMethod(
88
+ 'requestOneTimePurchase',
89
+ { sku },
90
+ {
91
+ onPurchased: (params: { orderId: string }) => {
92
+ onEvent({ type: 'purchased', data: params });
93
+ },
94
+ onSuccess: (result: IapCreateOneTimePurchaseOrderResult) => {
95
+ onEvent({ type: 'success', data: result });
96
+ },
97
+ onError: (error: any) => {
98
+ onError(error);
99
+ },
100
+ }
101
+ );
102
+
103
+ return unregisterCallbacks;
104
+ }
105
+
106
+ /**
107
+ * @public
108
+ * @category ์ธ์•ฑ๊ฒฐ์ œ
109
+ * @name createOneTimePurchaseOrder
42
110
  * @description
43
111
  * ํŠน์ • ์ธ์•ฑ๊ฒฐ์ œ ์ฃผ๋ฌธ์„œ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ด์š”. ์‚ฌ์šฉ์ž๊ฐ€ ์ƒํ’ˆ ๊ตฌ๋งค ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋Š” ์ƒํ™ฉ ๋“ฑ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ์‚ฌ์šฉ์ž์˜ ๊ฒฐ์ œ๋Š” ์ด๋™ํ•œ ํŽ˜์ด์ง€์—์„œ ์ง„ํ–‰๋ผ์š”. ๋งŒ์•ฝ ๊ฒฐ์ œ ์ค‘์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์—๋Ÿฌ ์œ ํ˜•์— ๋”ฐ๋ผ ์—๋Ÿฌ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ด์š”.
44
112
  * @param {IapCreateOneTimePurchaseOrderOptions} params - ์ธ์•ฑ๊ฒฐ์ œ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ•„์š”ํ•œ ์ •๋ณด์˜ˆ์š”.
45
- * @param {string} params.productId - ์ฃผ๋ฌธํ•  ์ƒํ’ˆ์˜ ID์˜ˆ์š”.
46
- * @returns {Promise<IapCreateOneTimePurchaseOrderResult | undefined>} ๊ฒฐ์ œ์— ์„ฑ๊ณตํ•˜๋ฉด ๊ฒฐ์ œ ๊ฒฐ๊ณผ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”. ์•ฑ ๋ฒ„์ „์ด ์ตœ์†Œ ์ง€์› ๋ฒ„์ „(์•ˆ๋“œ๋กœ์ด๋“œ 5.219.0, iOS 5.219.0)๋ณด๋‹ค ๋‚ฎ์œผ๋ฉด ์ธ์•ฑ๊ฒฐ์ œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์—†์–ด์„œ `undefined`๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”.
113
+ * @returns {() => void} ์•ฑ๋ธŒ๋ฆฟ์ง€ cleanup ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”. ์ธ์•ฑ๊ฒฐ์ œ ๊ธฐ๋Šฅ์ด ๋๋‚˜๋ฉด ๋ฐ˜๋“œ์‹œ ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด์ œํ•ด์•ผ ํ•ด์š”.
47
114
  *
48
115
  * @throw {code: "INVALID_PRODUCT_ID"} - ์œ ํšจํ•˜์ง€ ์•Š์€ ์ƒํ’ˆ ID์ด๊ฑฐ๋‚˜, ํ•ด๋‹น ์ƒํ’ˆ์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
49
116
  * @throw {code: "PAYMENT_PENDING"} - ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•œ ๊ฒฐ์ œ๊ฐ€ ์•„์ง ์Šน์ธ์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
@@ -55,6 +122,7 @@ export interface IapCreateOneTimePurchaseOrderResult {
55
122
  * @throw {code: "INTERNAL_ERROR"} - ์„œ๋ฒ„ ๋‚ด๋ถ€ ๋ฌธ์ œ๋กœ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
56
123
  * @throw {code: "KOREAN_ACCOUNT_ONLY"} - iOS ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉ์ž์˜ ๊ณ„์ •์ด ํ•œ๊ตญ ๊ณ„์ •์ด ์•„๋‹ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
57
124
  * @throw {code: "USER_CANCELED"} - ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒฐ์ œ๋ฅผ ์™„๋ฃŒํ•˜์ง€ ์•Š๊ณ  ์ฃผ๋ฌธ์„œ ํŽ˜์ด์ง€๋ฅผ ์ดํƒˆํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
125
+ * @throw {code: "PRODUCT_NOT_GRANTED_BY_PARTNER"} - ํŒŒํŠธ๋„ˆ์‚ฌ์˜ ์ƒํ’ˆ ์ง€๊ธ‰์ด ์‹คํŒจํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
58
126
  *
59
127
  * @example
60
128
  * ### ํŠน์ • ์ธ์•ฑ๊ฒฐ์ œ ์ฃผ๋ฌธ์„œ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๊ธฐ
@@ -62,38 +130,96 @@ export interface IapCreateOneTimePurchaseOrderResult {
62
130
  * ```tsx
63
131
  * import { IAP } from "@apps-in-toss/web-framework";
64
132
  * import { Button } from "@toss-design-system/react-native";
133
+ * import { useCallback } from "react";
65
134
  *
66
135
  * interface Props {
67
- * productId: string;
136
+ * sku: string;
68
137
  * }
69
138
  *
70
- * function IapCreateOneTimePurchaseOrderButton({ productId }: Props) {
71
- * async function handleClick() {
72
- * try {
73
- * await IAP.createOneTimePurchaseOrder({
74
- * productId,
75
- * });
76
- * console.error("์ธ์•ฑ๊ฒฐ์ œ์— ์„ฑ๊ณตํ–ˆ์–ด์š”");
77
- * } catch (error) {
78
- * console.error('์ธ์•ฑ๊ฒฐ์ œ์— ์‹คํŒจํ–ˆ์–ด์š”:', error);
79
- * }
80
- * }
139
+ * function IapCreateOneTimePurchaseOrderButton({ sku }: Props) {
140
+ * const handleClick = useCallback(async () => {
141
+ *
142
+ * const cleanup = await IAP.createOneTimePurchaseOrder({
143
+ * options: {
144
+ * sku,
145
+ * processProductGrant: ({ orderId }) => {
146
+ * // ์ƒํ’ˆ ์ง€๊ธ‰ ๋กœ์ง ์ž‘์„ฑ
147
+ * return true; // ์ƒํ’ˆ ์ง€๊ธ‰ ์—ฌ๋ถ€
148
+ * }
149
+ * },
150
+ * onEvent: (event) => {
151
+ * console.log(event);
152
+ * },
153
+ * onError: (error) => {
154
+ * console.error(error);
155
+ * },
156
+ * });
157
+ *
158
+ * return cleanup;
159
+ * }, []);
81
160
  *
82
161
  * return <Button onClick={handleClick}>๊ตฌ๋งคํ•˜๊ธฐ</Button>;
83
162
  * }
84
163
  * ```
85
164
  */
86
- async function createOneTimePurchaseOrder(params: IapCreateOneTimePurchaseOrderOptions) {
87
- const isSupported = isMinVersionSupported({
165
+ function createOneTimePurchaseOrder(params: IapCreateOneTimePurchaseOrderOptions) {
166
+ const isIAPSupported = isMinVersionSupported({
88
167
  android: '5.219.0',
89
168
  ios: '5.219.0',
90
169
  });
91
170
 
92
- if (!isSupported) {
93
- return;
171
+ if (!isIAPSupported) {
172
+ return noop;
173
+ }
174
+
175
+ const isProcessProductGrantSupported = isMinVersionSupported({
176
+ android: '5.230.0',
177
+ ios: '5.230.0',
178
+ });
179
+
180
+ const { options, onEvent, onError } = params;
181
+ const sku = (options.sku ?? options.productId) as string;
182
+
183
+ if (!isProcessProductGrantSupported) {
184
+ const v1 = () => {
185
+ AppsInTossModule.iapCreateOneTimePurchaseOrder({ productId: sku })
186
+ .then((response: IapCreateOneTimePurchaseOrderResult) => {
187
+ Promise.resolve(options.processProductGrant({ orderId: response.orderId }))
188
+ .then(() => {
189
+ onEvent({ type: 'success', data: response });
190
+ })
191
+ .catch((error: unknown) => {
192
+ onError(error);
193
+ });
194
+ })
195
+ .catch((error: unknown) => {
196
+ onError(error);
197
+ });
198
+
199
+ return noop;
200
+ };
201
+
202
+ return v1();
94
203
  }
95
204
 
96
- return AppsInTossModule.iapCreateOneTimePurchaseOrder(params);
205
+ const unregisterCallbacks = INTERNAL__appBridgeHandler.invokeAppBridgeMethod(
206
+ 'requestOneTimePurchase',
207
+ { sku },
208
+ {
209
+ onPurchased: async (params: { orderId: string }) => {
210
+ const isProductGranted = await options.processProductGrant(params);
211
+ await AppsInTossModule.processProductGrant({ orderId: params.orderId, isProductGranted });
212
+ },
213
+ onSuccess: (result: IapCreateOneTimePurchaseOrderResult) => {
214
+ onEvent({ type: 'success', data: result });
215
+ },
216
+ onError: (error: unknown) => {
217
+ onError(error);
218
+ },
219
+ }
220
+ );
221
+
222
+ return unregisterCallbacks;
97
223
  }
98
224
 
99
225
  /**
@@ -118,7 +244,7 @@ export interface IapProductListItem {
118
244
  /**
119
245
  * @public
120
246
  * @category ์ธ์•ฑ๊ฒฐ์ œ
121
- * @name iapGetProductItemList
247
+ * @name getProductItemList
122
248
  * @description ์ธ์•ฑ๊ฒฐ์ œ๋กœ ๊ตฌ๋งคํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํ’ˆ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์™€์š”. ์ƒํ’ˆ ๋ชฉ๋ก ํ™”๋ฉด์— ์ง„์ž…ํ•  ๋•Œ ํ˜ธ์ถœํ•ด์š”.
123
249
  * @returns {Promise<{ products: IapProductListItem[] } | undefined>} ์ƒํ’ˆ ๋ชฉ๋ก์„ ํฌํ•จํ•œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”. ์•ฑ ๋ฒ„์ „์ด ์ตœ์†Œ ์ง€์› ๋ฒ„์ „(์•ˆ๋“œ๋กœ์ด๋“œ 5.219.0, iOS 5.219.0)๋ณด๋‹ค ๋‚ฎ์œผ๋ฉด `undefined`๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”.
124
250
  *
@@ -1,10 +0,0 @@
1
- import { GraniteEventDefinition } from '@granite-js/react-native';
2
-
3
- export class BackButtonClickHandleEvent extends GraniteEventDefinition<undefined, undefined> {
4
- name = 'backButtonClickEvent' as const;
5
-
6
- remove() {}
7
-
8
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
9
- listener(_: undefined) {}
10
- }
@@ -1,10 +0,0 @@
1
- import { GraniteEventDefinition } from '@granite-js/react-native';
2
-
3
- export class HomeIconButtonClickHandleEvent extends GraniteEventDefinition<undefined, undefined> {
4
- name = 'homeIconButtonClickEvent' as const;
5
-
6
- remove() {}
7
-
8
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
9
- listener(_: undefined) {}
10
- }