diff --git a/config/proxy.ts b/config/proxy.ts index 8d4f66d..c15a069 100644 --- a/config/proxy.ts +++ b/config/proxy.ts @@ -11,6 +11,18 @@ const proxy = { proxyRes.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'; proxyRes.headers['Access-Control-Allow-Credentials'] = 'true'; } + }, + '/kaipiao': { + target: 'https://cosmic-sandbox.piaozone.com/xhcamzchwbgonerr/', + changeOrigin: true, + secure: false, + pathRewrite: { '^/kaipiao': '' }, + onProxyRes: function (proxyRes) { + proxyRes.headers['Access-Control-Allow-Origin'] = '*'; + proxyRes.headers['Access-Control-Allow-Methods'] = 'GET,PUT,POST,DELETE,OPTIONS'; + proxyRes.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization, X-Requested-With'; + proxyRes.headers['Access-Control-Allow-Credentials'] = 'true'; + } } } diff --git a/config/router.ts b/config/router.ts index eb01a9e..9ade4d5 100644 --- a/config/router.ts +++ b/config/router.ts @@ -17,6 +17,11 @@ export default [ path: '/DigitalElectronics/index', name: '开票管理', component: "@/pages/DigitalElectronics/index", + }, + { + path: '/InvoiceSearch/index', + name: '开票查询', + component: "@/pages/InvoiceSearch/index", } ] } diff --git a/src/models/user.ts b/src/models/user.ts index 0d30008..2129a90 100644 --- a/src/models/user.ts +++ b/src/models/user.ts @@ -227,6 +227,18 @@ const UserModel: UserModelType = { name: '开票管理', component: "@/pages/Invoicing/index", }, + { + path: '/DigitalElectronics/index', + redirect: '', + name: '开票管理', + component: "@/pages/DigitalElectronics/index", + }, + { + path: '/InvoiceSearch/index', + redirect: '', + name: '开票查询', + component: "@/pages/InvoiceSearch/index", + }, ] } @@ -296,7 +308,9 @@ const UserModel: UserModelType = { authority: [ '/test/index', '/cloudMenu/test/index', - "/Invoicing/index" + "/Invoicing/index", + "/DigitalElectronics/index", + "/InvoiceSearch/index" // '/examine/index', // '/examine/modal', // '/examine/question', diff --git a/src/pages/DigitalElectronics/index.tsx b/src/pages/DigitalElectronics/index.tsx new file mode 100644 index 0000000..e6302b6 --- /dev/null +++ b/src/pages/DigitalElectronics/index.tsx @@ -0,0 +1,483 @@ +// 数电的开票 +import ProTable, { ActionType } from "@ant-design/pro-table"; +import { FormInstance, Button, message, Tag } from "antd"; +import { useRef, useState } from "react"; +import { connect } from "umi"; +import { Datum } from "@/types/invoice"; +import { handleGetAppToken, handleGetKaiPiao, handleGetSDToken } from "./service"; + +interface ConnectState { + user: { + data: any; + }; +} + +const DigitalElectronics: React.FC<{ currentUser: any }> = (props) => { + const actionRef = useRef(); + const formRef = useRef(); + + // 第一个接口的token + const [appToken, setAppToken] = useState() + // 第二个接口的token + const [accessToken, setAccessToken] = useState() + + // 开票处理函数 + const handleInvoice = async (record: Datum) => { + try { + message.loading({ content: '正在发起开票...', key: 'invoice' }); + + // 检查是否有access_token + if (!accessToken) { + message.error({ content: '缺少访问令牌,请先刷新页面重新获取', key: 'invoice' }); + return; + } + + // 构造原始数据 + const originalData = [record]; // 将record作为data数组的一项 + + // 将data字段进行base64加密 + const dataString = JSON.stringify(originalData); + const encryptedData = btoa(unescape(encodeURIComponent(dataString))); // base64编码,支持中文 + + // 构造开票请求数据 + const invoiceData = { + businessSystemCode: "BUSINESS_YCIC", // 来源系统编码 + interfaceCode: "BILL.PUSH", // 接口业务编码 + requestId: Date.now().toString(), // 时间戳作为请求ID + data: encryptedData // 加密后的data字符串 + }; + + console.log('原始数据:', originalData); + console.log('JSON字符串:', dataString); + console.log('Base64加密后:', encryptedData); + console.log('最终请求数据:', invoiceData); + console.log('访问令牌:', accessToken); + + const response = await handleGetKaiPiao(invoiceData, accessToken); + console.log('开票响应:', response); + + if (response && response.code === 200) { + message.success({ content: `单据 ${record.billNo} 开票申请已提交成功`, key: 'invoice' }); + } else { + message.error({ content: `开票申请失败: ${response?.message || '未知错误'}`, key: 'invoice' }); + } + } catch (error) { + console.error('开票错误:', error); + message.error({ content: '开票申请失败,请重试', key: 'invoice' }); + } + }; + + const columns: any = [ + { + title: '单据编号', + dataIndex: 'billNo', + key: 'billNo', + width: 180, + ellipsis: true, + search: true, + hideInSearch: false, + onHeaderCell: () => ({ + style: { textAlign: 'center' } + }), + }, + { + title: '购方名称', + dataIndex: 'buyerName', + key: 'buyerName', + width: 200, + ellipsis: true, + search: false, + hideInSearch: true, + onHeaderCell: () => ({ + style: { textAlign: 'center' } + }), + }, + { + title: '购方税号', + dataIndex: 'buyerTaxpayerId', + key: 'buyerTaxpayerId', + width: 180, + ellipsis: true, + search: false, + hideInSearch: true, + onHeaderCell: () => ({ + style: { textAlign: 'center' } + }), + }, + { + title: '销方名称', + dataIndex: 'sellerName', + key: 'sellerName', + width: 200, + ellipsis: true, + search: false, + hideInSearch: true, + onHeaderCell: () => ({ + style: { textAlign: 'center' } + }), + }, + { + title: '销方税号', + dataIndex: 'sellerTaxpayerId', + key: 'sellerTaxpayerId', + width: 180, + ellipsis: true, + search: true, + hideInSearch: false, + onHeaderCell: () => ({ + style: { textAlign: 'center' } + }), + }, + { + title: '单据日期', + dataIndex: 'billDate', + key: 'billDate', + width: 120, + search: false, + hideInSearch: true, + onHeaderCell: () => ({ + style: { textAlign: 'center' } + }), + }, + { + title: '单据金额', + dataIndex: 'totalAmount', + key: 'totalAmount', + width: 120, + search: false, + hideInSearch: true, + render: (text: number) => text ? `¥${text.toFixed(2)}` : '-', + onHeaderCell: () => ({ + style: { textAlign: 'center' } + }), + }, + { + title: '含税标识', + dataIndex: 'includeTaxFlag', + key: 'includeTaxFlag', + width: 100, + search: false, + hideInSearch: true, + render: (text: string) => ( + + {text === '1' ? '含税' : '不含税'} + + ), + onHeaderCell: () => ({ + style: { textAlign: 'center' } + }), + }, + { + title: '发票性质', + dataIndex: 'invoiceProperty', + key: 'invoiceProperty', + width: 100, + search: true, + hideInSearch: false, + valueType: 'select', + valueEnum: { + '0': { text: '蓝票', status: 'Success' }, + '1': { text: '红票', status: 'Error' }, + }, + render: (text: string) => ( + + {text === '1' ? '红票' : '蓝票'} + + ), + onHeaderCell: () => ({ + style: { textAlign: 'center' } + }), + }, + { + title: '自动开票', + dataIndex: 'autoInvoice', + key: 'autoInvoice', + width: 100, + search: false, + hideInSearch: true, + render: (text: string) => ( + + {text === '1' ? '是' : '否'} + + ), + onHeaderCell: () => ({ + style: { textAlign: 'center' } + }), + }, + { + title: '备注', + dataIndex: 'remark', + key: 'remark', + width: 150, + ellipsis: true, + search: false, + hideInSearch: true, + onHeaderCell: () => ({ + style: { textAlign: 'center' } + }), + }, + { + title: '操作', + key: 'action', + width: 120, + fixed: 'center', + search: false, + hideInSearch: true, + render: (text: any, record: Datum) => ( + + ), + onHeaderCell: () => ({ + style: { textAlign: 'center' } + }), + }, + ] + + return ( +
+ + { + return `${record?.billNo}` + }} + scroll={{ x: "100%", y: 'calc(100vh - 400px)' }} + headerTitle={待开票列表} + search={{ + span: 8, + labelWidth: 100, + searchText: '查询', + resetText: '重置', + collapseRender: false, + collapsed: false + }} + request={async (params: any) => { + let req: any = { + appId: "FPY001", + appSecret: "FPY001fpy@2023***", + accountId: "2280459335882518528", + tenantid: "xhcamzchwbgonerr", + language: "" + } + const token = await handleGetAppToken(req) + console.log('tokentokentoken', token); + + let appToken: any = token.data.app_token + + let tokenReq: any = { + user: "18620126214", + apptoken: appToken, + tenantid: "xhcamzchwbgonerr", + accountId: "2280459335882518528", + usertype: "" + } + + const accessToken: any = await handleGetSDToken(tokenReq) + console.log('accessTokenaccessTokenaccessToken', accessToken); + + setAppToken(appToken) + setAccessToken(accessToken.data.access_token) + + + // 模拟数据 + const mockData: any = [ + { + billNo: "SRM_20250820001", + billDate: "2023-05-17", + totalAmount: 11300, + autoInvoice: "0", + invoiceType: "08xdp", + buyerName: "深圳市顺丰快运有限公司test01", + buyerProperty: "0", + sellerTaxpayerId: "91530112MA7MQ2JR9U", + sellerName: "云南交投集团经营开发有限公司彩云驿商业管理分公司", + sellerBankAndAccount: "13710884704", + sellerAddressAndTel: "高新技术产业园南区科技南十二路58996989", + drawer: "开票人", + billDetail: [ + { + amount: 11300, + detailId: "1194121661989796666", + goodsName: "蜂胶口腔膜", + lineProperty: 2, + price: 11300, + quantity: 1, + revenueCode: "1070304990000000000", + taxRate: "0.13", + units: "个" + } + ] + }, + { + billNo: "SRM_20250820002", + billDate: "2025-08-20", + buyerName: "深圳电子有限公司", + buyerTaxpayerId: "91440300123456789C", + sellerName: "云南交投集团经营开发有限公司彩云驿商业管理分公司", + sellerTaxpayerId: "91530112MA7MQ2JR9U", + totalAmount: 1.13, + includeTaxFlag: "1", + buyerProperty: "0", + sellerBankAndAccount: "", + sellerAddressAndTel: "", + pushMatchRules: "3", + drawer: "", + invoiceProperty: "0", + autoInvoice: "0", + invoiceType: "08xdp", + buyerRecipientPhone: "18158132615", + buyerRecipientMail: "", + remark: "设备采购款", + billDetail: [ + { + amount: 1, + detailId: "1194121661989796666", + goodsName: "蜂胶口腔膜", + lineProperty: 1, + price: 11300, + quantity: 1, + revenueCode: "1070304990000000000", + taxRate: "0.13", + units: "个" + } + ] + }, + { + billNo: "SRM_20250820003", + billDate: "2025-08-19", + buyerName: "杭州互联网有限公司", + buyerTaxpayerId: "91330100123456789E", + sellerName: "云南交投集团经营开发有限公司彩云驿商业管理分公司", + sellerTaxpayerId: "91530112MA7MQ2JR9U", + totalAmount: 1.13, + includeTaxFlag: "1", + buyerProperty: "0", + sellerBankAndAccount: "", + pushMatchRules: "3", + sellerAddressAndTel: "", + drawer: "", + invoiceProperty: "0", + autoInvoice: "1", + invoiceType: "08xdp", + buyerRecipientPhone: "18158132615", + buyerRecipientMail: "", + remark: "技术咨询服务", + billDetail: [ + { + amount: 1, + detailId: "1194121661989796666", + goodsName: "蜂胶口腔膜", + lineProperty: 2, + price: 1, + quantity: 1, + revenueCode: "1070304990000000000", + taxRate: "0.13", + units: "个" + } + ] + }, + { + billNo: "SRM_20250820004", + billDate: "2025-08-18", + buyerName: "成都科技有限公司", + buyerTaxpayerId: "91510100123456789G", + sellerName: "云南交投集团经营开发有限公司彩云驿商业管理分公司", + sellerTaxpayerId: "91530112MA7MQ2JR9U", + totalAmount: 1.13, + includeTaxFlag: "1", + buyerProperty: "0", + sellerBankAndAccount: "", + sellerAddressAndTel: "", + pushMatchRules: "3", + drawer: "", + invoiceProperty: "1", + autoInvoice: "0", + invoiceType: "08xdp", + buyerRecipientPhone: "18158132615", + buyerRecipientMail: "", + remark: "物流服务费红冲", + billDetail: [ + { + amount: 1, + detailId: "1194121661989796666", + goodsName: "蜂胶口腔膜", + lineProperty: 1, + price: 11300, + quantity: 1, + revenueCode: "1070304990000000000", + taxRate: "0.13", + units: "个" + } + ] + }, + { + billNo: "SRM_20250820005", + billDate: "2025-08-17", + buyerName: "西安制造有限公司", + buyerTaxpayerId: "91610100123456789I", + sellerName: "云南交投集团经营开发有限公司彩云驿商业管理分公司", + sellerTaxpayerId: "91530112MA7MQ2JR9U", + totalAmount: 1.13, + includeTaxFlag: "1", + buyerProperty: "0", + sellerBankAndAccount: "", + sellerAddressAndTel: "", + pushMatchRules: "3", + drawer: "", + invoiceProperty: "0", + autoInvoice: "1", + invoiceType: "08xdp", + buyerRecipientPhone: "18158132615", + buyerRecipientMail: "", + remark: "原材料采购", + billDetail: [ + { + amount: 1, + detailId: "1194121661989796666", + goodsName: "蜂胶口腔膜", + lineProperty: 2, + price: 1, + quantity: 1, + revenueCode: "1070304990000000000", + taxRate: "0.13", + units: "个" + } + ] + } + ]; + + return { + data: mockData, + success: true, + total: mockData.length + } + }} + /> +
+ ) +} + + +export default connect(({ user }: ConnectState) => ({ + currentUser: user.data +}))(DigitalElectronics); \ No newline at end of file diff --git a/src/pages/DigitalElectronics/service.ts b/src/pages/DigitalElectronics/service.ts new file mode 100644 index 0000000..c2fa5ce --- /dev/null +++ b/src/pages/DigitalElectronics/service.ts @@ -0,0 +1,44 @@ +import requestKaiPiao from "@/utils/requestKaiPiao" + + +// 获取app_token +export async function handleGetAppToken(params?: any) { + const data = await requestKaiPiao.post('/api/getAppToken.do', params) + return data +} + +// 获取 token +export async function handleGetSDToken(params?: any) { + const data = await requestKaiPiao.post('/api/login.do', params) + return data +} + +// 开票申请 +export async function handleGetKaiPiao(bodyData: any, accessToken: string) { + const data = await requestKaiPiao.post('/kapi/app/sim/openApi', bodyData, { + params: { + access_token: accessToken + }, + headers: { + 'access_token': accessToken + } + }) + return data +} + + + +// 开票申请单发票查询 +export async function handleGetInvoiceSearch(bodyData: any, accessToken: string) { + const data = await requestKaiPiao.post('/kapi/app/sim/openApi', bodyData, { + params: { + access_token: accessToken + }, + headers: { + 'access_token': accessToken + } + }) + return data +} + + diff --git a/src/pages/InvoiceSearch/index.tsx b/src/pages/InvoiceSearch/index.tsx new file mode 100644 index 0000000..90d5dec --- /dev/null +++ b/src/pages/InvoiceSearch/index.tsx @@ -0,0 +1,2 @@ +// 开票查询 + diff --git a/src/pages/Invoicing/DigitalElectronics.tsx b/src/pages/Invoicing/DigitalElectronics.tsx deleted file mode 100644 index 419239b..0000000 --- a/src/pages/Invoicing/DigitalElectronics.tsx +++ /dev/null @@ -1,52 +0,0 @@ -// 数电的开票 -import ProTable, { ActionType } from "@ant-design/pro-table"; -import { FormInstance } from "antd"; -import { useRef } from "react"; -import { connect } from "umi"; - - - -const DigitalElectronics: React.FC<{ currentUser: any }> = (props) => { - const actionRef = useRef(); - const formRef = useRef(); - - const columns: any = [] - - return ( -
- { - return `${record?.id}` - }} - scroll={{ x: "100%", y: 'calc(100vh - 400px)' }} - headerTitle={待开票列表} - search={{ span: 6 }} - request={async (params: any) => { - - if (tableData.list && tableData.list.length > 0) { - return { - data: tableData.list, - success: true, - total: tableData.total, // 总数据条数 - current: tableData.pageNo, // 当前页码 - pageSize: tableData.pageSize, // 每页条数 - } - } - return { data: [], success: true } - }} - /> -
- ) -} - - -export default connect(({ user }: ConnectState) => ({ - currentUser: user.data -}))(DigitalElectronics); \ No newline at end of file diff --git a/src/pages/authority.ts b/src/pages/authority.ts index 88c5f4d..48a8783 100644 --- a/src/pages/authority.ts +++ b/src/pages/authority.ts @@ -1,6 +1,8 @@ const authority: PageAuthority = { '/test/index': ['/test/index'], '/Invoicing/index': ['/Invoicing/index'], + '/DigitalElectronics/index': ['/DigitalElectronics/index'], + '/InvoiceSearch/index': ['/InvoiceSearch/index'], }; diff --git a/src/types/invoice.ts b/src/types/invoice.ts new file mode 100644 index 0000000..b5cbda7 --- /dev/null +++ b/src/types/invoice.ts @@ -0,0 +1,148 @@ +// 开票相关接口定义 +export interface ApifoxModel { + /** + * 来源系统;,对接不同系统来源编码,用于区分不同系统的回调接口;例如SRM系统,你可以传入SRM + */ + businessSystemCode: string; + /** + * 开票请求参数,需要把data的值加密成字符串,默认为base64 + */ + data: Datum[]; + /** + * 接口业务编码,接口业务编码,使用BILL.PUSH + */ + interfaceCode: InterfaceCode; + /** + * 时间戳,请求唯一ID,可使用时间戳或UUID如:1624601109096 + */ + requestId: string; + [property: string]: any; +} + +export interface Datum { + /** + * 数电账号,[系统]数电账号,数电票时可以传入,非数电传入会清空,发票云版本6.0.2可用 + */ + account?: string; + /** + * 申请方,[红字]0:购方申请-发票已抵扣; 1:购方申请-发票未抵扣;2:销方申请; 默认为销方申请【长度:10】 + */ + applicant?: string; + /** + * 自动开票标记,[系统]自动开票,0-否,1-是,默认0 + */ + autoInvoice?: string; + /** + * 自动合并标记,[系统]自动合并 0-否,1-是,自动开票为1时生效 + */ + autoMerge?: string; + /** + * 单据日期,格式:yyyy-MM-dd);如果为空,则默认为当天日期 + */ + billDate?: string; + /** + * 单据明细,单据明细 + */ + billDetail?: BillDetail[]; + /** + * 整单折扣金额,整单折扣金额 + */ + billDiscountAmount?: number; + /** + * 单据编号,参数限制:数字、英文、下划线、-如:Srm_20250518001 + */ + billNo: string; + /** + * 购买方名称,[购方]根据购方名称匹配税号、地址电话、开户行账号(如有),不传且需自动开票时,提示:购方名称为空,请补充,不传且不自动开票时,保存为开票申请单 + */ + buyerName?: string; + /** + * 购方税号,[购方](专票必填) 当购买方性质为企业填写税号,当购方性质为个人填写身份证 + */ + buyerTaxpayerId?: string; + /** + * 含税标识,含税标识,0-不含税,1-含税【长度:1】,默认为0 + */ + includeTaxFlag?: string; + /** + * 发票性质,0:蓝票;1:红票。不填默认蓝票 + */ + invoiceProperty?: string; + /** + * 发票种类,未配置票种管理策略时必填枚举值 + */ + invoiceType?: string; + /** + * 销方名称,[销方]销方名称,销方税号或销方二选一必填,两者都填,以销方税号为准 + */ + sellerName?: string; + /** + * 销方税号,[销方]销方税号。组织编号、销方名称/税号三选一必传 (1)传组织编号,销方信息未传时,根据组织编号找销方信息。 (2)销方税号/销方二选一,两者都填,以销方税号为准。 + */ + sellerTaxpayerId?: string; + /** + * 备注,GBK编码230字节【长度:230】 + */ + remark?: string; + /** + * 单据金额,单据金额,根据含税标记区分,含税标志是不含税时为不含税金额,含税是含税金额,不传使用明细金额累加。 + */ + totalAmount?: number; + [property: string]: any; +} + +export interface BillDetail { + /** + * 明细金额,明细金额,含税标识includeTaxFlag=1时该金额为含税金额 + */ + amount: number; + /** + * 业务系统明细id,业务系统明细id,用于反写回原业务系统明细 【长度:50】 + */ + detailId: string; + /** + * 商品编码,商品编码,与商品名称2填1,需提前在系统维护 + */ + goodsCode?: string; + /** + * 商品名称,商品名称,与商品编码2填1,需提前在系统维护【长度:GBK92字节】 + */ + goodsName?: string; + /** + * 行性质,行性质,1折扣行(折扣行必须紧跟被折扣的正常商品行),2正常商品行 + */ + lineProperty: string; + /** + * 单价,单价【长度:整数位加小数位最大16位,小数位最多13,小数点占1位】,price有值则quantity必填,含税标识includeTaxFlag=1时该金额为含税金额 + */ + price?: string; + /** + * 数量,数量【长度:整数位加小数位最大16位,小数位最多13,小数点占1位】,quantity有值则price必填 + */ + quantity?: string; + /** + * 税收分类编码,税收分类编码,开票项补全或映射会补全税收分类编码,未走开票项补全或映射必填 + */ + revenueCode?: string; + /** + * 规格型号,规格型号,【长度:GBK40字节】 + */ + specification?: string; + /** + * 税额,税额【长度:(14,2)】,可不传,系统自动计算 + */ + taxAmount?: string; + /** + * 税率,税率,【0.13,0.09,0.06等】。不传时根据开票项匹配税率 + */ + taxRate?: string; + /** + * 计量单位,计量单位,【长度:GBK22字节】 + */ + units?: string; + [property: string]: any; +} + +export enum InterfaceCode { + BillPush = "BILL.PUSH", +} \ No newline at end of file diff --git a/src/utils/requestKaiPiao.ts b/src/utils/requestKaiPiao.ts new file mode 100644 index 0000000..294200e --- /dev/null +++ b/src/utils/requestKaiPiao.ts @@ -0,0 +1,162 @@ +import axios from 'axios'; +import { getDvaApp } from 'umi'; +import { notification } from 'antd'; +import type { AxiosRequestHeaders } from 'axios/index'; +import CryptoJS from "crypto-js"; + +const { UMI_APP_BASEURL } = process.env; + +// const instance = axios.create({ baseURL: UMI_APP_BASEURL }); +// const instance = axios.create({ baseURL: 'https://api.eshangtech.com/EShangApiMain' }); + + +// const instance = axios.create({ baseURL: 'http://home.robot-z.cn:7001/' }); +// 修改baseURL为完整的API地址,确保在生产环境中正确访问 +// 从直接访问外部URL +// const instance = axios.create({ baseURL: 'https://cosmic-sandbox.piaozone.com/jdpjykjyxgs' }); + +// 改为使用代理路径 +const instance = axios.create({ baseURL: '/kaipiao' }); + + + +instance.interceptors.request.use( + (config) => { + // 对data数据进行加密 + // if (config.data) { + // config.data = preprocessData(JSON.stringify(config.data)); // 调用预处理函数 + // } + console.log('config', config); + + const isUpload = config.url?.includes("/oss/upload"); + + config.headers = { + ...config.headers, + Authorization: `Bearer ${localStorage.getItem('Authorization') || ''}`, + "Content-Type": isUpload ? "multipart/form-data" : "application/json;charset=utf-8", + } as AxiosRequestHeaders; + + return config; + }, + (error) => Promise.reject(error), +); + +instance.interceptors.response.use( + //状态码为2xx的时候执行 + (response) => { + const { data } = response; + + // if (data.code !== 200) { + // notification.error({ + // message: data.message, + // }); + // } + + const timestamp = getFormattedDate() + + return data + }, + //状态码不是2xx的时候执行 + (error) => { + const { response } = error; + + if (response && response.status === 401) { + // // 清除本地存储的token + // localStorage.removeItem('Authorization'); + // // 重定向到登录页 + // window.location.href = '/user/login'; + // notification.error({ + // message: response?.data?.message || '请求失败', + // description: error.message + // }); + } else { + notification.error({ + message: response?.data?.message || '请求失败', + description: error.message + }); + } + + return Promise.reject({ + code: response?.status || 500, + message: response?.data?.message || '请求失败' + }); + }, +); + + +// 加密 +const encryptAESECB = (data: string, key: string) => { + // const cipher = CryptoJS.createCipheriv('aes-128-ecb', key, null); // ECB 模式不需要 IV + const newKey = CryptoJS.enc.Utf8.parse(key); // 密钥必须是 16 字节 + const cipher = CryptoJS.AES.encrypt(data, newKey, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7 + }); + let encrypted = cipher.ciphertext.toString(CryptoJS.enc.Hex); + // let encrypted = cipher.update(data, 'utf8', 'hex'); + // encrypted += cipher.final('hex'); + return encrypted; +} + +// 解密 +const decryptAESECB = (data: string, key: string) => { + // const decipher = CryptoJS.createDecipheriv('aes-128-ecb', key, null); + // let decrypted = decipher.update(data, 'hex', 'utf8'); + // decrypted += decipher.final('utf8'); + const newKey = CryptoJS.enc.Utf8.parse(key); + + const encryptedData = CryptoJS.enc.Hex.parse(data); + + // 解密操作 + const decrypted = CryptoJS.AES.decrypt({ ciphertext: encryptedData }, newKey, { + mode: CryptoJS.mode.ECB, // ECB 模式 + padding: CryptoJS.pad.Pkcs7 // PKCS7 填充方式 + }); + // 将解密后的结果转为 UTF-8 字符串 + const decryptedText = decrypted.toString(CryptoJS.enc.Utf8); + return decryptedText; +} + +// md5 签名 +const md5 = (key: string, data: string, timestamp: string) => { + const text = "s" + key + data + timestamp; + return CryptoJS.MD5(text).toString(CryptoJS.enc.Hex); +} + +// 生成签名戳 +const getFormattedDate = () => { + const date = new Date(); + const year = date.getFullYear(); // 获取年份 (yyyy) + const month = String(date.getMonth() + 1).padStart(2, '0'); // 获取月份 (MM) + const day = String(date.getDate()).padStart(2, '0'); // 获取日期 (dd) + const hours = String(date.getHours()).padStart(2, '0'); // 获取小时 (HH) + return `es0${year}${month}${day}${hours}0es`; // 拼接成 yyyyMMddHH 格式 +} + +// 加密方法 +const preprocessData = (data: string) => { + console.log('data', data); + // YYYYMMDD + let timestamp = getFormattedDate() + console.log('timestamp', timestamp); + // 秒为单位的时间戳 + let timeSecond = parseInt((new Date().getTime() / 1000).toString()) + console.log('timeSecond', timeSecond); + // 数据的加密 + let encryptionData = encryptAESECB(data, timestamp) + console.log('encryptionData', encryptionData); + // md5签名方法 + let md5Data = md5(timestamp, encryptionData, timestamp) + console.log('md5Data', md5Data); + + let res = { + data: encryptionData, + timestamp: timeSecond, + sign: md5Data + } + console.log('res', res); + + return res +} + +export default instance;