因为地址打卡可以作假,那么将照相与地址打卡捆绑在一起,降低作假率.
下面介绍照相打卡.
工具类,或其它获取accessToken,自定义菜单等的,可以见我前一篇文章之微信地址打卡.
照相的controller,这个微信菜单及菜单设置的url请见前一篇文章之微信地址打卡.
@Controller
@RequestMapping("/weixin")
public class WeiXinController {
private static Logger logger = LogManager.getLogger(WeiXinController.class);
@Value("${spring.servlet.multipart.location}")
private String finalDirPath;
@Autowired
IPersonServ personServ;
private static JedisPool pool;
private static Jedis jedis;
@ResponseBody
@RequestMapping(value = "/getCamera")
public ModelAndView getCamera(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView view = new ModelAndView("camera");
String code = request.getParameter("code");
pool = new JedisPool(new JedisPoolConfig(), "127.0.0.1");
jedis = pool.getResource();
AccessToken accessToken = WeiXinUtil.getTheCode(code, jedis);
view.addObject("bean", accessToken.getOpenId());
return view;
}
}
controller调用的html如下
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>拍照</title>
<script src="/lib/jquery-3.3.1.min.js" type="text/javascript"></script>
<script type="text/javascript" src="../static/lib/bootstrap/js/bootstrap.min.js"></script>
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
</head>
<script>
var l_timestamp;
var l_noncestr;
var l_signature;
var appid;
var wx;
var openId;
$(function () {
//自动获取url
var url = location.href.split('#').toString();//url不能写死
var bean = $("#bean").val();
var path = "http://homey.nat100.top/weixin/getMobileLocateReal";
$.post(path, {wxurl: url, bean: bean}, function (data) {
var data = JSON.parse(data);
l_timestamp = data[0];
l_noncestr = data[1];
l_signature = data[2];
appid = data[4];
openId = data[5];
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: appid, // 必填,公众号的唯一标识
timestamp: l_timestamp, // 必填,生成签名的时间戳,上文通过后台获取的
nonceStr: l_noncestr, // 必填,生成签名的随机串,上文通过后台获取的
signature: l_signature,// 必填,签名,上文通过后台获取的
jsApiList: ['chooseImage', 'uploadImage'] // 必填,需要使用的JS接口列表,就是下文的分享朋友圈和转发给朋友的列表
});
});
});
wx.ready(function () {
wx.checkJsApi({
jsApiList: [
'chooseImage', 'uploadImage'
],
success: function (res) {
// alert(JSON.stringify(res));
// alert(JSON.stringify(res.checkResult.getLocation));
if (res.checkResult.chooseImage == false) {
alert('你的微信版本太低!');
return;
}
}
});
wx.error(function (res) {
alert("接口调取失败")
});
wx.chooseImage({
count: 1, // 最多可以选择的图片张数,默认9
sizeType: ['original', 'compressed'], // original 原图,compressed 压缩图,默认二者都有
sourceType: ['camera'], // album 从相册选图,camera 使用相机,默认二者都有
success: function (res) {
let localIds = res.localIds; // 返回选定照片的本地ID列表(手机上操作就是手机端的ID列表,是一个数组),localId可以作为img标签的src属性显示图片
wx.uploadImage({
localId: localIds[0], // 需要上传的图片的本地ID,由chooseImage接口获得
isShowProgressTips: 1, // 默认为1,显示进度提示
success: function (result) {
let serverId = result.serverId; // 返回图片的服务器端ID
window.location.href = "http://homey.nat100.top/weixin/saveOutPhoto?serverId="+serverId + "&openId=" + openId;
}
});
},
fail: function () {
},
complete: function () {
}
});
});
</script>
<body>
<input type="hidden" id="appId" th:value="${appId}">
<input type="hidden" id="l_timestamp" th:value="${l_timestamp}">
<input type="hidden" id="l_noncestr" th:value="${l_noncestr}">
<input type="hidden" id="l_signature" th:value="${l_signature}">
<input type="hidden" id="requestOri" th:value="${requestOri}">
<input type="hidden" id="bean" th:value="${bean}">
</body>
</html>
不要忘记引入微信JS接口包
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
下面将拍照的照片保存在服务器
@ResponseBody
@RequestMapping(value = "/saveOutPhoto")
public ModelAndView saveOutPhoto(HttpServletRequest request, HttpServletResponse response) throws Exception {
pool = new JedisPool(new JedisPoolConfig(), "127.0.0.1");
jedis = pool.getResource();
String openId = request.getParameter("openId");
String serverId = request.getParameter("serverId");
ModelAndView mav = new ModelAndView("success");
Date date = new Date();
SimpleDateFormat today = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat todaytime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr1 = today.format(date);
String todaytimeStr = todaytime.format(date);
String hourStr = todaytimeStr.split(" ")[1];
Integer hour = Integer.valueOf(hourStr.split(":")[0]);
String folderName = "weixin/" + dateStr1 + "/";
ImageUtils.saveImage(jedis.get(Constants.accessToken), finalDirPath + folderName, serverId, serverId + ".jpg");
OutClockIn outClockIn = new OutClockIn();
outClockIn.setClockInDateStr(dateStr1);
outClockIn.setWeixinNo(openId);
if (hour < 12 && hour >= 6) {//上午
outClockIn.setAmOnUrl(folderName + serverId + ".jpg");
int isPhotoInAlready = personServ.isClockInAlready(openId, dateStr1, "amOnUrl");
if (isPhotoInAlready == 0) {
personServ.saveOrUpdateOutClockInDataUrl(outClockIn);
} else {
//mav.addObject("flag", "您上午已经摄过像,不能重复摄像!");
mav = new ModelAndView("failed");
return mav;
}
} else if (hour >= 12 && hour <= 18) {//下午
outClockIn.setPmOnUrl(folderName + serverId + ".jpg");
int isPhotoInAlready = personServ.isClockInAlready(openId, dateStr1, "pmOnUrl");
if (isPhotoInAlready == 0) {
personServ.saveOrUpdateOutClockInDataUrl(outClockIn);
} else {
//mav.addObject("flag", "您下午已经摄过像,不能重复摄像!");
mav = new ModelAndView("failed");
return mav;
}
} else if (hour > 18 && hour <= 24) {//晚上
outClockIn.setNmOnUrl(folderName + serverId + ".jpg");
int isPhotoInAlready = personServ.isClockInAlready(openId, dateStr1, "nmOnUrl");
if (isPhotoInAlready == 0) {
personServ.saveOrUpdateOutClockInDataUrl(outClockIn);
} else {
//mav.addObject("flag", "您晚上已经摄过像,不能重复摄像!");
mav = new ModelAndView("failed");
return mav;
}
}
//mav.addObject("flag", "已摄像!");
return mav;
}
package com.cosun.cosunp.weixin;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* @author:homey Wong
* @Date: 2019/9/23 上午 10:56
* @Description:
* @Modified By:
* @Modified-date:
*/
public class ImageUtils {
public static boolean saveImage(String accessToken,String temp_path, String serverId, String image_number) {
boolean isSave = true;
File saveFile = new File(temp_path);
if (!saveFile.exists()) {
saveFile.mkdirs();
}
try {
String s = saveImageToDisk(accessToken,serverId, image_number, temp_path + "/");
if (s != null || !"".equals(s.trim())) {
isSave = true;
}
} catch (Exception e) {
e.printStackTrace();
}
return isSave;
}
//获取
private static InputStream getInputStream(String accessToken, String mediaId) {
InputStream is = null;
String url = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=" + accessToken + "&media_id=" + mediaId;
try {
URL urlGet = new URL(url);
HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
http.setRequestMethod("GET"); // 必须是get方式请求
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
http.connect();
// 获取文件转化为byte流
is = http.getInputStream();
} catch (Exception e) {
}
return is;
}
private static String saveImageToDisk(String accessToken, String serverId, String picName, String picPath) throws Exception {
InputStream inputStream = getInputStream(accessToken, serverId);
// 循环取出流中的数据
byte[] data = new byte[1024];
int len = 0;
FileOutputStream fileOutputStream = null;
String filePath = picPath + picName;
try {
fileOutputStream = new FileOutputStream(filePath);
while ((len = inputStream.read(data)) != -1) {
fileOutputStream.write(data, 0, len);
}
} catch (IOException e) {
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
}
}
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
}
}
}
return filePath;
}
}
@ResponseBody
@RequestMapping(value = "/getMobileLocateReal")
public void getMobileLocateReal(HttpServletRequest request, HttpServletResponse response) throws Exception {
String wxMsgXml = IOUtils.toString(request.getInputStream(), "utf-8");
String url = request.getParameter("wxurl");
String openId = request.getParameter("bean");
pool = new JedisPool(new JedisPoolConfig(), "127.0.0.1");
jedis = pool.getResource();
try {
String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳
System.out.println("accessToken:" + jedis.get(Constants.accessToken) + "\njsapi_ticket:" + jedis.get(Constants.jsapi_ticket) + "\n时间戳:" + timestamp + "\n随机字符串:" + noncestr);
String str = "jsapi_ticket=" + jedis.get(Constants.jsapi_ticket) + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + url;
//6、将字符串进行sha1加密
String signature = CheckUtil.getSha1(str);
System.out.println("参数:" + str + "\n签名:" + signature);
List l_data = new ArrayList();
l_data.add(timestamp);
l_data.add(noncestr);
l_data.add(signature);
l_data.add(url);
l_data.add(WeiXinConfig.appid);
l_data.add(openId);
JSONArray l_jsonarrary = JSONArray.fromObject(l_data);
//json转的字符串值
String l_jsonstring = l_jsonarrary.toString();
response.getWriter().print(l_jsonstring);
response.getWriter().flush();
response.getWriter().close();
} catch (Exception e) {
e.printStackTrace();
}
}
至此就完成了调用微信的拍照接口,并将微信服务器已保存的照片存到自己的服务器里.
这里附上我这边做的拍照成功后回显给手机的html页面,各位可以自由发挥.
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>打卡结果</title>
<script src="/lib/jquery-3.3.1.min.js" type="text/javascript"></script>
<script type="text/javascript" src="../static/lib/bootstrap/js/bootstrap.min.js"></script>
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<meta name="viewport"
content="
height = [pixel_value | device-height] ,
width = [pixel_value | device-width ] ,
initial-scale = 0.5 ,
minimum-scale = float_value ,
maximum-scale = float_value ,
user-scalable = [yes | no] ,
"
/>
</head>
<script>
$(function () {
window.parent.document.getElementById('content').style.display = "block";
window.parent.document.getElementById('contentnew').style.display = "none";
});
</script>
<style type="text/css">
a {
white-space: nowrap;
}
table tr td {
white-space: nowrap;
}
img {
margin: 0 auto;
width: 100px;
height: 100px;
position: absolute;
top: 40%;
left: 40%;
}
</style>
<body>
<img src="/images/page/success.jpg" align="middle" border="0"
style="width: 20%; height: 12%; vertical-align: middle"/>
</body>
</html>