苹果内购-后端php验证
2017-07-16 本文已影响2080人
Gneeux
公司项目支付加入了苹果内购,所以就涉及到需要去苹果服务器那边验证订单不是正确的。我这边是使用PHP写的服务器验证。
有人问为什么要用PHP吗?(假装你们有问,因为PHP是世界上最好的语言!!!!)
作好小板凳!知识点来了!!!!
思路:
1.判断status
2.检查receipt里面的bundle_id是否在允许列表
3.检查in_app,是否包含数据
4.判断返回数据的中产品ID是不是在合法的产品ID
5.判断该订单的时间,如果时间太久肯定不是不对的
/**
* 苹果内购服务器验证
* @return string
*/
public function CheckApplePay ()
{
// 苹果内购的验证收据,由客户端传过来
$apple_receipt = I("post.apple_receipt", "");
$password = I("post.password", "");
if (empty($password)) {
$jsonData = array("receipt-data"=>$apple_receipt);
unset($password);
}else{
$jsonData = array("receipt-data"=>$apple_receipt, "password" =>$password);
}
$jsonData1 = json_encode($jsonData);
$response = $this->http_post_data($jsonData1, ApplePayURLStatus);
if($response->status==21007) {
$response = $this->http_post_data($jsonData1, false);
}else if ($response->status==21008) {
$response = $this->http_post_data($jsonData1, true);
}
if($response->status == 0){
// 允许名单数组
$bundlelist=[];
$bundleid= $response->receipt->bundle_id;
if($bundleid && in_array($bundleid,$bundlelist)) {
$in_app = $response->receipt->in_app;
if($in_app && !empty($in_app)){
// 取出第一个支付时间
$firsttime = $in_app[0]->purchase_date;
foreach($in_app as $k=>$v){
if($firsttime < $v->purchase_date){
$firsttime = $v->purchase_date;
}
}
foreach($in_app as $key=>$value){
if($value->purchase_date == $firsttime){
$arr = $value;
}
}
// 产品的ID
$product_id = $arr->product_id;
// 原始购买时间毫秒
$purchase_date_pst = $arr->original_purchase_date_ms;
// 到期时间毫秒
$expires_date_formatted = $arr->expires_date_ms;
// 支付时间毫秒
$purchase_date_ms = $arr->purchase_date_ms;
if(empty($expires_date_formatted)){
$expires_date_formatted = 0;
}
if($product_id && !empty($product_id)){
// 产品ID数组
$productids = [];
if(in_array($product_id, $productids)){
// 自动订阅类型
$product_id_arr = [];
if(in_array($product_id, $product_id_arr)){
$purchase_date = strtotime(DateUtility::GetBeiJingTime($purchase_date_ms));
$difftime = time() - $purchase_date;
if($difftime > 10*60){
return self::run(4,"支付时间过期");
}else{
// 把自动订阅型的记录到数据库,方便检测订阅是否到期和继续订阅的操作
}
}else{
// 记录到数据库
}
// 写确认订单的业务逻辑
return self::run(0, "支付成功");
} else{
return self::run(6, "非法product_id");
}
}else{
return self::run(3, "produce_id不存在伪造充值");
}
}else{
return self::run(2, "伪造充值");
}
}else{
return self::run(1, "凭据bundleid不在白名单之内");
}
}else{
$code = $response->status;
$messagearr[21000] = "App Store无法读取你提供的JSON数据";
$messagearr[21002] = "收据数据不符合格式";
$messagearr[21003] = "收据无法被验证";
$messagearr[21004] = "你提供的共享密钥和账户的共享密钥不一致";
$messagearr[21005] = "收据服务器当前不可用";
$messagearr[21006] = "收据是有效的,但订阅服务已经过期。当收到这个信息时,解码后的收据信息也包含在返回内容中";
$messagearr[21007] = "收据信息是测试用(sandbox),但却被发送到产品环境中验证";
$messagearr[21008] = "收据信息是产品环境中使用,但却被发送到测试环境中验证";
return self::run($code, $messagearr[$code]);
}
}
/**
* curl请求苹果app_store验证地址
* @param $data_string 验证字符串
* @param $istest 是否是测试地址 true正式地址 false测试地址
* @return mixed
*/
private function http_post_data($data_string, $istest) {
if ($istest) {
// 正式验证地址
$url = 'https://buy.itunes.apple.com/verifyReceipt';
} else {
// 测试验证地址
$url = 'https://sandbox.itunes.apple.com/verifyReceipt';
}
$curl_handle=curl_init();
curl_setopt($curl_handle,CURLOPT_URL, $url);
curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_handle,CURLOPT_HEADER, 0);
curl_setopt($curl_handle,CURLOPT_POST, true);
curl_setopt($curl_handle,CURLOPT_POSTFIELDS, $data_string);
curl_setopt($curl_handle,CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($curl_handle,CURLOPT_SSL_VERIFYPEER, 0);
$response_json =curl_exec($curl_handle);
$response =json_decode($response_json);
curl_close($curl_handle);
return $response;
}