expo-iap 2.3.0 → 2.3.1-rc.2

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/iap.md CHANGED
@@ -209,8 +209,8 @@ Transactions map to `Purchase` or `SubscriptionPurchase` with platform-specific
209
209
  Below is a simple example of fetching products and making a purchase with `expo-iap` in a managed workflow, updated to use the new `requestPurchase` signature:
210
210
 
211
211
  ```tsx
212
- import {useEffect, useState} from 'react';
213
- import {Button, Text, View} from 'react-native';
212
+ import { useEffect, useState } from 'react';
213
+ import { Button, Text, View } from 'react-native';
214
214
  import {
215
215
  initConnection,
216
216
  endConnection,
@@ -237,7 +237,7 @@ export default function SimpleIAP() {
237
237
 
238
238
  const purchaseListener = purchaseUpdatedListener(async (purchase) => {
239
239
  if (purchase) {
240
- await finishTransaction({purchase, isConsumable: true});
240
+ await finishTransaction({ purchase, isConsumable: true });
241
241
  alert('Purchase completed!');
242
242
  }
243
243
  });
@@ -252,12 +252,12 @@ export default function SimpleIAP() {
252
252
  const buyItem = async () => {
253
253
  if (!product) return;
254
254
  await requestPurchase({
255
- request: {skus: [product.id]}, // Android expects 'skus'; iOS would use 'sku'
255
+ request: { skus: [product.id] }, // Android expects 'skus'; iOS would use 'sku'
256
256
  });
257
257
  };
258
258
 
259
259
  return (
260
- <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
260
+ <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
261
261
  <Text>{isConnected ? 'Connected' : 'Connecting...'}</Text>
262
262
  {product ? (
263
263
  <>
@@ -277,7 +277,7 @@ export default function SimpleIAP() {
277
277
  The `useIAP` hook simplifies managing in-app purchases. Below is an example updated to use the new `requestPurchase` signature:
278
278
 
279
279
  ```tsx
