@jayfong/x-server 2.6.0 → 2.8.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.
@@ -99,6 +99,18 @@ class CacheService {
99
99
  }
100
100
  });
101
101
  }
102
+ /**
103
+ * 获取距离过期时间的毫秒数(未设置过期时间返回-1,键不存在返回-2)。
104
+ *
105
+ * @param key 键
106
+ * @returns 返回距离过期时间的毫秒数
107
+ */
108
+
109
+
110
+ async ttl(key) {
111
+ const redisKey = this.toRedisKey(key);
112
+ return _x.x.redis.pttl(redisKey);
113
+ }
102
114
  /**
103
115
  * 缓存内容。
104
116
  *
@@ -142,6 +142,34 @@ class PayService {
142
142
  return res;
143
143
  }
144
144
 
145
+ async getOrderInfo(payload) {
146
+ // 微信支付
147
+ // https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_2.shtml
148
+ if (payload.channel === 'wepay') {
149
+ const res = await this.wepayRequest(payload.orderNo ? `https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/${payload.orderNo}?mchid=${this.options.wepay.merchantId}` : `https://api.mch.weixin.qq.com/v3/pay/transactions/id/${payload.channelOrderNo}?mchid=${this.options.wepay.merchantId}`);
150
+ return {
151
+ channelOrderNo: res.transaction_id,
152
+ orderNo: res.out_trade_no,
153
+ status: res.trade_state === 'SUCCESS' ? 'success' : 'fail'
154
+ };
155
+ } // 支付宝
156
+ // https://opendocs.alipay.com/open/028woa?scene=common&pathHash=dbf247eb
157
+
158
+
159
+ const res = await this.alipaySdk.exec('alipay.trade.query', {
160
+ biz_content: payload.orderNo ? {
161
+ out_trade_no: payload.orderNo
162
+ } : {
163
+ trade_no: payload.channelOrderNo
164
+ }
165
+ });
166
+ return {
167
+ channelOrderNo: res.trade_no,
168
+ orderNo: res.out_trade_no,
169
+ status: res.trade_status === 'TRADE_SUCCESS' || res.trade_status === 'TRADE_FINISHED' ? 'success' : 'fail'
170
+ };
171
+ }
172
+
145
173
  wepaySign(data) {
146
174
  return _crypto.default.createSign('RSA-SHA256').update(data.map(v => `${v}\n`).join('')).sign(this.options.wepay.privateKey, 'base64');
147
175
  }
@@ -162,9 +190,10 @@ class PayService {
162
190
 
163
191
  async wepayRequest(url, data) {
164
192
  const path = url.replace(/^https?:\/\/[^/]+/, '');
165
- const body = JSON.stringify(data);
193
+ const method = data == null ? 'GET' : 'POST';
194
+ const body = method === 'POST' ? JSON.stringify(data) : '';
166
195
  const params = {
167
- method: 'POST',
196
+ method: method,
168
197
  url: path,
169
198
  time: String(Math.round(Date.now() / 1000)),
170
199
  rand: Math.random().toString().substr(2, 12),
@@ -173,13 +202,19 @@ class PayService {
173
202
  };
174
203
  params.signature = this.wepaySign([params.method, params.url, params.time, params.rand, params.body]);
175
204
  const Authorization = [`WECHATPAY2-SHA256-RSA2048 `, `mchid="${this.options.wepay.merchantId}",`, `nonce_str="${params.rand}",`, `signature="${params.signature}",`, `timestamp="${params.time}",`, `serial_no="${this.options.wepay.certificateSerialNumber}"`].join('');
176
- const res = await _got.default.post(url, {
205
+ const res = method === 'POST' ? await _got.default.post(url, {
177
206
  json: data,
178
207
  headers: {
179
208
  Authorization
180
209
  },
181
210
  responseType: 'json',
182
211
  resolveBodyOnly: true
212
+ }) : await _got.default.get(url, {
213
+ headers: {
214
+ Authorization
215
+ },
216
+ responseType: 'json',
217
+ resolveBodyOnly: true
183
218
  });
184
219
  return res;
185
220
  }
@@ -52,6 +52,13 @@ export declare class CacheService<TData extends Data = Data, TKey extends Key<TD
52
52
  * @returns 返回获取到的缓存内容
53
53
  */
54
54
  getMany<K extends TKeyPath, V extends Value<TData, K>>(...keys: K[]): Promise<Array<V | null>>;
55
+ /**
56
+ * 获取距离过期时间的毫秒数(未设置过期时间返回-1,键不存在返回-2)。
57
+ *
58
+ * @param key 键
59
+ * @returns 返回距离过期时间的毫秒数
60
+ */
61
+ ttl<K extends TKeyPath>(key: K): Promise<number>;
55
62
  /**
56
63
  * 缓存内容。
57
64
  *
@@ -89,6 +89,18 @@ export class CacheService {
89
89
  }
90
90
  });
91
91
  }
92
+ /**
93
+ * 获取距离过期时间的毫秒数(未设置过期时间返回-1,键不存在返回-2)。
94
+ *
95
+ * @param key 键
96
+ * @returns 返回距离过期时间的毫秒数
97
+ */
98
+
99
+
100
+ async ttl(key) {
101
+ const redisKey = this.toRedisKey(key);
102
+ return x.redis.pttl(redisKey);
103
+ }
92
104
  /**
93
105
  * 缓存内容。
94
106
  *
@@ -73,6 +73,37 @@ export interface PayServiceVerifyNotifyDataResult {
73
73
  */
