PHP服务端 苹果内购支付(IAP),免费试用连续订阅等功能讲解

本文详细描述了如何在PHP服务端处理苹果应用内订阅支付,包括主动购买和订阅续费两种模式,涉及订单验证、票据解析、业务逻辑处理和通知接收等步骤,并分享了相关代码示例。
摘要由CSDN通过智能技术生成
 公司最近项目app需要做苹果订阅支付,开始觉得和微信的支付流程差不多,做起来还是有点麻烦,主要是网上的
 文章很少,不能直接硬抄。自己做完总结一下,希望对小伙伴们有帮助。

首先讲一下我的业务逻辑,也就是php服务端需要做什么事情。

先上图:

在这里插入图片描述

下面我详细的讲一下我的做法,并贴出来相应的代码供大家参考。

其实支付是有两种(我理解的分两种)
 1》第一种是主动直接购买,app创建订单,我们将订单信息保存,然后app调用SDK发起支付,这个时候会走苹果自
 己的支付,不管支付结果咋样,客户端会获取到一个苹果给到的receipt(俗称票据),此时客户端将票据和我们
 自己创建的订单号传给服务端进行验证,验证完成之后再进行相应的发货逻辑处理

票据其实就是一串很长的字符串,我们拿它到苹果服务器验证完成之后,会解析成一堆明文数据,我们在进行相应
的处理
 下面我贴一下代码:
/**
 * @title 验证支付票据 完成订单接口
 */
public function ios_pay()
    {
        $receipt_data = $_REQUEST['ios_billon'] ?? '';
        $order_id = $_REQUEST['order_id'] ?? '';
        
        $result = array('status' => false, 'message' => '非法参数');
        if (empty($receipt_data) || empty($order_id)) {
            return_json($result);
        }
        // 请求验证
        $appkey = "这里是你自己的苹果支付参数";
        $html = $this->acurl($receipt_data, $appkey);#这里封装方法去请求苹果验证票据
        $data = json_decode($html, true);
        // 如果是沙盒数据 则验证沙盒模式
        if ($data['status'] == '21007') {
            // 请求验证
            $html = $this->acurl($receipt_data, $appkey, 1);
            $data = json_decode($html, true);
            $data['sandbox'] = '1';
        }
        $str = "**************下面是票证信息".date("Y-m-d H:i:s")."*****************". "\n\r";
        file_put_contents("a.txt", $str.json_encode($data) . "\n\r", FILE_APPEND);
        // 判断是否购买成功
        if (intval($data['status']) === 0) {
            if ($data['receipt']['bundle_id'] != IOS_BUNDLE_ID || empty($data
            ['receipt']['in_app'])) {
                return_json($result);
            }
            // 找出时间最大的凭据数组
            $ks['status'] = $data['status'];
            $ks['receipt'] = $data['receipt'];
            unset($ks['receipt']['in_app']);
            $data['receipt']['in_app'][0] = $data['receipt']['latest_receipt_info'][0] ?? $data['receipt']['in_app'][0];
            //取in_app信息
            $k = array_merge($ks, $data['receipt']['in_app'][0]);
            $pay_date = date('Y-m-d H:i:s', $k['purchase_date_ms']/1000); // 购买日期
            $transaction_id = $k['transaction_id'];
            ··········
            这里是自己逻辑处理
            因为我们还有一个免费试用功能
            ··········
            if ($k['is_trial_period'] == 'true') {   // 享受了免费试用
                $update_data['money'] = 0;
                $update_data['ios_status'] = 1;//1代表免费试用中
                $is_try = 1;//1代表免费试用中
            }
            ·······
            处理完成
            ·······
        } else {
            $result = array('status' => false, 'message' => $this->err_msg[$data['status']] ?? $data['status']);
        }
        return_json($result);
    }
public function acurl($receipt_data, $appkey = "", $sandbox = 0)
    {
        //小票信息
        $POSTFIELDS = array("receipt-data" => $receipt_data);
        if (!empty($appkey)) {
            $POSTFIELDS = array("receipt-data" => $receipt_data, 'password' =>
             $appkey);
        }
        $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;
        //简单的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;
    }

