Как добавить покупку в приложении к приложению iOS?


Как добавить покупку в приложении в приложение iOS? Что все детали и есть ли пример кода?

это должно быть уловка-все виды для того, как добавить в приложение покупки для iOS приложений

4 244

4 ответа:

лучший способ получить покупку в приложении работающего на iOS 10iOS 9, 8 and 7) в Xcode 5+ сделать следующее:

  1. перейти кitunes.connect.apple.com и войдите в систему
  2. клик My Apps затем нажмите на приложение, которое вы хотите добавить покупку в
  3. выберите Features заголовок, а затем выберите In-App Purchases слева
  4. выберите в середине
  5. для этого урока мы собираетесь добавить покупку в приложении, чтобы удалить рекламу, поэтому выберите non-consumable. Если бы вы собирались отправить физический элемент пользователю или дать им что-то, что они могут купить более одного раза, вы бы выбрали consumable.
  6. для имени ссылки, положите все, что вы хотите (но убедитесь, что вы знаете, что это такое)
  7. для идентификатора продукта put tld.websitename.appname.referencename это будет работать лучше, так, например, вы могли бы использовать com.jojodmo.blix.removeads
  8. выбрать cleared for sale а затем выберите ценовой уровень как 1 (99¢). Уровень 2 будет $ 1,99, а уровень 3 будет $2,99. Полный список доступен, если вы нажмете view pricing matrix я рекомендую вам использовать tier 1, потому что это, как правило, больше всего кто-либо будет платить за удаление рекламы.
  9. нажмите на синюю add language кнопка, и введите информацию. Это все будет показано клиенту, так что не ставьте ничего, что вы не хотите, чтобы они видели
  10. на hosting content with Apple выбрать нет
  11. вы можете оставить заметки обзора пустыми для Сейчас.
  12. пропустить screenshot for reviewПОКА, все, что мы пропустим, мы вернемся.
  13. Нажмите кнопку "Сохранить"

это может занять несколько часов для код продукта для регистрации в iTunesConnect, так что будьте терпеливы.

теперь, когда вы настроили информацию о покупке в приложении на iTunesConnect, перейдите в свой проект Xcode и перейдите в Диспетчер приложений (синий значок страницы вверху, где находятся ваши методы и заголовочные файлы) нажмите на свое приложение в разделе цели (должно быть первым), затем перейдите в раздел Общие. Внизу вы должны увидеть linked frameworks and libraries нажмите на маленький символ плюс и добавьте рамки StoreKit.framework если вы этого не сделаете, покупка в приложении будет не работать!

если вы используете Objective-C в качестве языка для вашего приложения, вы можете пропустить эти пять шагов. В противном случае, если вы используете Swift, выполните следующие действия:

  1. создать новый .h файл (заголовок) к собираюсь File>New>File... (команда ⌘+ N). Этот файл будет называться "ваш .h файл" в остальной части учебника

  2. при появлении запроса нажмите кнопку Создать Заголовок Моста. Это будет наш файл заголовка моста. Если ты не предложено перейти к шагу 3. Если вы are предложено пропустить Шаг 3 и перейти непосредственно к шагу 4.

  3. создать еще один .h файл с именем Bridge.h в главной папке проекта перейдите в Диспетчер приложений (синий значок, похожий на страницу), затем выберите приложение в и нажмите кнопку Build Settings. Найдите опцию, которая говорит Swift Компилятор-Генерация Кода, а затем выберите Objective-C Bridging Header до Bridge.h

  4. в файле заголовка моста добавьте строку #import "MyObjectiveCHeaderFile.h", где MyObjectiveCHeaderFile - это имя файла заголовка что вы создали на первом шаге. Так, например, если вы назвали свой заголовочный файл InAppPurchase.h, вы бы добавили строку #import "InAppPurchase.h" в файле header моста.

  5. создать новые методы Objective-C (.m) файл, перейдя в File>New>File... (команда ⌘+ N). Назовите его так же, как файл заголовка, созданный на шаге 1. Например, если вы вызвали файл на шаге 1 InAppPurchase.h, вы бы назвали этот новый файл InAppPurchase.м. Этот файл будет называться "ваш " в остальной части учебника.

