@apps-in-toss/web-bridge 1.11.2 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -406,6 +406,84 @@ var IAP = {
406
406
  });
407
407
  return unregisterCallbacks;
408
408
  },
409
+ /**
410
+ * @public
411
+ * @category 인앱결제
412
+ * @name createSubscriptionPurchaseOrder
413
+ * @description
414
+ * 구독 인앱결제 주문서 페이지로 이동해요. 사용자가 구독 상품 구매 버튼을 누르는 상황 등에 사용할 수 있어요.
415
+ * @param {CreateSubscriptionPurchaseOrderOptions} params - 구독 인앱결제를 생성할 때 필요한 정보예요.
416
+ * @returns {() => void} 앱브릿지 cleanup 함수를 반환해요. 인앱결제 기능이 끝나면 반드시 이 함수를 호출해서 리소스를 해제해야 해요.
417
+ *
418
+ * ```tsx
419
+ * import { IAP } from "@apps-in-toss/web-framework";
420
+ * import { useCallback } from "react";
421
+ *
422
+ * interface Props {
423
+ * sku: string;
424
+ * offerId?: string;
425
+ * }
426
+ *
427
+ * function SubscriptionPurchaseButton({ sku, offerId }: Props) {
428
+ * const handleClick = useCallback(async () => {
429
+ * const cleanup = IAP.createSubscriptionPurchaseOrder({
430
+ * options: {
431
+ * sku,
432
+ * offerId,
433
+ * processProductGrant: ({ orderId, subscriptionId }) => {
434
+ * // 상품 지급 로직 작성
435
+ * return true; // 상품 지급 여부
436
+ * },
437
+ * },
438
+ * onEvent: (event) => {
439
+ * console.log(event);
440
+ * cleanup();
441
+ * },
442
+ * onError: (error) => {
443
+ * console.error(error);
444
+ * cleanup();
445
+ * },
446
+ * });
447
+ * }, [sku, offerId]);
448
+ *
449
+ * return <button onClick={handleClick}>구독하기</button>;
450
+ * }
451
+ * ```
452
+ */
453
+ createSubscriptionPurchaseOrder: (params) => {
454
+ const isSupported = isMinVersionSupported({
455
+ android: "5.248.0",
456
+ ios: "5.249.0"
457
+ });
458
+ const noop = () => {
459
+ };
460
+ if (!isSupported) {
461
+ return noop;
462
+ }
463
+ const { options, onEvent, onError } = params;
464
+ const { sku, offerId, processProductGrant: handleProcessProductGrant } = options;
465
+ const unregisterCallbacks = createEventBridge("requestSubscriptionPurchase")({
466
+ options: { sku, offerId: offerId ?? null },
467
+ onEvent: async (event) => {
468
+ if (event.type === "purchased") {
469
+ const isProductGranted = await handleProcessProductGrant({
470
+ orderId: event.data.orderId,
471
+ subscriptionId: event.data.subscriptionId
472
+ });
473
+ await processProductGrant({
474
+ orderId: event.data.orderId,
475
+ isProductGranted
476
+ }).catch(onError);
477
+ } else {
478
+ onEvent(event);
479
+ }
480
+ },
481
+ onError: (error) => {
482
+ onError(error);
483
+ }
484
+ });
485
+ return unregisterCallbacks;
486
+ },
409
487
  /**
410
488
  * @public
411
489
  * @category 인앱결제
package/dist/index.d.cts CHANGED
@@ -116,10 +116,21 @@ interface IapCreateOneTimePurchaseOrderResult {
116
116
  fraction: number;
117
117
  miniAppIconUrl: string | null;
118
118
  }
119
+ /**
120
+ * @public
121
+ * @category 인앱결제
122
+ * @name IapCreateSubscriptionPurchaseOrderResult
123
+ * @description 구독 인앱결제가 완료되면 결제 세부 정보와 상품 정보를 담아 반환해요. `IapCreateOneTimePurchaseOrderResult`와 동일한 구조예요.
124
+ */
125
+ type IapCreateSubscriptionPurchaseOrderResult = IapCreateOneTimePurchaseOrderResult;
119
126
  interface SuccessEvent {
120
127
  type: 'success';
121
128
  data: IapCreateOneTimePurchaseOrderResult;
122
129
  }
