zoukankan      html  css  js  c++  java
  • Windows Phone中In-App Purchase应用内购买

    • 前言

          应用内购买(In-App Purchase)对于开发者来说绝对是一个非常重要的功能,它提供了一个便捷的入口供用户来购买付费。在IAP盛行之前的游戏运营商一般都是通过接入第三方支付入口来收费。之前做过的一个安卓手机游戏服务器(Asp.Net),他们采用的付费方式有两种,一个是接入支付宝的接口,让用户可以通过支付宝来付费。还有一种是通过手机运营商来付费,先由用户把钱付给运营商,运营商通过你注册的服务器的API告知该用户已付费。在Windows Phone 8中就不用担心第三方付费服务器的问题了,微软为我们提供了一个付费的功能,也就是之前提到的IAP,付费的整个过程都是由微软的交易平台(Microsoft Commerce Platform)来提供支持的,通过Windows.ApplicationModel.Store命名空间下的API可以非常容易的实现IAP的功能,省去了很多接入第三方付费接口的调试时间。下面这张图介绍了创建和购买虚拟物品的流程。

          a/b:开发者通过Dev Center注册自己的付费App和所有虚拟物品信息。如果商品要从服务器下载,那么你需要自己提供这个服务器。

          c/d:开发者拉取Store上注册的虚拟物品并展示在App内,由用户来点击购买。

          e/f:微软交易平台告知你的App用户付费成功,并获取电子收据。

          g/h:通过微软交易平台提供的收据作为凭证,从你的服务器下载虚拟物品。并告知交易平台该商品已经成功分发。

          整个过程还是非常简单清晰的,需要注意的是如果你的游戏非常的轻量,比如是个单机游戏,那么虚拟商品就不需要服务器的支持,电子收据这步可以省略掉。大型的手机游戏一般都会有后端服务器的支持。电子收据为我们从服务器下载插件时提供了有效的凭证。下面我们就先省略掉注册应用和虚拟物品这两个步骤,做一个简单客户端IAP的例子。

    private async void LoadListingInformationAsync()
            {
                try
                {
                    // Query the Windows Phone Store for the in-app products defined for the currently-running app.
                    var listingInformation = await CurrentApp.LoadListingInformationAsync();
                    foreach (var v in listingInformation.ProductListings)
                    {
                        Products.Add(new ProductViewModel() { Title = v.Value.Name, ProductId = v.Value.ProductId, ImageUri = v.Value.ImageUri });
                    }
                }
                catch
                {
                    // An exception is expected to be raised by CurrentApp.LoadListingInformationAsync() 
    //when it is not called from an app installed from the Windows Phone Store.
    } }

        上面这段代码就是异步的从Store中获取我们事先注册好的虚拟物品集合。CurrentApp是一个非常重要的类,它包含了所有主要操作虚拟物品的方法。通过上面的方法获取到虚拟物品的信息后,我们就可以对数据做进一步的处理,例子当中用一个ObservableCollection类型的集合Producets来保存数据,并通过databinding将其展示在商品页面上,供用户选择购买。

    private async void PurchaseProduct(string productId)
    {
        try
        {
            // Kick off purchase; don't ask for a receipt when it returns
            await CurrentApp.RequestProductPurchaseAsync(productId, false);
    
            // Now that purchase is done, give the user the goods they paid for
            // (DoFulfillment is defined later)
            //DoFulfillment();
        }
        catch (Exception ex)
        {
            // When the user does not complete the purchase (e.g. cancels or navigates back from the Purchase Page), 
    // an exception with an HRESULT of E_FAIL is expected.
    } }

          当用户确定要购买某项虚拟物品的时候通过调用RequestProductPurchaseAsync方法来开启用户付费的过程,这个方法需要两个参数,一个是之前获取到的虚拟物品的id,另一个是bool类型的参数,代表在付费成功后是否要返回购买虚拟物品的电子收据,电子收据是一个xml格式的信息。如果用户没有完成付费操作,比如取消或者通过back键返回等,都会触发一个错误类型为E_FALL的Exception。

    public void DoFulfillment()
    {
        var productLicenses = CurrentApp.LicenseInformation.ProductLicenses;
        DistributeProduct(productLicenses);
    }
    
    private void DistributeProduct(IReadOnlyDictionary<string, ProductLicense> productLicenses)
    {
        var bagOfSilver = new Regex(@"Bag.Silver.(d+)");
        foreach (ProductLicense license in productLicenses.Values)
        {
            if (license.IsConsumable && license.IsActive)
            {
                var m = bagOfSilver.Matches(license.ProductId);
                if ((m.Count == 2) && (m[1].Success))
                {
                    m_silverCount += int.Parse(m[1].Value);
                    CurrentApp.ReportProductFulfillment(license.ProductId);
                }
            }
        }
    }

          当用户付费成功后我们就可以在App里面将虚拟物品分发给用户,通过CurrentApp.LicenseInformation.ProductLicenses获取到用户购买的虚拟物品的授权license,ProductLicenses是一个IDictionary类型的集合,可以通过TryGetValue方法获取到某个商品的授权。IsConsumable属性代表商品可以进行消费,IsActive属性代表这个license是有效的。如果license有效,我们就可以把虚拟物品分发给用户了。最后还要调用ReportProductFulfillment方法告诉Store商品已经分发,整个购买过程结束。

    public async Task<bool> LoadLevelAsync(string levelProductId)
    {
        var license = CurrentApp.LicenseInformation.ProductLicenses[levelProductId];
        if (!license.IsActive)
        {
            // User doesn't own this level
            return false;
        }
        if (!IsLevelDownloaded(levelProductId))
        {
            var receiptXml = await CurrentApp.GetProductReceiptAsync(levelProductId);
            await DownloadLevelAsync(receiptXml);
        }
        // TODO: Load the level
        return true;
    }
    
    private async Task DownloadLevelAsync(string receiptXml)
    {
        var webReq = (HttpWebRequest)WebRequest.Create(sc_DownloadUrl);
        webReq.Method = "POST";
        AddStringToWebRequestStream(webReq, receiptXml);
        WebResponse response = await webReq.GetResponseAsync();
        // TODO: Save the level to disk
    }

           如果我们的虚拟物品要从自己的服务器下载比如皮肤和主题文件,使用GetProductReceiptAsync方法获取电子收据recipt。有了电子收据方便我们的服务器对恶意的商品请求做出过滤,避免第三方通过不法手段获取虚拟商品。

    • 总结

         Windows Phone Store的IAP已经封装成了一个非常方便的接口,如果你还没有注册虚拟物品到Dev Center可以先通过CurrentAppSimulator类来模拟整个过程。IAP绝对是一个有益于开发者的特性,可以吸引更多的开发者来完善整个生态圈。那么就开始你的IAP之旅吧。

  • 相关阅读:
    Oracle 列转行函数 Listagg()
    JS正则表达式
    云经验
    业务架构、应用架构、数据架构和技术架构
    Sublime Text3+Golang搭建开发环境
    成功安装vscode中go的相关插件
    Visual Studio Code配置GoLang开发环境
    团队架构实践
    架构
    条件引用
  • 原文地址:https://www.cnblogs.com/ghostwutao/p/3656410.html
Copyright © 2011-2022 走看看