iOSの自動更新可能なサブスクリプション:適切な実装と落とし穴

自動更新可能なサブスクリプションは、おそらくiOSのすべての種類のアプリ内購入の中で最も難しいものであり、最初から最後まで正しく実装することはまったく容易ではありません。この難しいパスを通過した後でも、アプリケーションの受け入れを拒否する検閲に遭遇する可能性があります。



この投稿では、サブスクリプションを実装するすべての段階を案内するようにします。おそらく、このアイデアを思いとどまらせることができます。





自動更新可能なサブスクリプションとは



このタイプのアプリ内では、1つのアクションで提供するコンテンツをサブスクライブするようにユーザーに提案し、支払いを忘れます-毎月彼からお金が引き落とされます(サブスクリプションの期間を任意に選択できます)。サブスクリプション期間が終了していること、そしてこれについて彼に再度通知する必要はありません-お金は彼のアカウントから引き出され、あなたに送られます。



また、登録を解除するオプションを埋め込む必要はありません-これはiOSの設定でのみ可能です-これは便利であり、オプトアウトボタンはユーザーを興奮させません。



なぜ彼らは私を拒否できるのですか?



このような理想的なスキームのように思えるので、1か月試用してから、月に1ドルでアプリケーションにアクセスできるようにします。 しかし、それほど単純ではありません。 ここでのキーワードは、自動更新可能なサブスクリプションがデジタルコンテンツを提供するように設計されていることであり、これらの言葉は非常にぼやけています。



たとえば、私たちのアプリケーションは毎日いくつかの新しい単語をユーザーに提供しますが、それは非常に「デジタルコンテンツ」だと考えました。 Appleの連中はそうは思わなかった。 その結果、非更新サブスクリプションのすべてをやり直す必要がありました。



したがって、このタイプのショッピングの実装を開始する前に、Appleがこのメカニズムの意味に投資したものに本当に合っているかどうかを考えてください。



それでは、実装に移りましょう


自動更新可能なサブスクリプションの実装プロセスは、3つの段階で構成されています。



iTunes Connectで追加して構成する


最初に共有シークレットを取得する必要があり、Appleサーバーにアクセスするときにサーバー側で使用します。 「アプリ内購入の管理」セクションに進み、生成します。



ここで、適切なタイプの新しいアプリ内を追加し、期間、名前を選択して、すべてのフィールドに入力します。



特にプロダクトIDに関心があります -アプリケーションからリクエストします。



また、Privcayポリシーへのリンクを追加するよう求められますが、それなしには不可能です。 書くものは何ですか? はい、それほど重要ではありません。次のように書きました: www.easy10.com/privacy



さて、 共有シークレットを取得しました。 プロダクトIDがあり、サーバー側に移動します。



検証のためのサーバー側の構成


この段階は、購入時およびサブスクリプションが新しい月に更新されたかどうかに関心があるときにAppleから受け取った領収書を確認および解読するために必要です。



このメカニズムは次のように実装されます。

  1. アプリケーションで購入リクエストを行います
  2. Appleレシートから受け取ります
  3. base64でエンコードします
  4. サーバーに送信します(これらの手順は入れ替え可能です)
  5. サーバーからAppleサーバーに送信します
  6. 彼らはそれを解読し、私たちに送ります
  7. 必要な情報を抽出し、サブスクリプションのステータスをアプリケーションに伝えます。


独自のサーバーがない場合、 www.beeblex.comサービスを使用して手順4〜6を実行できます。



プロセスを完全に制御したい場合は、ステップ5で次のコンテンツをbuy.itunes.apple.com/verifyReceipt JSONに送信する必要があります

