@24i/bigscreen-sdk 1.0.51 → 1.0.53-alpha.2837

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.
Files changed (57) hide show
  1. package/package.json +4 -3
  2. package/packages/analytics/src/clients/GoogleAnalytics/constants.ts +10 -2
  3. package/packages/analytics/src/clients/GoogleAnalytics/interface.ts +5 -1
  4. package/packages/analytics/src/clients/TwentyFourIQ/TwentyFourIQClient.ts +2 -0
  5. package/packages/analytics/src/clients/TwentyFourIQ/constants.ts +15 -4
  6. package/packages/analytics/src/clients/TwentyFourIQ/interface.ts +7 -4
  7. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapAdEvent.ts +20 -0
  8. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapBase.ts +2 -0
  9. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapBuffering.ts +1 -1
  10. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapPlayerClose.ts +3 -2
  11. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapPlayerOpen.ts +1 -1
  12. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapSceneView.ts +1 -1
  13. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapScroll.ts +1 -1
  14. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoComplete.ts +3 -2
  15. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoPause.ts +3 -2
  16. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoProgress.ts +3 -2
  17. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoStart.ts +1 -1
  18. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapVideoStop.ts +1 -1
  19. package/packages/analytics/src/clients/TwentyFourIQ/types.ts +42 -33
  20. package/packages/driver-androidtv/src/DeviceAndroidTV.ts +14 -0
  21. package/packages/driver-androidtv/src/__mocks__/javaScriptBridge.ts +5 -0
  22. package/packages/driver-androidtv/src/index.ts +1 -0
  23. package/packages/driver-androidtv/src/types.ts +22 -0
  24. package/packages/driver-base/src/DeviceBase.ts +14 -0
  25. package/packages/driver-base/src/__mocks__/DeviceBase.ts +13 -0
  26. package/packages/driver-base/src/index.ts +3 -0
  27. package/packages/driver-base/src/types/InAppPurchase.ts +25 -0
  28. package/packages/driver-browser/src/DeviceBrowser.ts +14 -0
  29. package/packages/driver-entone/src/DeviceEntone.ts +19 -1
  30. package/packages/driver-firetv/src/DeviceFireTV.ts +59 -1
  31. package/packages/driver-firetv/src/__mocks__/javaScriptBridge.ts +5 -0
  32. package/packages/driver-firetv/src/types.ts +1 -0
  33. package/packages/driver-hbbtv/src/DeviceHbbTV.ts +14 -0
  34. package/packages/driver-kreatv/src/DeviceKreaTV.ts +14 -0
  35. package/packages/driver-saphi/src/DeviceSaphi.ts +14 -0
  36. package/packages/driver-smartcast/src/DeviceSmartCast.ts +49 -0
  37. package/packages/driver-smartcast/src/__mocks__/api.ts +26 -0
  38. package/packages/driver-smartcast/src/types.ts +36 -0
  39. package/packages/driver-tizen/src/DeviceTizen.ts +102 -7
  40. package/packages/driver-tizen/src/ITizen.ts +15116 -202
  41. package/packages/driver-tizen/src/IWebapis.ts +8641 -92
  42. package/packages/driver-tizen/src/TizenKeys.ts +2 -2
  43. package/packages/driver-tizen/src/__mocks__/tizen.ts +0 -8
  44. package/packages/driver-tizen/src/constants.ts +1 -195
  45. package/packages/driver-vidaa/src/DeviceVidaa.ts +14 -0
  46. package/packages/driver-webos/src/DeviceWebos.ts +14 -0
  47. package/packages/driver-xbox/src/DeviceXbox.ts +19 -1
  48. package/packages/input/src/Input.tsx +6 -0
  49. package/packages/list/DoubleList/README.md +105 -0
  50. package/packages/list/DoubleList/index.ts +1 -0
  51. package/packages/list/src/DoubleList/DoubleList.tsx +267 -0
  52. package/packages/list/src/DoubleList/DoubleListAdapter.ts +72 -0
  53. package/packages/list/src/DoubleList/config.ts +15 -0
  54. package/packages/list/src/DoubleList/interface.ts +82 -0
  55. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapAdLoaded.ts +0 -13
  56. package/packages/analytics/src/clients/TwentyFourIQ/mappers/mapAdSkipped.ts +0 -16
  57. package/packages/driver-tizen/src/types.ts +0 -14
