プログラムの事とか

お約束ですが「掲載内容は私個人の見解です」

UWPにアプリ内課金処理を入れる

f:id:puni-o:20160226135622j:plain

本当に意味のないうなじ。

UWPにアプリ内課金処理を入れてみます。いつもいい加減な内容ですが、今回は特にいい加減です。

今回はおカネが絡む事なので実装する際は自分でちゃんと調べてテストしてからリリースしてくださいね。 私は一切の責任をとれませんので・・・。

Windows 8のころとやることは変わらないのでその辺から検索するとちゃんとした情報が出てくるんじゃないでしょうか。

消費可能な課金処理

何度でも課金できる課金方法です。ジェムとかそういうやつの購入がイメージしやすいんじゃないでしょうか。 やはりじゃぶじゃぶ課金してがっぽり行きたいのでこれですよね。

Consumableというタイプになるそうです。

準備

以下の準備は実際にリリースするまでにあればいい情報なので、作ってデバッグ実行するだけであれば必要ありません。

課金処理を行うのはMicrosoftなのでまずそちらに課金情報を登録しておきます。

Windows デベロッパーセンター → ダッシュボード → 対象のアプリ → IAP → 新しいIAPの作成 と進みます。

f:id:puni-o:20160226140737p:plain


新しいIAPの作成画面では自分の好きなIDを入力します。 このIDはアプリ内で使う文字列になります。 こんかいはじゃぶじゃぶ課金してほしいのでjab1としました。

f:id:puni-o:20160226140937p:plain


次にこのIAPのプロパティを設定します。「製品の種類」を消費可能にすることを忘れずに。

f:id:puni-o:20160226141555p:plain


あとは価格とか説明を適当に入力してください。

作る

実際に作っていくうえでのポイントをざっくりと。

価格を取得する

Windows デベロッパーセンターでの価格指定はUSD(ドル)だけです。 現地の価格はこの指定したUSDを基準に為替レートとかでMicrosoftが決めます。(たぶん)

ということでいくらなのかはAPIを使って取得します。

var listing = await CurrentApp.LoadListingInformationAsync();
var paidStage1 = listing.ProductListings["jab1"];
Log.Add($"{paidStage1.FormattedPrice} 円の課金を開始しますよ");

こんな感じ。 paidStage1.FormattedPriceが現地の価格ですね。

listing.ProductListingsのキーに入れている文字列がデベロッパーセンターで登録したIAPのID(以下 productId)になります。

購入処理

指定したproductIdで購入処理をします。

var result = await CurrentApp.RequestProductPurchaseAsync(productId);
switch (result.Status)
{
case ProductPurchaseStatus.Succeeded: // 買った
case ProductPurchaseStatus.NotFulfilled: // まだサーバー(?)とのやり取りが終わってないけどとりあえず買った?
    break;
case ProductPurchaseStatus.NotPurchased: // 買ってない
    break;
}

?マークが増えてきました。よくわかってません、いい感じです。

サンプル等をみるとSucceeded/NotFulfilledで購入後処理を進めていいようです。

決済?確認???

さっきのは金を払ったのかどうなのかよくわかってないんですが、先ほどの購入後処理になります。

var result = await CurrentAppSimulator.ReportConsumableFulfillmentAsync(productId, transactionId);
switch (result)
{
case FulfillmentResult.Succeeded:
    Log.Add("課金してくれてありがとう");
    break;
case FulfillmentResult.NothingToFulfill:
    break;
case FulfillmentResult.PurchasePending:
    break;
case FulfillmentResult.PurchaseReverted:    // 購入したんだけどキャンセル?
    Log.Add("課金情報をキャンセルしとく");
    break;
case FulfillmentResult.ServerError:
    break;
}

ここのSucceededにいってやっと購入処理が完了です。

未完の決済処理

アプリ起動時なんかに前回完了していない決済処理をもう一度やっておく必要があるようなないような・・・

var products = await CurrentApp.GetUnfulfilledConsumablesAsync();
foreach (var product in products.Where(product => product.ProductId == "jab1"))
{
    決済?確認???(product.ProductId, product.TransactionId);
}

GetUnfulfilledConsumablesAsyncでそういうのが取れるらしいので、処理します。 この処理がWindows 8のころのストアアプリのサンプルにはあったはずなんですが、UWPのサンプルにはありませんでした。 いらないのかどうかもわかりません。

デバッグ用の準備

デバッグのために毎回マイクロソフトにお布施なんてできませんから、デバッグ用の機能を使います。

上で説明した CurrentApp.LoadListingInformationAsync 等の CurrentAppにはCurrentAppSimulator という親戚がいます。シミュレートしてくれるみたいです。

メソッドCurrentAppと同じなのでデバッグ時はこっちを呼ぶようにすればいけます。

シミュレートする際の課金情報はXMLで入れてあげることができます。

<?xml version="1.0" encoding="utf-16" ?>
<CurrentApp>
    <ListingInformation>
        <App>
            <AppId>アプリID(Guid)をいれてね</AppId>
            <LinkUri></LinkUri>
            <CurrentMarket>ja-jp</CurrentMarket>
            <AgeRating>3</AgeRating>
            <MarketData xml:lang="ja-jp">
                <Name>アプリ名</Name>
                <Description>てきとうにいれてみた</Description>
                <Price>5.99</Price>
                <CurrencySymbol>$</CurrencySymbol>
                <CurrencyCode>USD</CurrencyCode>
            </MarketData>
        </App>
        <Product ProductId="jab1" ProductType="Consumable">
            <MarketData xml:lang="ja-jp">
                <Name>じゃぶじゃぶ</Name>
                <Price>100</Price>
                <CurrencySymbol></CurrencySymbol>
                <CurrencyCode>JPY</CurrencyCode>
            </MarketData>
        </Product>
    </ListingInformation>
    <LicenseInformation>
        <App>
            <IsActive>true</IsActive>
            <IsTrial>false</IsTrial>
        </App>
    </LicenseInformation>
</CurrentApp>

こんなxmlをプロジェクトに追加して(test.xml)、デバッグ時はシミュレーターを読み直し(?)てからメソッドを呼びます。

#if DEBUG
    var proxyFile = await Package.Current.InstalledLocation.GetFileAsync("test.xml");
    await CurrentAppSimulator.ReloadSimulatorAsync(proxyFile);
    var listing = await CurrentAppSimulator.LoadListingInformationAsync();
#else
    var listing = await CurrentApp.LoadListingInformationAsync();
#endif

これでデバッグ時はxmlの内容でシミュレートして、リリース時には本物に課金処理を行うことができます。

さいごに

GitHubに上記プロジェクトを置いておきました。

github.com

さいごのさいごに

ここまで課金処理を説明してきましたがこの処理を入れたアプリをまだストアに提出していません。 ということで上の書き方でちゃんとUWPとして提出できるのかどうかは不明です。

いちおうデバッグ実行では試せているからきっと・・・