fc2ブログ

記事一覧

In-App Purchase で 購入履歴を復元する際の注意点 | Xamarin.iOS


iOS 用アプリにて 決済機能を追加する際に、かなりハマりポイントがありましたので、注意する点について述べたいと思います。


前提条件
・Windows10
・Visual Studio 2015 Community Update3
・Xamarin 4.2.0.703  (NuGet Xamarin.Forms 2.3.2.127)
・macOS Sierra 10.12 / Xcode8 / Xamarin.iOS 10.0.1.8
iTunes Connect にて テスターの設定が完了していること



1.デバッグはシミュレータではなく、実機で行う

 シミュレータで購入履歴を復元しようとすると、Sandbox テストの場合、エラーになってしまいます。

 SKPaymentTransactionObserverを継承したクラスにて、以下のメソッドが発生します。エラーの内容は 「Cannot connect to iTunes Store. 」 iTunes Storeに接続ができないといわれてしまいます。
 その場合、以下のメソッドにてエラー内容が渡っています。
public override void RestoreCompletedTransactionsFailedWithError(SKPaymentQueue queue, NSError error)

RestoreProducts_1.png   
また、テストアカウントではない正規のAppleIDを実機に埋め込んでいる場合は「code 0 : iTunes Store に接続できません」というエラーが返ってきますのでご注意ください。



2.プログラムの発生順序について

購入履歴を正常に復元した場合
public void RestoreProducts()
{
    SKPaymentQueue.DefaultQueue.RestoreCompletedTransactions();
}
↓非同期
public override void SKPaymentTransactionObserver.UpdatedTransactions(SKPaymentQueue queue, SKPaymentTransaction[] transactions)

public void RestoreTransaction(SKPaymentTransaction transaction)
{
    SKPaymentQueue.DefaultQueue.FinishTransaction(transaction);
}
↓登録イベント発生
this._restoreProductsObserver = NSNotificationCenter.DefaultCenter.AddObserver(InAppService.InAppRestoreProductsNotification,
    (notification) =>
    {
        // Notify anyone who needed to know that products were restored
        if (this.OnRestoreProducts != null)
        {
            this.OnRestoreProducts();
        }
    });

※上記だと購入履歴が無い場合に呼び出されませんので、
SKPaymentTransactionObserver.RestoreCompletedTransactionsFinished(SKPaymentQueue queue)
からOnRestoreCompleted等のイベントを発生させたほうが良いでしょう。

購入手続きが正常に行われた場合
public void PurchaseProduct(string productId)
{
    var payment = SKPayment.PaymentWithProduct(productId);
    SKPaymentQueue.DefaultQueue.AddPayment(payment);
}
↓非同期
public override void SKPaymentTransactionObserver.UpdatedTransactions(SKPaymentQueue queue, SKPaymentTransaction[] transactions)

public void PurchaseTransaction(SKPaymentTransaction transaction)
{
    SKPaymentQueue.DefaultQueue.FinishTransaction(transaction);
}
↓登録イベント発生
this._purchaseProductObserver = NSNotificationCenter.DefaultCenter.AddObserver(InAppService.InAppPurchaseProductNotification,
    (notification) =>
    {
        // Notify anyone who needed to know that product was purchased
        if (this.OnPurchaseProduct != null)
        {
            this.OnPurchaseProduct();
        }
    });


購入履歴を復元できなかった場合(エラーの場合)
public void RestoreProducts()
{
    SKPaymentQueue.DefaultQueue.RestoreCompletedTransactions();
}
↓非同期
public override void RestoreCompletedTransactionsFailedWithError(SKPaymentQueue queue, NSError error)



3.SKPaymentTransactionState について

<State>
Purchasing:購入処理中
Purchased:購入処理完了
Failed    :失敗
Restored :購入履歴を取得完了
Deferred  : ペアレンタルコントロールで保留中

public override void UpdatedTransactions(SKPaymentQueue queue, SKPaymentTransaction[] transactions)
{
    foreach (SKPaymentTransaction transaction in transactions)
    {
        switch (transaction.TransactionState)
        {
            case SKPaymentTransactionState.Purchasing:
                break;
            case SKPaymentTransactionState.Purchased:
                this._inAppService.PurchaseTransaction(transaction);
                break;
            case SKPaymentTransactionState.Failed:
                this._inAppService.FailedTransaction(transaction);
                break;
            case SKPaymentTransactionState.Restored:
                this._inAppService.RestoreTransaction(transaction);
                break;
            default:
                break;
        }
    }
}

Deferred が iOS8 から追加になっていますが、default: に落ちるのであれば現状は問題ないでしょう。



4.Subscriptions の有効期間について

