From c4b2e4957bcfc51128596c921468988893a0aef5 Mon Sep 17 00:00:00 2001 From: xuanchen <122383162@qq.com> Date: Tue, 31 Oct 2023 14:11:47 +0800 Subject: [PATCH] first --- .gitignore | 2 + composer.json | 19 + composer.lock | 485 ++++++++++++++++++++++++ config/config.php | 5 + src/Adapter/WechatAdapter.php | 49 +++ src/Adapter/YsdAdapter.php | 49 +++ src/Clients/ApiClient.php | 44 +++ src/Contracts/CouponGateway.php | 39 ++ src/CouponService.php | 33 ++ src/Gateways/BaseGateway.php | 66 ++++ src/Gateways/WechatGateway.php | 35 ++ src/Gateways/YsdGateway.php | 146 +++++++ src/Logging/CouponLogger.php | 17 + src/Providers/CouponServiceProvider.php | 27 ++ 14 files changed, 1016 insertions(+) create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 config/config.php create mode 100644 src/Adapter/WechatAdapter.php create mode 100644 src/Adapter/YsdAdapter.php create mode 100644 src/Clients/ApiClient.php create mode 100644 src/Contracts/CouponGateway.php create mode 100644 src/CouponService.php create mode 100644 src/Gateways/BaseGateway.php create mode 100644 src/Gateways/WechatGateway.php create mode 100644 src/Gateways/YsdGateway.php create mode 100644 src/Logging/CouponLogger.php create mode 100644 src/Providers/CouponServiceProvider.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9fd1dab --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +/vendor/ diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..8fe6fff --- /dev/null +++ b/composer.json @@ -0,0 +1,19 @@ +{ + "name": "xuanchen/card-coupon", + "description": "优惠券总模块", + "autoload": { + "psr-4": { + "XuanChen\\CardCoupon\\": "src/" + } + }, + "require": { + "php": ">=7.4", + "guzzlehttp/guzzle": "^6.2 || ^7.0" + }, + "authors": [ + { + "name": "xuanchen", + "email": "122383162@qq.com" + } + ] +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..3e8dad2 --- /dev/null +++ b/composer.lock @@ -0,0 +1,485 @@ +{ + "_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": "95db59cb7efec488d581da2cafacd03f", + "packages": [ + { + "name": "guzzlehttp/guzzle", + "version": "7.8.0", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/guzzlehttp/guzzle/7.8.0/guzzlehttp-guzzle-7.8.0.zip", + "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "ext-curl": "*", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "time": "2023-08-27T10:20:53+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/guzzlehttp/promises/2.0.1/guzzlehttp-promises-2.0.1.zip", + "reference": "111166291a0f8130081195ac4556a5587d7f1b5d", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2023-08-03T15:11:55+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.6.1", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/guzzlehttp/psr7/2.6.1/guzzlehttp-psr7-2.6.1.zip", + "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2023-08-27T10:13:57+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/http-client/1.0.3/psr-http-client-1.0.3.zip", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.2", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/http-factory/1.0.2/psr-http-factory-1.0.2.zip", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "time": "2023-04-10T20:10:41+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "dist": { + "type": "zip", + "url": "https://mirrors.tencent.com/repository/composer/psr/http-message/2.0/psr-http-message-2.0.zip", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://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": "2023-04-04T09:54:51+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "dist": { + "type": "zip", + "url": "https://mirrors.cloud.tencent.com/repository/composer/ralouphie/getallheaders/3.0.3/ralouphie-getallheaders-3.0.3.zip", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "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/deprecation-contracts", + "version": "v2.5.2", + "dist": { + "type": "zip", + "url": "https://mirrors.tencent.com/repository/composer/symfony/deprecation-contracts/v2.5.2/symfony-deprecation-contracts-v2.5.2.zip", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "time": "2022-01-02T09:53:40+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=7.4" + }, + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/config/config.php b/config/config.php new file mode 100644 index 0000000..24954e6 --- /dev/null +++ b/config/config.php @@ -0,0 +1,5 @@ + '优惠券模块' +]; \ No newline at end of file diff --git a/src/Adapter/WechatAdapter.php b/src/Adapter/WechatAdapter.php new file mode 100644 index 0000000..664b279 --- /dev/null +++ b/src/Adapter/WechatAdapter.php @@ -0,0 +1,49 @@ +gateway = $gateway; + } + + public function setRight($right): self + { + $this->gateway->setRight($right); + return $this; + } + + public function setOrder($order): self + { + $this->gateway->setOrder($order); + return $this; + } + + public function setUser($user): self + { + $this->gateway->setUser($user); + return $this; + } + + public function issue() + { + return $this->gateway->issue(); + } + + public function query($couponCode) + { + return $this->gateway->query($couponCode); + } + + public function validate($couponCode) + { + return $this->gateway->validate($couponCode); + } +} \ No newline at end of file diff --git a/src/Adapter/YsdAdapter.php b/src/Adapter/YsdAdapter.php new file mode 100644 index 0000000..26c6f68 --- /dev/null +++ b/src/Adapter/YsdAdapter.php @@ -0,0 +1,49 @@ +gateway = $gateway; + } + + public function setRight($right): self + { + $this->gateway->setRight($right); + return $this; + } + + public function setOrder($order): self + { + $this->gateway->setOrder($order); + return $this; + } + + public function setUser($user): self + { + $this->gateway->setUser($user); + return $this; + } + + public function issue() + { + return $this->gateway->issue(); + } + + public function query($couponCode) + { + return $this->gateway->query($couponCode); + } + + public function validate($couponCode) + { + return $this->gateway->validate($couponCode); + } +} \ No newline at end of file diff --git a/src/Clients/ApiClient.php b/src/Clients/ApiClient.php new file mode 100644 index 0000000..777d0ac --- /dev/null +++ b/src/Clients/ApiClient.php @@ -0,0 +1,44 @@ +http = new Client(['base_uri' => $baseUri]); + } + + public function get(string $endpoint, array $query = []) + { + return $this->send('GET', $endpoint, [ + 'query' => $query, + ]); + } + + public function post(string $endpoint, array $data = []) + { + return $this->send('POST', $endpoint, [ + 'json' => $data, + ]); + } + + private function send(string $method, string $endpoint, array $options = []) + { + try { + $response = $this->http->request($method, $endpoint, $options); + $statusCode = $response->getStatusCode(); + $body = $response->getBody(); + // Handle response + } catch (RequestException $e) { + // Handle request error + } + } + +} \ No newline at end of file diff --git a/src/Contracts/CouponGateway.php b/src/Contracts/CouponGateway.php new file mode 100644 index 0000000..87b6bc4 --- /dev/null +++ b/src/Contracts/CouponGateway.php @@ -0,0 +1,39 @@ +gateway = $gateway; + } + + public function issue(array $data) + { + try { + return $this->gateway->issue($data); + } catch (\Exception $e) { + CouponLogger::getLogger(__CLASS__)->error("Error issuing coupon: {$e->getMessage()}"); + throw $e; + } + } + + public function setChannel($channel) + { + $this->channel = $channel; + return $this; + } +} \ No newline at end of file diff --git a/src/Gateways/BaseGateway.php b/src/Gateways/BaseGateway.php new file mode 100644 index 0000000..6ecd59d --- /dev/null +++ b/src/Gateways/BaseGateway.php @@ -0,0 +1,66 @@ +logger = CouponLogger::getLogger(get_class($this)); + } + + protected function log($message, $context = []) + { + $this->logger->info($message, $context); + } + + /** + * Notes: 设置权益 + * + * @Author: 玄尘 + * @Date: 2023/10/31 10:21 + * @param $right + * @return \XuanChen\CardCoupon\Contracts\BaseGateway + */ + public function setRight($right): self + { + $this->right = $right; + + return $this; + } + + /** + * Notes: 设置订单 + * + * @Author: 玄尘 + * @Date: 2023/10/31 10:22 + * @param $order + */ + public function setOrder($order) + { + $this->order = $order; + return $this; + } + + /** + * Notes: 设置购买人 + * + * @Author: 玄尘 + * @Date: 2023/10/31 10:22 + * @param $user + */ + public function setUser($user) + { + $this->user = $user; + return $this; + } +} \ No newline at end of file diff --git a/src/Gateways/WechatGateway.php b/src/Gateways/WechatGateway.php new file mode 100644 index 0000000..a8c76b1 --- /dev/null +++ b/src/Gateways/WechatGateway.php @@ -0,0 +1,35 @@ +server_id = config('pingan.server_id'); + $this->des = config('pingan.des'); + $this->key = config('pingan.key'); + $this->outlet_id = config('pingan.outlet_id'); + $this->baseUri = config('pingan.BaseUrl'); + $this->apiClient = new ApiClient($this->baseUri); + } + +} \ No newline at end of file diff --git a/src/Gateways/YsdGateway.php b/src/Gateways/YsdGateway.php new file mode 100644 index 0000000..6067ddb --- /dev/null +++ b/src/Gateways/YsdGateway.php @@ -0,0 +1,146 @@ +server_id = config('pingan.server_id'); + $this->des = config('pingan.des'); + $this->key = config('pingan.key'); + $this->outlet_id = config('pingan.outlet_id'); + $this->baseUri = config('pingan.BaseUrl'); + + $this->apiClient = new ApiClient($this->baseUri); + } + + /** + * Notes: 发券 + * + * @Author: 玄尘 + * @Date: 2023/10/30 13:56 + * @return mixed + */ + public function issue() + { + $data = [ + 'activityId' => $this->right->type_no, + 'mobile' => $this->user->username, + 'outletId' => $this->outlet_id, + ]; + $params = $this->getData($data); + dd($params); + return $params; + } + + /** + * Notes: description + * + * @Author: 玄尘 + * @Date: 2023/10/30 13:56 + * @param \App\Models\Coupon $coupon + * @return mixed + */ + public function query(Coupon $coupon) + { + // TODO: Implement queryCoupon() method. + } + + /** + * Notes: description + * + * @Author: 玄尘 + * @Date: 2023/10/30 13:56 + * @param \App\Models\Coupon $coupon + * @return mixed + */ + public function validate(Coupon $coupon) + { + // TODO: Implement verifyCoupon() method. + } + + public function getData($paramArray, $channel = 'pingan') + { + $paramStr = self::keyasc(json_encode($paramArray)); + $addcode = Str::random(16); + $sign = self::keysign($paramStr, $addcode); + + $data = [ + 'server_id' => $this->server_id, + 'key' => $this->key, + 'data' => $paramStr, + 'addcode' => $addcode, + 'sign' => $sign, + ]; + + if ($channel == 'bsshop') { + $data['des'] = $this->des; + } + + return $data; + } + + public function checkData(Request $request) + { + $server_id = $request->server_id ?? false; + $key = $request->key ?? false; + $data = $request->data ?? false; + $addcode = $request->addcode ?? false; + $sign = $request->sign ?? false; + + if (! $server_id) { + return '参数server_id不能为空'; + } + + if (! $key) { + return '参数key不能为空'; + } + + if (! $sign) { + return '参数sign不能为空'; + } + + if (! $data) { + return '参数data不能为空'; + } + + if (! $addcode) { + return '参数addcode不能为空'; + } + + if ($this->key) { + $this->key = $key; + } + + $data = str_replace('\\', '', $data); + $data = str_replace(' ', '+', $data); + + $checksign = $this->keysign($data, $addcode); + if ($checksign != $sign) { + return '参数sign不正确'; + } + + $keydesc = $this->keydesc($data); + $keydescArr = json_decode($this->keydesc($data), true); + if (empty($keydescArr) && ! empty($keydesc)) { + return '传递的json数据不对'; + } + + return $keydescArr; + } +} \ No newline at end of file diff --git a/src/Logging/CouponLogger.php b/src/Logging/CouponLogger.php new file mode 100644 index 0000000..14f7a83 --- /dev/null +++ b/src/Logging/CouponLogger.php @@ -0,0 +1,17 @@ +pushHandler(new StreamHandler(storage_path('logs/coupon.log'))); + + return $logger; + } +} \ No newline at end of file diff --git a/src/Providers/CouponServiceProvider.php b/src/Providers/CouponServiceProvider.php new file mode 100644 index 0000000..b9b1083 --- /dev/null +++ b/src/Providers/CouponServiceProvider.php @@ -0,0 +1,27 @@ +app->singleton('card_coupon.', function ($app) { + return new CouponService(); + }); + + $this->app->bind(CouponService::class, function ($app) { + $couponGateway = $app->make(CouponGateway::class); + return new CouponService($couponGateway); + }); + } + + public function boot() + { + $this->mergeConfigFrom(__DIR__.'/../config/config.php', 'card-coupon'); + } +} \ No newline at end of file