130
+ interface SubscriptionSuccessEvent {
131
+ type: 'success';
132
+ data: IapCreateSubscriptionPurchaseOrderResult;
133
+ }
123
134
  /**
124
135
  * @public
125
136
  * @category 인앱결제
@@ -142,21 +153,85 @@ interface IapCreateOneTimePurchaseOrderOptions {
142
153
  /**
143
154
  * @public
144
155
  * @category 인앱결제
145
- * @name IapProductListItem
146
- * @description 인앱결제로 구매할 있는 상품 하나의 정보를 담은 객체예요. 상품 목록을 화면에 표시할 때 사용해요.
147
- * @property {string} sku - 상품의 고유 ID예요. [IAP.createOneTimePurchaseOrder](https://developers-apps-in-toss.toss.im/bedrock/reference/framework/%EC%9D%B8%EC%95%B1%20%EA%B2%B0%EC%A0%9C/createOneTimePurchaseOrder.html)를 호출할때 사용하는 `productId`와 동일한 값이에요.
148
- * @property {string} displayName - 화면에 표시할 상품 이름이에요. 상품 이름은 앱인토스 콘솔에서 설정한 값이에요.
149
- * @property {string} displayAmount - 통화 단위가 포함된 가격 정보예요. 예를 들어 `1,000원`으로 가격과 통화가 함께 표시돼요.
150
- * @property {string} iconUrl - 상품 아이콘 이미지의 URL이에요. 아이콘은 앱인토스 콘솔에서 설정한 이미지예요.
151
- * @property {string} description - 상품에 대한 설명이에요. 설명은 앱인토스 콘솔에서 설정한 값이에요.
156
+ * @name CreateSubscriptionPurchaseOrderOptions
157
+ * @description 구독 인앱결제를 생성할 필요한 옵션이에요.
158
+ * @property {object} options - 결제할 구독 상품의 정보예요.
159
+ * @property {string} options.sku - 주문할 구독 상품의 고유 ID예요.
160
+ * @property {string | null} [options.offerId] - 적용할 offer ID예요. 없으면 기본 가격이 적용돼요.
161
+ * @property {(params: { orderId: string, subscriptionId?: string }) => boolean | Promise<boolean>} options.processProductGrant - 주문이 만들어진 실제로 상품을 지급할 호출해요.
162
+ * @property {(event: SubscriptionSuccessEvent) => void | Promise<void>} onEvent - 결제가 성공했을 때 호출해요.
163
+ * @property {(error: unknown) => void | Promise<void>} onError - 결제 과정에서 에러가 발생했을 때 호출해요.
152
164
  */
