Browse Source

执法端手机调起摄像头提交

dev-v1.0.3
蟑螂恶霸 4 months ago
parent
commit
fa923801a0
  1. 71
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnfLoginController.java
  2. 3
      zdxt-web-client/zdxt-efcode-enforcement-app/src/api/enforcement/index.js
  3. 91
      zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/scanEntQRCode.vue

71
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnfLoginController.java

@ -1,20 +1,26 @@
package com.zdxt.enforcementcode.controller.app.enforcement; package com.zdxt.enforcementcode.controller.app.enforcement;
import cn.dev33.satoken.annotation.SaIgnore; import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson.JSONObject;
import com.zdxt.enforcementcode.common.commonenum.PlatformTypeEnums; import com.zdxt.enforcementcode.common.commonenum.PlatformTypeEnums;
import com.zdxt.enforcementcode.common.util.CommonUtil; import com.zdxt.enforcementcode.common.util.CommonUtil;
import com.zdxt.enforcementcode.controller.app.utils.HttpUtil;
import com.zdxt.enforcementcode.service.enforcement.IAppEnfLoginService; import com.zdxt.enforcementcode.service.enforcement.IAppEnfLoginService;
import com.zdxt.enforcementcode.controller.app.LoginController; import com.zdxt.enforcementcode.controller.app.LoginController;
import com.zdxt.enforcementcode.domain.vo.SrzDeptVo; import com.zdxt.enforcementcode.domain.vo.SrzDeptVo;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.system.domain.vo.SysDeptVo; import org.dromara.system.domain.vo.SysDeptVo;
import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISysDeptService; import org.dromara.system.service.ISysDeptService;
import org.dromara.system.service.ISysUserService; import org.dromara.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -31,6 +37,15 @@ public class AppEnfLoginController extends LoginController {
private final ISysDeptService sysDeptService; private final ISysDeptService sysDeptService;
private final IAppEnfLoginService appEnfLoginService; private final IAppEnfLoginService appEnfLoginService;
@Value("${szypt.corpid}")
private String szyptCorpid;
@Value("${szypt.agentid}")
private String szyptAgentid;
@Value("${szypt.corpsecret}")
private String szyptCorpsecret;
@Value("${szypt.url}")
private String szyptUrl;
/** /**
* 执法端用户登录 * 执法端用户登录
* *
@ -141,4 +156,60 @@ public class AppEnfLoginController extends LoginController {
String code = params.get("code"); String code = params.get("code");
return appEnfLoginService.szyptLogin(code); return appEnfLoginService.szyptLogin(code);
} }
/**
* 深圳易平台使用权限签名算法
*/
@GetMapping("/szyptGetToken")
@ResponseBody
public R<Map<String, Object>> szyptGetToken(@RequestParam("code") String code, @RequestParam("url") String url){
try {
System.out.println("====================== 获取政务微信认证签名URL ======================");
log.info("获取政务微信认证签名code:{}",code);
log.info("获取政务微信认证签名URL:{}",url);
// 获取 access_token
String accessTokenJson = HttpUtil.HttpSendGet(szyptUrl + "/cgi-bin/gettoken?corpid="+szyptCorpid+"&corpsecret="+szyptCorpsecret, null);
JSONObject tokenObj = JSONObject.parseObject(accessTokenJson);
String token = tokenObj.getString("access_token");
String jsapiTicket = HttpUtil.HttpSendGet(szyptUrl + "/cgi-bin/get_jsapi_ticket?access_token="+token, null);
JSONObject ticketObj = JSONObject.parseObject(jsapiTicket);
String ticket = ticketObj.getString("ticket");
log.info("====================== jsapiTicket start ======================");
log.info("ticket: {}",ticket);
log.info("====================== jsapiTicket end ======================");
long timestamp = System.currentTimeMillis() / 1000;
//随机字符串
String nonceStr = "Wm3WZYTPz0wzccnW";
String signature = getSignature(ticket, nonceStr, timestamp, url);
log.info("signature: {}",signature);
Map<String, Object> data = new HashMap<>();
data.put("agentid", szyptAgentid);
data.put("corpid", szyptCorpid);
data.put("timestamp", timestamp);
data.put("nonceStr", nonceStr);
data.put("signature", signature);
return R.ok(data);
} catch (Exception e) {
log.error(e.getMessage());
e.printStackTrace();
}
return R.ok();
}
private String getSignature(String ticket, String nonceStr, long timestamp, String url) {
try {
String unEncryptStr = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url;
MessageDigest sha = MessageDigest.getInstance("SHA");
// 调用digest方法,进行加密操作
byte[] cipherBytes = sha.digest(unEncryptStr.getBytes());
String encryptStr = Hex.encodeHexString(cipherBytes);
return encryptStr;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
} }

3
zdxt-web-client/zdxt-efcode-enforcement-app/src/api/enforcement/index.js

@ -6,6 +6,9 @@ const baseUrl = "/app-enf";
export const enforcementLogin = (params, success, error) => _post(baseUrl + "/login/szyptLogin", params, success, error); export const enforcementLogin = (params, success, error) => _post(baseUrl + "/login/szyptLogin", params, success, error);
export const enforcementLoginByPassword = (params, success, error) => _post(baseUrl + "/login/do", params, success, error); export const enforcementLoginByPassword = (params, success, error) => _post(baseUrl + "/login/do", params, success, error);
// 深圳易平台
export const szyptGetToken = (params, success, error) => _get(baseUrl + "/login/szyptGetToken",params,success,error);
// endregion // endregion
// region 企业模块 // region 企业模块

91
zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/scanEntQRCode.vue

@ -95,7 +95,7 @@ import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue';
import { useRouter, useRoute } from 'vue-router'; import { useRouter, useRoute } from 'vue-router';
import { showFailToast, showSuccessToast, showToast, showConfirmDialog } from 'vant'; import { showFailToast, showSuccessToast, showToast, showConfirmDialog } from 'vant';
import { baseUrl, appEnv } from '@/config/env.js'; import { baseUrl, appEnv } from '@/config/env.js';
import { getEntInfoByQRCode, queryEnterpriseListAndQrInfo } from '@/api/enforcement/index'; import { getEntInfoByQRCode, queryEnterpriseListAndQrInfo, szyptGetToken } from '@/api/enforcement/index';
import wx from 'weixin-js-sdk'; import wx from 'weixin-js-sdk';
const router = useRouter(); const router = useRouter();
@ -209,53 +209,60 @@ const onFileSelected = async (event) => {
// ---------- prod 环境:wx.scanQRCode ---------- // ---------- prod 环境:wx.scanQRCode ----------
const openWxScan = () => { const openWxScan = () => {
// TODO: 对接实际微信 JSSDK token 接口后启用 let fullUrl = window.location.href;
// 当前仅预留调用骨架,需配合服务端 szyptGetToken 接口获取签名 let code = fullUrl.substring(fullUrl.indexOf('code=') + 5, fullUrl.indexOf('&state='));
const fullUrl = window.location.href; let paramUrl = window.location.href.split("#")[0];
const paramUrl = fullUrl.split('#')[0]; let param = {code: code, url: paramUrl};
showToast('正在调起微信扫码...'); szyptGetToken(param, success => {
// 以下为 wx.config + wx.scanQRCode 的标准流程 let resMsg = success.data;
// 实际使用时需先调用服务端接口获取 config 参数 console.log(resMsg);
szyptGetToken({ url: paramUrl }, (res) => { wx.config({
const data = res.data; // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
wx.config({ debug: false,
debug: false, // 必填,公众号的唯一标识
appId: data.corpid, appId: resMsg.corpid,
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, timestamp: resMsg.timestamp,
signature: data.signature, // 必填,生成签名的随机串
jsApiList: ['scanQRCode'], nonceStr: resMsg.nonceStr,
}); // 必填,签名,见附录1
wx.ready(() => { signature: resMsg.signature,
wxClickScan(); // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
}); jsApiList: ["scanQRCode"],
wx.error((err) => { });
console.error('wx.config 失败', err); wx.ready(() => {
showFailToast('微信配置失败,请重试'); //微信扫一扫请求操作
ClickScan()
});
wx.error((res) => {
console.log("获取失败", res);
});
}, error => {
}); });
});
// 开发阶段直接尝试调用(在微信浏览器内有效)
wxClickScan();
}; };
const wxClickScan = () => { const ClickScan = () => {
wx.scanQRCode({ wx.scanQRCode({
needResult: 1, needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
scanType: ['qrCode', 'barCode'], scanType: ['qrCode', 'barCode'], // 可以指定扫二维码还是一维码,默认二者都有
success: (res) => { success: (res) => {
console.log('wx 扫码返回:', res); // 页面跳转
handleScanResult(res.resultStr); console.log("=========== 扫码返回 ===========")
console.log(res)
if(isHttpLink(res.resultStr)){
handleScanResult(res.resultStr);
}else{
showFailToast("该二维码不正确");
}
}, },
error: (res) => { error: function(res) {
console.error('wx 扫码错误:', res); console.log("错误回调",res)
if (res.errMsg && res.errMsg.indexOf('function_not_exist') > 0) { if (res.errMsg.indexOf('function_not_exist') > 0) {
showFailToast('版本过低请升级'); showFailToast('版本过低请升级')
} }
}, },
cancel: () => { cancel: (res) => {
console.log('用户取消扫码'); console.log('err', res);
}, },
}); });
}; };
@ -279,7 +286,7 @@ const handleScanResult = (resultStr) => {
// 将企业信息存入 sessionStorage,预览页直接使用,无需再调接口 // 将企业信息存入 sessionStorage,预览页直接使用,无需再调接口
sessionStorage.setItem('enterpriseScanData', JSON.stringify(data)); sessionStorage.setItem('enterpriseScanData', JSON.stringify(data));
// 跳转企业详情预览页,携带执法类型参数和企业编号 // 跳转企业详情预览页,携带执法类型参数和企业编号
router.push({ router.push({
path: '/enforcement/enterpriseScanPreview', path: '/enforcement/enterpriseScanPreview',
query: { type: enforceType, enterpriseNumber: data.enterpriseNumber } query: { type: enforceType, enterpriseNumber: data.enterpriseNumber }
}); });
@ -394,7 +401,7 @@ const selectEnterprise = (item) => {
showSearchModal.value = false; showSearchModal.value = false;
router.push({ router.push({
path: '/enforcement/enterpriseScanPreview', path: '/enforcement/enterpriseScanPreview',
query: { query: {
enterpriseNumber: item.enterpriseNumber, enterpriseNumber: item.enterpriseNumber,
type: enforceType type: enforceType
} }

Loading…
Cancel
Save