Logistics.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. <?php
  2. namespace common\helpers;
  3. use common\models\Region;
  4. use Yii;
  5. class Logistics
  6. {
  7. const prodDomain = 'https://warehouse.taoplus.com.my';
  8. const testDomain = 'http://warehouse.worldsyntech.com';
  9. // 1.获取bearer token,此token是其他api调用时的必传参数.
  10. const authenticationUrl = 'https://warehouse.taoplus.com.my/index.php?route=rest/admin_security/api_login&grant_type=client_credentials';
  11. // 2.创建订单和产品(以前不存在/已提交的产品).
  12. const createOrderUrl = 'https://warehouse.taoplus.com.my/index.php?route=rest/warehouse_api/add_order';
  13. // 3.获取产品/包裹的重量和状态.
  14. const getProductUrl = '/index.php?route=rest/warehouse_api/get_order_product';
  15. // 4.获取订单重量,m3,包装的包裹数量,费用跟踪号码和状态.
  16. const getOrderUrl = '/index.php?route=rest/warehouse_api/get_order';
  17. // 5.通知仓库已经付款,包裹可以投递.
  18. const notifyDeliveryUrl = '/index.php?route=rest/ warehouse_api/notify_delivery';
  19. // 6.创建产品/包裹.
  20. const addProductUrl = '/index.php?route=rest/warehouse_api/add_order_product';
  21. // 7.创建交付订单并将现有产品绑定到订单.需要先调用接口6创建商品.
  22. const createOrderSimpleUrl = '/index.php?route=rest/warehouse_api/add_order_simple';
  23. // 8.计算订单费用,并将订单状态改为待付款.
  24. const stockOutUrl = '/index.php?route=rest/warehouse_api/stock_out';
  25. // 9.通知物流系统订单不可删除.error包含错误的订单ID.
  26. const notifyOrderUndeletableUrl = '/index.php?route=rest/warehouse_api/notify_order_undeletable';
  27. // 10.取消订单产品/包裹。它将状态更改为无效,并保留订单产品/包裹.
  28. const cancelOrderProductUrl = ' /index.php?route=rest/warehouse_api/cancel_order_product';
  29. // 11.从数据库中删除订购产品/包裹.
  30. const deleteOrderProductUrl = '/index.php?route=rest/warehouse_api/delete_order_product';
  31. // 12.取消订单,状态改为无效,保留订单不删除.
  32. const cancelOrderUrl = '/index.php?route=rest/warehouse_api/cancel_order';
  33. // 13.从数据库中删除订单.
  34. const deleteOrderUrl = '/index.php?route=rest/warehouse_api/delete_order';
  35. // 14.运单追踪.
  36. const trackOrderUrl = 'https://taoplus.com.my/index.php?route=information/order_tracking/json&order_tracking_search=';
  37. // accessToken的缓存key
  38. const wstLogisticsBearerTokenKey = 'wstLogisticsBearerToken';
  39. // 国家
  40. const country = 'China';
  41. function __construct()
  42. {
  43. // if (!\Yii::$app->redis->get(self::wstLogisticsBearerTokenKey)) {
  44. $this->getAuthentication();
  45. // }
  46. }
  47. function getDomain()
  48. {
  49. $env = 'prod';
  50. return $env === 'prod' ? self::prodDomain : self::testDomain;
  51. }
  52. /**
  53. * 通用curl接口.
  54. * @param string $url api接口url
  55. * @param array $request_body 参数
  56. * @return mixed
  57. */
  58. function curl($url, $request_body)
  59. {
  60. $accessToken = \Yii::$app->redis->get(self::wstLogisticsBearerTokenKey);
  61. $ch = curl_init($url);
  62. header('Content-Type: application/json');
  63. $authorization = "Authorization: Bearer " . $accessToken;
  64. curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', $authorization]);
  65. curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
  66. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  67. curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($request_body));
  68. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  69. $response = curl_exec($ch);
  70. curl_close($ch);
  71. return json_decode($response, true);
  72. }
  73. // 1.获取bearer token,此token是其他api调用时的必传参数.
  74. function getAuthentication()
  75. {
  76. $request = [
  77. 'user_name' => Yii::$app->params['wst']['userName'],
  78. 'password' => Yii::$app->params['wst']['password'],
  79. 'agent_id' => Yii::$app->params['wst']['agentId'],
  80. ];
  81. LoggerTool::info(['curl', self::authenticationUrl, self::createOrderUrl]);
  82. $ch = curl_init(self::authenticationUrl);
  83. header('Content-Type: application/json');
  84. $authorization = "Authorization: Basic " . Yii::$app->params['wst']['baseToken'];
  85. curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', $authorization]);
  86. curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
  87. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  88. curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($request));
  89. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  90. $response = curl_exec($ch);
  91. LoggerTool::info(['getAuthentication', $response]);
  92. curl_close($ch);
  93. $result = json_decode($response, true);
  94. if ($result['success']) {
  95. // token和过期时间写入redis
  96. \Yii::$app->redis->set(self::wstLogisticsBearerTokenKey, $result['data']['access_token']);
  97. \Yii::$app->redis->expire(self::wstLogisticsBearerTokenKey, $result['data']['expires_in']);
  98. }
  99. }
  100. // 2.创建订单和产品(以前不存在/已提交的产品).
  101. function createOrder($order)
  102. {
  103. $request = [
  104. 'order_no' => $order['SN'], // 客户系统中的订单号
  105. 'delivery_method_id' => '133', // 快递方式ID. TODO:
  106. 'warehouse_id' => '1', // 仓库ID. TODO:
  107. 'country' => 'China', // 收件人国家 Malaysia
  108. 'state' => Region::getCnName($order['PROVINCE']), // , // 收件人省 Johor(test)
  109. 'city' => Region::getCnName($order['CITY']) . Region::getCnName($order['COUNTY']), // 收件市县
  110. 'post_code' => $order['ZIP_CODE'], // 收件人邮政编码 14000(test)
  111. 'address' => $order['ADDRESS'], // 送货地址
  112. 'consignee' => $order['CONSIGNEE_REAL_NAME'], // 收货人姓名,使用订单中的收货人真实姓名
  113. 'consignee_ic_number' => $order['CONSIGNEE_ID_NO'],
  114. 'telephone' => $order['MOBILE'], // 收件人电话号码
  115. 'sender' => $order['CONSIGNEE_REAL_NAME'],
  116. 'products' => [
  117. [
  118. 'product_no' => $order['SKU_CODE'], // 客户系统中的产品编号
  119. 'product_name' => $order['GOODS_TITLE'], // 产品名称
  120. 'tracking_number' => Date::today('Ymd') . $this->_random(10, 1),
  121. 'quantity' => $order['BUY_NUMS'], // 产品数量
  122. 'total_price' => number_format($order['PAY_AMOUNT'] * 0.3, 2, '.', ''), // 订单总金额,Decimal 方便通关,减少金额
  123. 'currency_code' => 'CNY', // 产品的货币代码. 如USD(美元),MYR(马来西亚林吉特),SGD(新加坡元),CNY(人民币)
  124. ],
  125. ],
  126. ];
  127. LoggerTool::info(['actionLogisticsOrder', $order, $request]);
  128. return $this->curl(self::createOrderUrl, $request);
  129. }
  130. // 3.获取产品/包裹的重量和状态.
  131. function getProduct($order)
  132. {
  133. $request = [
  134. 'tracking_number' => '027300027300',
  135. ];
  136. $response = $this->curl(self::getProductUrl, $request);
  137. LoggerTool::info($response);
  138. return $response;
  139. }
  140. // 4.获取订单重量,m3,包装的包裹数量,费用跟踪号码和状态
  141. function getOrder($order)
  142. {
  143. $request = [
  144. 'order_id' => 'elg8-785',
  145. ];
  146. $response = $this->curl(self::getOrderUrl, $request);
  147. LoggerTool::info($response);
  148. return $response;
  149. }
  150. // 5.通知仓库已经付款,包裹可以投递.
  151. function notifyDelivery($order)
  152. {
  153. $request = [
  154. 'order_id' => 'elg8-785',
  155. ];
  156. $response = $this->curl(self::notifyDeliveryUrl, $request);
  157. LoggerTool::info($response);
  158. return $response;
  159. }
  160. // 6.创建产品/包裹.
  161. function addProduct($orderProducts)
  162. {
  163. $products = [];
  164. foreach ($orderProducts as $item) {
  165. $products[] = [
  166. "product_no" => $item['SKU_CODE'],
  167. "product_name" => $item['GOODS_TITLE'],
  168. "tracking_number" => '',
  169. "quantity" => $item['BUY_NUMS'],
  170. "total_price" => $item['REAL_PV'],
  171. "currency_code" => "CNY",
  172. ];
  173. }
  174. $request = [
  175. 'warehouse_id' => '1',
  176. "products" => $products
  177. ];
  178. $response = $this->curl(self::addProductUrl, $request);
  179. LoggerTool::info($response);
  180. return $response;
  181. }
  182. // 7.创建交付订单并将现有产品绑定到订单.需要先调用接口6创建商品.
  183. function createOrderSimple($order)
  184. {
  185. $request = [
  186. "order_no" => "T-1000",
  187. "delivery_method_id" => "39",
  188. "warehouse_id" => "1",
  189. "country" => "Malaysia",
  190. "state" => "Pulau Pinang",
  191. "city" => "Bukit Mertajam",
  192. "post_code" => "14000",
  193. "address" => "1584,JALAN NANGKA,TAMAN JAMBU MAWAR,14000 BUKIT MERTAJAM",
  194. "consignee" => "TSA",
  195. "consignee_ic_number" => "111111-11-1111",
  196. "telephone" => "017-5423223",
  197. "cod" => "CNY",
  198. "cod_currency_code" => "100",
  199. "address_area" => "",
  200. "address_subdivision" => "",
  201. "products" => [
  202. [
  203. "product_no" => "12345",
  204. "tracking_number" => "2019061112A1",
  205. ],
  206. [
  207. "product_no" => "23456",
  208. "tracking_number" => "20190604_A12",
  209. ]
  210. ]
  211. ];
  212. $response = $this->curl(self::createOrderSimpleUrl, $request);
  213. LoggerTool::info($response);
  214. return $response;
  215. }
  216. // 8.根据货物重量计算订单费用,并更改订单状态为待付款
  217. function stockOut($order)
  218. {
  219. $request = [
  220. 'order_id' => 'elg8-785',
  221. 'weight' => '2.5', // 订单重量(KG)
  222. ];
  223. $response = $this->curl(self::stockOutUrl, $request);
  224. LoggerTool::info($response);
  225. return $response;
  226. }
  227. // 9.通知物流系统订单不可删除. error包含错误的订单ID.
  228. function notifyOrderUndeletable($order)
  229. {
  230. $request = [
  231. 'order_ids' => ['elg8-785']
  232. ];
  233. $response = $this->curl(self::notifyOrderUndeletableUrl, $request);
  234. LoggerTool::info($response);
  235. return $response;
  236. }
  237. // 10.取消订单产品/包裹。它将状态更改为无效,并保留订单产品/包裹.
  238. function cancelOrderProduct($order)
  239. {
  240. $request = [
  241. 'order_product_ids' => ['15895', '15896', '15897']
  242. ];
  243. $response = $this->curl(self::cancelOrderProductUrl, $request);
  244. LoggerTool::info($response);
  245. return $response;
  246. }
  247. // 11.从数据库中删除订购产品/包裹.
  248. function deleteOrderProduct($order)
  249. {
  250. $request = [
  251. 'order_product_ids' => ['15895', '15896', '15897']
  252. ];
  253. $response = $this->curl(self::deleteOrderProductUrl, $request);
  254. LoggerTool::info($response);
  255. return $response;
  256. }
  257. // 12.取消订单,状态改为无效,保留订单不删除.
  258. function cancelOrder($order)
  259. {
  260. $request = [
  261. 'order_ids' => ['elg8-787', 'elg8-786']
  262. ];
  263. $response = $this->curl(self::cancelOrderUrl, $request);
  264. LoggerTool::info($response);
  265. return $response;
  266. }
  267. // 13.从数据库中删除订单.
  268. function deleteOrder($order)
  269. {
  270. $request = [
  271. 'order_ids' => ['elg8-787', 'elg8-786']
  272. ];
  273. $response = $this->curl(self::deleteOrderUrl, $request);
  274. LoggerTool::info($response);
  275. return $response;
  276. }
  277. // 13.从数据库中删除订单.
  278. function trackOrder($trackNo)
  279. {
  280. // 运单号
  281. $trackNo = 'TBS10182495KJ2430';
  282. $curl = curl_init();
  283. curl_setopt($curl,CURLOPT_TIMEOUT,5000);
  284. curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,false);
  285. curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,false);
  286. curl_setopt($curl,CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
  287. curl_setopt($curl,CURLOPT_URL, self::trackOrderUrl . $trackNo);
  288. curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
  289. $response = curl_exec($curl);
  290. if (!$response) {
  291. $error = curl_errno($curl);
  292. curl_close($curl);
  293. LoggerTool::error($error);
  294. return false;
  295. }
  296. curl_close($curl);
  297. $result = json_decode($response, true);
  298. LoggerTool::info($result);
  299. return $result['data'];
  300. }
  301. /**
  302. * 生成随机数
  303. * @param $length
  304. * @param int $numeric
  305. * @return string
  306. */
  307. private function _random($length, $numeric = 0) {
  308. $seed = base_convert(md5(microtime() . $_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
  309. $seed = $numeric ? (str_replace('0', '', $seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed));
  310. $hash = '';
  311. $max = strlen($seed) - 1;
  312. for ($i = 0; $i < $length; $i++) {
  313. $hash .= $seed[mt_rand(0, $max)];
  314. }
  315. return $hash;
  316. }
  317. }