From e18a3bf35de835c5b906eb101e7ad98ab8b9a6c5 Mon Sep 17 00:00:00 2001 From: ZweiCD <416931358@qq.com> Date: Thu, 19 Mar 2020 17:05:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=E6=8E=A5=E4=BB=93=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + README.md | 9 + composer.json | 21 + composer.lock | 913 ++++++++++++++++++++++++++++++++++++++ config/express_choose.php | 7 + config/wms.php | 25 ++ src/BaseWms.php | 130 ++++++ src/GwallWms.php | 375 ++++++++++++++++ src/Service/Array2XML.php | 201 +++++++++ src/Service/XML2Array.php | 168 +++++++ src/WmsInterface.php | 22 + src/WmsStrategy.php | 55 +++ src/XinyiWms.php | 479 ++++++++++++++++++++ 13 files changed, 2407 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 config/express_choose.php create mode 100644 config/wms.php create mode 100644 src/BaseWms.php create mode 100644 src/GwallWms.php create mode 100644 src/Service/Array2XML.php create mode 100644 src/Service/XML2Array.php create mode 100644 src/WmsInterface.php create mode 100644 src/WmsStrategy.php create mode 100644 src/XinyiWms.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5049f84 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/vendor +/.idea diff --git a/README.md b/README.md new file mode 100644 index 0000000..51f5c5d --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# WMS + +> 该项目使用 composer 来完成加载 + +执行 +```bash +composer config repositories.php-wms-client vcs git@git.int.haowumc.com:composer/php-wms-client.git +composer require paidian/wms-client +``` diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..b884386 --- /dev/null +++ b/composer.json @@ -0,0 +1,21 @@ +{ + "name": "paidian/wms-client", + "description": "wms client", + "type": "library", + "authors": [ + { + "name": "ZweiCD", + "email": "416931358@qq.com" + } + ], + "minimum-stability": "dev", + "require": { + "illuminate/support": "^5.5", + "guzzlehttp/guzzle": "^6.3" + }, + "autoload": { + "psr-4": { + "PdWms\\": "src/" + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..5cb5acc --- /dev/null +++ b/composer.lock @@ -0,0 +1,913 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "d41cb728d6e60f3d4e01b9c670f83caf", + "packages": [ + { + "name": "doctrine/inflector", + "version": "1.3.x-dev", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2019-10-30T19:59:35+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.5.x-dev", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "400cefd25a23a3098486bfb52685b5367a464171" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/400cefd25a23a3098486bfb52685b5367a464171", + "reference": "400cefd25a23a3098486bfb52685b5367a464171", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.6.1", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.1" + }, + "suggest": { + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.5-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2019-12-30T04:52:42+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "89b1a76b7fda5853401297dc4b2a093cba1fda23" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/89b1a76b7fda5853401297dc4b2a093cba1fda23", + "reference": "89b1a76b7fda5853401297dc4b2a093cba1fda23", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.27 || ^7.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2020-02-15T23:33:03+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "c73b502efd02beb2602500aa36793fb405e383ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c73b502efd02beb2602500aa36793fb405e383ac", + "reference": "c73b502efd02beb2602500aa36793fb405e383ac", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "ext-zlib": "*", + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2020-02-12T23:13:46+00:00" + }, + { + "name": "illuminate/contracts", + "version": "5.8.x-dev", + "source": { + "type": "git", + "url": "https://github.com/illuminate/contracts.git", + "reference": "00fc6afee788fa07c311b0650ad276585f8aef96" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/00fc6afee788fa07c311b0650ad276585f8aef96", + "reference": "00fc6afee788fa07c311b0650ad276585f8aef96", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.1.3", + "psr/container": "^1.0", + "psr/simple-cache": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.8-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Contracts\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Contracts package.", + "homepage": "https://laravel.com", + "time": "2019-07-30T13:57:21+00:00" + }, + { + "name": "illuminate/support", + "version": "5.8.x-dev", + "source": { + "type": "git", + "url": "https://github.com/illuminate/support.git", + "reference": "df4af6a32908f1d89d74348624b57e3233eea247" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/support/zipball/df4af6a32908f1d89d74348624b57e3233eea247", + "reference": "df4af6a32908f1d89d74348624b57e3233eea247", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "doctrine/inflector": "^1.1", + "ext-json": "*", + "ext-mbstring": "*", + "illuminate/contracts": "5.8.*", + "nesbot/carbon": "^1.26.3 || ^2.0", + "php": "^7.1.3" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "suggest": { + "illuminate/filesystem": "Required to use the composer class (5.8.*).", + "moontoast/math": "Required to use ordered UUIDs (^1.1).", + "ramsey/uuid": "Required to use Str::uuid() (^3.7).", + "symfony/process": "Required to use the composer class (^4.2).", + "symfony/var-dumper": "Required to use the dd function (^4.2).", + "vlucas/phpdotenv": "Required to use the env helper (^3.3)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.8-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + }, + "files": [ + "helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Support package.", + "homepage": "https://laravel.com", + "time": "2019-12-12T14:16:47+00:00" + }, + { + "name": "nesbot/carbon", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "f4e7099512c051057bcc308bad83f5ca4b8cd7eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f4e7099512c051057bcc308bad83f5ca4b8cd7eb", + "reference": "f4e7099512c051057bcc308bad83f5ca4b8cd7eb", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "php": "^7.1.8 || ^8.0", + "symfony/translation": "^3.4 || ^4.0 || ^5.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.14 || ^3.0", + "kylekatarnls/multi-tester": "^1.1", + "phpmd/phpmd": "^2.8", + "phpstan/phpstan": "^0.11", + "phpunit/phpunit": "^7.5 || ^8.0", + "squizlabs/php_codesniffer": "^3.4" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "http://nesbot.com" + }, + { + "name": "kylekatarnls", + "homepage": "http://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "http://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "time": "2020-03-14T09:59:06+00:00" + }, + { + "name": "psr/container", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "fc1bc363ecf887921e3897c7b1dad3587ae154eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/fc1bc363ecf887921e3897c7b1dad3587ae154eb", + "reference": "fc1bc363ecf887921e3897c7b1dad3587ae154eb", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2019-10-04T14:07:35+00:00" + }, + { + "name": "psr/http-message", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "efd67d1dc14a7ef4fc4e518e7dee91c271d524e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/efd67d1dc14a7ef4fc4e518e7dee91c271d524e4", + "reference": "efd67d1dc14a7ef4fc4e518e7dee91c271d524e4", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2019-08-29T13:16:46+00:00" + }, + { + "name": "psr/simple-cache", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "time": "2017-10-23T01:57:42+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac", + "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.15-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2020-03-09T19:04:49+00:00" + }, + { + "name": "symfony/translation", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "bddc6b34770cc0f8462cf1fadb5f1eb77ffe7e1f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/bddc6b34770cc0f8462cf1fadb5f1eb77ffe7e1f", + "reference": "bddc6b34770cc0f8462cf1fadb5f1eb77ffe7e1f", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2" + }, + "conflict": { + "symfony/config": "<4.4", + "symfony/dependency-injection": "<5.0", + "symfony/http-kernel": "<5.0", + "symfony/twig-bundle": "<5.0", + "symfony/yaml": "<4.4" + }, + "provide": { + "symfony/translation-implementation": "2.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/dependency-injection": "^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/http-kernel": "^5.0", + "symfony/intl": "^4.4|^5.0", + "symfony/service-contracts": "^1.1.2|^2", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Translation Component", + "homepage": "https://symfony.com", + "time": "2020-03-15T14:51:35+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "fa3238c55d9d4d8f78b4bc5f17374b017e07dea7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/fa3238c55d9d4d8f78b4bc5f17374b017e07dea7", + "reference": "fa3238c55d9d4d8f78b4bc5f17374b017e07dea7", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2.5" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2020-02-14T07:31:56+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/config/express_choose.php b/config/express_choose.php new file mode 100644 index 0000000..f0c05d3 --- /dev/null +++ b/config/express_choose.php @@ -0,0 +1,7 @@ + ['浙江省', '江苏省', '上海市'], + 'jzh_express_weight' => 35, + 'other_express_weight' => 50, +]; \ No newline at end of file diff --git a/config/wms.php b/config/wms.php new file mode 100644 index 0000000..05c8ffe --- /dev/null +++ b/config/wms.php @@ -0,0 +1,25 @@ + [ + 'base_uri' => env('WMS_HOST', 'http://183.6.136.90:8081/service/BJPDmocker/mockqmcyb?'), + 'app_key' => env('WMS_APP_KEY','23152314'), + 'app_secret' => env('WMS_APP_SECRET','bjpdalog'), + 'customerId' => env('WMS_CUSTOMERID','BJPDmocker'), + 'version' => env('WMS_VERSION', '2.0'), + 'format' => 'xml', + 'sign_method' => 'md5', + 'warehouse_code' => env('WMS_WAREHOUSE_CODE','test0912'), + 'shipper_code' => env('WMS_SHIPPER_CODE','BJPD'), + ], + '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'), + 'shipper_code' => env('GWALL_SHIPPER_CODE', 'BJPD'), + ], +]; diff --git a/src/BaseWms.php b/src/BaseWms.php new file mode 100644 index 0000000..356331f --- /dev/null +++ b/src/BaseWms.php @@ -0,0 +1,130 @@ += $expressChooseConf['jzh_express_weight']) { + $logisticsCode = 'KYE'; + } else { + $logisticsCode = 'STO'; + } + } else { + if ($weight >= $expressChooseConf['other_express_weight']) { + $logisticsCode = 'KYE'; + } else { + $logisticsCode = 'STO'; + } + } + return $logisticsCode; + } + + function filterEmoji(string $str): string + { + if (!empty($str)) { + $str = preg_replace_callback( + '/./u', + function (array $match) { + return strlen($match[0]) >= 4 ? '' : $match[0]; + }, + $str + ); + } + return $str; + } + + /** + * 金额转换分=》元 + * + * @param mixed $data + * @param array $fields 一层数组字段转化 + * @param array $multi 两层数组转化 + * + * @return float|array + */ + function cent2yuan($data, $fields = [], $multi = []) + { + if (is_array($data) && !empty($data)) { + if (!empty($multi)) { + foreach ($multi as $key => $val) { + $data[$key] = $this->cent2yuan($data[$key], $val); + } + } + if (!empty($fields)) { + foreach ($fields as $key => &$val) { + if (is_int($key) && isset($data[$val])) { + $data[$val] = $this->formatMoneyDiv($data[$val], 100, 2); + } + if (!is_int($key) && isset($data[$key]) && is_array($val)) { + foreach ($data[$key] as &$datum) { + foreach ($val as $item) { + $datum[$item] = $this->formatMoneyDiv( + $datum[$item], + 100, + 2 + ); + } + } + } + } + + return $data; + } + } + if (is_numeric($data) || is_string($data)) { + if ($data === 0 || $data === '0') { + return '0.00'; + } else { + return $this->formatMoneyDiv($data, 100, 2); + } + } + + return $data; + } + + /** 除法 */ + function formatMoneyDiv($param1, $param2, $scale = 2) + { + return bcdiv($param1, $param2, $scale); + } + + //格式化金额 + function formatNumber($number, $decimals = 2) + { + return number_format($number, $decimals, ".", ""); + } + + + //商品入库采购单号 + function goodsWarehouseCgrkNumber() + { + return "10" . $this->generate(); + } + + function generate() + { + $time = date("YmdHis", time()); + $no = $time . rand(1000, 9999); + return substr($no, 2, strlen($no)); + } +} diff --git a/src/GwallWms.php b/src/GwallWms.php new file mode 100644 index 0000000..0da1832 --- /dev/null +++ b/src/GwallWms.php @@ -0,0 +1,375 @@ +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); + return $result; + } + + /** + * 商品库存查询(批量) + * @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['isSuccess']) { + continue; + } + array_push($data, $result['body']); + } + return $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); + 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']['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_addr']['receive_mobile'], + 'stna' => $params['order_addr']['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, + ]; + $response = $this->post($query); + return \GuzzleHttp\json_decode($response, true); + } + + 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'])); + } +} diff --git a/src/Service/Array2XML.php b/src/Service/Array2XML.php new file mode 100644 index 0000000..58fd149 --- /dev/null +++ b/src/Service/Array2XML.php @@ -0,0 +1,201 @@ +. + */ + +/** + * Array2XML: A class to convert array in PHP to XML + * It also takes into account attributes names unlike SimpleXML in PHP + * It returns the XML in form of DOMDocument class for further manipulation. + * It throws exception if the tag name or attribute name has illegal chars. + * + * Author : Lalit Patel + * Website: http://www.lalit.org/lab/convert-php-array-to-xml-with-attributes + * License: Apache License 2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * Version: 0.1 (10 July 2011) + * Version: 0.2 (16 August 2011) + * - replaced htmlentities() with htmlspecialchars() (Thanks to Liel Dulev) + * - fixed a edge case where root node has a false/null/0 value. (Thanks to Liel Dulev) + * Version: 0.3 (22 August 2011) + * - fixed tag sanitize regex which didn't allow tagnames with single character. + * Version: 0.4 (18 September 2011) + * - Added support for CDATA section using @cdata instead of @value. + * Version: 0.5 (07 December 2011) + * - Changed logic to check numeric array indices not starting from 0. + * Version: 0.6 (04 March 2012) + * - Code now doesn't @cdata to be placed in an empty array + * Version: 0.7 (24 March 2012) + * - Reverted to version 0.5 + * Version: 0.8 (02 May 2012) + * - Removed htmlspecialchars() before adding to text node or attributes. + * Version: 0.11 (28 October 2015) + * - Fixed typos; Added support for plain insertion of XML trough @xml. + * + * Usage: + * $xml = Array2XML::createXML('root_node_name', $php_array); + * echo $xml->saveXML(); + */ +class Array2XML { + + /** + * @var \DOMDocument + */ + private static $xml = null; + private static $encoding = 'UTF-8'; + + /** + * Initialize the root XML node [optional] + * @param $version + * @param $encoding + * @param $format_output + */ + public static function init($version = '1.0', $encoding = 'UTF-8', $format_output = true) { + self::$xml = new \DomDocument($version, $encoding); + self::$xml->formatOutput = $format_output; + self::$encoding = $encoding; + } + + /** + * Convert an Array to XML + * @param string $node_name - name of the root node to be converted + * @param array $arr - aray to be converterd + * @return \DomDocument + */ + public static function &createXML($node_name, $arr = array()) { + $xml = self::getXMLRoot(); + $xml->appendChild(self::convert($node_name, $arr)); + + self::$xml = null; // clear the xml node in the class for 2nd time use. + return $xml; + } + + /** + * Convert an Array to XML. + * + * @param string $node_name + * Name of the root node to be converted. + * @param array $arr + * Array to be converted. + * + * @throws \Exception + * + * @return \DOMNode + */ + private static function &convert($node_name, $arr = array()) { + + //print_arr($node_name); + $xml = self::getXMLRoot(); + $node = $xml->createElement($node_name); + + if (is_array($arr)) { + // get the attributes first.; + if (isset($arr['@attributes'])) { + foreach ($arr['@attributes'] as $key => $value) { + if (!self::isValidTagName($key)) { + throw new \Exception('[Array2XML] Illegal character in attribute name. attribute: ' . $key . ' in node: ' . $node_name); + } + $node->setAttribute($key, self::bool2str($value)); + } + unset($arr['@attributes']); //remove the key from the array once done. + } + + // check if it has a value stored in @value, if yes store the value and return + // else check if its directly stored as string + if (isset($arr['@value'])) { + $node->appendChild($xml->createTextNode(self::bool2str($arr['@value']))); + unset($arr['@value']); //remove the key from the array once done. + //return from recursion, as a note with value cannot have child nodes. + return $node; + } else if (isset($arr['@cdata'])) { + $node->appendChild($xml->createCDATASection(self::bool2str($arr['@cdata']))); + unset($arr['@cdata']); //remove the key from the array once done. + //return from recursion, as a note with cdata cannot have child nodes. + return $node; + } + else if (isset($arr['@xml'])) { + $fragment = $xml->createDocumentFragment(); + $fragment->appendXML($arr['@xml']); + $node->appendChild($fragment); + unset($arr['@xml']); + return $node; + } + } + + //create subnodes using recursion + if (is_array($arr)) { + // recurse to get the node for that key + foreach ($arr as $key => $value) { + if (!self::isValidTagName($key)) { + throw new \Exception('[Array2XML] Illegal character in tag name. tag: ' . $key . ' in node: ' . $node_name); + } + if (is_array($value) && is_numeric(key($value))) { + // MORE THAN ONE NODE OF ITS KIND; + // if the new array is numeric index, means it is array of nodes of the same kind + // it should follow the parent key name + foreach ($value as $k => $v) { + $node->appendChild(self::convert($key, $v)); + } + } else { + // ONLY ONE NODE OF ITS KIND + $node->appendChild(self::convert($key, $value)); + } + unset($arr[$key]); //remove the key from the array once done. + } + } + + // after we are done with all the keys in the array (if it is one) + // we check if it has any text value, if yes, append it. + if (!is_array($arr)) { + $node->appendChild($xml->createTextNode(self::bool2str($arr))); + } + + return $node; + } + + /* + * Get the root XML node, if there isn't one, create it. + */ + private static function getXMLRoot() { + if (empty(self::$xml)) { + self::init(); + } + return self::$xml; + } + + /* + * Get string representation of boolean value + */ + private static function bool2str($v) { + //convert boolean to text value. + $v = $v === true ? 'true' : $v; + $v = $v === false ? 'false' : $v; + return $v; + } + + /* + * Check if the tag name or attribute name contains illegal characters + * Ref: http://www.w3.org/TR/xml/#sec-common-syn + */ + private static function isValidTagName($tag) { + $pattern = '/^[a-z_]+[a-z0-9\:\-\.\_]*[^:]*$/i'; + return preg_match($pattern, $tag, $matches) && $matches[0] == $tag; + } +} \ No newline at end of file diff --git a/src/Service/XML2Array.php b/src/Service/XML2Array.php new file mode 100644 index 0000000..e8ec399 --- /dev/null +++ b/src/Service/XML2Array.php @@ -0,0 +1,168 @@ +. + */ + +/** + * XML2Array: A class to convert XML to array in PHP + * It returns the array which can be converted back to XML using the Array2XML script + * It takes an XML string or a DOMDocument object as an input. + * + * See Array2XML: http://www.lalit.org/lab/convert-php-array-to-xml-with-attributes + * + * Author : Lalit Patel + * Website: http://www.lalit.org/lab/convert-xml-to-array-in-php-xml2array + * License: Apache License 2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * Version: 0.1 (07 Dec 2011) + * Version: 0.2 (04 Mar 2012) + * Fixed typo 'DomDocument' to 'DOMDocument' + * + * Usage: + * $array = XML2Array::createArray($xml); + */ + +class XML2Array { + + protected static $xml = null; + protected static $encoding = 'UTF-8'; + protected static $prefix_attributes = '@'; + + /** + * Initialize the root XML node [optional] + * @param $version + * @param $encoding + * @param $format_output + */ + public static function init($version = '1.0', $encoding = 'UTF-8', $format_output = true) { + self::$xml = new \DOMDocument($version, $encoding); + self::$xml->formatOutput = $format_output; + self::$encoding = $encoding; + } + + /** + * Convert an XML to Array + * @param string $node_name - name of the root node to be converted + * @param int - Bitwise OR of the libxml option constants see @link http://php.net/manual/zh/libxml.constants.php + * @param array $arr - aray to be converterd + * @return \DOMDocument + */ + public static function &createArray($input_xml, $options = 0) { + $xml = self::getXMLRoot(); + if(is_string($input_xml)) { + $parsed = $xml->loadXML($input_xml, $options); + if(!$parsed) { + throw new \Exception('[XML2Array] Error parsing the XML string.'); + } + } else { + if(get_class($input_xml) != 'DOMDocument') { + throw new \Exception('[XML2Array] The input XML object should be of type: DOMDocument.'); + } + $xml = self::$xml = $input_xml; + } + $array[$xml->documentElement->tagName] = self::convert($xml->documentElement); + self::$xml = null; // clear the xml node in the class for 2nd time use. + return $array; + } + + /** + * Convert an Array to XML + * @param mixed $node - XML as a string or as an object of DOMDocument + * @return mixed + */ + protected static function &convert($node) { + $output = array(); + + switch ($node->nodeType) { + case XML_CDATA_SECTION_NODE: + $output[static::$prefix_attributes.'cdata'] = trim($node->textContent); + break; + + case XML_TEXT_NODE: + $output = trim($node->textContent); + break; + + case XML_ELEMENT_NODE: + + // for each child node, call the covert function recursively + for ($i=0, $m=$node->childNodes->length; $i<$m; $i++) { + $child = $node->childNodes->item($i); + $v = self::convert($child); + if(isset($child->tagName)) { + $t = $child->tagName; + + // avoid fatal error if the content looks like 'You are being redirected.' + if(isset($output) && !is_array($output)) { + continue; + } + // assume more nodes of same kind are coming + if(!isset($output[$t])) { + $output[$t] = array(); + } + $output[$t][] = $v; + } else { + //check if it is not an empty text node + if($v !== '') { + $output = $v; + } + } + } + + if(is_array($output)) { + // if only one node of its kind, assign it directly instead if array($value); + foreach ($output as $t => $v) { + if(is_array($v) && count($v)==1) { + $output[$t] = $v[0]; + } + } + if(empty($output)) { + //for empty nodes + $output = ''; + } + } + + // loop through the attributes and collect them + if($node->attributes->length) { + $a = array(); + foreach($node->attributes as $attrName => $attrNode) { + $a[$attrName] = (string) $attrNode->value; + } + // if its an leaf node, store the value in @value instead of directly storing it. + if(!is_array($output)) { + $output = array(static::$prefix_attributes.'value' => $output); + } + $output[static::$prefix_attributes.'attributes'] = $a; + } + break; + } + return $output; + } + + /* + * Get the root XML node, if there isn't one, create it. + */ + protected static function getXMLRoot(){ + if(empty(self::$xml)) { + self::init(); + } + return self::$xml; + } +} \ No newline at end of file diff --git a/src/WmsInterface.php b/src/WmsInterface.php new file mode 100644 index 0000000..94626ae --- /dev/null +++ b/src/WmsInterface.php @@ -0,0 +1,22 @@ +wmsClient = new XinyiWms(); + break; + case 2: + $this->wmsClient = new GwallWms(); + break; + default: + throw new \Exception('仓库不存在'); + } + } + + public function saleOrderCreate($params) { + return $this->wmsClient->saleOrderCreate($params); + } + + public function goodsStockInfoSingle($wmsCode, $inventoryType = 'ZP') { + return $this->wmsClient->goodsStockInfoSingle($wmsCode, $inventoryType); + } + + public function goodsStockInfo($params, $inventoryType = 'ZP') { + return $this->wmsClient->goodsStockInfo($params, $inventoryType); + } + + public function goodsSync($params) { + return $this->wmsClient->goodsSync($params); + } + + public function orderCancel($params) { + return $this->wmsClient->orderCancel($params); + } + + public function saleReturnOrderCreate($params) { + return $this->wmsClient->saleReturnOrderCreate($params); + } + + public function stockInCreate($params, $type = 0) { + return $this->wmsClient->stockInCreate($params, $type); + } + + public function stockOutCreate($params) { + return $this->wmsClient->stockOutCreate($params); + } +} diff --git a/src/XinyiWms.php b/src/XinyiWms.php new file mode 100644 index 0000000..fbd070c --- /dev/null +++ b/src/XinyiWms.php @@ -0,0 +1,479 @@ + 'CGRK', + '10' => 'DBRK', + '20' => 'QTRK', + '30' => 'XNRK', + '40' => 'QTRK', + ]; + + protected $config = []; + + public function __construct($config = null) + { + $wmsConf = $config ?? (require(dirname(dirname(__FILE__)) . '/config/wms.php'))['xinyi']; + $this->config = $wmsConf; + } + + /** + * 销售发货单创建 + * @param array $order + * @return array|\DOMDocument + */ + public function saleOrderCreate($order) + { + $method = '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' => [], + 'stock_out_create' => 0, + ]; + + $orderLine = []; + $skuTotalWeight = 0; + $orderLineNo = 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, [ + 'orderLineNo' => $orderLineNo, + '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; + $orderLineNo++; + } elseif ($item['sku_type'] == 1) { + foreach ($item['sku_nexus_snapshot'] as $gv) { + array_push($orderLine, [ + 'orderLineNo' => $orderLineNo, + '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; + $orderLineNo++; + } + } + } + $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 goodsStockInfoSingle($wmsCode, $inventoryType = 'ZP') + { + return $this->goodsStockInfo([['wms_code' => $wmsCode]], $inventoryType); + } + + /** + * 商品库存查询(批量) + * @param array $params + * @param string $inventoryType + * @return array|\DOMDocument + */ + public function goodsStockInfo($params, $inventoryType = 'ZP') + { + $method = 'inventory.query'; + + $postData = [ + 'criteriaList' => [ + 'criteria' => [], + ], + ]; + foreach ($params as $item) { + array_push($postData['criteriaList']['criteria'], [ + 'warehouseCode' => $this->config['warehouse_code'], + 'ownerCode' => $this->config['shipper_code'], + 'itemCode' => $item['wms_code'], + 'itemId' => $item['wms_code'], + 'inventoryType' => $inventoryType, + ]); + } + + $result = $this->xmlPost($method, $postData); + return $result; + } + + /** + * 商品同步(商品创建或修改) + * @param array $params + * @return array|\DOMDocument + */ + public function goodsSync($params) + { + $method = '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 = '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 saleReturnOrderCreate($params) + { + $method = 'returnorder.create'; + + $postData = [ + 'returnOrder' => [ + 'returnOrderCode' => $params['refund_no'], + 'warehouseCode' => $this->config['warehouse_code'], + 'orderType' => 'THRK', + 'preDeliveryOrderCode' => $params['order']['order_no'], + 'preDeliveryOrderId' => $params['order']['order_no'], + 'logisticsCode' => strtoupper($params['express_code']), + 'logisticsName' => $params['express_company'], + 'expressCode' => $params['express_no'], + 'returnReason' => $params['desc'], + 'senderInfo' => [ + 'name' => $params['order_addr']['receive_name'], + 'mobile' => $params['order_addr']['receive_mobile'], + 'province' => $params['order_addr']['receive_province'], + 'city' => $params['order_addr']['receive_city'], + 'area' => $params['order_addr']['receive_district'], + 'detailAddress' => $params['order_addr']['receive_address'], + ], + ], + 'orderLines' => [], + ]; + $orderLine = []; + $ownerCode = $this->config['shipper_code']; + 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 = 0) + { + $method = 'entryorder.create'; + + $ownerCode = $this->config['shipper_code']; + $postData = [ + 'entryOrder' => [ + 'entryOrderCode' => $params['number'], + 'ownerCode' => $ownerCode, + 'purchaseOrderCode' => $this->goodsWarehouseCgrkNumber(), + 'warehouseCode' => $this->config['warehouse_code'], + 'orderType' => self::TYPE_JB[$params['type']] ?? 'DBRK', + ], + 'orderLines' => [], + ]; + $orderLineNo = 1; + $orderLine = []; + foreach ($params['sku_info'] as $skuV) { + $stockZP = [ + 'orderLineNo' => $orderLineNo, + 'ownerCode' => $ownerCode, + 'itemCode' => $skuV['wms_code'], + 'itemId' => $skuV['wms_code'], + 'planQty' => $skuV['apply_stock'] * 1, + 'purchasePrice' => $this->formatNumber($skuV['price']), + 'inventoryType' => 'ZP', + ]; + $orderLineNo++; + array_push($orderLine, $stockZP); + if (!empty($skuV["apply_bad_stock"])) { + $stockCC = array_merge($stockZP, [ + 'orderLineNo' => $orderLineNo, + 'planQty' => $skuV['apply_bad_stock'] * 1, + 'inventoryType' => 'CC', + ]); + array_push($orderLine, $stockCC); + $orderLineNo++; + } + } + $postData = array_merge($postData, ['orderLines' => ['orderLine' => $orderLine]]); + + $result = $this->xmlPost($method, $postData); + return $result; + } + + /** + * 新增出库计划 + * @param array $params + * @return array|\DOMDocument + */ + public function stockOutCreate($params) + { + $method = '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; + } + + /** + * @生产签名 + * + * @param $method + * @param string $body + * @param string $timestamp + * @return [] + */ + public function createSign($method, $body = '', $timestamp = '') { + $timestamp = $timestamp ?? date('Y-m-d H:i:s', time()); + + $app_key = $this->config['app_key']; + $app_secret = $this->config['app_secret']; + $version = $this->config['version']; + $customer_id = $this->config['customerId']; + $format = $this->config['format']; + $sign_method = $this->config['sign_method']; + + $treeMap['method'] = $method; + $treeMap['timestamp'] = $timestamp; + $treeMap['format'] = $format; + $treeMap['app_key'] = $app_key; + $treeMap['v'] = $version; + $treeMap['sign_method'] = $sign_method; + $treeMap['customerId'] = $customer_id; + + ksort($treeMap); + $info = ''; + foreach ($treeMap as $key => $val) { + $info .= $key; + $info .= $val; + } + $info .= $body; + $info = $app_secret . '' . $info . '' . $app_secret; + $sign = strtoupper(md5($info)); + $params['method'] = $method; + $params['timestamp'] = $timestamp; + $params['format'] = $format; + $params['app_key'] = $app_key; + $params['v'] = $version; + $params['sign'] = $sign; + $params['sign_method'] = $sign_method; + $params['customerId'] = $customer_id; + return $params; + } + + /** + * @发送请求 + * @param $body + * @param array $params + * @param array $headers + * @param array $ret + * @return array|\DOMDocument + * @throws \Exception + * @throws \GuzzleHttp\Exception\GuzzleException + */ + 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(); + $response = $client->request('POST', $url, $data); + $content = $response->getBody()->getContents(); + $ret = XML2Array::createArray($content); + return $ret; + } + + /** + * @检查签名 + * @param $params + * @return bool + */ + public function checkSign($params) + { + if (empty($params)) { + return false; + } + $sign = $params['sign']; + $new_sign = $this->createSign( + $params['method'], + $params['body'], + $params['timestamp'] + ); + if (!hash_equals((string) $new_sign['sign'], (string) $sign)) { + return false; + } + return true; + } + + public function xmlPost($method, $params) + { + $xml = Array2XML::createXML('request', $params); + $body = $xml->saveXML(); + $res = $this->createSign($method, $body); + $result = $this->post($body, $res); + + return $result; + } +} \ No newline at end of file