'查询消息池表tenantId不存在', 515024 => '请购买选品库', 300001 => '参数无效,内容:s', 300000 => 'spuId的数量不得超过500', 300002 => 'sku编码数量不得超过200', 507033 => '同一时间请勿重复提交', 507003 => '必填参数为空', 507087 => '商品匹配错误', 507080 => '该收货地址不在配送范围', 507086 => '暂无报价', 507089 => '获取运营商信息失败', 507090 => '预付款扣减失败', 507017 => '订单不存在', 507055 => '确认收货失败', 507043 => '该订单当前状态不能取消', ]; /** * 初始化 * * @param array $config */ private function __construct(array $config) { if (empty($config['app_key']) || empty($config['app_secret'])) { throw new Exception('缺少appKey,或者appSecret'); } parent::__construct($config); } /** * 禁止克隆 * * @return void */ public function __clone() { } /** * 获取自身实例化 * * @param array $config * @return BaseApi */ public static function getInstance($config = []) { if (self::$instance instanceof self) { return self::$instance; } else { return new self($config); } } /** * 获取分类信息 1.0版 * * @param array $params * @param string $method * @return array */ public function getCategorys($params = [], $method = 'post') { $data = $params; return $this->guzz('/scce/cmc/cmc/spu/open/getCategorys', $data, $method); } /** * 查询商品库SPUID列表 1.0版 * * @param array $params * @param string $method * @return array */ public function getSpuIdList($params = [], $method = 'post') { $data = array_merge([ 'hasVideo' => '', 'createStartTime' => '', 'pageIndex' => '', 'createEndTime' => '', 'brandId' => '', 'pageSize' => '24', 'firstCategoryId' => '', 'secondCategoryId' => '', 'thirdCategoryId' => '', 'status' => '' ], $params); return $this->guzz('/scce/cmc/cmc/spu/open/getSpuIdList', $data, $method); } /** * 查询SPU商品详情 1.0版 * * @param array $params * @param string $method * @return array */ public function getSpuBySpuIds($params = [], $method = 'post') { $data['spuIdList'] = $params; return $this->guzz('/scce/cmc/cmc/spu/open/getSpuBySpuIds', $data, $method); } /** * 查询SKU规格信息 1.0版(单个查询) * * @param string $id * @param string $method * @return array */ public function listSkuBySpuId($id, $method = 'post') { $data['spuId'] = $id; return $this->guzz('/scce/cmc/cmc/spu/open/listSkuBySpuId', $data, $method); } /** * 查询SKU规格信息 1.0版(复数查询) * * @param array $ids * @param string $method * @return array */ public function listSkuBySpuIds($ids = [], $method = 'post') { $requests = function ($data) use ($method) { foreach ($data as $id) { yield $this->getRequest('/scce/cmc/cmc/spu/open/listSkuBySpuId', ['spuId' => $id], $method); } }; // 创建关系数据用于存储返回数据 $result = []; foreach ($ids as $v) { $result[] = [ 'spuId' => $v ]; } return $this->pool($requests, $ids, $result); } /** * 查询SPU商品详情 1.0版(pool) * * @param array $spu_ids * @param string $method * @return array */ public function getSpuBySpuIdsPool($spu_ids = [], $method = 'post') { $requests = function ($spu_ids) use ($method) { foreach ($spu_ids as $id) { $data['spuIdList'] = [$id]; yield $this->getRequest('/scce/cmc/cmc/spu/open/getSpuBySpuIds', $data, $method); } }; return $this->pool($requests, $spu_ids); } /** * 获取省市区地址 1.0版 * * @param string $region_code * @param string $method * @return array */ public function getRegionByCodeOpen($region_code = '', $method = 'post') { $data['regionCode'] = $region_code; return $this->guzz('/scce/pbc/pbc/region/getRegionByCodeOpen', $data, $method); } /** * 查询商品运费 1.0版 * * @param array $freight * [ * spuInfoList => [ * quantity => 商品数量 * spuId => 商品spuId * ], * orderSn => 订单号 * cityId => 收货城市ID * ] * @param string $method * @return string */ public function calculate($freight, $method = 'post') { return $this->guzz('/scce/cmc/cmc/freight/calculate', $freight, $method); } /** * 创建订单 1.0版 * * @param array $data * @param string $method * @return array */ public function submitOrder($data, $method = 'post') { return $this->guzz('/scce/ctc/ctc/reseller/order/submitOrder', $data, $method); } /** * 查询消息池表 1.0版 * * @param integer $enum 消息枚举值 * @param string $content 消息内容 * @param string $method * @return array */ public function messagePool($enum = null, $content = null, $method = 'post') { $data = []; $enum && $data['enumNum'] = $enum; $content && $data['content'] = $content; return $this->guzz('/scce/opm/opm/messagePool/list/page', $data, $method); } /** * 删除消息 1.0版 * * @param array $ids 需要删除的消息IDS * @param integer $enum 消息枚举值 * @param string $method * @return array */ public function removeMessagePoolByParam(array $ids, $enum = null, $method = 'post') { $data['id'] = implode(',', $ids); $enum && $data['enumNum'] = $enum; return $this->guzz('/scce/opm/opm/messagePool/removeMessagePoolByParam', $data, $method); } /** * 查询订单详情 1.0版 * * @param string $order_sn * @param string $method * @return array */ public function getOrderDetail($order_sn, $method = 'post') { $data['orderSn'] = $order_sn; return $this->guzz('/scce/ctc/ctc/reseller/order/getOrderDetail', $data, $method); } /** * 查询物流信息 1.0版 * * @param string $order_sn 订单编号 * @param string $delivery_sn 物流单号 * @param string $method * @return array */ public function getOrderExpressListByOs($order_sn, $delivery_sn = null, $method = 'post') { $data['orderSn'] = $order_sn; $delivery_sn && $data['deliverySn'] = $delivery_sn; return $this->guzz('/scce/ctc/ctc/tOrderExpress/getOrderExpressListByOs', $data, $method); } /** * 售后申请 1.0版 * * @param array $data * @param string $method * @return array */ public function applyRefund($data, $method = 'post') { return $this->guzz('/scce/ctc/ctc/reseller/orderReturnGoods/applyRefund', $data, $method); } /** * 查询售后单详细信息 1.0版 * * @param string $return_sn * @param string $method * @return array */ public function orderReturnGoodsDetail($return_sn, $method = 'post') { $data['returnSn'] = $return_sn; return $this->guzz('/scce/ctc/ctc/reseller/orderReturnGoods/detail', $data, $method); } /** * 确认收货 1.0版 * * @param string $order_sn 订单编号 * @param string $operator 操作人 * @param string $method * @return boolean */ public function confirmReceive($order_sn, $operator, $method = 'post') { $data['orderSn'] = $order_sn; $data['operator'] = $operator; return $this->guzz('/scce/ctc/ctc/reseller/order/confirmReceive', $data, $method); } /** * 退货/换货邮寄卖家 1.0版 * * @param string $returnSn * @param string $deliverySn * @param string $deliveryCorpName * @param string $method * @return array */ public function sendReturnGoods($return_sn, $delivery_sn, $delivery_corp_name, $method = 'post') { $data['returnSn'] = $return_sn; $data['deliverySn'] = $delivery_sn; $data['deliveryCorpName'] = $delivery_corp_name; return $this->guzz('/scce/ctc/ctc/reseller/orderReturnGoods/sendReturnGoods', $data, $method); } /** * 换货确认收货 1.0版 * * @param string $returnSn * @param string $method * @return array */ public function receiptRefund($return_sn, $method = 'post') { $data['returnSn'] = $return_sn; return $this->guzz('/scce/ctc/ctc/reseller/orderReturnGoods/receiptRefund', $data, $method); } /** * 批量校验下单商品销售范围和库存 1.0版 * * @param array $itemDTOList * @param string $areaRegionCode * @return array */ public function checkSkuStock(array $itemDTOList, string $areaRegionCode, $method = 'post') { $data = compact('itemDTOList', 'areaRegionCode'); return $this->guzz('/scce/cmc/cmc/spu/open/checkSkuStock', $data, $method); } /** * 请求 * * @param string $api * @param array $data * @param string $method * @return array */ private function request($api, $data = [], $method = 'get') { try { $result = $this->curl($this->url . $api, $data, $method); if ($result['status'] == 200) { return $result['data']; } throw new Exception( $result['msg'] // $this->errorMsg($result['status']) ); } catch (Exception $e) { dd($e); } } /** * 错误信息 * * @param integer $code * @return string */ private function errorMsg($code) { return isset($this->err_code[$code]) ? $this->err_code[$code] : '未知错误'; } /** * 执行curl * * @param string $url * @param array $data * @param string $method * @return array */ private function curl($url, $data = [], $method = 'get') { if ($method == 'get' && !empty($data)) { $str = http_build_query($data); $url = strpos($url, '?') === false ? $url . '?' . $str : $url . '&' . $str; } // Header头 $headers = $this->formatHeader($this->getHeaders($data)); if ($this->debug) { echo "
";
            var_dump($headers);
        }

        $curl = curl_init();
        $timeout = 5;
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
        if ($method == 'post') {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, Json::encode($data));
        }
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        $curl_data = curl_exec($curl);
        if (curl_error($curl)) {
            $error = '错误:' . $url . '=>' . curl_error($curl);
            throw new Exception($error);
        }
        return Json::decode($curl_data);
    }

    /**
     * 请求池
     *
     * @param array $requests
     * @return array
     */
    public function pool($requests, $data, $result = null)
    {
        $relation = $result === null ? false : true;
        $pool = new Pool($this->getClient(), $requests($data), [
            'concurrency' => $this->concurrency,
            'fulfilled' => function ($response, $index) use (&$result, $relation) {
                // this is delivered each successful response
                $relation 
                    ? $result[$index] = array_merge(
                        $result[$index],
                        ['data' => $this->getResponseData($response, $index)]
                    )
                    : $result[] = $this->getResponseData($response, $index);
            },
            'rejected' => function ($reason, $index) {
                // this is delivered each failed request
            },
        ]);
        $promise = $pool->promise();
        $promise->wait();

        return $result;
    }

    /**
     * 使用Guzz请求
     *
     * @param string $api
     * @param array $data
     * @param string $method
     * @return array
     */
    private function guzz($api, $data = [], $method = 'post')
    {
        // 客户端
        $client = $this->getClient();
        // Header头
        $data = array_filter($data, function ($item) {
            return $item !== null && $item !== '';
        });
        $response = $client->send($this->getRequest($api, $data, $method));

        return $this->getResponseData($response);
    }

    /**
     * 获取响应数据
     *
     * @param ResponseInterface $response
     * @param integer|null $index
     * @return array|void
     */
    private function getResponseData($response, $index = null)
    {
        $code = $response->getStatusCode();
        $reason = $response->getReasonPhrase();
        $content = $response->getBody()->getContents();

        \Yii::$app->custom->logs('星链响应信息', $content);
        if ($code == 200) {
            $data = Json::decode($content);
            // 返回状态码
            if ($data['status'] == 200) {
                return $data['data'] ?? [];
            }
            if (!$this->exception) {
                return [];
            }
            throw new Exception($data['msg']);
        }
        throw new Exception('查询失败');
    }

    /**
     * 获取请求
     *
     * @param array $data
     * @param string $method
     * @return Request
     */
    public function getRequest($api, $data, $method)
    {
        \Yii::$app->custom->logs('星链请求信息', $api);
        \Yii::$app->custom->logs('请求数据', $data);
        if ($this->debug) {
            echo "API:";
            var_dump($api);
            echo "
"; echo "DATA:"; var_dump($data); echo "
"; } $body = empty($data) ? '{}' : Json::encode($data); return new Request(strtoupper($method), $api, $this->getHeaders($data), $body); } /** * 获取guzz客户端 * * @return Client */ public function getClient() { return new Client([ 'base_uri' => $this->url, 'verify' => false ]); } /** * 获取请求头 * * @param array $body * @return array */ private function getHeaders($body = []) { mt_srand(); // appKey、version、timeStamp、randomNumber $headers = [ 'appKey' => $this->app_key, 'version' => $this->version, 'timeStamp' => time() - 3 . '000', // 'timeStamp' => '1638424611703', 'randomNumber' => mt_rand(1000000, 9999999), // 'randomNumber' => '5441080065398753214', ]; // 签名 $headers['sign'] = $this->getSign($headers, $body); $headers['Content-Type'] = 'application/json'; \Yii::$app->custom->logs('星链请求头', $headers); if ($this->debug) { echo "HEADERS:"; var_dump($headers); echo "
"; } return $headers; } /** * 转换header头 curl使用 * * @param array $headers * @return array */ private function formatHeader($headers) { // 转换 $result = []; foreach ($headers as $k => $v) { $result[] = $k . ':' . $v; } return $result; } /** * 获取签名 * * @param array $headers * @param array $body * @return string */ private function getSign($headers, $body) { $arr = array_merge($headers, $body); ksort($arr); $str = ''; foreach ($arr as $k => $v) { $str .= $k . '=' . (is_array($v) ? Json::encode($v) : $v) . '&'; } $str .= $this->app_secret; $str = trim($str); \Yii::$app->custom->logs('星链签名', $str); return md5($str); } /** * 设置不抛异常 * * @param boolean $boolean * @return void */ public function setNotExcption($boolean = false) { return $this->exception = false; } }