iphone – 任何(早期)体验与自动可再生的订阅iOS

iphone – 任何(早期)体验与自动可再生的订阅iOS,第1张

概述苹果终于介绍了所谓的 auto-renewable subscriptions昨天。由于我只有很少的(沙箱)的应用程序内购买的经验,我不知道我是否在这里。看来需要一个服务器端验证收据。它似乎是唯一的方法来查明订阅是否仍然有效,是在服务器端存储原始的交易数据。关于这个话题的苹果编程指南对我来说都是隐藏的。 我的期望是,我可以与一个iOS客户端工作,只是通过商店工具箱询问iTunes他/她已经购买这个 苹果终于介绍了所谓的 auto-renewable subscriptions昨天。由于我只有很少的(沙箱)的应用程序内购买的经验,我不知道我是否在这里。看来需要一个服务器端验证收据。它似乎是唯一的方法来查明订阅是否仍然有效,是在服务器端存储原始的交易数据。关于这个话题的苹果编程指南对我来说都是隐藏的。

我的期望是,我可以与一个iOS客户端工作,只是通过商店工具箱询问iTunes他/她已经购买这个(订阅)产品,并收到一个是/否的回答连同到期日期。

有没有人有自动可再生的订阅或(因为他们似乎在某种程度上类似的)非消费品的经验?有什么好的教程吗?

谢谢。

解决方法 我有它在沙盒中运行,几乎要现场…

应该使用服务器来验证收据。

在服务器上,您可以使用收据数据记录设备udID,因为收据总是新生成的。并且它将在多个设备上工作,因为收据总是新鲜生成的。

在设备上不需要存储任何敏感数据。和不应该:)

每当应用程序出现时,应该检查与商店的最后收据。应用程序调用服务器并且服务器使用存储进行验证。只要商店返回有效的收据应用程序提供该功能。

我开发了一个Rails3.x应用程序来处理服务器端,实际的代码验证看起来像这样:

APPLE_SHARED_PASS = "enter_yours"APPLE_RECEIPT_VERIFY_URL = "https://sandBox.itunes.apple.com/verifyReceipt" #test# APPLE_RECEIPT_VERIFY_URL = "https://buy.itunes.apple.com/verifyReceipt"     #realdef self.verify_receipt(b64_receipt)  Json_resp = nil  url = URI.parse(APPLE_RECEIPT_VERIFY_URL)  http = Net::http.new(url.host,url.port)  http.use_ssl = true  http.verify_mode = OpenSSL::SSL::VERIFY_NONE  Json_request = {'receipt-data' => b64_receipt,'password' => APPLE_SHARED_PASS}.to_Json  resp,resp_body = http.post(url.path,Json_request.to_s,{'Content-Type' => 'application/x-www-form-urlencoded'})  if resp.code == '200'    Json_resp = JsON.parse(resp_body)    logger.info "verify_receipt response: #{Json_resp}"  end  Json_respend#App Store error responses#21000 The App Store Could not read the JsON object you provIDed.#21002 The data in the receipt-data property was malformed.#21003 The receipt Could not be authenticated.#21004 The shared secret you provIDed does not match the shared secret on file for your account.#21005 The receipt server is not currently available.#21006 This receipt is valID but the subscription has expired.

更新

我的应用程序被拒绝,因为元数据没有清楚地说明一些关于自动可再生订阅的信息。

In your Meta data at iTunes Connect (in your app description): You
need to clearly and conspicuously disclose to users the following
information regarding Your auto-renewing subscription:
 

Title of publication or service Length of subscription (time period and/or number of deliverIEs during each subscription period) Price of subscription,and price per issue if appropriate Payment will be charged to iTunes Account at confirmation of purchase Subscription automatically renews unless auto-renew is turned off at least 24-hours before the end of the current period Account will be charged for @R_339_5026@ within 24-hours prior to the end of the current period,and IDentify the cost of the @R_339_5026@ Subscriptions may be managed by the user and auto-@R_339_5026@ may be turned off by going to the user’s Account Settings after purchase No cancellation of the current subscription is allowed during active subscription period links to Your Privacy Policy and Terms of Use Any unused portion of a free trial period,if offered,will be forfeited when the user purchases a subscription to that publication.”

更新二

应用程式再次遭到拒绝。订阅收据未由生产AppStore验证网址验证。我不能在沙盒中重现这个问题,我的应用程序工作完美无瑕。调试此的唯一方法是再次提交应用程序以供查看并查看服务器日志。

更新III

另一个拒绝。同时苹果记录了另外两个状态:

#21007 This receipt is a sandBox receipt,but it was sent to the production service for verification.#21008 This receipt is a production receipt,but it was sent to the sandBox service for verification.

在提交应用进行审核之前,不应将服务器切换到生产
收据验证网址。如果有,则获得验证返回的状态21007。

这次拒绝读起来像这样:

Application initiates the In App Purchase process in a non-standard manner. We have included the following details to help
explain the issue and hope you’ll consIDer revising and resubmitting
your application.

iTunes username & password are being asked for immediately on application launch. Please refer to the attached screenshot for more
information.

我没有线索为什么会这样。是否会恢复密码对话框,因为正在恢复上一个事务?或者在从应用商店请求产品信息时d出?

更新四

我得到它的权利后5拒绝。我的代码做的最明显的错误。人们应该确保在交付给应用程序时始终完成事务。

如果交易没有完成,他们被交付回应用程序,东西出了奇怪的错误。

首先需要启动付款,如下所示:

//make the paymentSKPayment *payment = [SKPayment paymentWithProductIDentifIEr:productIDentifIEr];[[SKPaymentQueue defaultQueue] addPayment:payment];

那么应用程序将立即退出其活动状态,并在应用程序代理上调用此方法:

- (voID)applicationWillResignActive:(UIApplication *)application

当应用程序处于非活动状态时,AppStored出其对话框。随着应用程式再次启用:

- (voID)applicationDIDBecomeActive:(UIApplication *)application

*** 作系统通过以下方式交付事务:

- (voID)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{  for (SKPaymentTransaction *transaction in transactions)  {    switch (transaction.transactionState)    {        case SKPaymentTransactionStatePurchased: {            [self completeTransaction:transaction];            break;        }        case SKPaymentTransactionStateFailed: {            [self FailedTransaction:transaction];            break;        }        case SKPaymentTransactionStateRestored: {            [self restoreTransaction:transaction];            break;        }        default:            break;      }  }}

然后一个完成事务:

//a fresh purchase- (voID) completeTransaction: (SKPaymentTransaction *)transaction{    [self recordTransaction: transaction];    [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; }

请参见,在将接收到的事务传递给recordTransaction之后,如何调用方法finishTransaction,然后调用应用服务器,并与appstore进行订阅接收验证。喜欢这个:

- (voID)recordTransaction: (SKPaymentTransaction *)transaction {    [self subscribeWithTransaction:transaction];}- (voID)subscribeWithTransaction:(SKPaymentTransaction*)transaction {    NSData *receiptData = [transaction transactionReceipt];    Nsstring *receiptEncoded = [Kriya base64encode:(uint8_t*)receiptData.bytes length:receiptData.length];//encode to base64 before sending    Nsstring *urlString = [Nsstring stringWithFormat:@"%@/API/%@/%@/subscribe",[Kriya server_url],APP_ID,[Kriya deviceid]];    NSURL *url = [NSURL URLWithString:urlString];    ASIFormDataRequest *request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease];    [request setPostValue:[[transaction payment] productIDentifIEr] forKey:@"product"];    [request setPostValue:receiptEncoded forKey:@"receipt"];    [request setPostValue:[Kriya deviceModelString] forKey:@"model"];    [request setPostValue:[Kriya deviceiOsstring] forKey:@"ios"];    [request setPostValue:[appDelegate version] forKey:@"v"];    [request setDIDFinishSelector:@selector(subscribeWithTransactionFinished:)];    [request setDIDFailSelector:@selector(subscribeWithTransactionFailed:)];    [request setDelegate:self];    [request startAsynchronous];}

以前我的代码试图调用finishTransaction只有在我的服务器验证收据后,但是当时的事务以某种方式失去了。所以只要确保尽快完成交易。

还有一个可以遇到的另一个问题是,当应用程序在沙盒中时,它调用沙盒appstore验证url,但当它在审查,它是在某种程度上世界之间。所以我不得不改变我的服务器代码这样:

APPLE_SHARED_PASS = "83f1ec5e7d864e89beef4d2402091cd0" #you can get this in iTunes ConnectAPPLE_RECEIPT_VERIFY_URL_SANDBox    = "https://sandBox.itunes.apple.com/verifyReceipt"APPLE_RECEIPT_VERIFY_URL_PRODUCTION = "https://buy.itunes.apple.com/verifyReceipt"  def self.verify_receipt_for(b64_receipt,receipt_verify_url)    Json_resp = nil    url = URI.parse(receipt_verify_url)    http = Net::http.new(url.host,url.port)    http.use_ssl = true    http.verify_mode = OpenSSL::SSL::VERIFY_NONE    Json_request = {'receipt-data' => b64_receipt,'password' => APPLE_SHARED_PASS}.to_Json    resp,{'Content-Type' => 'application/x-www-form-urlencoded'})    if resp.code == '200'      Json_resp = JsON.parse(resp_body)    end    Json_respenddef self.verify_receipt(b64_receipt)    Json_resp = Subscription.verify_receipt_for(b64_receipt,APPLE_RECEIPT_VERIFY_URL_PRODUCTION)    if Json_resp!=nil      if Json_resp.kind_of? Hash        if Json_resp['status']==21007           #try the sandBox then          Json_resp = Subscription.verify_receipt_for(b64_receipt,APPLE_RECEIPT_VERIFY_URL_SANDBox)        end      end    end    Json_respend

所以基本上总是用生产URL验证,但如果它返回21007代码,则意味着沙盒收据被发送到生产URL,然后只需尝试使用沙箱URL再次尝试。这种方式你的应用程序在沙箱和生产模式下工作相同。

最后苹果希望我在订阅按钮旁边添加一个RESTORE按钮,以处理由一个用户拥有的多个设备的情况。这个按钮然后调用[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];并且应用程序将交付已恢复的交易(如果有)。

也有时,测试用户帐户被污染了某种方式,事情停止工作,你可能会得到一个“无法连接到iTunes商店”消息订阅时。它有助于创建一个新的测试用户。

这里是剩下的相关代码:

- (voID) restoreTransaction: (SKPaymentTransaction *)transaction{    [self recordTransaction: transaction];    [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; }- (voID) FailedTransaction: (SKPaymentTransaction *)transaction{    if (transaction.error.code == SKErrorPaymentCancelled)    {        //present error to user here     }    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}}

我祝你顺利InAppPurchase编程经验。 总结

以上是内存溢出为你收集整理的iphone – 任何(早期)体验与自动可再生的订阅iOS全部内容,希望文章能够帮你解决iphone – 任何(早期)体验与自动可再生的订阅iOS所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1087482.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存