|
|
@@ -0,0 +1,364 @@
|
|
|
+# SixShop Wangdian SDK
|
|
|
+
|
|
|
+A modern PHP SDK for Wangdian (旺店通) API integration with PHP 8.3+ support.
|
|
|
+
|
|
|
+## Features
|
|
|
+
|
|
|
+- **Modern PHP 8.3+**: Uses latest PHP features including readonly classes, named parameters, and strict typing
|
|
|
+- **PSR Compatible**: Implements PSR-4 autoloading, PSR-18 HTTP client, and PSR-3 logging interfaces
|
|
|
+- **Service-Oriented Architecture**: Clean separation of concerns with dedicated service classes
|
|
|
+- **Type Safety**: Full type hints and strict typing for better IDE support and error prevention
|
|
|
+- **Exception Handling**: Comprehensive exception hierarchy for proper error handling
|
|
|
+- **Easy Configuration**: Simple configuration management for different environments
|
|
|
+- **Comprehensive API Coverage**: Supports all major Wangdian API endpoints
|
|
|
+
|
|
|
+## Installation
|
|
|
+
|
|
|
+```bash
|
|
|
+composer require six-shop/wangdian
|
|
|
+```
|
|
|
+
|
|
|
+## Quick Start
|
|
|
+
|
|
|
+### Basic Usage
|
|
|
+
|
|
|
+```php
|
|
|
+use SixShop\Wangdian\WangdianFactory;
|
|
|
+
|
|
|
+// Create a client for sandbox environment
|
|
|
+$client = WangdianFactory::createSandboxClient(
|
|
|
+ sid: 'your-sid',
|
|
|
+ appKey: 'your-app-key',
|
|
|
+ appSecret: 'your-app-secret'
|
|
|
+);
|
|
|
+
|
|
|
+// Query shop information
|
|
|
+$response = $client->basic()->queryShop('api_test');
|
|
|
+
|
|
|
+if ($response->isSuccess()) {
|
|
|
+ $shopData = $response->getData();
|
|
|
+ echo "Shop Name: " . $shopData['shop_name'];
|
|
|
+} else {
|
|
|
+ echo "Error: " . $response->getMessage();
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### Production Environment
|
|
|
+
|
|
|
+```php
|
|
|
+use SixShop\Wangdian\WangdianFactory;
|
|
|
+
|
|
|
+// Create a client for production environment
|
|
|
+$client = WangdianFactory::createProductionClient(
|
|
|
+ sid: 'your-sid',
|
|
|
+ appKey: 'your-app-key',
|
|
|
+ appSecret: 'your-app-secret'
|
|
|
+);
|
|
|
+```
|
|
|
+
|
|
|
+### Custom Configuration
|
|
|
+
|
|
|
+```php
|
|
|
+use SixShop\Wangdian\Config\Config;
|
|
|
+use SixShop\Wangdian\WangdianFactory;
|
|
|
+
|
|
|
+$config = new Config(
|
|
|
+ sid: 'your-sid',
|
|
|
+ appKey: 'your-app-key',
|
|
|
+ appSecret: 'your-app-secret',
|
|
|
+ baseUrl: 'https://custom.wangdian.cn/openapi2',
|
|
|
+ timeout: 60,
|
|
|
+ debug: true
|
|
|
+);
|
|
|
+
|
|
|
+$client = WangdianFactory::createClient($config);
|
|
|
+```
|
|
|
+
|
|
|
+## API Services
|
|
|
+
|
|
|
+The SDK is organized into service classes for different API domains:
|
|
|
+
|
|
|
+### Basic Service
|
|
|
+
|
|
|
+Handle shops, warehouses, logistics, and purchase providers:
|
|
|
+
|
|
|
+```php
|
|
|
+// Query shop information
|
|
|
+$response = $client->basic()->queryShop('shop_no');
|
|
|
+
|
|
|
+// Query warehouses
|
|
|
+$response = $client->basic()->queryWarehouse();
|
|
|
+
|
|
|
+// Query logistics providers
|
|
|
+$response = $client->basic()->queryLogistics();
|
|
|
+
|
|
|
+// Query purchase providers
|
|
|
+$response = $client->basic()->queryPurchaseProvider();
|
|
|
+
|
|
|
+// Create purchase provider
|
|
|
+$response = $client->basic()->createPurchaseProvider([
|
|
|
+ 'provider_name' => 'New Provider',
|
|
|
+ 'contact' => 'John Doe',
|
|
|
+ 'phone' => '1234567890'
|
|
|
+]);
|
|
|
+```
|
|
|
+
|
|
|
+### Goods Service
|
|
|
+
|
|
|
+Manage products and specifications:
|
|
|
+
|
|
|
+```php
|
|
|
+// Query goods
|
|
|
+$response = $client->goods()->query([
|
|
|
+ 'start_time' => '2024-01-01 00:00:00',
|
|
|
+ 'end_time' => '2024-01-31 23:59:59'
|
|
|
+]);
|
|
|
+
|
|
|
+// Push goods
|
|
|
+$response = $client->goods()->push([
|
|
|
+ 'goods_list' => [
|
|
|
+ [
|
|
|
+ 'goods_name' => 'Test Product',
|
|
|
+ 'goods_no' => 'TEST001',
|
|
|
+ 'brand_name' => 'Test Brand'
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+]);
|
|
|
+
|
|
|
+// Push specifications
|
|
|
+$response = $client->goods()->pushSpec([
|
|
|
+ 'spec_list' => [
|
|
|
+ [
|
|
|
+ 'spec_name' => 'Red-Large',
|
|
|
+ 'spec_no' => 'TEST001-RL',
|
|
|
+ 'goods_no' => 'TEST001'
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+]);
|
|
|
+```
|
|
|
+
|
|
|
+### Trade Service
|
|
|
+
|
|
|
+Handle orders and trade-related operations:
|
|
|
+
|
|
|
+```php
|
|
|
+// Push trade orders
|
|
|
+$response = $client->trade()->push([
|
|
|
+ 'shop_no' => 'api_test',
|
|
|
+ 'switch' => 0,
|
|
|
+ 'trade_list' => [
|
|
|
+ [
|
|
|
+ 'tid' => 'ORDER' . time(),
|
|
|
+ 'trade_status' => 30,
|
|
|
+ 'delivery_term' => 1,
|
|
|
+ 'pay_status' => 2,
|
|
|
+ 'buyer_nick' => 'customer001',
|
|
|
+ 'receiver_name' => 'John Doe',
|
|
|
+ 'receiver_mobile' => '13800138000',
|
|
|
+ 'receiver_address' => 'Test Address',
|
|
|
+ 'logistics_type' => 4,
|
|
|
+ 'post_amount' => 10,
|
|
|
+ 'paid' => 100,
|
|
|
+ 'order_list' => [
|
|
|
+ [
|
|
|
+ 'oid' => 'ITEM' . time(),
|
|
|
+ 'status' => 30,
|
|
|
+ 'goods_id' => 'GOODS001',
|
|
|
+ 'goods_name' => 'Test Product',
|
|
|
+ 'num' => 1,
|
|
|
+ 'price' => 90,
|
|
|
+ 'cid' => '1'
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+]);
|
|
|
+
|
|
|
+// Query trades
|
|
|
+$response = $client->trade()->query([
|
|
|
+ 'start_time' => '2024-01-01 00:00:00',
|
|
|
+ 'end_time' => '2024-01-31 23:59:59'
|
|
|
+]);
|
|
|
+```
|
|
|
+
|
|
|
+### Stock Service
|
|
|
+
|
|
|
+Manage inventory and stock operations:
|
|
|
+
|
|
|
+```php
|
|
|
+// Query stock
|
|
|
+$response = $client->stock()->query([
|
|
|
+ 'start_time' => '2024-01-01 00:00:00',
|
|
|
+ 'end_time' => '2024-01-31 23:59:59'
|
|
|
+]);
|
|
|
+
|
|
|
+// Push stock transfer
|
|
|
+$response = $client->stock()->pushTransfer([
|
|
|
+ 'transfer_info' => [
|
|
|
+ 'from_warehouse_no' => '001',
|
|
|
+ 'to_warehouse_no' => '002',
|
|
|
+ 'details_list' => [
|
|
|
+ [
|
|
|
+ 'spec_no' => 'TEST001',
|
|
|
+ 'num' => 10
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+]);
|
|
|
+
|
|
|
+// Push stockin order
|
|
|
+$response = $client->stock()->pushStockinOrder([
|
|
|
+ 'stockin_info' => [
|
|
|
+ 'warehouse_no' => '001',
|
|
|
+ 'stockin_type' => 1,
|
|
|
+ 'details_list' => [
|
|
|
+ [
|
|
|
+ 'spec_no' => 'TEST001',
|
|
|
+ 'num' => 100,
|
|
|
+ 'price' => 50
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+]);
|
|
|
+```
|
|
|
+
|
|
|
+### Purchase Service
|
|
|
+
|
|
|
+Handle purchase orders and returns:
|
|
|
+
|
|
|
+```php
|
|
|
+// Push purchase order
|
|
|
+$response = $client->purchase()->pushOrder([
|
|
|
+ 'purchase_info' => [
|
|
|
+ 'provider_no' => '2',
|
|
|
+ 'warehouse_no' => '001',
|
|
|
+ 'outer_no' => 'PO' . time(),
|
|
|
+ 'contact' => 'Supplier Contact',
|
|
|
+ 'details_list' => [
|
|
|
+ [
|
|
|
+ 'spec_no' => 'TEST001',
|
|
|
+ 'num' => 50,
|
|
|
+ 'price' => 40
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+]);
|
|
|
+
|
|
|
+// Query purchase orders
|
|
|
+$response = $client->purchase()->queryOrder([
|
|
|
+ 'start_time' => '2024-01-01 00:00:00',
|
|
|
+ 'end_time' => '2024-01-31 23:59:59'
|
|
|
+]);
|
|
|
+```
|
|
|
+
|
|
|
+### Refund Service
|
|
|
+
|
|
|
+Handle refund processing:
|
|
|
+
|
|
|
+```php
|
|
|
+// Query refunds
|
|
|
+$response = $client->refund()->query([
|
|
|
+ 'start_time' => '2024-01-01 00:00:00',
|
|
|
+ 'end_time' => '2024-01-31 23:59:59'
|
|
|
+]);
|
|
|
+
|
|
|
+// Push sales refund
|
|
|
+$response = $client->refund()->pushSalesRefund([
|
|
|
+ 'refund_list' => [
|
|
|
+ [
|
|
|
+ 'refund_no' => 'REF' . time(),
|
|
|
+ 'tid' => 'ORDER123',
|
|
|
+ 'refund_amount' => 50,
|
|
|
+ 'refund_reason' => 'Customer request'
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+]);
|
|
|
+```
|
|
|
+
|
|
|
+## Error Handling
|
|
|
+
|
|
|
+The SDK provides comprehensive error handling:
|
|
|
+
|
|
|
+```php
|
|
|
+use SixShop\Wangdian\Exception\ApiException;
|
|
|
+use SixShop\Wangdian\Exception\HttpException;
|
|
|
+use SixShop\Wangdian\Exception\ConfigException;
|
|
|
+
|
|
|
+try {
|
|
|
+ $response = $client->basic()->queryShop('invalid_shop');
|
|
|
+} catch (ApiException $e) {
|
|
|
+ // API returned an error
|
|
|
+ echo "API Error: " . $e->getMessage();
|
|
|
+ echo "API Code: " . $e->getApiCode();
|
|
|
+ var_dump($e->getResponseData());
|
|
|
+} catch (HttpException $e) {
|
|
|
+ // HTTP request failed
|
|
|
+ echo "HTTP Error: " . $e->getMessage();
|
|
|
+ echo "HTTP Status: " . $e->getHttpStatusCode();
|
|
|
+} catch (ConfigException $e) {
|
|
|
+ // Configuration error
|
|
|
+ echo "Config Error: " . $e->getMessage();
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## Response Handling
|
|
|
+
|
|
|
+All API responses are wrapped in an `ApiResponse` object:
|
|
|
+
|
|
|
+```php
|
|
|
+$response = $client->basic()->queryShop('api_test');
|
|
|
+
|
|
|
+// Check if successful
|
|
|
+if ($response->isSuccess()) {
|
|
|
+ // Get response data
|
|
|
+ $data = $response->getData();
|
|
|
+
|
|
|
+ // Get specific fields
|
|
|
+ $shopName = $response->get('data.shop_name');
|
|
|
+
|
|
|
+ // Convert to array
|
|
|
+ $array = $response->toArray();
|
|
|
+
|
|
|
+ // Convert to JSON
|
|
|
+ $json = $response->toJson();
|
|
|
+} else {
|
|
|
+ // Handle error
|
|
|
+ echo "Error Code: " . $response->getCode();
|
|
|
+ echo "Error Message: " . $response->getMessage();
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## Logging
|
|
|
+
|
|
|
+The SDK supports PSR-3 compatible logging:
|
|
|
+
|
|
|
+```php
|
|
|
+use Monolog\Logger;
|
|
|
+use Monolog\Handler\StreamHandler;
|
|
|
+use SixShop\Wangdian\WangdianFactory;
|
|
|
+
|
|
|
+$logger = new Logger('wangdian');
|
|
|
+$logger->pushHandler(new StreamHandler('wangdian.log', Logger::INFO));
|
|
|
+
|
|
|
+$client = WangdianFactory::createSandboxClient(
|
|
|
+ sid: 'your-sid',
|
|
|
+ appKey: 'your-app-key',
|
|
|
+ appSecret: 'your-app-secret',
|
|
|
+ logger: $logger
|
|
|
+);
|
|
|
+```
|
|
|
+
|
|
|
+## Requirements
|
|
|
+
|
|
|
+- PHP >= 8.3
|
|
|
+- ext-json
|
|
|
+- ext-curl
|
|
|
+- guzzlehttp/guzzle ^7.8
|
|
|
+
|
|
|
+## Contributing
|
|
|
+
|
|
|
+Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
+
|
|
|
+## License
|
|
|
+
|
|
|
+This project is licensed under the MIT License - see the LICENSE file for details.
|