@@ -1,5 +1,7 @@
1
1
  import {
2
2
  DeviceBase, ConnectionType, ScreenSaverStatus, VolumeRange,
3
+ IAPSuccessPayload,
4
+ IAPPurchaseProductData,
3
5
  } from '@24i/bigscreen-sdk/driver-base';
4
6
  import { runAsync } from '@24i/bigscreen-sdk/utils/timers';
5
7
  import { generateUuid } from '@24i/bigscreen-sdk/utils';
@@ -179,4 +181,16 @@ export class DeviceBrowser extends DeviceBase {
179
181
  // for development purpose. Correctly, it should return '' for unknown MAC addr.
180
182
  return '00:00:00:00:00:00';
181
183
  }
184
+
185
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
186
+ async purchaseProduct(data: IAPPurchaseProductData): Promise<IAPSuccessPayload> {
187
+ // not supported
188
+ throw new Error('Not supported');
189
+ }
190
+
191
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
192
+ async cancelSubscription(data: IAPPurchaseProductData): Promise<void> {
193
+ // not supported
194
+ throw new Error('Not supported');
195
+ }
182
196
  }
@@ -1,4 +1,10 @@
1
- import { DeviceBase, ScreenSaverStatus, VolumeRange } from '@24i/bigscreen-sdk/driver-base';
1
+ import {
2
+ DeviceBase,
3
+ IAPPurchaseProductData,
4
+ IAPSuccessPayload,
5
+ ScreenSaverStatus,
6
+ VolumeRange,
7
+ } from '@24i/bigscreen-sdk/driver-base';
2
8
  import { generateUuid } from '@24i/bigscreen-sdk/utils';
3
9
  import { getKeyMap } from './keymap';
4
10
  import { EntoneDeviceModelName } from './constants';
@@ -241,4 +247,16 @@ export class DeviceEntone extends DeviceBase {
241
247
  }
242
248
  return macAddress || '';
243
249
  }
250
+
251
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
252
+ async purchaseProduct(data: IAPPurchaseProductData): Promise<IAPSuccessPayload> {
253
+ // not supported
254
+ throw new Error('Not supported');
255
+ }
256
+
257
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
258
+ async cancelSubscription(data: IAPPurchaseProductData): Promise<void> {
259
+ // not supported
260
+ throw new Error('Not supported');
261
+ }
244
262
  }
@@ -1,4 +1,14 @@
1
- import { DeviceAndroidTV } from '@24i/bigscreen-sdk/driver-androidtv';
1
+ import {
2
+ DeviceAndroidTV,
3
+ IAPErrorEvent,
4
+ IAPSuccessEvent,
5
+ } from '@24i/bigscreen-sdk/driver-androidtv';
6
+ import {
7
+ IAPSuccessPayload, IAPPromiseReject, IAPPromiseResolve,
8
+ IAPPurchaseProductData,
9
+ } from '@24i/bigscreen-sdk/driver-base';
10
+ import { VendorType } from '@24i/smartapps-datalayer/api';
11
+ import { Receipt } from './types';
2
12
 
3
13
  /**
4
14
  * Fire TV driver implementing API of Android TV Bridge.
@@ -6,6 +16,11 @@ import { DeviceAndroidTV } from '@24i/bigscreen-sdk/driver-androidtv';
6
16
  * See https://github.com/24i/prd-smart-ott-androidtv
7
17
  */
8
18
  export class DeviceFireTV extends DeviceAndroidTV {
19
+ subscriptionFeaturesConfiguration = {
20
+ purchase: true,
21
+ management: false,
22
+ };
23
+
9
24
  async getPlatformName(): Promise<string> {
10
25
  return 'FireTV';
11
26
  }
@@ -30,4 +45,47 @@ export class DeviceFireTV extends DeviceAndroidTV {
30
45
  }
31
46
  return { adId, type, latEnabled };
32
47
  }
