PHP对接快手平台

学习记录 留作参考
祝君好运

实际业务中需要使用PHP对接快手平台,而快手官方只给出了一个JAVA的SDK。结合网络上找到的一些代码,自己又整理了一份。

参考内容:
快手开放平台新手指南
CSDN相关使用PHP对接快手平台的博客

<?php

/**
 * 业务方法
 * 
 * 需要自行配置快手账号信息,来获得授权。
 * 本文使用文件记录访问快手接口的token信息,需要自行配置保存目录,默认为当前目录。
 */
class index
{
    public $ksToolObj = null;

    public function __construct()
    {
        // 从配置文件中读取快手平台的账号信息
        $appKey = config::get('appKey');
        $appSecret = config::get('appSecret');
        $signSecret = config::get('signSecret');
        $secretKey = config::get('secretKey');

        $this->ksToolObj = new ksTool($appKey, $appSecret, $signSecret, $secretKey);

        // 配置一个保存日志缓存文件的目录。
        if (!defined("STORAGE_DIR")) {
            define('STORAGE_DIR', './');
        }
    }

    /**
     * code换取token的方法,所有的请求都需要access_token
     * @param string $code 用户的授权code
     */
    public function code($code)
    {
        try {
            $this->ksToolObj->code2Token($code);
        } catch (\Exception $e) {
            print_r($e->getMessage());
        }
    }

    /**
     * 示例方法,实际业务
     */
    public function someMethod()
    {
        try {
            $api = 'open.funds.financial.bill.batch.detail';
            $param = array();
            $param['cursor'] = '';
            $param['settlementStartTime'] = strtotime('2023-1-1') * 1000;
            $param['settlementEndTime'] = strtotime('2023-1-4') * 1000;

            $res = $this->ksToolObj->ksData($api, $param, 'get');
            $this->__saveFileStorage($res); // 为了方便查看效果而记录文件日志
            print_r($res);
        } catch (\Exception $e) {
            print_r($e->getMessage());
        }
    }

    // 记录文件日志
    private function __saveFileStorage($res)
    {
        $logStr = date('Y-m-d H:i:s') . "\n" . var_export($res, true) . "\n\n";
        file_put_contents(STORAGE_DIR . './ks.log', $logStr, FILE_APPEND);
    }
}


class ksTool
{
    public $appKey;
    public $appSecret;
    public $signSecret;
    public $secretKey;
    public $urlCommon = 'https://openapi.kwaixiaodian.com';

    // 通过接口获取的token
    public $access_token = '';

    public function __construct($appKey, $appSecret, $signSecret, $secretKey = '')
    {
        $this->appKey = $appKey;
        $this->appSecret = $appSecret;
        $this->signSecret = $signSecret;
        $this->secretKey = $secretKey;
    }

    /**
     * 通过code获取 refresh_token和access_token (调用次数比较少)
     * @param string $code 测试用户或者授权用户的授权code
     * @return array
     * @throws Exception
     */
    public function code2Token($code)
    {
        $param['app_id'] = $this->appKey;
        $param['app_secret'] = $this->appSecret;
        $param['grant_type'] = 'code';
        $param['code'] = $code;

        $url = $this->urlCommon . '/oauth2/access_token?' . http_build_query($param, '', '&');
        $res = $this->requestGet($url);

        if ($res && $res['result'] === 1) {
            $setRes = $this->__setStorageData($res);
            if ($setRes === false) {
                throw new Exception('缓存文件记录失败!');
            }
            return ['code' => 0, 'msg' => 'refresh token is success'];
        } else {
            $errStr = '';
            if ($res && is_array($res)) {
                foreach ($res as $key => $val) {
                    $errStr .= $key . ':' . $val . ' ';
                }
            }
            throw new Exception('通过code获取Token失败。响应:' . $errStr);
        }
    }

