ThinkPHP5成功调通IOS苹果支付

先上代码,以备后用

 

1,'money'=>12],
            ['id'=>2,'money'=>68],
            ['id'=>3,'money'=>128],
            ['id'=>4,'money'=>198],
            ['id'=>5,'money'=>588],
            ['id'=>6,'money'=>1098],
        ];
        return json(['code'=>'1','message'=>'','data'=>$t]);
    }

    /**
     * 苹果下单
     */
    public function setorder(){
        $param = $this->ios_data();
        if(!isset($param['userid'])){
            return json(['code'=>0,'message'=>'请传递用户id']);
        }
//        $this->checkToken();
//        if(!isset($param['num'])){
//            json(['code'=>0,'message'=>'请选择结藤币数量'])->send();exit;
//        }
        if(!isset($param['money'])){
            return json(['code'=>0,'message'=>'请传递支付金额']);
        }
//        if(!isset($param['type'])){//0=微信支付,1=支付宝支付 4=苹果支付
//            return json(['code'=>0,'message'=>'请选择支付方式']);
//        }
        $userinfo = $this->userinfo($param['userid']);

//        $jt_member_row = Db::name(self::JT_MEMBER)->where('id',$userinfo['jt_member_id'])->find();
        //计算实际支付金额
//        $money = $param['num'] * ($jt_member_row['discount']/100);
//        $money = $param['num'] * ($jt_member_row['discount']/100);

//        if($money!=$param['money']){
//            json(['code'=>0,'message'=>'所支付金额不符'])->send();exit;
//        }

        $order_id=Random::build('alnum',20);

        $add_db = [
            'order_type' => 4,
            'user_id' => $param['userid'],
            'fee' => $param['money']*100,//数据库单位为分
            'open_id' => $userinfo['open_id'],
            'add_time' => time(),
            'jt_point' => $param['money'],
            'purchase_type'=>8,
            'order_status'=>0,
            'order_id'=>$order_id
        ];

        $res = Db::table('order')->insert($add_db,false,true);
        if(!$res){
            return json(['code'=>0,'message'=>'支付订单创建失败']);
        }else{
            return json(['code'=>1,'message'=>'订单创建成功','data'=>$add_db]);
        }
    }



    /**
     * @title 验证支付票据 完成订单接口
     */
    public function verifyReceipt()
    {




        $param = $this->ios_data();

//
//        $receipt = Request::instance()->param('receipt');  //票据
//        $orderSn = Request::instance()->param('order_id');  //订单号
        $receipt=$param['receipt'];
        $orderSn=$param['order_id'];



        $ck=Db::table('order')->where(array('order_id'=>$orderSn))->find();
        if($ck){
            if($ck['order_status']==3){
                return json(['code'=>0,'message'=>'订单已成功支付,请勿重复发起申请']);
            }
        }

        //判断订单是否存在 检查状态
        //写入日志  查看票据格式  记录日志的方法 这个方法不贴出来了
//        Tool::callAddLog('request-param',json_encode(['receipt'=>$receipt,'orderSn'=>$orderSn]));

        trace('receipt**************************************************');
        trace($receipt);
        trace('receipt**************************************************');

        trace('orderSn&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&');
        trace($orderSn);
        trace('orderSn&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&');

        //password 是验证秘钥
        $jsonItem = json_encode(['receipt-data'=>$receipt]);
//        $jsonItem = json_encode(['receipt-data'=>$receipt, 'password'=>'XXXXXXXXXXXXXXXX']);

        //$url= 'https://buy.itunes.apple.com/verifyReceipt';      //正式
        $url= 'https://sandbox.itunes.apple.com/verifyReceipt';  //测试

        //模拟post提交   下面会贴出来
        $result =  $this->http_post_json($jsonItem,$url);


        trace('orderS$result$result$result$result$result$result$result$result$result$result$result$result$result$result$result$result');
        trace($result);
        trace('orderS$result$result$result$result$result$result$result$result$result$result$result$result$result$result$result$result');

        if($result['status'] !== 0){
           //验证失败 返回app错误状态
            return json(['code'=>0,'message'=>'秘钥验证失败']);
        }

        //验证完成加入日志
//        Tool::callAddLog('verifyReceipt_finish',json_encode($result));

        trace('success&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&');
        trace($result);
        trace('success&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&');

        //找出时间最大的数组
        $receiptitem = $result['receipt']['in_app'];

        //这个是排序的方法  下面回帖出来 苹果会把这个会员往期的订单信息全部返回,需要找出来最近的那一组信息
        $item = $this->arraySort($receiptitem,'purchase_date','desc');

        //判断一下过期时间 延长会员时间

        $orderThird = $item['transaction_id'];                //本次订阅的订单号

        $orderThirdFirst = $item['original_transaction_id'];  //这个是原始订单号

        $orderinfo=Db::table('order')->where(array('order_id'=>$orderSn))->find();

        if($orderThird == $orderThirdFirst){                  //首次订阅 两个相等
            /*业务逻辑*/
            Db::startTrans();
            try {
                /*更新订单*/


                Db::commit();

                return json(['code'=>1,'message'=>'支付成功1']);
            } catch (Exception $e) {
                Db::rollback();

                return json(['code'=>0,'message'=>'支付失败1']);
            }

        }else{
            //判断过期时间和当前时间比较   expires_date_ms是毫秒单位
            if($item['expires_date_ms']/1000 > time()){

                /*业务逻辑*/
                Db::startTrans();
                try {
                    /*更新订单*/


                    Db::commit();
   
                } catch (Exception $e) {
                    Db::rollback();
            
                }

            }else{
                //过期处理  票据失效
            }
        }
        // 接下来处理订单业务逻辑,处理订单,修改订单信息,original_transaction_id 把这个单号和存入订单信息,
        // 在异步回调的时候根据这个单号来查找订单信息来判断是哪个用户,
        // 苹果票据里面也有产品product_id,是app_store的产品id,不是自己业务的产品id,
        // 可以在后台把自己的产品ID和 product_id 关联,处理业务逻辑。
    }


    //模拟post提交
    public static function http_post_json($json,$url) {

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
        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;
    }

    //查找最新数据的方法
    public static function arraySort($arr,$key,$type='asc')
    {
        $keyArr = []; // 初始化存放数组将要排序的字段值
        foreach ($arr as $k => $v) {
            $keyArr[$k] = $v[$key]; // 循环获取到将要排序的字段值
        }
        if ($type == 'asc') {
            asort($keyArr); // 排序方式,将一维数组进行相应排序
        } else {
            arsort($keyArr);
        }
        foreach ($keyArr as $k => $v) {
            $newArray[$k] = $arr[$k]; // 循环将配置的值放入响应的下标下
        }
        $newArray = array_merge($newArray); // 重置下标
        return $newArray[0]; // 数据返回
    }


    /**
     * 异步回调
     */
    public function applePayReceive(){

        $str = file_get_contents('php://input');


        trace('request-param……………………………………………………………………………………………………');
        trace($str);
        trace('request-param……………………………………………………………………………………………………');


        //写入通知日志

        $jsonItem = json_decode($str,true);

        if($jsonItem['notification_type'] == 'RENEWAL' || $jsonItem['notification_type'] == 'DID_CHANGE_RENEWAL_STATUS'){

            if($jsonItem['notification_type'] == 'DID_CHANGE_RENEWAL_STATUS'){
                if($jsonItem['auto_renew_status'] == 'true'){
                    //第一次够买的时候 不处理通知
                     die;
                }

                $expires_date = $jsonItem['latest_receipt_info']['expires_date'];
                $expires_date = $expires_date/1000;

//                Tool::asynAddLog('request-param',$expires_date.'----'.time());
                trace('request-param&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&');
                trace($expires_date);
                trace('request-param&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&');


                if($expires_date > time()){


                }else{
                    //时间不对 不处理
                }
            }
            //处理订阅产品的业务逻辑
            echo '完成!';die;
        }
    }











}

 

 

 

