utils.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. import { Inject, Provide } from '@midwayjs/decorator';
  2. import { Context } from '@midwayjs/koa';
  3. import * as ipdb from 'ipip-ipdb';
  4. import * as _ from 'lodash';
  5. import * as moment from 'moment';
  6. import * as NodeRSA from 'node-rsa';
  7. import * as crypto from 'crypto'
  8. import * as speakeasy from 'speakeasy';
  9. import { BinaryToTextEncoding } from 'crypto';
  10. /**
  11. * 帮助类
  12. */
  13. @Provide()
  14. export class Utils {
  15. @Inject()
  16. baseDir;
  17. /**
  18. * 获得请求IP
  19. */
  20. async getReqIP(ctx: Context) {
  21. const req = ctx.req;
  22. return (
  23. req.headers['x-forwarded-for'] ||
  24. req.socket.remoteAddress.replace('::ffff:', '')
  25. );
  26. }
  27. /**
  28. * 根据IP获得请求地址
  29. * @param ip 为空时则为当前请求的IP地址
  30. */
  31. async getIpAddr(ctx: Context, ip?: string | string[]) {
  32. try {
  33. if (!ip) {
  34. ip = await this.getReqIP(ctx);
  35. }
  36. const bst = new ipdb.BaseStation(`${this.baseDir}/comm/ipipfree.ipdb`);
  37. const result = bst.findInfo(ip, 'CN');
  38. const addArr: any = [];
  39. if (result) {
  40. addArr.push(result.countryName);
  41. addArr.push(result.regionName);
  42. addArr.push(result.cityName);
  43. return _.uniq(addArr).join('');
  44. }
  45. } catch (err) {
  46. return '无法获取地址信息';
  47. }
  48. }
  49. /**
  50. * 去除对象的空值属性
  51. * @param obj
  52. */
  53. async removeEmptyP(obj) {
  54. Object.keys(obj).forEach(key => {
  55. if (obj[key] === null || obj[key] === '' || obj[key] === 'undefined') {
  56. delete obj[key];
  57. }
  58. });
  59. }
  60. /**
  61. * 线程阻塞毫秒数
  62. * @param ms
  63. */
  64. sleep(ms) {
  65. return new Promise(resolve => setTimeout(resolve, ms));
  66. }
  67. /**
  68. * 获得最近几天的日期集合
  69. * @param recently
  70. */
  71. getRecentlyDates(recently, format = 'YYYY-MM-DD') {
  72. moment.locale('zh-cn');
  73. const dates = [];
  74. for (let i = 0; i < recently; i++) {
  75. dates.push(moment().subtract(i, 'days').format(format));
  76. }
  77. return dates.reverse();
  78. }
  79. /**
  80. * 获得最近几个月的月数
  81. * @param recently
  82. */
  83. getRecentlyMonths(recently, format = 'YYYY-MM') {
  84. moment.locale('zh-cn');
  85. const dates = [];
  86. const date = moment(Date.now()).format('YYYY-MM');
  87. for (let i = 0; i < recently; i++) {
  88. dates.push(moment(date).subtract(i, 'months').format(format));
  89. }
  90. return dates.reverse();
  91. }
  92. /**
  93. * 根据开始和结束时间,获得时间段内的日期集合
  94. * @param start
  95. * @param end
  96. */
  97. getBetweenDays(start, end, format = 'YYYY-MM-DD') {
  98. moment.locale('zh-cn');
  99. const dates = [];
  100. const startTime = moment(start).format(format);
  101. const endTime = moment(end).format(format);
  102. const days = moment(endTime).diff(moment(startTime), 'days');
  103. for (let i = 0; i <= days; i++) {
  104. dates.push(moment(startTime).add(i, 'days').format(format));
  105. }
  106. return dates;
  107. }
  108. /**
  109. * 根据开始和结束时间,获得时间段内的月份集合
  110. * @param start
  111. * @param end
  112. */
  113. getBetweenMonths(start, end, format = 'YYYY-MM') {
  114. moment.locale('zh-cn');
  115. const dates = [];
  116. const startTime = moment(start).format(format);
  117. const endTime = moment(end).format(format);
  118. const months = moment(endTime).diff(moment(startTime), 'months');
  119. for (let i = 0; i <= months; i++) {
  120. dates.push(moment(startTime).add(i, 'months').format(format));
  121. }
  122. return dates;
  123. }
  124. /**
  125. * 根据开始和结束时间,获得时间段内的小时集合
  126. * @param start
  127. * @param end
  128. */
  129. getBetweenHours(start, end, format = 'YYYY-MM-DD HH') {
  130. moment.locale('zh-cn');
  131. const dates = [];
  132. const startTime = moment(start).format(format);
  133. const endTime = moment(end).format(format);
  134. const hours = moment(endTime).diff(moment(startTime), 'hours');
  135. for (let i = 0; i <= hours; i++) {
  136. dates.push(moment(startTime).add(i, 'hours').format(format));
  137. }
  138. return dates;
  139. }
  140. /**
  141. * 字段转驼峰法
  142. * @param obj
  143. * @returns
  144. */
  145. toCamelCase(obj) {
  146. let camelCaseObject = {};
  147. for (let i in obj) {
  148. let camelCase = i.replace(/([-_][a-z])/gi, $1 => {
  149. return $1.toUpperCase().replace('-', '').replace('_', '');
  150. });
  151. camelCaseObject[camelCase] = obj[i];
  152. }
  153. return camelCaseObject;
  154. }
  155. createOrderNo(prefix) {
  156. return (
  157. prefix +
  158. moment().format('YYYYMMDDHHmmss') +
  159. _.sampleSize([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 4).join('')
  160. );
  161. }
  162. signSort(args) {
  163. let keys = Object.keys(args);
  164. keys = keys.sort();
  165. let newArgs = {};
  166. keys.forEach(key => {
  167. newArgs[key] = args[key];
  168. });
  169. let string = '';
  170. for (let k in newArgs) {
  171. string += '&' + k + '=' + newArgs[k];
  172. }
  173. string = string.substr(1);
  174. return string;
  175. }
  176. isMerchant(roleIds) {
  177. return roleIds.findIndex(item => +item === 2) > -1;
  178. }
  179. isAgent(roleIds) {
  180. return roleIds.findIndex(item => +item === 4) > -1;
  181. }
  182. stringToHex(str) {
  183. let hex = '';
  184. for (let i = 0; i < str.length; i++) {
  185. hex += str.charCodeAt(i).toString(16);
  186. }
  187. return hex;
  188. }
  189. hexToString(hexString) {
  190. // 移除前缀0x,如果有的话
  191. if (hexString.startsWith('0x')) {
  192. hexString = hexString.slice(2);
  193. }
  194. // 将16进制字符串转换为Buffer
  195. const buffer = Buffer.from(hexString, 'hex');
  196. // 将Buffer转换为字符串
  197. return buffer.toString('utf8');
  198. }
  199. signByMD5WithRSA(data, privateKey) {
  200. const hmac = crypto.createSign('md5WithRSAEncryption');
  201. // 更新hash对象与传入的数据
  202. hmac.update(data);
  203. // 生成哈希值
  204. return hmac.sign(privateKey, 'base64');
  205. }
  206. verifyByMD5WithRSA(data, sign, publicKey) {
  207. const key = new NodeRSA(publicKey);
  208. key.setOptions({ signingScheme: 'pkcs1-sha256' });
  209. return key.verify(data, sign);
  210. }
  211. signBySha256(data, secretKey, format: BinaryToTextEncoding = 'hex') {
  212. const hmac = crypto.createHmac('sha256', secretKey);
  213. // 更新hash对象与传入的数据
  214. hmac.update(data);
  215. // 生成哈希值
  216. return hmac.digest(format);
  217. }
  218. signByHmacSha1(data, secretKey) {
  219. const hmac = crypto.createHmac('sha1', secretKey);
  220. // 更新hash对象与传入的数据
  221. hmac.update(data);
  222. // 生成哈希值
  223. return hmac.digest('base64');
  224. }
  225. getGoogleSecret() {
  226. return speakeasy.generateSecret({ length: 20 })
  227. }
  228. validGoogleSecret(secret, code) {
  229. return speakeasy.totp.verify({
  230. secret: secret,
  231. encoding: 'base32',
  232. token: code,
  233. algorithm: 'sha1'
  234. })
  235. }
  236. }