теперь мы перейдем к фактическому кодированию. Добавьте следующий код в код .h file:

BOOL areAdsRemoved;

- (IBAction)restore;
- (IBAction)tapsRemoveAds;

Далее вам нужно импортировать StoreKit рамки на ваш .m файл, а также добавить SKProductsRequestDelegate и SKPaymentTransactionObserver после @interface объявление:

#import <StoreKit/StoreKit.h>

//put the name of your view controller in place of MyViewController
@interface MyViewController() <SKProductsRequestDelegate, SKPaymentTransactionObserver>

@end

@implementation MyViewController //the name of your view controller (same as above)
  //the code below will be added here
@end

а теперь добавьте в свой .m файл, эта часть усложняется, поэтому я предлагаю вам прочитать комментарии в коде:

//If you have more than one in-app purchase, you can define both of
//of them here. So, for example, you could define both kRemoveAdsProductIdentifier
//and kBuyCurrencyProductIdentifier with their respective product ids
//
//for this example, we will only use one product

#define kRemoveAdsProductIdentifier @"put your product id (the one that we just made in iTunesConnect) in here"

- (IBAction)tapsRemoveAds{
    NSLog(@"User requests to remove ads");

    if([SKPaymentQueue canMakePayments]){
        NSLog(@"User can make payments");

        //If you have more than one in-app purchase, and would like
        //to have the user purchase a different product, simply define 
        //another function and replace kRemoveAdsProductIdentifier with 
        //the identifier for the other product

        SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:kRemoveAdsProductIdentifier]];
        productsRequest.delegate = self;
        [productsRequest start];

    }
    else{
        NSLog(@"User cannot make payments due to parental controls");
        //this is called the user cannot make payments, most likely due to parental controls
    }
}

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    SKProduct *validProduct = nil;
    int count = [response.products count];
    if(count > 0){
        validProduct = [response.products objectAtIndex:0];
        NSLog(@"Products Available!");
        [self purchase:validProduct];
    }
    else if(!validProduct){
        NSLog(@"No products available");
        //this is called if your product id is not valid, this shouldn't be called unless that happens.
    }
}

- (void)purchase:(SKProduct *)product{
    SKPayment *payment = [SKPayment paymentWithProduct:product];

    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

- (IBAction) restore{
    //this is called when the user restores purchases, you should hook this up to a button
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}

- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
    NSLog(@"received restored transactions: %i", queue.transactions.count);
    for(SKPaymentTransaction *transaction in queue.transactions){
        if(transaction.transactionState == SKPaymentTransactionStateRestored){
            //called when the user successfully restores a purchase
            NSLog(@"Transaction state -> Restored");

            //if you have more than one in-app purchase product,
            //you restore the correct product for the identifier.
            //For example, you could use
            //if(productID == kRemoveAdsProductIdentifier)
            //to get the product identifier for the
            //restored purchases, you can use
            //
            //NSString *productID = transaction.payment.productIdentifier;
            [self doRemoveAds];
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            break;
        }
    }   
}

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
    for(SKPaymentTransaction *transaction in transactions){
        //if you have multiple in app purchases in your app,
        //you can get the product identifier of this transaction
        //by using transaction.payment.productIdentifier
        //
        //then, check the identifier against the product IDs
        //that you have defined to check which product the user
        //just purchased            

        switch(transaction.transactionState){
            case SKPaymentTransactionStatePurchasing: NSLog(@"Transaction state -> Purchasing");
                //called when the user is in the process of purchasing, do not add any of your own code here.
                break;
            case SKPaymentTransactionStatePurchased:
            //this is called when the user has successfully purchased the package (Cha-Ching!)
                [self doRemoveAds]; //you can add your code for what you want to happen when the user buys the purchase here, for this tutorial we use removing ads
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                NSLog(@"Transaction state -> Purchased");
                break;
            case SKPaymentTransactionStateRestored:
                NSLog(@"Transaction state -> Restored");
                //add the same code as you did from SKPaymentTransactionStatePurchased here
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
            case SKPaymentTransactionStateFailed:
                //called when the transaction does not finish
                if(transaction.error.code == SKErrorPaymentCancelled){
                    NSLog(@"Transaction state -> Cancelled");
                    //the user cancelled the payment ;(
                }
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
        }
    }
}

