插件窝 干货文章 ThinkPHP5对接IOS苹果支付代码

ThinkPHP5对接IOS苹果支付代码

amp gt result 支付 322    来源:    2024-10-29

ThinkPHP5使用IOS支付流程:

1、前端在调起苹果支付前,先请求到服务端,服务端先生成一条充值记录,但是状态为:未支付;然后把这个订单id发给前端。

2、前端在支付完成的时候,会收到苹果的支付凭证,将此凭证和订单id回传给服务端。订单id的作用是用来确定是哪一笔。支付凭证是拿来校验是否支付成功。检验成功后,自己的业务逻辑(将该条订单的状态改为已支付,然后加余额或延长会员时间)

ThinkPHP5接口代码

<?php
namespace app\index\controller\v1\ios;
use app\index\controller\Base;
use fast\Random;
use think\Db;
use think\Request;
class Applepay extends Base {
    /**
     * 获取套餐
     * @return \think\response\Json
     */
    public function getpackage(){
        $t=[
            ['id'=>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;
        }
    }
}

IOS内购接口返回参数示例

[ 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',
)

到此这篇关于ThinkPHP5对接IOS苹果支付代码的文章就介绍到这了,更多相关ThinkPHP5使用IOS支付内容请搜索插件窝以前的文章或继续浏览下面的相关文章希望大家以后多多支持插件窝!