The JCSubscriptionManager class provides a singleton that manages autorenewable subscriptions for an iOS app. It is a simple solution for apps with only one 'family' of autorenewable subscriptions.
JCSubscriptionManager uses the following:
- RMStore for app receipt verification (submodule).
- Lockbox for keychain storage (submodule).
- NSData+Base64 for base-64 encoding/decoding.
- Reachability for internet connectivity checking.
- MKStoreKit for inspiration.
ARC is required.
###Add to your project
-
Link
StoreKit.framework
,Security.framework
, andSystemConfiguration.framework
. -
Drag the
SubscriptionManager
,RMStore
,Lockbox
, andReachability
directories to your project. -
Add OpenSSL includes (from RMStore) to your Target's Header Search Paths, e.g.:
$(SRCROOT)/RMStore/RMStore/Optional/openssl-1.0.1e/include
-
Edit
ProductIdentifiers.plist
to include product identifiers for your autorenewable subscriptions. -
Edit
JCSubscriptionManagerConfigs.h
to customize settings. -
Add to app delegate's
-didFinishLaunching:withOptions:
[JCSubscriptionManager sharedManager];
###Set up server-side receipt verification Skip this step if your app supports only >= iOS 7, where the local app receipt is used for verification.
- Edit
<<YOUR APPLE APP SECRET>>
inverifyReceipt.php
to your autorenewable subscription shared secret (from iTunesConnect > Manage Your Apps > Manage In-App Purchases). - Upload
verifyReceipt.php
to your verification server, the one you list asOWN_VERIFICATION_SERVER
inJCSubscriptionManagerConfigs.h
.
###Get product data
Use this to populate your buy screen. Product data may not always be available (depending on connectivity) and the notification JCProductDataWasFetchedNotification
is sent on retrieval of product data.
- (NSArray *)products;
Also, a category on SKProduct to conveniently get a product's price formatted and localized.
- (NSString *)formattedPrice;
###Purchase a subscription
To purchase a subscription, use:
- (BOOL)buyProductWithIdentifier:(NSString *)productIdentifier
completion:(void (^)(BOOL success, NSError *transactionError))completion
error:(NSError *__autoreleasing *)pretransactionError;
This method returns NO if an error prevents the product being added to the payment queue.
You may also provide/remove access to subscription features by responding to the notifications JCSubscriptionWasMadeNotification
and JCSubscriptionExpiredNotification
, described below.
###Restore previous purchases
Restore previous transactions with:
- (BOOL)restorePreviousTransactionsWithCompletion:(void (^)(BOOL success, NSError *transactionError))completion
error:(NSError *__autoreleasing *)pretransactionError;
Again, this returns NO if the restore fails to start, and you will also be notified of changes in subscription status through the notifications described below.
###Check if user is subscribed
- (BOOL)isSubscriptionActive;
If you have multiple subscriptions in a 'family', this checks if any of them is active.
###Notifications
JCSubscriptionWasMadeNotification
: sent if an active subscription was verified when no previous subscription was found or a previous subscription lapsed.JCSubscriptionExpiredNotification
: sent if an active subscription has expired. JCSubscriptionManager will subsequently check if the subscription has been renewed.JCProductDataWasFetchedNotification
: sent when data on your subscriptions has been retrieved from iTunesConnect. This is when it is possible to populate your buy screen with info.
###Testing
Edit ProductIdentifiers.plist
and JCSubscriptionManagerConfigs.h
in the example project, upload verifyReceipt.php
to your server (for < iOS7), and run the example project on a physical device to test your subscriptions.
A few things to point out:
- You will need to create a Test User on iTunesConnect with which to make the sandbox purchases.
- 1 month subscriptions are 5 minutes long in the sandbox, 6 month subscriptions are 30 minutes long, etc.
- Subscriptions auto-renew a max of 6 times a day in the sandbox.
- Nearly-expired subscriptions get renewed when the app launches in the 24 hours prior to the expiration date. In the sandbox, this may be hard to replicate, and when a subscription expires JCSubscriptionManager tries to refresh the saved receipt to check for a renewal. However, there may be a lapses between expiration and renewal verification.
###License
Copyright 2014 Joseph Chen
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.