iOS连续订阅IAP自动续订服务端接入流程

2 篇文章 2 订阅

业务逻辑

 注意:

  1. 同一Apple 账号生成续订订单的原始交易ID(original_transaction_id)一致

  2. 服务端处理交易过程 :要确定一个交易ID(transaction_id)只能完成一笔订单,处理完该交易的订单之后,该交易ID记录标识为处理完成状态

  3. 服务端可以通过用户购买凭证(receipt_data)查询用户所有交易记录 查询到的数据有in_app、latest_receipt_info、pending_renewal_info

  4. 连续订阅主要用到数据是latest_receipt_info,里面有所有的续订记录。

  5. 如果里面的交易有cancellation_date字段,说明该交易已经被退款。

  6. pending_renewal_info里面的auto_renew_status字段用于标识用户是否开通自动订阅;0:已关闭;1:已开通。

在接收 App Store的续订、取消、退款通知时,因为选择的版本2(version 2 notification)的通知,版本二通知是jwt编码实现。

所以需要解码,方法如下:

<?php

class IapNotifyController extends Controller
{

    public function notify(Request $request){
        $post_data = $request->getContent();
        $data = json_decode($post_data,true);
        $data = $data['signedPayload'];
        $data = $this->verifyToken($data);
        $data['signedTransactionInfo'] = $this->verifyToken($data['data']['signedTransactionInfo']);
        $data['signedRenewalInfo'] = $this->verifyToken($data['data']['signedRenewalInfo']);
        if($data) {
             /*通知类型
             https://developer.apple.com/documentation/appstoreservernotifications/notificationtype
             CONSUMPTION_REQUEST 表示客户针对消耗品内购发起退款申请
             DID_CHANGE_RENEWAL_PREF 对其订阅计划进行了更改 如果subtype是UPGRADE,则用户升级了他们的订阅;如果subtype是DOWNGRADE,则用户将其订阅降级或交叉分级
             DID_CHANGE_RENEWAL_STATUS 通知类型及其subtype指示用户对订阅续订状态进行了更改
             DID_FAIL_TO_RENEW 一种通知类型及其subtype指示订阅由于计费问题而未能续订
             DID_RENEW 一种通知类型,连同其subtype指示订阅成功续订
             EXPIRED 一种通知类型及其subtype指示订阅已过期
             GRACE_PERIOD_EXPIRED 表示计费宽限期已结束,无需续订,因此您可以关闭对服务或内容的访问
             OFFER_REDEEMED 一种通知类型,连同其subtype指示用户兑换了促销优惠或优惠代码。 subtype DID_RENEW
             PRICE_INCREASE 一种通知类型,连同其subtype指示系统已通知用户订阅价格上涨
             REFUND 表示 App Store 成功为消耗性应用内购买、非消耗性应用内购买、自动续订订阅或非续订订阅的交易退款
             REFUND_DECLINED 表示 App Store 拒绝了应用开发者发起的退款请求
             RENEWAL_EXTENDED 表示 App Store 延长了开发者要求的订阅续订日期
             REVOKE表示 用户有权通过家庭共享获得的应用内购买不再通过共享获得
             SUBSCRIBED 一种通知类型,连同其subtype指示用户订阅了产品
             1. 用户主动取消订阅notificationType:DID_CHANGE_RENEWAL_STATUS
             2. 用户取消订阅,又重新开通连续订阅notificationType: SUBSCRIBED  subtype: RESUBSCRIBE
             3. 用户首次开通订阅notificationType: SUBSCRIBED  subtype: INITIAL_BUY
             */
            $notification_type = $data['notificationType'];
            $transactionData = $data['signedTransactionInfo'];
            $product_id = $transactionData['productId'];
            $sub_type = isset($data['subtype']) ? $data['subtype'] : '';
            $original_transaction_id = $transactionData['originalTransactionId'];  // //原始交易ID
            $transaction_id = $transactionData['transactionId'];  //  //交易的标识
            $expires_date = date('Y-m-d H:i:s',$transactionData['expiresDate']/1000);
            //todo 记录通知log

            //查询原始交易绑定的用户ID
            if (in_array($notification_type, ['DID_RENEW','SUBSCRIBED'])) {
                //开通成功以及续订成功处理交易
            }

            //用户退款处理交易
            if (in_array($notification_type, ['REFUND'])) {
                
            }

            //用户取消订阅或者订阅过期
            if (in_array($notification_type, ['EXPIRED','DID_FAIL_TO_RENEW'])
                || ($notification_type == 'DID_CHANGE_RENEWAL_STATUS')) {
                   $is_renew = 0;
                   if(($notification_type == 'DID_CHANGE_RENEWAL_STATUS') && $sub_type == 'AUTO_RENEW_ENABLED')
                   {
                       //开通订阅成功
                   }elseif (($notification_type == 'DID_CHANGE_RENEWAL_STATUS') && $sub_type == 'AUTO_RENEW_DISABLED'){
                       //取消订阅成功
                   }
                   //更新用户订阅状态
            }
        }
    }

 

