苹果内购-后端php验证(已解决)

不得不说想吐槽一下苹果,虚拟物品付费必须要给苹果交过路费,否则连审核都通过不了。

正题开始:

其实苹果内购,后台要做的事情很少,支付的话就是ios和苹果那些的事,我等要做的事情就是对支付结果的再次验证。


思路:

1.判断status

2.检查receipt里面的bundle_id是否在允许列表

3.检查in_app,是否包含数据

4.判断返回数据的中产品ID是不是在合法的产品ID

5.判断该订单的时间,如果时间太久肯定不是不对的

    //充值完成调的接口
    public function notify()
    {
    	//苹果内购的验证收据
        $receipt_data = I('post.apple_receipt');
        $id = I('post.id');
        $uid = I('post.uid');

        // 验证支付状态
        $result = $this->validate_apple_pay($receipt_data);

        if($result['status']){
            // 验证通过,进行购买完成后的操作
        	
        }else{
             //验证未通过
        
          }

    }


    /**
	 * 验证AppStore内付
	 * @param  string $receipt_data 付款后凭证
	 * @return array                验证是否成功
	 */
	public function validate_apple_pay($receipt_data){
	    

	    // 验证参数
	    if (strlen($receipt_data)<20){
	        $result=array(
	            'status'=>false,
	            'message'=>'非法参数'
	            );
	        return $result;
	    }

	    // 请求验证
	    $html = $this->acurl($receipt_data);
	    $data = json_decode($html,true);


	    // 如果是沙盒数据 则验证沙盒模式
	    if($data['status']=='21007'){
	        // 请求验证
	        $html = $this->acurl($receipt_data, 1);
	        $data = json_decode($html,true);
	        $data['sandbox'] = '1';
	    }

	    if (isset($_GET['debug'])) {
	        exit(json_encode($data));
	    }

	    // 判断是否购买成功
	    if(intval($data['status'])===0){
	        $result=array(
	            'status'=>true,
	            'message'=>'购买成功'
	            );
	    }else{
	        $result=array(
	            'status'=>false,
	            'message'=>'购买失败 status:'.$data['status']
	            );
	    }
	    return $result;
	}


	/**
	     * 21000 App Store不能读取你提供的JSON对象
	     * 21002 receipt-data域的数据有问题
	     * 21003 receipt无法通过验证
	     * 21004 提供的shared secret不匹配你账号中的shared secret
	     * 21005 receipt服务器当前不可用
	     * 21006 receipt合法,但是订阅已过期。服务器接收到这个状态码时,receipt数据仍然会解码并一起发送
	     * 21007 receipt是Sandbox receipt,但却发送至生产系统的验证服务
	     * 21008 receipt是生产receipt,但却发送至Sandbox环境的验证服务
	     */
	   public  function acurl($receipt_data, $sandbox=1){
	        //小票信息
	        $POSTFIELDS['receipt-data'] = $receipt_data;



	        // $POSTFIELDS = json_encode($POSTFIELDS,JSON_UNESCAPED_SLASHES);

	        $POSTFIELDS = '{"receipt-data": "'.$receipt_data.'"}';
	        //手动拼接json字符串,使用json_encode会自动转义斜杠
	        
	        //正式购买地址 沙盒购买地址
	        $url_buy     = "https://buy.itunes.apple.com/verifyReceipt";
	        $url_sandbox = "https://sandbox.itunes.apple.com/verifyReceipt";
	        $url = $sandbox ? $url_sandbox : $url_buy;

	        //简单的curl
	        $ch = curl_init($url);
	        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	        curl_setopt($ch, CURLOPT_POST, 1);
	        curl_setopt($ch, CURLOPT_POSTFIELDS, $POSTFIELDS);
	        $result = curl_exec($ch);
	        curl_close($ch);
	        return $result;
	    }

关于$receipt-data这个参数,由IOS处理以后传给服务端,前端处理时一定要注意:

IOS对receipt-data使用base64加密,转为string类型后,要对字符串中的\\n和\\r做特殊字符处理,但是千万不要对 "+" 做处理

我之前百度查到的资料都是对+做了处理,都会报错{"status":21002, "exception":"com.apple.its.drm.InvalidDrmArgumentException"}

服务端拿到IOS给的receipt-data数据,不要用json_encode直接转,需要手动拼接,不然也会报错的



—————————————————————————————————————

亲爱的用户,您好!如果您喜欢这个网站,欢迎赞助我,您们的支持是我的动力。

赞赏款用于服务器、文章等网站的固定支出。欢迎大家支持,谢谢!

51cb4e9a9397260f1f774ee07de0b77.jpg