48
+
49
+ onIAPSuccess = (resolve: IAPPromiseResolve, reject: IAPPromiseReject) => (event: unknown) => {
50
+ this.removeIAPListeners(resolve, reject);
51
+ try {
52
+ const { userId, receipt: receiptToParse } = event as IAPSuccessEvent;
53
+ const receipt: Receipt = JSON.parse(receiptToParse);
54
+ window.JavaScriptBridge
55
+ .bridgeReceiptAmazonIAPValidated(receipt.receiptId);
56
+ resolve({
57
+ platform: VendorType.AMAZON,
58
+ receiptPayload: {
59
+ userId,
60
+ receiptId: receipt.receiptId,
61
+ },
62
+ });
63
+ } catch (e) {
64
+ reject(e);
65
+ }
66
+ };
67
+
68
+ onIAPError = (resolve: IAPPromiseResolve, reject: IAPPromiseReject) => (event: unknown) => {
69
+ this.removeIAPListeners(resolve, reject);
70
+ reject(new Error((event as IAPErrorEvent).message));
71
+ };
72
+
73
+ removeIAPListeners(resolve: IAPPromiseResolve, reject: IAPPromiseReject) {
74
+ document.removeEventListener('iapSuccess', this.onIAPSuccess(resolve, reject));
75
+ document.removeEventListener('iapError', this.onIAPError(resolve, reject));
76
+ }
77
+
78
+ async purchaseProduct(data: IAPPurchaseProductData): Promise<IAPSuccessPayload> {
79
+ return new Promise((resolve, reject) => {
80
+ document.addEventListener('iapSuccess', this.onIAPSuccess(resolve, reject));
81
+ document.addEventListener('iapError', this.onIAPError(resolve, reject));
82
+ window.JavaScriptBridge.bridgeReceiptAmazonIAPValidation(data.sku!);
83
+ });
84
+ }
85
+
86
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
87
+ async cancelSubscription(data: IAPPurchaseProductData): Promise<void> {
88
+ // not supported
89
+ throw new Error('Not supported');
90
+ }
33
91
  }
@@ -18,6 +18,7 @@ export const mockJavaScriptBridge: IJavaScriptBridge = {
18
18
  bridgeJavaScriptToAndroid_GetOsLanguage: () => '',
19
19
  bridgeJavaScriptToAndroid_GetMediaInfo: () => '{}',
20
20
  bridgeJavaScriptToAndroid_Back: () => {},
21
+ bridgeJavaScriptToAndroid_ReloadPlayer: () => {},
21
22
  bridgeJavaScriptToAndroid_StopVideo: () => {},
22
23
  bridgeJavaScriptToAndroid_FullScreenVideo: () => {},
23
24
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -36,5 +37,9 @@ export const mockJavaScriptBridge: IJavaScriptBridge = {
36
37
  bridgeJavaScriptToAndroid_SetTrack: (track: string) => {},
37
38
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
38
39
  bridgeJavaScriptToAndroid_SetAudioTrack: (track: string) => {},
40
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
41
+ bridgeReceiptAmazonIAPValidation: (sku: string) => {},
42
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
43
+ bridgeReceiptAmazonIAPValidated: (receiptId: string) => {},
39
44
  },
40
45
  };
@@ -0,0 +1 @@
1
+ export type Receipt = object & { receiptId: string };
@@ -1,5 +1,7 @@
1
1
  import {
2
2
  DeviceBase, ConnectionType, ScreenSaverStatus, loadObject, VolumeRange,
3
+ IAPSuccessPayload,
4
+ IAPPurchaseProductData,
3
5
  } from '@24i/bigscreen-sdk/driver-base';
4
6
  import { generateUuid } from '@24i/bigscreen-sdk/utils';
5
7
  import { getKeyMap } from './keymap';
