web-dev-qa-db-fra.com

Comment vérifier l'achat d'applications ACHAT Auto Renewable Subscription est valide

Je cherche à mettre en œuvre les nouveaux abonnements automatiques renouvelables à l'aide de l'achat d'applications, mais je ne sais pas comment ou quand vérifier si l'utilisateur est actuellement souscrit. Ma compréhension est que lorsque l'utilisateur abonna initialement à l'application peut utiliser la date d'achat avec la date d'abonnement pour calculer la durée de la durée de leur abonnement. Que se passe-t-il après cette date? Comment vérifions-nous si l'utilisateur a automatiquement renouvelé ou annulé?

Si j'utilise restoreCompletedTransactions pour obtenir une transaction et une réception pour chaque renouvellement, l'utilisateur sera invité à entrer son mot de passe iTunes. Cela signifie-t-il que s'ils ont acheté une abonnement de 7 jours, ils devront entrer leur mot de passe tous les 7 jours lorsque l'application vérifie si l'abonnement est toujours valide?

31
Adam Swinden

Si vous souhaitez le vérifier à partir d'un serveur Web, vous pingez leur API et il renvoie le statut de l'abonnement et des informations renouvelables automatiques sur le dernier paiement.

Si vous êtes sur l'appareil, vous devez probablement appeler des installations de restauration de restauration que je devine demander le mot de passe.

Je ne vois aucune autre méthode. Je suppose que de l'appareil que vous pouvez vérifier l'abonnement en contactant le même service Web utilisé sur le côté serveur? Je ne sais pas comment les avantages et les inconvénients de cela.

9
Dobes Vandermeer

Aujourd'hui, j'ai des problèmes avec ce problème.

Suivre Apple doc ici, j'ai utilisé ce moyen de vérifier que l'abonnement est expiré ou non. Mon idée: utilisateur Apple REST Réponse de l'API: (Demande de requête + Temps expiré) pour vérifier expiré ou non

+ (BOOL)checkInAppPurchaseStatus
{
    // Load the receipt from the app bundle.
    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
    if (receipt) {
        BOOL sandbox = [[receiptURL lastPathComponent] isEqualToString:@"sandboxReceipt"];
        // Create the JSON object that describes the request
        NSError *error;
        NSDictionary *requestContents = @{
                                          @"receipt-data": [receipt base64EncodedStringWithOptions:0],@"password":@"SHARE_SECRET_CODE"
                                          };
        NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                              options:0
                                                                error:&error];

        if (requestData) {
            // Create a POST request with the receipt data.
            NSURL *storeURL = [NSURL URLWithString:@"https://buy.iTunes.Apple.com/verifyReceipt"];
            if (sandbox) {
                storeURL = [NSURL URLWithString:@"https://sandbox.iTunes.Apple.com/verifyReceipt"];
            }
            NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
            [storeRequest setHTTPMethod:@"POST"];
            [storeRequest setHTTPBody:requestData];

            BOOL rs = NO;
            //Can use sendAsynchronousRequest to request to Apple API, here I use sendSynchronousRequest
            NSError *error;
            NSURLResponse *response;
            NSData *resData = [NSURLConnection sendSynchronousRequest:storeRequest returningResponse:&response error:&error];
            if (error) {
                rs = NO;
            }
            else
            {
                NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:resData options:0 error:&error];
                if (!jsonResponse) {
                    rs = NO;
                }
                else
                {
                    NSLog(@"jsonResponse:%@", jsonResponse);

                    NSDictionary *dictLatestReceiptsInfo = jsonResponse[@"latest_receipt_info"];
                    long long int expirationDateMs = [[dictLatestReceiptsInfo valueForKeyPath:@"@max.expires_date_ms"] longLongValue];
                    long long requestDateMs = [jsonResponse[@"receipt"][@"request_date_ms"] longLongValue];
                    NSLog(@"%lld--%lld", expirationDateMs, requestDateMs);
                    rs = [[jsonResponse objectForKey:@"status"] integerValue] == 0 && (expirationDateMs > requestDateMs);
                }
            }
            return rs;
        }
        else
        {
            return NO;
        }
    }
    else
    {
        return NO;
    }
}

J'espère que cette aide.

16
Clover03ti05

Mieux vaut utiliser une solution locale avant de faire appel à l'API Apple. Chaque fois que l'application fonctionne, c'est une bonne pratique pour valider le reçu local et si vous devez vérifier si un utilisateur dispose de l'abonnement actif, vous pouvez d'abord récupérer les achats à partir du reçu local et savoir que l'achat est toujours actif pour aujourd'hui. .

J'ai mis en place une petite bibliothèque écrite dans Swift pour simplifier de travailler avec la réception intégrée localement. Vous pouvez facilement extraire l'objet qui représente le reçu (InAppReceipt) et récupérer un achat actif/tous les achats.

N'hésitez pas à utiliser. link github

Voici un exemple de résolution de votre problème:

import TPInAppReceipt

do {
    let receipt = try InAppReceiptManager.shared.receipt()

    //retrive active auto renewable subscription for a specific product and date
    let purchase = receipt.activeAutoRenewableSubscriptionPurchases(ofProductIdentifier: "ProductName", forDate: Date())

    //retrive all auto renewable subscription purchases for a specific product
    let allAutoRenewableSubscriptionPurchases = receipt.purchases(ofProductIdentifier: "productName").filter({ return $0.isRenewableSubscription })
} catch {
    print(error)
}
5
tikhop

Je commence une campagne autour de cette question. Voici mon observation et ma campagne:

Lors du renouvellement automatique, l'App Store appelle le paymentQueue et publie une transaction. La transaction est affichée avec transaction.transactionState==SKPaymentTransactionStateRestored.

Le problème est que malheureusement cela ne fait pas affiché qu'à un seul appareil. Un deuxième appareil ne reçoit pas l'affichage. Par conséquent, pour détecter le renouvellement automatique, ou plutôt pour détecter le manque d'autoroutewal et refuser le périphérique un abonnement continu, vous devez faire un restoreCompletedTransaction ou "http Publier un JSON codé 64 bits contenant le dernier transaction". Si le premier, l'utilisateur doit donner leur mot de passe; C'est intrusif - comme vous l'avez signalé ci-dessus. Si ces derniers, beaucoup de codage supplémentaire sont nécessaires. Donc, ma question est ... pourquoi ne fonctionne pas StoreKit avoir une commande:

(n'existe pas) - [[SKPaymentQueue defaultQueue] restoreAttachedTransactions:(NSArray *)transactions];

Cette commande déboulerait comme un restoreCompletedTransactions mais il ne restaurerait que les transactions ci-jointes et, surtout, cela ne nécessiterait pas la connexion de l'utilisateur. Il a la même protection de sécurité que "HTTP Publier un JSON codé 64 bits contenant la dernière transaction" et permet de faire l'ensemble du processus d'achat d'applications à effectuer dans StoreKit plutôt que de nécessiter un code d'enregistrement Web.

Si cela est logique pour vous, veuillez suggérer comment obtenir ceci à Apple ... merci.

3
Peter B. Kramer