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

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

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

4 ответов


лучший способ получить покупку в приложении работающего for 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. для продукта id put tld.websitename.appname.referencename это будет работать лучше всего, так что, например, вы можете использовать com.jojodmo.blix.removeads
  8. выбрать cleared for sale и затем выберите ценовой уровень как 1 (99¢). Уровень 2 будет $ 1,99, а уровень 3 будет $2,99. Полный список доступен, если нажать view pricing matrix я рекомендую вам использовать уровень 1, потому что обычно это самое большое, что кто-либо когда-либо заплатит за удаление рекламы.
  9. нажмите синий add language кнопка и введите информацию. Это все будет показано клиенту, поэтому не ставьте ничего, что вы не хотите, чтобы они видели
  10. на hosting content with Apple выбрать нет
  11. вы можете оставить заметки обзора пустыми для Теперь.
  12. пропустить screenshot for review ПОКА, все, что мы пропустим, мы вернемся.
  13. Нажмите кнопку "Сохранить"

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

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

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

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

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

  3. создать другой .h файл с именем Bridge.h в главной папке проекта, затем перейдите в Диспетчер приложений (синий значок страницы, как), а затем выберите приложение в и нажмите кнопку Build Settings. Найдите опцию, которая говорит Swift Компилятор-Генерация Кода, а затем выберите Цель-C Мостовой Заголовок до 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.м. Этот файл будет называться " Your " в остальной части учебника.

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

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 файл и добавьте две кнопки, одна из которых говорит о покупке,а другая-о восстановлении. Подключить tapsRemoveAds IBAction к кнопке покупки, которую вы просто сделал, и то restore IBAction на кнопку "Восстановить". The 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!


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

вход: 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. The вся документация вполне понятно, если вы терпение, чтобы прочитать его,но несколько продвинулся в природе технической.

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

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-кнопка восстановления потока-используйте для этого restoreCompletedTransactions SKPaymentQueue-Шаг 3 позаботится об остальном, а также следующие методы SKPaymentTransactionObserver:

paymentQueueRestoreCompletedTransactionsFinished
restoreCompletedTransactionsFailedWithError

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

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