@apps-in-toss/framework 0.0.28 → 0.0.30

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
@@ -35,6 +35,8 @@ __export(src_exports, {
35
35
  Analytics: () => Analytics2,
36
36
  AppsInToss: () => AppsInToss,
37
37
  GoogleAdMob: () => GoogleAdMob,
38
+ IAP: () => IAP,
39
+ INTERNAL__onVisibilityChangedByTransparentServiceWeb: () => INTERNAL__onVisibilityChangedByTransparentServiceWeb,
38
40
  Storage: () => Storage,
39
41
  TossPay: () => TossPay,
40
42
  WebView: () => WebView,
@@ -52,9 +54,11 @@ __export(src_exports, {
52
54
  getTossShareLink: () => getTossShareLink,
53
55
  isMinVersionSupported: () => isMinVersionSupported,
54
56
  openCamera: () => openCamera,
57
+ saveBase64Data: () => saveBase64Data,
55
58
  setClipboardText: () => setClipboardText,
56
59
  setDeviceOrientation: () => setDeviceOrientation,
57
60
  startUpdateLocation: () => startUpdateLocation,
61
+ useCreateUserAgent: () => useCreateUserAgent,
58
62
  useGeolocation: () => useGeolocation
59
63
  });
60
64
  module.exports = __toCommonJS(src_exports);
@@ -63,7 +67,7 @@ var import_analytics2 = require("@apps-in-toss/analytics");
63
67
  // src/core/registerApp.tsx
64
68
  var import_analytics = require("@apps-in-toss/analytics");
65
69
  var import_react_native6 = require("@toss-design-system/react-native");
66
- var import_react_native_bedrock7 = require("react-native-bedrock");
70
+ var import_react_native_bedrock8 = require("react-native-bedrock");
67
71
 
68
72
  // src/core/components/AppEvent.tsx
69
73
  var import_react2 = require("react");
@@ -261,7 +265,7 @@ var import_react_native5 = require("@toss-design-system/react-native");
261
265
  var import_react3 = require("react");
262
266
 
263
267
  // src/native-event-emitter/appsInTossEvent.ts
264
- var import_react_native_bedrock6 = require("react-native-bedrock");
268
+ var import_react_native_bedrock7 = require("react-native-bedrock");
265
269
 
266
270
  // src/native-event-emitter/event-plugins/EntryMessageExitedEvent.ts
267
271
  var import_react_native_bedrock3 = require("react-native-bedrock");
@@ -420,11 +424,39 @@ var AppBridgeCallbackEvent = class _AppBridgeCallbackEvent extends import_react_
420
424
  }
421
425
  };
422
426
 
427
+ // src/native-event-emitter/internal/VisibilityChangedByTransparentServiceWebEvent.ts
428
+ var import_react_native_bedrock6 = require("react-native-bedrock");
429
+ var VisibilityChangedByTransparentServiceWebEvent = class extends import_react_native_bedrock6.BedrockEventDefinition {
430
+ name = "onVisibilityChangedByTransparentServiceWeb";
431
+ subscription = null;
432
+ remove() {
433
+ this.subscription?.remove();
434
+ this.subscription = null;
435
+ }
436
+ listener(options, onEvent, onError) {
437
+ const subscription = nativeEventEmitter.addListener("visibilityChangedByTransparentServiceWeb", (params) => {
438
+ if (this.isVisibilityChangedByTransparentServiceWebResult(params)) {
439
+ if (params.callbackId === options.callbackId) {
440
+ onEvent(params.isVisible);
441
+ }
442
+ } else {
443
+ onError(new Error("Invalid visibility changed by transparent service web result"));
444
+ }
445
+ });
446
+ this.subscription = subscription;
447
+ }
448
+ isVisibilityChangedByTransparentServiceWebResult(params) {
449
+ return typeof params === "object" && typeof params.callbackId === "string" && typeof params.isVisible === "boolean";
450
+ }
451
+ };
452
+
423
453
  // src/native-event-emitter/appsInTossEvent.ts