    /**
     * 验证token是否有效,默认验证exp,nbf,iat时间
     * @param string $Token 需要验证的token
     * @return bool|string
     */
    public static function verifyToken($Token)
    {
        $tokens = explode('.', $Token);
        if (count($tokens) != 3)
            return false;

        list($base64header, $base64payload) = $tokens;

        //获取jwt算法
        $base64decodeheader = json_decode(self::base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY);
        if (empty($base64decodeheader['alg']) || $base64decodeheader['alg'] != 'ES256')
            return false;

        $payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);

        return $payload;
    }

    /**
     * base64UrlEncode   https://jwt.io/  中base64UrlEncode编码实现
     * @param string $input 需要编码的字符串
     * @return string
     */
    private static function base64UrlEncode($input)
    {
        return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
    }

    /**
     * base64UrlEncode  https://jwt.io/  中base64UrlEncode解码实现
     * @param string $input 需要解码的字符串
     * @return bool|string
     */
    private static function base64UrlDecode($input)
    {
        $remainder = strlen($input) % 4;
        if ($remainder) {
            $addlen = 4 - $remainder;
            $input .= str_repeat('=', $addlen);
        }
        return base64_decode(strtr($input, '-_', '+/'));
    }

}

参考文章:IAP 自动续费后端接入指南_theCrucian的博客-CSDN博客

iOS自动续订订阅开发----验证收据和状态回调JSON解析 - 简书

  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
iOS 16上的内购项目(IAP)经历超时问题时,可能会导致用户无法完成购买或受阻于支付过程。这可能是由于多种因素引起的,包括网络连接问题、服务器故障或应用程序错误等。以下是一些可能的解决方法: 1. 检查网络连接:首先,请确保您的设备已正确连接至互联网。尝试连接其他应用或使用浏览器验证网络连接是否正常。 2. 重启设备和应用程序:关闭并重新启动设备,然后重新打开应用程序。这有助于刷新应用程序的状态并清除可能存在的临时错误。 3. 更新应用程序和iOS版本:检查应用商店或系统设置中是否有可用的应用程序或iOS更新。更新通常包括修复错误和增强功能,可能有助于解决超时问题。 4. 清除应用程序缓存:在iOS设置中找到应用程序,并尝试清除其缓存。这有时可以解决应用程序运行过程中的问题。 5. 取消和重新购买:如果内购项目超时,尝试取消并重新提交购买请求。确保您的支付信息正确并且账户余额充足。 6. 联系技术支持:如果问题仍然存在,请联系应用程序的开发者或苹果的技术支持团队。提供详细的问题描述和相关的错误信息,以便他们可以帮助您解决问题。 总结而言,iOS 16上的IAP超时问题可能是由于网络连接、设备或应用程序错误引起的。通过检查网络连接、重启设备和应用程序、更新软件、清除缓存、重新购买或联系技术支持,您可以尝试解决这个问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值