In App Purchase Verification using PHP

At SpeakingPal we offer our apps for free, and provide customers ways to extend content availability via in-app purchase. In our case, in-app purchase is build from two parts: the first, is the client's  integration with the device's apps services (AppStore in iOS, Market in Android), the second is the server-side verification of the in-app receipt, avoiding trickery of the client's app.


Client-side code samples are in abundance, and usually are very well documented (well, of course, the OS vendor wants to get paid, no?). But the other side, the server-side, is not well documented and lack samples, although considered a best-practice.


Android
Android dev-site suggests making the in-app verification at the server-side as safer, but does not provide any code sample.
Google method of in-app verification is via digital signatures verification: You provide a nonce, they give you a receipt with that nonce prefixed and a RSA-SHA1 signature on that text. The key used for signing is defined in your Market developer console. With that public key, the signed receipt and the signature, you can verify that the receipt is real, that is, produced by the Market service.


Verifying an RSA-SHA1 signature is simple in PHP, but tricky. Here is a working code:


function verify_market_in_app($signed_data, $signature, $public_key_base64)
{
$key =	"-----BEGIN PUBLIC KEY-----\n".
chunk_split($public_key_base64, 64,"\n").
'-----END PUBLIC KEY-----';
//using PHP to create an RSA key
$key = openssl_get_publickey($key);
//$signature should be in binary format, but it comes as BASE64.
//So, I'll convert it.
$signature = base64_decode($signature);
//using PHP's native support to verify the signature
$result = openssl_verify(
$signed_data,
$signature,
$key);
if (0 === $result)
{
return false;
}
else if (1 !== $result)
{
return false;
}
else
{
return true;
}
}

iOS
Apple went with something else; verifying the AppStore receipt is done by asking iTunes' servers whether a receipt is real: after in-app is done, device's AppStore service gives you a base64 encoded receipt, which you'll send to iTunes' servers, and get a json response about the validity of the receipt. Here's a snippet:

function verify_app_store_in_app($receipt, $is_sandbox)
{
//$sandbox should be TRUE if you want to test against itunes sandbox servers
if ($is_sandbox)
$verify_host = "ssl://sandbox.itunes.apple.com";
else
$verify_host = "ssl://buy.itunes.apple.com";
$json='{"receipt-data" : "'.$receipt.' }';
//opening socket to itunes
$fp = fsockopen ($verify_host, 443, $errno, $errstr, 30);
if (!$fp)
{
// HTTP ERROR
return false;
}
else
{
//iTune's request url is /verifyReceipt
$header = "POST /verifyReceipt HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($json) . "\r\n\r\n";
fputs ($fp, $header . $json);
$res = '';
while (!feof($fp))
{
$step_res = fgets ($fp, 1024);
$res = $res . $step_res;
}
fclose ($fp);
//taking the JSON response
$json_source = substr($res, stripos($res, "\r\n\r\n{") + 4);
//decoding
$app_store_response_map = json_decode($json_source);
$app_store_response_status = $app_store_response_map->{'status'};
if ($app_store_response_status == 0)//eithr OK or expired and needs to synch
{
//here are some fields from the json, btw.
$json_receipt = $app_store_response_map->{'receipt'};
$transaction_id = $json_receipt->{'transaction_id'};
$original_transaction_id = $json_receipt->{'original_transaction_id'};
$json_latest_receipt = $app_store_response_map->{'latest_receipt_info'};
return true;
}
else
{
return false;
}
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值