import { Provide, Inject, Config, ALL } from '@midwayjs/decorator'; import { Repository } from 'typeorm'; import { InjectEntityModel } from '@midwayjs/typeorm'; import { PaymentChannelEntity } from '../entity/channel'; import axios from 'axios'; import { CustomerEntity } from '../entity/customer'; import qs = require('qs'); import { ILogger } from '@midwayjs/core'; class TokenManager { authUrl = ''; // 认证URL clientId = ''; // 客户端ID clientSecret = ''; // 客户端密钥 refreshToken = null; // 刷新令牌 accessToken = null; // 访问令牌 expiresIn = 0; // 令牌过期时间 constructor(authUrl, clientId, clientSecret) { this.authUrl = authUrl; // 初始化认证URL this.clientId = clientId; // 初始化客户端ID this.clientSecret = clientSecret; // 初始化客户端密钥 this.accessToken = null; // 初始化访问令牌为空 this.refreshToken = null; // 初始化刷新令牌为空 this.expiresIn = 0; // 初始化过期时间为0 } // 登录方法,用于获取访问令牌和刷新令牌 async login() { try { const dataString = qs.stringify({ client_id: this.clientId, // 传递客户端ID client_secret: this.clientSecret, // 传递客户端密钥 grant_type: 'client_credentials', // 假设使用密码授权类型进行初始登录 }); const config = { method: 'post', url: this.authUrl, data: dataString, }; const response = await axios(config); const data = response.data; this.accessToken = data.access_token; // 获取访问令牌 this.refreshToken = data.refresh_token; // 获取刷新令牌 this.expiresIn = Math.floor(Date.now() / 1000) + data.expires_in; // 计算令牌过期时间 console.log('Login successful. Access Token acquired.'); // 登录成功日志 } catch (error) { console.error('Login failed:', error); // 登录失败日志 throw error; // 抛出错误 } } // 获取访问令牌的方法 async getAccessToken() { const currentTime = Math.floor(Date.now() / 1000); // 获取当前时间戳 if (this.accessToken && this.expiresIn > currentTime) { return this.accessToken; // 如果令牌有效,返回访问令牌 } if (!this.refreshToken) { throw new Error('No refresh token available. Please login first.'); // 如果没有刷新令牌,抛出错误 } try { const response = await axios.post(this.authUrl, { client_id: this.clientId, // 传递客户端ID client_secret: this.clientSecret, // 传递客户端密钥 refresh_token: this.refreshToken, // 传递刷新令牌 grant_type: 'refresh_token', // 使用刷新令牌授权类型 }); const data = response.data; this.accessToken = data.access_token; // 更新访问令牌 this.expiresIn = currentTime + data.expires_in; // 更新过期时间 return this.accessToken; // 返回新的访问令牌 } catch (error) { console.error('Error fetching access token:', error); // 获取令牌错误日志 throw error; // 抛出错误 } } } @Provide() export class EasyPayAdapter { @InjectEntityModel(PaymentChannelEntity) channelEntity: Repository; @InjectEntityModel(CustomerEntity) customerEntity: Repository; @Config(ALL) globalConfig; @Inject() ctx; @Inject() logger: ILogger; private config: { apiKey: string; apiSecret: string; apiUrl: string; chainApiKey: string; chainApiSecret: string; chainApiUrl: string; tokenManager: TokenManager; }; baseInfo: { account_id?: string } Init() { this.initConfig() } /** * 初始化渠道配置 */ private async initConfig() { if (!this.config) { const channel = await this.channelEntity.findOne({ where: { code: 'EASYPAY', isEnabled: true }, }); if (!channel) { throw new Error('FusionPay channel not found or disabled'); } const tokenManager = new TokenManager( `${channel.apiUrl}/auth`, channel.apiKey, channel.apiSecret ); await tokenManager.login(); this.config = { apiKey: channel.apiKey, apiSecret: channel.apiSecret, apiUrl: channel.apiUrl, chainApiKey: channel.chainApiKey, chainApiSecret: channel.chainApiSecret, chainApiUrl: channel.chainApiUrl, tokenManager: tokenManager, }; this.baseInfo = channel.config } } /** * 发送请求到 EasyPay API */ async request(method: string, endpoint: string, data?: any) { await this.initConfig(); // return Promise.resolve(`https://api.easypayx.com${endpoint.replace('/api/open', '')}`); let url = this.config.apiUrl; try { url = `${url}${endpoint.replace('/api/open', '')}`; console.log(158, data) const accessToken = await this.config.tokenManager.getAccessToken(); const axiosParams = { method, url, data: method !== 'GET' ? data : undefined, params: method === 'GET' ? data : undefined, headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${accessToken}`, }, }; this.logger.info('向easyPay发送请求', axiosParams); const response = await axios(axiosParams); // 检查响应 // if (response.data.code !== 200) { // console.log(response.data); // throw new Error(`FusionPay API ${response.data.msg}`); // } // console.log('response', response.data); return response.data; } catch (error) { // console.log(error.response.data); if (axios.isAxiosError(error) && error.response) { // console.log(error.response.data); // throw new Error(`FusionPay API Network ${error.response.data.msg}`); this.ctx.status = error.response.status; // 服务器错误 // this.ctx.body = error.response.data; // return this.res.status(500).json({}); this.logger.info('向easyPay发送请求失败了', error.response); return error.response.data; // throw this.ctx.body; } throw error; } } // 获取签名 private async getAuthorization() { await this.initConfig(); const res = await axios.post(`${this.config.apiUrl}/auth`, { client_id: 'client_id', client_secret: this.config.apiSecret, grant_type: 'client_credentials', }); return ''; } }