// +----------------------------------------------------------------------\ namespace crmeb\services\delivery\storage; use crmeb\basic\BaseDelivery; use think\exception\ValidateException; class Dada extends BaseDelivery { const BASE_URL = 'https://newopen.imdada.cn'; const ADD_MERCHANT = '/merchantApi/merchant/add'; const ADD_SHOP = '/api/shop/add'; const UPDATE_SHOP = '/api/shop/update'; const GET_CITY_CODE = '/api/cityCode/list'; const GET_SHOP_DETAIL = '/api/shop/detail'; const GET_ORDER_PRICE = '/api/order/queryDeliverFee'; const ADD_ORDER_AFTER_QUERY = '/api/order/addAfterQuery'; const ADD_ORDER_STSATUS_QUERY = '/api/order/status/query'; const GET_REASONS = '/api/order/cancel/reasons'; const CANCEL_ORDER = '/api/order/formalCancel'; const GET_BALANCE = '/api/balance/query'; const GET_RECHARGE = '/api/recharge'; public $config; public function initialize(array $config) { $this->config = $config; parent::initialize($config); } /** * 创建商户 * @param $data * @return mixed */ public function addMerchant($data) { return $this->sendRequest(self::ADD_MERCHANT, $data); } /** * 创建门店 * @param $data * @return mixed */ public function addShop($data) { $parmas[] = $data; return $this->sendRequest(self::ADD_SHOP, $parmas); } /** * 更新门店 * @param $data * @return mixed */ public function updateShop($data) { $params['origin_shop_id'] = $data['origin_shop_id']; if (isset($data['new_shop_id'])) $params['new_shop_id'] = $data['new_shop_id']; if (isset($data['station_name'])) $params['station_name'] = $data['station_name']; if (isset($data['business'])) $params['business'] = $data['business']; if (isset($data['station_address'])) $params['station_address'] = $data['station_address']; if (isset($data['lng'])) $params['lng'] = $data['lng']; if (isset($data['lat'])) $params['lat'] = $data['lat']; if (isset($data['contact_name'])) $params['contact_name'] = $data['contact_name']; if (isset($data['phone'])) $params['phone'] = $data['phone']; if (isset($data['status'])) $params['status'] = $data['status']; return $this->sendRequest(self::UPDATE_SHOP, $params); } /** * 预发布订单 * @param $data * @return mixed */ public function addOrder($data) { $params = [ 'deliveryNo' => $data['deliveryNo'], ]; return $this->sendRequest(self::ADD_ORDER_AFTER_QUERY, $params); } /** * 计算订单价格 * @param $data * @return mixed */ public function getOrderPrice($data) { $params = [ 'shop_no' => $data['shop_no'], 'origin_id' => $data['origin_id'], 'city_code' => $data['city_code'], 'cargo_price' => $data['cargo_price'], 'is_prepay' => $data['is_prepay'], 'receiver_name' => $data['receiver_name'], 'receiver_address'=> $data['receiver_address'], 'callback' => $this->callback_url, 'cargo_weight' => $data['cargo_weight'], 'receiver_phone' => $data['receiver_phone'], 'is_finish_code_needed'=> $data['is_finish_code_needed'], ]; return $this->sendRequest(self::GET_ORDER_PRICE, $params); } /** * 获取订单详情 * @param $data * @return mixed */ public function getOrderDetail($data) { $params['order_id'] = $data['origin_id']; return $this->sendRequest(self::ADD_ORDER_STSATUS_QUERY, $params); } /** * 取消订单 * @param $data * @return mixed */ public function cancelOrder($data) { $params['order_id'] = $data['origin_id']; $params['cancel_reason'] = $data['cancel_reason'] ?? '无'; $params['cancel_reason_id'] = $data['reason']; return $this->sendRequest(self::CANCEL_ORDER, $params); } /** * 获取充值地址 * @param $data * @return mixed */ public function getRecharge($data =[]) { $params = [ 'amount' => $data['amount'] ?? 100, 'category'=> $data['category'] ?? 'PC', ]; return $this->sendRequest(self::GET_RECHARGE, $params); } /** * 获取余额 * @param $data * @return mixed */ public function getBalance($data) { $params['category'] = $data['category'] ?? 3; $res = $this->sendRequest(self::GET_BALANCE, $params); return [ 'deliverBalance' => $res['deliverBalance'] ]; } /** * 支付小费 * @param $data * @return mixed */ public function addTip($data) { return true; } /** * 取消原因 * @param $data * @return mixed */ public function reasons($data = '') { $options = $this->sendRequest(self::GET_REASONS, $data); foreach ($options as $option) { $value = $option['id']; $label = $option['reason']; $res[] = compact('value','label'); } return $res; } /** * 获取城市信息 * @param $data * @return mixed */ public function getCity($data = '') { $res = $this->sendRequest(self::GET_CITY_CODE, $data); foreach ($res as $item) { $data[] = [ 'key' => $item['cityName'], 'label' => $item['cityName'], ]; } return $data; } /** * 获取门店信息 * @param $data * @return mixed */ public function getShopDetail($id) { $data = ['origin_shop_id' => $id]; return $this->sendRequest(self::GET_SHOP_DETAIL, $data); } public function getBusiness() { return [ ['key' => 1 , 'label' => '食品小吃'], ['key' => 2 , 'label' => '饮料'], ['key' => 3 , 'label' => '鲜花绿植'], ['key' => 5 , 'label' => '其他'], ['key' => 8 , 'label' => '文印票务'], ['key' => 9 , 'label' => '便利店'], ['key' => 13 , 'label' => '水果生鲜'], ['key' => 19 , 'label' => '同城电商'], ['key' => 20 , 'label' => '医药'], ['key' => 21 , 'label' => '蛋糕'], ['key' => 24 , 'label' => '酒品'], ['key' => 25 , 'label' => '小商品市场'], ['key' => 26 , 'label' => '服装'], ['key' => 27 , 'label' => '汽修零配'], ['key' => 28 , 'label' => '数码家电'], ['key' => 29 , 'label' => '小龙虾/烧烤'], ['key' => 31 , 'label' => '超市'], ['key' => 51 , 'label' => '火锅'], ['key' => 53 , 'label' => '个护美妆'], ['key' => 55 , 'label' => '母婴'], ['key' => 57 , 'label' => '家居家纺'], ['key' => 59 , 'label' => '手机'], ['key' => 61 , 'label' => '家装'], ['key' => 63 , 'label' => '成人用品'], ]; } public function sendRequest($api, $params) { $url = self::BASE_URL . $api; $params = $this->bulidRequestParams($params); $response = $this->httpRequestWithPost($url, $params); $data = $this->getMessage($response); return $data; } /** * 构造请求数据 * data:业务参数,json字符串 */ public function bulidRequestParams($params) { $requestParams = array(); $requestParams['app_key'] = $this->config['app_key']; $requestParams['body'] = json_encode($params); $requestParams['format'] = 'json'; $requestParams['v'] = '1.0'; $requestParams['source_id'] = $this->config['source_id']; $requestParams['timestamp'] = time(); $requestParams['signature'] = $this->_sign($requestParams); return json_encode($requestParams); } /** * 签名生成signature */ public function _sign($data) { //1.升序排序 ksort($data); //2.字符串拼接 $args = ""; foreach ($data as $key => $value) { $args .= $key . $value; } $args = $this->config['app_secret'] . $args . $this->config['app_secret']; //3.MD5签名,转为大写 $sign = strtoupper(md5($args)); return $sign; } /** * 发送请求,POST * @param $url 指定URL完整路径地址 * @param $data 请求的数据 */ public function httpRequestWithPost($url, $data, $headers = []) { $headers = array( 'Content-Type: application/json', ); $curl = curl_init($url); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); curl_setopt($curl, CURLOPT_TIMEOUT, 3); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); $resp = curl_exec($curl); $info = curl_getinfo($curl); curl_close($curl); if (isset($info['http_code']) && $info['http_code'] == 200) { return $resp; } return ; } protected function getMessage($json, $message = '未知错误!') { $data = json_decode($json, true); //code=2551 订单创建中 if (!in_array($data['code'], [0, 2551])) { isset($data['msg']) && $message = $data['msg']; if ($data['errorCode'] == 7718) { foreach ($data['result']['failedList'] as $datum) { $message .= ':'.$datum['shopName'].'/'. $datum['msg'].';'; } } throw new ValidateException('【达达错误提示' . $data['code'] . '】:'.$message); } else { if ($data['status'] == 'success') { return $data['result'] ?? $data; } return $data; } } }