Condividi tramite


Transazioni e verifica in Xamarin.iOS

Ripristino delle transazioni passate

Se l'applicazione supporta i tipi di prodotto ripristinabili, è necessario includere alcuni elementi dell'interfaccia utente per consentire agli utenti di ripristinare tali acquisti. Questa funzionalità consente a un cliente di aggiungere il prodotto ad altri dispositivi o di ripristinare il prodotto nello stesso dispositivo dopo essere stato cancellato o rimosso e reinstallato l'app. I tipi di prodotto seguenti sono ripristinabili:

  • Prodotti non di consumo
  • Sottoscrizioni auto-rinnovabili
  • Sottoscrizioni gratuite

Il processo di ripristino deve aggiornare i record mantenuti nel dispositivo per soddisfare i prodotti. Il cliente può scegliere di eseguire il ripristino in qualsiasi momento, in qualsiasi dispositivo. Il processo di ripristino invia nuovamente tutte le transazioni precedenti per l'utente; Il codice dell'applicazione deve quindi determinare l'azione da intraprendere con tali informazioni (ad esempio, verificare se è già presente un record di tale acquisto nel dispositivo e, in caso contrario, creare un record dell'acquisto e abilitare il prodotto per l'utente).

Implementazione del ripristino

Il pulsante Restore dell'interfaccia utente chiama il metodo seguente, che attiva RestoreCompletedTransactions in SKPaymentQueue.

public void Restore()
{
   // theObserver will be notified of when the restored transactions start arriving <- AppStore
   SKPaymentQueue.DefaultQueue.RestoreCompletedTransactions();​​​
}

StoreKit invierà la richiesta di ripristino ai server Apple in modo asincrono.

CustomPaymentObserver Poiché è registrato come osservatore delle transazioni, riceverà messaggi quando i server Apple rispondono. La risposta conterrà tutte le transazioni eseguite dall'utente in questa applicazione (in tutti i dispositivi). Il codice esegue un ciclo in ogni transazione, rileva lo stato Restored e chiama il UpdatedTransactions metodo per elaborarlo come illustrato di seguito:

// called when the transaction status is updated
public override void UpdatedTransactions (SKPaymentQueue queue, SKPaymentTransaction[] transactions)
{
   foreach (SKPaymentTransaction transaction in transactions)
   {
       switch (transaction.TransactionState)
       {
       case SKPaymentTransactionState.Purchased:
          theManager.CompleteTransaction(transaction);
           break;
       case SKPaymentTransactionState.Failed:
          theManager.FailedTransaction(transaction);
           break;
       case SKPaymentTransactionState.Restored:
           theManager.RestoreTransaction(transaction);
           break;
​default:
           break;
       }
   }
}

Se non sono presenti prodotti ripristinabili per l'utente, UpdatedTransactions non viene chiamato.

Il codice più semplice possibile per ripristinare una determinata transazione nell'esempio esegue le stesse azioni di quando si verifica un acquisto, ad eccezione del fatto che la OriginalTransaction proprietà viene usata per accedere all'ID prodotto:

public void RestoreTransaction (SKPaymentTransaction transaction)
{
   // Restored Transactions always have an 'original transaction' attached
   var productId = transaction.OriginalTransaction.Payment.ProductIdentifier;
   // Register the purchase, so it is remembered for next time
   PhotoFilterManager.Purchase(productId); // it's as though it was purchased again
   FinishTransaction(transaction, true);
}

Un'implementazione più sofisticata può controllare altre transaction.OriginalTransaction proprietà, ad esempio la data originale e il numero di ricevuta. Queste informazioni saranno utili per alcuni tipi di prodotto ( ad esempio le sottoscrizioni).

Completamento del ripristino

Include CustomPaymentObserver due metodi aggiuntivi che verranno chiamati da StoreKit quando il processo di ripristino è stato completato (correttamente o con un errore), illustrato di seguito:

public override void PaymentQueueRestoreCompletedTransactionsFinished (SKPaymentQueue queue)
{
   Console.WriteLine(" ** RESTORE Finished ");
}
public override void RestoreCompletedTransactionsFailedWithError (SKPaymentQueue queue, NSError error)
{
   Console.WriteLine(" ** RESTORE FailedWithError " + error.LocalizedDescription);
}

Nell'esempio questi metodi non eseguono alcuna operazione, tuttavia un'applicazione reale può scegliere di implementare un messaggio all'utente o ad altre funzionalità.

