@jolibox/implement 1.2.3 → 1.2.5-beta.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.
Files changed (74) hide show
  1. package/.rush/temp/package-deps_build.json +44 -28
  2. package/.rush/temp/shrinkwrap-deps.json +2 -1
  3. package/CHANGELOG.json +11 -0
  4. package/CHANGELOG.md +9 -0
  5. package/dist/common/context/index.d.ts +5 -0
  6. package/dist/common/report/base-tracker.d.ts +2 -1
  7. package/dist/common/rewards/cached-fetch-reward.d.ts +46 -0
  8. package/dist/common/rewards/cached-reward-service.d.ts +24 -0
  9. package/dist/common/rewards/fetch-reward.d.ts +2 -3
  10. package/dist/common/rewards/index.d.ts +3 -0
  11. package/dist/common/rewards/registers/use-subscription.d.ts +7 -0
  12. package/dist/common/rewards/registers/utils/coins/jolicoin/cached-fetch-balance.d.ts +34 -0
  13. package/dist/common/rewards/registers/utils/coins/jolicoin/fetch-balance.d.ts +2 -1
  14. package/dist/common/rewards/registers/utils/coins/joligem/cached-fetch-gem-balance.d.ts +34 -0
  15. package/dist/common/rewards/registers/utils/coins/joligem/fetch-gem-balance.d.ts +2 -1
  16. package/dist/common/rewards/registers/utils/subscription/commands/index.d.ts +1 -0
  17. package/dist/common/rewards/registers/utils/subscription/commands/use-subscription.d.ts +4 -0
  18. package/dist/common/rewards/registers/utils/subscription/sub-handler.d.ts +13 -0
  19. package/dist/common/rewards/reward-emitter.d.ts +7 -0
  20. package/dist/common/rewards/reward-helper.d.ts +2 -1
  21. package/dist/common/utils/index.d.ts +18 -0
  22. package/dist/h5/api/platformAdsHandle/JoliboxAdsHandler.d.ts +1 -0
  23. package/dist/h5/bootstrap/auth/__tests__/auth.test.d.ts +1 -0
  24. package/dist/h5/bootstrap/auth/index.d.ts +2 -0
  25. package/dist/h5/bootstrap/auth/sub.d.ts +2 -0
  26. package/dist/index.js +9 -13
  27. package/dist/index.native.js +49 -53
  28. package/dist/native/api/index.d.ts +1 -0
  29. package/dist/native/api/payment.d.ts +1 -0
  30. package/dist/native/payment/__tests__/payment-service-simple.test.d.ts +1 -0
  31. package/dist/native/payment/payment-helper.d.ts +8 -5
  32. package/dist/native/payment/payment-service.d.ts +44 -0
  33. package/implement.build.log +2 -2
  34. package/package.json +8 -7
  35. package/src/common/context/index.ts +12 -0
  36. package/src/common/report/base-tracker.ts +2 -2
  37. package/src/common/rewards/cached-fetch-reward.ts +258 -0
  38. package/src/common/rewards/cached-reward-service.ts +255 -0
  39. package/src/common/rewards/fetch-reward.ts +17 -93
  40. package/src/common/rewards/index.ts +4 -0
  41. package/src/common/rewards/registers/use-subscription.ts +34 -0
  42. package/src/common/rewards/registers/utils/coins/jolicoin/cached-fetch-balance.ts +177 -0
  43. package/src/common/rewards/registers/utils/coins/jolicoin/fetch-balance.ts +13 -1
  44. package/src/common/rewards/registers/utils/coins/jolicoin/jolicoin-handler.ts +2 -0
  45. package/src/common/rewards/registers/utils/coins/joligem/cached-fetch-gem-balance.ts +181 -0
  46. package/src/common/rewards/registers/utils/coins/joligem/fetch-gem-balance.ts +13 -1
  47. package/src/common/rewards/registers/utils/coins/joligem/gem-handler.ts +2 -0
  48. package/src/common/rewards/registers/utils/subscription/commands/index.ts +1 -0
  49. package/src/common/rewards/registers/utils/subscription/commands/use-subscription.ts +29 -0
  50. package/src/common/rewards/registers/utils/subscription/sub-handler.ts +88 -0
  51. package/src/common/rewards/reward-emitter.ts +8 -0
  52. package/src/common/rewards/reward-helper.ts +8 -1
  53. package/src/common/utils/index.ts +23 -0
  54. package/src/h5/api/ads.ts +18 -12
  55. package/src/h5/api/platformAdsHandle/JoliboxAdsHandler.ts +25 -1
  56. package/src/h5/api/storage.ts +2 -2
  57. package/src/h5/bootstrap/auth/__tests__/auth.test.ts +308 -0
  58. package/src/h5/bootstrap/auth/index.ts +20 -0
  59. package/src/h5/bootstrap/auth/sub.ts +56 -0
  60. package/src/h5/bootstrap/index.ts +4 -19
  61. package/src/h5/http/index.ts +2 -2
  62. package/src/h5/report/event-tracker.ts +2 -2
  63. package/src/h5/rewards/index.ts +18 -1
  64. package/src/native/api/ads.ts +7 -1
  65. package/src/native/api/call-host-method.ts +1 -1
  66. package/src/native/api/index.ts +1 -0
  67. package/src/native/api/navigate.ts +10 -1
  68. package/src/native/api/payment.ts +56 -0
  69. package/src/native/payment/__tests__/payment-service-simple.test.ts +274 -0
  70. package/src/native/payment/payment-helper.ts +10 -4
  71. package/src/native/payment/payment-service.ts +293 -0
  72. package/src/native/payment/registers/jolicoin-iap.ts +4 -4
  73. package/src/native/report/index.ts +4 -1
  74. package/src/native/rewards/ui/payment-modal.ts +20 -60