теперь вы хотите добавить свой код для того, что произойдет, когда пользователь завершит транзакцию, для этого урока мы используем удаление добавлений, вам нужно будет добавить свой собственный код для того, что произойдет, когда загрузится баннер.

- (void)doRemoveAds{
    ADBannerView *banner;
    [banner setAlpha:0];
    areAdsRemoved = YES;
    removeAdsButton.hidden = YES;
    removeAdsButton.enabled = NO;
    [[NSUserDefaults standardUserDefaults] setBool:areAdsRemoved forKey:@"areAdsRemoved"];
    //use NSUserDefaults so that you can load whether or not they bought it
    //it would be better to use KeyChain access, or something more secure
    //to store the user data, because NSUserDefaults can be changed.
    //You're average downloader won't be able to change it very easily, but
    //it's still best to use something more secure than NSUserDefaults.
    //For the purpose of this tutorial, though, we're going to use NSUserDefaults
    [[NSUserDefaults standardUserDefaults] synchronize];
}

если у вас нет рекламы в приложении, вы можете используйте любую другую вещь, которую вы хотите. Например, мы могли бы сделать цвет фона синий. Для этого мы хотели бы использовать:

- (void)doRemoveAds{
    [self.view setBackgroundColor:[UIColor blueColor]];
    areAdsRemoved = YES
    //set the bool for whether or not they purchased it to YES, you could use your own boolean here, but you would have to declare it in your .h file

    [[NSUserDefaults standardUserDefaults] setBool:areAdsRemoved forKey:@"areAdsRemoved"];
    //use NSUserDefaults so that you can load wether or not they bought it
    [[NSUserDefaults standardUserDefaults] synchronize];
}

теперь, где-то в вашем viewDidLoad метод, вы хотите добавить следующий код:

areAdsRemoved = [[NSUserDefaults standardUserDefaults] boolForKey:@"areAdsRemoved"];
[[NSUserDefaults standardUserDefaults] synchronize];
//this will load wether or not they bought the in-app purchase

if(areAdsRemoved){
    [self.view setBackgroundColor:[UIColor blueColor]];
    //if they did buy it, set the background to blue, if your using the code above to set the background to blue, if your removing ads, your going to have to make your own code here
}

теперь, когда вы добавили весь код, зайдите в .xib или storyboard файл и добавьте две кнопки, одна из которых говорит о покупке, а другая-о восстановлении. Подключи tapsRemoveAdsIBAction к кнопке покупки, что вы просто сделал, а то restoreIBAction на кнопку "Восстановить". Элемент restore действие будет проверять, если пользователь ранее купил покупку в приложении, и дать им покупку в приложении бесплатно, если они еще не имеют его.

Далее переходим в iTunesConnect и нажмите кнопку Users and Roles выберите Sandbox Testers заголовок, а затем нажмите кнопку + символ слева, где он говорит Testers. Вы можете просто положить в случайные вещи для имени и фамилии, и электронная почта делает не обязательно быть реальным - вы просто должны быть в состоянии запомнить его. Введите пароль (который вам придется запомнить) и заполните остальную информацию. Я бы рекомендовал вам сделать Date of Birth дата, которая сделает пользователей старше 18 лет. App Store Territoryи чтобы быть в правильной стране. Затем выйдите из существующей учетной записи iTunes (вы можете войти обратно после этого урока).

теперь запустите приложение на устройстве iOS, Если вы попытаетесь запустить его на симуляторе, покупка будет всегда ошибки, вы ОБЯЗАТЕЛЬНО запустите его на своем устройстве iOS. Как только приложение запущено, нажмите кнопку "Заказать". Когда вам будет предложено войти в свою учетную запись iTunes, войдите в систему как тестовый пользователь, который мы только что создали. Затем, когда он попросит вас подтвердить покупку 99¢ или что бы вы ни установили ценовой уровень, СДЕЛАЙТЕ СНИМОК ЭКРАНА ИЗ НЕГО это то, что вы собираетесь использовать для вашего screenshot for review на iTunesConnect. Теперь отмените платеж.