Protezione degli acquisti

I due esempi in questo documento usano NSUserDefaults per tenere traccia degli acquisti:

Consumabili : il "saldo" degli acquisti di credito è un valore intero semplice NSUserDefaults incrementato con ogni acquisto.

Non consumabili: ogni acquisto di filtri fotografici viene archiviato come coppia chiave-valore in NSUserDefaults.

L'uso NSUserDefaults di mantiene semplice il codice di esempio, ma non offre una soluzione molto sicura, perché gli utenti tecnicamente attenti possono aggiornare le impostazioni (ignorando il meccanismo di pagamento).

Nota: le applicazioni reali devono adottare un meccanismo sicuro per l'archiviazione di contenuti acquistati che non sono soggetti a manomissioni da parte dell'utente. Ciò può comportare la crittografia e/o altre tecniche, tra cui l'autenticazione remota del server.

Il meccanismo deve essere progettato anche per sfruttare le funzionalità di backup e ripristino predefinite di iOS, iTunes e iCloud. In questo modo, dopo che un utente ripristina un backup, gli acquisti precedenti saranno immediatamente disponibili.

Per altre linee guida specifiche per iOS, vedere la Guida alla codifica sicura di Apple.

Verifica della ricevuta e prodotti recapitati tramite server

Gli esempi in questo documento finora sono costituiti esclusivamente dall'applicazione che comunica direttamente con i server di App Store per condurre transazioni di acquisto, che sbloccano funzionalità o funzionalità già codificate nell'app.

Apple offre un livello aggiuntivo di sicurezza degli acquisti consentendo la verifica indipendente delle ricevute di acquisto da un altro server, che può essere utile per convalidare una richiesta prima di distribuire contenuti digitali come parte di un acquisto (ad esempio un libro digitale o una rivista).

Prodotti predefiniti: come gli esempi in questo documento, il prodotto acquistato esiste come funzionalità fornita con l'applicazione. Un acquisto in-app consente all'utente di accedere alla funzionalità. Gli ID prodotto sono hardcoded.

Prodotti recapitati dal server: il prodotto è costituito da contenuto scaricabile archiviato in un server remoto fino a quando una transazione ha esito positivo, in modo che il contenuto venga scaricato. Esempi possono includere libri o problemi di rivista. Gli ID prodotto vengono in genere originati da un server esterno (dove è ospitato anche il contenuto del prodotto). Le applicazioni devono implementare un metodo affidabile di registrazione al termine di una transazione, in modo che, se il download del contenuto non riesce, può essere rieserito senza confondere l'utente.

Prodotti recapitati tramite server

Alcuni contenuti del prodotto, ad esempio libri e riviste (o anche a livello di gioco) devono essere scaricati da un server remoto durante il processo di acquisto. Ciò significa che è necessario un server aggiuntivo per archiviare e distribuire il contenuto del prodotto dopo l'acquisto.

Ottenere i prezzi per i prodotti forniti dal server