返回参数(重头戏):

[ log ] array (
  'receipt' => 
  array (
    'receipt_type' => 'ProductionSandbox',
    'adam_id' => 0,
    'app_item_id' => 0,
    'bundle_id' => 'com.spanish.jietengshe',
    'application_version' => '1.2',
    'download_id' => 0,
    'version_external_identifier' => 0,
    'receipt_creation_date' => '2020-06-02 09:03:31 Etc/GMT',
    'receipt_creation_date_ms' => '1591088611000',
    'receipt_creation_date_pst' => '2020-06-02 02:03:31 America/Los_Angeles',
    'request_date' => '2020-06-02 09:03:40 Etc/GMT',
    'request_date_ms' => '1591088620543',
    'request_date_pst' => '2020-06-02 02:03:40 America/Los_Angeles',
    'original_purchase_date' => '2013-08-01 07:00:00 Etc/GMT',
    'original_purchase_date_ms' => '1375340400000',
    'original_purchase_date_pst' => '2013-08-01 00:00:00 America/Los_Angeles',
    'original_application_version' => '1.0',
    'in_app' => 
    array (
      0 => 
      array (
        'quantity' => '1',
        'product_id' => '1',
        'transaction_id' => '1000000673581721',
        'original_transaction_id' => '1000000673581721',
        'purchase_date' => '2020-06-02 08:56:34 Etc/GMT',
        'purchase_date_ms' => '1591088194000',
        'purchase_date_pst' => '2020-06-02 01:56:34 America/Los_Angeles',
        'original_purchase_date' => '2020-06-02 08:56:34 Etc/GMT',
        'original_purchase_date_ms' => '1591088194000',
        'original_purchase_date_pst' => '2020-06-02 01:56:34 America/Los_Angeles',
        'is_trial_period' => 'false',
      ),
      1 => 
      array (
        'quantity' => '1',
        'product_id' => '2',
        'transaction_id' => '1000000673586536',
        'original_transaction_id' => '1000000673586536',
        'purchase_date' => '2020-06-02 09:03:31 Etc/GMT',
        'purchase_date_ms' => '1591088611000',
        'purchase_date_pst' => '2020-06-02 02:03:31 America/Los_Angeles',
        'original_purchase_date' => '2020-06-02 09:03:31 Etc/GMT',
        'original_purchase_date_ms' => '1591088611000',
        'original_purchase_date_pst' => '2020-06-02 02:03:31 America/Los_Angeles',
        'is_trial_period' => 'false',
      ),
    ),
  ),
  'status' => 0,
  'environment' => 'Sandbox',
)

