diff --git a/config/wms.php b/config/wms.php index 1cacfe7..7722f45 100644 --- a/config/wms.php +++ b/config/wms.php @@ -14,13 +14,15 @@ return [ 'warehouse_id' => env('WMS_WAREHOUSE_ID', 1), ], 'gwall' => [ - 'base_uri' => env('GWALL_HOST', 'http://s.gwall.cn:8092/GwallServices3.0/WMSService?'), - 'app_key' => env('GWALL_APP_KEY', '23232323'), - 'session_key' => env('GWALL_SESSION_KEY', 'qwertyuiopasdfghjkl'), - 'version' => env('GWALL_VERSION', '3.0'), - 'format' => 'JSON', - 'encrypt' => 1, - 'warehouse_code' => env('GWALL_WAREHOUSE_CODE', 'test2306'), + 'base_uri' => env('GWALL_HOST', 'http://qimen.api.taobao.com/top/router/qmtest?'), +// 'base_uri' => env('GWALL_HOST', 'http://qimenapi.tbsandbox.com/router/qimen/service?'), + 'app_key' => env('GWALL_APP_KEY', '23152314'), + 'app_secret' => env('GWALL_APP_SECRET', 'bjpdalog'), + 'customerId' => env('WMS_CUSTOMERID','BJPDmocker'), + 'version' => env('GWALL_VERSION', '2.0'), + 'format' => 'xml', + 'sign_method' => 'md5', + 'warehouse_code' => env('GWALL_WAREHOUSE_CODE', 'test0912'), 'shipper_code' => env('GWALL_SHIPPER_CODE', 'BJPD'), 'warehouse_id' => env('GWALL_WAREHOUSE_ID', 2), ], diff --git a/src/BaseWms.php b/src/BaseWms.php index 356331f..90e0aaa 100644 --- a/src/BaseWms.php +++ b/src/BaseWms.php @@ -14,6 +14,14 @@ class BaseWms const DEFAULT_SENDER_ADDRESS = '岗山路75号维龙仓储3号库'; const DEFAULT_ZIP_CODE = '000000'; + const RK_TYPE = [ + '0' => 'CGRK', + '10' => 'DBRK', + '20' => 'QTRK', + '30' => 'XNRK', + '40' => 'QTRK', + ]; + /** * 选择物流公司 * @param string $province diff --git a/src/GwallWms.php b/src/GwallWms.php index 43145cb..ba9bacf 100644 --- a/src/GwallWms.php +++ b/src/GwallWms.php @@ -2,412 +2,11 @@ namespace PdWms; -use GuzzleHttp\Client; - -class GwallWms extends BaseWms implements WmsInterface +class GwallWms extends QimenWms { - protected $config = []; - public function __construct($config = null) { $wmsConf = $config ?? (require(dirname(dirname(__FILE__)) . '/config/wms.php'))['gwall']; - $this->config = $wmsConf; - } - - /** - * 销售发货单创建 - * @param array $params - * @return mixed - */ - public function saleOrderCreate($params) - { - $service = 'gwisSubCreateSaleOrder'; - - $detailList = []; - $skuTotalWeight = 0; - foreach ($params['order_goods'] as $item) { - if ($item['sku_type'] == 0) { - array_push($detailList, [ - 'sku' => $item['wms_code'], //SKU编码 - 'qty' => $item['sku_quantity'], //数量 - ]); - $skuTotalWeight += ($item['weight'] * $item['sku_quantity']) / 1000; - } elseif ($item['sku_type'] == 1) { - foreach ($item['sku_nexus_snapshot'] as $gv) { - array_push($detailList, [ - 'sku' => $gv['wms_code'], //SKU编码 - 'qty' => $gv['sku_quantity'] * $item['sku_quantity'], //数量 - ]); - $skuTotalWeight += ($gv['weight'] * $gv['sku_quantity'] * $item['sku_quantity']) / 1000; - } - } - } - - $postData = [ - 'headList' => [ - [ - 'orderCode' => $params['order_no'], //配货单号 - 'bity' => 'EBUS', //订单类型 EBUS:线上订单 OFFLINE:线下订单 SPECIAL:特殊订单 - 'warehouseCode' => $this->config['warehouse_code'], //仓库编码 - 'isUrgency' => 0, //是否紧急(0普通,1紧急) - 'downDate' => $params['created_at'], //下单时间(yyyy/MM/dd HH:mm:ss) - 'payTime' => $params['pay_at'], //支付时间(yyyy/MM/dd HH:mm:ss) - 'auditTime' => date('Y-m-d H:i:s'), //审核时间(即生成通知单的时间)(yyyy/MM/dd HH:mm:ss) - 'logisticsCompanyCode' => $this->chooseLogisticsCompany($params['order_address']['receive_province'], $skuTotalWeight), //物流公司编码 - 'postage' => $params['express_fee'], //邮费 - 'isDeliveryPay' => false, //是否货到付款(true/false) - 'shopName' => $order['order_sender_info']['shop_name'] ?? self::DEFAULT_SHOP_NAME, //店铺名称 - 'shopCode' => $order['order_sender_info']['shop_name'] ?? self::DEFAULT_SHOP_NAME, //店铺编码 - 'consignee' => $this->filterEmoji($params['order_address']['receive_name']), //收货人姓名 - 'postCode' => $params['order_address']['receive_zip_code'] ?? self::DEFAULT_ZIP_CODE, //邮码 - 'provinceName' => $params['order_address']['receive_province'], //省名称 - 'cityName' => $params['order_address']['receive_city'], //市名称 - 'areaName' => $params['order_address']['receive_district'], //区名称 - 'address' => $params['order_address']['receive_address'], //收货地址 - 'mobile' => trim($params['order_address']['receive_mobile']), //移动电话 - 'orderPrice' => $params['total_fee'], //订单金额 - 'amountReceivable' => $params['pay_fee'], //应收金额 - 'isPostagePay' => false, //邮费是否到付 true/false - 'actualPayment' => $params['pay_fee'], //实际支付 - 'goodsOwner' => $this->config['shipper_code'], //货主 - 'remark' => $params['remark'], //备注 - 'detailList' => $detailList, - ], - ] - ]; - - $result = $this->request($service, $postData); - return $result; - } - - /** - * 新增采购订单 - * @param array $params - * @return mixed - */ - public function purchaseOrderCreate($params) - { - $service = 'gwisSubCreatePurchaseOrder'; - - $detailList = []; - foreach ($params['sku_info'] as $skuV) { - array_push($detailList, [ - 'sku' => $skuV['wms_code'], - 'price' => $this->formatNumber($skuV['price']), - 'qty' => intval($skuV['apply_stock']) + intval($skuV['apply_bad_stock']), - ]); - } - - $postData = [ - 'head' => [ - 'orderCode' => $params['number'], - 'supplierCode' => $params['orders_purchase']['supplier_id'], - 'warehouseCode' => $this->config['warehouse_code'], - 'planDate' => $params['orders_purchase']['estimated_time'], - 'goodsOwner' => $this->config['shipper_code'], - 'remark' => $params['remarks'], - 'detailList' => $detailList, - ], - ]; - - $result = $this->request($service, $postData); - return $result; - } - - /** - * 商品库存查询(单个) - * @param string $wmsCode - * @param string $inventoryType - * @return mixed - */ - public function goodsStockInfoSingle($wmsCode, $inventoryType = 'ZP') - { - $service = 'gwisSubGetGoodsStockInfo'; - - $postData = [ - 'warehouseCode' => $this->config['warehouse_code'], - 'sku' => $wmsCode, - 'goodsOwner' => $this->config['shipper_code'], - ]; - - $result = $this->request($service, $postData); - if (!$result['success']) { - return $result; - } - $data = $result['response'][0]; - $formatData = $this->formatGoodsStockInfo($data); - return array_merge($result, ['response' => $formatData]); - } - - /** - * 商品库存查询(批量) - * @param array $params - * @param string $inventoryType - * @return array - */ - public function goodsStockInfo($params, $inventoryType = 'ZP') - { - $data = []; - foreach ($params as $item) { - $result = $this->goodsStockInfoSingle($item['wms_code']); - if (!$result['success']) { - continue; - } - array_push($data, $result['response']); - } - return ['success' => true, 'response' => $data]; - } - - /** - * 商品同步(商品创建或修改) - * @param array $params - * @return mixed - */ - public function goodsSync($params) - { - $service = 'gwisSubGoodsCreateOrUpadte'; - - $postData = [ - 'items' => [ - [ - 'sku' => $params['wms_code'], - 'goodsName' => $params['name'], - 'goodsType' => 'P', //商品属性(默认P) P:正常商品 G:赠品 S:饰品 M:辅料 C:耗材 B:包装 X:虚拟物品 L:残次品 I:发票 - 'price' => $params['unit_price'], - 'brcode' => $params['upc_code'] ?? $params['wms_code'], - 'state' => 1, //状态(默认有效) 1:有效 0:注销 - 'goodsOwner' => $this->config['shipper_code'], - ] - ], - ]; - - $result = $this->request($service, $postData); - if ($result['success']) { - $result = array_merge($result, [ - 'response' => [ - 'message' => $result['response'], - 'itemId' => $params['wms_code'], - ], - ]); - } - return $result; - } - - /** - * 单据取消 - * @param array $params - * @return mixed - */ - public function orderCancel($params) - { - $service = 'gwisSubCancelOrder'; - - $postData = [ - 'orderCode' => $params['order_code'], - 'orderType' => $params['order_type'], //取消订单类型 JYCK:销售订单 XTRK:销售退货 CGRK:采购订单 CGTH:采购退货 TRAN:调拨计划 - 'goodsOwner' => $this->config['shipper_code'], - 'remark' => $params['cancel_reason'], - ]; - - $result = $this->request($service, $postData); - return $result; - } - - /** - * 退货入库单创建(新增销售退货计划) - * @param array $params - * @return mixed - */ - public function saleReturnOrderCreate($params) - { - $service = 'gwisSubCreateSaleReturnPlan'; - - $detailList = []; - foreach ($params['refund_goods'] as $item) { - array_push($detailList, [ - 'saleOrderCode' => $params['order_info']['order_no'], - 'sku' => $item['wms_code'], - 'qty' => $item['sku_quantity'], - ]); - } - - $postData = [ - 'head' => [ - 'orderCode' => $params['refund_no'], - 'warehouseCode' => $this->config['warehouse_code'], - 'createDate' => $params['created_at'], - 'logisticsCompanyCode' => strtoupper($params['express_code']), - 'expressNo' => $params['express_no'], - 'phno' => $params['order_address_info']['receive_mobile'], - 'stna' => $params['order_address_info']['receive_name'], - 'goodsOwner' => $this->config['shipper_code'], - 'remark' => $params['desc'], - 'detailList' => $detailList, - ], - ]; - - $result = $this->request($service, $postData); - return $result; - } - - /** - * 新增调拨入库计划 - * @param $params - * @return mixed - */ - public function stockTransferInCreate($params) - { - $service = 'gwisSubCreateTranPlan'; - - $detailList = []; - foreach($params['sku_info'] as $skuV){ - array_push($detailList, [ - 'sku' => $skuV['wms_code'], - 'qty' => intval($skuV['apply_stock']), - ]); - } - - $postData = [ - 'head' => [ - 'orderCode' => $params['number'], - 'sourceType' => '02', //来源类型不能为空,默认为(01) 01:普通调拨(出、入仓库必需传) 02:调拨入库 03:调拨出库 04:唯品调拨 - 'targetWhcode' => $this->config['warehouse_code'], - 'createDate' => date('Y-m-d H:i:s'), - 'goodsOwner' => $this->config['shipper_code'], - 'detailList' => $detailList, - ] - ]; - - $result = $this->request($service, $postData); - return $result; - } - - /** - * 新增入库单 - * @param array $params - * @param string $type - * @return mixed - */ - public function stockInCreate($params, $type) - { - $result = []; - switch ($type) { - //采购入库 - case 0: - $result = $this->purchaseOrderCreate($params); - break; - //调拨入库 - case 10: - $result = $this->stockTransferInCreate($params); - break; - //销退入库 - case 40: - $result = $this->saleReturnOrderCreate($params); - break; - } - return $result; - } - - /** - * 新增出库单 - * @param array $params - * @return mixed - */ - public function stockOutCreate($params) - { - $service = 'gwisSubCreateTranPlan'; - - $detailList = []; - foreach ($params['order_goods'] as $item) { - array_push($detailList, [ - 'sku' => $item['wms_code'], - 'qty' => $item['number'], - ]); - } - - $postData = [ - 'head' => [ - 'orderCode' => $params['out_warehouse_number'], - 'sourceType' => '03', //来源类型不能为空,默认为(01) 01:普通调拨(出、入仓库必需传) 02:调拨入库 03:调拨出库 04:唯品调拨 - 'fromWhcode' => $this->config['warehouse_code'], - 'createDate' => date('Y-m-d H:i:s'), - 'logisticsCompanyCode' => 'SF', - 'goodsOwner' => $this->config['shipper_code'], - 'detailList' => $detailList, - ] - ]; - - $result = $this->request($service, $postData); - return $result; - } - - final protected function post($query, $body = '', $headers = ['content-type' => 'application/json; charset = utf-8']) - { - $url = $this->config['base_uri']; - $url .= http_build_query($query); - $data = [ - 'body' => $body, - 'headers' => $headers, - ]; - $client = new Client(); - $response = $client->request('POST', $url, $data); - $content = $response->getBody()->getContents(); - return $content; - } - - public function request($service, $content) - { - $encrypt = $this->config['encrypt']; - $base64Content = $this->base64Content($content, $encrypt); - $query = [ - 'service' => $service, - 'appkey' => $this->config['app_key'], - 'secret' => $encrypt ? $this->createSign($base64Content) : '1', - 'format' => $this->config['format'], - 'encrypt' => $encrypt, - 'content' => $base64Content, - ]; - $result = $this->post($query); - $result = \GuzzleHttp\json_decode($result, true); - - $isSuccess = (empty($result) || !$result['isSuccess']) ? false : true; - $response = [ - 'success' => $isSuccess, - 'response' => $isSuccess ? $result['body'] : $result, - ]; - return $response; - } - - public function base64Content($content, $encrypt = 0) - { - $content = \GuzzleHttp\json_encode($content); - if (!$encrypt) { - return $content; - } - $content = str_replace('=', '\\u003d', base64_encode($content)); - return $content; - } - - public function createSign($content) - { - return strtoupper(md5($content . $this->config['session_key'])); - } - - public function formatGoodsStockInfo($params) - { - $params = array_map(function ($item) { - return array_merge($item, [ - 'itemCode' => $item['sku'], - 'itemId' => $item['sku'], - 'quantity' => $item['uqty'], - 'lockQuantity' => $item['qty'] - $item['uqty'], - ]); - }, $params); - return $params; - } - - public function callback($params) - { - + parent::__construct($wmsConf); } } diff --git a/src/QimenWms.php b/src/QimenWms.php new file mode 100644 index 0000000..36782a9 --- /dev/null +++ b/src/QimenWms.php @@ -0,0 +1,618 @@ +config = $config; + } + + /** + * 销售发货单创建 + * @param array $order + * @return array|\DOMDocument + */ + public function deliveryOrderCreate($order) + { + $method = 'taobao.qimen.deliveryorder.create'; + + $postData = [ + 'deliveryOrder' => [ + 'deliveryOrderCode' => $order['order_no'], //出库单号 + 'orderType' => 'JYCK', //出库单类型, string (50) , 必填, JYCK=一般交易出库单, HHCK=换货出库单,BFCK=补发出库单,QTCK=其他出库单 + 'warehouseCode' => $this->config['warehouse_code'], //仓库编码 + 'sourcePlatformCode' => 'OTHER', //订单来源平台编码 + 'createTime' => date('Y-m-d H:i:s'), //发货单创建时间 + 'placeOrderTime' => $order['created_at'], //前台订单 (店铺订单) 创建时间 (下单时间) + 'operateTime' => date('Y-m-d H:i:s'), //操作 (审核) 时间 + 'shopNick' => $order['order_sender_info']['shop_name'] ?? self::DEFAULT_SHOP_NAME, + 'sellerNick' => $order['order_sender_info']['shop_name'] ?? self::DEFAULT_SELLER_NICK, + 'remark' => $order['remark'], + //发货人信息 + 'senderInfo' => [ + 'name' => $order['order_sender_info']['name'] ?? self::DEFAULT_SENDER_NAME, + 'mobile' => $order['order_sender_info']['tel'] ?? self::DEFAULT_SENDER_MOBILE, + 'province' => self::DEFAULT_SENDER_PROVINCE, + 'city' => self::DEFAULT_SENDER_CITY, + 'area' => self::DEFAULT_SENDER_AREA, + 'detailAddress' => self::DEFAULT_SENDER_ADDRESS, + ], + //收件人信息 + 'receiverInfo' => [ + 'name' => $this->filterEmoji($order['order_address']['receive_name']), + 'zipCode' => $order['order_address']['receive_zip_code'] ?? self::DEFAULT_ZIP_CODE, + 'mobile' => trim($order['order_address']['receive_mobile']), + 'province' => $order['order_address']['receive_province'], + 'city' => $order['order_address']['receive_city'], + 'area' => $order['order_address']['receive_district'], + 'detailAddress' => $order['order_address']['receive_address'], + ], + ], + 'orderLines' => [], + ]; + + $orderLine = []; + $skuTotalWeight = 0; + $ownerCode = $this->config['shipper_code']; //货主编码 + foreach ($order['order_goods'] as $item) { + $itemName = $item['goods_name'] . '(' . $item['sku_name'] . ')'; //商品名称 + $actualPrice = $this->cent2yuan($item['sku_pay_fee']); //实际成交价 + if ($item['sku_type'] == 0) { + array_push($orderLine, [ + 'ownerCode' => $ownerCode, + 'itemCode' => $item['wms_code'], //商品编码 + 'itemId' => $item['wms_code'], //仓储系统商品编码 + 'itemName' => $itemName, + 'planQty' => $item['sku_quantity'], //应发商品数量 + 'actualPrice' => $actualPrice, + ]); + $skuTotalWeight += ($item['weight'] * $item['sku_quantity']) / 1000; + } elseif ($item['sku_type'] == 1) { + foreach ($item['sku_nexus_snapshot'] as $gv) { + array_push($orderLine, [ + 'ownerCode' => $ownerCode, + 'itemCode' => $gv['wms_code'], + 'itemId' => $gv['wms_code'], + 'itemName' => $itemName, + 'planQty' => $gv['sku_quantity'] * $item['sku_quantity'], + 'actualPrice' => $actualPrice, + + ]); + $skuTotalWeight += ($gv['weight'] * $gv['sku_quantity'] * $item['sku_quantity']) / 1000; + } + } + } + $postData = array_merge($postData, ['orderLines' => ['orderLine' => $orderLine]]); + $postData['deliveryOrder'] = array_merge($postData['deliveryOrder'], ['logisticsCode' => $this->chooseLogisticsCompany($order['order_address']['receive_province'], $skuTotalWeight)]); + + $result = $this->xmlPost($method, $postData); + return $result; + } + + /** + * 商品库存查询(单个) + * @param $wmsCode + * @param string $inventoryType + * @return array|\DOMDocument + */ + public function inventoryQuerySingle($wmsCode, $inventoryType) + { + return $this->inventoryQuery([['wms_code' => $wmsCode]], $inventoryType); + } + + /** + * 商品库存查询(批量) + * @param array $params + * @param string $inventoryType + * @return array|\DOMDocument + */ + public function inventoryQuery($params, $inventoryType) + { + $method = 'taobao.qimen.inventory.query'; + + $criteria = []; + foreach ($params as $item) { + array_push($criteria, [ + 'warehouseCode' => $this->config['warehouse_code'], + 'ownerCode' => $this->config['shipper_code'], + 'itemCode' => $item['wms_code'], + 'itemId' => $item['wms_code'], + 'inventoryType' => $inventoryType, + ]); + } + $postData = [ + 'criteriaList' => [ + 'criteria' => $criteria, + ], + ]; + + $result = $this->xmlPost($method, $postData); + return $result['success'] + ? array_merge($result, ['response' => $result['response']['items']['item']]) + : $result; + } + + /** + * 商品同步(商品创建或修改) + * @param array $params + * @return array|\DOMDocument + */ + public function goodsSkuSync($params) + { + $method = 'taobao.qimen.singleitem.synchronize'; + + $postData = [ + 'actionType' => $params['action_type'], + 'warehouseCode' => $this->config['warehouse_code'], + 'ownerCode' => $this->config['shipper_code'], + 'item' => [ + [ + 'itemCode' => $params['wms_code'], + 'itemId' => $params['wms_code'], + 'itemName' => $params['name'], + 'barCode' => $params['upc_code'] ?? $params['wms_code'], + //商品类型 (ZC=正常商品, FX=分销商品, ZH=组合商品, ZP=赠品, BC=包材, HC=耗材, FL=辅料, XN=虚拟品, + //FS=附属品, CC=残次品, OTHER=其它) , string (10) , 必填, (只传英文编码) + 'itemType' => 'ZC', + 'retailPrice' => $params['unit_price'], + 'isValid' => 'Y', + ] + ], + ]; + + $result = $this->xmlPost($method, $postData); + return $result; + } + + /** + * 单据取消 + * @param array $params + * @return array|\DOMDocument + */ + public function orderCancel($params) + { + $method = 'taobao.qimen.order.cancel'; + + $postData = [ + 'warehouseCode' => $this->config['warehouse_code'], + 'orderCode' => $params['order_code'], + 'orderId' => $params['order_code'], + 'orderType' => $params['order_type'], + 'cancelReason' => $params['cancel_reason'], + ]; + + $result = $this->xmlPost($method, $postData); + return $result; + } + + /** + * 退货入库单创建(新增销售退货计划) + * @param array $params + * @return array|\DOMDocument + */ + public function returnOrderCreate($params) + { + $method = 'taobao.qimen.returnorder.create'; + + $ownerCode = $this->config['shipper_code']; + $postData = [ + 'returnOrder' => [ + 'returnOrderCode' => $params['refund_no'], + 'ownerCode' => $ownerCode, + 'warehouseCode' => $this->config['warehouse_code'], + 'orderType' => 'THRK', + 'preDeliveryOrderCode' => $params['order_info']['order_no'], + 'preDeliveryOrderId' => $params['order_info']['order_no'], + 'logisticsCode' => strtoupper($params['express_code']), + 'logisticsName' => $params['express_company'], + 'expressCode' => $params['express_no'], + 'returnReason' => $params['desc'], + 'senderInfo' => [ + 'name' => $params['order_address_info']['receive_name'], + 'mobile' => $params['order_address_info']['receive_mobile'], + 'province' => $params['order_address_info']['receive_province'], + 'city' => $params['order_address_info']['receive_city'], + 'area' => $params['order_address_info']['receive_district'], + 'detailAddress' => $params['order_address_info']['receive_address'], + ], + ], + 'orderLines' => [], + ]; + $orderLine = []; + foreach ($params['refund_goods'] as $item) { + if ($item['sku_type'] == 0) { + array_push($orderLine, [ + 'ownerCode' => $ownerCode, + 'itemCode' => $item['wms_code'], + 'itemId' => $item['wms_code'], + 'planQty' => $item['sku_quantity'], + 'inventoryType' => 'ZP', + ]); + } elseif ($item['sku_type'] == 1) { + foreach ($item['combined_sku'] as $v) { + array_push($orderLine, [ + 'ownerCode' => $ownerCode, + 'itemCode' => $v['wms_code'], + 'itemId' => $v['wms_code'], + 'planQty' => $v['sku_quantity'], + 'inventoryType' => 'ZP', + ]); + } + } + } + $postData = array_merge($postData, ['orderLines' => ['orderLine' => $orderLine]]); + + $result = $this->xmlPost($method, $postData); + return $result; + } + + /** + * 新增入库计划 + * @param array $params + * @param int $type + * @return array|\DOMDocument + */ + public function stockInCreate($params, $type) + { + $method = 'taobao.qimen.entryorder.create'; + + $ownerCode = $this->config['shipper_code']; + $postData = [ + 'entryOrder' => [ + 'entryOrderCode' => $params['number'], + 'ownerCode' => $ownerCode, + 'purchaseOrderCode' => $this->goodsWarehouseCgrkNumber(), + 'warehouseCode' => $this->config['warehouse_code'], + 'orderType' => self::RK_TYPE[$params['type']] ?? 'DBRK', + ], + 'orderLines' => [], + ]; + $orderLine = []; + foreach ($params['sku_info'] as $skuV) { + $stockZP = [ + 'ownerCode' => $ownerCode, + 'itemCode' => $skuV['wms_code'], + 'itemId' => $skuV['wms_code'], + 'planQty' => $skuV['apply_stock'] * 1, + 'purchasePrice' => $this->formatNumber($skuV['price']), + 'inventoryType' => 'ZP', + ]; + array_push($orderLine, $stockZP); + if (!empty($skuV["apply_bad_stock"])) { + $stockCC = array_merge($stockZP, [ + 'planQty' => $skuV['apply_bad_stock'] * 1, + 'inventoryType' => 'CC', + ]); + array_push($orderLine, $stockCC); + } + } + $postData = array_merge($postData, ['orderLines' => ['orderLine' => $orderLine]]); + + $result = $this->xmlPost($method, $postData); + return $result; + } + + public function stockOutCreate($params) + { + $method = 'taobao.qimen.stockout.create'; + + $postData = [ + 'deliveryOrder' => [ + 'deliveryOrderCode' => $params['out_warehouse_number'], //出库单号 + 'orderType' => 'DBCK', //出库单类型 + 'warehouseCode' => $this->config['warehouse_code'], //仓库编码 + 'logisticsCode' => 'SF', + 'logisticsName' => '顺丰', + 'createTime' => date('Y-m-d H:i:s'), //出库单创建时间 + 'receiverInfo' => [ + 'name' => $params['address_name'], + 'zipCode' => $params['receive_zip_code'] ?? self::DEFAULT_ZIP_CODE, + 'mobile' => $params['address_telephone'], + 'province' => $params['address_province'], + 'city' => $params['address_city'], + 'area' => $params['address_area'], + 'detailAddress' => $params['address_detail'], + ], + ], + 'orderLines' => [], + ]; + + $ownerCode = $this->config['shipper_code']; + $orderLine = []; + foreach ($params['order_goods'] as $item) { + $goodsZP = [ + 'ownerCode' => $ownerCode, //货主编码 + 'itemCode' => $item['wms_code'], //商品编码 + 'itemId' => $item['wms_code'], //仓储系统商品编码 + 'itemName' => $item['product_name'] . "(" . $item['sku_name'] . ")", //商品名称 + 'planQty' => $item['number'], //应发商品数量 + 'inventoryType' => 'ZP', //库存类型,ZP=正品, CC=残次,JS=机损, XS= 箱损 + ]; + if ($item['number'] > 0) { + array_push($orderLine, $goodsZP); + } + if (isset($item['bad_num']) && $item['bad_num'] > 0) { + $goodsCC = array_merge($goodsZP, [ + 'planQty' => $item['number'], + 'inventoryType' => 'CC', + ]); + array_push($orderLine, $goodsCC); + } + } + $postData = array_merge($postData, ['orderLines' => ['orderLine' => $orderLine]]); + + $result = $this->xmlPost($method, $postData); + return $result; + } + + public function createSign($params, $body) + { + ksort($params); + $info = ''; + foreach ($params as $key => $val) { + $info .= $key . $val; + } + $appSecret = $this->config['app_secret']; + $info = $appSecret . '' . $info . $body . '' . $appSecret; + $sign = strtoupper(md5($info)); + return $sign; + } + + public function xmlPost($method, $params) + { + $query = [ + 'method' => $method, + 'timestamp' => date('Y-m-d H:i:s'), + 'format' => $this->config['format'], + 'app_key' => $this->config['app_key'], + 'v' => $this->config['version'], + 'sign_method' => $this->config['sign_method'], + 'customerId' => $this->config['customerId'], + ]; + $xml = Array2XML::createXML('request', $params); + $body = $xml->saveXML(); + $sign = $this->createSign($query, $body); + $query['sign'] = $sign; + $response = $this->post($body, $query); + $content = $response->getBody()->getContents(); + $result = XML2Array::createArray($content); + + $isSuccess = (empty($result) || !is_array($result) || $result['response']['flag'] != 'success') ? false : true; + $result = [ + 'success' => $isSuccess, + 'response' => $isSuccess ? $result['response'] : $result, + ]; + return $result; + } + + final protected function post($body, $params = [], $headers = ['content-type' => 'text/xml; charset = utf-8'], $ret = []) { + $url = $this->config['base_uri']; + $url = $url . http_build_query($params); + $data = [ + 'body' => $body, + 'headers' => $headers, + ]; + $client = new Client(); + $result = $client->request('POST', $url, $data); + return $result; + } + + /** + * 确认回传方法 + * @var array + */ + private static $callbackMethods = [ + 'deliveryorder.confirm' => 'deliveryOrderConfirm', + 'entryorder.confirm' => 'stockInConfirm', + 'itemlack.report' => 'itemLackReport', + 'orderprocess.report' => 'orderProcessReport', + 'returnorder.confirm' => 'returnOrderConfirm', + 'stockchange.report' => 'stockChangeReport', + 'stockout.confirm' => 'stockOutConfirm', + ]; + + public function callback($params) + { + if (!isset($params['method']) || empty($params['method'])) { + return $this->response('缺少参数method', false); + } + if (!isset($params['timestamp']) || empty($params['timestamp'])) { + return $this->response('缺少参数timestamp', false); + } + if (!isset($params['format']) || empty($params['format'])) { + return $this->response('缺少参数format', false); + } + if (!isset($params['app_key']) || empty($params['app_key'])) { + return $this->response('缺少参数key', false); + } + if (!isset($params['v']) || empty($params['v'])) { + return $this->response('缺少版本参数', false); + } + if (!isset($params['sign']) || empty($params['sign'])) { + return $this->response('缺少参数sign', false); + } + if (!isset($params['sign_method']) || empty($params['sign_method'])) { + return $this->response('缺少加密方式', false); + } + if (!isset($params['customerId']) || empty($params['customerId'])) { + return $this->response('缺少参数customerId', false); + } + if (empty(($params['body']))) { + return $this->response('缺少消息body', false); + } + + $method = $params['method']; + if (!array_key_exists($method, self::$callbackMethods)) { + return $this->response('调用的方法不存在', false); + } + if (!$this->checkSign($params)) { + return $this->response('签名错误', false); + } + $body = XML2Array::createArray($params['body']); + if (!isset($body['request']) || empty($body['request'])) { + return $this->response('消息body错误', false); + } + $result = call_user_func([$this, self::$callbackMethods[$method]], $body['request']); + return $result; + } + + /** + * 发货单确认 + * @param $params + * @return array + */ + private function deliveryOrderConfirm($params) + { + $service = new OrderService(); + $result = $service->deliverOrderConfirm($params); + if (!$result) { + return $this->response('失败', false); + } + return $this->response(); + } + + /** + * 入库单确认 + * @param $params + * @return array + */ + private function stockInConfirm($params) + { + $service = new GoodsWarehouseService(); + $result = $service->entryorderConfirm($params); + if (!$result) { + return $this->response('失败', false); + } + return $this->response(); + } + + /** + * 发货单缺货通知 + * @param $params + * @return array + */ + private function itemLackReport($params) + { + $service = new OrderItemLackReportService(); + $result = $service->createReceipts($params); + if (!$result) { + return $this->response('失败', false); + } + return $this->response(); + } + + /** + * 订单流水通知 + * @param $params + * @return array + */ + private function orderProcessReport($params) + { + $service = new OrderProcessReportService(); + $result = $service->orderProcessReport($params); + if (!$result) { + return $this->response('失败', false); + } + return $this->response(); + } + + /** + * 退货入库单确认 + * @param $params + * @return array + */ + private function returnOrderConfirm($params) + { + $service = new RefundService(); + $result = $service->refundOrderConfirm($params); + if (!$result) { + return $this->response('失败', false); + } + return $this->response(); + } + + /** + * 库存异动通知 + * @param $params + * @return array + */ + private function stockChangeReport($params) + { + $service = new GoodsWarehouseService(); + $result = $service->StockChangeReport($params); + if (!$result) { + return $this->response('失败', false); + } + return $this->response(); + } + + /** + * 出库单确认 + * @param $params + * @return array + */ + private function stockOutConfirm($params) + { + $service = new OrderService(); + $result = $service->stockOutOrderConfirm($params); + if (!$result) { + return $this->response('失败', false); + } + return $this->response(); + } + + /** + * @检查签名 + * @param $params + * @return bool + */ + public function checkSign($params) + { + if (empty($params)) { + return false; + } + $query = [ + 'method' => $params['method'], + 'timestamp' => $params['timestamp'], + 'format' => $params['format'], + 'app_key' => $params['app_key'], + 'v' => $params['v'], + 'sign_method' => $params['sign_method'], + 'customerId' => $params['customerId'], + ]; + $sign = $this->createSign($query, $params['body']); + if (!hash_equals((string) $sign, (string) $params['sign'])) { + return false; + } + return true; + } + + public function response($message = '成功', $flag = true) + { + $response = [ + 'flag' => $flag ? 'success' : 'failure', + 'code' => $flag ? '001' : '002', + 'message' => $message, + ]; + $xml = Array2XML::createXML('response', $response); + $body = $xml->saveXML(); + return [ + 'content' => $body, + 'status' => 200, + 'headers' => ['Content-Type' => 'xml'], + ]; + } +} diff --git a/src/WmsInterface.php b/src/WmsInterface.php index b430b7b..3963a38 100644 --- a/src/WmsInterface.php +++ b/src/WmsInterface.php @@ -4,17 +4,17 @@ namespace PdWms; Interface WmsInterface { - public function saleOrderCreate(array $params); + public function deliveryOrderCreate(array $params); - public function goodsStockInfoSingle(string $wmsCode, string $inventoryType); + public function inventoryQuerySingle(string $wmsCode, string $inventoryType); - public function goodsStockInfo(array $params, string $inventoryType); + public function inventoryQuery(array $params, string $inventoryType); - public function goodsSync(array $params); + public function goodsSkuSync(array $params); public function orderCancel(array $params); - public function saleReturnOrderCreate(array $params); + public function returnOrderCreate(array $params); public function stockInCreate(array $params, int $type); diff --git a/src/WmsStrategy.php b/src/WmsStrategy.php index 7dd85eb..f0ba06a 100644 --- a/src/WmsStrategy.php +++ b/src/WmsStrategy.php @@ -22,28 +22,28 @@ class WmsStrategy } } - public function saleOrderCreate($params) { - return $this->wmsClient->saleOrderCreate($params); + public function deliveryOrderCreate($params) { + return $this->wmsClient->deliveryOrderCreate($params); } - public function goodsStockInfoSingle($wmsCode, $inventoryType = 'ZP') { - return $this->wmsClient->goodsStockInfoSingle($wmsCode, $inventoryType); + public function inventoryQuerySingle($wmsCode, $inventoryType = 'ZP') { + return $this->wmsClient->inventoryQuerySingle($wmsCode, $inventoryType); } - public function goodsStockInfo($params, $inventoryType = 'ZP') { - return $this->wmsClient->goodsStockInfo($params, $inventoryType); + public function inventoryQuery($params, $inventoryType = 'ZP') { + return $this->wmsClient->inventoryQuery($params, $inventoryType); } - public function goodsSync($params) { - return $this->wmsClient->goodsSync($params); + public function goodsSkuSync($params) { + return $this->wmsClient->goodsSkuSync($params); } public function orderCancel($params) { return $this->wmsClient->orderCancel($params); } - public function saleReturnOrderCreate($params) { - return $this->wmsClient->saleReturnOrderCreate($params); + public function returnOrderCreate($params) { + return $this->wmsClient->returnOrderCreate($params); } public function stockInCreate($params, $type = 0) { @@ -53,9 +53,4 @@ class WmsStrategy public function stockOutCreate($params) { return $this->wmsClient->stockOutCreate($params); } - - public static function callback($params) { - $client = new XinyiWms(); - return $client->callback($params); - } } diff --git a/src/XinyiWms.php b/src/XinyiWms.php index aa89c1c..d29124c 100644 --- a/src/XinyiWms.php +++ b/src/XinyiWms.php @@ -13,14 +13,6 @@ use GuzzleHttp\Client; class XinyiWms extends BaseWms implements WmsInterface { - const TYPE_JB = [ - '0' => 'CGRK', - '10' => 'DBRK', - '20' => 'QTRK', - '30' => 'XNRK', - '40' => 'QTRK', - ]; - protected $config = []; public function __construct($config = null) @@ -34,12 +26,12 @@ class XinyiWms extends BaseWms implements WmsInterface * @param array $order * @return array|\DOMDocument */ - public function saleOrderCreate($order) + public function deliveryOrderCreate($order) { $method = 'deliveryorder.create'; $postData = [ - 'deliveryOrder' =>[ + 'deliveryOrder' => [ 'deliveryOrderCode' => $order['order_no'], //出库单号 'orderType' => 'JYCK', //出库单类型, string (50) , 必填, JYCK=一般交易出库单, HHCK=换货出库单,BFCK=补发出库单,QTCK=其他出库单 'warehouseCode' => $this->config['warehouse_code'], //仓库编码 @@ -124,9 +116,9 @@ class XinyiWms extends BaseWms implements WmsInterface * @param string $inventoryType * @return array|\DOMDocument */ - public function goodsStockInfoSingle($wmsCode, $inventoryType = 'ZP') + public function inventoryQuerySingle($wmsCode, $inventoryType = 'ZP') { - return $this->goodsStockInfo([['wms_code' => $wmsCode]], $inventoryType); + return $this->inventoryQuery([['wms_code' => $wmsCode]], $inventoryType); } /** @@ -135,7 +127,7 @@ class XinyiWms extends BaseWms implements WmsInterface * @param string $inventoryType * @return array|\DOMDocument */ - public function goodsStockInfo($params, $inventoryType = 'ZP') + public function inventoryQuery($params, $inventoryType = 'ZP') { $method = 'inventory.query'; @@ -165,7 +157,7 @@ class XinyiWms extends BaseWms implements WmsInterface * @param array $params * @return array|\DOMDocument */ - public function goodsSync($params) + public function goodsSkuSync($params) { $method = 'singleitem.synchronize'; @@ -218,7 +210,7 @@ class XinyiWms extends BaseWms implements WmsInterface * @param array $params * @return array|\DOMDocument */ - public function saleReturnOrderCreate($params) + public function returnOrderCreate($params) { $method = 'returnorder.create'; @@ -290,7 +282,7 @@ class XinyiWms extends BaseWms implements WmsInterface 'ownerCode' => $ownerCode, 'purchaseOrderCode' => $this->goodsWarehouseCgrkNumber(), 'warehouseCode' => $this->config['warehouse_code'], - 'orderType' => self::TYPE_JB[$params['type']] ?? 'DBRK', + 'orderType' => self::RK_TYPE[$params['type']] ?? 'DBRK', ], 'orderLines' => [], ]; @@ -472,11 +464,11 @@ class XinyiWms extends BaseWms implements WmsInterface * @var array */ private static $callbackMethods = [ - 'taobao.qimen.deliveryorder.confirm' => 'saleOrderConfirm', + 'taobao.qimen.deliveryorder.confirm' => 'deliveryOrderConfirm', 'taobao.qimen.entryorder.confirm' => 'stockInConfirm', 'taobao.qimen.itemlack.report' => 'itemLackReport', 'taobao.qimen.orderprocess.report' => 'orderProcessReport', - 'taobao.qimen.returnorder.confirm' => 'saleReturnOrderConfirm', + 'taobao.qimen.returnorder.confirm' => 'returnOrderConfirm', 'taobao.qimen.stockchange.report' => 'stockChangeReport', 'taobao.qimen.stockout.confirm' => 'stockOutConfirm', ]; @@ -531,7 +523,7 @@ class XinyiWms extends BaseWms implements WmsInterface * @param $params * @return array */ - private function saleOrderConfirm ($params) + private function deliveryOrderConfirm ($params) { $service = new OrderService(); $result = $service->deliverOrderConfirm($params); @@ -591,7 +583,7 @@ class XinyiWms extends BaseWms implements WmsInterface * @param $params * @return array */ - private function saleReturnOrderConfirm($params) + private function returnOrderConfirm($params) { $service = new RefundService(); $result = $service->refundOrderConfirm($params);