@@ -322,4 +324,16 @@ export class DeviceHbbTV extends DeviceBase {
322
324
  console.warn('[HbbTV] Broadcast tune failed');
323
325
  }
324
326
  }
327
+
328
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
329
+ async purchaseProduct(data: IAPPurchaseProductData): Promise<IAPSuccessPayload> {
330
+ // not supported
331
+ throw new Error('Not supported');
332
+ }
333
+
334
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
335
+ async cancelSubscription(data: IAPPurchaseProductData): Promise<void> {
336
+ // not supported
337
+ throw new Error('Not supported');
338
+ }
325
339
  }
@@ -3,6 +3,8 @@ import {
3
3
  ConnectionType,
4
4
  ScreenSaverStatus,
5
5
  VolumeRange,
6
+ IAPSuccessPayload,
7
+ IAPPurchaseProductData,
6
8
  } from '@24i/bigscreen-sdk/driver-base';
7
9
  import { generateUuid } from '@24i/bigscreen-sdk/utils';
8
10
  import { getKeyMap } from './keymap';
@@ -280,4 +282,16 @@ export class DeviceKreaTV extends DeviceBase {
280
282
  async getMacAddress(): Promise<string> {
281
283
  return this.toiResolver.getMacAddress();
282
284
  }
285
+
286
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
287
+ async purchaseProduct(data: IAPPurchaseProductData): Promise<IAPSuccessPayload> {
288
+ // not supported
289
+ throw new Error('Not supported');
290
+ }
291
+
292
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
293
+ async cancelSubscription(data: IAPPurchaseProductData): Promise<void> {
294
+ // not supported
295
+ throw new Error('Not supported');
296
+ }
283
297
  }
@@ -3,6 +3,8 @@ import {
3
3
  ConnectionType,
4
4
  ScreenSaverStatus,
5
5
  VolumeRange,
6
+ IAPSuccessPayload,
7
+ IAPPurchaseProductData,
6
8
  } from '@24i/bigscreen-sdk/driver-base';
7
9
  import { generateUuid } from '@24i/bigscreen-sdk/utils';
8
10
  import { getDeviceInfo, getFirmware, getPlatformInfo } from './formatUserAgent';
@@ -153,4 +155,16 @@ export class DeviceSaphi extends DeviceBase {
153
155
  // not supported on Saphi platform
154
156
  return '';
155
157
  }
158
+
159
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
160
+ async purchaseProduct(data: IAPPurchaseProductData): Promise<IAPSuccessPayload> {
161
+ // not supported
162
+ throw new Error('Not supported');
163
+ }
164
+
165
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
166
+ async cancelSubscription(data: IAPPurchaseProductData): Promise<void> {
167
+ // not supported
168
+ throw new Error('Not supported');
169
+ }
156
170
  }
@@ -1,8 +1,11 @@
1
1
  import {
2
2
  DeviceBase, ConnectionType, ScreenSaverStatus, VolumeRange,
3
+ IAPSuccessPayload,
4
+ IAPPurchaseProductData,
3
5
  } from '@24i/bigscreen-sdk/driver-base';
4
6
  import { runAsync } from '@24i/bigscreen-sdk/utils/timers';
5
7
  import { ipify } from '@24i/bigscreen-sdk/ipify';
8
+ import { VendorType } from '@24i/smartapps-datalayer/api';
6
9
  import { getKeyMap } from './keymap';
