文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

PHP App Store Server API 苹果API退款 查询订单 历史订单 PHP校验签名解码

2023-09-26 15:15

关注

本文使用是基于thinkPHP 实现相关的功能,Python、java等实现的网上都有相关的实现连接。不说废话,直接开始。

一、安装jwt.

composer 安装【强烈推荐】本文用这种方式:

composer require firebase/php-jwt

自己上传下载的安装包,下载地址在下面,如果是用这种方式,请独自引入相关的load,如【require_once '/xxx/xxx/xxx/xxxx/autoload.php';】:

https://github.com/firebase/php-jwt

二、找好相关参数及文件

         $this->private_key = file_get_contents('/xxx/xxxx/xxxx/xxxx/teset.p8'); //密钥
        //公钥 官网可以下载,但要将cer转化为pem PHP只能读取pem格式
        $this->pub_key = file_get_contents('/xxx/xxx/xxx/xxxx/xxx/testappleRootCA-G3.pem'); 
        $this->kid = 'test'; //kid
        $this->bundle_id = 'com.test.com.package'; //工程包名
        $this->iss = '123445-23456-1111-0000-123456789111';

苹果公钥下载链接,需转换为转换为pem格式:https://www.apple.com/certificateauthority/AppleRootCA-G3.cer

不知道的具体看看这篇文章,里面说明了参数该在那里找:WWDC21 - App Store Server API 实践总结 - 腾讯云开发者社区-腾讯云

三、正式写代码

private_key = file_get_contents('/xxx/xxxx/xxxx/xxxx/teset.p8'); //密钥        //公钥 官网可以下载,但要将cer转化为pem PHP只能读取pem格式        $this->pub_key = file_get_contents('/xxx/xxx/xxx/xxxx/xxx/testappleRootCA-G3.pem');         $this->kid = 'test'; //kid        $this->bundle_id = 'com.test.com.package'; //工程包名        $this->iss = '123445-23456-1111-0000-123456789111';    }       // 请求苹果的订单查询接口    public function getapple()    {        try {            $orderid = input('orderid');//接收输入的订单号查询            $url = "https://api.storekit.itunes.apple.com/inApps/v1/lookup/" . $orderid;            $res = $this->getres($url);            if (!empty($res['signedTransactions'])) {                $data = $res['signedTransactions'];                $resl = [];                foreach ($data as $k => $v) {                    $payload = $this->decodePayNotifyV2($v);                    $resl[] = $payload;                }                dump($resl);            }        } catch (\Throwable $th) {            echo $th->getMessage();        }    }    // 查询苹果用户历史收据【消耗型商品只返回退款\失效订单数据】    function gethis()    {        $orderid = input('orderid');        $url = 'https://api.storekit.itunes.apple.com/inApps/v1/history/' . $orderid;        $res = $this->getres($url);        $resl = [];        dump($res);        if (!empty($res['signedTransactions'])) {            foreach ($res['signedTransactions'] as $k => $v) {                $payload = $this->decodePayNotifyV2($v);                $resl[] = $payload;            }        }        dump($resl);    }    // 查询订单退款记录    function getrefund()    {        $orderid = input('orderid');        $url = 'https://api.storekit.itunes.apple.com/inApps/v1/refund/lookup/' . $orderid;        $res = $this->getres($url);        $resl = [];        dump($res);        if (!empty($res['signedTransactions'])) {            foreach ($res['signedTransactions'] as $k => $v) {                $payload = $this->decodePayNotifyV2($v);                $resl[] = $payload;            }        }        dump($resl);    }      //获取Authorization: Bearer    private function authorbeaer()    {                $this->payload  = [            'iss' => $this->iss, //iss值            'iat' => intval(time()),            'exp' => intval(time() + 3600),            'aud' => 'https://appleid.apple.com',  //固定值            'bid' => $this->bundle_id, //应用bundle_id        ];        $this->header = [            "alg" => "ES256",            "kid" => $this->kid,            "typ" => "JWT"        ];        $token = JWT::encode($this->payload, $this->private_key, $this->algorithm, $this->kid, $this->header);        return $token;    }    // 校验签名并解码返回数据    public function decodePayNotifyV2($jwt)    {        list($header, $payload, $sign) = explode('.', $jwt);        $header_decode = base64_decode($header);        $header_json = json_decode($header_decode, true);        if (!isset($header_json['x5c'])) {            // 解析失败                      return false;        }        //这一步是将公钥转成对应的格式        $pubkey = "-----BEGIN CERTIFICATE-----\n" . $header_json['x5c'][0] . "\n-----END CERTIFICATE-----";        try {            $decoded = JWT::decode($jwt, new Key($pubkey,  $header_json['alg']));            // 判断返回的证书链是否等于苹果公钥证书            $pem = $this->pub_key;            $str = str_replace("\r\n", "", $pem);            $pubPem = "-----BEGIN CERTIFICATE-----" . $header_json['x5c'][2] . "-----END CERTIFICATE-----";            if ($str != $pubPem) {                // 返回的公钥证书链错误                           }        } catch (\Exception $e) {            // 签名校验失败                        return false;        }        return json_decode(json_encode($decoded), true);    }    //发起请求 获取token     private function getres($url, $token = null)    {        $jwt_str = $token ?? $this->authorbeaer();        $curl = curl_init();        curl_setopt_array($curl, array(            CURLOPT_URL => $url,            CURLOPT_RETURNTRANSFER => true,            CURLOPT_ENCODING => '',            CURLOPT_MAXREDIRS => 10,            CURLOPT_TIMEOUT => 0,            CURLOPT_FOLLOWLOCATION => true,            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,            CURLOPT_CUSTOMREQUEST => 'GET',            CURLOPT_HTTPHEADER => array(                'Authorization: Bearer ' . $jwt_str            ),        ));        $response = curl_exec($curl);        $errno = curl_errno($curl);        if (!empty($errno)) {            echo 'err:' . $errno;        }        curl_close($curl);        $res = json_decode($response, true);        return $res;    }}

三、小结

代码应该都是挺简单的,大概的流程就是:将下面三部分转码变成JWT然后放在get请求的header中的Authorization 中,形式就是:Bearer AJDasdfaSFJFJFGFL【‘JWT’】,

然后如果成功会返回相对应的结果,这里提供一些坑:

查询订单号时,要用用户端的订单号,大致形式是这样子的:MVL678M6AL;如果用其他订单号查询会返回:{status:1}这是订单错误的提示;

校验并返回结果的时候,decode函数参数要注意一下,假如返回的结果如下图,

$jwt:就是【signedTransactions[0]的值】,$header_json['alg']就是刚开始转码前的那个,这里的是ES256;$pubkey这里不是那个官网下载的公钥,jwt用小数点(.)分割后,base64_decode后再json_decode后得到一个key:【x5c】的数组,里面有3个证书链,取用下标为0的那个证书链作为这里的值。而开头准备的那个公钥是用来比对X5C下标为2的那个证书链

JWT::decode($jwt, new Key($pubkey,  $header_json['alg']));

至于其他的,欢迎大家补充,有啥疑问的,可以在评论区留言,大家探讨探讨。

下面有大牛写的文章,详细看看,写得非常好:

WWDC21 - App Store Server API 实践总结 - 腾讯云开发者社区-腾讯云

WWDC21 - App Store Server API 实践总结 - 掘金

下面的这个大佬的校验是有点的问题的,仅供参考

苹果商店退款API PHP验签 signedPayload - 简书

来源地址:https://blog.csdn.net/weixin_45143733/article/details/129714412

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