74
74
  channelOrderNo: string;
75
75
  }
76
+ export interface PayServiceGetOrderInfoPayload {
77
+ /**
78
+ * 渠道。
79
+ */
80
+ channel: 'alipay' | 'wepay';
81
+ /**
82
+ * 商家订单号。
83
+ */
84
+ orderNo?: string;
85
+ /**
86
+ * 渠道订单号。
87
+ */
88
+ channelOrderNo?: string;
89
+ }
90
+ export interface PayServiceGetOrderInfoResult {
91
+ /**
92
+ * 商家订单号。
93
+ */
94
+ orderNo: string;
95
+ /**
96
+ * 渠道订单号。
97
+ *
98
+ * - 支付宝最长 `64` 位;
99
+ * - 微信支付最长 `32` 位。
100
+ */
101
+ channelOrderNo: string;
102
+ /**
103
+ * 订单状态。
104
+ */
105
+ status: 'success' | 'fail';
106
+ }
76
107
  export declare class PayService implements BaseService {
77
108
  private options;
78
109
  serviceName: string;
@@ -82,6 +113,7 @@ export declare class PayService implements BaseService {
82
113
  prepareWepay(options: PayServicePrepareWepayOptions): Promise<PayServicePrepareWepayResult>;
83
114
  verifyNotifyData(data: any): false | PayServiceVerifyNotifyDataResult;
84
115
  verifyNotifyDataOrFail(data: any, message?: string): PayServiceVerifyNotifyDataResult;
116
+ getOrderInfo(payload: PayServiceGetOrderInfoPayload): Promise<PayServiceGetOrderInfoResult>;
85
117
  private wepaySign;
86
118
  private wepayDecrypt;
87
119
  private wepayRequest;
@@ -130,6 +130,34 @@ export class PayService {
130
130
  return res;
131
131
  }
132
132
 
133
+ async getOrderInfo(payload) {
134
+ // 微信支付
135
+ // https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_2.shtml
136
+ if (payload.channel === 'wepay') {
137
+ const res = await this.wepayRequest(payload.orderNo ? `https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/${payload.orderNo}?mchid=${this.options.wepay.merchantId}` : `https://api.mch.weixin.qq.com/v3/pay/transactions/id/${payload.channelOrderNo}?mchid=${this.options.wepay.merchantId}`);
138
+ return {
139
+ channelOrderNo: res.transaction_id,
140
+ orderNo: res.out_trade_no,
141
+ status: res.trade_state === 'SUCCESS' ? 'success' : 'fail'
142
+ };
143
+ } // 支付宝
144
+ // https://opendocs.alipay.com/open/028woa?scene=common&pathHash=dbf247eb
145
+
146
+
147
+ const res = await this.alipaySdk.exec('alipay.trade.query', {
148
+ biz_content: payload.orderNo ? {
149
+ out_trade_no: payload.orderNo
150
+ } : {
151
+ trade_no: payload.channelOrderNo
152
+ }
153
+ });
154
+ return {
155
+ channelOrderNo: res.trade_no,
156
+ orderNo: res.out_trade_no,
157
+ status: res.trade_status === 'TRADE_SUCCESS' || res.trade_status === 'TRADE_FINISHED' ? 'success' : 'fail'
158
+ };
159
+ }
160
+
133
161
  wepaySign(data) {
134
162
  return crypto.createSign('RSA-SHA256').update(data.map(v => `${v}\n`).join('')).sign(this.options.wepay.privateKey, 'base64');
135
163
  }
@@ -148,9 +176,10 @@ export class PayService {
148
176
 
149
177
  async wepayRequest(url, data) {
150
178
  const path = url.replace(/^https?:\/\/[^/]+/, '');
151
- const body = JSON.stringify(data);
179
+ const method = data == null ? 'GET' : 'POST';
180
+ const body = method === 'POST' ? JSON.stringify(data) : '';
152
181
  const params = {
153
- method: 'POST',
182
+ method: method,
154
183
  url: path,
155
184
  time: String(Math.round(Date.now() / 1000)),
156
185
  rand: Math.random().toString().substr(2, 12),
@@ -159,13 +188,19 @@ export class PayService {
159
188
  };
160
189
  params.signature = this.wepaySign([params.method, params.url, params.time, params.rand, params.body]);
161
190
  const Authorization = [`WECHATPAY2-SHA256-RSA2048 `, `mchid="${this.options.wepay.merchantId}",`, `nonce_str="${params.rand}",`, `signature="${params.signature}",`, `timestamp="${params.time}",`, `serial_no="${this.options.wepay.certificateSerialNumber}"`].join('');
162
- const res = await got.post(url, {
191
+ const res = method === 'POST' ? await got.post(url, {
163
192
  json: data,
164
193
  headers: {
165
194
  Authorization
166
195
  },
167
196
  responseType: 'json',
168
197
  resolveBodyOnly: true
198
+ }) : await got.get(url, {
199
+ headers: {
200
+ Authorization
201
+ },
202
+ responseType: 'json',
203
+ resolveBodyOnly: true
169
204
  });
170
205
  return res;
171
206
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jayfong/x-server",
3
- "version": "2.6.0",
3
+ "version": "2.8.0",
4
4
  "license": "ISC",
5
5
  "sideEffects": false,
6
6
  "main": "lib/_cjs/index.js",