153
- interface IapProductListItem {
165
+ interface CreateSubscriptionPurchaseOrderOptions {
166
+ options: {
167
+ sku: string;
168
+ offerId?: string | null;
169
+ processProductGrant: (params: {
170
+ orderId: string;
171
+ subscriptionId?: string;
172
+ }) => boolean | Promise<boolean>;
173
+ };
174
+ onEvent: (event: SubscriptionSuccessEvent) => void | Promise<void>;
175
+ onError: (error: unknown) => void | Promise<void>;
176
+ }
177
+ interface BasicProductListItem {
154
178
  sku: string;
155
179
  displayAmount: string;
156
180
  displayName: string;
157
181
  iconUrl: string;
158
182
  description: string;
159
183
  }
184
+ type Offer = {
185
+ type: 'FREE_TRIAL';
186
+ offerId: string;
187
+ period: string;
188
+ } | {
189
+ type: 'NEW_SUBSCRIPTION';
190
+ offerId: string;
191
+ period: string;
192
+ displayAmount: string;
193
+ } | {
194
+ type: 'RETURNING';
195
+ offerId: string;
196
+ period: string;
197
+ displayAmount: string;
198
+ };
199
+ /**
200
+ * @public
201
+ * @category 인앱결제
202
+ * @name ConsumableProductListItem
203
+ * @description 소모품 상품 정보를 담은 객체예요.
204
+ */
205
+ interface ConsumableProductListItem extends BasicProductListItem {
206
+ type: 'CONSUMABLE';
207
+ }
208
+ /**
209
+ * @public
210
+ * @category 인앱결제
211
+ * @name NonConsumableProductListItem
212
+ * @description 비소모품 상품 정보를 담은 객체예요.
213
+ */
214
+ interface NonConsumableProductListItem extends BasicProductListItem {
215
+ type: 'NON_CONSUMABLE';
216
+ }
217
+ /**
218
+ * @public
219
+ * @category 인앱결제
220
+ * @name SubscriptionProductListItem
221
+ * @description 자동 갱신 구독 상품 정보를 담은 객체예요.
222
+ */
223
+ interface SubscriptionProductListItem extends BasicProductListItem {
224
+ type: 'SUBSCRIPTION';
225
+ renewalCycle: 'WEEKLY' | 'MONTHLY' | 'YEARLY';
226
+ offers?: Offer[];
227
+ }
228
+ /**
229
+ * @public
230
+ * @category 인앱결제
231
+ * @name IapProductListItem
232
+ * @description 인앱결제로 구매할 수 있는 상품 하나의 정보를 담은 객체예요. 상품 목록을 화면에 표시할 때 사용해요.
233
+ */
234
+ type IapProductListItem = ConsumableProductListItem | NonConsumableProductListItem | SubscriptionProductListItem;
160
235
  /**
161
236
  * @public
162
237
  * @category 인앱결제
@@ -214,6 +289,51 @@ declare const IAP: {
214
289
  * @throw {code: "PRODUCT_NOT_GRANTED_BY_PARTNER"} - 파트너사의 상품 지급이 실패했을 때 발생해요.
215
290
  */
216
291
  createOneTimePurchaseOrder: (params: IapCreateOneTimePurchaseOrderOptions) => () => void;
292
+ /**
293
+ * @public
294
+ * @category 인앱결제
295
+ * @name createSubscriptionPurchaseOrder
296
+ * @description
297
+ * 구독 인앱결제 주문서 페이지로 이동해요. 사용자가 구독 상품 구매 버튼을 누르는 상황 등에 사용할 수 있어요.
298
+ * @param {CreateSubscriptionPurchaseOrderOptions} params - 구독 인앱결제를 생성할 때 필요한 정보예요.
299
+ * @returns {() => void} 앱브릿지 cleanup 함수를 반환해요. 인앱결제 기능이 끝나면 반드시 이 함수를 호출해서 리소스를 해제해야 해요.
300
+ *
301
+ * ```tsx
302
+ * import { IAP } from "@apps-in-toss/web-framework";
303
+ * import { useCallback } from "react";
304
+ *
305
+ * interface Props {
306
+ * sku: string;
307
+ * offerId?: string;
308
+ * }
309
+ *
310
+ * function SubscriptionPurchaseButton({ sku, offerId }: Props) {
311
+ * const handleClick = useCallback(async () => {
312
+ * const cleanup = IAP.createSubscriptionPurchaseOrder({
313
+ * options: {
314
+ * sku,
315
+ * offerId,
316
+ * processProductGrant: ({ orderId, subscriptionId }) => {
317
+ * // 상품 지급 로직 작성
318
+ * return true; // 상품 지급 여부
319
+ * },
320
+ * },
321
+ * onEvent: (event) => {
322
+ * console.log(event);
323
+ * cleanup();
324
+ * },
325
+ * onError: (error) => {
326
+ * console.error(error);
327
+ * cleanup();
328
+ * },
329
+ * });
330
+ * }, [sku, offerId]);
331
+ *
332
+ * return <button onClick={handleClick}>구독하기</button>;
333
+ * }
334
+ * ```
335
+ */
336
+ createSubscriptionPurchaseOrder: (params: CreateSubscriptionPurchaseOrderOptions) => () => void;
217
337
  /**
218
338
  * @public
219
339
  * @category 인앱결제
@@ -906,4 +1026,4 @@ declare const getServerTime: (() => Promise<number | undefined>) & {
906
1026
  isSupported: () => boolean;
907
1027
  };
908
1028
 
909
- export { type AddAccessoryButtonOptions, type AppsInTossEvent, type AppsInTossGlobals, type CompletedOrRefundedOrdersResult, GoogleAdMob, type GraniteEvent, IAP, type IapCreateOneTimePurchaseOrderOptions, type IapProductListItem, SafeAreaInsets$1 as SafeAreaInsets, Storage, type TdsEvent, TossAds, type AttachBannerOptions as TossAdsAttachBannerOptions, type AttachBannerResult as TossAdsAttachBannerResult, type AttachOptions as TossAdsAttachOptions, type BannerSlotCallbacks as TossAdsBannerSlotCallbacks, type BannerSlotErrorPayload as TossAdsBannerSlotErrorPayload, type BannerSlotEventPayload as TossAdsBannerSlotEventPayload, type InitializeOptions as TossAdsInitializeOptions, appsInTossEvent, env, fetchAlbumPhotos, fetchContacts, getAppsInTossGlobals, getClipboardText, getCurrentLocation, getSafeAreaInsets, getServerTime, graniteEvent, isMinVersionSupported, loadFullScreenAd, openCamera, partner, setClipboardText, showFullScreenAd, startUpdateLocation, tdsEvent };
1029
+ export { type AddAccessoryButtonOptions, type AppsInTossEvent, type AppsInTossGlobals, type CompletedOrRefundedOrdersResult, type ConsumableProductListItem, type CreateSubscriptionPurchaseOrderOptions, GoogleAdMob, type GraniteEvent, IAP, type IapCreateOneTimePurchaseOrderOptions, type IapProductListItem, type NonConsumableProductListItem, SafeAreaInsets$1 as SafeAreaInsets, Storage, type SubscriptionProductListItem, type TdsEvent, TossAds, type AttachBannerOptions as TossAdsAttachBannerOptions, type AttachBannerResult as TossAdsAttachBannerResult, type AttachOptions as TossAdsAttachOptions, type BannerSlotCallbacks as TossAdsBannerSlotCallbacks, type BannerSlotErrorPayload as TossAdsBannerSlotErrorPayload, type BannerSlotEventPayload as TossAdsBannerSlotEventPayload, type InitializeOptions as TossAdsInitializeOptions, appsInTossEvent, env, fetchAlbumPhotos, fetchContacts, getAppsInTossGlobals, getClipboardText, getCurrentLocation, getSafeAreaInsets, getServerTime, graniteEvent, isMinVersionSupported, loadFullScreenAd, openCamera, partner, setClipboardText, showFullScreenAd, startUpdateLocation, tdsEvent };
package/dist/index.d.ts CHANGED
@@ -116,10 +116,21 @@ interface IapCreateOneTimePurchaseOrderResult {
116
116
  fraction: number;
117
117
  miniAppIconUrl: string | null;
118
118
  }
119
+ /**
120
+ * @public
121
+ * @category 인앱결제
122
+ * @name IapCreateSubscriptionPurchaseOrderResult
123
+ * @description 구독 인앱결제가 완료되면 결제 세부 정보와 상품 정보를 담아 반환해요. `IapCreateOneTimePurchaseOrderResult`와 동일한 구조예요.
124
+ */
125
+ type IapCreateSubscriptionPurchaseOrderResult = IapCreateOneTimePurchaseOrderResult;
119
126
  interface SuccessEvent {
120
127
  type: 'success';
121
128
  data: IapCreateOneTimePurchaseOrderResult;
122
129
  }
130
+ interface SubscriptionSuccessEvent {
131
+ type: 'success';
132
+ data: IapCreateSubscriptionPurchaseOrderResult;
133
+ }
123
134
  /**
124
135
  * @public
125
136
  * @category 인앱결제
@@ -142,21 +153,85 @@ interface IapCreateOneTimePurchaseOrderOptions {
142
153
  /**
143
154
  * @public
144
155
  * @category 인앱결제
145
- * @name IapProductListItem
146
- * @description 인앱결제로 구매할 있는 상품 하나의 정보를 담은 객체예요. 상품 목록을 화면에 표시할 때 사용해요.
147
- * @property {string} sku - 상품의 고유 ID예요. [IAP.createOneTimePurchaseOrder](https://developers-apps-in-toss.toss.im/bedrock/reference/framework/%EC%9D%B8%EC%95%B1%20%EA%B2%B0%EC%A0%9C/createOneTimePurchaseOrder.html)를 호출할때 사용하는 `productId`와 동일한 값이에요.
148
- * @property {string} displayName - 화면에 표시할 상품 이름이에요. 상품 이름은 앱인토스 콘솔에서 설정한 값이에요.
149
- * @property {string} displayAmount - 통화 단위가 포함된 가격 정보예요. 예를 들어 `1,000원`으로 가격과 통화가 함께 표시돼요.
150
- * @property {string} iconUrl - 상품 아이콘 이미지의 URL이에요. 아이콘은 앱인토스 콘솔에서 설정한 이미지예요.
151
- * @property {string} description - 상품에 대한 설명이에요. 설명은 앱인토스 콘솔에서 설정한 값이에요.
156
+ * @name CreateSubscriptionPurchaseOrderOptions
157
+ * @description 구독 인앱결제를 생성할 필요한 옵션이에요.
158
+ * @property {object} options - 결제할 구독 상품의 정보예요.
159
+ * @property {string} options.sku - 주문할 구독 상품의 고유 ID예요.
160
+ * @property {string | null} [options.offerId] - 적용할 offer ID예요. 없으면 기본 가격이 적용돼요.
161
+ * @property {(params: { orderId: string, subscriptionId?: string }) => boolean | Promise<boolean>} options.processProductGrant - 주문이 만들어진 실제로 상품을 지급할 호출해요.
162
+ * @property {(event: SubscriptionSuccessEvent) => void | Promise<void>} onEvent - 결제가 성공했을 때 호출해요.
163
+ * @property {(error: unknown) => void | Promise<void>} onError - 결제 과정에서 에러가 발생했을 때 호출해요.
152
164
  */
153
- interface IapProductListItem {
165
+ interface CreateSubscriptionPurchaseOrderOptions {
166
+ options: {
167
+ sku: string;
168
+ offerId?: string | null;
169
+ processProductGrant: (params: {
170
+ orderId: string;
171
+ subscriptionId?: string;
172
+ }) => boolean | Promise<boolean>;
173
+ };
174
+ onEvent: (event: SubscriptionSuccessEvent) => void | Promise<void>;
175
+ onError: (error: unknown) => void | Promise<void>;
176
+ }
177
+ interface BasicProductListItem {
154
178
  sku: string;
155
179
  displayAmount: string;
156
180
  displayName: string;
157
181
  iconUrl: string;
158
182
  description: string;
159
183
  }
184
+ type Offer = {
185
+ type: 'FREE_TRIAL';
186
+ offerId: string;
187
+ period: string;
188
+ } | {
189
+ type: 'NEW_SUBSCRIPTION';
190
+ offerId: string;
191
+ period: string;
192
+ displayAmount: string;
193
+ } | {
194
+ type: 'RETURNING';
195
+ offerId: string;
196
+ period: string;
197
+ displayAmount: string;
198
+ };
199
+ /**
200
+ * @public
201
+ * @category 인앱결제
202
+ * @name ConsumableProductListItem
203
+ * @description 소모품 상품 정보를 담은 객체예요.
204
+ */
205
+ interface ConsumableProductListItem extends BasicProductListItem {
206
+ type: 'CONSUMABLE';
207
+ }
208
+ /**
209
+ * @public
210
+ * @category 인앱결제
211
+ * @name NonConsumableProductListItem
212
+ * @description 비소모품 상품 정보를 담은 객체예요.
213
+ */
214
+ interface NonConsumableProductListItem extends BasicProductListItem {
215
+ type: 'NON_CONSUMABLE';
216
+ }
217
+ /**
218
+ * @public
219
+ * @category 인앱결제
220
+ * @name SubscriptionProductListItem
221
+ * @description 자동 갱신 구독 상품 정보를 담은 객체예요.
222
+ */
223
+ interface SubscriptionProductListItem extends BasicProductListItem {
224
+ type: 'SUBSCRIPTION';
225
+ renewalCycle: 'WEEKLY' | 'MONTHLY' | 'YEARLY';
226
+ offers?: Offer[];
227
+ }
228
+ /**
229
+ * @public
230
+ * @category 인앱결제
231
+ * @name IapProductListItem
232
+ * @description 인앱결제로 구매할 수 있는 상품 하나의 정보를 담은 객체예요. 상품 목록을 화면에 표시할 때 사용해요.
233
+ */
234
+ type IapProductListItem = ConsumableProductListItem | NonConsumableProductListItem | SubscriptionProductListItem;
160
235
  /**
161
236
  * @public
162
237
  * @category 인앱결제
@@ -214,6 +289,51 @@ declare const IAP: {
214
289
  * @throw {code: "PRODUCT_NOT_GRANTED_BY_PARTNER"} - 파트너사의 상품 지급이 실패했을 때 발생해요.
215
290
  */
216
291
  createOneTimePurchaseOrder: (params: IapCreateOneTimePurchaseOrderOptions) => () => void;
292
+ /**
293
+ * @public
294
+ * @category 인앱결제
295
+ * @name createSubscriptionPurchaseOrder
296
+ * @description
297
+ * 구독 인앱결제 주문서 페이지로 이동해요. 사용자가 구독 상품 구매 버튼을 누르는 상황 등에 사용할 수 있어요.
298
+ * @param {CreateSubscriptionPurchaseOrderOptions} params - 구독 인앱결제를 생성할 때 필요한 정보예요.
299
+ * @returns {() => void} 앱브릿지 cleanup 함수를 반환해요. 인앱결제 기능이 끝나면 반드시 이 함수를 호출해서 리소스를 해제해야 해요.
300
+ *
301
+ * ```tsx
302
+ * import { IAP } from "@apps-in-toss/web-framework";
303
+ * import { useCallback } from "react";
304
+ *
305
+ * interface Props {
306
+ * sku: string;
307
+ * offerId?: string;
308
+ * }
309
+ *
310
+ * function SubscriptionPurchaseButton({ sku, offerId }: Props) {
311
+ * const handleClick = useCallback(async () => {
312
+ * const cleanup = IAP.createSubscriptionPurchaseOrder({
313
+ * options: {
314
+ * sku,
315
+ * offerId,
316
+ * processProductGrant: ({ orderId, subscriptionId }) => {
317
+ * // 상품 지급 로직 작성
318
+ * return true; // 상품 지급 여부
319
+ * },
320
+ * },
321
+ * onEvent: (event) => {
322
+ * console.log(event);
323
+ * cleanup();
324
+ * },
325
+ * onError: (error) => {
326
+ * console.error(error);
327
+ * cleanup();
328
+ * },
329
+ * });
330
+ * }, [sku, offerId]);
331
+ *
332
+ * return <button onClick={handleClick}>구독하기</button>;
333
+ * }
334
+ * ```
335
+ */
336
+ createSubscriptionPurchaseOrder: (params: CreateSubscriptionPurchaseOrderOptions) => () => void;
217
337
  /**
218
338
  * @public
219
339
  * @category 인앱결제
@@ -906,4 +1026,4 @@ declare const getServerTime: (() => Promise<number | undefined>) & {
906
1026
  isSupported: () => boolean;
907
1027
  };
908
1028
 
909
- export { type AddAccessoryButtonOptions, type AppsInTossEvent, type AppsInTossGlobals, type CompletedOrRefundedOrdersResult, GoogleAdMob, type GraniteEvent, IAP, type IapCreateOneTimePurchaseOrderOptions, type IapProductListItem, SafeAreaInsets$1 as SafeAreaInsets, Storage, type TdsEvent, TossAds, type AttachBannerOptions as TossAdsAttachBannerOptions, type AttachBannerResult as TossAdsAttachBannerResult, type AttachOptions as TossAdsAttachOptions, type BannerSlotCallbacks as TossAdsBannerSlotCallbacks, type BannerSlotErrorPayload as TossAdsBannerSlotErrorPayload, type BannerSlotEventPayload as TossAdsBannerSlotEventPayload, type InitializeOptions as TossAdsInitializeOptions, appsInTossEvent, env, fetchAlbumPhotos, fetchContacts, getAppsInTossGlobals, getClipboardText, getCurrentLocation, getSafeAreaInsets, getServerTime, graniteEvent, isMinVersionSupported, loadFullScreenAd, openCamera, partner, setClipboardText, showFullScreenAd, startUpdateLocation, tdsEvent };
1029
+ export { type AddAccessoryButtonOptions, type AppsInTossEvent, type AppsInTossGlobals, type CompletedOrRefundedOrdersResult, type ConsumableProductListItem, type CreateSubscriptionPurchaseOrderOptions, GoogleAdMob, type GraniteEvent, IAP, type IapCreateOneTimePurchaseOrderOptions, type IapProductListItem, type NonConsumableProductListItem, SafeAreaInsets$1 as SafeAreaInsets, Storage, type SubscriptionProductListItem, type TdsEvent, TossAds, type AttachBannerOptions as TossAdsAttachBannerOptions, type AttachBannerResult as TossAdsAttachBannerResult, type AttachOptions as TossAdsAttachOptions, type BannerSlotCallbacks as TossAdsBannerSlotCallbacks, type BannerSlotErrorPayload as TossAdsBannerSlotErrorPayload, type BannerSlotEventPayload as TossAdsBannerSlotEventPayload, type InitializeOptions as TossAdsInitializeOptions, appsInTossEvent, env, fetchAlbumPhotos, fetchContacts, getAppsInTossGlobals, getClipboardText, getCurrentLocation, getSafeAreaInsets, getServerTime, graniteEvent, isMinVersionSupported, loadFullScreenAd, openCamera, partner, setClipboardText, showFullScreenAd, startUpdateLocation, tdsEvent };
package/dist/index.js CHANGED
@@ -355,6 +355,84 @@ var IAP = {
355
355
  });
356
356
  return unregisterCallbacks;
357
357
  },
358
+ /**
359
+ * @public
360
+ * @category 인앱결제
361
+ * @name createSubscriptionPurchaseOrder
362
+ * @description
363
+ * 구독 인앱결제 주문서 페이지로 이동해요. 사용자가 구독 상품 구매 버튼을 누르는 상황 등에 사용할 수 있어요.
364
+ * @param {CreateSubscriptionPurchaseOrderOptions} params - 구독 인앱결제를 생성할 때 필요한 정보예요.
365
+ * @returns {() => void} 앱브릿지 cleanup 함수를 반환해요. 인앱결제 기능이 끝나면 반드시 이 함수를 호출해서 리소스를 해제해야 해요.
366
+ *
367
+ * ```tsx
368
+ * import { IAP } from "@apps-in-toss/web-framework";
369
+ * import { useCallback } from "react";
370
+ *
371
+ * interface Props {
372
+ * sku: string;
373
+ * offerId?: string;
374
+ * }
375
+ *
376
+ * function SubscriptionPurchaseButton({ sku, offerId }: Props) {
377
+ * const handleClick = useCallback(async () => {
378
+ * const cleanup = IAP.createSubscriptionPurchaseOrder({
379
+ * options: {
380
+ * sku,
381
+ * offerId,
382
+ * processProductGrant: ({ orderId, subscriptionId }) => {
383
+ * // 상품 지급 로직 작성
384
+ * return true; // 상품 지급 여부
385
+ * },
386
+ * },
387
+ * onEvent: (event) => {
388
+ * console.log(event);
389
+ * cleanup();
390
+ * },
391
+ * onError: (error) => {
392
+ * console.error(error);
393
+ * cleanup();
394
+ * },
395
+ * });
396
+ * }, [sku, offerId]);
397
+ *
398
+ * return <button onClick={handleClick}>구독하기</button>;
399
+ * }
400
+ * ```
401
+ */
402
+ createSubscriptionPurchaseOrder: (params) => {
403
+ const isSupported = isMinVersionSupported({
404
+ android: "5.248.0",
405
+ ios: "5.249.0"
406
+ });
407
+ const noop = () => {
408
+ };
409
+ if (!isSupported) {
410
+ return noop;
411
+ }
412
+ const { options, onEvent, onError } = params;
413
+ const { sku, offerId, processProductGrant: handleProcessProductGrant } = options;
414
+ const unregisterCallbacks = createEventBridge("requestSubscriptionPurchase")({
415
+ options: { sku, offerId: offerId ?? null },
416
+ onEvent: async (event) => {
417
+ if (event.type === "purchased") {
418
+ const isProductGranted = await handleProcessProductGrant({
419
+ orderId: event.data.orderId,
420
+ subscriptionId: event.data.subscriptionId
421
+ });
422
+ await processProductGrant({
423
+ orderId: event.data.orderId,
424
+ isProductGranted
425
+ }).catch(onError);
426
+ } else {
427
+ onEvent(event);
428
+ }
429
+ },
430
+ onError: (error) => {
431
+ onError(error);
432
+ }
433
+ });
434
+ return unregisterCallbacks;
435
+ },
358
436
  /**
359
437
  * @public
360
438
  * @category 인앱결제
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@apps-in-toss/web-bridge",
3
3
  "type": "module",
4
- "version": "1.11.2",
4
+ "version": "1.13.0",
5
5
  "description": "Web Bridge for Apps In Toss",
6
6
  "scripts": {
7
7
  "typecheck": "tsc --noEmit",
@@ -27,11 +27,11 @@
27
27
  "dist"
28
28
  ],
29
29
  "dependencies": {
30
- "@apps-in-toss/types": "1.11.2"
30
+ "@apps-in-toss/types": "1.13.0"
31
31
  },
32
32
  "devDependencies": {
33
- "@apps-in-toss/bridge-core": "1.11.2",
34
- "@apps-in-toss/native-modules": "^1.11.2",
33
+ "@apps-in-toss/bridge-core": "1.13.0",
34
+ "@apps-in-toss/native-modules": "^1.13.0",
35
35
  "@swc/core": "^1.12.7",
36
36
  "picocolors": "^1.1.1",
37
37
  "ts-morph": "^26.0.0",