теперь иди к iTunesConnect, затем перейдите к My Apps>the app you have the In-app purchase on>In-App Purchases. Затем щелкните свою покупку в приложении и нажмите кнопку Изменить в разделе Сведения о покупке в приложении. Как только вы это сделаете, импортируйте фотографию, которую вы только что взяли на свой iPhone, в свой компьютер и загрузите ее в качестве скриншота для обзора, а затем в примечаниях к обзору поместите свой ТЕСТОВЫЙ ПОЛЬЗОВАТЕЛЬ электронная почта и пароль. Это поможет Apple в процессе обзора.

после того, как вы сделав это, вернитесь в приложение на своем устройстве iOS, все еще войдите в систему как тестовая учетная запись пользователя и нажмите кнопку покупки. На этот раз подтвердите оплату не волнуйтесь, это не будет взимать с вашего счета никаких денег, тестовые учетные записи пользователей получить все покупки в приложении бесплатно после подтверждения оплаты, убедитесь, что то, что происходит, когда пользователь покупает ваш продукт на самом деле происходит. Если это не так, то это будет ошибка с вашим doRemoveAds метод. Опять Же, Я рекомендуется использовать изменение фона на синий для тестирования покупки в приложении,это не должно быть вашей фактической покупкой в приложении. Если все работает и вы хорошо идти! Просто убедитесь, что вы включили покупку в приложении в свой новый двоичный файл, Когда вы загружаете его в iTunesConnect!


вот некоторые распространенные ошибки:

Logged:No Products Available

