Namespaces

Variants
Actions

Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries over the next few weeks. Thanks for all your past and future contributions.

程序内支付(IAP)-Midlet例子解析

From Wiki
Jump to: navigation, search
WP Metro Icon Chinese.png
Article Metadata

文章
Amazing110 在 11 Jan 2012 创建
最后由 hamishwillee 在 19 Nov 2013 编辑


例子介绍

本文解析的例子是一个坦克游戏,用户下载后有两关可以试玩,如果要继续后面的关卡,就在本游戏中通过IAP购买。 你可以从这里下载该BattleTank游戏源码。
BattleTank-IAP.png Tank-IAP-mainview.JPG Tank-IAP-mainview-buy.JPG


IAP相关代码分析

IAP被添加到了这个坦克游戏中,通过它你可以你可以以一种简单的方式集成OVI商店购买功能到你的Java应用。 坦克游戏使用RecordStore 保存了一个布尔值,它表明了当前应用是否已经被购买。另外一种判断是否购买的方式是读取DRM保护的资源然后捕获IO异常,如果不能读取抛出该异常。这种方式的好处是在每次运行游戏时,不需要复位。

1. 实现接口-监听IAP支付事件

import com.nokia.mid.payment.IAPClientPaymentException;
import com.nokia.mid.payment.IAPClientPaymentListener;
import com.nokia.mid.payment.IAPClientPaymentManager;
import com.nokia.mid.payment.IAPClientProductData;
import com.nokia.mid.payment.IAPClientUserAndDeviceData;
..............
public class Main extends MIDlet implements IAPClientPaymentListener {
public static final String PURCHASE_ID = "681803";
private static boolean trial = true;
private static IAPClientPaymentManager manager;
private static Display display;
private BattleTankCanvas battleTankCanvas = null;

-这里有一种重要的成员变量,private static boolean trial = true; 这个成员就是用来标示,目前版本的是试用版还是已付费版的。 -另外一个重要成员就是“IAPClientPaymentManager manager”,基本上所有支付相关的实际操作都是靠它来完成的。 从上面的代码我们可以我们实现了一个很重要的接口“IAPClientPaymentListener ”,它提供了对IAPClientPaymentProvider相关事件的监听,你的程序需要实现和这个接口别且注册到IAPClientPaymentProvider,当相应的事件发生时以便获得异步的调用。 它定义了如下一些回调接口:

  • void productDataReceived(int status, IAPClientProductData pd)
  • void productDataListReceived(int status, IAPClientProductData[] productDataList)
  • void purchaseCompleted(int status, java.lang.String purchaseTicket)
  • void restorationCompleted(int status, java.lang.String purchaseTicket)
  • void restorableProductsReceived(int status, IAPClientProductData[] productDataList)
  • void userAndDeviceDataReceived(int status, IAPClientUserAndDeviceData ud)

在该例子中:

   public void userAndDeviceDataReceived(int status, IAPClientUserAndDeviceData ud) {}
public void restorableProductsReceived(int status, IAPClientProductData[] productDataList) {}
public void productDataListReceived(int status, IAPClientProductData[] productDataList) {}
 
public void productDataReceived(int status, IAPClientProductData pd) {
if(status == OK) BuyMenu.setPrice(pd.getPrice());
}
 
public void purchaseCompleted(int status, String purchaseTicket) {
battleTankCanvas.hideBuyMenuWaitIndicator();
if(status == OK) {
setTrial(false);
battleTankCanvas.hideBuyOption();
battleTankCanvas.hideBuyMenu();
} else {
showAlertMessage("Purchase failure", "Purchase process failed. "
+ Messages.getPaymentError(status), AlertType.ERROR);
}
}
 
public void restorationCompleted(int status, String purchaseTicket)
{
battleTankCanvas.hideBuyMenuWaitIndicator();
if(status == OK) {
setTrial(false);
battleTankCanvas.hideBuyOption();
battleTankCanvas.hideBuyMenu();
} else {
showAlertMessage("Restoraiton failure", "Restoration failed. "
+ Messages.getPaymentError(status), AlertType.ERROR);
}
}

我们可以从回调productDataReceived()的参数IAPClientProductData 中获取到价格。 当支付完成后,回调函数purchaseCompleted()会被调用,这时程序设定成员“trival”为false,同时把“Buy”从菜单中隐藏。



2. 获取实例,别且注册监听

    public void startApp() {
if(battleTankCanvas == null) {
battleTankCanvas = new BattleTankCanvas(this);
display = Display.getDisplay(this);
display.setCurrent(battleTankCanvas);
}
manager = getIAPManager();
manager.setIAPClientPaymentListener(this);
 
// If the trial flag has not been set to false in record store,
// query the status through In-app Puchase API. The boolean gets
// set during the instantiation of battleTankaCanvas
if(trial) {
manager.getProductData(PURCHASE_ID);
}
}

通过IAPClientPaymentManager.getIAPClientPaymentManager();我们就获取到了一个IAPClientPaymentManager的实例,别且通过manager.setIAPClientPaymentListener(this);设置回调监听。


3. 获取当前应用的相关信息

        if(trial) {
manager.getProductData(PURCHASE_ID);
}

我们通过IAPClientPaymentManager获取参数PURCHASE_ID所指定的应用的相关信息,以便后面的使用,当信息回去成功后,函数listener中的productDataReceived()会被调用。


4. 点击“BUY”按钮 当我们单击“BUY”按钮时,上面的函数将会被调用:

    public static boolean purchaseFullVersion() {
int status = manager.purchaseProduct(PURCHASE_ID,
IAPClientPaymentManager.FORCED_AUTOMATIC_RESTORATION);
if(status != IAPClientPaymentManager.SUCCESS)
{
showAlertMessage(display, "Purchase failure", "Purchase process failed. "
+ Messages.getPaymentError(status), AlertType.ERROR);
return false;
}
return true;
}

我们通过IAPClientPaymentManager::purchaseProduct(PURCHASE_ID, IAPClientPaymentManager.FORCED_AUTOMATIC_RESTORATION);实现商品的购买。 其中PURCHASE_ID就是该引用在Nokia'商店注册时得到的一个唯一的ID,第二参数是一些flag, 有NO_FORCED_RESTORATION 和 FORCED_AUTOMATIC_RESTORATION 可选。


5. 解锁付费关卡 代码如下:

    public static Image getImage(int level) throws ProtectedContentException, IOException {
System.out.println(Main.isTrial());
String fileName = fileNames[(level-1)%fileNames.length];
if(level <= 2) {
return Image.createImage(PATH + fileName);
} else if (Main.isTrial()) {
throw new ProtectedContentException();
} else {
try {
InputStream input = Main.getIAPManager().getDRMResourceAsStream(DRM_PATH+Main.PURCHASE_ID+"/"+fileName);
return Image.createImage(input);
} catch(Exception e) {
throw new IOException();
}
}
}

从上面的代码我们可以看到,当关卡小于等于2时,我们可以直接返回关卡的Image,当大于2时,我们需要判断是否已经付费,如果付费然后通过 IAPClientPaymentManager::getDRMResourceAsStream()获取并返回所需的被DRM封装的关卡资源。

相关链接

This page was last modified on 19 November 2013, at 06:26.
311 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×