7
10
  import {
8
11
  ISmartCastApi,
@@ -10,6 +13,7 @@ import {
10
13
  DEFAULT_TTS_TIMEOUT,
11
14
  DevicePlaybackQuality,
12
15
  DeviceLanguage,
16
+ PurchaseData,
13
17
  } from './types';
14
18
 
15
19
  declare const window: Window & { VIZIO: ISmartCastApi };
@@ -48,6 +52,7 @@ export class DeviceSmartCast extends DeviceBase {
48
52
  this.initVisibilityChangeListener();
49
53
  this.initMouseActiveListener();
50
54
  await this.initPlatformApiListeners();
55
+ this.setSubscriptionFeaturesConfiguration();
51
56
  }
52
57
 
53
58
  async initPlatformApiListeners(): Promise<void> {
@@ -244,6 +249,12 @@ export class DeviceSmartCast extends DeviceBase {
244
249
  .replace('{{us_privacy}}', IFAObject.LMT ? '1YYN' : '1YNN');
245
250
  }
246
251
 
252
+ async getUserMetadata() {
253
+ await this.checkAndLinkTv();
254
+ const result = await this.API!.Account.getUserMetadata();
255
+ return result?.data || null;
256
+ }
257
+
247
258
  async getManufacturerName() {
248
259
  return 'VIZIO';
249
260
  }
@@ -342,4 +353,42 @@ export class DeviceSmartCast extends DeviceBase {
342
353
  // not supported on SmartCast platform
343
354
  return '';
344
355
  }
356
+
357
+ setSubscriptionFeaturesConfiguration() {
358
+ try {
359
+ this.subscriptionFeaturesConfiguration.purchase = this.API?.Account.isSVODEnabled?.()
360
+ || false;
361
+ } catch {}
362
+ }
363
+
364
+ registerPartner(callback: (challenge: string) => Promise<string>, appKeyId: string) {
365
+ this.API!.Account.registerPartner(callback, appKeyId);
366
+ }
367
+
368
+ async checkAndLinkTv() {
369
+ const isLinked = await this.API!.Account.getLinkStatus();
370
+ if (!isLinked) await this.API!.Account.startTVLink();
371
+ }
372
+
373
+ async purchaseProduct({ sku, serviceId }: IAPPurchaseProductData): Promise<IAPSuccessPayload> {
374
+ await this.checkAndLinkTv();
375
+ await this.API!.Account.getPlans({ includeBundlePlans: true });
376
+ const purchaseResult = await this.API!.Account.startSVODPurchase(
377
+ sku!, serviceId ?? '',
378
+ );
379
+ const receiptPayload: PurchaseData = {
380
+ customerId: purchaseResult.data.customerId,
381
+ partnerAccountId: purchaseResult.data.partnerAccountId,
382
+ planCode: purchaseResult.data.planCode,
383
+ addOnCodes: purchaseResult.data.addOnCodes,
384
+ subscriptionId: purchaseResult.data.subscriptionId,
385
+ };
386
+ return { platform: VendorType.VIZIO, receiptPayload };
387
+ }
388
+
389
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
390
+ async cancelSubscription(data: IAPPurchaseProductData): Promise<void> {
391
+ // not supported
392
+ throw new Error('Not supported');
393
+ }
345
394
  }
@@ -50,4 +50,30 @@ export const SmartCastMockApi: ISmartCastApi = {
50
50
  console.log(text);
51
51
  },
52
52
  },
53
+
54
+ Account: {
55
+ isSVODEnabled: () => true,
56
+ startSVODPurchase: async () => ({
57
+ id: 'id',
58
+ data: {
59
+ customerId: 'customerId',
60
+ partnerAccountId: 'partnerAccountId',
61
+ planCode: 'planCode',
62
+ subscriptionId: 'subscriptionId',
63
+ },
64
+ }),
65
+ registerPartner: jest.fn(),
66
+ getLinkStatus: async () => true,
67
+ getUserMetadata: async () => ({
68
+ id: 'id',
69
+ data: {
70
+ customerId: 'customerId',
71
+ email: 'email@example.com',
72
+ firstName: 'First',
73
+ lastName: 'Last',
74
+ },
75
+ }),
76
+ startTVLink: async () => ({}),
77
+ getPlans: async () => ({ id: 'id', data: [] }),
78
+ },
53
79
  };
