Google Apps Marketplace Billing APIについて調べてみた
Google Apps Marketplaceの課金の仕組みについて調べてみました。
Google Apps Marketplaceを知らない方は、以下の記事を読んでください。
- Google Apps Marketplaceにアプリケーションを登録する方法 - Startup Reality
- Google Apps Marketplace manifestファイルの書き方 - hrendohの日記
- Google Apps Marketplace企業向けアプリ出店入門(1/2) ─ @IT
表題の件について、簡単なスライドを作って某所で説明したので、資料を公開してしまいます。
正しいのかはだいぶ不安です。詳しい人がいたら、ぜひコメントお願いします。
なお、公式ドキュメントはBilling Overview - Google Apps Marketplace - Google Codeです。
実装について
スライド内では実装については説明していません。簡単に書いておきます。
でも、実際には動いていません。動くはずのサンプルコードです^^;
基本的にはGoogle Apps Marketplaceにアプリケーションを登録する方法 - Startup Realityで使用しているサンプルアプリケーションを使っています。
それに対して以下のような修正を加えています。
manifest.xmlに以下を追加
Application Manifestと言われるものです。実際のところこのmanifest.xmlと次のlisting.xmlはファイルとして存在する必要はなくて、Google Apps Marketplaceにアプリを登録する際の入力フォームにこのXMLの内容を記述します。
<!-- Configures the default_edition for existing users --> <Edition id="free"> <Name>Default Edition</Name> <Extension ref="navLink"/> <Extension ref="realm"/> </Edition> <!-- Configures extensions available for the standard edition of the application. --> <Edition id="standard"> <Name>Standard Edition</Name> <Extension ref="navLink"/> <Extension ref="realm"/> </Edition> <!-- Configures extensions available for the pro edition of the application --> <Edition id="premium"> <Name>Premium Edition</Name> <Extension ref="navLink"/> <Extension ref="realm"/> </Edition>
listing.xmlを新規作成
Listing Manifestと呼ばれるものです。無料のMarketplaceアプリの場合は空欄にしていた項目です。
<?xml version="1.0" encoding="UTF-8" ?> <ListingManifest> <SubListings> <SubListing> <DisplayName>Invoicer Free</DisplayName> <EditionId>free</EditionId> <PaymentModel>FREE</PaymentModel> </SubListing> <SubListing> <DisplayName>Invoicer Standard $5/year</DisplayName> <PaymentModel>PAID</PaymentModel> <PurchaseUrl>http://billing-test.appspot.com/purchase?edition=standard</PurchaseUrl> </SubListing> <SubListing> <DisplayName>Invoicer Premium $10/year</DisplayName> <PaymentModel>PAID</PaymentModel> <PurchaseUrl>http://billing-test.appspot.com/purchase?edition=premium</PurchaseUrl> </SubListing> </SubListings> <Merchants> <Merchant> <CurrencyCode>USD</CurrencyCode> <MerchantEmailAddress>xxxxxx@gmail.com</MerchantEmailAddress> </Merchant> </Merchants> </ListingManifest>
PurchaseServlet.javaを新規作成
これはBillling APIを使って課金情報をGoogle Apps Marketplaceに送信するために使われるサーブレットです。Listing ManifestでPurchaseUrlとして指定している本体です。
package com.google.code.samples.apps.marketplace; import java.io.IOException; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.google.api.client.sample.appsmarket.AppsMarketService; import com.google.api.client.sample.appsmarket.model.Cart; import com.google.api.client.sample.appsmarket.model.InitialCart; import com.google.api.client.sample.appsmarket.model.LineItem; import com.google.api.client.sample.appsmarket.model.PurchasingCustomerInfo; import com.google.api.client.sample.appsmarket.model.RecurringCart; import com.google.api.client.sample.appsmarket.model.Subscription; public class PurchaseServlet extends HttpServlet { private static final String YOUR_APPLICATION_ID = "999999999999"; private static final String YOUR_APPLICATION_NAME = "Billing API Test"; private static final String YOUR_CONSUMER_SECRET = "abcdefghijklmnopqrstuvwxyz"; Logger logger = Logger.getLogger(this.getClass().getName()); @Override public void init(ServletConfig config) throws ServletException { super.init(config); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String token = req.getParameter("appsmarket.purchaseToken"); String edition = req.getParameter("edition"); String redirectUrl = sendShoppingCard(token, edition); logger.warning("redirectUrl=" + redirectUrl); resp.sendRedirect(redirectUrl); // req.getRequestDispatcher("/WEB-INF/jsp/purchase.jsp") // .forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.sendError(405); } private String sendShoppingCard(String purchaseToken, String edition) throws IOException { AppsMarketService service = new AppsMarketService(); service.appId = YOUR_APPLICATION_ID; service.appName = YOUR_APPLICATION_NAME; service.endpoint = "https://www.googleapis.com/appsmarket/v2sandbox/"; service.consumerKey = service.appId + ".apps.googleusercontent.com"; service.consumerSecret = YOUR_CONSUMER_SECRET; service.authorize(); PurchasingCustomerInfo info = service .getPurchasingCustomerInfo(purchaseToken); String customerId = info.customerLicense.customerId; String developerSku = edition; // Configure the base subscription. Subscription sub = new Subscription(); sub.applicationId = service.appId; sub.customerId = customerId; sub.purchaseToken = purchaseToken; sub.name = service.appName + " Subscription"; sub.description = "Example subscription description"; sub.currencyCode = "USD"; LineItem item; // Configure the initial cart (up front fees). sub.initialCart = new InitialCart(); sub.initialCart.cart = new Cart(); sub.initialCart.cart.receiptName = "Initial cart"; sub.initialCart.cart.receiptDescription = "Initial cart description"; item = new LineItem(); item.name = "Setup fee"; item.description = "Setup fee description"; item.developerSku = "setupfee"; item.price = 99000000L; // 99 USD, in micro-dollars item.seatCount = 1; sub.initialCart.cart.items = new ArrayList(); sub.initialCart.cart.items.add(item); // Configure the recurring cart (recurring subscription). sub.recurringCart = new RecurringCart(); sub.recurringCart.cart = new Cart(); sub.recurringCart.cart.receiptName = "Recurring subscription"; sub.recurringCart.cart.receiptDescription = "Recurring cart description"; item = new LineItem(); item.name = edition + " edition"; item.description = edition + " edition description"; item.editionId = edition; item.developerSku = developerSku; item.seatCount = 5; item.price = 250000000L; // 250 USD (50/seat), in micro-dollars sub.recurringCart.cart.items = new ArrayList(); sub.recurringCart.cart.items.add(item); sub.recurringCart.firstChargeDays = 0; // Begin charging immediately sub.recurringCart.frequency = "MONTHLY"; // Charge once a month // Send the subscription to Google. Subscription response = service.insertSubscription(sub); String redirectUrl = response.redirectUrl; return redirectUrl; } }
web.xmlに以下を追加
<servlet> <servlet-name>PurchaseServlet</servlet-name> <servlet-class>com.google.code.samples.apps.marketplace.PurchaseServlet</servlet-class> </servlet> ... <servlet-mapping> <servlet-name>PurchaseServlet</servlet-name> <url-pattern>/purchase</url-pattern> </servlet-mapping>
問題のテスト環境設定
Setting up your test environmentにテスト環境の構築方法が書いてあるんですが、これがどうしてもうまく行きませんでした。
一応苦闘の記録を書いておくと、最初のGoogle Checkoutのsandboxでテストアカウントを作るところからうまく行かない。
まず、ここで日本を選択するとダメなようなので、アラバマ州にする。でも、郵便番号と電話番号がアラバマ州っぽくないとだめらしくて、アラバマ州っぽくすると成功。ここはなんとか突破。なお、キャプチャは電話番号がアラバマになっていません。
次が法人情報設定画面みたいなところに行くので、入力してみる。
すると、こんなメッセージ。いや、どうしろと。
There was an error processing your request. Refresh the page in a few minutes and try again. If you continue to experience this, please contact support, referencing this error code: SERVER_ERROR.
何かわかる人いればぜひ教えてください!
というわけで、結局うまくいかずあまり参考にならないかもしれませんが、何かの役に立てば幸いです。
やたらと情報少ないので、調べている方が他にいればぜひ情報共有したいです。
*1:いや、動いてないんですけどね>