| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- import APP from '@/services';
- import { getUserId } from '@/services/bus/account';
- import { getErrorInfoByCode } from '@/services/bus/error';
- import { funCode } from '@/services/funcode/index';
- import ProtobufCtr from '@/services/socket/protobuf/index';
- import { Callback } from '@/utils/websocket';
- import { Package50 } from '@/utils/websocket/package';
- import { v4 as uuidv4 } from 'uuid';
- import * as type from './interface';
- import { CommonSearchParam, ParseRsp, SoleSearchParam } from './interface';
- import { IMessageHead } from './proto.d';
- import { getProtoHeadParam, HeadEnum } from './protoHeader';
- /**
- * 构建proto50 报文
- * 具体某个proto查询参数 SoleSearchParam
- * 通用查询查询参数 CommonSearchParam
- * @param param SoleSearchParam | CommonSearchParam
- */
- export function buildProtoReq50(param: SoleSearchParam | CommonSearchParam): Package50 {
- if (Reflect.has(param, 'funCodeName')) {
- return buildSoleProtoReq50(param as SoleSearchParam);
- } else {
- return buildCommonProtoReq50(param as CommonSearchParam);
- }
- }
- /**
- * 解析proto50 报文
- */
- export function parseProtoRsp50(rspPackage: any, funCodeName?: string): ParseRsp {
- if (funCodeName) {
- // 解析funCodeName 相对应的报文
- return parseSoleProtoRsp(rspPackage, funCodeName);
- } else {
- // 解析通用查询报文
- return parseCommonProtoRsp(rspPackage);
- }
- }
- /**
- * 生成 Package50 报文
- * @param funCodeName
- * @param req
- */
- function setPackage50(funCodeName: string, req: any): Package50 {
- const buffer = new Uint8Array(req.toArrayBuffer());
- const reqPackage = new Package50([funCode[funCodeName], buffer], undefined);
- return reqPackage;
- }
- /**
- * 获取proto实例
- * @param protobufName
- */
- function getProtoInstence(protobufName: string) {
- return ProtobufCtr.generateProtoInstence(protobufName);
- }
- /**
- * 构建单独的proto
- * @param protobufName
- * @param reqParams
- */
- function buildSoleProtoReq(protobufName: string, reqParams: type.ReqParams) {
- // 登录报文
- const Req = getProtoInstence(protobufName);
- // 此处处理 一:为了 不需要单独写 构建报文函数,二:是 处理 报文中例如 id 和 ID 各种大写混乱的情况
- const ReqKeys = Object.keys(Req);
- const ReqKeysMap = new Map();
- ReqKeys.forEach((e) => {
- ReqKeysMap.set(e.toLowerCase(), e);
- });
- // 此处需要待优化,proto嵌套的时候存在问题
- const paramKeys = Object.keys(reqParams);
- for (let i = 0; i < paramKeys.length; i++) {
- const item = paramKeys[i];
- const lowerKey = item.toLowerCase();
- if (ReqKeysMap.has(lowerKey)) {
- Req[ReqKeysMap.get(lowerKey)] = reqParams[item];
- } else {
- console.error(`$报文包中不存在 ${item} 属性}`);
- }
- }
- console.log('Req', Req)
- return Req;
- }
- /**
- * 构建消息头部
- * @param funCodeName funCodeName
- * @param params IMessageHead
- */
- function buildMsgHead(funCodeName: string, params: IMessageHead) {
- const code = funCode[funCodeName];
- if (!code) console.error('没有找到对应的funCode值,请配置');
- const messageHead = getProtoInstence('MessageHead');
- const head = {
- FunCode: code,
- UUID: uuidv4(),
- UserID: getUserId(),
- };
- Object.assign(messageHead, head, params);
- return messageHead;
- }
- /**
- * 构建单独的proto请求 Package50 报文
- * @param params SoleSearchParam
- */
- function buildSoleProtoReq50(params: SoleSearchParam): Package50 {
- const { protobufName, funCodeName, reqParams, Header } = params;
- // // // 消息头
- // const messageHead = buildMsgHead(funCodeName, headParam);
- // proto头部参数,站在用户角度,参数数据可以通用获取,但站在管理端的角度,则需要不能通用获取,而是需用选中对应数据中传入进来
- // 登录报文
- const header = typeof Header == 'object' ? buildMsgHead(funCodeName, Header) : getProtoHeadParam(funCodeName, Header);
- const Req = buildSoleProtoReq(protobufName, reqParams);
- Req.Header = header
- return setPackage50(funCodeName, Req);
- }
- /**
- * 构建通用查询 Package50 报文
- * @param param CommonSearchParam
- */
- function buildCommonProtoReq50(param: CommonSearchParam): Package50 {
- const { senNames, statement, params } = param;
- let queryReq = null;
- let funCodeName = '';
- // 加密信息
- if (senNames && senNames.length > 0) {
- queryReq = getProtoInstence('QueryCommonSenReq');
- queryReq.setSenNames(senNames);
- funCodeName = 'QueryCommonSenReq';
- } else {
- queryReq = getProtoInstence('QueryCommonReq');
- funCodeName = 'QueryCommonReq';
- }
- // 消息头
- const messageHead = getProtoHeadParam(funCodeName, 0);
- queryReq.setStatement(statement);
- // 构建查询参数
- const paramValues = [];
- for (const key in params) {
- const value = params[key];
- const Req = getProtoInstence('ParamValue');
- const hasId = (id: string): boolean => key.toLowerCase() === id;
- // 如果有accountid则需加到head中
- if (hasId('accountid') || hasId('buyaccountid') || hasId('sellaccountid')) {
- messageHead.AccountID = value;
- }
- Req.setKey(key);
- Req.setValue(value);
- paramValues.push(Req);
- }
- queryReq.setParamValues(paramValues);
- queryReq.setHeader(messageHead);
- return setPackage50(funCodeName, queryReq);
- }
- function isErrer(rspPackage: any, funCodeName: string): void {
- if (APP.Socket.trade.connState !== 2) {
- console.error(`交易服务未连接!`);
- }
- // 判断回复FunCode是否正确
- if (rspPackage.funCode !== funCode[funCodeName]) {
- console.error(`服务返回【${funCodeName}: ${funCode[funCodeName]}】解析包错误!`);
- }
- // 判断是否有数据体
- if (!rspPackage.content) {
- console.error(`服务未返回数据体!`);
- }
- }
- /**
- * 解析 funCodeName 对应的报文
- * @param rspPackage
- * @param funCodeName
- */
- function parseSoleProtoRsp(rspPackage: any, funCodeName: string): ParseRsp {
- isErrer(rspPackage, funCodeName);
- const reqPackage = ProtobufCtr.generateProtoContent(funCodeName, rspPackage.content);
- const { RetCode, Status, RetDesc } = reqPackage;
- // console.warn(`解析${funCodeName}对应的报文错误:RetCode: ${RetCode}: RetDesc${RetDesc}`)
- if (RetCode !== null) {
- if (RetCode === 0) {
- return { isSuccess: true, result: reqPackage };
- } if (RetCode === -1) { // 管理端错误消息
- return { isSuccess: false, result: RetDesc };
- } else {
- const errMsg = getErrorInfoByCode(String(RetCode));
- const result = errMsg ? errMsg : `未知错误:${RetCode}`;
- return { isSuccess: false, result };
- }
- } else {
- // 银行 业务 以 Status 作为判断依据
- console.log(`Status:${Status}`);
- if (Status === 0) {
- return { isSuccess: true, result: getErrorInfoByCode(Status) };
- } else {
- return { isSuccess: false, result: getErrorInfoByCode(Status) };
- }
- }
- }
- /**
- * 解析通用查询报文
- * @param rspParam
- */
- function parseCommonProtoRsp(rspParam: any): ParseRsp {
- //是否加密
- const funCodeName = rspParam.isSen ? 'QueryCommonSenRsp' : 'QueryCommonRsp';
- const { isSuccess, result } = parseSoleProtoRsp(rspParam, funCodeName);
- if (isSuccess) {
- // 组装数据
- const { FieldInfos, RowValues } = result.Rsps[0];
- // 此处只是简单处理
- const arr = RowValues.map((item: any) => {
- const result: any = {};
- FieldInfos.forEach((el: any, i: number) => {
- const { FieldName, FieldType } = el;
- const dateType = ['date', 'time', 'datetime', 'timestamp'];
- let value = item.RowValues[i];
- if (dateType.includes(lower(FieldType))) {
- // 解决safari时间问题
- value = value.replace(/-/g, '/').replace('.0', '');
- }
- result[lower(FieldName)] = value;
- });
- return result;
- });
- return { isSuccess: true, result: arr };
- } else {
- return { isSuccess, result };
- }
- }
- /**
- * 解析通知
- * @param rspPackage 回应包
- * @param funCodeName funcode 名
- */
- export const noticeParseRsp = (rspPackage: any, funCodeName: string) => {
- isErrer(rspPackage, funCodeName);
- const reqPackage = ProtobufCtr.generateProtoContent(funCodeName, rspPackage.content);
- const { RetCode } = reqPackage;
- let errMsg = getErrorInfoByCode(String(RetCode));
- if (errMsg === '') {
- errMsg = `未知错误:${RetCode}`;
- }
- return errMsg;
- };
- function lower(value: string): string {
- return value.toLowerCase();
- }
- // 枚举 proto hader
- export function protoMiddleware<T>(param: T, reqName: string, rspName: string, headerEnum: HeadEnum): Promise<any>
- // 自定义 protp header
- export function protoMiddleware<T>(param: T, reqName: string, rspName: string, headerEnum: IMessageHead): Promise<any>
- /**
- * @param param proto除去head 剩下参数
- * @param headerEnum 自定义的proto参数枚举值,减小重复抒写 默认0
- * @param reqFuncodeName proto 发送请求定义的头名字,特别需要注意,自已的funCodeName要与这个一致
- * @param rspFuncodeName proto 响应请求定义的头名字
- * @returns
- */
- export function protoMiddleware<T>(param: T, reqName: string, rspName: string, headerEnumOrParam: HeadEnum | IMessageHead = 0): Promise<any> {
- return new Promise((resolve, reject) => {
- const params = {
- protobufName: reqName,
- funCodeName: reqName,
- reqParams: param,
- Header: headerEnumOrParam,
- };
- const package50 = buildProtoReq50(params);
- const code = rspName ? funCode[rspName] : undefined
- APP.sendTradingServer(package50, code, {
- onSuccess: (res) => {
- const { isSuccess, result } = parseProtoRsp50(res, rspName);
- if (isSuccess) {
- resolve(result);
- } else {
- reject(result);
- }
- },
- onFail: (err) => {
- console.log(`proto:${reqName}错误消息:${err}`)
- reject(err.message)
- },
- } as Callback);
- });
- }
|