验证在App购买中的收据 [英] Verify receipt for in App purchase

查看:126
本文介绍了验证在App购买中的收据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在玩应用程序购买几天,一切正常,直到我尝试通过应用程序商店验证收据,因为我经常回到无效状态。

I have been playing around with in app purchases for a few days, everything works fine up until the point where I try to validate the receipt with the app store, as i am constantly getting back an invalid status.

我将收据数据传递给我的PHP服务器,然后从那里转发到应用程序商店,一旦我收到有效的回复,我打算将收据数据添加到我的数据库。

I am passing the receipt data to my PHP server then forwarding from there to the app store and once I get a valid response I intend to add the receipt data to my database.

商店套件编程指南和类引用对于这个特定区域来说并不是没用,因为它们并没有真正给你任何一个例子,我找到了一个有用的文章对我有所帮助但是有些事情仍然是错误的。

The store kit programming guide and the class references are less than useless for this particular area as they don't really give you any sort of example, I did find one useful article which helped me out a bit but something is still wrong.

基本上我想知道有收据验证工作的人是否愿意分享他们的代码,因为我无处可去。

Basically I am wondering if someone who has receipt validation working would be willing to share their code as I'm getting nowhere.

谢谢

推荐答案

首先,发布的代码中有一些拼写错误。尝试这个。 (免责声明:Refactoring et.al留作读者的练习!)

First, there are a few typos in the posted code. Try this. (Disclaimer: Refactoring et. al is left as an exercise for the readership!)

- (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编码,但是你会在应用审批时查看导出限制和额外步骤。但我离题了......

Note: You could use something like libcrypto to handle base64 encoding, but then you're looking at export restrictions and extra steps at app approval time. But I digress ...

然后,无论您打算在远程服务器上开始记录交易,请致电 verifyReceipt:交易,并确保它回来积极。

Then, wherever you intend to kick-off recording the transaction on your remote server, call verifyReceipt: with your transaction and make sure it comes back positive.

同时,在您的服务器上,这里有一些超级精简的PHP来处理事情:

Meanwhile, on your server, here's some super-stripped-down PHP to handle things:

$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拥有独家新闻!)

Where call-your-http-post-here is your favorite HTTP post mechanism. (cURL is one possible choice. YMMV. PHP.net has the scoop!)

我有点担心的一件事是长度URL中从应用程序到服务器的有效负载(通过GET)。如果每个RFC都存在长度问题,我会忘记。也许没关系,或者可能是服务器特定的。 (读者:欢迎提供此部分的建议!)

One thing that has me slightly concerned is the length of the payload in the URL going from the app to the server (via GET). I forget if there's a length issue there per the RFCs. Maybe it's OK, or maybe it's server-specific. (Readers: Advisement welcome on this part!)

可能还有一些因为要求同步请求而烦恼。您可能想要异步发布它并放置ol' UIActivityIndi​​catorView 或其他一些HUD。例证: initWithData:encoding:调用对我来说需要一段时间。几秒钟,这是iPhone土地上的一个小小的永恒(或者其他任何在线的事情)。显示某种不确定的进度指标可能是可取的。

There may also be some balking at making this a synchronous request. You may want to post it asynchronously and put up the ol' UIActivityIndicatorView or some other HUD. Case in point: That initWithData:encoding: call takes a loooooong time for me. A few seconds, which is a small eternity in iPhone land (or anywhere else online, for that matter). Showing some sort of indeterminate progress indicator may be advisable.

这篇关于验证在App购买中的收据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