wangzhibo
2026-07-28 2b662657c5bc5bc45b69f475c7b2edcf8fc92f0c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import { Provide, Inject } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import axios from 'axios';
import { BaseSysParamEntity } from '../../base/entity/sys/param';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
 
interface Ys7TokenData {
  accessToken: string;
  /** 萤石返回的毫秒级过期时间戳 */
  expireTime: number;
}
 
@Provide()
export class Ys7Service extends BaseService {
  @InjectEntityModel(BaseSysParamEntity)
  baseSysParamEntity: Repository<BaseSysParamEntity>;
 
  /** 内存并发锁 */
  private refreshing: Promise<Ys7TokenData> | null = null;
 
  /**
   * 对外暴露:拿 token(自动读缓存 / 续签)
   */
  async getAccessToken() {
    const token = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.accessToken' });
    if (
      !token ||
      !token.updateTime ||
      Date.now() - new Date(token.updateTime).getTime() > 6 * 24 * 60 * 60 * 1000
    ) {
      await this.fetchAndSaveRemote();
    }
  }
 
  /** 真正调萤石 */
  private async fetchAndSaveRemote(): Promise<Ys7TokenData> {
    const appKey_result = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.appKey' });
    const appSecret_result = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.appSecret' });
 
    if (!appKey_result || !appSecret_result) {
      throw new Error(
        '萤石云 appKey/appSecret 未配置,请在【系统参数】中维护 ys7.appKey / ys7.appSecret'
      );
    }
 
    const { data: res } = await axios.post(
      'https://open.ys7.com/api/lapp/token/get',
      new URLSearchParams({ appKey: appKey_result.data, appSecret: appSecret_result.data }),
      {
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        timeout: 8000,
      }
    );
 
    if (String(res.code) !== '200') {
      throw new Error(`萤石云获取 Token 失败:${res.msg}(code: ${res.code})`);
    }
 
    const tokenData: Ys7TokenData = {
      accessToken: res.data.accessToken,
      expireTime: res.data.expireTime,
    };
 
    // 写回系统参数表(Cool-Admin 自带 upsert)
    const token = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.accessToken' });
    this.baseSysParamEntity.save({
      ...token,
      data: tokenData.accessToken,
      updateTime: new Date(),
    }).catch(() => {
      // 忽略写回失败
    }); 
    return tokenData;
  }
}