    /**
     * 通用的调用快手接口的方法
     * @param string $apiName 快手平台的接口
     * @param array $param 请求参数
     * @param string $method 请求方式
     * @return array
     * @throws Exception
     */
    public function ksData($apiName, $param = [], $method = 'get')
    {
        if (!$this->access_token) {
            $this->__getStorageToken();
        }

        $sendData['access_token'] = $this->access_token;
        $sendData['appkey'] = $this->appKey;
        $sendData['method'] = $apiName;
        $sendData['param'] = $param ? json_encode($param) : "{}";
        $sendData['signMethod'] = 'MD5';
        $sendData['timestamp'] = intval(microtime(true) * 1000);
        $sendData['version'] = 1;
        ksort($sendData);

        $paramStr = '';
        foreach ($sendData as $key => $val) {
            $paramStr .= $key . "=" . $val . "&";
        }
        $signStr = $paramStr . 'signSecret=' . $this->signSecret;

        $sendData['sign'] = md5($signStr);

        $url = $this->urlCommon . '/' . str_replace('.', '/', $sendData['method']);
        if (strtolower($method) === 'post') {
            $res = $this->requestPost($url, $sendData);
        } else {
            $url .= '?' . http_build_query($sendData, '', '&');
            $res = $this->requestGet($url);
        }
        return $res;
    }

    /**
     * 获取缓存到文件的token信息
     */
    private function __getStorageToken()
    {
        $fileStr = file_get_contents(STORAGE_DIR . '/kuaishou.conf.txt');
        if ($fileStr && $fileArr = json_decode($fileStr, true)) {
            if ($fileArr['access_expires'] > time() + 900) {
                $this->access_token = $fileArr['access_token'];
            } else if ($fileArr['refresh_expires'] > time()) {
                $this->__refreshAllToken($fileArr['refresh_token']);
            } else {
                throw new \Exception('refresh_token已经失效');
            }
        } else {
            throw new \Exception('未找到快手平台有效的token数据');
        }
    }

    /**
     * 保存快手接口返回的token信息
     * @param array $res 快手接口的响应信息
     * @return bool|int
     */
    private function __setStorageData($res)
    {
        $res['access_expires'] = time() + $res['expires_in']; // 计算access_token失效时间戳
        $res['refresh_expires'] = time() + $res['refresh_token_expires_in']; // 计算refresh_token失效时间戳
        $this->access_token = $res['access_token'];

        unset($res['expires_in'], $res['refresh_token_expires_in']);
        return file_put_contents(STORAGE_DIR . '/kuaishou.conf.txt', json_encode($res)); // 实际开发需要的变量
    }

    /**
     * 通过refresh_token来刷新access_token,同时refresh_token也会被刷新。
     * @param string $refreshToken
     * @return array
     * @throws Exception
     */
    private function __refreshAllToken($refreshToken)
    {
        $param['app_id'] = $this->appKey;
        $param['app_secret'] = $this->appSecret;
        $param['grant_type'] = 'refresh_token';
        $param['refresh_token'] = $refreshToken;

        $url = $this->urlCommon . '/oauth2/refresh_token?' . http_build_query($param, '', '&');
        $res = $this->requestGet($url);

        if ($res && $res['result'] === 1) {
            $setRes = $this->__setStorageData($res);
            if ($setRes === false) {
                throw new Exception('缓存文件记录失败!');
            }
            return ['code' => 0, 'msg' => 'refresh token is success'];
        } else {
            throw new Exception('刷新access_token失败。 error_msg:' . $res['error_msg']);
        }
    }

    /**
     * 发送GET请求
     */
    private function requestGet($url)
    {
        $headerArray = array("Content-type:application/x-www-form-urlencoded;", "Accept:application/json;charset=UTF-8");
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray);
        $output = curl_exec($ch);
        curl_close($ch);
        return json_decode($output, true, 512, JSON_BIGINT_AS_STRING);
    }

    /**
     * 发送POST请求
     */
    private function requestPost($url, $data)
    {
        $data = json_encode($data);
        $headerArray = array("Content-type:application/x-www-form-urlencoded;", "Accept:application/json;charset=UTF-8");
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headerArray);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        return json_decode($output, true, 512, JSON_BIGINT_AS_STRING);
    }
}
posted @   azsd  阅读(118)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示