几天来,我一直在玩应用内购买,一切正常,直到我尝试通过应用商店验证收据,因为我不断返回无效状态。
我将收据数据传递到我的 PHP 服务器,然后从那里转发到应用商店,一旦我得到有效的响应,我打算将收据数据添加到我的数据库中。
商店工具包编程指南和类引用对于这个特定领域来说并没有什么用处,因为它们并没有真正给你任何例子,我确实找到了一个有用的 article这对我有所帮助,但仍然有问题。
基本上我想知道有收据验证工作的人是否愿意分享他们的代码,因为我无处可去。
谢谢
最佳答案
首先,发布的代码中有一些拼写错误。尝试这个。 (免责声明: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 消息的类上创建这些内部方法:
@interface YourStoreClass (Internal)
- (BOOL)verifyReceipt:(SKPaymentTransaction *)transaction;
- (NSString *)encode:(const uint8_t *)input length:(NSInteger)length;
@end
注意:您可以使用 libcrypto 之类的东西来处理 base64 编码,但随后您会在应用批准时查看导出限制和额外步骤。但我离题了...
然后,无论您打算在远程服务器上开始记录交易的何处,使用您的交易调用 verifyReceipt: 并确保它返回正面。
同时,在您的服务器上,这里有一些 super 精简的 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 是一种可能的选择。YMMV。PHP.net 有独家新闻!)
让我稍微担心的一件事是从应用程序到服务器的 URL 中有效负载的长度(通过 GET)。我忘记了每个 RFC 是否存在长度问题。也许没关系,或者它是特定于服务器的。 (读者:欢迎对这部分提出建议!)
将其设为同步请求也可能会有些犹豫。您可能希望异步发布它并放置 ol' UIActivityIndicatorView 或其他一些 HUD。恰当的例子:initWithData:encoding: 调用对我来说需要很长时间。几秒钟,这在 iPhone 领域(或其他任何在线的地方,就此而言)是一个小小的永恒。建议显示某种不确定的进度指示器。
关于php - 验证应用内购买的收据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1298998/