{"id":22065148,"url":"https://github.com/wilddylan/apkit","last_synced_at":"2025-05-13T01:16:09.763Z","repository":{"id":56900887,"uuid":"43044229","full_name":"wilddylan/APKit","owner":"wilddylan","description":"IAP framework!","archived":false,"fork":false,"pushed_at":"2018-10-22T03:08:58.000Z","size":578,"stargazers_count":159,"open_issues_count":0,"forks_count":23,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-13T01:16:00.731Z","etag":null,"topics":["iap"],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wilddylan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-09-24T04:11:58.000Z","updated_at":"2024-06-17T13:17:37.000Z","dependencies_parsed_at":"2022-08-20T18:20:40.771Z","dependency_job_id":null,"html_url":"https://github.com/wilddylan/APKit","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wilddylan%2FAPKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wilddylan%2FAPKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wilddylan%2FAPKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wilddylan%2FAPKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wilddylan","download_url":"https://codeload.github.com/wilddylan/APKit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253851075,"owners_count":21973674,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["iap"],"created_at":"2024-11-30T19:15:14.451Z","updated_at":"2025-05-13T01:16:09.742Z","avatar_url":"https://github.com/wilddylan.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"##APKit\n\n[![MIT Licence](https://badges.frapsoft.com/os/mit/mit.svg?v=103)](https://opensource.org/licenses/mit-license.php) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FWildDylan%2FAPKit.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FWildDylan%2FAPKit?ref=badge_shield)\n\n###### How to use\n\nThe under code block only for OS X:\n\n```objective-c\nif ( ![NSData dataWithContentsOfURL:[NSBundle mainBundle].appStoreReceiptURL] ) {\n  exit(173);\n}\n```\n\nCan be used in Objective-C or swift:\n\n```ruby\npod 'APKit', '~\u003e 0.3.1'\n```\n\nrun command `pod update --no-repo-update`.\n\nIn`AppDelegate.m`：\n\n```objective-c\n#import \u003cStoreKit/StoreKit.h\u003e\n#import \u003cAPKit/APKit.h\u003e\n```\n\n```objective-c\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n#warning Add transaction observer\n    [[SKPaymentQueue defaultQueue] addTransactionObserver:[APStoreObserver sharedInstance]];\n    \n    return YES;\n}\n```\n\n```objective-c\n- (void)applicationWillTerminate:(UIApplication *)application {\n#warning Remove transaction observer\n    [[SKPaymentQueue defaultQueue] removeTransactionObserver: [APStoreObserver sharedInstance]];\n}\n```\n\nSet result listener：\n\n```objective-c\n- (instancetype)init {\n    self = [super init];\n    if ( self ) {\n        [[NSNotificationCenter defaultCenter] addObserver:self\n                                                 selector:@selector(handleProductRequestNotification:)\n                                                     name:APProductRequestNotification\n                                                   object:[APProductManager sharedInstance]];\n        \n        [[NSNotificationCenter defaultCenter] addObserver:self\n                                                 selector:@selector(handlePurchasesNotification:)\n                                                     name:APPurchaseNotification\n                                                   object:[APStoreObserver sharedInstance]];\n    }\n    return self;\n}\n```\n\n`handleProductRequestNotification`will be fired when get response for product.\n\n`handlePurchasesNotification` will be fired when get response for purchase.\n\nRequest product with identifier:\n\n```objective-c\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    \n    NSArray *productIdentifiers = @[\n                                    @\"1994101101\",\n                                    @\"1994101102\",\n                                    @\"1994101103\"\n                                    ];\n    \n    APProductManager *productManager = [APProductManager sharedInstance];\n    [productManager\n     fetchProductInformationForIds:productIdentifiers];\n}\n```\n\n```objective-c\n-(void)handleProductRequestNotification: (NSNotification *)notification {\n    APProductManager *productRequestNotification = (APProductManager*)notification.object;\n    APProductRequestStatus result = (APProductRequestStatus)productRequestNotification.status;\n    \n    if (result == APProductRequestSuccess) {\n        NSLog(@\"VALID: %@\", productRequestNotification.availableProducts);\n        NSLog(@\"INVALID: %@\", productRequestNotification.invalidProductIds);\n    }\n}\n```\n\n![](http://ocef2grmj.bkt.clouddn.com/productResult)\n\n1994101103 is an invalid product identifier.\n\nPurchase：\n\n```objective-c\nNSArray *productArray = productRequestNotification.availableProducts;\nif ( productArray.count \u003e 0 ) {\n    SKProduct *product_1 = productArray.firstObject;\n  \n    APStoreObserver *storeObs = [APStoreObserver sharedInstance];\n    [storeObs buy:product_1];\n}\n```\n\n```objective-c\n#pragma mark - Handle purchase notification\n\n-(void)handlePurchasesNotification: (NSNotification *)notification {\n    APStoreObserver *purchasesNotification = (APStoreObserver *)notification.object;\n    APPurchaseStatus status = (APPurchaseStatus)purchasesNotification.status;\n    \n    switch ( status ) {\n#pragma - Purchase\n        case APPurchaseSucceeded: {\n            NSLog(@\"Purchase-Success: %@\", purchasesNotification.productsPurchased);\n            // Verify receipts step.\n            [self verifyReceipts];\n            break;\n        }\n        case APPurchaseFailed: {\n            NSLog(@\"Purchase-Failed %@\", purchasesNotification.errorMessage);\n            break;\n        }\n        case APPurchaseCancelled: {\n            NSLog(@\"Purchase-Cancelled!\");\n            break;\n        }\n#pragma - Restore\n        case APRestoredSucceeded: {\n            NSLog(@\"Restored-Success: %@\", purchasesNotification.productsRestored);\n            break;\n        }\n        case APRestoredFailed: {\n            NSLog(@\"Restored-Failed %@\", purchasesNotification.errorMessage);\n            break;\n        }\n        case APRestoredCancelled: {\n            NSLog(@\"Restored-Cancelled!\");\n            break;\n        }\n        default:\n            break;\n    }\n}\n```\n\nWatch for line 12, ` [self verifyReceipts];` it's important.\n\nVerify receipt：\n\nIf you get some error, try to use [SKReceiptRefreshRequest](https://developer.apple.com/reference/storekit/skreceiptrefreshrequest)。\n\n```objective-c\nNSURL *localReceiptURL = [[NSBundle mainBundle] appStoreReceiptURL];\nNSData *data = [NSData dataWithContentsOfURL:localReceiptURL];\nNSString *receiptStr = [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];\n```\n\nsend `receiptStr`to your server.\n\nAbout local receipt verify [local verify your receipt](https://github.com/WildDylan/iap-local-receipt).\n\nor use [go-iap-verify-receipt](https://github.com/awa/go-iap)\n\n###### Release note\n\n- 0.3.2: Update comments and add some documents, update license, remove unused files and folders.\n\n- 0.3.0, 0.3.1: Clean workspace, format code with 2 indent.\n- 0.2.0: Download Hosted content.\n- 0.1.0: basic features develope, initialized repo.\n\n###### ReadMe in cdn\n\n[APKit introduction](http://blog.devdylan.cn/APKit/)\n\n###### License\n\nMIT. \n\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FWildDylan%2FAPKit.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FWildDylan%2FAPKit?ref=badge_large)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwilddylan%2Fapkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwilddylan%2Fapkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwilddylan%2Fapkit/lists"}