PHP验证IOS原生支付是否成功(代码全篇)

  • 前言
    IOS原生支付后,需要调用服务端接口进行验证,检测是否真正的支付成功!
<?php
class ApplePay
{
    /** 环境配置(建议提成配置)
     * @var bool
     */
    private $sandbox = false ;

    /** result as json
     * @param int $code
     * @param string $msg
     * @param array $data
     * @return string
     */
    private function jsonRet(int $code=200, string $msg='', array $data = [])
    {
        $result = [
            'code' => $code ,
            'message' => $msg ,
            'data' => $data ,
        ] ;
        return json_encode($result,true);
    }

    /** code400
     * @param string $msg
     * @return string
     */
    private function code400( $msg = '参数错误!' )
    {
        return $this->jsonRet(400,$msg);
    }

    /** code200
     * @param string $msg
     * @return string
     */
    private function code200( $msg = '操作成功!')
    {
        return $this->jsonRet(200,$msg);
    }

    /** log
     * @param $info
     */
    private function log($info)
    {
        //log info
    }

    /** ios apple 支付验证
     * @return string
     */
    public function apple()
    {
        //苹果支付认证的凭证(base64后的数据)
        $receipt = $_POST('receipt') ;
        if(empty($receipt)) {
            return $this->code400() ;
        }
        //环境配置
        if($this->sandbox) {
            $endpoint = 'https://sandbox.itunes.apple.com/verifyReceipt';//沙箱地址
        } else {
            $endpoint = 'https://buy.itunes.apple.com/verifyReceipt';//真实运营地址
        }
        //数据组装
        //$receipt ='MIITg45+CLLy37vkb0ADflcoqEY/3mH1Rc9rC4q3/O7eG/sT7MntcVH1gc8GiEuZZ1T0Qormu2TFRrg866YxxI0LVfxzQ==';
        $postData = json_encode(
            array('receipt-data' => $receipt)
            ,JSON_UNESCAPED_SLASHES);
        //日志记录
        $this->log($postData);
        //curl操作
        $ch = curl_init($endpoint);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);  //这两行一定要加,不加会报SSL 错误
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        $response = curl_exec($ch);
        $errno    = curl_errno($ch);
        curl_close($ch);
        if ($errno != 0) {
            return $this->code400('curl请求有错误!') ;
        } else {
            $data = json_decode($response, true);
            if (!is_array($data)) {
                return $this->code400('数据错误!') ;
            }
            //判断购买是否成功
            if (!isset($data['status']) || $data['status'] != 0) {
                return $this->code400('无效的iOS支付数据!') ;
            }
            //无效的bundle_id
            if(!in_array($data['receipt']['bundle_id'],['ios申请的bundle_id类似于支付的app_id'])) {
                return $this->code400('无效的bundle_id:'.$data['receipt']['bundle_id']) ;
            }
            //多物品购买时
            // in_app为多个(坑)
            // ios一次支付可能返回多个,可能是上次成功后没有及时返回,这次成功后会把上次或上上次成功的返回
            if(!empty($inAppData = $data['receipt']['in_app'])) {
                //产品配置,对应ios申请的product_id eg : yw_6 支付6元
                $productB = ['yw_6'];
                //多物品信息
                foreach ($inAppData as $product) {
                    //订单重复验证
                    $appleData = $product->check('自身业务去重');
                    if($appleData) {
                        continue ;
                        //return $this->code400('交易单号重复,请不要重复验证!id:'.$transactionId) ;
                    }
                    if(isset($productB[$product['product_id']])) {
                        $productId = $product['product_id'];
                        $money = $productB[$productId] ;
                        if(!$money) {
                            return $this->code400('没有找到对应产品的金额,ID:'.$product['product_id']) ;
                        }
                        //业务逻辑处理
                        //加余额,记录资金日志之类的操作
                        $product['add_balance'] = true ;
                    }
                    //环境
                    $product['is_sandbox']   = $this->sandbox ;
                    //数据
                    $product['receipt_data']  = $receipt ;
                    //时间
                    $product['time']         = date('YmdHis') ;
                    //返回码
                    $product['err_no']       = '200' ;
                    //save $product 保存数据
                }
            }
            //根据自身需求返回数据
            $returnData = [] ;
            return $this->code200($returnData) ;
        }
    }
}

相关推荐