Poiché i prodotti vengono recapitati in remoto, è anche possibile aggiungere altri prodotti nel tempo (senza aggiornare il codice dell'app), ad esempio l'aggiunta di altri libri o nuovi problemi di una rivista. In modo che l'applicazione possa individuare questi prodotti di notizie e visualizzarli all'utente, il server aggiuntivo deve archiviare e recapitare queste informazioni.

Getting Prices for Server-Delivered Products

  1. Le informazioni sul prodotto devono essere archiviate in più posizioni: sul server e in iTunes Connessione. Inoltre, a ogni prodotto saranno associati file di contenuto. Questi file verranno recapitati dopo un acquisto riuscito.

  2. Quando l'utente desidera acquistare un prodotto, l'applicazione deve determinare quali prodotti sono disponibili. Queste informazioni possono essere memorizzate nella cache, ma devono essere recapitate da un server remoto in cui è archiviato l'elenco master dei prodotti.

  3. Il server restituisce un elenco di ID prodotto per l'applicazione da analizzare.

  4. L'applicazione determina quindi quale di questi ID prodotto inviare a StoreKit per recuperare i prezzi e le descrizioni.

  5. StoreKit invia l'elenco degli ID prodotto ai server Apple.

  6. I server iTunes rispondono con informazioni valide sul prodotto (descrizione e prezzo corrente).

  7. Le informazioni sul prodotto dell'applicazione SKProductsRequestDelegate vengono passate all'utente.

Acquisto di prodotti recapitati tramite server

Poiché il server remoto richiede un modo per convalidare che una richiesta di contenuto sia valida (ad esempio è stata pagata), le informazioni sulla ricevuta vengono passate per l'autenticazione. Il server remoto inoltra i dati a iTunes per la verifica e, in caso di esito positivo, include il contenuto del prodotto nella risposta all'applicazione.

Purchasing Server-Delivered Products

  1. L'app aggiunge un oggetto SKPayment alla coda. Se richiesto, all'utente verrà richiesto l'ID Apple e verrà chiesto di confermare il pagamento.

  2. StoreKit invia la richiesta al server per l'elaborazione.

  3. Al termine della transazione, il server risponde con una ricevuta di transazione.

  4. La SKPaymentTransactionObserver sottoclasse riceve la ricevuta e la elabora. Poiché il prodotto deve essere scaricato da un server, l'applicazione avvia una richiesta di rete al server remoto.

  5. La richiesta di download è accompagnata dai dati della ricevuta in modo che il server remoto possa verificare che sia autorizzato ad accedere al contenuto. Il client di rete dell'applicazione attende una risposta a questa richiesta.

  6. Quando il server riceve una richiesta di contenuto, analizza i dati della ricevuta e invia una richiesta direttamente ai server iTunes per verificare che la ricevuta sia per una transazione valida. Il server deve usare una logica per determinare se inviare la richiesta all'URL di produzione o sandbox. Apple suggerisce di usare sempre l'URL di produzione e passare alla sandbox se lo stato di ricezione 21007 (ricevuta sandbox inviata al server di produzione). Per altri dettagli, vedere la Guida alla programmazione della convalida delle ricevute di Apple.

  7. iTunes verificherà la ricevuta e restituirà lo stato zero se è valido.

  8. Il server attende la risposta di iTunes. Se riceve una risposta valida, il codice deve individuare il file di contenuto del prodotto associato da includere nella risposta all'applicazione.

  9. L'applicazione riceve e analizza la risposta, salvando il contenuto del prodotto nel file system del dispositivo.

  10. L'applicazione abilita il prodotto e quindi chiama storeKit.FinishTransaction L'applicazione può quindi visualizzare facoltativamente il contenuto acquistato (ad esempio, mostrare la prima pagina di un libro o un numero di rivista acquistato).

Un'implementazione alternativa per i file di contenuto di prodotti di grandi dimensioni potrebbe comportare semplicemente l'archiviazione della ricevuta della transazione nel passaggio 9 in modo che la transazione possa essere completata rapidamente e fornire un'interfaccia utente per consentire all'utente di scaricare il contenuto effettivo del prodotto in un secondo momento. La richiesta di download successiva può inviare nuovamente la ricevuta archiviata per accedere al file di contenuto del prodotto richiesto.

Scrittura del codice di verifica della ricevuta lato server

La convalida di una ricevuta nel codice lato server può essere eseguita con una semplice richiesta/risposta HTTP POST che include i passaggi da 5 a 8 nel diagramma del flusso di lavoro.

Estrarre la SKPaymentTansaction.TransactionReceipt proprietà nell'app. Si tratta dei dati che devono essere inviati a iTunes per la verifica (passaggio 5).

Codifica in base64 i dati della ricevuta della transazione (nel passaggio 5 o n. 6).

Creare un payload JSON semplice simile al seguente:

{
   "receipt-data" : "(base-64 encoded receipt here)"
}

HTTP POST il codice JSON in https://buy.itunes.apple.com/verifyReceipt per la produzione o https://sandbox.itunes.apple.com/verifyReceipt per i test.

La risposta JSON conterrà le chiavi seguenti:

{
   "status" : 0,
   "receipt" : { (receipt repeated here) }
}

Lo stato zero indica una ricevuta valida. Il server può continuare a soddisfare il contenuto del prodotto acquistato. La chiave di ricezione contiene un dizionario JSON con le stesse proprietà dell'oggetto SKPaymentTransaction ricevuto dall'app, in modo che il codice del server possa eseguire query su questo dizionario per recuperare informazioni quali il product_id e la quantità dell'acquisto.

Per altre informazioni, vedere la documentazione della Guida alla programmazione della convalida delle ricevute di Apple.