@@ -0,0 +1,293 @@
1
+ import { IPaymentChoice } from '@/common/rewards/reward-emitter';
2
+ import { paymentHelper } from './index';
3
+ import { isUndefinedOrNull } from '@jolibox/common';
4
+ import { StandardResponse } from '@jolibox/types';
5
+ import { applyNative } from '@jolibox/native-bridge';
6
+ import { innerFetch as fetch } from '@/native/network';
7
+ import type { PaymentResult } from './payment-helper';
8
+ import { RequestCacheService, RequestAdapter } from '@jolibox/common';
9
+
10
+ type PaymentPurchaseType = 'JOLI_COIN' | 'JOLI_GEM';
11
+
12
+ // Request/Response interfaces for RequestCacheService
13
+
14
+ type PaymentRequest = Record<string, never>;
15
+
16
+ interface PaymentResponse {
17
+ balance: number;
18
+ enableAutoDeduct: boolean;
19
+ paymentChoices: IPaymentChoice[];
20
+ }
21
+
22
+ interface PaymentCacheData {
23
+ paymentChoices: IPaymentChoice[];
24
+ }
25
+
26
+ interface PaymentRealTimeData {
27
+ balance: number;
28
+ enableAutoDeduct: boolean;
29
+ }
30
+
31
+ // Utility function for merging response data
32
+ function mergeResponseData(
33
+ responseData: { paymentChoices: IPaymentChoice[] },
34
+ data: { [appStoreProductId: string]: { price: string } }
35
+ ) {
36
+ Object.keys(data).forEach((key) => {
37
+ const choice = responseData.paymentChoices.find((choice) => choice.appStoreProductId === key);
38
+ if (choice) {
39
+ choice.totalAmountStr = data[key].price;
40
+ }
41
+ });
42
+
43
+ responseData.paymentChoices = responseData.paymentChoices.filter(
44
+ (choice) => !isUndefinedOrNull(choice.totalAmountStr)
45
+ ) as IPaymentChoice[];
46
+ }
47
+
48
+ // Payment Request Adapter for RequestCacheService
49
+ class PaymentRequestAdapter
50
+ implements RequestAdapter<PaymentRequest, PaymentResponse, PaymentCacheData, PaymentRealTimeData>
51
+ {
52
+ // applyNative 的缓存
53
+ private static nativePriceCache = new Map<string, { [appStoreProductId: string]: { price: string } }>();
54
+ private static readonly NATIVE_PRICE_CACHE_DURATION = 30 * 60 * 1000; // 30分钟缓存
55
+ private static nativePriceCacheTimestamp = new Map<string, number>();
56
+
57
+ async execute(endpoint: string, _options?: PaymentRequest): Promise<PaymentResponse> {
58
+ // 获取服务端数据(余额等实时数据)
59
+ const { response } = await fetch<StandardResponse<PaymentResponse>>(endpoint, {
60
+ method: 'GET',
61
+ appendHostCookie: true,
62
+ responseType: 'json'
63
+ });
64
+
65
+ console.log('[PaymentService] get products info from server', endpoint, response.data);
66
+
67
+ if (!response.data?.data) {
68
+ throw new Error('get products info failed');
69
+ }
70
+
71
+ const serverData = response.data.data;
72
+
73
+ const appStoreProductIds =
74
+ serverData.paymentChoices
75
+ ?.filter((choice) => typeof choice.appStoreProductId === 'string')
76
+ .map((choice) => choice.appStoreProductId as string) ?? [];
77
+
78
+ if (appStoreProductIds.length > 0) {
79
+ const nativeData = await this.getNativePriceData(appStoreProductIds);
80
+ if (nativeData) {
81
+ mergeResponseData(serverData, nativeData);
82
+ }
83
+ }
84
+
85
+ if (serverData.paymentChoices.length === 0) {
86
+ throw new Error('paymentChoices is empty');
87
+ }
88
+
89
+ return serverData;
90
+ }
91
+
92
+ private async getNativePriceData(
93
+ appStoreProductIds: string[]
94
+ ): Promise<{ [appStoreProductId: string]: { price: string } } | null> {
95
+ // 检查缓存
96
+ const cacheKey = appStoreProductIds.sort().join(',');
97
+ const cached = PaymentRequestAdapter.nativePriceCache.get(cacheKey);
98
+ const cacheTime = PaymentRequestAdapter.nativePriceCacheTimestamp.get(cacheKey) || 0;
99
+
100
+ if (cached && Date.now() - cacheTime < PaymentRequestAdapter.NATIVE_PRICE_CACHE_DURATION) {
101
+ console.log('[PaymentService] Using cached native price data');
102
+ return cached;
103
+ }
104
+
105
+ console.log('[PaymentService] Fetching fresh native price data');
106
+
107
+ try {
108
+ const { data } = await applyNative('requestProductDetailsAsync', {
109
+ appStoreProductIds
110
+ });
111
+
112
+ if (data) {
113
+ // cache
114
+ PaymentRequestAdapter.nativePriceCache.set(cacheKey, data);
115
+ PaymentRequestAdapter.nativePriceCacheTimestamp.set(cacheKey, Date.now());
116
+ }
117
+
118
+ return data;
119
+ } catch (error) {
120
+ console.warn('[PaymentService] Failed to fetch native product details:', error);
121
+ throw error; // rethrow error, let upper layer handle it
122
+ }
123
+ }
124
+
125
+ extractCacheableData(response: PaymentResponse): PaymentCacheData {
126
+ return {
127
+ paymentChoices: response.paymentChoices
128
+ };
129
+ }
130
+
131
+ extractRealTimeData?: undefined;
132
+ mergeData(cached: PaymentCacheData, realTime: PaymentRealTimeData): PaymentResponse {
133
+ return {
134
+ balance: realTime.balance,
135
+ enableAutoDeduct: realTime.enableAutoDeduct,
136
+ paymentChoices: cached.paymentChoices
137
+ };
138
+ }
139
+
140
+ processCachedData(cached: PaymentCacheData): PaymentResponse {
141
+ // when only cached data is available, use default real-time data values
142
+ return {
143
+ balance: 0, // default balance
144
+ enableAutoDeduct: false, // default not enable auto deduct
145
+ paymentChoices: cached.paymentChoices
146
+ };
147
+ }
148
+
149
+ // clear native price cache static method
150
+ static clearNativePriceCache(): void {
151
+ this.nativePriceCache.clear();
152
+ this.nativePriceCacheTimestamp.clear();
153
+ console.log('[PaymentService] Cleared native price cache');
154
+ }
155
+ }
156
+
157
+ // Base Payment Service class
158
+ class BasePaymentService extends RequestCacheService<
159
+ PaymentRequest,
160
+ PaymentResponse,
161
+ PaymentCacheData,
162
+ PaymentRealTimeData
163
+ > {
164
+ // 失败计数器,按 endpoint 统计
165
+ private static failureCounters = new Map<string, number>();
166
+ private static readonly MAX_FAILURE_COUNT = 2;
167
+
168
+ constructor(private apiEndpoint: string, private paymentType: PaymentPurchaseType) {
169
+ super(new PaymentRequestAdapter(), {
170
+ duration: 10 * 60 * 1000, // 10分钟缓存 paymentChoices
171
+ timeout: 1000 // 1秒超时
172
+ });
173
+ }
174
+
175
+ async getProductsInfo(): Promise<PaymentResponse | undefined> {
176
+ // 检查失败计数,如果达到最大失败次数则直接抛出错误
177
+ const currentFailureCount = BasePaymentService.failureCounters.get(this.apiEndpoint) || 0;
178
+ if (currentFailureCount >= BasePaymentService.MAX_FAILURE_COUNT) {
179
+ throw new Error(
180
+ `getProductsInfo has failed more than ${BasePaymentService.MAX_FAILURE_COUNT} times for ${this.apiEndpoint}`
181
+ );
182
+ }
183
+
184
+ try {
185
+ const result = await this.request(this.apiEndpoint);
186
+ // 成功时重置失败计数器
187
+ BasePaymentService.failureCounters.delete(this.apiEndpoint);
188
+ return result;
189
+ } catch (error) {
190
+ // 失败时增加计数器
191
+ const newCount = currentFailureCount + 1;
192
+ BasePaymentService.failureCounters.set(this.apiEndpoint, newCount);
193
+ console.warn(
194
+ `[PaymentService] getProductsInfo failed (${newCount}/${
195
+ BasePaymentService.MAX_FAILURE_COUNT + 1
196
+ }) for ${this.apiEndpoint}:`,
197
+ error
198
+ );
199
+ throw error;
200
+ }
201
+ }
202
+
203
+ async purchase(productId: string): Promise<PaymentResult<{ totalAmount: string }>> {
204
+ const productsInfo = await this.getProductsInfo();
205
+ const appStoreProductId = productsInfo?.paymentChoices.find(
206
+ (choice) => choice.productId === productId
207
+ )?.appStoreProductId;
208
+ if (!appStoreProductId) {
209
+ throw new Error('appStoreProductId not found');
210
+ }
211
+
212
+ const result = (await paymentHelper.invokePayment(
213
+ this.paymentType === 'JOLI_COIN' ? 'JOLI_COIN_IAP' : 'JOLI_GEM_IAP',
214
+ {
215
+ productId,
216
+ appStoreProductId
217
+ }
218
+ )) as PaymentResult<{ totalAmount: string }>;
219
+
220
+ return result;
221
+ }
222
+
223
+ // 获取产品信息(使用 RequestCacheService)
224
+ async getProductsInfoWithBalance(): Promise<PaymentResponse | undefined> {
225
+ return this.request(this.apiEndpoint);
226
+ }
227
+
228
+ // 强制刷新产品信息
229
+ async refreshProductsInfo(): Promise<PaymentResponse | undefined> {
230
+ return this.forceRequest(this.apiEndpoint);
231
+ }
232
+
233
+ // 重置失败计数器(供测试使用)
234
+ static resetFailureCounters(): void {
235
+ this.failureCounters.clear();
236
+ }
237
+
238
+ // 获取失败计数器状态(供测试使用)
239
+ static getFailureCount(endpoint: string): number {
240
+ return this.failureCounters.get(endpoint) || 0;
241
+ }
242
+ }
243
+
244
+ // JOLI_COIN payment service
245
+ export class JoliCoinPaymentService extends BasePaymentService {
246
+ constructor() {
247
+ super('/api/joli-coin/balance-detail', 'JOLI_COIN');
248
+ }
249
+ }
250
+
251
+ // JOLI_GEM payment service
252
+ export class JoliGemPaymentService extends BasePaymentService {
253
+ constructor() {
254
+ super('/api/joli-gem/balance-detail', 'JOLI_GEM');
255
+ }
256
+ }
257
+
258
+ // service instance management
259
+ let joliCoinServiceInstance: JoliCoinPaymentService | null = null;
260
+ let joliGemServiceInstance: JoliGemPaymentService | null = null;
261
+
262
+ // create JOLI_COIN payment service instance
263
+ export const createJoliCoinPaymentService = (): JoliCoinPaymentService => {
264
+ if (joliCoinServiceInstance) {
265
+ return joliCoinServiceInstance;
266
+ }
267
+ joliCoinServiceInstance = new JoliCoinPaymentService();
268
+ return joliCoinServiceInstance;
269
+ };
270
+
271
+ // create JOLI_GEM payment service instance
272
+ export const createJoliGemPaymentService = (): JoliGemPaymentService => {
273
+ if (joliGemServiceInstance) {
274
+ return joliGemServiceInstance;
275
+ }
276
+ joliGemServiceInstance = new JoliGemPaymentService();
277
+ return joliGemServiceInstance;
278
+ };
279
+
280
+ // 导出原生价格缓存清理方法供测试使用
281
+ export const clearNativePriceCache = (): void => {
282
+ PaymentRequestAdapter.clearNativePriceCache();
283
+ };
284
+
285
+ // 导出失败计数器重置方法供测试使用
286
+ export const resetFailureCounters = (): void => {
287
+ BasePaymentService.resetFailureCounters();
288
+ };
289
+
290
+ // 导出获取失败计数方法供测试使用
291
+ export const getFailureCount = (endpoint: string): number => {
292
+ return BasePaymentService.getFailureCount(endpoint);
293
+ };
@@ -75,7 +75,7 @@ onNative('onPaymentStateChange', (data) => {
75
75
  pendingPayments.delete(orderUUID);
76
76
  });