424
- var appsInTossEvent = new import_react_native_bedrock6.BedrockEvent([
425
- new AppBridgeCallbackEvent(),
454
+ var appsInTossEvent = new import_react_native_bedrock7.BedrockEvent([
426
455
  new UpdateLocationEvent(),
427
- new EntryMessageExitedEvent()
456
+ new EntryMessageExitedEvent(),
457
+ // Internal events
458
+ new AppBridgeCallbackEvent(),
459
+ new VisibilityChangedByTransparentServiceWebEvent()
428
460
  ]);
429
461
 
430
462
  // src/core/utils/getAppsInTossGlobals.ts
@@ -472,6 +504,7 @@ __export(async_bridges_exports, {
472
504
  getCurrentLocation: () => getCurrentLocation,
473
505
  getTossShareLink: () => getTossShareLink,
474
506
  openCamera: () => openCamera,
507
+ saveBase64Data: () => saveBase64Data,
475
508
  setClipboardText: () => setClipboardText,
476
509
  setDeviceOrientation: () => setDeviceOrientation
477
510
  });
@@ -612,6 +645,19 @@ async function setDeviceOrientation(options) {
612
645
  return AppsInTossModule.setDeviceOrientation(options);
613
646
  }
614
647
 
648
+ // src/native-modules/saveBase64Data.ts
649
+ async function saveBase64Data(params) {
650
+ const isSupported = isMinVersionSupported({
651
+ android: "5.218.0",
652
+ ios: "5.216.0"
653
+ });
654
+ if (!isSupported) {
655
+ console.warn("saveBase64Data is not supported in this app version");
656
+ return;
657
+ }
658
+ await AppsInTossModule.saveBase64Data(params);
659
+ }
660
+
615
661
  // src/core/registerApp.tsx
616
662
  var import_jsx_runtime = require("react/jsx-runtime");
617
663
  function AppsInTossContainer(Container, { children, ...initialProps }) {
@@ -630,7 +676,7 @@ function registerApp(container, { context, analytics }) {
630
676
  logger: (params) => void eventLog(params),
631
677
  debug: analytics?.debug ?? __DEV__
632
678
  });
633
- return import_react_native_bedrock7.Bedrock.registerApp(AppsInTossContainer.bind(null, container), {
679
+ return import_react_native_bedrock8.Bedrock.registerApp(AppsInTossContainer.bind(null, container), {
634
680
  appName: getAppName(),
635
681
  context,
636
682
  router: {
@@ -753,7 +799,6 @@ var ENVIRONMENT = getOperationalEnvironment();
753
799
  function createIsSupported() {
754
800
  return () => {
755
801
  if (ENVIRONMENT !== "toss") {
756
- console.warn("Google AdMob is not supported in the current environment");
757
802
  return false;
758
803
  }
759
804
  return isMinVersionSupported({
@@ -800,6 +845,32 @@ var Storage = {
800
845
  clearItems
801
846
  };
802
847
 
848
+ // src/native-modules/iap.ts
849
+ async function createOneTimePurchaseOrder(params) {
850
+ const isSupported = isMinVersionSupported({
851
+ android: "5.219.0",
852
+ ios: "5.219.0"
853
+ });
854
+ if (!isSupported) {
855
+ return;
856
+ }
857
+ return AppsInTossModule.iapCreateOneTimePurchaseOrder(params);
858
+ }
859
+ async function getProductItemList() {
860
+ const isSupported = isMinVersionSupported({
861
+ android: "5.219.0",
862
+ ios: "5.219.0"
863
+ });
864
+ if (!isSupported) {
865
+ return;
866
+ }
867
+ return AppsInTossModule.iapGetProductItemList({});
868
+ }
869
+ var IAP = {
870
+ createOneTimePurchaseOrder,
871
+ getProductItemList
872
+ };
873
+
803
874
  // src/native-modules/index.ts
804
875
  var TossPay = {
805
876
  checkoutPayment
@@ -812,10 +883,11 @@ var GoogleAdMob = {
812
883
  };
813
884
 
814
885
  // src/components/WebView.tsx
815
- var import_react_native14 = require("@toss-design-system/react-native");
886
+ var import_react_native15 = require("@toss-design-system/react-native");
816
887
  var import_private = require("@toss-design-system/react-native/private");
817
- var import_react6 = require("react");
818
- var import_react_native_bedrock10 = require("react-native-bedrock");
888
+ var import_react7 = require("react");
889
+ var import_react_native16 = require("react-native");
890
+ var import_react_native_bedrock13 = require("react-native-bedrock");
819
891
  var bedrockAsyncBridges = __toESM(require("react-native-bedrock/async-bridges"), 1);
820
892
  var bedrockConstantBridges = __toESM(require("react-native-bedrock/constant-bridges"), 1);
821
893
 
@@ -825,7 +897,7 @@ var import_react_native12 = require("@toss-design-system/react-native");
825
897
  var import_es_hangul = require("es-hangul");
826
898
  var import_react4 = require("react");
827
899
  var import_react_native13 = require("react-native");
828
- var import_react_native_bedrock8 = require("react-native-bedrock");
900
+ var import_react_native_bedrock9 = require("react-native-bedrock");
829
901
 
830
902
  // src/components/GameWebViewNavigationBar/GameNavigationBar.tsx
831
903
  var import_react_native_svg = require("@react-native-bedrock/native/react-native-svg");
@@ -936,14 +1008,14 @@ var GameWebView = (0, import_react4.forwardRef)(function GameWebView2(props, ref
936
1008
  closeOnDimmerClick: true
937
1009
  });
938
1010
  if (isConfirmed) {
939
- (0, import_react_native_bedrock8.closeView)();
1011
+ (0, import_react_native_bedrock9.closeView)();
940
1012
  }
941
1013
  }, [brandDisplayName, openConfirm]);
942
1014
  (0, import_react4.useEffect)(() => {
943
1015
  if (import_react_native13.Platform.OS === "ios") {
944
- (0, import_react_native_bedrock8.setIosSwipeGestureEnabled)({ isEnabled: false });
1016
+ (0, import_react_native_bedrock9.setIosSwipeGestureEnabled)({ isEnabled: false });
945
1017
  return () => {
946
- (0, import_react_native_bedrock8.setIosSwipeGestureEnabled)({ isEnabled: true });
1018
+ (0, import_react_native_bedrock9.setIosSwipeGestureEnabled)({ isEnabled: true });
947
1019
  };
948
1020
  }
949
1021
  return;
@@ -1105,8 +1177,63 @@ __export(event_bridges_exports, {
1105
1177
  startUpdateLocation: () => startUpdateLocation
1106
1178
  });
1107
1179
 
1180
+ // src/hooks/useCreateUserAgent.ts
1181
+ var import_react_native14 = require("react-native");
1182
+ var import_react_native_bedrock10 = require("react-native-bedrock");
1183
+ function useCreateUserAgent({
1184
+ batteryModePreference,
1185
+ colorPreference,
1186
+ fontA11y,
1187
+ locale,
1188
+ navbarPreference,
1189
+ pureSafeArea,
1190
+ safeArea,
1191
+ safeAreaBottomTransparency
1192
+ }) {
1193
+ const platform = (0, import_react_native_bedrock10.getPlatformOS)();
1194
+ const appVersion = getTossAppVersion();
1195
+ const fontScale = (0, import_react_native14.useWindowDimensions)().fontScale;
1196
+ const platformString = platform === "ios" ? "iPhone" : "Android";
1197
+ return [
1198
+ `TossApp/${appVersion}`,
1199
+ batteryModePreference && `TossBatteryModePreference/${batteryModePreference}`,
1200
+ colorPreference && `TossColorPreference/${colorPreference}`,
1201
+ fontA11y && `TossFontAccessibility/${fontA11y}`,
1202
+ fontScale && `TossFontScale/${fontScale}`,
1203
+ locale && `TossLocale/${locale}`,
1204
+ navbarPreference && `TossNavbarPreference/${navbarPreference}`,
1205
+ pureSafeArea && `TossPureSafeArea/${pureSafeArea}`,
1206
+ safeArea && `TossSafeArea/${safeArea}`,
1207
+ safeAreaBottomTransparency && `TossSafeAreaBottomTransparency/${safeAreaBottomTransparency}`,
1208
+ platformString
1209
+ ].filter(Boolean).join(" ");
1210
+ }
1211
+
1212
+ // src/hooks/useGeolocation.ts
1213
+ var import_react6 = require("react");
1214
+ var import_react_native_bedrock11 = require("react-native-bedrock");
1215
+ function useGeolocation({ accuracy, distanceInterval, timeInterval }) {
1216
+ const isVisible = (0, import_react_native_bedrock11.useVisibility)();
1217
+ const [location, setLocation] = (0, import_react6.useState)(null);
1218
+ (0, import_react6.useEffect)(() => {
1219
+ if (!isVisible) {
1220
+ return;
1221
+ }
1222
+ return startUpdateLocation({
1223
+ options: {
1224
+ accuracy,
1225
+ distanceInterval,
1226
+ timeInterval
1227
+ },
1228
+ onEvent: setLocation,
1229
+ onError: console.error
1230
+ });
1231
+ }, [accuracy, distanceInterval, timeInterval, isVisible]);
1232
+ return location;
1233
+ }
1234
+
1108
1235
  // src/utils/log.ts
1109
- var import_react_native_bedrock9 = require("react-native-bedrock");
1236
+ var import_react_native_bedrock12 = require("react-native-bedrock");
1110
1237
 
1111
1238
  // src/utils/extractDateFromUUIDv7.ts
1112
1239
  var extractDateFromUUIDv7 = (uuid) => {
@@ -1132,7 +1259,7 @@ var getGroupId = (url) => {
1132
1259
  };
1133
1260
  var getReferrer = () => {
1134
1261
  try {
1135
- const referrer = new URL((0, import_react_native_bedrock9.getSchemeUri)());
1262
+ const referrer = new URL((0, import_react_native_bedrock12.getSchemeUri)());
1136
1263
  return referrer.searchParams.get("referrer");
1137
1264
  } catch {
1138
1265
  return "";
@@ -1159,13 +1286,13 @@ var appsInTossGlobals = getAppsInTossGlobals();
1159
1286
  var operationalEnvironment = getOperationalEnvironment();
1160
1287
  var TYPES = ["partner", "external", "game"];
1161
1288
  var WEBVIEW_TYPES = {
1162
- partner: import_react_native14.PartnerWebViewScreen,
1163
- external: import_react_native14.ExternalWebViewScreen,
1289
+ partner: import_react_native15.PartnerWebViewScreen,
1290
+ external: import_react_native15.ExternalWebViewScreen,
1164
1291
  game: GameWebView
1165
1292
  };
1166
1293
  function mergeSchemeQueryParamsInto(url) {
1167
1294
  const baseUrl = new URL(url);
1168
- const schemeUrl = new URL((0, import_react_native_bedrock10.getSchemeUri)());
1295
+ const schemeUrl = new URL((0, import_react_native_bedrock13.getSchemeUri)());
1169
1296
  baseUrl.pathname = schemeUrl.pathname;
1170
1297
  for (const [key, value] of schemeUrl.searchParams.entries()) {
1171
1298
  baseUrl.searchParams.set(key, value);
@@ -1189,10 +1316,11 @@ function WebView({ type, local, onMessage, ...props }) {
1189
1316
  if (!TYPES.includes(type)) {
1190
1317
  throw new Error(`Invalid WebView type: '${type}'`);
1191
1318
  }
1192
- const bedrockEvent = (0, import_react_native_bedrock10.useBedrockEvent)();
1193
- const uri = (0, import_react6.useMemo)(() => getWebViewUri(local), [local]);
1319
+ const bedrockEvent = (0, import_react_native_bedrock13.useBedrockEvent)();
1320
+ const uri = (0, import_react7.useMemo)(() => getWebViewUri(local), [local]);
1194
1321
  const top = (0, import_private.useSafeAreaTop)();
1195
1322
  const bottom = (0, import_private.useSafeAreaBottom)();
1323
+ const global2 = getAppsInTossGlobals();
1196
1324
  const handler = useBridgeHandler({
1197
1325
  onMessage,
1198
1326
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -1214,6 +1342,7 @@ function WebView({ type, local, onMessage, ...props }) {
1214
1342
  ...constant_bridges_exports,
1215
1343
  getSafeAreaTop: () => top,
1216
1344
  getSafeAreaBottom: () => bottom,
1345
+ ...Object.fromEntries(Object.entries(global2).map(([key, value]) => [key, () => value])),
1217
1346
  /** AdMob */
1218
1347
  loadAdMobInterstitialAd_isSupported: GoogleAdMob.loadAdMobInterstitialAd.isSupported,
1219
1348
  showAdMobInterstitialAd_isSupported: GoogleAdMob.showAdMobInterstitialAd.isSupported,
@@ -1231,10 +1360,13 @@ function WebView({ type, local, onMessage, ...props }) {
1231
1360
  getStorageItem: Storage.getItem,
1232
1361
  setStorageItem: Storage.setItem,
1233
1362
  removeStorageItem: Storage.removeItem,
1234
- clearItems: Storage.clearItems
1363
+ clearItems: Storage.clearItems,
1364
+ /** IAP */
1365
+ iapCreateOneTimePurchaseOrder: IAP.createOneTimePurchaseOrder,
1366
+ iapGetProductItemList: IAP.getProductItemList
1235
1367
  }
1236
1368
  });
1237
- const baseProps = (0, import_react6.useMemo)(() => {
1369
+ const baseProps = (0, import_react7.useMemo)(() => {
1238
1370
  switch (type) {
1239
1371
  case "partner": {
1240
1372
  const headerOnlyProp = {
@@ -1265,18 +1397,28 @@ function WebView({ type, local, onMessage, ...props }) {
1265
1397
  }, [type, props]);
1266
1398
  const BaseWebView = WEBVIEW_TYPES[type];
1267
1399
  const webViewDebuggingEnabled = operationalEnvironment === "sandbox";
1268
- const handleNavigationStateChange = (0, import_react6.useCallback)((event) => {
1400
+ const handleNavigationStateChange = (0, import_react7.useCallback)((event) => {
1269
1401
  if (event.url) {
1270
1402
  trackScreen(event.url);
1271
1403
  }
1272
1404
  }, []);
1405
+ const userAgent = useCreateUserAgent({
1406
+ colorPreference: "light"
1407
+ });
1273
1408
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1274
1409
  BaseWebView,
1275
1410
  {
1276
1411
  ref: handler.ref,
1277
1412
  ...props,
1278
1413
  ...baseProps,
1279
- source: { uri },
1414
+ source: {
1415
+ uri,
1416
+ // NOTE: https://github.com/react-native-webview/react-native-webview/pull/3133
1417
+ headers: {
1418
+ "User-Agent": userAgent
1419
+ }
1420
+ },
1421
+ userAgent: import_react_native16.Platform.OS === "ios" ? userAgent : void 0,
1280
1422
  sharedCookiesEnabled: true,
1281
1423
  webviewDebuggingEnabled: webViewDebuggingEnabled,
1282
1424
  thirdPartyCookiesEnabled: true,
@@ -1294,29 +1436,6 @@ function ensureValue(value, name) {
1294
1436
  return value;
1295
1437
  }
1296
1438
 
1297
- // src/hooks/useGeolocation.ts
1298
- var import_react7 = require("react");
1299
- var import_react_native_bedrock11 = require("react-native-bedrock");
1300
- function useGeolocation({ accuracy, distanceInterval, timeInterval }) {
1301
- const isVisible = (0, import_react_native_bedrock11.useVisibility)();
1302
- const [location, setLocation] = (0, import_react7.useState)(null);
1303
- (0, import_react7.useEffect)(() => {
1304
- if (!isVisible) {
1305
- return;
1306
- }
1307
- return startUpdateLocation({
1308
- options: {
1309
- accuracy,
1310
- distanceInterval,
1311
- timeInterval
1312
- },
1313
- onEvent: setLocation,
1314
- onError: console.error
1315
- });
1316
- }, [accuracy, distanceInterval, timeInterval, isVisible]);
1317
- return location;
1318
- }
1319
-
1320
1439
  // src/types.ts
1321
1440
  var Accuracy2 = /* @__PURE__ */ ((Accuracy3) => {
1322
1441
  Accuracy3[Accuracy3["Lowest"] = 1] = "Lowest";
@@ -1328,6 +1447,14 @@ var Accuracy2 = /* @__PURE__ */ ((Accuracy3) => {
1328
1447
  return Accuracy3;
1329
1448
  })(Accuracy2 || {});
1330
1449
 
1450
+ // src/native-event-emitter/internal/onVisibilityChangedByTransparentServiceWeb.ts
1451
+ function onVisibilityChangedByTransparentServiceWeb(eventParams) {
1452
+ return appsInTossEvent.addEventListener("onVisibilityChangedByTransparentServiceWeb", eventParams);
1453
+ }
1454
+
1455
+ // src/private.ts
1456
+ var INTERNAL__onVisibilityChangedByTransparentServiceWeb = onVisibilityChangedByTransparentServiceWeb;
1457
+
1331
1458
  // src/index.ts
1332
1459
  __reExport(src_exports, require("@apps-in-toss/analytics"), module.exports);
1333
1460
  var Analytics2 = {
@@ -1342,6 +1469,8 @@ var Analytics2 = {
1342
1469
  Analytics,
1343
1470
  AppsInToss,
1344
1471
  GoogleAdMob,
1472
+ IAP,
1473
+ INTERNAL__onVisibilityChangedByTransparentServiceWeb,
1345
1474
  Storage,
1346
1475
  TossPay,
1347
1476
  WebView,
@@ -1359,9 +1488,11 @@ var Analytics2 = {
1359
1488
  getTossShareLink,
1360
1489
  isMinVersionSupported,
1361
1490
  openCamera,
1491
+ saveBase64Data,
1362
1492
  setClipboardText,
1363
1493
  setDeviceOrientation,
1364
1494
  startUpdateLocation,
1495
+ useCreateUserAgent,
1365
1496
  useGeolocation,
1366
1497
  ...require("@apps-in-toss/analytics")
1367
1498
  });
package/dist/index.d.cts CHANGED
@@ -1716,6 +1716,204 @@ declare function setDeviceOrientation(options: {
1716
1716
  type: 'portrait' | 'landscape';
1717
1717
  }): Promise<void>;
1718
1718
 
1719
+ interface SaveBase64DataParams {
1720
+ data: string;
1721
+ fileName: string;
1722
+ mimeType: string;
1723
+ }
1724
+ /**
1725
+ * @public
1726
+ * @category 데이터
1727
+ * @name saveBase64Data
1728
+ * @description 문자열로 인코딩된 Base64 데이터를 지정한 파일 이름과 MIME 타입으로 사용자 기기에 저장해요. 이미지, 텍스트, PDF 등 다양한 형식의 데이터를 저장할 수 있어요.
1729
+ * @param {SaveBase64DataParams} params - 저장할 데이터와 파일 정보를 담은 객체예요.
1730
+ * @param {string} params.data - Base64 형식으로 인코딩된 데이터 문자열이에요.
1731
+ * @param {string} params.fileName - 저장할 파일 이름이에요. 확장자도 같이 붙여줘야해요. 예를 들어, 'example.png'로 저장할 수 있어요.
1732
+ * @param {string} params.mimeType - 저장할 파일의 MIME 타입이에요. 예를 들어 'image/png' 로 지정하면 이미지, 'application/pdf'는 PDF 파일이에요. 자세한 내용은 [MIME 문서](https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/MIME_types)를 참고해주세요.
1733
+ *
1734
+ * @example
1735
+ * ### Base64 이미지 데이터를 사용자 기기에 저장하기
1736
+ *
1737
+ * ```tsx
1738
+ * import { Button } from 'react-native';
1739
+ * import { saveBase64Data } from '@apps-in-toss/framework';
1740
+ *
1741
+ * // '저장' 버튼을 누르면 이미지가 사용자 기기에 저장돼요.
1742
+ * function SaveButton() {
1743
+ * const handleSave = async () => {
1744
+ * try {
1745
+ * await saveBase64Data({
1746
+ * data: 'iVBORw0KGgo...',
1747
+ * fileName: 'some-photo.png',
1748
+ * mimeType: 'image/png',
1749
+ * });
1750
+ * } catch (error) {
1751
+ * console.error('데이터 저장에 실패했어요:', error);
1752
+ * }
1753
+ * };
1754
+ *
1755
+ * return <Button title="저장" onPress={handleSave} />;
1756
+ * }
1757
+ * ```
1758
+ */
1759
+ declare function saveBase64Data(params: SaveBase64DataParams): Promise<void>;
1760
+
1761
+ /**
1762
+ * @public
1763
+ * @category 인앱결제
1764
+ * @name IapCreateOneTimePurchaseOrderOptions
1765
+ * @description 인앱결제 1건을 요청할 때 필요한 정보예요.
1766
+ * @property {string} productId - 주문할 상품의 ID예요.
1767
+ */
1768
+ interface IapCreateOneTimePurchaseOrderOptions {
1769
+ productId: string;
1770
+ }
1771
+ /**
1772
+ * @public
1773
+ * @category 인앱결제
1774
+ * @name IapCreateOneTimePurchaseOrderResult
1775
+ * @description 인앱결제 1건이 완료되면 결제 세부 정보와 상품 정보를 담아 반환해요. 반환된 정보로 결제한 상품의 정보를 화면에 표시할 수 있어요.
1776
+ * @property {string | null} miniAppIconUrl - 미니앱 아이콘 이미지의 URL이에요. 아이콘은 앱인토스 콘솔에서 설정한 이미지예요. 콘솔에서 아이콘을 등록하지 않았다면 `null`로 반환돼요.
1777
+ * @property {string} displayName - 화면에 표시할 상품 이름이에요.
1778
+ * @property {string} displayAmount - 통화 단위가 포함된 가격 정보예요. 예를 들어 `1,000원`으로 가격과 통화가 함께 표시돼요.
1779
+ * @property {number} amount - 상품 가격 숫자 값이에요. 화폐 단위와 쉼표를 제외한 순수 숫자예요. 예를 들어 `1000`으로 표시돼요.
1780
+ * @property {string} currency - [ISO 4217 표준](https://ko.wikipedia.org/wiki/ISO_4217)에 따른 상품 가격 통화 단위예요. 예를 들어 원화는 `KRW`, 달러는 `USD`로 표시돼요.
1781
+ * @property {number} fraction - 가격을 표시할 때 소수점 아래 몇 자리까지 보여줄지 정하는 값이에요. 예를 들어 달러는 소수점 둘째 자리까지 보여줘서 `2`, 원화는 소수점이 필요 없어서 `0`이에요
1782
+ */
1783
+ interface IapCreateOneTimePurchaseOrderResult {
1784
+ miniAppIconUrl: string | null;
1785
+ displayName: string;
1786
+ displayAmount: string;
1787
+ amount: number;
1788
+ currency: string;
1789
+ fraction: number;
1790
+ }
1791
+ /**
1792
+ * @public
1793
+ * @category 인앱결제
1794
+ * @name iapCreateOneTimePurchaseOrder
1795
+ * @description
1796
+ * 특정 인앱결제 주문서 페이지로 이동해요. 사용자가 상품 구매 버튼을 누르는 상황 등에 사용할 수 있어요. 사용자의 결제는 이동한 페이지에서 진행돼요. 만약 결제 중에 에러가 발생하면 에러 유형에 따라 에러 페이지로 이동해요.
1797
+ * @param {IapCreateOneTimePurchaseOrderOptions} params - 인앱결제를 생성할 때 필요한 정보예요.
1798
+ * @param {string} params.productId - 주문할 상품의 ID예요.
1799
+ * @returns {Promise<IapCreateOneTimePurchaseOrderResult | undefined>} 결제에 성공하면 결제 결과 객체를 반환해요. 앱 버전이 최소 지원 버전(안드로이드 5.219.0, iOS 5.219.0)보다 낮으면 인앱결제를 실행할 수 없어서 `undefined`를 반환해요.
1800
+ *
1801
+ * @throw {code: "INVALID_PRODUCT_ID"} - 유효하지 않은 상품 ID이거나, 해당 상품이 존재하지 않을 때 발생해요.
1802
+ * @throw {code: "PAYMENT_PENDING"} - 사용자가 요청한 결제가 아직 승인을 기다리고 있을 때 발생해요.
1803
+ * @throw {code: "NETWORK_ERROR"} - 서버 내부 문제로 요청을 처리할 수 없을 때 발생해요.
1804
+ * @throw {code: "INVALID_USER_ENVIRONMENT"} - 특정 기기, 계정 또는 설정 환경에서 구매할 수 없는 상품일 때 발생해요.
1805
+ * @throw {code: "ITEM_ALREADY_OWNED"} - 사용자가 이미 구매한 상품을 다시 구매하려고 할 때 발생해요.
1806
+ * @throw {code: "APP_MARKET_VERIFICATION_FAILED"} - 사용자가 결제를 완료했지만, 앱스토어에서 사용자 정보 검증에 실패했을 때 발생해요. 사용자가 앱스토어에 문의해서 환불을 요청해야해요.
1807
+ * @throw {code: "TOSS_SERVER_VERIFICATION_FAILED"} - 사용자가 결제를 완료했지만, 서버 전송에 실패해서 결제 정보를 저장할 수 없을 때 발생해요.
1808
+ * @throw {code: "INTERNAL_ERROR"} - 서버 내부 문제로 요청을 처리할 수 없을 때 발생해요.
1809
+ * @throw {code: "KOREAN_ACCOUNT_ONLY"} - iOS 환경에서 사용자의 계정이 한국 계정이 아닐 때 발생해요.
1810
+ * @throw {code: "USER_CANCELED"} - 사용자가 결제를 완료하지 않고 주문서 페이지를 이탈했을 때 발생해요.
1811
+ *
1812
+ * @example
1813
+ * ### 특정 인앱결제 주문서 페이지로 이동하기
1814
+ *
1815
+ * ```tsx
1816
+ * import { Button } from 'react-native';
1817
+ * import { IAP } from '@apps-in-toss/framework';
1818
+ *
1819
+ * interface Props {
1820
+ * productId: string;
1821
+ * }
1822
+ *
1823
+ * function IapCreateOneTimePurchaseOrderButton({ productId }: Props) {
1824
+ * const handleClick = async () => {
1825
+ * try {
1826
+ * await IAP.createOneTimePurchaseOrder({
1827
+ * productId,
1828
+ * });
1829
+ * } catch (error) {
1830
+ * console.error('인앱결제에 실패했어요:', error);
1831
+ * }
1832
+ * };
1833
+ *
1834
+ * return <Button title="구매하기" onPress={handleClick} />;
1835
+ * }
1836
+ * ```
1837
+ */
1838
+ declare function createOneTimePurchaseOrder(params: IapCreateOneTimePurchaseOrderOptions): Promise<IapCreateOneTimePurchaseOrderResult | undefined>;
1839
+ /**
1840
+ * @public
1841
+ * @category 인앱결제
1842
+ * @name IapProductListItem
1843
+ * @description 인앱결제로 구매할 수 있는 상품 하나의 정보를 담은 객체예요. 상품 목록을 화면에 표시할 때 사용해요.
1844
+ * @property {string} sku - 상품의 고유 ID예요. [인앱결제 주문서 페이지로 이동할때](/bedrock/reference/framework/인앱결제/createOneTimePurchaseOrder.html) 사용하는 `productId`와 동일한 값이에요.
1845
+ * @property {string} displayName - 화면에 표시할 상품 이름이에요. 상품 이름은 앱인토스 콘솔에서 설정한 값이에요.
1846
+ * @property {string} displayAmount - 통화 단위가 포함된 가격 정보예요. 예를 들어 `1,000원`으로 가격과 통화가 함께 표시돼요.
1847
+ * @property {string} iconUrl - 상품 아이콘 이미지의 URL이에요. 아이콘은 앱인토스 콘솔에서 설정한 이미지예요.
1848
+ * @property {string} description - 상품에 대한 설명이에요. 설명은 앱인토스 콘솔에서 설정한 값이에요.
1849
+ */
1850
+ interface IapProductListItem {
1851
+ sku: string;
1852
+ displayAmount: string;
1853
+ displayName: string;
1854
+ iconUrl: string;
1855
+ description: string;
1856
+ }
1857
+ /**
1858
+ * @public
1859
+ * @category 인앱결제
1860
+ * @name iapGetProductItemList
1861
+ * @description 인앱결제로 구매할 수 있는 상품 목록을 가져와요. 상품 목록 화면에 진입할 때 호출해요.
1862
+ * @returns {Promise<{ products: IapProductListItem[] } | undefined>} 상품 목록을 포함한 객체를 반환해요. 앱 버전이 최소 지원 버전(안드로이드 5.219.0, iOS 5.219.0)보다 낮으면 `undefined`를 반환해요.
1863
+ *
1864
+ * @example
1865
+ * ### 구매 가능한 인앱결제 상품목록 가져오기
1866
+ *
1867
+ * ```tsx
1868
+ * import { useEffect, useState } from 'react';
1869
+ * import { List, ListRow, Txt } from '@toss-design-system/react-native';
1870
+ * import { IAP } from '@apps-in-toss/framework';
1871
+ *
1872
+ * function IapGetProductItemList() {
1873
+ * const [products, setProducts] = useState<IapProductListItem[]>([]);
1874
+ *
1875
+ * useEffect(() => {
1876
+ * async function fetchProducts() {
1877
+ * try {
1878
+ * const response = await IAP.getProductItemList();
1879
+ * setProducts(response?.products ?? []);
1880
+ * } catch (error) {
1881
+ * console.error('상품 목록을 가져오는 데 실패했어요:', error);
1882
+ * }
1883
+ * }
1884
+ *
1885
+ * fetchProducts();
1886
+ * }, []);
1887
+ *
1888
+ * return (
1889
+ * <List>
1890
+ * {products.map((product) => (
1891
+ * <ListRow
1892
+ * key={product.sku}
1893
+ * contents={<Txt>{product.displayName}</Txt>}
1894
+ * />
1895
+ * ))}
1896
+ * </List>
1897
+ * );
1898
+ * }
1899
+ * ```
1900
+ */
1901
+ declare function getProductItemList(): Promise<{
1902
+ products: IapProductListItem[];
1903
+ } | undefined>;
1904
+ /**
1905
+ * @public
1906
+ * @category 인앱결제
1907
+ * @name IAP
1908
+ * @description 인앱결제 관련 기능을 모은 객체예요. 단건 인앱결제 주문서 이동과 상품 목록 조회 기능을 제공해요.
1909
+ * @property {typeof createOneTimePurchaseOrder} [createOneTimePurchaseOrder] 특정 인앱결제 주문서 페이지로 이동해요. 자세한 내용은 [createOneTimePurchaseOrder](/bedrock/reference/framework/인앱결제/createOneTimePurchaseOrder.html) 문서를 참고하세요.
1910
+ * @property {typeof getProductItemList} [getProductItemList] 인앱결제로 구매할 수 있는 상품 목록을 가져와요. 자세한 내용은 [getProductItemList](/bedrock/reference/framework/인앱결제/getProductItemList.html) 문서를 참고하세요.
1911
+ */
1912
+ declare const IAP: {
1913
+ createOneTimePurchaseOrder: typeof createOneTimePurchaseOrder;
1914
+ getProductItemList: typeof getProductItemList;
1915
+ };
1916
+
1719
1917
  /**
1720
1918
  * @public
1721
1919
  * @category 토스페이
@@ -1765,6 +1963,17 @@ interface LocalNetwork {
1765
1963
  type InternalProps = 'source' | 'cacheEnabled' | 'sharedCookiesEnabled' | 'thirdPartyCookiesEnabled' | 'injectedJavaScriptBeforeContentLoaded';
1766
1964
  declare function WebView({ type, local, onMessage, ...props }: WebViewProps): react_jsx_runtime.JSX.Element;
1767
1965
 
1966
+ declare function useCreateUserAgent({ batteryModePreference, colorPreference, fontA11y, locale, navbarPreference, pureSafeArea, safeArea, safeAreaBottomTransparency, }: {
1967
+ batteryModePreference?: string;
1968
+ colorPreference?: string;
1969
+ fontA11y?: string;
1970
+ locale?: string;
1971
+ navbarPreference?: string;
1972
+ pureSafeArea?: string;
1973
+ safeArea?: string;
1974
+ safeAreaBottomTransparency?: string;
1975
+ }): string;
1976
+
1768
1977
  type UseGeolocationOptions = Omit<StartUpdateLocationOptions$1, 'callback'>;
1769
1978
  /**
1770
1979
  * @public
@@ -1859,7 +2068,26 @@ declare class AppBridgeCallbackEvent extends BedrockEventDefinition<void, AppBri
1859
2068
  private ensureInvokeAppBridgeCallback;
1860
2069
  }
1861
2070
 
1862
- declare const appsInTossEvent: BedrockEvent<EntryMessageExitedEvent | AppBridgeCallbackEvent | UpdateLocationEvent>;
2071
+ interface VisibilityChangedByTransparentServiceWebOptions {
2072
+ callbackId: string;
2073
+ }
2074
+ declare class VisibilityChangedByTransparentServiceWebEvent extends BedrockEventDefinition<VisibilityChangedByTransparentServiceWebOptions, boolean> {
2075
+ name: "onVisibilityChangedByTransparentServiceWeb";
2076
+ subscription: EmitterSubscription | null;
2077
+ remove(): void;
2078
+ listener(options: VisibilityChangedByTransparentServiceWebOptions, onEvent: (isVisible: boolean) => void, onError: (error: unknown) => void): void;
2079
+ private isVisibilityChangedByTransparentServiceWebResult;
2080
+ }
2081
+
2082
+ declare const appsInTossEvent: BedrockEvent<EntryMessageExitedEvent | VisibilityChangedByTransparentServiceWebEvent | UpdateLocationEvent | AppBridgeCallbackEvent>;
2083
+
2084
+ declare function onVisibilityChangedByTransparentServiceWeb(eventParams: {
2085
+ options: VisibilityChangedByTransparentServiceWebOptions;
2086
+ onEvent: (isVisible: boolean) => void;
2087
+ onError: (error: unknown) => void;
2088
+ }): () => void;
2089
+
2090
+ declare const INTERNAL__onVisibilityChangedByTransparentServiceWeb: typeof onVisibilityChangedByTransparentServiceWeb;
1863
2091
 
1864
2092
  declare const Analytics: {
1865
2093
  init: (options: _apps_in_toss_analytics.AnalyticsConfig) => void;
@@ -1868,4 +2096,4 @@ declare const Analytics: {
1868
2096
  Area: ({ children, params: _params, ...props }: _apps_in_toss_analytics.LoggingAreaProps) => react_jsx_runtime.JSX.Element;
1869
2097
  };
1870
2098
 
1871
- export { Accuracy, Analytics, AppsInToss, type ContactEntity, type EventLogParams, type ExternalWebViewProps, type FetchAlbumPhotosOptions, type GameWebViewProps, type GetCurrentLocationOptions, GoogleAdMob, type ImageResponse, type LoadAdMobInterstitialAdEvent, type LoadAdMobInterstitialAdOptions, type LoadAdMobRewardedAdEvent, type LoadAdMobRewardedAdOptions, type Location, type LocationCoords, type OpenCameraOptions, type PartnerWebViewProps, type ShowAdMobInterstitialAdEvent, type ShowAdMobInterstitialAdOptions, type ShowAdMobRewardedAdEvent, type ShowAdMobRewardedAdOptions, type StartUpdateLocationOptions$1 as StartUpdateLocationOptions, type StartUpdateLocationSubscription, Storage, TossPay, type UpdateLocationEventEmitter, type UseGeolocationOptions, WebView, type WebViewProps, appLogin, appsInTossEvent, env, eventLog, fetchAlbumPhotos, fetchContacts, getClipboardText, getCurrentLocation, getDeviceId, getOperationalEnvironment, getTossAppVersion, getTossShareLink, isMinVersionSupported, openCamera, setClipboardText, setDeviceOrientation, startUpdateLocation, useGeolocation };
2099
+ export { Accuracy, Analytics, AppsInToss, type ContactEntity, type EventLogParams, type ExternalWebViewProps, type FetchAlbumPhotosOptions, type GameWebViewProps, type GetCurrentLocationOptions, GoogleAdMob, IAP, INTERNAL__onVisibilityChangedByTransparentServiceWeb, type IapCreateOneTimePurchaseOrderOptions, type IapCreateOneTimePurchaseOrderResult, type IapProductListItem, type ImageResponse, type LoadAdMobInterstitialAdEvent, type LoadAdMobInterstitialAdOptions, type LoadAdMobRewardedAdEvent, type LoadAdMobRewardedAdOptions, type Location, type LocationCoords, type OpenCameraOptions, type PartnerWebViewProps, type SaveBase64DataParams, type ShowAdMobInterstitialAdEvent, type ShowAdMobInterstitialAdOptions, type ShowAdMobRewardedAdEvent, type ShowAdMobRewardedAdOptions, type StartUpdateLocationOptions$1 as StartUpdateLocationOptions, type StartUpdateLocationSubscription, Storage, TossPay, type UpdateLocationEventEmitter, type UseGeolocationOptions, WebView, type WebViewProps, appLogin, appsInTossEvent, env, eventLog, fetchAlbumPhotos, fetchContacts, getClipboardText, getCurrentLocation, getDeviceId, getOperationalEnvironment, getTossAppVersion, getTossShareLink, isMinVersionSupported, openCamera, saveBase64Data, setClipboardText, setDeviceOrientation, startUpdateLocation, useCreateUserAgent, useGeolocation };