Comment ajouter un achat intégré à une application iOS?

Comment ajouter un achat intégré à une application iOS? Quels sont tous les détails et y a-t-il un exemple de code?

Ceci est censé être un fourre-tout pour savoir comment ajouter des achats intégrés aux applications iOS

244
demandé sur Jojodmo 2013-10-24 07:24:07

4 réponses

La meilleure façon d'obtenir un achat in-app travailler pour iOS 10 (et iOS 9, 8 and 7) dans Xcode 5+ est de faire ce qui suit:

  1. Aller itunes.connect.apple.com et connectez -
  2. Sur My Apps, puis cliquez sur l'application que vous voulez ajouter l'achat de
  3. cliquez sur l'en-tête Features, puis sélectionnez In-App Purchases à gauche
  4. cliquez sur l'icône + au milieu
  5. pour ce tutoriel, nous allons ajouter un achat in-app pour supprimer les annonces, alors choisissez non-consumable. Si vous deviez envoyer un article physique à l'utilisateur, ou lui donner quelque chose qu'il peut acheter plus d'une fois, vous choisiriez consumable.
  6. pour le nom de référence, mettez ce que vous voulez (mais assurez-vous de savoir ce que c'est)
  7. pour l'id de produit Mettre tld.websitename.appname.referencename cela fonctionnera le mieux, donc par exemple, vous pouvez utiliser com.jojodmo.blix.removeads
  8. Choisissez cleared for sale, puis choisissez le niveau de prix 1 (99¢). Niveau 2 serait à 1,99$, et le niveau 3 serait de 2,99$. La liste complète est disponible si vous cliquez sur view pricing matrix je vous recommande d'utiliser tier 1, parce que c'est généralement le plus que tout le monde va jamais payer pour supprimer les annonces.
  9. cliquez sur le bouton bleu add language et saisissez les informations. Tout cela sera montré au client, alors ne mettez rien que vous ne voulez pas voir
  10. Pour hosting content with Apple choisissez non
  11. Vous pouvez laisser les notes de révision en blanc pour l'instant .
  12. sauter le screenshot for review pour l'instant , tout ce que nous sautons nous reviendrons.
  13. cliquez 'enregistrer'

Cela peut prendre quelques heures pour que votre ID de produit s'inscrive dans iTunesConnect, alors soyez patient.

Maintenant que vous avez configuré vos informations d'achat in-app sur iTunesConnect, accédez à votre projet Xcode et accédez au gestionnaire d'applications (icône de type page bleue en haut de l'emplacement de vos méthodes et fichiers d'en-tête). En bas, vous devriez voir linked frameworks and libraries cliquer sur le petit symbole plus et ajouter le cadre StoreKit.framework Si vous ne le faites pas, l'achat in-app sera PAS travail!

Si vous utilisez Objective-C comme langue pour votre application, vous pouvez ignorer ces cinq étapes. Sinon, si vous utilisez Swift, procédez comme suit:

  1. Créer un nouveau .h (en-tête) du fichier en allant à File > New > File... (Commande ⌘ + N). Ce fichier sera appelé "Votre .h fichier" dans le reste du tutoriel

  2. Quand lorsque vous y êtes invité, cliquez sur créer un en-tête de pontage. Ce sera notre fichier d'en-tête de pontage. Si vous n'êtes pas invité à , passez à l'étape 3. Si vous êtes invité à , ignorez l'étape 3 et passez directement à l'étape 4.

  3. Créez un autre fichier .h nommé Bridge.h dans le dossier principal du projet, puis accédez au gestionnaire D'applications (l'icône de type page bleue), puis sélectionnez votre application dans la section Targets et cliquez sur Build Settings. Trouvez l'option qui dit Swift compilateur-Code Génération, puis définissez la Objective-C de Transition de l'en-Tête option pour Bridge.h

  4. Dans votre fichier d'en-tête de pontage, ajoutez la ligne #import "MyObjectiveCHeaderFile.h", où MyObjectiveCHeaderFile est le nom du fichier d'en-tête que vous avez créé à la première étape. Ainsi, par exemple, si vous avez nommé votre fichier d'en-tête InAppPurchase.h , vous ajouteriez la ligne #import "InAppPurchase.h" à votre fichier d'en-tête de pont.

  5. Créer un nouvel Objectif-Méthodes C (.m) fichier en allant à File > New > File... (Commande ⌘ + N). Nommez-le comme le fichier d'en-tête que vous avez créé à l'étape 1. Par exemple, si vous avez appelé le fichier à l'étape 1 InAppPurchase.h , vous appelleriez ce nouveau fichier InAppPurchase.m . Ce fichier sera appelé "Votre .m fichier" dans le reste du tutoriel.