77
77
 
78
- const payInApp = async (params: { appStoreProductId: string; appAccountToken?: string }) => {
78
+ const purchaseGem = async (params: { appStoreProductId: string; appAccountToken?: string }) => {
79
79
  const deferred = new Deferred<StandardResponse<{ totalAmount: string }>>();
80
80
  let targetOrderUUID: string | undefined;
81
81
 
@@ -88,7 +88,7 @@ const payInApp = async (params: { appStoreProductId: string; appAccountToken?: s
88
88
  });
89
89
  targetOrderUUID = response.data?.orderUUID;
90
90
 
91
- console.info('---payInApp---', response);
91
+ console.info('---purchaseGem---', response);
92
92
  if (!targetOrderUUID) {
93
93
  throw createPaymentInternalError(
94
94
  'orderUUID is null',
@@ -134,7 +134,7 @@ class JolicoinIAPAndroidPaymentResiter extends BasePaymentRegister<
134
134
  };
135
135
 
136
136
  pay = async (): Promise<StandardResponse<{ totalAmount: string }>> => {
137
- return await payInApp({ appStoreProductId: this.appStoreProductId });
137
+ return await purchaseGem({ appStoreProductId: this.appStoreProductId });
138
138
  };
139
139
  }
140
140
 
@@ -180,7 +180,7 @@ class JolicoinIAPIOSPaymentResiter extends BasePaymentRegister<
180
180
  };
181
181
 
182
182
  pay = async (): Promise<StandardResponse<{ totalAmount: string }>> => {
183
- return await payInApp({
183
+ return await purchaseGem({
184
184
  appStoreProductId: this.appStoreProductId,
185
185
  appAccountToken: this.appAccountToken
186
186
  });
@@ -13,12 +13,15 @@ const reportNative: ReportHandler = (event, data, webviewId) => {
13
13
  : isString(_data.extra)
14
14
  ? JSON.parse(_data.extra)
15
15
  : {};
16
+ const { mpName, mpVersion } = context.mpInfo ?? {}; //
16
17
  const extra = {
17
18
  ...originExtra,
18
19
  mp_id: (_data.mp_id as string) ?? '',
19
20
  mp_version: (_data.mp_version as string) ?? '',
20
21
  session_id: context.sessionId,
21
- user_id: context.hostUserInfo?.uid ?? ''
22
+ user_id: context.hostUserInfo?.uid ?? '',
23
+ ...(mpName ? { mp_name: mpName } : {}),
24
+ ...(mpVersion ? { mp_info_version: mpVersion } : {})
22
25
  };
23
26
  const eventType = (_data.eventType ?? EventType.Other) as number;
24
27
 
@@ -23,12 +23,12 @@ import {
23
23
  import { paymentHelper } from '@/native/payment';
24
24
  import { createLoading } from '@jolibox/ui';
25
25
  import { canIUseNative } from '@/native/api/base';
26
- import { applyNative } from '@jolibox/native-bridge';
27
- import { isUndefinedOrNull } from '@jolibox/common';
26
+
28
27
  import { track } from '@/native/report';
29
28
  import { updateAutoDeductConfig } from './utils';
30
29
  import { createEventPromiseHandler } from '@/common/rewards/registers/utils/event-listener';
31
30
  import { TrackEvent } from '@jolibox/types';
31
+ import { createJoliCoinPaymentService, createJoliGemPaymentService } from '@/native/payment/payment-service';
32
32
 
33
33
  // 货币配置映射
34
34
  interface CurrencyPaymentConfig {
@@ -85,6 +85,9 @@ const CURRENCY_PAYMENT_CONFIG: Record<'JOLI_COIN' | 'JOLI_GEM', CurrencyPaymentC
85
85
 
86
86
  const loading = createLoading();
87
87
 
88
+ const JoliCoinPaymentService = createJoliCoinPaymentService();
89
+ const JoliGemPaymentService = createJoliGemPaymentService();
90
+
88
91
  const modalUseFrequencyConfig = createEventPromiseHandler<
89
92
  IUseModalFrequencyConfig,
90
93
  typeof UseModalFrequencyEventName
@@ -114,6 +117,7 @@ rewardsEmitter.on(
114
117
  await loading.show({
115
118
  duration: 3000
116
119
  });
120
+
117
121
  const config = await modalUseFrequencyConfig.getData();
118
122
  const { canShow: canShowPaymentModal } = await paymentConfig.frequencyChecker(
119
123
  config.joliCoinUseAndCharge[paymentConfig.frequencyConfigKey]
@@ -134,7 +138,9 @@ rewardsEmitter.on(
134
138
  await loading.show({
135
139
  duration: 3000
136
140
  });
137
- const balenceDetails = await getBalenceDetails(paymentConfig.apiEndpoint);
141
+ const paymentService = currencyType === 'JOLI_COIN' ? JoliCoinPaymentService : JoliGemPaymentService;
142
+ // get product info from cache, if not found, get from server and cache it
143
+ const balenceDetails = await paymentService.getProductsInfo();
138
144
  loading.hide();
139
145
 
140
146
  if (!balenceDetails) {
@@ -158,7 +164,7 @@ rewardsEmitter.on(
158
164
  ...choice,
159
165
  totalAmountStr: choice.totalAmountStr ?? ''
160
166
  })) ?? [],
161
- enableAutoDeduct: balenceDetails.enableAutoDeduct
167
+ enableAutoDeduct: params.enableAutoDeduct
162
168
  },
163
169
  buttons: {
164
170
  confirm: {
@@ -183,8 +189,8 @@ rewardsEmitter.on(
183
189
  return;
184
190
  }
185
191
 
186
- const balenceDetails = await getBalenceDetails(paymentConfig.apiEndpoint);
187
- if ((balenceDetails?.balance ?? 0) >= params.quantity) {
192
+ const newBalence = await paymentService.refreshProductsInfo();
193
+ if ((newBalence?.balance ?? 0) >= params.quantity) {
188
194
  rewardsEmitter.emit(PaymentResultEventName, {
189
195
  paymentResult: 'SUCCESS',
190
196
  currency: currencyType
@@ -193,6 +199,7 @@ rewardsEmitter.on(
193
199
  return;
194
200
  }
195
201
  }
202
+ // invoke native payment
196
203
  console.log('invokeNativePayment', productId);
197
204
  const appStoreProductId = balenceDetails?.paymentChoices?.find(
198
205
  (choice) => choice.productId === productId
@@ -278,58 +285,11 @@ rewardsEmitter.on(
278
285
  }
279
286
  );
280
287
 
281
- const mergeResponseData = (
282
- responseData: { paymentChoices: IPaymentChoice[] },
283
- data: { [appStoreProductId: string]: { price: string } }
284
- ) => {
285
- Object.keys(data).forEach((key) => {
286
- const choice = responseData.paymentChoices.find((choice) => choice.appStoreProductId === key);
287
- if (choice) {
288
- choice.totalAmountStr = data[key].price;
289
- }
290
- });
291
-
292
- responseData.paymentChoices = responseData.paymentChoices.filter(
293
- (choice) => !isUndefinedOrNull(choice.totalAmountStr)
294
- ) as IPaymentChoice[];
295
- };
296
-
297
- const getBalenceDetails = async (
298
- apiEndpoint: string
299
- ): Promise<
300
- | {
301
- balance: number;
302
- enableAutoDeduct: boolean;
303
- paymentChoices: IPaymentChoice[];
304
- }
305
- | undefined
306
- > => {
307
- const { response } = await fetch<
308
- StandardResponse<{
309
- balance: number;
310
- enableAutoDeduct: boolean;
311
- paymentChoices: IPaymentChoice[];
312
- }>
313
- >(apiEndpoint, {
314
- method: 'GET',
315
- appendHostCookie: true,
316
- responseType: 'json'
317
- });
318
-
319
- console.info('getBalenceDetails', response);
320
- const { data } = await applyNative('requestProductDetailsAsync', {
321
- appStoreProductIds:
322
- response.data?.data?.paymentChoices
323
- ?.filter((choice) => typeof choice.appStoreProductId === 'string')
324
- .map((choice) => choice.appStoreProductId as string) ?? []
325
- });
288
+ /** preload payment details */
326
289
 
327
- if (response.data?.data && data) {
328
- mergeResponseData(response.data?.data, data);
329
- }
330
- console.info('productDetails', response.data?.data);
331
- if (response.data?.data?.paymentChoices.length === 0) {
332
- throw new Error('paymentChoices is empty');
333
- }
334
- return response.data?.data;
335
- };
290
+ JoliCoinPaymentService.getProductsInfo().catch((e) => {
291
+ console.error('preload joli coin payment details failed', e);
292
+ });
293
+ JoliGemPaymentService.getProductsInfo().catch((e) => {
294
+ console.error('preload joli gem payment details failed', e);
295
+ });