php苹果内购的代码分享,以及当中遇到的一些坑


众所周知,苹果的支付流程大致如下
1.在苹果商店添加商品(并且审核通过)
2.用户购买商品—》提交接口到服务端(服务端创建订单)——》返回数据(苹果内购产品的id)
3.app获取到苹果内购的id,提交产品到苹果商店(一般情况下苹果商店会和支付宝绑定)
4.苹果商店返回支付凭证——》提交到服务端(验证支付是否成功或失败)
5.更新订单状态

好了,闲话不多说直接开始给大家上代码

以下是苹果商店返回的支付凭证(仅供参考)

{
	"signature" = "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";
	"purchase-info" = "ewoJIm9yaWdpbmFsLXB1cmNoYXNlLWRhdGUtcHN0IiA9ICIyMDE5LTAyLTI3IDE4OjA1OjUwIEFtZXJpY2EvTG9zX0FuZ2VsZXMiOwoJInF1YW50aXR5IiA9ICIxIjsKCSJ1bmlxdWUtdmVuZG9yLWlkZW50aWZpZXIiID0gIkQ3MDExMzU1LTZGNkYtNDY3Mi1CQjk1LTAwMDlDNzlFNjA2NCI7Cgkib3JpZ2luYWwtcHVyY2hhc2UtZGF0ZS1tcyIgPSAiMTU1MTMxOTU1MDAwMCI7CgkiZXhwaXJlcy1kYXRlLWZvcm1hdHRlZCIgPSAiMjAxOS0wMi0yOCAwNDowNjo0OSBFdGMvR01UIjsKCSJpcy1pbi1pbnRyby1vZmZlci1wZXJpb2QiID0gImZhbHNlIjsKCSJwdXJjaGFzZS1kYXRlLW1zIiA9ICIxNTUxMzIzMjA5NDIxIjsKCSJleHBpcmVzLWRhdGUtZm9ybWsadasdasddF0dGVkLXBzdCIgPSAiMjAxOS0wMi0yNyAyMDowNjo0OSBBbWVyaWNhL0xvc19BbmdlbGVzIjsKCSJpcy10cmlhbC1wZXJpb2QiID0gImZhbHNlIjsKCSJpdGVtLWlkIiA9ICIxNDUyNzQyMjk5IjsKCSJ1bmlxdWUtaWRlbnRpZmllciIgPSAiZGJmYzc4MDY2NjJhMTNmNGNmZmNmYjQ0NWJjNjg1ZmM2OTYzMjViMiI7Cgkib3JpZ2luYWwtdHJhbnNhY3Rpb24taWQiID0gIjEwMDAwMDA1MDYzNTAyNTIiOwoJImV4cGlyZXMtZGF0ZSIgPSAiMTU1MTMyNjgwOTQyMSI7CgkidHJhbnNhY3Rpb24taWQiID0gIjEwMDAwMDA1MDYzNjQ2NjAiOwoJImJ2cnMiID0gIjciOwoJIndlYi1vcmRlci1saW5lLWl0ZW0taWQiID0gIjEwMDAwMDAwNDI5NjkyOTQiOwoJInZlcnNpb24tZXh0ZXJuYWwtaWRlbnRpZmllciIgPSAiMCI7CgkiYmlkIiA9ICJjb20uY2hyaXN0aWFuaXR5LmFwcHAiOwoJInByb2R1Y3QtaWQiID0gIjQiOwoJInB1cmNoYXNlLWRhdGUiID0gIjIwMTktMDItMjggMDM6MDY6NDkgRXRjL0dNVCI7CgkicHVyY2hhc2UtZGF0ZS1wc3QiID0gIjIwMTktMDItMjcgMTk6MDY6NDkgQW1lcmljYS9Mb3NfQW5nZWxlcyI7Cgkib3JpZ2luYWwtcHVyY2hhc2UtZGF0ZSIgPSAiMjAxOS0wMi0yOCAwMjowNTo1MCBFdGMvR01UIjsKfQ==";
	"environment" = "Sandbossdasdx";
	"pod" = "100";
	"signing-status" = "0";
}

以下是php服务端验证支付凭证的代码

public function upIosApp(Request $request)
    {
       //其中 receipt_data 表示支付凭证 
        $redata = $request->only('receipt_data');
        $receipt_data = $redata['receipt_data'];
        // 验证参数
        if (strlen($receipt_data)<20){
            $result=array(
                'status'=>false,
                'message'=>'非法参数'
            );
            return json_encode($result);
        }
        // 请求验证
        $data = $this->acurl($receipt_data);
        // 如果是沙盒数据 则验证沙盒模式
        if($data['status']=='21007'){
            // 请求验证
            $data = $this->acurl($receipt_data, 1);
            $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 json_encode($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环境的验证服务
     */
    function acurl($receipt_data, $sandbox=0){
        //小票信息
        $secret = "e947476b619f4db88abc37757b61f03c";// APP固定密钥,在itunes中获取
        **此处是重点,重点,重点(需将凭证转为base64格式)**
        $POSTFIELDS = array("receipt-data" => $receipt_data,'password'=>$secret);
        $POSTFIELDS = json_encode($POSTFIELDS);

        //正式购买地址 沙盒购买地址
        $url_buy     = "https://buy.itunes.apple.com/verifyReceipt";
        $url_sandbox = "https://sandbox.itunes.apple.com/verifyReceipt";
        $url = $sandbox ? $url_sandbox : $url_buy;

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $POSTFIELDS);
        curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);  //这两行一定要加,不加会报SSL 错误
        curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);


        $response = curl_exec($ch);
        $errno    = curl_errno($ch);
        $errmsg   = curl_error($ch);
        curl_close($ch);

        $data = json_decode($response,true);
        return $data;
    }

以上代码有几个需要注意的地方
1.注意:php安装curl扩展,否则curl无法使用
2.注意:若已经上线,可以去掉沙盒测试地址
3.注意:在验证支付成功时更改订单的购买状态
4.注意:注意验证凭证时,我写的重点状态(切记,不然会验证失败的)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值