SandBoxにてテストを実施する際、Subscriptions の有効期間が実際とは異なります。
有効期間は以下の通りです。
本番環境 SandBox
1週間 3分
1ヵ月 5分
2ヵ月 10分
3ヵ月 15分
6ヵ月 30分
1年 1時間

 AppStoreに配布されてからはiPhoneの設定から購読の停止ができますが、Sandboxでは停止することができません。自動更新はされませんので年間購読であれば1時間待つしかありません。
 その後有効期間を迎えても、UpdatedTransactionsによって購読が継続の処理(自動更新)が行われます。それが6回発生しますので、結局6時間待つことになっています。おそらく本番と同じ仕様なのでしょう。
だったら停止(キャンセル)処理ができるようにしておいて欲しいですね。。。



5.Apple の無駄な仕様について

 これはAppleの審査チーム(iTune Store Review Team)から言われたことですが、必ず復元ボタンを用意しなければいけないということです。
 端末初期化や機種変更時などの対策として、購入履歴のデータをアプリ内に復元する方法は必要ですが、iOSの場合はボタンとして存在しないと Review にて Reject されます。いちいちボタンを押させるという無駄な行為で、手間ですが、そういう規則だそうです。私は自動で復元する機能を搭載したアプリを審査に出しましたが、Rejectされ、電話で議論しましたが、一歩も応じませんでした。



6.In-App Purchase Shared Secret (App内課金共有シークレット) の取得方法

 iTunes Connect の マイApp のページにて取得します。
 詳しくは以下のページにて取得場所をご紹介しています。
In-App Purchase Shared Secret (App内課金共有シークレット) の取得方法について | iTunes Connect



7.レシート取得時のステータスについて

以下のURLに記載ありますが、
https://developer.apple.com/jp/documentation/ValidateAppStoreReceipt.pdf

status 説明
        0 正常に接続できています。
21000 App Storeは、提供したJSONオブジェクトを読むことができません。
21002 receipt-dataプロパティのデータが不正であるか、または欠落しています。
21003 レシートを認証できません。
21004 この共有秘密鍵は、アカウントのファイルに保存された共有秘密鍵と一致し ません。自動更新型の購読に用いる、iOS 6型のトランザクションレシートの場合の み。
21005 レシートサーバは現在利用できません。
21006 このレシートは有効ですが、定期購読の期限が切れています。ステータス コードがサーバに返される際、レシートデータもデコードされ、応答の一部 として返されます。自動更新型の購読に用いる、iOS 6型のトランザクションレシートの場合のみ。
21007 テスト環境のレシートを、実稼働環境に送信して検証しようとしました。こ れはテスト環境に送信してください。
21008 実稼働環境のレシートを、テスト環境に送信して検証しようとしました。こ れは実稼働環境に送信してください。

status ==21007 の場合、SandBoxに送信するようにプログラムすることが iTunes Connect の審査上、必須となっています。
レシートに関するコーディングについては以下のURLにてご説明しております。
Xamarin.iOS でレシートを取得するサンプルコード | Xamarin.forms



当ブログの内容をまとめた Xamarin逆引きメニュー は以下のURLからご覧になれます。
https://itblog.dynaspo.com/blog-entry-81.html


関連記事

コメント

コメントの投稿

※名前とタイトルが入力されていないコメントでは他のコメントとの区別ができません。

 入力されていないコメントには返信しませんのであらかじめご了承くださいませ。

※ニックネームでも良いので必ずご入力ください。

    

※必ずご入力ください。

    
    

※必ずご入力ください。

※技術的な質問には環境やエラーについて正確かつ詳細にお教えください。

・正確なエラーの内容

・Windowsのバージョン番号

・Visual Studioのバージョン

・機器の型番

・アプリやソフトのバージョン

    

カテゴリ別記事一覧

広告

プロフィール

石河 純


著者名 :石河 純
自己紹介:素人上がりのIT技術者。趣味は卓球・車・ボウリング

IT関連の知識はざっくりとこんな感じです。
【OS関連】
WindowsServer: 2012/2008R2/2003/2000/NT4
Windows: 10/8/7/XP/2000/me/NT4/98
Linux: CentOS RedHatLinux9
Mac: macOS Catalina 10.15 / Mojave 10.14 / High Sierra 10.13 / Sierra 10.12 / OSX Lion 10.7.5 / OSX Snow Leopard 10.6.8
【言語】
VB.net ASP.NET C#.net Java VBA
Xamarin.Forms
【データベース】
Oracle 10g/9i
SQLServer 2016/2008R2/2005/2000
SQLAnywhere 16/11/8
【BI/レポートツール】
Cognos ReportNet (IBM)
Microsoft PowerBI
ActiveReport (GrapeCity)
CrystalReport
【OCX関連】
GrapeCity InputMan SPREAD MultiRow GridView
【ネットワーク関連】
CCNP シスコ技術者認定
Cisco Catalyst シリーズ
Yamaha RTXシリーズ
FireWall関連
【WEB関連】
SEO SEM CSS jQuery IIS6/7 apache2

休みの日は卓球をやっています。
現在、卓球用品通販ショップは休業中です。