taro-vue2 如何使用国密加解密
return unescape(encodeURIComponent(str)).split("").map(val => val.charCodeAt());
return decodeURIComponent(escape(String.fromCharCode(...strBuffer)));
const sm2 = require('miniprogram-sm-crypto').sm2
const SM4 = require("gm-crypt").sm4;
以下是需要引入的文件
修改crypt.js源码
'use strict'
const base64js = require('base64-js')
class Crypt {
/**
* Converts a JS string to an UTF-8 uint8array.
*
* @static
* @param {String} str 16-bit unicode string.
* @return {Uint8Array} UTF-8 Uint8Array.
* @memberof Crypt
*/
static stringToArrayBufferInUtf8 (str) {
// if not browser env, then require node.js's util. otherwise just use window's
const TextEncoder = (typeof window === 'undefined') ? require('util').TextEncoder : window.TextEncoder
// always utf-8
// let encoder = new TextEncoder()
// return encoder.encode(str)
return unescape(encodeURIComponent(str)).split("").map(val => val.charCodeAt());
}
/**
* Converts an UTF-8 uint8array to a JS string.
*
* @static
* @param {Uint8Array} strBuffer UTF-8 Uint8Array.
* @return {String} 16-bit unicode string.
* @memberof Crypt
*/
static utf8ArrayBufferToString (strBuffer) {
// if not browser env, then require node.js's util. otherwise just use window's
const TextDecoder = (typeof window === 'undefined') ? require('util').TextDecoder : window.TextDecoder
// let decoder = new TextDecoder('utf-8')
// return decoder.decode(strBuffer)
return decodeURIComponent(escape(String.fromCharCode(...strBuffer)));
}
/**
* crypt a utf8 byteArray to base64 string
*
* @static
* @param {Uint8Array} strBuffer UTF-8 Uint8Array.
* @returns {String} base64 str
* @memberof Crypt
*/
static arrayBufferToBase64 (strBuffer) {
return base64js.fromByteArray(strBuffer)
}
/**
* crypt base64 stringa to utf8 byteArray
*
* @static
* @param {String} base64 str
* @returns {Uint8Array} strBuffer UTF-8 Uint8Array.
* @memberof Crypt
*/
static base64ToArrayBuffer (base64) {
return base64js.toByteArray(base64)
}
}
module.exports = Crypt
request.js
import Taro from "@tarojs/taro";
import axios from "taro-axios";
import { commInHandle } from "./cryptography";
import handleReqData from "./handleReqData";
import { BASE_API_URL } from "./config";
import {
// baseURL,
contentType,
requestTimeout,
handleFailCode,
successCode,
noLoading,
enc_algorithm, //0国际密 1国密
} from "./config";
import { removeStore } from "./plugins";
let loading;
// 操作正常Code数组
const codeVerificationArray = [...successCode];
const CODE_MESSAGE = {
200: "服务器成功返回请求数据",
201: "新建或修改数据成功",
202: "一个请求已经进入后台排队(异步任务)",
204: "删除数据成功",
400: "发出信息有误",
401: "用户没有权限(令牌失效、用户名、密码错误、登录过期)",
402: "前端无痛刷新token",
403: "用户得到授权,但是访问是被禁止的",
404: "访问资源不存在",
406: "请求格式不可得",
410: "请求资源被永久删除,且不会被看到",
500: "服务器发生错误",
502: "网关错误",
503: "服务不可用,服务器暂时过载或维护",
504: "网关超时",
};
const handleResponseData = ({ data, config, status, statusText }) => {
// console.log('🚀 ~ handleResponseData ~ data:', data)
Taro.hideLoading();
let code = data.result ? data.result : status;
if (data.result && codeVerificationArray.indexOf(data.result) + 1) code = 200;
switch (code) {
case 200:
// return data.data
if (enc_algorithm == "1") {
if (data.resBody) {
if (handleReqData.verifySign_SM(data)) return data.resBody;
return Taro.showToast({
title: "",
icon: "none",
duration: 3000,
});
} else {
return data.data;
}
} else {
return data.data;
}
}
// 异常处理
const errMsg =
data && data.msg
? data.msg
: CODE_MESSAGE[code]
? CODE_MESSAGE[code]
: statusText;
Taro.showToast({
title: errMsg || "请求异常",
icon: "none",
duration: 3000,
});
const err = new Error(errMsg);
if (code == 999996) {
Taro.setStorageSync("user", "");
Taro.setStorageSync("verifyFlag", "");
Taro.setStorageSync("loginName", "");
Taro.setStorageSync("code", "");
Taro.setStorageSync("openId", "");
Taro.setStorageSync("cardNo", "");
Taro.setStorageSync("certNo", "");
Taro.setStorageSync("name", "");
Taro.reLaunch({
url: "/pages/login/login",
});
}
return Promise.reject(err);
};
// const handleResponseData = ({ data, status, statusText }) => {
// Taro.hideLoading();
// if (data.key1 && data.data) {
// data = commInHandle.dncryptedByDES(
// commInHandle.decryptData(data.key1),
// data.data
// );
// }
// let code = data && data.result ? data.result : status;
// if (code != "900099") {
// if (data && data.result && codeVerificationArray.indexOf(data.result) + 1)
// code = 200;
// // console.log("成功返回参数", data);
// if (code === 200) return data;
// // console.log(code);
// // 异常处理
// const errMsg =
// data && data.msg
// ? data.msg
// : CODE_MESSAGE[code]
// ? CODE_MESSAGE[code]
// : statusText;
// Taro.showToast({
// title: errMsg || "请求异常",
// icon: "none",
// duration: 3000
// });
// const err = new Error(errMsg);
// if (code == 999996) {
// Taro.setStorageSync("user", "");
// Taro.setStorageSync("verifyFlag", "");
// Taro.setStorageSync("loginName", "");
// Taro.setStorageSync("code", "");
// Taro.setStorageSync("openId", "");
// Taro.setStorageSync("cardNo", "");
// Taro.setStorageSync("certNo", "");
// Taro.setStorageSync("name", "");
// Taro.reLaunch({
// url: "/pages/login/login"
// });
// }
// return Promise.reject(err);
// } else {
// return data;
// }
// };
/**
* @description axios初始化
*/
const instance = axios.create({
baseURL: BASE_API_URL,
timeout: requestTimeout,
headers: {
"Content-Type": contentType,
},
});
console.log(BASE_API_URL);
/**
* @description axios请求拦截器
*/
instance.interceptors.request.use(
async (config) => {
let isLoading = noLoading.includes(config.url);
if (!isLoading) {
Taro.showLoading({ title: "加载中" });
}
if (enc_algorithm == "1") {
console.log("sm2");
console.log(config);
const data = await handleReqData._encryptAndSign_SM(config, true);
config.data = data;
} else {
const data = commInHandle.sign(commInHandle.encrypt(config.data));
config.data = data;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
/**
* @description axios响应拦截器
*/
instance.interceptors.response.use(
(response) => handleResponseData(handleReqData.decryptSM4(response)),
(error) => {
const { response } = error;
if (response === undefined) {
Taro.showToast({
title: "网络连接失败",
icon: "none",
duration: 3000,
});
return {};
} else return handleResponseData(handleReqData.decryptSM4(response));
}
);
export default instance;
handleReqData.js
import { isArray, isJson, dateFormat } from "./plugins";
// import JSEncrypt from "jsencrypt";
// import jsrsasign from "jsrsasign";
import CryptoJS from "crypto-js";
// import sha1 from "sha1";
// import md5 from "md5";
import sm4Util from "./sm4Util";
import sm2Util from "./sm2Util";
export default {
data: {
publicKey:
"xxxxxxxxxxxxxxxxxxxxx",
privateKey:
"xxxxxxxxxxxxxxxxxxxxxxxxx",
encryptKeys: [
], // 需要加密的key
salt: "xxxxxxxxxxx",
noSignKeys: [
],
},
/**
* @description SM加密签名
* @param {*} jsonData
* @return {*}
*/
async _encryptAndSign_SM(configData, isEncrypt) {
let jsonData = configData.data;
let data = filterReqBody(jsonData);
//加密
const rand = randomWord(true, 16, 16).toUpperCase();
// const key = sm2Util.encrypt(rand)
const key = sm2Util.encrypt("xxxxxxxxxxxxx");
// const reqHeader = {
// channel: sessionStorage.getItem('channel'), //渠道
// appVerNo: '1.0.0', //版本号
// timeStamp: new Date().getTime(), //时间戳
// ranNum: randomWord(true, 8, 8), //随机值,用于防重放验证,可随机生成
// decKey: key, //用于3DES加密的key,并且要传给接口
// }
// 公共参数
const commParameters = {
channel: "05",
term_sys: 2,
model: "-1",
term_sys_ver: "-1",
root: "1",
key1: "1",
term_id: "0",
app_ver_no: "1.0.0",
// 时间戳:yyyy-MM-dd HH:mm:ss, 需要加上时间矫正值
time: dateFormat(new Date(), "yyyy-MM-dd HH:mm:ss"),
decKey: key, //用于3DES加密的key,并且要传给接口
};
// if (process.env.VUE_APP_FTP_USE_LOCAL_URL == 'true') {
// commParameters.domainUrl = window.location.origin
// }
console.log("data:", data);
if (isEncrypt) {
this.data.encryptKeys.map((item) => {
if (data[item])
// data[item] = sm4Util.encryptHex(data[item].toString(), rand)
data[item] = sm4Util.encryptHex(data[item].toString());
for (let param in commParameters) {
if (item === param) {
commParameters[param] = sm4Util.encryptHex(
commParameters[param].toString()
// rand
);
}
}
});
}
// console.log(data);
// const reqBody = data
//签名
data = { ...commParameters, ...data };
// 去除空值
data = filterReqBody(data);
let signStr = "";
//2021-08-16,pengm,增加安全加密签名开关,配合性能测试使用
if (isEncrypt) {
data = filterNoSignDataType(data);
let keyArr = Object.keys(data).sort();
// keyArr = keyArr.filter((item) => {
// if (!this.data.noSignKeys.includes(item)) {
// return item
// }
// })
// key集合
data["key"] = keyArr.join(",");
keyArr.map((item) => {
signStr += data[item].toString();
});
data["sign"] = sm2Util.getSign(signStr);
// incSign = signStr
}
return data;
},
/**
* @description 解密2.0版本
* @param {*} jsonData
* @return {*}
*/
_decrypt_v2(jsonData) {
const { decryptKeys, privateKey } = this.data;
decryptKeys.forEach((item) => {
if (jsonData[item])
jsonData[item] = decryptByDES(privateKey, jsonData[item].toString());
});
return jsonData;
},
/**
* @description SM验签
* @param {*} jsonData
* @return {*}
*/
verifySign_SM(jsonData) {
const sign = jsonData.incSign;
delete jsonData.resHeader.decKey;
let data = { ...jsonData.resHeader, ...jsonData.resBody };
data = filterReqBody(data);
data = filterNoSignDataType(data);
let keys = Object.keys(data).sort();
let valueStr = "";
keys = keys.filter((item) => {
if (!this.data.noSignKeys.includes(item)) {
return item;
}
});
keys.map((item) => {
valueStr += data[item].toString();
});
// console.log('验签', valueStr)
let isVerify = sm2Util.verifySign(valueStr, sign);
// console.log(isVerify)
return isVerify;
},
/**
* @description SM4解密
* @param {*} key 密钥
* @param {*} message 入参值
* @return {*}
*/
decryptSM4(jsonData) {
if (jsonData.data.result == 0) {
jsonData.data.data = JSON.parse(sm4Util.decryptHex(jsonData.data.data));
console.log(jsonData.config.url + "解密:", jsonData.data.data);
}
return jsonData;
},
encryptByDES(message) {
const crypto_key = CryptoJS.enc.Utf8.parse(
"xxxxxxxxxxxxxx"
);
const crypto_iv = CryptoJS.enc.Utf8.parse("xxxxxx");
const encode_str = CryptoJS.TripleDES.encrypt(message, crypto_key, {
iv: crypto_iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
});
return encode_str.toString();
},
decryptByDES(message) {
const crypto_key = CryptoJS.enc.Utf8.parse(
"xxxxxxxxxxxxxxx"
);
const crypto_iv = CryptoJS.enc.Utf8.parse("xxxxxx");
console.log("🚀 ~ decryptByDES ~ crypto_iv:", crypto_iv);
const decrypt_str = CryptoJS.TripleDES.decrypt(message, crypto_key, {
iv: crypto_iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
});
console.log(
"🚀 ~ decryptByDES ~ decrypt_str:",
message,
">>>>>>",
decrypt_str
);
return decrypt_str.toString(CryptoJS.enc.Utf8);
},
};
/**
* description 过滤空值
* param {*} jsonData
* return {*}
*/
function filterReqBody(jsonData) {
for (let param in jsonData) {
if (!jsonData[param] && typeof jsonData[param] !== "number") {
delete jsonData[param];
}
}
return jsonData;
}
/**
* description 过滤不参与签名的数据类型(array,json)
* param {*} jsonData
* return {*}
*/
function filterNoSignDataType(jsonData) {
for (let param in jsonData) {
if (isArray(jsonData[param]) || isJson(jsonData[param])) {
delete jsonData[param];
}
}
return jsonData;
}
/**
* @description 产生任意长度随机字母数字组合
* @param {*} randomFlag 是否任意长度
* @param {*} min 任意长度最小位[固定位数]
* @param {*} max 任意长度最大位
* @return {*}
*/
function randomWord(randomFlag, min, max) {
let str = "",
range = min,
arr = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
];
if (randomFlag) {
range = Math.round(Math.random() * (max - min)) + min;
}
for (let i = 0; i < range; i++) {
let pos = Math.round(Math.random() * (arr.length - 1));
str += arr[pos];
}
return str;
}
plugins.js
/*
* @Descripttion: 常用js方法 封装
* @version:
* @Author: sang junke
* @Date: 2021-03-25 11:28:41
* @LastEditors: zhouyx
* @LastEditTime: 2022-05-27 15:45:53
*/
/**
* @name: setLocalStore
* @test: test font
* @msg: localStorage 存值
* @param {*} name key
* @param {*} content value
* @return {*}
*/
import Taro from "@tarojs/taro";
export const setLocalStore = (name, content) => {
if (!name) return;
if (typeof content !== "string") {
content = JSON.stringify(content);
}
window.localStorage.setItem(name, content);
};
/**
* @name: getLocalStore
* @test: test font
* @msg: localStorage 取值
* @param {*} name key
* @return {*}
*/
export const getLocalStore = (name) => {
if (!name) return;
return window.localStorage.getItem(name);
};
/**
* @name: removeStore
* @test: test font
* @msg: 删除 localStorage
* @param {*} name key
* @return {*}
*/
export const removeLocalStore = (value) => {
if (!value) return;
if (typeof value == "string") {
window.localStorage.removeItem(value);
} else if (isArray(value)) {
for (var item of value) {
window.localStorage.removeItem(item);
}
}
};
/**
* @name: setSessionStore
* @test: test font
* @msg:sessionStorage 存储
* @param {*} name key
* @param {*} content value
* @return {*}
*/
export const setSessionStore = (name, content) => {
if (!name) return;
if (typeof content !== "string") {
content = JSON.stringify(content);
}
window.sessionStorage.setItem(name, content);
};
/**
* @name: getSessionStore
* @test: test font
* @msg: sessionStorage 取值
* @param {*} name key
* @return {*}
*/
export const getSessionStore = (name) => {
if (!name) return;
return window.sessionStorage.getItem(name);
};
/**
* @name:removeSessionStore
* @test: test font
* @msg:sessionStorage 删除 单个||多个
* @param {*} value
* @return {*}
*/
export const removeSessionStore = (value) => {
if (!value) return;
if (typeof value == "string") {
window.sessionStorage.removeItem(value);
} else if (isArray(value)) {
for (var item of value) {
window.sessionStorage.removeItem(item);
}
}
};
/**
* @name: getUrlString
* @test: test font
* @msg: 获取url 参数
* @param {*} str
* @return {*} value
*/
export const getUrlString = (str) => {
let LocString = String(window.document.location.href);
let rs = new RegExp("(^|)" + str + "=([^&]*)(&|$)", "gi").exec(LocString),
tmp;
if ((tmp = rs)) return decodeURI(tmp[2]);
return null;
};
/**
* @name: desCertNo
* @test: test font
* @msg: 18位身份证号脱敏处理 显示前三后四
* @param {*} str
* @return {*}
*/
export const desCertNo = (str) => {
if (!str) return;
let id = str.substr(0, 3) + "***********" + str.substr(+str.length - 4, 4);
return id;
};
/**
* @name: desmobile
* @test: test font
* @msg: 手机号脱敏处理 前三后四
* @param {*} str
* @return {*}
*/
export const desmobile = (str) => {
let id = str.substr(0, 3) + "****" + str.substr(+str.length - 4, 4);
return id;
};
/**
* @name: getMoney
* @test: test font
* @msg: 处理金额 保留后两位小数 分转元
* @param {*} str
* @return {*}
*/
export const getMoney = (str) => {
if (!str) return;
let money = (Number(str) / 100).toFixed(2);
return money;
};
// 卡号脱敏
export const cardnos = (str) => {
if (!str) return;
let id = "**************" + str.substr(+str.length - 4, 4);
return id;
};
export const desName = (str) => {
if (!str) return;
// console.log(str.substr(1, 1));
let id = "*" + str.substr(1);
return id;
};
/**
* @name: formatTime
* @test: test font
* @msg: 格式化日期函数
* @param {*} timeType yyyy-MM-dd HH:mm:ss || yyyy/MM/dd HH:mm:ss
* @param {*} time Date() 标准时间
* @return {*}
*/
export const formatTime = (
time = new Date(),
timeType = "yyyy-MM-dd HH:mm:ss"
) => {
var t = new Date(time);
var format = timeType;
var tf = function (i) {
return (i < 10 ? "0" : "") + i;
};
return format.replace(/yyyy|MM|dd|HH|mm|ss/g, function (a) {
let str = "";
switch (a) {
case "yyyy":
str = tf(t.getFullYear());
break;
case "MM":
str = tf(t.getMonth() + 1);
break;
case "mm":
str = tf(t.getMinutes());
break;
case "dd":
str = tf(t.getDate());
break;
case "HH":
str = tf(t.getHours());
break;
case "ss":
str = tf(t.getSeconds());
break;
}
return str;
});
};
/**
* @name: mobileValidate
* @test: test font
* @msg: 手机号格式校验
* @param {*} mobile
* @return {*}
*/
export const mobileValidate = (mobile) => {
const newReg =
/^(((13[0-9]{1})|(14[0,1,4,5,6,7,8,9]{1})|(15[0,1,2,3,5,6,7,8,9]{1})|(16[2,5,6,7]{1})|(17[0-8]{1})|(18[0-9]{1})|(19[0,1,2,3,5,6,7,8,9]{1}))+\d{8})$/;
if (!mobile) return false;
if (newReg.test(mobile)) return true;
return false;
};
/**
* @name: emailValidate
* @test: test font
* @msg: 邮箱格式校验
* @param {*} emails
* @return {*}
*/
export const emailValidate = (emails) => {
const newReg = /^\w+@[a-zA-Z0-9]{2,10}(?:\.[a-z]{2,4}){1,3}$/;
if (!emails) return false;
if (newReg.test(emails)) return true;
return false;
};
/**
* @name: nameValidate
* @test: test font
* @msg: 姓名基本检测 特殊符号过滤
* @param {*} name
* @return {*}
*/
export const nameValidate = (name) => {
const newReg = new RegExp(
"[`~!@#%$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()《》——|{}【】‘;:”“'。,、?]"
);
if (!name) return false;
if (newReg.test(name)) return false;
return true;
};
/**
* @name: certNoValidate
* @test: test font
* @msg: 身份证号格式校验
* @param {*} certNo
* @return {*}
*/
export const certNoValidate = (certNo) => {
if (!certNo) return false;
// 加权因子
const weight_factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
// 校验码
const check_code = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"];
let code = certNo + "";
let seventeen = code.substring(0, 17);
// 判断最后一位校验码是否正确
let arr = seventeen.split("");
let len = arr.length;
let num = 0;
for (let i = 0; i < len; i++) {
num = num + arr[i] * weight_factor[i];
}
// 获取余数
let resisue = num % 11;
let last_no = check_code[resisue];
// 格式的正则
// 正则思路
/*
第一位不可能是0
第二位到第六位可以是0-9
第七位到第十位是年份,所以七八位为19或者20
十一位和十二位是月份,这两位是01-12之间的数值
十三位和十四位是日期,是从01-31之间的数值
十五,十六,十七都是数字0-9
十八位可能是数字0-9,也可能是X
*/
const newReg =
/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/;
// 判断格式是否正确
let format = newReg.test(certNo);
// 返回验证结果,校验码和格式同时正确才算是合法的身份证号码
if (last_no && format) return true;
return false;
};
/**
* @name: isArray
* @test: test font
* @msg: 检测是否为数组
* @param {*} arr array
* @return {*} isArray
*/
export const isArray = (arr) => {
if (!Array.isArray) {
Array.isArray = function (arg) {
return Object.prototype.toString.call(arg) === "[object Array]";
};
}
return Array.isArray(arr);
};
export const trim = (str) => {
return str.replace(/(^\s*)|(\s*$)/g, "");
};
/**
* 渠道设备
*/
export const browser = {
versions: (function () {
const u = navigator.userAgent;
return {
ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
android: u.indexOf("Android") > -1 || u.indexOf("Linux") > -1, //android终端或者uc浏览器
};
})(),
};
/**
* Created by Wandergis on 2015/7/8.
* 提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换
*/
//定义一些常量
var x_PI = (3.14159265358979324 * 3000.0) / 180.0;
var PI = 3.1415926535897932384626;
var a = 6378245.0;
var ee = 0.00669342162296594323;
/**
* 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
* 即 百度 转 谷歌、高德
* @param bd_lon
* @param bd_lat
* @returns {*[]}
*/
export function bd09togcj02(bd_lon, bd_lat) {
var x_pi = (3.14159265358979324 * 3000.0) / 180.0;
var x = bd_lon - 0.0065;
var y = bd_lat - 0.006;
var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
var gg_lng = z * Math.cos(theta);
var gg_lat = z * Math.sin(theta);
return [gg_lng, gg_lat];
}
/**
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
* 即谷歌、高德 转 百度
* @param lng
* @param lat
* @returns {*[]}
*/
export function gcj02tobd09(lng, lat) {
var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
var bd_lng = z * Math.cos(theta) + 0.0065;
var bd_lat = z * Math.sin(theta) + 0.006;
return [bd_lng, bd_lat];
}
/**
* WGS84转GCj02
* @param lng
* @param lat
* @returns {*[]}
*/
export function wgs84togcj02(lng, lat) {
if (out_of_china(lng, lat)) {
return [lng, lat];
} else {
var dlat = transformlat(lng - 105.0, lat - 35.0);
var dlng = transformlng(lng - 105.0, lat - 35.0);
var radlat = (lat / 180.0) * PI;
var magic = Math.sin(radlat);
magic = 1 - ee * magic * magic;
var sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI);
dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI);
var mglat = lat + dlat;
var mglng = lng + dlng;
return [mglng, mglat];
}
}
/**
* GCJ02 转换为 WGS84
* @param lng
* @param lat
* @returns {*[]}
*/
export function gcj02towgs84(lng, lat) {
if (out_of_china(lng, lat)) {
return [lng, lat];
} else {
var dlat = transformlat(lng - 105.0, lat - 35.0);
var dlng = transformlng(lng - 105.0, lat - 35.0);
var radlat = (lat / 180.0) * PI;
var magic = Math.sin(radlat);
magic = 1 - ee * magic * magic;
var sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI);
dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI);
var mglat = lat + dlat;
var mglng = lng + dlng;
return [lng * 2 - mglng, lat * 2 - mglat];
}
}
export function transformlat(lng, lat) {
var ret =
-100.0 +
2.0 * lng +
3.0 * lat +
0.2 * lat * lat +
0.1 * lng * lat +
0.2 * Math.sqrt(Math.abs(lng));
ret +=
((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
2.0) /
3.0;
ret +=
((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * 2.0) /
3.0;
ret +=
((160.0 * Math.sin((lat / 12.0) * PI) + 320 * Math.sin((lat * PI) / 30.0)) *
2.0) /
3.0;
return ret;
}
export function transformlng(lng, lat) {
var ret =
300.0 +
lng +
2.0 * lat +
0.1 * lng * lng +
0.1 * lng * lat +
0.1 * Math.sqrt(Math.abs(lng));
ret +=
((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
2.0) /
3.0;
ret +=
((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) /
3.0;
ret +=
((150.0 * Math.sin((lng / 12.0) * PI) +
300.0 * Math.sin((lng / 30.0) * PI)) *
2.0) /
3.0;
return ret;
}
/**
* 判断是否在国内,不在国内则不做偏移
* @param lng
* @param lat
* @returns {boolean}
*/
export function out_of_china(lng, lat) {
return (
lng < 72.004 || lng > 137.8347 || lat < 0.8293 || lat > 55.8271 || false
);
}
// 格式化日期
export const SetFormatTime = (timeType, time = new Date()) => {
var t = new Date(time);
var format = timeType; //timeType =>yyyy-MM-dd HH:mm:ss
var tf = function (i) {
return (i < 10 ? "0" : "") + i;
};
return format.replace(/yyyy|MM|dd|HH|mm|ss/g, function (a) {
switch (a) {
case "yyyy":
return tf(t.getFullYear());
case "MM":
return tf(t.getMonth() + 1);
case "mm":
return tf(t.getMinutes());
case "dd":
return tf(t.getDate());
case "HH":
return tf(t.getHours());
case "ss":
return tf(t.getSeconds());
}
});
};
// 生成用户相关的唯一标识
export const generateUUID = async () => {
const user = Taro.getStorageSync("user");
const systemInfo = await Taro.getSystemInfoSync();
const deviceInfoStr =
(user.userId || "") +
"_" +
systemInfo.model +
"_" +
systemInfo.version +
"_" +
systemInfo.windowWidth +
"_" +
systemInfo.windowHeight;
console.log("generateUUID == ", deviceInfoStr);
const md5Hash = CryptoJS.MD5(deviceInfoStr).toString();
return md5Hash;
};
// Date格式化
export const dateFormat = (
date = new Date(),
format = "yyyy-MM-dd HH:mm:ss"
) => {
// 转成
if (!date) return "";
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const hour = date.getHours();
const minute = date.getMinutes();
const seconds = date.getSeconds();
return format
.replace("yyyy", year)
.replace("MM", month < 10 ? "0" + month : month)
.replace("dd", day < 10 ? "0" + day : day)
.replace("HH", hour < 10 ? "0" + hour : hour)
.replace("mm", minute < 10 ? "0" + minute : minute)
.replace("ss", seconds < 10 ? "0" + seconds : seconds);
};
/**
* @description: 判断是否Json
* @param {*} value
* @return {*}
*/
export const isJson = (value) => {
if (value && typeof value === "object") return true;
return false;
};
/**
* 16进制字符转为Base64字符串
* @param {*} str
* @returns
*/
export function hexToBase64(str) {
// 将16进制字符串两个字符一组转换为ASCII码字符,然后转为Base64字符串
// return btoa(
// String.fromCharCode.apply(
// null,
// str.match(/.{2}/g).map((hexPair) => parseInt(hexPair, 16))
// )
// );
// // 将16进制字符串转换为Buffer对象
const buffer = Buffer.from(str, 'hex');
// 将Buffer对象转换为Base64字符串
const base64String = buffer.toString('base64');
return base64String
// const uint8Array = new Uint8Array(
// str.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))
// );
// return Taro.arrayBufferToBase64(uint8Array);
}
/**
* Base64字符串16进制字符
* @param {*} str
* @returns
*/
export function base64ToHex(str) {
return Buffer.from(str, "base64").toString("hex");
}
sm2Util.js
const sm2 = require('miniprogram-sm-crypto').sm2
const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为1
// 后端会生成密钥对(16进制字符串)
// publicKey:公钥 后端提供
// privateKey:私钥 后端提供
const privateKey = xxxxxxxxxxxx
const publicKey =xxxxxxxxxxxxxxx
const gatewayPrivateKey =xxxxxxxxxxxx
export default {
// 加密
// value:需要加密的内容
encrypt(value) {
// 给后端传值时需要在加密的密文前面加04 ,这样后端才能解密正确不报错
return sm2.doEncrypt(value, publicKey, cipherMode)
},
// 解密
// value:需要解密的密文
decrypt(value) {
// 后端传输过来的密文开头的两个字符通常也为04,因此解密时需要删除
return sm2.doDecrypt(value, privateKey, cipherMode)
},
//签名
getSign(text) {
return sm2.doSignature(text, privateKey, {
hash: true,
der: true,
})
// return hexToBase64(
// sm2.doSignature(text, privateKey, {
// hash: true,
// der: true,
// })
// )
},
//验签
verifySign(text, sign) {
return sm2.doVerifySignature(text, sign, publicKey, {
hash: true,
der: true,
})
// return sm2.doVerifySignature(text, base64ToHex(sign), publicKey, {
// hash: true,
// der: true,
// })
},
//网关签名
gatewaySign(text) {
return sm2.doSignature(text, gatewayPrivateKey, {
hash: true,
der: true,
})
// return hexToBase64(
// sm2.doSignature(text, privateKey, {
// hash: true,
// der: true,
// })
// )
},
}
sm4Util.js
import { hexToBase64, base64ToHex } from "./plugins";
// const SM4 = require("gm-crypt").sm4;
// const SM4 = require("miniprogram-sm-crypto").sm4;
const SM4 = require("./gm-crypt").sm4
console.log("15 line -> SM4:", SM4);
const pwdKey = "xxxxxxxxx"; //密钥 前后端一致,后端提供
console.log(pwdKey);
//密钥 前后端一致,后端提供
let sm4Config = {
key: pwdKey,
mode: "ecb", // 加密的方式有两种,ecb和cbc两种,看后端如何定义的,cbc需要iv参数,ecb不用
// mode: CryptoJS.mode.ECB, // 加密的方式有两种,ecb和cbc两种,看后端如何定义的,cbc需要iv参数,ecb不用
iv: "xxxxxxxxxxxxxxxxx", // 初始向量,cbc模式的第二个参数,也需要跟后端配置的一致
cipherType: "base64",
// padding: "PKCS7",
// padding: CryptoJS.pad.Pkcs7,
};
const sm4Util = new SM4(sm4Config);
export default {
/*
* 加密工具函数 返回base64字符串
* @param {String} text 待加密文本
*/
encryptBase64(text, key) {
if (key) {
sm4Config.key = key;
}
const sm4Util = new SM4(sm4Config);
return sm4Util.encrypt(text, pwdKey);
},
/*
* 解密工具函数
* @param {String} text 待解密密文 base64字符串
*/
decryptBase64(text, key) {
if (key) {
sm4Config.key = key;
}
const sm4Util = new SM4(sm4Config);
return sm4Util.decrypt(text, pwdKey);
},
/*
* 加密工具函数 返回16进制字符串
* @param {String} text 待加密文本
*/
encryptHex(text, key) {
if (key) {
sm4Config.key = key;
}
const sm4Util = new SM4(sm4Config);
return base64ToHex(sm4Util.encrypt(text, pwdKey));
},
/*
* 解密工具函数
* @param {String} text 待解密密文 16进制字符串
*/
decryptHex(hexStr, key) {
if (key) {
sm4Config.key = key;
}
const sm4Util = new SM4(sm4Config);
return sm4Util.decrypt(hexToBase64(hexStr), pwdKey);
},
};