280
- import {useEffect, useState} from 'react';
280
+ import { useEffect, useState } from 'react';
281
281
  import {
282
282
  SafeAreaView,
283
283
  ScrollView,
@@ -289,20 +289,12 @@ import {
289
289
  InteractionManager,
290
290
  Alert,
291
291
  } from 'react-native';
292
- import {useIAP} from 'expo-iap';
293
- import type {ProductPurchase, SubscriptionProduct} from 'expo-iap';
292
+ import { useIAP } from 'expo-iap';
293
+ import type { ProductPurchase, SubscriptionProduct } from 'expo-iap';
294
294
 
295
295
  // Define SKUs
296
- const productSkus = [
297
- 'cpk.points.1000',
298
- 'cpk.points.5000',
299
- 'cpk.points.10000',
300
- 'cpk.points.30000',
301
- ];
302
- const subscriptionSkus = [
303
- 'cpk.membership.monthly.bronze',
304
- 'cpk.membership.monthly.silver',
305
- ];
296
+ const productSkus = ['cpk.points.1000', 'cpk.points.5000', 'cpk.points.10000', 'cpk.points.30000'];
297
+ const subscriptionSkus = ['cpk.membership.monthly.bronze', 'cpk.membership.monthly.silver'];
306
298
 
307
299
  // Define operations
308
300
  const operations = ['getProducts', 'getSubscriptions'] as const;
@@ -329,10 +321,7 @@ export default function IAPWithHook() {
329
321
 
330
322
  const initializeIAP = async () => {
331
323
  try {
332
- await Promise.all([
333
- getProducts(productSkus),
334
- getSubscriptions(subscriptionSkus),
335
- ]);
324
+ await Promise.all([getProducts(productSkus), getSubscriptions(subscriptionSkus)]);
336
325
  setIsReady(true);
337
326
  } catch (error) {
338
327
  console.error('Error initializing IAP:', error);
@@ -400,10 +389,7 @@ export default function IAPWithHook() {
400
389
  <View style={styles.buttons}>
401
390
  <ScrollView contentContainerStyle={styles.buttonsWrapper} horizontal>
402
391
  {operations.map((operation) => (
403
- <Pressable
404
- key={operation}
405
- onPress={() => handleOperation(operation)}
406
- >
392
+ <Pressable key={operation} onPress={() => handleOperation(operation)}>
407
393
  <View style={styles.buttonView}>
408
394
  <Text>{operation}</Text>
409
395
  </View>
@@ -415,10 +401,10 @@ export default function IAPWithHook() {
415
401
  {!isReady ? (
416
402
  <Text>Loading...</Text>
417
403
  ) : (
418
- <View style={{gap: 12}}>
419
- <Text style={{fontSize: 20}}>Products</Text>
404
+ <View style={{ gap: 12 }}>
405
+ <Text style={{ fontSize: 20 }}>Products</Text>
420
406
  {products.map((item) => (
421
- <View key={item.id} style={{gap: 12}}>
407
+ <View key={item.id} style={{ gap: 12 }}>
422
408
  <Text>
423
409
  {item.title} -{' '}
424
410
  {item.platform === 'android'
@@ -429,24 +415,20 @@ export default function IAPWithHook() {
429
415
  title="Buy"
430
416
  onPress={() =>
431
417
  requestPurchase({
432
- request:
433
- item.platform === 'android'
434
- ? {skus: [item.id]}
435
- : {sku: item.id},
418
+ request: item.platform === 'android' ? { skus: [item.id] } : { sku: item.id },
436
419
  })
437
420
  }
438
421
  />
439
422
  </View>
440
423
  ))}
441
424
 
442
- <Text style={{fontSize: 20}}>Subscriptions</Text>
425
+ <Text style={{ fontSize: 20 }}>Subscriptions</Text>
443
426
  {subscriptions.map((item) => (
444
- <View key={item.id} style={{gap: 12}}>
427
+ <View key={item.id} style={{ gap: 12 }}>
445
428
  <Text>
446
429
  {item.title || item.displayName} -{' '}
447
430
  {item.platform === 'android' && item.subscriptionOfferDetails
448
- ? item.subscriptionOfferDetails[0]?.pricingPhases
449
- .pricingPhaseList[0].formattedPrice
431
+ ? item.subscriptionOfferDetails[0]?.pricingPhases.pricingPhaseList[0].formattedPrice
450
432
  : item.displayPrice}
451
433
  </Text>
452
434
  <Button
@@ -463,7 +445,7 @@ export default function IAPWithHook() {
463
445
  offerToken: offer.offerToken,
464
446
  })) || [],
465
447
  }
466
- : {sku: item.id},
448
+ : { sku: item.id },
467
449
  type: 'subs',
468
450
  })
469
451
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-iap",
3
- "version": "2.3.0",
3
+ "version": "2.3.1-rc.2",
4
4
  "description": "In App Purchase module in Expo",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -21,7 +21,11 @@ const modifyProjectBuildGradle = (gradle) => {
21
21
  if (!modified.includes(supportLib)) {
22
22
  modified = addLineToGradle(modified, /ext\s*{/, supportLib);
23
23
  }
24
- // 2. billing library
24
+ return modified;
25
+ };
26
+ const modifyAppBuildGradle = (gradle) => {
27
+ let modified = gradle;
28
+ // Add billing library dependencies to app-level build.gradle
25
29
  const billingDep = ` implementation "com.android.billingclient:billing-ktx:7.0.0"`;
26
30
  const gmsDep = ` implementation "com.google.android.gms:play-services-base:18.1.0"`;
27
31
  if (!modified.includes(billingDep)) {
@@ -33,10 +37,16 @@ const modifyProjectBuildGradle = (gradle) => {
33
37
  return modified;
34
38
  };
35
39
  const withIAPAndroid = (config) => {
40
+ // Add supportLibVersion to project build.gradle
36
41
  config = (0, config_plugins_1.withProjectBuildGradle)(config, (config) => {
37
42
  config.modResults.contents = modifyProjectBuildGradle(config.modResults.contents);
38
43
  return config;
39
44
  });
45
+ // Add IAP dependencies to app build.gradle
46
+ config = (0, config_plugins_1.withAppBuildGradle)(config, (config) => {
47
+ config.modResults.contents = modifyAppBuildGradle(config.modResults.contents);
48
+ return config;
49
+ });
40
50
  config = (0, config_plugins_1.withAndroidManifest)(config, (config) => {
41
51
  const manifest = config.modResults;
42
52
  if (!manifest.manifest['uses-permission']) {
@@ -2,6 +2,7 @@ import {
2
2
  WarningAggregator,
3
3
  withAndroidManifest,
4
4
  withProjectBuildGradle,
5
+ withAppBuildGradle,
5
6
  ConfigPlugin,
6
7
  createRunOncePlugin,
7
8
  } from 'expo/config-plugins';
@@ -36,7 +37,13 @@ const modifyProjectBuildGradle = (gradle: string): string => {
36
37
  modified = addLineToGradle(modified, /ext\s*{/, supportLib);
37
38
  }
38
39
 
39
- // 2. billing library
40
+ return modified;
41
+ };
42
+
43
+ const modifyAppBuildGradle = (gradle: string): string => {
44
+ let modified = gradle;
45
+
46
+ // Add billing library dependencies to app-level build.gradle
40
47
  const billingDep = ` implementation "com.android.billingclient:billing-ktx:7.0.0"`;
41
48
  const gmsDep = ` implementation "com.google.android.gms:play-services-base:18.1.0"`;
42
49
  if (!modified.includes(billingDep)) {
@@ -50,6 +57,7 @@ const modifyProjectBuildGradle = (gradle: string): string => {
50
57
  };
51
58
 
52
59
  const withIAPAndroid: ConfigPlugin = (config) => {
60
+ // Add supportLibVersion to project build.gradle
53
61
  config = withProjectBuildGradle(config, (config) => {
54
62
  config.modResults.contents = modifyProjectBuildGradle(
55
63
  config.modResults.contents,
@@ -57,6 +65,14 @@ const withIAPAndroid: ConfigPlugin = (config) => {
57
65
  return config;
58
66
  });
59
67
 
68
+ // Add IAP dependencies to app build.gradle
69
+ config = withAppBuildGradle(config, (config) => {
70
+ config.modResults.contents = modifyAppBuildGradle(
71
+ config.modResults.contents,
72
+ );
73
+ return config;
74
+ });
75
+
60
76
  config = withAndroidManifest(config, (config) => {
61
77
  const manifest = config.modResults;
62
78
  if (!manifest.manifest['uses-permission']) {