Maintenant, nous allons entrer dans le codage réel. Ajoutez le code suivant dans votre fichier .h:

BOOL areAdsRemoved;

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

Ensuite, vous devez importer le cadre StoreKit dans votre .m fichier, ainsi que d'ajouter SKProductsRequestDelegate et SKPaymentTransactionObserver après votre @interface déclaration:

#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

Et maintenant ajoutez ce qui suit dans votre fichier .m, cette partie se complique, donc je vous suggère de lire les commentaires dans le code:

//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;
        }
    }
}

Maintenant, vous voulez ajouter votre code pour ce qui va se passer lorsque l'utilisateur termine la transaction, pour ce tutoriel, nous utilisons la suppression ajoute, vous devrez ajouter votre propre code pour ce qui se passe quand la bannière de vue des charges.

- (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];
}

Si vous n'avez pas annonces dans votre application, vous pouvez utiliser tout autre chose que vous souhaitez. Par exemple, nous pourrions rendre la couleur de l'arrière-plan bleue. Pour ce faire, nous voudrions utiliser:

- (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];
}

Maintenant, quelque part dans votre viewDidLoad méthode, vous allez ajouter le code suivant:

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
}

Maintenant que vous avez ajouté tout le code, allez dans votre fichier .xib ou storyboard, et ajoutez deux boutons, l'un disant achat, et l'autre disant restauration. Branchez le tapsRemoveAds IBAction pour le bouton d'achat que vous venez fait, et le restore IBAction sur le bouton Restaurer. L'action restore vérifiera si l'Utilisateur a déjà acheté l'achat in-app, et lui donnera l'achat in-app gratuitement s'il ne l'a pas déjà.

Ensuite, allez dans iTunesConnect , et cliquez sur Users and Roles puis cliquez sur l'en-tête Sandbox Testers, puis cliquez sur le symbole + à gauche où il est écrit Testers. Vous pouvez simplement mettre des choses au hasard pour le prénom et le nom, et l'e-mail ne doit pas être réel-vous venez devez être capable de vous en souvenir. Mettez un mot de passe (dont vous devrez vous souvenir) et remplissez le reste de l'information. Je vous recommande de faire le Date of Birth une date qui rendrait l'utilisateur 18 ou plus. App Store Territory A pour être dans le bon pays. Ensuite, déconnectez-vous de votre compte iTunes existant (vous pouvez vous reconnecter après ce tutoriel).

Maintenant, vous pouvez exécuter votre application sur votre appareil iOS, si vous essayer de l'exécuter sur le simulateur, l'achat toujours erreur, vous doivent l'exécuter sur votre appareil iOS. Une fois l'application en cours d'exécution, appuyez sur le bouton d'achat. Lorsque vous êtes invité à vous connecter à votre compte iTunes, connectez-vous en tant qu'utilisateur de test que nous venons de créer. Ensuite, quand il vous demande de confirmer l'achat de 99¢ ou tout ce que vous définissez le niveau de prix aussi, prenez un instantané de L'écran {[97] } c'est ce que vous allez utiliser pour votre screenshot for review sur iTunesConnect. Maintenant, annulez le paiement.

Maintenant, allez à la iTunesConnect, puis aller à My Apps > the app you have the In-app purchase on > In-App Purchases. Cliquez ensuite sur votre achat in-app et cliquez sur modifier sous l'in-app achat. Une fois que vous avez fait cela, importer la photo que vous venez de prendre sur votre iPhone dans votre ordinateur, et télécharger que la capture d'écran pour examen, puis, dans les notes d'examen, mettre votre utilisateur de TEST e-mail et mot de passe. Cela aidera apple dans le processus d'examen.