@@ -39,6 +39,24 @@ export type ISmartCastApi = {
39
39
  */
40
40
  setDeviceLanguageHandler: (callback: (deviceLanguage: DeviceLanguage) => void) => void;
41
41
 
42
+ Account: {
43
+ isSVODEnabled: () => boolean,
44
+ startSVODPurchase: (
45
+ planCode: string,
46
+ partnerAccountId: string,
47
+ couponCode?: string,
48
+ addOnCodes?: string[],
49
+ noFreeTrial?: boolean,
50
+ ) => Promise<{ id: string, data: PurchaseData }>
51
+ registerPartner: (callback:(challenge: string) => Promise<string>, keyId: string) => void
52
+ getLinkStatus: () => Promise<boolean>
53
+ getUserMetadata: () => Promise<{ id: string, data: UserMetadata }>
54
+ startTVLink: () => Promise<object>
55
+ getPlans: (options: { includeBundlePlans?: boolean }) => Promise<{
56
+ id: string, data: object[]
57
+ }>
58
+ }
59
+
42
60
  /**
43
61
  * Device model.
44
62
  */
@@ -52,6 +70,24 @@ export type ISmartCastApi = {
52
70
  play: (text: string) => void,
53
71
  };
54
72
  };
73
+ /**
74
+ * Data type when purchase successfull.
75
+ */
76
+
77
+ export type PurchaseData = {
78
+ customerId: string,
79
+ partnerAccountId: string,
80
+ planCode: string,
81
+ addOnCodes?: string[],
82
+ subscriptionId: string
83
+ };
84
+
85
+ export type UserMetadata = {
86
+ customerId: string;
87
+ email: string;
88
+ firstName: string;
89
+ lastName: string;
90
+ };
55
91
 