完成业务逻辑,结束,注意异步回调,才是解决掉单的关键,另外还有查单接口需要调试

 

 

参考地址:

https://www.jianshu.com/p/25d64699e20e

https://blog.csdn.net/u013358222/article/details/100540180

https://www.dazhuanlan.com/2019/12/16/5df6e8505f861/?__cf_chl_jschl_tk__=6b2be0bc60331884beca64b941e0b8c9c526853a-1590029597-0-AZBVHWlSXDdMvlJDbxikNOyVJuxSdOsBjHjo1qURz5pGZwXm8hnEo9CxpbkwMA-RZGliiymKxNF92kPyfcR_fQQoZIbfVEI4896pKojh2lOPoZQtJUTmP0Wz8ojIb8RSYkpgM-EXgdEunjLG8o697rD8QjdauJvXeGCZ6KR7yQOSyRk5ssLoNb3BUd8WJVnSKClfY_U_Kz3McPUXLcHvKtgxJ8Zd1Mc2LuiHtYn99Wz47itf5MWePE0e1mNU-4HUL4SMcpV43kqmp3HDaKRw2HEqUCK-cQWyt2qvWF7tDzA5qV7UzyoeFf0wwNV5d1bgSA

 

你可能感兴趣的:(IOS苹果支付,苹果支付,PHP发起苹果支付)