Après avoir fait cela, revenez sur l'application de votre appareil iOS, toujours connecté en tant que compte d'utilisateur de test, et cliquez sur bouton d'achat. Cette fois, confirmez le paiement ne vous inquiétez pas, cela ne facturera pas votre compte D'argent, testez les comptes d'utilisateurs obtenez tous les achats in-app gratuitement après avoir confirmé le paiement, assurez-vous que ce qui se passe lorsque l'utilisateur achète votre produit se produit réellement. Si ce n'est pas le cas, alors ce sera une erreur avec votre méthode doRemoveAds. Encore une fois, je recommande d'utiliser changer l'arrière-plan en bleu pour tester l'achat in-app, cela ne devrait pas être votre achat in-app réel bien. Si tout fonctionne et que vous êtes prêt à partir! Juste assurez-vous d'inclure l'achat in-app dans votre nouveau binaire lorsque vous téléchargez à iTunesConnect!


Voici quelques erreurs courantes:

Connecté: No Products Available

, Cela pourrait signifier trois choses:

  • Vous n'avez pas mis le bon d'achat dans l'application ID dans votre code (pour l'identificateur kRemoveAdsProductIdentifier dans le code ci-dessus
  • Vous n'avez pas effacé votre achat in-app à vendre sur iTunesConnect
  • Vous N'avez pas attendu que l'ID d'achat intégré soit enregistré dans iTunesConnect . Attendez quelques heures à partir de la création de l'ID, et votre problème devrait être résolu.
  • Vous n'avez pas rempli vos accords, vos informations fiscales et bancaires.

Si cela ne fonctionne pas la première fois, ne soyez pas frustré! N'abandonnez pas! Il m "a fallu environ 5 heures d" affilée avant de pouvoir obtenir ce travail, et environ 10 heures à la recherche du droit le code! Si vous utilisez exactement le code ci-dessus, cela devrait fonctionner correctement. N'hésitez pas à commenter si vous avez des questions tous.

J'espère que cela aidera tous ceux qui espèrent ajouter un achat in-app à leur application iOS. À votre santé!

532
répondu Jojodmo 2017-07-13 00:20:36

Traduisez simplement le code Jojodmo en 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")

        }


    }
}
} 
12
répondu Yedidya Reiss 2016-02-28 18:37:01

RMStore est une bibliothèque iOS légère pour les achats intégrés. Il enveloppe L'API StoreKit et vous fournit des blocs pratiques pour les demandes asynchrones. L'achat d'un produit est aussi facile que d'appeler une seule méthode.

Pour les utilisateurs avancés, cette bibliothèque fournit également la vérification des reçus, les téléchargements de contenu et la persistance des transactions.

4
répondu Vladimir Grigorov 2016-01-30 13:15:54

Je sais que je suis assez en retard pour poster ceci, mais je partage une expérience similaire quand j'ai appris les ficelles du modèle IAP.

In-app purchase est l'un des flux de travail les plus complets dans iOS implémenté par Storekit framework. La documentation entière est assez claire si vous avez de la patience pour la lire, mais est quelque peu Avancée dans la nature de la technicité.

Pour résumer:

1-Demande les produits-utilisez les classes SKProductRequest & SKProductRequestDelegate pour émettre une demande pour ID de produit et de les recevoir à partir de votre propre magasin itunesconnect.

Ces SKProducts doivent être utilisés pour remplir l'interface utilisateur de votre magasin que l'utilisateur peut utiliser pour acheter un produit spécifique.

2-émettre une demande de paiement-utilisez SKPayment & SKPaymentQueue pour ajouter un paiement à la file d'attente des transactions.

3-surveiller la file d'attente des transactions pour la mise à jour de l'état-utilisez la méthode updatedTransactions du protocole skpaymenttransactionobserver pour surveiller l'état:

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

4-bouton de restauration flux-utiliser RestoreCompletedTransactions de SKPaymentQueue pour accomplir ceci-l'étape 3 prendra soin du reste, avec les méthodes suivantes de SKPaymentTransactionObserver:

paymentQueueRestoreCompletedTransactionsFinished
restoreCompletedTransactionsFailedWithError

Voici un tutoriel étape par étape (écrit par moi à la suite de mes propres tentatives pour le comprendre) qui l'explique. À la fin, il fournit également un exemple de code que vous pouvez utiliser directement.

Voici un autre que j'ai créé pour expliquer certaines choses que seul le texte pourrait mieux décrire manière.

0
répondu Nirav Bhatt 2015-06-28 17:29:01