это может означать три вещи:

  • вы не ставили правильный идентификатор покупки в приложении в вашем коде (для идентификатора kRemoveAdsProductIdentifier в приведенном выше коде
  • вы не очистили свою покупку в приложении для продажи на iTunesConnect
  • вы не ждали, пока идентификатор покупки в приложении будет зарегистрирован в iTunesConnect. Подождите пару часов от создания ID, и ваша проблема должна быть решена.
  • вы не завершили заполнение ваших соглашений, налогов и банковских операций информация.

если он не работает в первый раз, не расстраивайтесь! Не сдавайся! Это заняло у меня около 5 часов подряд, прежде чем я смог получить эту работу, и около 10 часов искать правильный код! Если использовать код выше, он должен работать нормально. Не стесняйтесь комментировать, если у вас есть какие-либо вопросы на всех.

я надеюсь, что это поможет всем тем, кто надеется добавить покупку в приложении к своему приложению iOS. Ура!

просто переведите код Jojodmo в Swift:

class InAppPurchaseManager: NSObject , SKProductsRequestDelegate, SKPaymentTransactionObserver{





//If you have more than one in-app purchase, you can define both of
//of them here. So, for example, you could define both kRemoveAdsProductIdentifier
//and kBuyCurrencyProductIdentifier with their respective product ids
//
//for this example, we will only use one product

let kRemoveAdsProductIdentifier = "put your product id (the one that we just made in iTunesConnect) in here"

@IBAction func tapsRemoveAds() {

    NSLog("User requests to remove ads")

    if SKPaymentQueue.canMakePayments() {
        NSLog("User can make payments")

        //If you have more than one in-app purchase, and would like
        //to have the user purchase a different product, simply define
        //another function and replace kRemoveAdsProductIdentifier with
        //the identifier for the other product
        let set : Set<String> = [kRemoveAdsProductIdentifier]
        let productsRequest = SKProductsRequest(productIdentifiers: set)
        productsRequest.delegate = self
        productsRequest.start()

    }
    else {
        NSLog("User cannot make payments due to parental controls")
        //this is called the user cannot make payments, most likely due to parental controls
    }
}


func purchase(product : SKProduct) {

    let payment = SKPayment(product: product)
    SKPaymentQueue.defaultQueue().addTransactionObserver(self)
    SKPaymentQueue.defaultQueue().addPayment(payment)
}

func restore() {
    //this is called when the user restores purchases, you should hook this up to a button
    SKPaymentQueue.defaultQueue().addTransactionObserver(self)
    SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
}


func doRemoveAds() {
    //TODO: implement
}

/////////////////////////////////////////////////
//////////////// store delegate /////////////////
/////////////////////////////////////////////////
// MARK: - store delegate -


func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {

    if let validProduct = response.products.first {
        NSLog("Products Available!")
        self.purchase(validProduct)
    }
    else {
        NSLog("No products available")
        //this is called if your product id is not valid, this shouldn't be called unless that happens.
    }
}

func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {


    NSLog("received restored transactions: \(queue.transactions.count)")
    for transaction in queue.transactions {
        if transaction.transactionState == .Restored {
            //called when the user successfully restores a purchase
            NSLog("Transaction state -> Restored")

            //if you have more than one in-app purchase product,
            //you restore the correct product for the identifier.
            //For example, you could use
            //if(productID == kRemoveAdsProductIdentifier)
            //to get the product identifier for the
            //restored purchases, you can use
            //
            //NSString *productID = transaction.payment.productIdentifier;
            self.doRemoveAds()
            SKPaymentQueue.defaultQueue().finishTransaction(transaction)
            break;
        }
    }
}


func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {

    for transaction in transactions {
        switch transaction.transactionState {
        case .Purchasing: NSLog("Transaction state -> Purchasing")
            //called when the user is in the process of purchasing, do not add any of your own code here.
        case .Purchased:
            //this is called when the user has successfully purchased the package (Cha-Ching!)
            self.doRemoveAds() //you can add your code for what you want to happen when the user buys the purchase here, for this tutorial we use removing ads
            SKPaymentQueue.defaultQueue().finishTransaction(transaction)
            NSLog("Transaction state -> Purchased")
        case .Restored:
            NSLog("Transaction state -> Restored")
            //add the same code as you did from SKPaymentTransactionStatePurchased here
            SKPaymentQueue.defaultQueue().finishTransaction(transaction)
        case .Failed:
            //called when the transaction does not finish
            if transaction.error?.code == SKErrorPaymentCancelled {
                NSLog("Transaction state -> Cancelled")
                //the user cancelled the payment ;(
            }
            SKPaymentQueue.defaultQueue().finishTransaction(transaction)
        case .Deferred:
            // The transaction is in the queue, but its final status is pending external action.
            NSLog("Transaction state -> Deferred")

        }


    }
}
} 

RMStore это легкая библиотека iOS для покупок в приложении. Он обертывает StoreKit API и предоставляет вам удобные блоки для асинхронных запросов. Приобретение продукта так же просто, как вызов одного метода.

для продвинутых пользователей эта библиотека также обеспечивает проверку получения, загрузку содержимого и сохраняемость транзакций.

Я знаю, что я довольно поздно, чтобы опубликовать это, но я разделяю подобный опыт, когда я узнал веревки модели IAP.

in-app purchase является одним из самых полных рабочих процессов в iOS, реализованных Storekit framework. Элемент вся документация вполне понятно, если вы терпение, чтобы прочитать его, но несколько продвинутый в характере формальности.

подведем итоги:

1-запрос продуктов-используйте SKProductRequest & SKProductRequestDelegate классы для выдачи запроса на идентификаторы продуктов и получения их обратно из вашего собственного магазина itunesconnect.

эти SKProducts должны использоваться для заполнения пользовательского интерфейса вашего магазина, который пользователь может использовать для покупки определенного продукта.

2-выдать платежный запрос-используйте SKPayment & SKPaymentQueue, чтобы добавить платеж в очередь транзакций.

3-мониторинг очереди транзакций для обновления состояния-используйте метод updatedTransactions протокола SKPaymentTransactionObserver для мониторинга статус:

SKPaymentTransactionStatePurchasing - don't do anything
SKPaymentTransactionStatePurchased - unlock product, finish the transaction
SKPaymentTransactionStateFailed - show error, finish the transaction
SKPaymentTransactionStateRestored - unlock product, finish the transaction

4-кнопка восстановления потока-используйте skpaymentqueue restoreCompletedTransactions для достижения этой цели-Шаг 3 позаботится об остальном, наряду со следующими методами SKPaymentTransactionObserver:

paymentQueueRestoreCompletedTransactionsFinished
restoreCompletedTransactionsFailedWithError

здесь это пошаговый учебник (написанный мной в результате моих собственных попыток понять его), который объясняет это. В конце он также предоставляет пример кода, который можно непосредственно использовать.

здесь is еще один я создал, чтобы объяснить некоторые вещи, которые только текст может описать лучше.