@waywake/youzanyun-sdk 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +115 -0
- package/dist/cjs/client.d.ts +11 -0
- package/dist/cjs/client.d.ts.map +1 -0
- package/dist/cjs/config/http.d.ts +9 -0
- package/dist/cjs/config/http.d.ts.map +1 -0
- package/dist/cjs/crypto.d.ts +11 -0
- package/dist/cjs/crypto.d.ts.map +1 -0
- package/dist/cjs/index.d.ts +15 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +231 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/token.d.ts +15 -0
- package/dist/cjs/token.d.ts.map +1 -0
- package/dist/cjs/types.d.ts +53 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/utils/http.d.ts +18 -0
- package/dist/cjs/utils/http.d.ts.map +1 -0
- package/dist/esm/client.d.ts +11 -0
- package/dist/esm/client.d.ts.map +1 -0
- package/dist/esm/config/http.d.ts +9 -0
- package/dist/esm/config/http.d.ts.map +1 -0
- package/dist/esm/crypto.d.ts +11 -0
- package/dist/esm/crypto.d.ts.map +1 -0
- package/dist/esm/index.d.ts +15 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +180 -0
- package/dist/esm/token.d.ts +15 -0
- package/dist/esm/token.d.ts.map +1 -0
- package/dist/esm/types.d.ts +53 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/utils/http.d.ts +18 -0
- package/dist/esm/utils/http.d.ts.map +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 Youzan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
YouzanYun SDK
|
|
2
|
+
=======
|
|
3
|
+
|
|
4
|
+
[](https://www.npmjs.com/package/@waywake/youzanyun-sdk)
|
|
5
|
+
[](LICENSE.md)
|
|
6
|
+
[]()
|
|
7
|
+
[](https://travis-ci.org/youzan/open-sdk-node)
|
|
8
|
+
[](https://coveralls.io/github/youzan/open-sdk-node?branch=master)
|
|
9
|
+
|
|
10
|
+
YouzanYun SDK for Node.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm i @waywake/youzanyun-sdk --save
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
可参考 [examples](examples)
|
|
21
|
+
|
|
22
|
+
### 1. 获取及刷新access_token
|
|
23
|
+
|
|
24
|
+
#### 工具型应用 获取access_token
|
|
25
|
+
|
|
26
|
+
```node
|
|
27
|
+
const youzanyun = require('@waywake/youzanyun-sdk');
|
|
28
|
+
|
|
29
|
+
// 获取token
|
|
30
|
+
const resp = youzanyun.token.get({
|
|
31
|
+
authorize_type: 'authorization_code',
|
|
32
|
+
client_id: 'YOUR_CLIENT_ID',
|
|
33
|
+
client_secret: 'YOUR_CLIENT_SECRET',
|
|
34
|
+
code: 'YOUR_CODE',
|
|
35
|
+
redirect_uri: 'YOUR_REDIRECT_URI',
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
#### 自用型应用 获取access_token
|
|
40
|
+
|
|
41
|
+
```node
|
|
42
|
+
const youzanyun = require('@waywake/youzanyun-sdk');
|
|
43
|
+
|
|
44
|
+
const resp = youzanyun.token.get({
|
|
45
|
+
authorize_type: 'silent',
|
|
46
|
+
client_id: 'YOUR_CLIENT_ID',
|
|
47
|
+
client_secret: 'YOUR_CLIENT_SECRET',
|
|
48
|
+
grant_id: 110,
|
|
49
|
+
refresh: true, // 是否获取refresh_token(可通过refresh_token刷新token)
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### 工具型应用及自用型应用 刷新access_token
|
|
54
|
+
|
|
55
|
+
```node
|
|
56
|
+
const youzanyun = require('@waywake/youzanyun-sdk');
|
|
57
|
+
|
|
58
|
+
// 刷新token
|
|
59
|
+
const resp = youzanyun.token.get({
|
|
60
|
+
authorize_type: 'refresh_token',
|
|
61
|
+
client_id: 'YOUR_CLIENT_ID',
|
|
62
|
+
client_secret: 'YOUR_CLIENT_SECRET',
|
|
63
|
+
refresh_token: 'YOUR_REFRESH_TOKEN',
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 2. 接口调用
|
|
68
|
+
|
|
69
|
+
#### Token方式
|
|
70
|
+
|
|
71
|
+
```node
|
|
72
|
+
const youzanyun = require('@waywake/youzanyun-sdk');
|
|
73
|
+
|
|
74
|
+
const token = 'f59b1a6bb04f4eqweqd1c6af315d';
|
|
75
|
+
const params = {tid: 'E20190509110527067500013'};
|
|
76
|
+
|
|
77
|
+
const resp = youzanyun.client.call({
|
|
78
|
+
api: 'youzan.trade.get',
|
|
79
|
+
version: '4.0.0',
|
|
80
|
+
token,
|
|
81
|
+
params,
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
#### 文件上传
|
|
86
|
+
|
|
87
|
+
```node
|
|
88
|
+
const youzanyun = require('@waywake/youzanyun-sdk');
|
|
89
|
+
|
|
90
|
+
const token = 'f59b1a6bb0asdasq613d1c6af315d';
|
|
91
|
+
const files = {'image': path.resolve(__dirname, './pic.png')};
|
|
92
|
+
|
|
93
|
+
const resp = youzanyun.client.call({
|
|
94
|
+
api: 'youzan.materials.storage.platform.img.upload',
|
|
95
|
+
version: '3.0.0',
|
|
96
|
+
token,
|
|
97
|
+
params: {},
|
|
98
|
+
files,
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 3. 消息解密
|
|
103
|
+
|
|
104
|
+
```node
|
|
105
|
+
const youzanyun = require('@waywake/youzanyun-sdk');
|
|
106
|
+
|
|
107
|
+
const messages = 'YOUR_RECEIVED_MESSAGES';
|
|
108
|
+
const clientSecret = 'YOUR_CLIENT_SECRET';
|
|
109
|
+
|
|
110
|
+
const resp = youzanyun.crypto.decrypt(messages, clientSecret);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API 调用客户端
|
|
3
|
+
*/
|
|
4
|
+
import type { ApiCallParams } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* 发起接口调用
|
|
7
|
+
*
|
|
8
|
+
* @param apiParam 接口调用参数 { api, version, token?, params?, files?, config?, host? }
|
|
9
|
+
*/
|
|
10
|
+
export declare function call(apiParam: ApiCallParams): Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
11
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAa7C;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,QAAQ,EAAE,aAAa,wDAgC3C"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP URL 配置
|
|
3
|
+
*/
|
|
4
|
+
export declare function getBaseUrl(): string;
|
|
5
|
+
export declare function getUrlToken(): string;
|
|
6
|
+
export declare function getUrlAPI(api: string, version: string, token: string): string;
|
|
7
|
+
export declare function getUrlAPIExempt(api: string, version: string): string;
|
|
8
|
+
export declare function getUrlTextArea(api: string, version: string): string;
|
|
9
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/config/http.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 密文解密
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 密文解密,适用于订购等消息
|
|
6
|
+
*
|
|
7
|
+
* @param messages 应用收到的密文(收到的原始密文消息,无需解码)
|
|
8
|
+
* @param clientSecret 应用的 clientSecret(可在有赞云控制台查看)
|
|
9
|
+
*/
|
|
10
|
+
export declare function decrypt(messages: string, clientSecret: string): string;
|
|
11
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAatE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YouzanYun SDK for Node
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* import { client, token, crypto } from '@waywake/youzanyun-sdk';
|
|
6
|
+
*/
|
|
7
|
+
export { call } from './client';
|
|
8
|
+
export { get } from './token';
|
|
9
|
+
export { decrypt } from './crypto';
|
|
10
|
+
export type { AuthorizeType, ApiCallParams, TokenParams, SilentTokenParams, AuthorizationCodeTokenParams, RefreshTokenParams, ClientConfig } from './types';
|
|
11
|
+
import * as client from './client';
|
|
12
|
+
import * as token from './token';
|
|
13
|
+
import * as crypto from './crypto';
|
|
14
|
+
export { client, token, crypto };
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAAE,4BAA4B,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5J,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,KAAK,KAAK,MAAM,SAAS,CAAC;AACjC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAEnC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
function __accessProp(key) {
|
|
8
|
+
return this[key];
|
|
9
|
+
}
|
|
10
|
+
var __toESMCache_node;
|
|
11
|
+
var __toESMCache_esm;
|
|
12
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
13
|
+
var canCache = mod != null && typeof mod === "object";
|
|
14
|
+
if (canCache) {
|
|
15
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
16
|
+
var cached = cache.get(mod);
|
|
17
|
+
if (cached)
|
|
18
|
+
return cached;
|
|
19
|
+
}
|
|
20
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
21
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
22
|
+
for (let key of __getOwnPropNames(mod))
|
|
23
|
+
if (!__hasOwnProp.call(to, key))
|
|
24
|
+
__defProp(to, key, {
|
|
25
|
+
get: __accessProp.bind(mod, key),
|
|
26
|
+
enumerable: true
|
|
27
|
+
});
|
|
28
|
+
if (canCache)
|
|
29
|
+
cache.set(mod, to);
|
|
30
|
+
return to;
|
|
31
|
+
};
|
|
32
|
+
var __toCommonJS = (from) => {
|
|
33
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
34
|
+
if (entry)
|
|
35
|
+
return entry;
|
|
36
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
37
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
38
|
+
for (var key of __getOwnPropNames(from))
|
|
39
|
+
if (!__hasOwnProp.call(entry, key))
|
|
40
|
+
__defProp(entry, key, {
|
|
41
|
+
get: __accessProp.bind(from, key),
|
|
42
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
__moduleCache.set(from, entry);
|
|
46
|
+
return entry;
|
|
47
|
+
};
|
|
48
|
+
var __moduleCache;
|
|
49
|
+
var __returnValue = (v) => v;
|
|
50
|
+
function __exportSetter(name, newValue) {
|
|
51
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
52
|
+
}
|
|
53
|
+
var __export = (target, all) => {
|
|
54
|
+
for (var name in all)
|
|
55
|
+
__defProp(target, name, {
|
|
56
|
+
get: all[name],
|
|
57
|
+
enumerable: true,
|
|
58
|
+
configurable: true,
|
|
59
|
+
set: __exportSetter.bind(all, name)
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// src/index.ts
|
|
64
|
+
var exports_src = {};
|
|
65
|
+
__export(exports_src, {
|
|
66
|
+
token: () => exports_token,
|
|
67
|
+
get: () => get,
|
|
68
|
+
decrypt: () => decrypt,
|
|
69
|
+
crypto: () => exports_crypto,
|
|
70
|
+
client: () => exports_client,
|
|
71
|
+
call: () => call
|
|
72
|
+
});
|
|
73
|
+
module.exports = __toCommonJS(exports_src);
|
|
74
|
+
|
|
75
|
+
// src/client.ts
|
|
76
|
+
var exports_client = {};
|
|
77
|
+
__export(exports_client, {
|
|
78
|
+
call: () => call
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// src/config/http.ts
|
|
82
|
+
var BASE_URL = "https://open.youzanyun.com";
|
|
83
|
+
function getBaseUrl() {
|
|
84
|
+
return BASE_URL;
|
|
85
|
+
}
|
|
86
|
+
function getUrlToken() {
|
|
87
|
+
return "/auth/token";
|
|
88
|
+
}
|
|
89
|
+
function getUrlAPI(api, version, token) {
|
|
90
|
+
return `/api/${api}/${version}?access_token=${token}`;
|
|
91
|
+
}
|
|
92
|
+
function getUrlAPIExempt(api, version) {
|
|
93
|
+
return `/api/auth_exempt/${api}/${version}`;
|
|
94
|
+
}
|
|
95
|
+
function getUrlTextArea(api, version) {
|
|
96
|
+
return `/api/_textarea_/${api}/${version}`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/utils/http.ts
|
|
100
|
+
var import_fs = __toESM(require("fs"));
|
|
101
|
+
var import_axios = __toESM(require("axios"));
|
|
102
|
+
var import_form_data = __toESM(require("form-data"));
|
|
103
|
+
var httpClient = import_axios.default.create({
|
|
104
|
+
baseURL: getBaseUrl(),
|
|
105
|
+
headers: {
|
|
106
|
+
"User-Agent": "YZY-Open-Client 1.0.0 - Node"
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
async function post(url, params) {
|
|
110
|
+
const resp = await httpClient.post(url, params, {
|
|
111
|
+
headers: { "Content-type": "application/json;charset=UTF-8" }
|
|
112
|
+
});
|
|
113
|
+
return resp;
|
|
114
|
+
}
|
|
115
|
+
async function upload(url, files) {
|
|
116
|
+
const form = new import_form_data.default;
|
|
117
|
+
if (files instanceof Map) {
|
|
118
|
+
files.forEach((filePath, key) => {
|
|
119
|
+
form.append(key, import_fs.default.createReadStream(filePath));
|
|
120
|
+
});
|
|
121
|
+
} else {
|
|
122
|
+
for (const [key, filePath] of Object.entries(files)) {
|
|
123
|
+
form.append(key, import_fs.default.createReadStream(filePath));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const resp = await httpClient.post(url, form, {
|
|
127
|
+
headers: form.getHeaders()
|
|
128
|
+
});
|
|
129
|
+
return resp;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/client.ts
|
|
133
|
+
function hasFiles(files) {
|
|
134
|
+
if (!files)
|
|
135
|
+
return false;
|
|
136
|
+
if (files instanceof Map)
|
|
137
|
+
return files.size > 0;
|
|
138
|
+
return Object.keys(files).length > 0;
|
|
139
|
+
}
|
|
140
|
+
function call(apiParam) {
|
|
141
|
+
if (!apiParam || typeof apiParam !== "object") {
|
|
142
|
+
throw new Error("参数异常: api 必传");
|
|
143
|
+
}
|
|
144
|
+
if (!apiParam.api) {
|
|
145
|
+
throw new Error("参数异常: api 必传");
|
|
146
|
+
}
|
|
147
|
+
if (!apiParam.version) {
|
|
148
|
+
throw new Error("参数异常: version 必传");
|
|
149
|
+
}
|
|
150
|
+
let urlPath;
|
|
151
|
+
if (apiParam.token != null) {
|
|
152
|
+
urlPath = getUrlAPI(apiParam.api, apiParam.version, apiParam.token);
|
|
153
|
+
if (apiParam.config?.isRichText) {
|
|
154
|
+
urlPath = getUrlTextArea(apiParam.api, apiParam.version);
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
urlPath = getUrlAPIExempt(apiParam.api, apiParam.version);
|
|
158
|
+
}
|
|
159
|
+
if (apiParam.host != null) {
|
|
160
|
+
urlPath = apiParam.host + urlPath;
|
|
161
|
+
}
|
|
162
|
+
if (hasFiles(apiParam.files)) {
|
|
163
|
+
return upload(urlPath, apiParam.files);
|
|
164
|
+
}
|
|
165
|
+
return post(urlPath, apiParam.params);
|
|
166
|
+
}
|
|
167
|
+
// src/token.ts
|
|
168
|
+
var exports_token = {};
|
|
169
|
+
__export(exports_token, {
|
|
170
|
+
get: () => get
|
|
171
|
+
});
|
|
172
|
+
var VALID_AUTHORIZE_TYPES = new Set([
|
|
173
|
+
"silent",
|
|
174
|
+
"authorization_code",
|
|
175
|
+
"refresh_token"
|
|
176
|
+
]);
|
|
177
|
+
function get(params) {
|
|
178
|
+
if (!params || typeof params !== "object") {
|
|
179
|
+
throw new Error("参数异常: 参数缺少必要字段");
|
|
180
|
+
}
|
|
181
|
+
if (!params.client_id || !params.client_secret) {
|
|
182
|
+
throw new Error("参数异常: client_id client_secret 必传");
|
|
183
|
+
}
|
|
184
|
+
if (!params.authorize_type || !VALID_AUTHORIZE_TYPES.has(params.authorize_type)) {
|
|
185
|
+
throw new Error("参数异常: authorize_type 类型错误");
|
|
186
|
+
}
|
|
187
|
+
switch (params.authorize_type) {
|
|
188
|
+
case "silent":
|
|
189
|
+
if (!params.grant_id) {
|
|
190
|
+
throw new Error("参数异常: grant_id 必传");
|
|
191
|
+
}
|
|
192
|
+
break;
|
|
193
|
+
case "authorization_code":
|
|
194
|
+
if (!params.code || !params.redirect_uri) {
|
|
195
|
+
throw new Error("参数异常: code redirect_uri 必传");
|
|
196
|
+
}
|
|
197
|
+
break;
|
|
198
|
+
case "refresh_token":
|
|
199
|
+
if (!params.refresh_token) {
|
|
200
|
+
throw new Error("参数异常: refresh_token 必传");
|
|
201
|
+
}
|
|
202
|
+
break;
|
|
203
|
+
default: {
|
|
204
|
+
const _exhaustive = params;
|
|
205
|
+
throw new Error(`参数异常: 未知的 authorize_type`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
let urlPath = getUrlToken();
|
|
209
|
+
if (params.host != null) {
|
|
210
|
+
urlPath = params.host + urlPath;
|
|
211
|
+
}
|
|
212
|
+
return post(urlPath, params);
|
|
213
|
+
}
|
|
214
|
+
// src/crypto.ts
|
|
215
|
+
var exports_crypto = {};
|
|
216
|
+
__export(exports_crypto, {
|
|
217
|
+
decrypt: () => decrypt
|
|
218
|
+
});
|
|
219
|
+
var import_crypto = require("crypto");
|
|
220
|
+
function decrypt(messages, clientSecret) {
|
|
221
|
+
if (!messages || !clientSecret) {
|
|
222
|
+
throw new Error("参数异常: messages clientSecret 不可为空");
|
|
223
|
+
}
|
|
224
|
+
const algorithm = decodeURIComponent(messages);
|
|
225
|
+
const key = clientSecret.substring(0, 16);
|
|
226
|
+
const iv = "0102030405060708";
|
|
227
|
+
const decipher = import_crypto.createDecipheriv("aes-128-cbc", key, iv);
|
|
228
|
+
let dec = decipher.update(algorithm, "base64", "utf-8");
|
|
229
|
+
dec += decipher.final();
|
|
230
|
+
return dec;
|
|
231
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token 管理
|
|
3
|
+
*/
|
|
4
|
+
import type { TokenParams } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* 获取 Token
|
|
7
|
+
*
|
|
8
|
+
* 必要字段: authorize_type client_id client_secret
|
|
9
|
+
*
|
|
10
|
+
* 自用型应用获取 Token: authorize_type = silent, 必传 grant_id
|
|
11
|
+
* 工具型应用获取 Token: authorize_type = authorization_code, 必传 code redirect_uri
|
|
12
|
+
* 工具型应用/自用型应用刷新 Token: authorize_type = refresh_token, 必传 refresh_token
|
|
13
|
+
*/
|
|
14
|
+
export declare function get(params: TokenParams): Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
15
|
+
//# sourceMappingURL=token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/token.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAU3C;;;;;;;;GAQG;AACH,wBAAgB,GAAG,CAAC,MAAM,EAAE,WAAW,wDA4CtC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth 授权类型
|
|
3
|
+
*/
|
|
4
|
+
export type AuthorizeType = 'silent' | 'authorization_code' | 'refresh_token';
|
|
5
|
+
/** Token 请求公共字段 */
|
|
6
|
+
interface TokenBaseParams {
|
|
7
|
+
client_id: string;
|
|
8
|
+
client_secret: string;
|
|
9
|
+
host?: string;
|
|
10
|
+
}
|
|
11
|
+
/** 自用型应用获取 Token */
|
|
12
|
+
export interface SilentTokenParams extends TokenBaseParams {
|
|
13
|
+
authorize_type: 'silent';
|
|
14
|
+
grant_id: number;
|
|
15
|
+
refresh?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/** 工具型应用获取 Token(授权码模式) */
|
|
18
|
+
export interface AuthorizationCodeTokenParams extends TokenBaseParams {
|
|
19
|
+
authorize_type: 'authorization_code';
|
|
20
|
+
code: string;
|
|
21
|
+
redirect_uri: string;
|
|
22
|
+
}
|
|
23
|
+
/** 刷新 Token */
|
|
24
|
+
export interface RefreshTokenParams extends TokenBaseParams {
|
|
25
|
+
authorize_type: 'refresh_token';
|
|
26
|
+
refresh_token: string;
|
|
27
|
+
}
|
|
28
|
+
/** Token 请求参数联合类型 */
|
|
29
|
+
export type TokenParams = SilentTokenParams | AuthorizationCodeTokenParams | RefreshTokenParams;
|
|
30
|
+
/** API 调用配置 */
|
|
31
|
+
export interface ClientConfig {
|
|
32
|
+
/** 是否使用富文本接口 */
|
|
33
|
+
isRichText?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/** API 调用参数 */
|
|
36
|
+
export interface ApiCallParams {
|
|
37
|
+
/** 接口名称,如 'youzan.trade.get'(必传) */
|
|
38
|
+
api: string;
|
|
39
|
+
/** 接口版本,如 '4.0.0'(必传) */
|
|
40
|
+
version: string;
|
|
41
|
+
/** OAuth access token(免登接口可不传) */
|
|
42
|
+
token?: string;
|
|
43
|
+
/** 请求参数 */
|
|
44
|
+
params?: Record<string, unknown>;
|
|
45
|
+
/** 上传文件:字段名到文件路径的映射 */
|
|
46
|
+
files?: Map<string, string> | Record<string, string>;
|
|
47
|
+
/** 额外配置 */
|
|
48
|
+
config?: ClientConfig;
|
|
49
|
+
/** 自定义主机地址 */
|
|
50
|
+
host?: string;
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,oBAAoB,GAAG,eAAe,CAAC;AAE9E,mBAAmB;AACnB,UAAU,eAAe;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,oBAAoB;AACpB,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,cAAc,EAAE,QAAQ,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,2BAA2B;AAC3B,MAAM,WAAW,4BAA6B,SAAQ,eAAe;IACnE,cAAc,EAAE,oBAAoB,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAe;AACf,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,cAAc,EAAE,eAAe,CAAC;IAChC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qBAAqB;AACrB,MAAM,MAAM,WAAW,GACnB,iBAAiB,GACjB,4BAA4B,GAC5B,kBAAkB,CAAC;AAIvB,eAAe;AACf,MAAM,WAAW,YAAY;IAC3B,gBAAgB;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAe;AACf,MAAM,WAAW,aAAa;IAC5B,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW;IACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,uBAAuB;IACvB,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrD,WAAW;IACX,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,cAAc;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP 请求工具
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 发起 POST 请求
|
|
6
|
+
*
|
|
7
|
+
* @param url 支持绝对路径、相对路径
|
|
8
|
+
* @param params POST 参数
|
|
9
|
+
*/
|
|
10
|
+
export declare function post(url: string, params?: Record<string, unknown>): Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
11
|
+
/**
|
|
12
|
+
* 发起上传文件请求
|
|
13
|
+
*
|
|
14
|
+
* @param url 支持绝对路径、相对路径
|
|
15
|
+
* @param files 上传文件参数,支持 Map 或 Object。示例: {"image": "/path/to/filename.jpg"}
|
|
16
|
+
*/
|
|
17
|
+
export declare function upload(url: string, files: Map<string, string> | Record<string, string>): Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
18
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/utils/http.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,wDAKvE;AAED;;;;;GAKG;AACH,wBAAsB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,wDAiB5F"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API 调用客户端
|
|
3
|
+
*/
|
|
4
|
+
import type { ApiCallParams } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* 发起接口调用
|
|
7
|
+
*
|
|
8
|
+
* @param apiParam 接口调用参数 { api, version, token?, params?, files?, config?, host? }
|
|
9
|
+
*/
|
|
10
|
+
export declare function call(apiParam: ApiCallParams): Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
11
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAa7C;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,QAAQ,EAAE,aAAa,wDAgC3C"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP URL 配置
|
|
3
|
+
*/
|
|
4
|
+
export declare function getBaseUrl(): string;
|
|
5
|
+
export declare function getUrlToken(): string;
|
|
6
|
+
export declare function getUrlAPI(api: string, version: string, token: string): string;
|
|
7
|
+
export declare function getUrlAPIExempt(api: string, version: string): string;
|
|
8
|
+
export declare function getUrlTextArea(api: string, version: string): string;
|
|
9
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/config/http.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 密文解密
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 密文解密,适用于订购等消息
|
|
6
|
+
*
|
|
7
|
+
* @param messages 应用收到的密文(收到的原始密文消息,无需解码)
|
|
8
|
+
* @param clientSecret 应用的 clientSecret(可在有赞云控制台查看)
|
|
9
|
+
*/
|
|
10
|
+
export declare function decrypt(messages: string, clientSecret: string): string;
|
|
11
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAatE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YouzanYun SDK for Node
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* import { client, token, crypto } from '@waywake/youzanyun-sdk';
|
|
6
|
+
*/
|
|
7
|
+
export { call } from './client';
|
|
8
|
+
export { get } from './token';
|
|
9
|
+
export { decrypt } from './crypto';
|
|
10
|
+
export type { AuthorizeType, ApiCallParams, TokenParams, SilentTokenParams, AuthorizationCodeTokenParams, RefreshTokenParams, ClientConfig } from './types';
|
|
11
|
+
import * as client from './client';
|
|
12
|
+
import * as token from './token';
|
|
13
|
+
import * as crypto from './crypto';
|
|
14
|
+
export { client, token, crypto };
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAAE,4BAA4B,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5J,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,KAAK,KAAK,MAAM,SAAS,CAAC;AACjC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAEnC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __returnValue = (v) => v;
|
|
3
|
+
function __exportSetter(name, newValue) {
|
|
4
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
5
|
+
}
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, {
|
|
9
|
+
get: all[name],
|
|
10
|
+
enumerable: true,
|
|
11
|
+
configurable: true,
|
|
12
|
+
set: __exportSetter.bind(all, name)
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// src/client.ts
|
|
17
|
+
var exports_client = {};
|
|
18
|
+
__export(exports_client, {
|
|
19
|
+
call: () => call
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// src/config/http.ts
|
|
23
|
+
var BASE_URL = "https://open.youzanyun.com";
|
|
24
|
+
function getBaseUrl() {
|
|
25
|
+
return BASE_URL;
|
|
26
|
+
}
|
|
27
|
+
function getUrlToken() {
|
|
28
|
+
return "/auth/token";
|
|
29
|
+
}
|
|
30
|
+
function getUrlAPI(api, version, token) {
|
|
31
|
+
return `/api/${api}/${version}?access_token=${token}`;
|
|
32
|
+
}
|
|
33
|
+
function getUrlAPIExempt(api, version) {
|
|
34
|
+
return `/api/auth_exempt/${api}/${version}`;
|
|
35
|
+
}
|
|
36
|
+
function getUrlTextArea(api, version) {
|
|
37
|
+
return `/api/_textarea_/${api}/${version}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/utils/http.ts
|
|
41
|
+
import fs from "fs";
|
|
42
|
+
import axios from "axios";
|
|
43
|
+
import FormData from "form-data";
|
|
44
|
+
var httpClient = axios.create({
|
|
45
|
+
baseURL: getBaseUrl(),
|
|
46
|
+
headers: {
|
|
47
|
+
"User-Agent": "YZY-Open-Client 1.0.0 - Node"
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
async function post(url, params) {
|
|
51
|
+
const resp = await httpClient.post(url, params, {
|
|
52
|
+
headers: { "Content-type": "application/json;charset=UTF-8" }
|
|
53
|
+
});
|
|
54
|
+
return resp;
|
|
55
|
+
}
|
|
56
|
+
async function upload(url, files) {
|
|
57
|
+
const form = new FormData;
|
|
58
|
+
if (files instanceof Map) {
|
|
59
|
+
files.forEach((filePath, key) => {
|
|
60
|
+
form.append(key, fs.createReadStream(filePath));
|
|
61
|
+
});
|
|
62
|
+
} else {
|
|
63
|
+
for (const [key, filePath] of Object.entries(files)) {
|
|
64
|
+
form.append(key, fs.createReadStream(filePath));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const resp = await httpClient.post(url, form, {
|
|
68
|
+
headers: form.getHeaders()
|
|
69
|
+
});
|
|
70
|
+
return resp;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/client.ts
|
|
74
|
+
function hasFiles(files) {
|
|
75
|
+
if (!files)
|
|
76
|
+
return false;
|
|
77
|
+
if (files instanceof Map)
|
|
78
|
+
return files.size > 0;
|
|
79
|
+
return Object.keys(files).length > 0;
|
|
80
|
+
}
|
|
81
|
+
function call(apiParam) {
|
|
82
|
+
if (!apiParam || typeof apiParam !== "object") {
|
|
83
|
+
throw new Error("参数异常: api 必传");
|
|
84
|
+
}
|
|
85
|
+
if (!apiParam.api) {
|
|
86
|
+
throw new Error("参数异常: api 必传");
|
|
87
|
+
}
|
|
88
|
+
if (!apiParam.version) {
|
|
89
|
+
throw new Error("参数异常: version 必传");
|
|
90
|
+
}
|
|
91
|
+
let urlPath;
|
|
92
|
+
if (apiParam.token != null) {
|
|
93
|
+
urlPath = getUrlAPI(apiParam.api, apiParam.version, apiParam.token);
|
|
94
|
+
if (apiParam.config?.isRichText) {
|
|
95
|
+
urlPath = getUrlTextArea(apiParam.api, apiParam.version);
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
urlPath = getUrlAPIExempt(apiParam.api, apiParam.version);
|
|
99
|
+
}
|
|
100
|
+
if (apiParam.host != null) {
|
|
101
|
+
urlPath = apiParam.host + urlPath;
|
|
102
|
+
}
|
|
103
|
+
if (hasFiles(apiParam.files)) {
|
|
104
|
+
return upload(urlPath, apiParam.files);
|
|
105
|
+
}
|
|
106
|
+
return post(urlPath, apiParam.params);
|
|
107
|
+
}
|
|
108
|
+
// src/token.ts
|
|
109
|
+
var exports_token = {};
|
|
110
|
+
__export(exports_token, {
|
|
111
|
+
get: () => get
|
|
112
|
+
});
|
|
113
|
+
var VALID_AUTHORIZE_TYPES = new Set([
|
|
114
|
+
"silent",
|
|
115
|
+
"authorization_code",
|
|
116
|
+
"refresh_token"
|
|
117
|
+
]);
|
|
118
|
+
function get(params) {
|
|
119
|
+
if (!params || typeof params !== "object") {
|
|
120
|
+
throw new Error("参数异常: 参数缺少必要字段");
|
|
121
|
+
}
|
|
122
|
+
if (!params.client_id || !params.client_secret) {
|
|
123
|
+
throw new Error("参数异常: client_id client_secret 必传");
|
|
124
|
+
}
|
|
125
|
+
if (!params.authorize_type || !VALID_AUTHORIZE_TYPES.has(params.authorize_type)) {
|
|
126
|
+
throw new Error("参数异常: authorize_type 类型错误");
|
|
127
|
+
}
|
|
128
|
+
switch (params.authorize_type) {
|
|
129
|
+
case "silent":
|
|
130
|
+
if (!params.grant_id) {
|
|
131
|
+
throw new Error("参数异常: grant_id 必传");
|
|
132
|
+
}
|
|
133
|
+
break;
|
|
134
|
+
case "authorization_code":
|
|
135
|
+
if (!params.code || !params.redirect_uri) {
|
|
136
|
+
throw new Error("参数异常: code redirect_uri 必传");
|
|
137
|
+
}
|
|
138
|
+
break;
|
|
139
|
+
case "refresh_token":
|
|
140
|
+
if (!params.refresh_token) {
|
|
141
|
+
throw new Error("参数异常: refresh_token 必传");
|
|
142
|
+
}
|
|
143
|
+
break;
|
|
144
|
+
default: {
|
|
145
|
+
const _exhaustive = params;
|
|
146
|
+
throw new Error(`参数异常: 未知的 authorize_type`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
let urlPath = getUrlToken();
|
|
150
|
+
if (params.host != null) {
|
|
151
|
+
urlPath = params.host + urlPath;
|
|
152
|
+
}
|
|
153
|
+
return post(urlPath, params);
|
|
154
|
+
}
|
|
155
|
+
// src/crypto.ts
|
|
156
|
+
var exports_crypto = {};
|
|
157
|
+
__export(exports_crypto, {
|
|
158
|
+
decrypt: () => decrypt
|
|
159
|
+
});
|
|
160
|
+
import { createDecipheriv } from "crypto";
|
|
161
|
+
function decrypt(messages, clientSecret) {
|
|
162
|
+
if (!messages || !clientSecret) {
|
|
163
|
+
throw new Error("参数异常: messages clientSecret 不可为空");
|
|
164
|
+
}
|
|
165
|
+
const algorithm = decodeURIComponent(messages);
|
|
166
|
+
const key = clientSecret.substring(0, 16);
|
|
167
|
+
const iv = "0102030405060708";
|
|
168
|
+
const decipher = createDecipheriv("aes-128-cbc", key, iv);
|
|
169
|
+
let dec = decipher.update(algorithm, "base64", "utf-8");
|
|
170
|
+
dec += decipher.final();
|
|
171
|
+
return dec;
|
|
172
|
+
}
|
|
173
|
+
export {
|
|
174
|
+
exports_token as token,
|
|
175
|
+
get,
|
|
176
|
+
decrypt,
|
|
177
|
+
exports_crypto as crypto,
|
|
178
|
+
exports_client as client,
|
|
179
|
+
call
|
|
180
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token 管理
|
|
3
|
+
*/
|
|
4
|
+
import type { TokenParams } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* 获取 Token
|
|
7
|
+
*
|
|
8
|
+
* 必要字段: authorize_type client_id client_secret
|
|
9
|
+
*
|
|
10
|
+
* 自用型应用获取 Token: authorize_type = silent, 必传 grant_id
|
|
11
|
+
* 工具型应用获取 Token: authorize_type = authorization_code, 必传 code redirect_uri
|
|
12
|
+
* 工具型应用/自用型应用刷新 Token: authorize_type = refresh_token, 必传 refresh_token
|
|
13
|
+
*/
|
|
14
|
+
export declare function get(params: TokenParams): Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
15
|
+
//# sourceMappingURL=token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/token.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAU3C;;;;;;;;GAQG;AACH,wBAAgB,GAAG,CAAC,MAAM,EAAE,WAAW,wDA4CtC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth 授权类型
|
|
3
|
+
*/
|
|
4
|
+
export type AuthorizeType = 'silent' | 'authorization_code' | 'refresh_token';
|
|
5
|
+
/** Token 请求公共字段 */
|
|
6
|
+
interface TokenBaseParams {
|
|
7
|
+
client_id: string;
|
|
8
|
+
client_secret: string;
|
|
9
|
+
host?: string;
|
|
10
|
+
}
|
|
11
|
+
/** 自用型应用获取 Token */
|
|
12
|
+
export interface SilentTokenParams extends TokenBaseParams {
|
|
13
|
+
authorize_type: 'silent';
|
|
14
|
+
grant_id: number;
|
|
15
|
+
refresh?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/** 工具型应用获取 Token(授权码模式) */
|
|
18
|
+
export interface AuthorizationCodeTokenParams extends TokenBaseParams {
|
|
19
|
+
authorize_type: 'authorization_code';
|
|
20
|
+
code: string;
|
|
21
|
+
redirect_uri: string;
|
|
22
|
+
}
|
|
23
|
+
/** 刷新 Token */
|
|
24
|
+
export interface RefreshTokenParams extends TokenBaseParams {
|
|
25
|
+
authorize_type: 'refresh_token';
|
|
26
|
+
refresh_token: string;
|
|
27
|
+
}
|
|
28
|
+
/** Token 请求参数联合类型 */
|
|
29
|
+
export type TokenParams = SilentTokenParams | AuthorizationCodeTokenParams | RefreshTokenParams;
|
|
30
|
+
/** API 调用配置 */
|
|
31
|
+
export interface ClientConfig {
|
|
32
|
+
/** 是否使用富文本接口 */
|
|
33
|
+
isRichText?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/** API 调用参数 */
|
|
36
|
+
export interface ApiCallParams {
|
|
37
|
+
/** 接口名称,如 'youzan.trade.get'(必传) */
|
|
38
|
+
api: string;
|
|
39
|
+
/** 接口版本,如 '4.0.0'(必传) */
|
|
40
|
+
version: string;
|
|
41
|
+
/** OAuth access token(免登接口可不传) */
|
|
42
|
+
token?: string;
|
|
43
|
+
/** 请求参数 */
|
|
44
|
+
params?: Record<string, unknown>;
|
|
45
|
+
/** 上传文件:字段名到文件路径的映射 */
|
|
46
|
+
files?: Map<string, string> | Record<string, string>;
|
|
47
|
+
/** 额外配置 */
|
|
48
|
+
config?: ClientConfig;
|
|
49
|
+
/** 自定义主机地址 */
|
|
50
|
+
host?: string;
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,oBAAoB,GAAG,eAAe,CAAC;AAE9E,mBAAmB;AACnB,UAAU,eAAe;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,oBAAoB;AACpB,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,cAAc,EAAE,QAAQ,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,2BAA2B;AAC3B,MAAM,WAAW,4BAA6B,SAAQ,eAAe;IACnE,cAAc,EAAE,oBAAoB,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAe;AACf,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,cAAc,EAAE,eAAe,CAAC;IAChC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qBAAqB;AACrB,MAAM,MAAM,WAAW,GACnB,iBAAiB,GACjB,4BAA4B,GAC5B,kBAAkB,CAAC;AAIvB,eAAe;AACf,MAAM,WAAW,YAAY;IAC3B,gBAAgB;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAe;AACf,MAAM,WAAW,aAAa;IAC5B,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW;IACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,uBAAuB;IACvB,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrD,WAAW;IACX,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,cAAc;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP 请求工具
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 发起 POST 请求
|
|
6
|
+
*
|
|
7
|
+
* @param url 支持绝对路径、相对路径
|
|
8
|
+
* @param params POST 参数
|
|
9
|
+
*/
|
|
10
|
+
export declare function post(url: string, params?: Record<string, unknown>): Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
11
|
+
/**
|
|
12
|
+
* 发起上传文件请求
|
|
13
|
+
*
|
|
14
|
+
* @param url 支持绝对路径、相对路径
|
|
15
|
+
* @param files 上传文件参数,支持 Map 或 Object。示例: {"image": "/path/to/filename.jpg"}
|
|
16
|
+
*/
|
|
17
|
+
export declare function upload(url: string, files: Map<string, string> | Record<string, string>): Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
18
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/utils/http.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,wDAKvE;AAED;;;;;GAKG;AACH,wBAAsB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,wDAiB5F"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@waywake/youzanyun-sdk",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "YouzanYun SDK for Node",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/cjs/index.js",
|
|
7
|
+
"module": "./dist/esm/index.js",
|
|
8
|
+
"types": "./dist/esm/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/esm/index.d.ts",
|
|
13
|
+
"default": "./dist/esm/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/cjs/index.d.ts",
|
|
17
|
+
"default": "./dist/cjs/index.js"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "bun run build:cjs && bun run build:esm",
|
|
26
|
+
"build:cjs": "bun build src/index.ts --outdir dist/cjs --target node --format cjs --external axios --external form-data && tsc -p tsconfig.cjs.json --emitDeclarationOnly && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
|
|
27
|
+
"build:esm": "bun build src/index.ts --outdir dist/esm --target node --format esm --external axios --external form-data && tsc -p tsconfig.esm.json --emitDeclarationOnly",
|
|
28
|
+
"clean": "rm -rf dist",
|
|
29
|
+
"test": "bun test",
|
|
30
|
+
"prepublishOnly": "bun run clean && bun run build"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"youzan",
|
|
34
|
+
"youzanyun",
|
|
35
|
+
"sdk",
|
|
36
|
+
"open"
|
|
37
|
+
],
|
|
38
|
+
"author": "youzan",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"homepage": "https://github.com/waywake/youzan-sdk-ts#readme",
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "https://github.com/waywake/youzan-sdk-ts.git"
|
|
44
|
+
},
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/waywake/youzan-sdk-ts/issues"
|
|
47
|
+
},
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=16.0.0"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"axios": "^1.7.0",
|
|
53
|
+
"form-data": "^4.0.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/bun": "^1.1.0",
|
|
57
|
+
"@types/node": "^20.0.0",
|
|
58
|
+
"typescript": "^5.5.0"
|
|
59
|
+
}
|
|
60
|
+
}
|