2011-02-25 10 views
18

Szukam wdrożenia nowych subskrypcji Auto Renewable za pomocą zakupu aplikacji, ale nie jestem pewien, jak i kiedy sprawdzić, czy użytkownik jest obecnie subskrybowany. Rozumiem, że gdy użytkownik subskrybuje wstępnie aplikację, może użyć daty zakupu wraz z datą subskrypcji, aby obliczyć, jak długo będzie trwał ich abonament. Co stanie się po upływie tego terminu? Jak sprawdzić, czy użytkownik automatycznie odnowił lub anulował?Jak sprawdzić zakup aplikacji Automatycznie odnawialna subskrypcja jest ważna

Jeśli użyję restoreCompletedTransactions, aby uzyskać transakcję i pokwitowanie dla każdego odnowienia, użytkownik zostanie poproszony o podanie swojego hasła do iTunes. Czy to oznacza, że ​​jeśli kupili 7-dniową subskrypcję, będą musieli wpisywać hasło co 7 dni, gdy aplikacja sprawdzi, czy subskrypcja jest nadal ważna?

+0

Ten link https://stackoverflow.com/questions/22680059/auto-renewable-subscription-in-ios7/45220204#45220204 może pomóc ty. –

Odpowiedz

7

Zobacz to na docs:

http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StoreKitGuide/VerifyingStoreReceipts/VerifyingStoreReceipts.html#//apple_ref/doc/uid/TP40008267-CH104-SW1

jeśli chcesz sprawdzić na nią z serwera WWW, ping ich API i zwraca status subskrypcji auto-odnawialną i informacje o ostatnim Zapłata.

Jeśli jesteś na urządzeniu, prawdopodobnie musisz zadzwonić do funkcji restoreCompletedTransactions, o którą, jak sądzę, pyta hasło.

Nie widzę żadnej innej metody. Przypuszczam, że z urządzenia można zweryfikować subskrypcję, kontaktując się z tą samą usługą sieciową po stronie serwera? Nie wiem, jakie są tego plusy i minusy.

+1

Myślę, że umowa jest - musisz użyć komponentu serwera tak czy inaczej, ponieważ musisz również podać wspólny klucz jako parametr w wywołaniu do serwera Apple podczas sprawdzania ważności paragonu. Nie sądzę, że powinieneś umieścić wspólny sekret w kodzie klienta aplikacji na iOS, ponieważ wtedy sekret nie byłby już tak bardzo tajny ... – Jonny

+0

Czy wspólne tajne hasło potrzebne do sprawdzenia pokwitowania w piaskownicy i produkcji tryb subskrypcji automatycznego odnawiania? @ Jonny –

+0

Witam, że powiedziałeś "pingujesz swoje API i zwraca status subskrypcji automatycznie odnawianej i informacje o ostatniej płatności" Co to jest API, aby sprawdzić status po stronie serwera? – Yohan

3

Rozpoczynam kampanię dotyczącą tego problemu. Oto moja obserwacja i kampania:

Po automatycznym odnawianiu, App Store wywołuje paymentQueue i wysyła transakcję. Transakcja została zaksięgowana pod numerem transaction.transactionState==SKPaymentTransactionStateRestored.

Problem polega na tym, że niestety jest on publikowany tylko na jednym urządzeniu. Drugie urządzenie nie otrzymuje tego postu. Dlatego, aby wykryć automatyczne odnawianie lub raczej wykryć brak automatycznego odnawiania i odmówić urządzeniu kontynuacji subskrypcji, musisz wykonać restoreCompletedTransaction lub "http post 64-bitowy kodowany JSON zawierający ostatnią transakcję". W pierwszym przypadku użytkownik musi podać swoje hasło; to jest uciążliwe - jak zauważyłeś powyżej. Jeśli to drugie, wymagane jest dużo dodatkowego kodowania. Więc moje pytanie brzmi ... dlaczego nie StoreKit ma polecenie:

(nie istnieje) - [[SKPaymentQueue defaultQueue] restoreAttachedTransactions:(NSArray *)transactions];

Polecenie to płynąć niczym restoreCompletedTransactions ale byłoby przywrócić tylko załączonego transakcje, a przede co ważne, nie wymagałoby to zalogowania się przez użytkownika. Ma taką samą ochronę bezpieczeństwa, jak "http post 64-bitowy kodowany JSON zawierający ostatnią transakcję" i pozwala, aby cały proces zakupu aplikacji był wykonywany w StoreKit zamiast wymagać kodu publikowania w Internecie.

Jeśli ma to dla ciebie sens, proszę zasugeruj, jak dostać to do Apple .... dzięki.

+0

To, co opisujesz, wydaje się pasować do tego, co znalazłem w dalszej grze, więc zdecydowałem się zaimplementować komponent serwera. Chociaż jest to trudne, ponieważ wymaga dodatkowego kodowania, komponent serwera jest całkiem prosty i prawdopodobnie warty jest go dla ścieżki audytu i potwierdzenia odbioru. –

12

Dzisiaj mam problem z tym problemem.

Postępuj zgodnie z Apple doc tutaj, użyłem w ten sposób, aby sprawdzić, czy subskrypcja wygasła lub nie. Mój pomysł: użytkownik APPLE odpowiedź REST API: (czas upłynął czas żądania +), aby sprawdzić, czy nie upłynął

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

nadzieję, że ta pomoc.

+1

Dziękuję. Zalecane suplementy: samouczek NSURLSession, dzięki czemu można wykonać asynchroniczne sprawdzenie https://www.raywenderlich.com/110458/nsurlsession-tutorial-getting-started, a także to, jak przetestować subskrypcje Sandbox (w kierunku końca): https: // savvyapps .com/blog/how-setup-test-auto-odnawialna-subskrypcja-ios-app – Philosophistry

4

Lepiej używać lokalnego rozwiązania przed wykonywaniem jakichkolwiek połączeń do api Apple. Za każdym razem, gdy aplikacja jest uruchomiona, dobrą praktyką jest sprawdzanie lokalnego potwierdzenia, a jeśli chcesz sprawdzić, czy użytkownik ma aktywną subskrypcję, możesz najpierw pobrać zakupy z lokalnego paragonu i dowiedzieć się, czy zakup jest nadal aktywny. .

Zaimplementowałem małą bibliotekę napisaną w Swift, aby ułatwić pracę z lokalnym odbiorem aplikacji. Możesz łatwo pobrać obiekt reprezentujący paragon (InAppReceipt) i pobrać aktywny zakup/wszystkie zakupy.

Zapraszam do korzystania. Github link

Oto przykład rozwiązywania problemu:

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) 
} 
Powiązane problemy