验证之前的票据
在这里插入图片描述
验证之后的信息
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  	验证完返回的状态,处理订单业务逻辑,处理订单,修改订单信息,original_transaction_id 把这个
  	单号和存入订单信息,在异步回调的时候根据这个单号来查找订单信息来判断是哪个用户,苹果票据里面
  	也有产品product_id,是 app_store的产品id,不是自己业务的产品id,可以在后台把自己的产品ID和
  	 product_id 关联,处理业务逻辑。这样主动购买逻辑就完成了。
接下来是第二种:
2》通过订阅的方式购买,因为苹果订阅不一样,例如你购买一个会员之后,会在你的订阅中心有一条订阅记录,
如果你不取消,到期之后,他会自动扣款进行续费,你也可以提前进行取消订阅,到期之后,就不会再进行一个
扣款续费了。这里我建议这里与上面的接口分开,因为这个接口需要配置在苹果开发者后台的,等待他那边进行回
调。了解逻辑之后,我们再来看代码,

在这里插入图片描述

通知类型: notification_type 有很多种情况,有些通知接收存入日志,不用处理,我们要根据自己的需求进
行相关业务处理,我自己只处理了RENEWAL,DID_RENEW,INTERACTIVE_RENEWAL这些状态
public function ios_continu_pay()
    {
        $input_data = trim(file_get_contents("php://input"));
        $str = "**************下面是IOS最新信息".date("Y-m-d H:i:s")."****************
        *". "\n\r";
        file_put_contents("b.txt", $str . $input_data . "\n\r", FILE_APPEND);
        $resp_str = json_decode($input_data, true);
        if (!empty($resp_str)) {
            $data = $resp_str['unified_receipt'];
            //有时候苹果那边会传空数据调用
            // notification_type         几种状态描述
            // INITIAL_BUY               初次购买订阅。latest_receipt通过在App Store中验证,可以随时将您的服务器存储在服务器上以验证用户的订阅状态。
            // CANCEL                    Apple客户支持取消了订阅。检查Cancellation Date以了解订阅取消的日期和时间。
            // RENEWAL                   已过期订阅的自动续订成功。检查Subscription Expiration Date以确定下一个续订日期和时间。
            // INTERACTIVE_RENEWAL       客户通过使用用App Store中的App Store以交互方式续订订阅。服务立即可用。
            // DID_CHANGE_RENEWAL_PREF   客户更改了在下次续订时生效的计划。当前的有效计划不受影响。
            $notification_type = $resp_str['notification_type'];//通知类型
            $password = $resp_str['password']; // 共享秘钥
            if ($password == "你的苹果支付秘钥") {
                //latest_expired_receipt_info 好像只有更改续订状态才有
                $receipt = $data['latest_receipt_info'] ?? $data['latest_expired_receipt_info'];
                //找出来最近的那一组信息
                $receipt = self::arraySort($receipt, 'purchase_date', 'desc');
                $original_transaction_id = $receipt['original_transaction_id'];  // //原始交易ID
                $transaction_id = $receipt['transaction_id'];  //  //交易的标识
                $purchaseDate = str_replace(' America/Los_Angeles', '', $receipt['purchase_date_pst']);
                ·········
                进行你的业务处理逻辑
                ·········
            } else {
                NewLog::log('通知传递的密码不正确--password:' . $password, 'ios_pay_continu_password');
            }
        }
    }


//查找最新数据的方法
 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]; // 数据返回
}
好了,上面是我写的苹果支付所有流程和代码,业务代码部分我去掉了,大家自己写自己的业务逻辑就可以。大家
在对接过程,可能会遇到与我不一样的一些地方,因为我们做了连续订阅,免费试用等等相关功能,所以只要思路
一样就是可以了,希望这篇文章对你有所帮助。
  • 17
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大力水手z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值