在做应用开发的时候难免想赚点伙食费什么的,也就是所谓的收费应用。Windows8里头的收费有应用收费和应用内收费
应用收费很简单在应用发布的‘销售详细’时候设置国家然后设置金额就行如下图
然后就等待用户点击购买吧,当然你也可以添加试用功能。
当你选择的是应用收费的话,你可以在程序中取到当前应用的License(存有应用的相关信息)这里面可以判断当前应用是否处于试用状态已经证书有效日期。
如果你想添加应用内收费的话,需要在上传的时候声明,就是在'高级功能'哪儿如下图
这里面的产品ID不要乱输入应是字符串而且是唯一的(相对于这个应用)因为在代码中要更具这个产品ID来取相关信息。
当你添加产品ID的时候需要在提要哪儿有一段说明。
好了应用在商店发布的配置已经完成,当程序在调试的时候我们无法获取到刚刚在上面填写的所以在开发的时候应该使用CurrentAppSimulator对象。
以下是MSDN的描述
直到应用程序在 Windows 存储列表中,CurrentApp 对象在应用程序中不起作用。当您开发应用程序时,请使用 CurrentAppSimulator 测试应用程序的授权和应用中获取。测试应用程序之后,将其提交 Windows Store 之前,将 CurrentAppSimulator 的实例替换为 CurrentApp。如果使用CurrentAppSimulator ,您的应用程序将通不过身份验证。
注意 当使用模拟时,在 WindowsStoreProxy.xml 中描述应用程序的初始允许状态。更改许可证状态的 CurrentAppSimulator 方法(如通过买一个许可证或处理程序内采购)只能更新内存中的对象的许可证状态。不更改 WindowsStoreProxy.xml 内容。当再次启动应用程序时,许可证状态还原到 WindowsStoreProxy.xml 中所述。
CurrentAppSimulator 对象从 %userprofile%\appdata\local\packages\<package-moniker>\localstate\microsoft\Windows Store\Apidata 文件夹中的 WindowsStoreProxy.xml 文件获取其数据。您必须为在 CurrentAppSimulator 属性要模拟的方案配置此文件。
大致的意思是使用模拟器支付的时候需要在程序的路径下创建一个WindowsStoreProxy.xml 文件来进行描述。 关于这个文件的路径上面已经指出了(复制%userprofile%\appdata\local\packages\,内容粘贴在资源管理器地址栏上面可以跳转到没然后更具包的名字找到应用的本地独立存储目录)你可以手动的创建也可以不创建(系统会自动创建的)。
而如果你发布到商店里面的时候就会更具你配置的信息来产生相应的信息。
好吧上代码。
前台添加三个TextBlock 用来显示当前应用信息和产品内购信息、显示消息三个Button用来购买应用购买产品 和更新信息如下代码:
1 <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center"> 2 <TextBlock x:Name="appInfo" FontSize="25" /> 3 <TextBlock x:Name="productInfo" FontSize="25" /> 4 <Button Content="购买应用" x:Name="btn_BuyApp" Click="btn_Buy_Click" /> 5 <Button Content="购买产品" x:Name="btn_BuyProduct" Click="btn_BuyProduct_Click" /> 6 <Button Content="更新信息" x:Name="btn_Update" Click="btn_Update_Click_1" /> 7 <TextBlock FontSize="25" x:Name="tb_Info" /> 8 </StackPanel>
首先得了解下面两个类,这两个类90%的字母相同 更具我的理解应该是
LicenseInformation 概要信息 通常可找到的数据(应用当前的名字 ,有多少个收费项目等等)
ListingInformation 详细信息 应用程序可用许可证的数据(应用当前是否购买的状态和 内购项目的状态等等)
使用 Windows.ApplicationModel.Store.CurrentAppSimulator.LicenseInformation;//从模拟器中获取当前应用的许可证信息
使用 Windows.ApplicationModel.Store.CurrentApp.LicenseInformation;//从Windows Store中获取当前应用的许可证信息
注意,直到应用程序在 Windows 存储列表中,CurrentApp 对象在应用程序中不起作用,所以在Debug 的时候应该使用的是Windows.ApplicationModel.Store.CurrentAppSimulator.LicenseInformation
在代码中可以这样写
#if DEBUG //如果是调试状态则调用模拟器否则就... licenseInfo = Windows.ApplicationModel.Store.CurrentAppSimulator.LicenseInformation; #else licenseInfo = Windows.ApplicationModel.Store.CurrentApp.LicenseInformation; #endif
当使用Windows.ApplicationModel.Store.CurrentAppSimulator.LicenseInformation;的时候 应用会自动检测%userprofile%\appdata\local\packages\<package-moniker>\localstate\microsoft\Windows Store\Apidata
也就是当前应用的Localstate里面的WindowsStoreProxy.xml 文件是否存在如果存在就加载否则就创建一个(还有写初始数据哦)
应是这个样子滴
1 <?xml version="1.0" encoding="utf-16" ?> 2 <CurrentApp> 3 <ListingInformation> 4 <App> 5 <AppId>00000000-0000-0000-0000-000000000000</AppId> 6 <LinkUri>http://apps.microsoft.com/webpdp/app/00000000-0000-0000-0000-000000000000</LinkUri> 7 <CurrentMarket>en-US</CurrentMarket> 8 <AgeRating>3</AgeRating> 9 <MarketData xml:lang="en-us"> 10 <Name>AppName</Name> 11 <Description>AppDescription</Description> 12 <Price>1.00</Price> 13 <CurrencySymbol>$</CurrencySymbol> 14 <CurrencyCode>USD</CurrencyCode> 15 </MarketData> 16 </App> 17 <Product ProductId="1" LicenseDuration="0"> 18 <MarketData xml:lang="en-us"> 19 <Name>Product1Name</Name> 20 <Price>1.00</Price> 21 <CurrencySymbol>$</CurrencySymbol> 22 <CurrencyCode>USD</CurrencyCode> 23 </MarketData> 24 </Product> 25 </ListingInformation> 26 <LicenseInformation> 27 <App> 28 <IsActive>true</IsActive> 29 <IsTrial>true</IsTrial> 30 </App> 31 <Product ProductId="1"> 32 <IsActive>true</IsActive> 33 </Product> 34 </LicenseInformation> 35 </CurrentApp>
然后我将他修改成了 应用处于试用状态而且没有激活并且有一个产品id为product1的产品‘10块购买完整版’价格为 10.00 没有购买 当前应用的价格是10美元。以下是我修改后的
关于这个xml文件的介绍可以单击下面这个连接
1 <?xml version="1.0" encoding="utf-16" ?> 2 <CurrentApp> 3 <ListingInformation> 4 <App> 5 <AppId>9ee87f78-ab14-4cdc-9ba1-0bc20a021054</AppId> 6 <LinkUri>http://apps.microsoft.com/webpdp/app/9ee87f78-ab14-4cdc-9ba1-0bc20a021054</LinkUri> 7 <CurrentMarket>en-US</CurrentMarket> 8 <AgeRating>3</AgeRating> 9 <MarketData xml:lang="en-us"> 10 <Name>10块钱你买不了吃亏,也买不了上当</Name> 11 <Description>应用购买</Description> 12 <Price>10.00</Price> 13 <CurrencySymbol>$</CurrencySymbol> 14 <CurrencyCode>USD</CurrencyCode> 15 </MarketData> 16 </App> 17 <Product ProductId="product1" LicenseDuration="10"> 18 <MarketData xml:lang="en-us"> 19 <Name>10块购买完整版</Name> 20 <Price>10.00</Price> 21 <CurrencySymbol>$</CurrencySymbol> 22 <CurrencyCode>USD</CurrencyCode> 23 </MarketData> 24 </Product> 25 </ListingInformation> 26 <LicenseInformation> 27 <App> 28 <IsActive>false</IsActive> 29 <IsTrial>true</IsTrial> 30 </App> 31 <Product ProductId="product1"> 32 <IsActive>false</IsActive> 33 </Product> 34 </LicenseInformation> 35 </CurrentApp>
然后在代码里面可以这样写:
使用 Windows.ApplicationModel.Store.CurrentAppSimulator.LicenseInformation; 获取到 LicenseInformation(概要信息)
使用 await Windows.ApplicationModel.Store.CurrentAppSimulator.LoadListingInformationAsync(); ListingInformation(详细信息)
写一个获取信息的方法来更新信息(注意 LicenseInformation和ListingInformation)
1 private async System.Threading.Tasks.Task GetLicenseInfo() 2 { 3 4 #if DEBUG 5 //如果是调试状态则调用模拟器否则就xxoo 6 licenseInfo = Windows.ApplicationModel.Store.CurrentAppSimulator.LicenseInformation; 7 #else 8 licenseInfo = Windows.ApplicationModel.Store.CurrentApp.LicenseInformation; 9 #endif 10 #if DEBUG 11 listingInfo = await Windows.ApplicationModel.Store.CurrentAppSimulator.LoadListingInformationAsync(); 12 #else 13 listingInfo = await Windows.ApplicationModel.Store.CurrentApp.LoadListingInformationAsync(); 14 #endif 15 16 appInfo.Text = "当前应用程序状态:"; 17 appInfo.Text += (licenseInfo.IsActive == true ? "已激活," : "未激活,");//概要信息 能得到当前应用是否激活 18 appInfo.Text += (licenseInfo.IsTrial == true ? "试用期." : "非试用期.");//概要信息 得到当前应用是否处于试用期 19 20 21 var product1 = listingInfo.ProductListings["product1"];//详细信息 取product1的信息 这个配置在商店里面'高级功能'配置 22 23 productInfo.Text = "内购产品:"; 24 productInfo.Text += "\"" + product1.Name + "\""; 25 productInfo.Text += "价格:" + product1.FormattedPrice;//10块钱你买不了吃亏,10块钱你买不了上当 26 productInfo.Text += "状态:" + (licenseInfo.ProductLicenses["product1"].IsActive == true ? "已购买" : "未购买"); 27 }
然后可以更具定义好的产品ID来实现内购功能 如下代码
string receipt = ""; #if DEBUG receipt = await CurrentAppSimulator.RequestProductPurchaseAsync("product1", true);//第一个参数是产品ID 第二个是是否返回发票(一些信息) 一般为false #else await CurrentApp.RequestProductPurchaseAsync("product1", false); #endif
1 //应用内购买功能 2 var product1 = licenseInfo.ProductLicenses["product1"];//取product1的信息 3 4 if (!product1.IsActive) 5 { 6 tb_Info.Text = "购买产品中"; 7 try 8 { 9 10 string receipt = ""; 11 #if DEBUG 12 receipt = await CurrentAppSimulator.RequestProductPurchaseAsync("product1", true);//第一个参数是产品ID 第二个是是否返回发票 一般为false 13 #else 14 await CurrentApp.RequestProductPurchaseAsync("product1", false); 15 #endif 16 if (licenseInfo.ProductLicenses["product1"].IsActive) 17 { 18 tb_Info.Text = "购买成功!"; 19 Debug.WriteLine("打印发票:" + receipt); 20 } 21 22 } 23 catch (Exception) 24 { 25 tb_Info.Text = "没有购买成功!"; 26 } 27 } 28 else 29 { 30 tb_Info.Text = "您已经购买了该功能!"; 31 }
还有购买应用的功能
1 string receipt = ""; 2 #if DEBUG 3 receipt = await CurrentAppSimulator.RequestAppPurchaseAsync(true);//购买应用 要发票! 4 #else 5 await CurrentApp.RequestAppPurchaseAsync(false); 6 #endif
1 if (licenseInfo.IsTrial) 2 { 3 try 4 { 5 6 string receipt = ""; 7 #if DEBUG 8 receipt = await CurrentAppSimulator.RequestAppPurchaseAsync(true);//购买应用 要发票! 9 #else 10 await CurrentApp.RequestAppPurchaseAsync(false); 11 #endif 12 if (licenseInfo.IsActive) 13 { 14 tb_Info.Text = "购买成功!"; 15 Debug.WriteLine("打印发票:" + receipt); 16 } 17 } 18 catch (Exception) 19 { 20 tb_Info.Text = "没有购买成功!"; 21 } 22 23 } 24 else 25 { 26 tb_Info.Text = "钱很多么?您已经购买了本应用!"; 27 }
需要注意的是
当使用模拟时,在 WindowsStoreProxy.xml 中描述应用程序的初始允许状态。更改许可证状态的 CurrentAppSimulator 方法(如通过买一个许可证或处理程序内采购)只能更新内存中的对象的许可证状态。不更改 WindowsStoreProxy.xml 内容。当再次启动应用程序时,许可证状态还原到 WindowsStoreProxy.xml 中所述
而如果发布到商店的时候 应该会保存在系统中(我没有测试过)而且相对于保存在其他位置比较安全
判断用户是否购买应用或者是购买内购的时候 一定不要把状态保存到 ApplicationData.Current.LocalSettings 或者其他Setting里面 因为这里面相当的不安全!加密也不安全!
在应用包的安装路径下的Settings文件夹下面的settings.dat文件就是setting存放的位置 微软竟然没有加密他!用复制到其他程序里面写个遍历就出来了。。。。
运行起来的效果如下
模拟器里里头可以返回相应的信息。
关于那个 WindowsStoreProxy.xml文件你可以使用 CurrentAppSimulator.ReloadSimulatorAsync 来加载一个自定义的xml文件 在微软给的Demo里头有介绍的。
整体上感觉Windows8的支付模式不大安全,前段时间国外的黑客已经出了工具可以把收费的应用变成已购买,竟然还是开源的...
听说新浪有个支付系统看起来挺牛x的..
如果谁有更好的办法可欢迎来告诉我。
ps:一个好的应用是在免费的情况下还能带来盈利!
欢迎转载,转载请注明来自BeyondBlog的博客