在应用程序购买validation收据
我一直玩的应用程序购买了几天,一切正常,直到我试图validation与应用程序商店的收据,因为我经常回到无效状态。
我将收据数据传递给我的PHP服务器,然后从那里转发到app store,一旦我得到一个有效的响应,我打算将收据数据添加到我的数据库。
商店套件编程指南和类参考对于这个特定的领域来说没有什么用处,因为它们并没有给你任何例子,我find了一篇有用的文章 ,帮助我了解了一些东西,但还是有些错误。
基本上我想知道是否有收到validation工作的人愿意分享他们的代码,因为我无处可去。
谢谢
首先,在发布代码中有几个拼写错误。 尝试这个。 (免责声明:Refactoring et。al留给读者!
- (BOOL)verifyReceipt:(SKPaymentTransaction *)transaction { NSString *jsonObjectString = [self encode:(uint8_t *)transaction.transactionReceipt.bytes length:transaction.transactionReceipt.length]; NSString *completeString = [NSString stringWithFormat:@"http://url-for-your-php?receipt=%@", jsonObjectString]; NSURL *urlForValidation = [NSURL URLWithString:completeString]; NSMutableURLRequest *validationRequest = [[NSMutableURLRequest alloc] initWithURL:urlForValidation]; [validationRequest setHTTPMethod:@"GET"]; NSData *responseData = [NSURLConnection sendSynchronousRequest:validationRequest returningResponse:nil error:nil]; [validationRequest release]; NSString *responseString = [[NSString alloc] initWithData:responseData encoding: NSUTF8StringEncoding]; NSInteger response = [responseString integerValue]; [responseString release]; return (response == 0); } - (NSString *)encode:(const uint8_t *)input length:(NSInteger)length { static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; NSMutableData *data = [NSMutableData dataWithLength:((length + 2) / 3) * 4]; uint8_t *output = (uint8_t *)data.mutableBytes; for (NSInteger i = 0; i < length; i += 3) { NSInteger value = 0; for (NSInteger j = i; j < (i + 3); j++) { value <<= 8; if (j < length) { value |= (0xFF & input[j]); } } NSInteger index = (i / 3) * 4; output[index + 0] = table[(value >> 18) & 0x3F]; output[index + 1] = table[(value >> 12) & 0x3F]; output[index + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '='; output[index + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '='; } return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease]; }
您可以在处理您的SKPaymentTransactionObserver消息的类上创build这些内部方法:
@interface YourStoreClass (Internal) - (BOOL)verifyReceipt:(SKPaymentTransaction *)transaction; - (NSString *)encode:(const uint8_t *)input length:(NSInteger)length; @end
注意:您可以使用像libcrypto这样的东西来处理base64编码,但是在应用程序批准时您正在查看导出限制和额外的步骤。 但是我离题了
然后,无论您打算在远程服务器上开始logging交易,请在您的交易中致电verifyReceipt:并确保它回复正面。
同时,在你的服务器上,这里有一些超级精简的PHP来处理事情:
$receipt = json_encode(array("receipt-data" => $_GET["receipt"])); // NOTE: use "buy" vs "sandbox" in production. $url = "https://sandbox.itunes.apple.com/verifyReceipt"; $response_json = call-your-http-post-here($url, $receipt); $response = json_decode($response_json); // Save the data here! echo $response->status;
其中call-your-http-post-here是您最喜欢的HTTP发布机制。 ( cURL是一个可能的select.YMMV。PHP.net有独家新闻!)
有一点我有点担心的是从应用程序到服务器(通过GET)URL中的有效载荷的长度。 我忘了,如果每个RFC有一个长度问题。 也许这是可以的,或者它可能是服务器特定的。 (读者:这个部分很受欢迎!)
同步请求也可能会有一些障碍。 你可能想要asynchronous发布它,然后放置“ UIActivityIndicatorView”或其他一些HUD。 例如: initWithData:encoding: call对我来说占用了很多时间。 几秒钟,这是iPhone的土地(或其他任何地方在线,就此而言)的永恒。 显示某种不确定的进度指标可能是可取的。
完整的源代码以及PHP实现的托pipe示例可在以下urlfind: http : //www.chrismaddern.com/validate-app-store-iap-receipt-codes-online-tool/
希望它可以帮助你!
对于任何想知道如何处理使用In-App-Purchase服务器模型时可能发生的连接或validation错误的人来说, 收据validation确保交易完成并成功。 你不想从iPhone那里做,因为你不能真正相信用户的手机。
- 用户启动应用程序内购买
- 完成后,应用程序会要求您的服务器进行validation
- 您使用Applevalidation收据:如果有效,您可以执行与购买相关的任何操作(解锁/传送内容,注册订阅…)
- 应用程序从队列中移除事务(finishTransaction)
如果服务器closures,则不应完成交易,而是向用户显示“不可用消息”。
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
稍后会再调用。
但是,如果您发现收据无效,则应完成关联的交易。 如果没有,您可能会在交易队列中永远存在额外的交易。 这意味着每次运行应用程序时,paymentQueue:updatedTransaction:将被每个事务调用一次…
在我的应用程序中,收据validation是通过Web服务完成的,如果收据无效,则返回错误代码。 这就是为什么需要外部服务器。 如果用户以某种方式pipe理跳过接收validation(通过伪造Web服务“成功”响应),他将不能解锁内容/访问function,因为服务器没有购买的痕迹。
经过一段时间,我终于find了苹果公司文档中的状态码列表, 包括可怕的21002(这是“收据数据属性中的数据格式不正确”)。 虽然我看到其他状态代码的报告没有包含在这个列表中,但是迄今为止,我还没有看到任何超出苹果公司的logging。 请注意,这些代码仅适用于自动更新订阅,而不适用于其他types的应用内购买(或者文档所述)。
有关的文件可以在这里find。
我很惊讶没有发现Ray Wenderlich的教程 – 只是挽救了我的生命。 通过validation收据没有服务器(不是一个推荐的解决scheme,但很重要的反正)。
您必须将收据作为文件发送到您的PHP服务器。 在你的PHP方面,你可以使用这个脚本来validation:
<?php $path = 'receipt'; // $_FILE['receipt-data']["tmp_name"]; $receipt = file_get_contents($path); $json['receipt-data'] = base64_encode($receipt); $post = json_encode($json); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,"https://buy.itunes.apple.com/verifyReceipt"); curl_setopt($ch, CURLOPT_POST,1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); $result=curl_exec ($ch); curl_close ($ch); ?>
https://gist.github.com/eduardo22i/9adc2191f71ea612a7d071342e1e4a6f
只是再次打开这个,并添加我的2分钱,以换取这些forms的信息掠夺。
我只是在我的应用程序中设置了一个IAP服务,并遇到了相同的21002错误。 我发现当你的PHP服务器的post是空的(因此对app store的HTTP请求是空的)或格式不正确时,21002发生。 为了得到我们的工作,在iPhone端,我们将发布数据设置为NSString,并将其作为base64编码,然后将其作为HTTP请求发送到我们的服务器。
然后在我们的服务器上,我们将它插入并进行数组和json编辑。 喜欢这个:
$receipt = json_encode(array("receipt-data"=>$_POST['receipt-data']));
你会注意到它和上面一样,除了我们使用POST而不是GET。 个人喜好真的。
然后,我们使用CURL将其发布到沙箱,并在响应中使用json_decode。
如果您收到空响应或错误代码,例如21002,请尝试添加这些行。 如果您检查了curl错误代码,那是一个SSL证书错误…
curl_setopt ($curl_handle, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt ($curl_handle, CURLOPT_SSL_VERIFYPEER, 0);