56
92
  /**
57
93
  * Identifier For Advertising (IFA) and Limited Tracking parameter object
@@ -4,20 +4,29 @@ import {
4
4
  ScreenSaverStatus,
5
5
  VolumeRange,
6
6
  ExitOptions,
7
+ IAPSuccessPayload,
8
+ IAPPurchaseProductData,
7
9
  } from '@24i/bigscreen-sdk/driver-base';
8
10
  import { Storage } from '@24i/bigscreen-sdk/storage';
9
11
  import { runAsync } from '@24i/bigscreen-sdk/utils/timers';
10
- import { TizenKeys } from './TizenKeys';
12
+ import { VendorType } from '@24i/smartapps-datalayer/api';
11
13
  import {
12
- VENDOR,
14
+ type Webapis,
15
+ BillingBuyData,
13
16
  NetworkState,
14
17
  NetworkActiveConnectionType,
15
18
  AppCommonScreenSaverState,
19
+ CancelSubscriptionData,
20
+ CancelSubscriptionAPIResult,
21
+ } from './IWebapis';
22
+ import { Tizen, Application } from './ITizen';
23
+ import { TizenKeys } from './TizenKeys';
24
+ import {
25
+ VENDOR,
16
26
  } from './constants';
17
- import { IWebapis, ITizen, TizenApplication } from './types';
18
27
 
19
- declare const webapis: IWebapis;
20
- declare const tizen: ITizen;
28
+ declare const webapis: Webapis;
29
+ declare const tizen: Tizen;
21
30
 
22
31
  const isNetworkConnected = (state: NetworkState) => {
23
32
  switch (state) {
@@ -36,7 +45,7 @@ const isNetworkConnected = (state: NetworkState) => {
36
45
  export class DeviceTizen extends DeviceBase {
37
46
  // MARK: Properties
38
47
 
39
- application: TizenApplication = tizen.application.getCurrentApplication();
48
+ application: Application = tizen.application.getCurrentApplication();
40
49
 
41
50
  keys: TizenKeys = new TizenKeys();
42
51
 
@@ -46,6 +55,11 @@ export class DeviceTizen extends DeviceBase {
46
55
 
47
56
  screenSaverStatus: AppCommonScreenSaverState = AppCommonScreenSaverState.SCREEN_SAVER_OFF;
48
57
 
58
+ subscriptionFeaturesConfiguration = {
59
+ purchase: true,
60
+ management: true,
61
+ };
62
+
49
63
  // MARK: Initialization
50
64
 
51
65
  async initDevice(): Promise<void> {
@@ -270,7 +284,7 @@ export class DeviceTizen extends DeviceBase {
270
284
  ? AppCommonScreenSaverState.SCREEN_SAVER_ON
271
285
  : AppCommonScreenSaverState.SCREEN_SAVER_OFF;
272
286
  return new Promise((resolve) => {
273
- webapis.appCommon.setScreenSaver(
287
+ webapis.appcommon.setScreenSaver(
274
288
  status,
275
289
  () => {
276
290
  this.screenSaverStatus = status;
@@ -319,4 +333,85 @@ export class DeviceTizen extends DeviceBase {
319
333
  async getMacAddress() {
320
334
  return webapis.network.getMac();
321
335
  }
336
+
337
+ async purchaseProduct({
338
+ sku, product, appId,
339
+ }: IAPPurchaseProductData): Promise<IAPSuccessPayload> {
340
+ return new Promise((resolve, reject) => {
341
+ if (!product || !appId) reject(new Error('Missing product or appId'));
342
+ const paymentDetails = {
343
+ OrderItemID: sku,
344
+ OrderTitle: product!.title,
345
+ OrderTotal: product!.price![0].amount,
346
+ OrderCurrencyID: product!.price![0].currency,
347
+ OrderCustomID: webapis.sso.getLoginUid(),
348
+ };
349
+ const onSuccess = (data: BillingBuyData) => {
350
+ try {
351
+ if (data.payResult !== 'SUCCESS') throw new Error('Purchase failed');
352
+ const countryCode = webapis.productinfo.getSystemConfig(
353
+ webapis.productinfo.ProductInfoConfigKey.CONFIG_KEY_SERVICE_COUNTRY,
354
+ );
355
+ const detail = JSON.parse(data.payDetail);
356
+ resolve({
357
+ platform: VendorType.SAMSUNG,
358
+ receiptPayload: {
359
+ appId,
360
+ samsungInvoiceId: detail.InvoiceID,
361
+ samsungCustomId: paymentDetails.OrderCustomID,
362
+ countryCode,
363
+ },
364
+ });
365
+ } catch (e) {
366
+ reject(e);
367
+ }
368
+ };
369
+ webapis.billing.buyItem(
370
+ appId!, 'PRD', JSON.stringify(paymentDetails), onSuccess, reject,
371
+ );
372
+ });
373
+ }
374
+
375
+ async cancelSubscription(
376
+ { product, appId }: IAPPurchaseProductData,
377
+ ): Promise<void> {
378
+ return new Promise((resolve, reject) => {
379
+ if (!product || !appId) {
380
+ reject(new Error('Missing product or appId'));
381
+ }
382
+ const UID = webapis.sso.getLoginUid();
383
+ const countryCode = webapis.productinfo.getSystemConfig(
384
+ webapis.productinfo.ProductInfoConfigKey.CONFIG_KEY_SERVICE_COUNTRY,
385
+ );
386
+ try {
387
+ const vendorTransactionId = product?.vendorTransactionId;
388
+ if (!vendorTransactionId) {
389
+ reject(new Error('Missing vendorTransactionId'));
390
+ }
391
+ const onSuccess = (data: CancelSubscriptionData) => {
392
+ try {
393
+ const result: CancelSubscriptionAPIResult = JSON.parse(data.apiResult);
394
+ if (result.CPStatus === '100000') {
395
+ resolve();
396
+ } else {
397
+ reject(new Error(`Cancel subscription failed: ${result.CPStatus}`));
398
+ }
399
+ } catch (e) {
400
+ reject(e);
401
+ }
402
+ };
403
+ webapis.billing.cancelSubscription(
404
+ appId!,
405
+ product!.vendorTransactionId!.toString(),
406
+ UID,
407
+ countryCode,
408
+ 'PRD',
409
+ onSuccess,
410
+ reject,
411
+ );
412
+ } catch (e) {
413
+ reject(e);
414
+ }
415
+ });
416
+ }
322
417
  }