From 7f9ff8efbfc9b79204eb004ece673594c96a6e20 Mon Sep 17 00:00:00 2001 From: Andres Aguilar Date: Wed, 24 Aug 2022 19:51:42 -0700 Subject: [PATCH] product purchase lifecycle (#1885) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci: replace publication for next branch * refactor!: create a PurchaseError class (#1866) * refactor!: remove support for default export (#1864) * chore: clean up non existing errors (#1868) * chore: move some logic into internal files (#1871) * refactor: extract event-emitter to specific file (#1872) * refactor!: make all methods take an object of params (#1873) * integrate ios storekit 2 (#1882) * set min ios version to 15 * consolidated buy methods * removed checks for older versions of ios * cleared most errors * swiftlint * continue migration, purchases * return promises to class * moved utils to ios * clean up promises and error codes * serialized Transactions * removed remaining old methods, added serialization * default to Xcode 4 spaces * Split files * Added more transaction methods * removed global autofinish * fix lint on doc Co-authored-by: Andres Aguilar * Able to purchase products * swift lint * fixed lint issues, removed methods Co-authored-by: hyochan Co-authored-by: Jérémy Barbet Co-authored-by: Andres Aguilar --- .swiftlint.yml | 1 - IapExample/ios/Configuration.storekit | 48 + .../ios/IapExample.xcodeproj/project.pbxproj | 4 + .../xcschemes/IapExample.xcscheme | 3 + IapExample/ios/Podfile | 2 +- IapExample/ios/Podfile.lock | 6 +- IapExample/src/screens/ClassSetup.tsx | 16 +- IapExample/src/screens/Products.tsx | 33 +- IapExample/src/screens/Subscriptions.tsx | 11 +- RNIap.podspec | 2 +- .../usage_instructions/receipt_validation.md | 22 - ios/IapSerializationUtils.swift | 111 ++ ios/IapTypes.swift | 39 + ios/IapUtils.swift | 30 + ios/RNIapIos.m | 43 +- ios/RNIapIos.swift | 1275 +++++------------ src/eventEmitter.ts | 3 +- src/hooks/useIAP.ts | 7 +- src/hooks/withIAPContext.tsx | 25 +- src/iap.ts | 211 +-- src/types/index.ts | 47 +- 21 files changed, 697 insertions(+), 1242 deletions(-) create mode 100644 IapExample/ios/Configuration.storekit create mode 100644 ios/IapSerializationUtils.swift create mode 100644 ios/IapTypes.swift create mode 100644 ios/IapUtils.swift diff --git a/.swiftlint.yml b/.swiftlint.yml index ad9f471c7..cb1d5094d 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -6,6 +6,5 @@ opt_in_rules: - operator_usage_whitespace - redundant_type_annotation -indentation: 2 vertical_whitespace_closing_braces: true vertical_whitespace_opening_braces: true diff --git a/IapExample/ios/Configuration.storekit b/IapExample/ios/Configuration.storekit new file mode 100644 index 000000000..e57a4bbcb --- /dev/null +++ b/IapExample/ios/Configuration.storekit @@ -0,0 +1,48 @@ +{ + "identifier" : "5BB04EE6", + "nonRenewingSubscriptions" : [ + + ], + "products" : [ + { + "displayPrice" : "0.99", + "familyShareable" : false, + "internalID" : "FF5725DC", + "localizations" : [ + { + "description" : "", + "displayName" : "", + "locale" : "en_US" + } + ], + "productID" : "com.cooni.point1000", + "referenceName" : "1000 points", + "type" : "Consumable" + }, + { + "displayPrice" : "2.99", + "familyShareable" : false, + "internalID" : "47DD16EA", + "localizations" : [ + { + "description" : "", + "displayName" : "", + "locale" : "en_US" + } + ], + "productID" : "com.cooni.point5000", + "referenceName" : "5000 points", + "type" : "NonConsumable" + } + ], + "settings" : { + + }, + "subscriptionGroups" : [ + + ], + "version" : { + "major" : 1, + "minor" : 2 + } +} diff --git a/IapExample/ios/IapExample.xcodeproj/project.pbxproj b/IapExample/ios/IapExample.xcodeproj/project.pbxproj index 86fd3f4fc..4bbae8907 100644 --- a/IapExample/ios/IapExample.xcodeproj/project.pbxproj +++ b/IapExample/ios/IapExample.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 7699B88040F8A987B510C191 /* libPods-IapExample-IapExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-IapExample-IapExampleTests.a */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; + 8553967928B5A2D700E7E3CE /* Configuration.storekit in Resources */ = {isa = PBXBuildFile; fileRef = 8553967828B5A2D700E7E3CE /* Configuration.storekit */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -42,6 +43,7 @@ 5B7EB9410499542E8C5724F5 /* Pods-IapExample-IapExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-IapExample-IapExampleTests.debug.xcconfig"; path = "Target Support Files/Pods-IapExample-IapExampleTests/Pods-IapExample-IapExampleTests.debug.xcconfig"; sourceTree = ""; }; 5DCACB8F33CDC322A6C60F78 /* libPods-IapExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-IapExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = IapExample/LaunchScreen.storyboard; sourceTree = ""; }; + 8553967828B5A2D700E7E3CE /* Configuration.storekit */ = {isa = PBXFileReference; lastKnownFileType = text; path = Configuration.storekit; sourceTree = ""; }; 89C6BE57DB24E9ADA2F236DE /* Pods-IapExample-IapExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-IapExample-IapExampleTests.release.xcconfig"; path = "Target Support Files/Pods-IapExample-IapExampleTests/Pods-IapExample-IapExampleTests.release.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -92,6 +94,7 @@ 13B07FB61A68108700A75B9A /* Info.plist */, 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, 13B07FB71A68108700A75B9A /* main.m */, + 8553967828B5A2D700E7E3CE /* Configuration.storekit */, ); name = IapExample; sourceTree = ""; @@ -243,6 +246,7 @@ buildActionMask = 2147483647; files = ( 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, + 8553967928B5A2D700E7E3CE /* Configuration.storekit in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/IapExample/ios/IapExample.xcodeproj/xcshareddata/xcschemes/IapExample.xcscheme b/IapExample/ios/IapExample.xcodeproj/xcshareddata/xcschemes/IapExample.xcscheme index 84938ba74..c7beab13b 100644 --- a/IapExample/ios/IapExample.xcodeproj/xcshareddata/xcschemes/IapExample.xcscheme +++ b/IapExample/ios/IapExample.xcodeproj/xcshareddata/xcschemes/IapExample.xcscheme @@ -60,6 +60,9 @@ ReferencedContainer = "container:IapExample.xcodeproj"> + + false target 'IapExample' do diff --git a/IapExample/ios/Podfile.lock b/IapExample/ios/Podfile.lock index 9bbd26596..6b83d36bd 100644 --- a/IapExample/ios/Podfile.lock +++ b/IapExample/ios/Podfile.lock @@ -360,7 +360,7 @@ PODS: - React-Core - RNGestureHandler (2.5.0): - React-Core - - RNIap (8.6.5): + - RNIap (10.0.0): - React-Core - RNScreens (3.15.0): - React-Core @@ -575,12 +575,12 @@ SPEC CHECKSUMS: ReactCommon: e30ec17dfb1d4c4f3419eac254350d6abca6d5a2 RNCMaskedView: cb9670ea9239998340eaab21df13fa12a1f9de15 RNGestureHandler: bad495418bcbd3ab47017a38d93d290ebd406f50 - RNIap: e9f648d00e693913f80bbe5b661a5257fb72fe93 + RNIap: 6f4925d680b31ff5d252f982aad12c8b66200b31 RNScreens: 4a1af06327774490d97342c00aee0c2bafb497b7 SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 Yoga: 7ab6e3ee4ce47d7b789d1cb520163833e515f452 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: cfed50b11ea421296640e72457dcf62114e957f6 +PODFILE CHECKSUM: 47f330ba4aa0808e88cd2a085debf346af3dc659 COCOAPODS: 1.11.3 diff --git a/IapExample/src/screens/ClassSetup.tsx b/IapExample/src/screens/ClassSetup.tsx index 32ff51a4d..295a1e595 100644 --- a/IapExample/src/screens/ClassSetup.tsx +++ b/IapExample/src/screens/ClassSetup.tsx @@ -8,7 +8,6 @@ import { View, } from 'react-native'; import { - clearTransactionIOS, endConnection, finishTransaction, flushFailedPurchasesCachedAsPendingAndroid, @@ -65,17 +64,6 @@ export class ClassSetup extends Component<{}, State> { if (isAndroid) { await flushFailedPurchasesCachedAsPendingAndroid(); - } else { - /** - * WARNING This line should not be included in production code - * This call will call finishTransaction in all pending purchases - * on every launch, effectively consuming purchases that you might - * not have verified the receipt or given the consumer their product - * - * TL;DR you will no longer receive any updates from Apple on - * every launch for pending purchases - */ - await clearTransactionIOS(); } } catch (error) { if (error instanceof PurchaseError) { @@ -199,7 +187,7 @@ export class ClassSetup extends Component<{}, State> { {productList.map((product, index) => ( { >