Dada.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------\
  11. namespace crmeb\services\delivery\storage;
  12. use crmeb\basic\BaseDelivery;
  13. use think\exception\ValidateException;
  14. class Dada extends BaseDelivery
  15. {
  16. const BASE_URL = 'https://newopen.imdada.cn';
  17. const ADD_MERCHANT = '/merchantApi/merchant/add';
  18. const ADD_SHOP = '/api/shop/add';
  19. const UPDATE_SHOP = '/api/shop/update';
  20. const GET_CITY_CODE = '/api/cityCode/list';
  21. const GET_SHOP_DETAIL = '/api/shop/detail';
  22. const GET_ORDER_PRICE = '/api/order/queryDeliverFee';
  23. const ADD_ORDER_AFTER_QUERY = '/api/order/addAfterQuery';
  24. const ADD_ORDER_STSATUS_QUERY = '/api/order/status/query';
  25. const GET_REASONS = '/api/order/cancel/reasons';
  26. const CANCEL_ORDER = '/api/order/formalCancel';
  27. const GET_BALANCE = '/api/balance/query';
  28. const GET_RECHARGE = '/api/recharge';
  29. public $config;
  30. public function initialize(array $config)
  31. {
  32. $this->config = $config;
  33. parent::initialize($config);
  34. }
  35. /**
  36. * 创建商户
  37. * @param $data
  38. * @return mixed
  39. */
  40. public function addMerchant($data)
  41. {
  42. return $this->sendRequest(self::ADD_MERCHANT, $data);
  43. }
  44. /**
  45. * 创建门店
  46. * @param $data
  47. * @return mixed
  48. */
  49. public function addShop($data)
  50. {
  51. $parmas[] = $data;
  52. return $this->sendRequest(self::ADD_SHOP, $parmas);
  53. }
  54. /**
  55. * 更新门店
  56. * @param $data
  57. * @return mixed
  58. */
  59. public function updateShop($data)
  60. {
  61. $params['origin_shop_id'] = $data['origin_shop_id'];
  62. if (isset($data['new_shop_id'])) $params['new_shop_id'] = $data['new_shop_id'];
  63. if (isset($data['station_name'])) $params['station_name'] = $data['station_name'];
  64. if (isset($data['business'])) $params['business'] = $data['business'];
  65. if (isset($data['station_address'])) $params['station_address'] = $data['station_address'];
  66. if (isset($data['lng'])) $params['lng'] = $data['lng'];
  67. if (isset($data['lat'])) $params['lat'] = $data['lat'];
  68. if (isset($data['contact_name'])) $params['contact_name'] = $data['contact_name'];
  69. if (isset($data['phone'])) $params['phone'] = $data['phone'];
  70. if (isset($data['status'])) $params['status'] = $data['status'];
  71. return $this->sendRequest(self::UPDATE_SHOP, $params);
  72. }
  73. /**
  74. * 预发布订单
  75. * @param $data
  76. * @return mixed
  77. */
  78. public function addOrder($data)
  79. {
  80. $params = [
  81. 'deliveryNo' => $data['deliveryNo'],
  82. ];
  83. return $this->sendRequest(self::ADD_ORDER_AFTER_QUERY, $params);
  84. }
  85. /**
  86. * 计算订单价格
  87. * @param $data
  88. * @return mixed
  89. */
  90. public function getOrderPrice($data)
  91. {
  92. $params = [
  93. 'shop_no' => $data['shop_no'],
  94. 'origin_id' => $data['origin_id'],
  95. 'city_code' => $data['city_code'],
  96. 'cargo_price' => $data['cargo_price'],
  97. 'is_prepay' => $data['is_prepay'],
  98. 'receiver_name' => $data['receiver_name'],
  99. 'receiver_address'=> $data['receiver_address'],
  100. 'callback' => $this->callback_url,
  101. 'cargo_weight' => $data['cargo_weight'],
  102. 'receiver_phone' => $data['receiver_phone'],
  103. 'is_finish_code_needed'=> $data['is_finish_code_needed'],
  104. ];
  105. return $this->sendRequest(self::GET_ORDER_PRICE, $params);
  106. }
  107. /**
  108. * 获取订单详情
  109. * @param $data
  110. * @return mixed
  111. */
  112. public function getOrderDetail($data)
  113. {
  114. $params['order_id'] = $data['origin_id'];
  115. return $this->sendRequest(self::ADD_ORDER_STSATUS_QUERY, $params);
  116. }
  117. /**
  118. * 取消订单
  119. * @param $data
  120. * @return mixed
  121. */
  122. public function cancelOrder($data)
  123. {
  124. $params['order_id'] = $data['origin_id'];
  125. $params['cancel_reason'] = $data['cancel_reason'] ?? '无';
  126. $params['cancel_reason_id'] = $data['reason'];
  127. return $this->sendRequest(self::CANCEL_ORDER, $params);
  128. }
  129. /**
  130. * 获取充值地址
  131. * @param $data
  132. * @return mixed
  133. */
  134. public function getRecharge($data =[])
  135. {
  136. $params = [
  137. 'amount' => $data['amount'] ?? 100,
  138. 'category'=> $data['category'] ?? 'PC',
  139. ];
  140. return $this->sendRequest(self::GET_RECHARGE, $params);
  141. }
  142. /**
  143. * 获取余额
  144. * @param $data
  145. * @return mixed
  146. */
  147. public function getBalance($data)
  148. {
  149. $params['category'] = $data['category'] ?? 3;
  150. $res = $this->sendRequest(self::GET_BALANCE, $params);
  151. return [
  152. 'deliverBalance' => $res['deliverBalance']
  153. ];
  154. }
  155. /**
  156. * 支付小费
  157. * @param $data
  158. * @return mixed
  159. */
  160. public function addTip($data)
  161. {
  162. return true;
  163. }
  164. /**
  165. * 取消原因
  166. * @param $data
  167. * @return mixed
  168. */
  169. public function reasons($data = '')
  170. {
  171. $options = $this->sendRequest(self::GET_REASONS, $data);
  172. foreach ($options as $option) {
  173. $value = $option['id'];
  174. $label = $option['reason'];
  175. $res[] = compact('value','label');
  176. }
  177. return $res;
  178. }
  179. /**
  180. * 获取城市信息
  181. * @param $data
  182. * @return mixed
  183. */
  184. public function getCity($data = '')
  185. {
  186. $res = $this->sendRequest(self::GET_CITY_CODE, $data);
  187. foreach ($res as $item) {
  188. $data[] = [
  189. 'key' => $item['cityName'],
  190. 'label' => $item['cityName'],
  191. ];
  192. }
  193. return $data;
  194. }
  195. /**
  196. * 获取门店信息
  197. * @param $data
  198. * @return mixed
  199. */
  200. public function getShopDetail($id)
  201. {
  202. $data = ['origin_shop_id' => $id];
  203. return $this->sendRequest(self::GET_SHOP_DETAIL, $data);
  204. }
  205. public function getBusiness()
  206. {
  207. return [
  208. ['key' => 1 , 'label' => '食品小吃'],
  209. ['key' => 2 , 'label' => '饮料'],
  210. ['key' => 3 , 'label' => '鲜花绿植'],
  211. ['key' => 5 , 'label' => '其他'],
  212. ['key' => 8 , 'label' => '文印票务'],
  213. ['key' => 9 , 'label' => '便利店'],
  214. ['key' => 13 , 'label' => '水果生鲜'],
  215. ['key' => 19 , 'label' => '同城电商'],
  216. ['key' => 20 , 'label' => '医药'],
  217. ['key' => 21 , 'label' => '蛋糕'],
  218. ['key' => 24 , 'label' => '酒品'],
  219. ['key' => 25 , 'label' => '小商品市场'],
  220. ['key' => 26 , 'label' => '服装'],
  221. ['key' => 27 , 'label' => '汽修零配'],
  222. ['key' => 28 , 'label' => '数码家电'],
  223. ['key' => 29 , 'label' => '小龙虾/烧烤'],
  224. ['key' => 31 , 'label' => '超市'],
  225. ['key' => 51 , 'label' => '火锅'],
  226. ['key' => 53 , 'label' => '个护美妆'],
  227. ['key' => 55 , 'label' => '母婴'],
  228. ['key' => 57 , 'label' => '家居家纺'],
  229. ['key' => 59 , 'label' => '手机'],
  230. ['key' => 61 , 'label' => '家装'],
  231. ['key' => 63 , 'label' => '成人用品'],
  232. ];
  233. }
  234. public function sendRequest($api, $params)
  235. {
  236. $url = self::BASE_URL . $api;
  237. $params = $this->bulidRequestParams($params);
  238. $response = $this->httpRequestWithPost($url, $params);
  239. $data = $this->getMessage($response);
  240. return $data;
  241. }
  242. /**
  243. * 构造请求数据
  244. * data:业务参数,json字符串
  245. */
  246. public function bulidRequestParams($params)
  247. {
  248. $requestParams = array();
  249. $requestParams['app_key'] = $this->config['app_key'];
  250. $requestParams['body'] = json_encode($params);
  251. $requestParams['format'] = 'json';
  252. $requestParams['v'] = '1.0';
  253. $requestParams['source_id'] = $this->config['source_id'];
  254. $requestParams['timestamp'] = time();
  255. $requestParams['signature'] = $this->_sign($requestParams);
  256. return json_encode($requestParams);
  257. }
  258. /**
  259. * 签名生成signature
  260. */
  261. public function _sign($data)
  262. {
  263. //1.升序排序
  264. ksort($data);
  265. //2.字符串拼接
  266. $args = "";
  267. foreach ($data as $key => $value) {
  268. $args .= $key . $value;
  269. }
  270. $args = $this->config['app_secret'] . $args . $this->config['app_secret'];
  271. //3.MD5签名,转为大写
  272. $sign = strtoupper(md5($args));
  273. return $sign;
  274. }
  275. /**
  276. * 发送请求,POST
  277. * @param $url 指定URL完整路径地址
  278. * @param $data 请求的数据
  279. */
  280. public function httpRequestWithPost($url, $data, $headers = [])
  281. {
  282. $headers = array(
  283. 'Content-Type: application/json',
  284. );
  285. $curl = curl_init($url);
  286. curl_setopt($curl, CURLOPT_URL, $url);
  287. curl_setopt($curl, CURLOPT_HEADER, false);
  288. curl_setopt($curl, CURLOPT_POST, true);
  289. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  290. curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
  291. curl_setopt($curl, CURLOPT_TIMEOUT, 3);
  292. curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  293. $resp = curl_exec($curl);
  294. $info = curl_getinfo($curl);
  295. curl_close($curl);
  296. if (isset($info['http_code']) && $info['http_code'] == 200) {
  297. return $resp;
  298. }
  299. return ;
  300. }
  301. protected function getMessage($json, $message = '未知错误!')
  302. {
  303. $data = json_decode($json, true);
  304. if ($data['code'] !== 0) {
  305. isset($data['msg']) && $message = $data['msg'];
  306. if ($data['errorCode'] == 7718) {
  307. foreach ($data['result']['failedList'] as $datum) {
  308. $message .= ':'.$datum['shopName'].'/'. $datum['msg'].';';
  309. }
  310. }
  311. throw new ValidateException('【达达错误提示】:'.$message);
  312. } else {
  313. if ($data['status'] == 'success') return $data['result'] ?? $data;
  314. return $data;
  315. }
  316. }
  317. }