{ "receipt-data" : "(receipt bytes here)", "password" : "(shared secret bytes here)"//  shared secret }
      
      





ステップ6に応答して、次のJSONを取得します

 { "status" : 0, "receipt" : { (receipt here) }, "latest_receipt" : "(base-64 encoded receipt here)", "latest_receipt_info" : { (latest receipt info here) } }
      
      







status = 0の場合、すべてが正常です。 21006の場合、ユーザーはサブスクリプションを更新していないため、コンテンツの提供を停止する必要があります。 他のすべてのコードはここで見ることができます:

自動更新可能なサブスクリプションのステータスコード



領収書フィールド自体では、値expires_dateに最も関心があります-現在の値と比較し、これに基づいていくつかの決定を行います。 ユーザーがサブスクリプションのサブスクリプションを解除していない場合、自動的に更新されます。



そして、これをすべてテストする方法は?


これを行うには、iTunes Connectでテストユーザーを作成し、受信確認のリクエストをサーバー上のsandbox.itunes.apple.com/verifyReceipt送信する必要があります。



テストモードではサブスクリプションが6回だけ自動的に更新されるという事実にあなたの注意を引き付けたいと思います。 そしてそれだけです。 これについてはほとんど書かれておらず、expires_dateが変更されなかった理由を理解せずに、眠れぬ夜を過ごしました。 これにあります。 そのため、この自己更新の瞬間をテストするには、新しいユーザーを作成する必要があります。



さらに、テストモードの有効期間は実際よりもはるかに短くなります。たとえば、月間サブスクリプションは5分に圧縮されます。



最後に、アプリケーション自体で購入コードを提供します。 それは何百もの場所で書かれましたが、私はそれをすべてまとめることに決めたので、この部分は不可欠です。



アプリ内購入



このため、iOSはStoreKit.frameworkを使用します。 これには、購入、トランザクションの進行状況の追跡、新しいデバイスからの購入の復元に必要なすべてが含まれています。



まず、SKPaymentTransactionObserverプロトコルをサポートするトランザクションオブザーバーを追加する必要があります。これは、ユーザーが電話またはインターネットを突然オフにしたときにトランザクションが失われないようにするために必要です。
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //// [[SKPaymentQueue defaultQueue] addTransactionObserver:sharedPaymentsOberver];//   ///}
      
      





必要なすべてのプロトコルをサポートするPaymentsOberverクラスを作成しましょう。

 #import <Foundation/Foundation.h> #import <StoreKit/StoreKit.h> @interface PaymentsObserver : NSObject <SKPaymentTransactionObserver,SKProductsRequestDelegate,SKRequestDelegate> - (void)requestProductData:(NSString*)ofProduct; - (BOOL)validateReceipt; @end
      
      







まず、必要な製品IDを示す製品リクエストを作成する必要があります。一度に無制限の数の製品をリクエストできます。

 - (void)requestProductData:(NSString*)ofProduct { if ([SKPaymentQueue canMakePayments])//,      { NSLog(@"Request Began"); SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject:ofProduct]]; request.delegate = self; [request start]; } else { UIAlertView *noPayment = [[UIAlertView alloc]initWithTitle:NSLocalizedString(@"You can't make payments", nil ) message:NSLocalizedString(@"Enable payments in your account settings,please", nil) delegate:self cancelButtonTitle:NSLocalizedString(@"Ok", nil) otherButtonTitles: nil]; [noPayment show]; } }
      
      







リクエストが完了すると、SKProductRequestDelegateメソッドの1つへの呼び出しを受け取ります。成功した場合、これは

 - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { NSArray *myProduct = response.products; if ([response.products count]) { SKPayment *payment = [SKPayment paymentWithProduct:[myProduct lastObject]]; [[SKPaymentQueue defaultQueue] addPayment:payment]; } }
      
      





その中で、結果の製品をトランザクションキューに追加します。 Appleはそれをさらに扱い、ユーザーに購入の確信があるかどうかを尋ねるウィンドウを投げます。 このプロセスの最後に、SKPaymentTransactionObserverを呼び出します。この呼び出しでは、トランザクションが成功したかどうかに応じて、確認のためにレシートをサーバーに渡すことでプロセスを続行します。

 - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { for (SKPaymentTransaction *transaction in transactions) { switch (transaction.transactionState) { case SKPaymentTransactionStatePurchased: [self completeTransaction:transaction]; break; case SKPaymentTransactionStateFailed: [self failedTransaction:transaction]; break; case SKPaymentTransactionStateRestored: [self restoreTransaction:transaction]; default: break; } } }
      
      







領収書の検証が成功した場合、ユーザーにコンテンツを提供し、非常に重要なことに、トランザクションをキューから削除する必要があります。



 - (void)completeTransaction:(SKPaymentTransaction *)transaction { if ([self validateReceipt:transaction.transactionReceipt]) { [self provideContent: transaction.payment.productIdentifier]; // Remove the transaction from the payment queue. [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; } }
      
      







サブスクリプション期間の終わりに、サーバーにリクエストを送信し、リクエストが更新されたかどうかを確認するだけです。



最後に、これはこのプロジェクトでは役に立たなかったのですが、皆さんの一部がより幸運であることを願っています!



All Articles