package com.ys.zhenlian.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import com.ys.zhenlian.bean.*; import com.ys.zhenlian.entity.*; import com.ys.zhenlian.service.AccessTokenService; import com.ys.zhenlian.service.TeacherService; import com.ys.zhenlian.service.UserService; import com.ys.zhenlian.service.ZhenLianService; import com.ys.zhenlian.util.*; import com.ys.zhenlian.util.voiceTools.entity.TranslateResult; import com.ys.zhenlian.util.voiceTools.entity.XunfeiRequest; import com.ys.zhenlian.util.voiceTools.tools.Consts; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.math.BigDecimal; import java.net.URLEncoder; import java.nio.charset.Charset; import java.security.NoSuchAlgorithmException; import java.util.*; /** * 微信验证,获取token控制器 * Created by DELL on 2017/11/30. */ @Controller @RequestMapping("/service/weixin") public class WeiXinValidateController extends BaseController { private final Logger log = LoggerFactory.getLogger(this.getClass()); // public long timeLose; @Value("${accessTokenVersion}") private Integer accessTokenVersion; @Value("${baseUrl}") private String baseUrl; @Value("${voicePath}") private String voicePath; @Value("${picturePath}") private String picturePath; @Value("${appid}") private String appid; @Value("${secret}") private String secret; /*打分接口 header参数*/ @Value("${authorization}") private String token; /*打分接口 请求Url*/ @Value("${reqUrl}") private String reqUrl; @Resource private UserService userService; @Resource private TeacherService teacherService; @Resource private ZhenLianService zhenLianService; @Resource private AccessTokenService accessTokenService; private static final Map<String, String> htmlUrl = new HashMap<String, String>(); /** * 微信网页授权验证 * * @param response * @throws Exception */ @RequestMapping("/getAuthorize") public void getAuthorize(HttpServletRequest request, HttpServletResponse response) throws Exception { String rUrl = StringUtils.trim(request.getParameter("url")); if(rUrl != null) { rUrl = rUrl.replace("?from=singlemessage", "").replace("&isappinstalled=0", ""); } // rUrl = rUrl.replace("?from=singlemessage", "").replace("&isappinstalled=0", ""); String uid = UUID.randomUUID().toString(); if (StringUtils.isNotEmpty(rUrl)){ htmlUrl.put(uid, rUrl); } //第一步:用户同意授权,获取code String cbUrl = URLEncoder.encode(baseUrl + "/service/weixin/" + uid + "/index.do", "utf-8"); String url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + "appid=" + appid + //公众号的唯一标识 //授权后重定向的回调链接地址,请使用urlEncode对链接进行处理,应当使用https链接来确保授权code的安全性 "&redirect_uri=" + cbUrl + "&response_type=code" +//返回类型,请填写code //应用授权作用域: // 1.snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid) // 2.snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息) "&scope=snsapi_userinfo" + //非必须字段,重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节 "&state=STATE" + //无论直接打开还是做页面302重定向时候,必须带此参数 "#wechat_redirect"; //重定向至微信验证地址 response.sendRedirect(url); } /** * 根据code获取用户登陆accesstoken * 获取用户信息 * 初始化教师信息 * * @param request * @return * @throws Exception */ @ResponseBody @RequestMapping("/{uid}/index") public Msg getToken(HttpServletRequest request, HttpServletResponse response, @PathVariable("uid")String uid) { try { String code = request.getParameter("code"); if (code == null || code.isEmpty()) { log.error("获取code失败"); return new Msg(400, "获取code失败"); } log.info("获取code成功,code=" + code); //第二步:通过code换取网页授权access_token String url = "https://api.weixin.qq.com/sns/oauth2/access_token?" + "appid=" + appid + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code"; WeiXinTokenResult tokenResult; String token_result = HttpUtil.sendGet(url); if (token_result.contains("errcode")) { log.error("用户token获取失败," + token_result); return new Msg(400, "用户token获取失败," + token_result); } Gson gson = new Gson(); tokenResult = gson.fromJson(token_result, WeiXinTokenResult.class); log.info("token获取成功,token=" + tokenResult.getAccess_token()); request.getSession().setAttribute("user_token", tokenResult); //第三部:获取用户信息 UserInfo userInfo = getUser(tokenResult); if (userInfo == null) { log.error("用户信息获取失败"); return new Msg(400, "用户信息获取失败"); } //根据opeaId查询用户 List<UserInfo> userList = userService.selectByOpeaId(userInfo.getOpenid()); if (userList == null || userList.size() <= 0) { log.info("用户信息不存在,第一次登陆,开始保存用户信息"); //保存到数据库 int result = userService.insertByUserInfo(userInfo); if (result != 1) { log.error("用户信息保存失败"); return new Msg(400, "用户信息保存失败"); } } else { log.info(userInfo.toString()); //更新数据库 int result = userService.updateByOpenid(userInfo); if (result != 1) { log.error("用户信息更新失败"); return new Msg(400, "用户信息更新失败"); } } userList = userService.selectByOpeaId(userInfo.getOpenid()); if (userList.size() != 1) { log.error("用户信息保存更新失败"); return new Msg(400, "用户信息保存更新失败"); } request.getSession().setAttribute("user_info", userList.get(0)); //初始化教师信息 List<Teacher> list = teacherService.getTeacherList(); if (list.size() == 0) { log.error("获取老师信息失败"); return new Msg(400, "获取老师信息失败"); } request.getSession().setAttribute("teacher_List", list); log.info("教师信息初始化成功"); String rUrl = htmlUrl.get(uid); if (StringUtils.isEmpty(rUrl)){ //重定向到前台html response.sendRedirect(baseUrl + "/index.html"); } else { htmlUrl.remove(uid); response.sendRedirect(rUrl); } return new Msg(200, "登陆成功"); } catch (Exception ex) { log.info("登陆错误," + ex.getMessage()); return new Msg(400, "登陆错误," + ex.getMessage()); } } /** * 刷新网页token */ @ResponseBody @RequestMapping("/refreshToken") public Msg refreshToken(HttpServletRequest request) { try { WeiXinTokenResult tokenResult = (WeiXinTokenResult) request.getSession().getAttribute("user_token"); String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token" + "?appid=" + appid + "&grant_type=refresh_token" + "&refresh_token=" + tokenResult.getRefresh_token(); String refresh_result = HttpUtil.sendGet(url); if (!refresh_result.contains("errcode")) { log.error("token刷新失败" + refresh_result); return new Msg(400, "token刷新失败" + refresh_result); } Gson gson = new Gson(); tokenResult = gson.fromJson(refresh_result, WeiXinTokenResult.class); request.getSession().setAttribute("user_token", tokenResult); log.info("token刷新成功,token=" + tokenResult.getAccess_token()); return new Msg(200, "", "token刷新成功"); } catch (JsonSyntaxException e) { e.printStackTrace(); log.error("token刷新错误," + e.getMessage()); return new Msg(400, "token刷新错误," + e.getMessage()); } } /** * 返回用户信息 */ @ResponseBody @RequestMapping("/getUserInfo") public Msg getUserInfo(HttpServletRequest request) { try { UserInfo userInfo = (UserInfo) request.getSession().getAttribute("user_info"); if (userInfo == null) { log.error("用户信息获取失败"); return new Msg(400, "用户信息获取失败"); } return new Msg(200, userInfo); } catch (Exception e) { e.printStackTrace(); log.error("用户信息获取错误," + e.getMessage()); return new Msg(400, "用户信息获取错误," + e.getMessage()); } } /** * 返回用户微信信息 */ @ResponseBody @RequestMapping("/getWeixinUser") public Msg getWeixinUser(HttpServletRequest request) { try { WeiXinTokenResult tokenResult = (WeiXinTokenResult) request.getSession().getAttribute("user_token"); if (tokenResult == null) { log.error("用户没有授权,无法获取用户微信信息"); return new Msg(400, "用户没有授权,无法获取用户微信信息"); } UserInfo userInfo = getUser(tokenResult); return new Msg(200, userInfo); } catch (Exception e) { e.printStackTrace(); log.error("获取错误," + e.getMessage()); return new Msg(400, "获取错误," + e.getMessage()); } } /** * 登陆接口(测试使用) * * @param request * @return */ @ResponseBody @RequestMapping("/login") public Msg loginTest(HttpServletRequest request) { //取openid List<UserInfo> userInfos = userService.getOpenId(); WeiXinTokenResult tokenResult = new WeiXinTokenResult(); tokenResult.setOpenid(userInfos.get(0).getOpenid()); request.getSession().setAttribute("user_token", tokenResult); request.getSession().setAttribute("user_info", userInfos.get(0)); List<Teacher> list = teacherService.getTeacherList(); if (list.size() == 0) { log.error("获取老师信息失败"); return new Msg(400, "获取老师信息失败"); } request.getSession().setAttribute("teacher_List", list); System.out.println(Charset.defaultCharset()); log.info("登陆成功"); return new Msg(200, "登陆成功"); } /** * 下载用户音频,返回微信下载地址 * * @param request * @param media_id * @return */ @ResponseBody @RequestMapping("/downloadVoice") public Msg downloadVoice(HttpServletRequest request, Integer dialog_id, String media_id) { if (request.getSession().getAttribute("user_info") == null) return new Msg(201, "没有用户信息"); if (dialog_id == null || dialog_id == 0) return new Msg(201, "缺少dialog_id参数"); if (media_id == null || media_id.isEmpty()) return new Msg(201, "缺少media_id参数"); log.info("成功获得media_id,media_id为:" + media_id); try { //获取accessToken //需要配置(1,old;2,new) AccessToken accessToken = accessTokenService.getAccessToken(accessTokenVersion); String tokenStr = accessToken.getAccessToken(); log.info("成功获得tokenStr,tokenStr为:" + tokenStr); UserInfo userInfo = (UserInfo) request.getSession().getAttribute("user_info"); //根据dialog_id,获取保存路径 String voiceSavePath = zhenLianService.getVoicePath(dialog_id); if (voiceSavePath == null || voiceSavePath.isEmpty()) { log.error("找不到对话保存路径"); return new Msg(400, "找不到对话保存路径"); } //得到用户语音保存地址 StringBuilder sb = new StringBuilder(); voiceSavePath = sb.append(voiceSavePath).insert("download".length() + 1, "/userVoice/" + userInfo.getId()).toString(); voiceSavePath = voiceSavePath.substring(0, voiceSavePath.lastIndexOf("/") + 1) + System.currentTimeMillis() + ".speex"; log.info("得到用户语音保存地址:" + voiceSavePath); //微信下载音频url String url = "https://api.weixin.qq.com/cgi-bin/media/get/jssdk" + "?access_token=" + tokenStr + "&media_id=" + media_id; String path = new File(voicePath).getCanonicalPath() + voiceSavePath; File file = FileDownloadUtil.saveUrlAs(url, path); if (file == null) { log.error("下载失败!"); return new Msg(400, "下载失败!"); } //speex转wav String wavPath = path.replace(".speex", ".wav"); VoiceUtil.speex2wav(path, wavPath); //获取音频时长 int lengh = VoiceUtil.getVoiceLenWav(wavPath); // int lengh = VoiceUtil.getVoiceLenWavNew(wavPath); //音频相对路径 String substring = voicePath.substring(voicePath.lastIndexOf("/") + 1); String returnPath = wavPath.substring(wavPath.lastIndexOf(substring) + substring.length()); //保存用户音频 log.info("保存音频前dialog_id为:"+dialog_id); DialogVoiceUser voiceUser = new DialogVoiceUser(dialog_id, userInfo.getOpenid(), returnPath, lengh); zhenLianService.insertDialogVoiceUser(voiceUser); //获取语音评分 // Score score = getSpeechScore(returnPath,dialog_id); //获取音频路径 String voice_path = voicePath+returnPath; //根据dialog_id查询语音话题ConEn SubjectDialog subjectDialog=zhenLianService.getSubjectDialogById(dialog_id); log.info("音频地址为:"+voice_path); log.info("文本信息为:"+subjectDialog.getConEn()); // JSONObject score = this.getSpeechScoreData(reqUrl,voice_path,subjectDialog.getConEn()); //TODO,获取teacher_en,直接数据库获取 String teacher_en = ""; teacher_en = zhenLianService.getTeacherEnByDialog(subjectDialog.getId()); log.info("获取到老师翻译的音频为:----->"+teacher_en); // //模拟数据 // String voice_path = "E:\wavFile\Joey.wav"; //如果teacher_en是"",则采用con_en请求打分接口,否则用teacher_en JSONObject score = new JSONObject(); if (teacher_en == null || "".equals(teacher_en)){ score = this.getSpeechScoreData(reqUrl,voice_path,subjectDialog.getConEn()); log.info("获取con_en值为:----->"+subjectDialog.getConEn()); log.info("根据con_en获取的打分结果为:----->"+score.toString()); }else { score = this.getSpeechScoreData(reqUrl,voice_path,teacher_en); } //获取语音评分 BigDecimal speechScore=BigDecimal.ZERO;//语音评分 //用于存放语音打分数据 String speech_score_msg = ""; log.info("打分详情信息为:"+score); log.info("请求之前音频得分为:------"+score.get("score")); if(null != score){ // speechScore=new BigDecimal(score.getFinalScore()*100); //如果err_code不等于空,这段音频则为无效数据 if(score.get("err_code") != null && !"".equals(score.get("err_code").toString())){ log.info("无效数据!或者声音太小"); log.info("接口数据返回为:----"+score.toString()); return new Msg(401, "无效音频文件,请重新录入!"); } //分数由十分制改为百分制。author(袁勋) if(score.get("score") != null && !"".equals(score.get("score").toString())){ log.info("请求之后音频得分为:------"+score.get("score").toString()); speechScore=new BigDecimal(Double.parseDouble(score.get("score").toString())*10); if(speechScore.compareTo(BigDecimal.ZERO) <= 0){//小于等于0,得0随机分 // Random random=new Random(); // speechScore=new BigDecimal(random.nextInt(10)+30); speechScore = new BigDecimal(0); } // else if(speechScore.compareTo(new BigDecimal(96))>0){//大于96,得96分 // speechScore=new BigDecimal(96); // } }else{ // Random random=new Random(); // speechScore=new BigDecimal(random.nextInt(10)+30); speechScore = new BigDecimal(0); } speechScore=speechScore.setScale(3,BigDecimal.ROUND_UP);//格式化返回0.000 // JSONObject resultObject=JSON.parseObject(score.toString()); // resultObject.remove("DetailResponse");//移除DetailResponse 响应详情 // resultObject.remove("BestMatch");//移除BestMatch 批量处理详情 // speechScoreMsg=resultObject.toJSONString();//返回评分消息 //如果该JSON字符串字节长度超过1024,则不存入到数据库。author(袁勋)注:将该字段类型转换为text // if (score.toString().getBytes().length>1024){ // speechScoreMsg = ""; // } speech_score_msg = score.toString(); }else { log.error("打分接口无数据返回"); log.info("返回的打分数据为:--->"+score.toString()); speech_score_msg = ""; return new Msg(400, "测评失败,请联系服务商!"); } //低于30分再加30分 // if(speechScore.compareTo(new BigDecimal(30))<0){ // speechScore=speechScore.add(new BigDecimal(30)); // } System.out.println("计算语音评分--得分:"+speechScore); log.info("dialog_id为:"+dialog_id); //保存用户对话记录 int resultNumber = zhenLianService.saveUserDialogRecord(dialog_id, userInfo.getOpenid(), returnPath, lengh,speechScore,speech_score_msg); if (resultNumber == 0){ System.out.println("====>>>>>>> 保存用户对话记录失败 <<<<<<<<===="); } VoiceResult voiceResult = new VoiceResult(returnPath, lengh,speechScore); log.info("下载成功!用户音频地址为:" + returnPath); return new Msg(200, "", voiceResult); } catch (Exception ex) { ex.printStackTrace(); log.error("下载错误!" + ex.getMessage()); return new Msg(400, "下载错误!" + ex.getMessage()); } } private String getTeacherConEn(String voiceSavePath) { //定义课程英语翻译 String con_en= ""; // String reqPath = voicePath + voiceSavePath; String reqPath = voiceSavePath; //请求xunfei参数设置 XunfeiRequest xfReq = new XunfeiRequest(); xfReq.setLanguage(Consts.Language.ENGLISH); xfReq.setPath(reqPath); //请求讯飞翻译接口 TranslateResult translateResult = TranslateUtils.xunfei(xfReq); log.info("downloadVoice()---获取讯飞翻译结果translateResult :"+ translateResult.getText()); if (translateResult.isSuccess()){ con_en = translateResult.getText().replace("[", "").replace("]", "").replace(",", "").replace(""", ""); }else { con_en = "Error,this dialog is not exist !"; } return con_en; } /** * 获取用户的语音平均评分 * * @param request * @param lesson_id 主题ID * @return */ @ResponseBody @RequestMapping("/getSpeechAvgScore") public Msg getSpeechAvgScore(HttpServletRequest request, Integer lesson_id) { if (request.getSession().getAttribute("user_info") == null) return new Msg(201, "没有用户信息"); if (lesson_id == null || lesson_id == 0) return new Msg(201, "缺少lesson_id参数"); try { //获取accessToken //需要配置(1,old;2,new) AccessToken accessToken = accessTokenService.getAccessToken(accessTokenVersion); String tokenStr = accessToken.getAccessToken(); log.info("成功获得tokenStr,tokenStr为:" + tokenStr); UserInfo userInfo = (UserInfo) request.getSession().getAttribute("user_info"); //保存用户对话记录 BigDecimal speechScore = zhenLianService.getSpeechAvgScore(lesson_id, userInfo.getOpenid()); //百分比(超过百分之几的人) BigDecimal percentScore=BigDecimal.ZERO; if(speechScore != null){ BigDecimal seventy=new BigDecimal(70); BigDecimal hundred=new BigDecimal(100); //scoreNumber=(平均分-70)*100/70 BigDecimal scoreNumber=speechScore.subtract(seventy).multiply(hundred).divide(seventy,3); //scoreNumber=50+scoreNumber scoreNumber=new BigDecimal(50).add(scoreNumber); //如果百分比小于0,则按照0显示 if(scoreNumber.compareTo(BigDecimal.ZERO)>0){ percentScore=scoreNumber; } } JSONObject result=new JSONObject(); result.put("speechScore",speechScore); result.put("lesson_id",lesson_id); result.put("percentScore",percentScore); log.info(userInfo.getOpenid()+"用户语音平均评分为:" + speechScore); return new Msg(200, "", result); } catch (Exception ex) { log.error("获取用户语音评分错误:",ex); return new Msg(400, "获取用户语音平均评分错误!" + ex.getMessage()); } } /** * 生成微信前端接口权限 * * @param url * @return * @throws NoSuchAlgorithmException */ @ResponseBody @RequestMapping("/getJsConfig") public String getJsConfig(String url) { if (url == null || url.isEmpty()) return "wx.config(缺少url参数);"; log.info("url获取成功,url:" + url); try { //第一步获取AccessToken String tokenStr; //获取accessToken AccessToken accessToken = accessTokenService.getAccessToken(accessTokenVersion); if (accessToken != null && System.currentTimeMillis() - accessToken.getLastTime().getTime() < 7200000) { tokenStr = accessToken.getAccessToken(); } else { log.info("accessToken不存在,或者已过期,开始获取accessToken"); tokenStr = getAccessToken(); if (tokenStr.isEmpty() || tokenStr.contains("失败")) { log.error("access_token获取失败," + tokenStr); return "wx.config(获取access_token信息失败);"; } log.info("accessToken获取成功,accessToken:" + tokenStr); } //第二步,获取jsTicket(相同的accesstoken,得到的ticket是不变的) String getUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket" + "?access_token=" + tokenStr + "&type=jsapi"; String jsTicket_result = HttpUtil.sendGet(getUrl); if (!jsTicket_result.contains("ticket")) { log.error("获取jsTicket失败," + jsTicket_result); return "wx.config(获取jsTicket失败);"; } Gson gson = new Gson(); JsTicket jsTicket = gson.fromJson(jsTicket_result, JsTicket.class); String ticket = jsTicket.getTicket(); log.info("jsTicket获取成功,jsTicket:" + ticket); //第三步,生成JS-SDK权限验证的签名 String noncestr = WXSignatureUtil.getRandomString(16); log.info("noncestr获取成功,noncestr:" + noncestr); // String timestamp = String.valueOf(System.currentTimeMillis()); //当前时间戳(单位秒)(去掉后三位) Date date = new Date(); String timestampTemp = String.valueOf(date.getTime()); int length = timestampTemp.length(); String timestamp = timestampTemp.substring(0, length - 3); log.info("timestamp获取成功,timestamp:" + timestamp); //按照参数名排序,拼接成str String str = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + url; //生成签名(签名算法) String signature = WXSignatureUtil.SHA1(str); log.info("签名:" + signature); //前端使用接口集合 List<String> jsApiList = new ArrayList<>(); jsApiList.add("onMenuShareTimeline"); jsApiList.add("onMenuShareAppMessage"); jsApiList.add("onMenuShareQQ"); jsApiList.add("onMenuShareWeibo"); jsApiList.add("previewImage"); jsApiList.add("downloadImage"); jsApiList.add("chooseImage"); jsApiList.add("uploadImage"); jsApiList.add("checkJsApi"); jsApiList.add("startRecord"); jsApiList.add("stopRecord"); jsApiList.add("onVoiceRecordEnd"); jsApiList.add("playVoice"); jsApiList.add("pauseVoice"); jsApiList.add("stopVoice"); jsApiList.add("onVoicePlayEnd"); jsApiList.add("uploadVoice"); jsApiList.add("downloadVoice"); jsApiList.add("translateVoice"); jsApiList.add("hideOptionMenu"); jsApiList.add("showOptionMenu"); jsApiList.add("hideMenuItems"); jsApiList.add("showMenuItems"); jsApiList.add("hideAllNonBaseMenuItem"); jsApiList.add("showAllNonBaseMenuItem"); WXsignature wXsignature = new WXsignature(false, appid, timestamp, noncestr, signature, jsApiList); log.info("wx.config获取成功,wx.config:" + "wx.config(" + gson.toJson(wXsignature) + ");"); return "wx.config(" + gson.toJson(wXsignature) + ");"; } catch (Exception e) { log.error("wx.config(获取权限错误," + e.getMessage() + ");"); return "wx.config(获取权限错误," + e.getMessage() + ");"; } } /** * 提交用户预约 * * @return */ @ResponseBody @RequestMapping("/saveUserReservation") public Msg userReservation(@ModelAttribute("json") JSONObject jsonObject) { if (jsonObject == null || jsonObject.size() == 0) { log.error("缺少UserReservation对象参数"); return new Msg(201, "缺少UserReservation对象参数"); } UserReservation userReservation = JSON.toJavaObject(jsonObject, UserReservation.class); try { int result = userService.saveUserReservation(userReservation); if (result != 1) { log.error("用户预约失败"); return new Msg(400, "用户预约失败"); } log.info("用户预约成功"); return new Msg(200, "用户预约成功"); } catch (Exception ex) { log.error("用户预约错误," + ex.getMessage()); return new Msg(400, "用户预约错误," + ex.getMessage()); } } /** * 获取、刷新accessToken */ // private String getAccessToken() { // try { // String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" + // "&appid=" + appid + //公众号的唯一标识; // "&secret=" + secret; // String token_result = HttpUtil.sendGet(url); // if (token_result.contains("errcode")) { // log.error("获取、刷新accessToken失败,原因:" + token_result); // return token_result; // } // Gson gson = new Gson(); // AccessTokenResult accessToken = gson.fromJson(token_result, AccessTokenResult.class); // String access_token = accessToken.getAccess_token(); // log.info("获取、刷新accessToken成功,access_token:" + access_token); // //封装条件 // Map<String, Object> condition = new HashMap<>(); // condition.put("accessTokenVersion", accessTokenVersion); // condition.put("access_token", access_token); // //保存access_token(存在刷新,不存在添加) // accessTokenService.saveAccessToken(condition); // return access_token; // } catch (JsonSyntaxException e) { // e.printStackTrace(); // log.error("获取、刷新accessToken错误," + e.getMessage()); // return "获取、刷新accessToken错误," + e.getMessage(); // } // } private String getAccessToken() { try { //返回值初始化 String access_token = ""; //根据accessTokenVersion查询access_token AccessToken accessToken = accessTokenService.getAccessToken(accessTokenVersion); access_token = accessToken.getAccessToken(); log.info("获取的access_token为:------"+access_token); return access_token; }catch (Exception e){ e.printStackTrace(); log.error("获取、刷新accessToken错误," + e.getMessage()); return "获取、刷新accessToken错误," + e.getMessage(); } } /** * 获取用户信息 * * @param tokenResult * @return */ private UserInfo getUser(WeiXinTokenResult tokenResult) { String url = "https://api.weixin.qq.com/sns/userinfo" + "?access_token=" + tokenResult.getAccess_token() + "&openid=" + tokenResult.getOpenid() + "&lang=zh_CN"; String info_result = HttpUtil.sendGet(url); if (info_result.contains("errcode")) { log.error("用户信息获取失败,原因" + info_result); return null; } Gson gson = new Gson(); UserInfo userInfo = gson.fromJson(info_result, UserInfo.class); log.info("用户信息获取成功"); return userInfo; } /** *根据语音文本进行语音评分 * @param returnPath 文件路径 * @param dialog_id 对话ID * @return score 评分 * */ // private Score getSpeechScore(String returnPath,Integer dialog_id){ // try { // SubjectDialog subjectDialog=zhenLianService.getSubjectDialogById(dialog_id); // if(subjectDialog==null){ // return null; // } // File file=new File(voicePath+returnPath); // InputStream stream = new FileInputStream(file); // String fileName = System.nanoTime() + ".wav"; // //获取打分 //// Score score = SpeechScoreApp.getScore(subjectDialog.getConEn(), stream, fileName); // return score; // } catch (Exception ex) { // log.error("获取用户语音评分错误:",ex); // return null; // } // } /** * 用户音频打分接口 * * @param request * @param dialog_id * @return */ @ResponseBody @RequestMapping("/getUserSpeechScoreInfo") public Msg getUserSpeechScoreInfo(HttpServletRequest request, Integer dialog_id) { if (dialog_id == null || dialog_id == 0) return new Msg(201, "缺少dialog_id参数"); log.info("dialog_id,dialog_id为:" + dialog_id); if (request.getSession().getAttribute("user_info") == null) return new Msg(201, "没有用户信息"); try { //获取accessToken //需要配置(1,old;2,new) AccessToken accessToken = accessTokenService.getAccessToken(accessTokenVersion); String tokenStr = accessToken.getAccessToken(); log.info("成功获得tokenStr,tokenStr为:" + tokenStr); UserInfo userInfo = (UserInfo) request.getSession().getAttribute("user_info"); //返回结果初始化 JSONObject json = new JSONObject(); //根据user的openId、dialogId查询用户音频数据 Map<String,Object> userDialogRecord = zhenLianService.getUserDialogRecordById(dialog_id,userInfo.getOpenid()); //获取用户音频text SubjectDialog subjectDialog = zhenLianService.getSubjectDialogById(dialog_id); json.put("speech_dialog",subjectDialog.getConEn()); //获取用户音频的打分数据 if (userDialogRecord != null && userDialogRecord.size() > 0){ //获取音频得分 BigDecimal speechScore = new BigDecimal(userDialogRecord.get("speech_score").toString()); speechScore=speechScore.setScale(0,BigDecimal.ROUND_UP);//格式化返回0 json.put("score",speechScore); //根据得分判断返回话术 String speechMsg = ""; if (speechScore.compareTo(new BigDecimal(60)) < 0){ speechMsg = "学习不易,再接再厉!"; } if (speechScore.compareTo(new BigDecimal(60)) >= 0 && speechScore.compareTo(new BigDecimal(90)) < 0){ speechMsg = "很不错,继续加油!"; } if (speechScore.compareTo(new BigDecimal(90)) >= 0){ speechMsg = "非常赞!"; } json.put("speech_msg",speechMsg); String wavPath = userDialogRecord.get("voice_url").toString(); String returnPath = wavPath; json.put("voice_path",returnPath); JSONObject voiceData = new JSONObject(); //标红单词列表初始化 JSONArray errArray = new JSONArray(); //TODO,获取teacher_en,直接数据库获取 String teacher_en = ""; teacher_en = zhenLianService.getTeacherEnByDialog(subjectDialog.getId()); //如果音频数据不为空,则取数据返回 if(userDialogRecord.get("speech_score_msg") != null && !"".equals(userDialogRecord.get("speech_score_msg"))){ String speechJson = userDialogRecord.get("speech_score_msg").toString(); log.info("获取的userDialogJson数据为:-------"+speechJson); if (teacher_en != null){ json.put("teachen_cn",teacher_en);//返回老师的音频翻译 }else { json.put("teachen_cn",""); } voiceData = JSONObject.parseObject(speechJson); //如果err_code不等于空,这段音频则为无效数据 if(voiceData.get("err_code") != null && !"".equals(voiceData.get("err_code").toString())){ log.info("无效数据!或者声音太小"); log.info("接口数据返回为:----"+voiceData.toString()); return new Msg(401, "无效音频文件,请重新录入!"); } getErrorWordsJarray(voiceData, errArray); }else { //如果用户的返回数据为空,则请求打分接口获取数据返回 //获取音频路径 String voice_path = voicePath+wavPath; //根据dialog_id,获取保存路径 String teacher_voice = ""; if (teacher_en != null){ json.put("teachen_cn",teacher_en);//返回老师的音频翻译 }else { json.put("teachen_cn",""); } //模拟数据 // String voice_path = "E:\wavFile\Joey.wav"; //请求声讯科技打分接口 // JSONObject speech_score_data = this.getSpeechScoreData(reqUrl,voice_path,subjectDialog.getConEn()); //如果老师翻译文本不为空则根据老师音频打分 JSONObject speech_score_data = new JSONObject(); if (teacher_en == null || "".equals(teacher_en)){ speech_score_data = this.getSpeechScoreData(reqUrl,voice_path,subjectDialog.getConEn()); log.info("获取con_en值为:----->"+subjectDialog.getConEn()); log.info("根据con_en获取的打分结果为:----->"+speech_score_data.toString()); }else { speech_score_data = this.getSpeechScoreData(reqUrl,voice_path,teacher_en); } if (speech_score_data == null){ return new Msg(400,"打分异常,无法解析到打分结果!"); }else { //如果err_code不等于空,这段音频则为无效数据 if(speech_score_data.get("err_code") != null && !"".equals(speech_score_data.get("err_code").toString())){ log.info("无效数据!或者声音太小"); log.info("接口数据返回为:----"+speech_score_data.toString()); return new Msg(401, "无效音频文件,请重新录入!"); } } log.info("获取的userDialogJson数据为:-------"+speech_score_data.toString()); getErrorWordsJarray(speech_score_data, errArray); } json.put("err_words",errArray); }else{ return new Msg(400,"没有用户音频记录"); } log.info("返回的Json数据为:----->"+json.toString()); return new Msg(200, "", json); } catch (Exception ex) { log.error("获取用户语音评分错误:",ex); return new Msg(400, "获取用户语音评分信息错误!" + ex.getMessage()); } } private void getErrorWordsJarray(JSONObject voiceData, JSONArray errArray) throws Exception { if (voiceData.get("words") != null && !"".equals(voiceData.get("words").toString())){ JSONArray wordsArray = JSONArray.parseArray(voiceData.get("words").toString()); if (wordsArray != null && wordsArray.size() > 0){ for (int i = 0; i < wordsArray.size();i++){ JSONObject wordObject = wordsArray.getJSONObject(i); log.info("获取打分结果的单词信息:----->"+wordObject.toString()); if (wordObject != null && !"".equals(wordObject)){ //获取读错的单词列表 JSONObject word = new JSONObject(); BigDecimal wordScore = new BigDecimal(Double.parseDouble(wordObject.get("score").toString())*10); if (wordScore.compareTo(new BigDecimal(60)) < 0){ word.put("word_name",wordObject.get("name").toString()); JSONArray syllables = JSONArray.parseArray(wordObject.get("syllables").toString()); String dict = "";//正确音标 String rec = "";//用户发音音标 if (syllables != null && syllables.size() >0 ){ for(int s = 0;s < syllables.size();s++){ JSONObject syllables_view = syllables.getJSONObject(s); //获取单词音标组phones if (syllables_view != null && !"".equals(syllables_view)){ JSONArray phones = JSONObject.parseArray(syllables_view.get("phones").toString()); if(phones !=null && phones.size() > 0){ for(int p = 0;p < phones.size(); p++){ JSONObject phone = phones.getJSONObject(p); if (phone != null && !"".equals(phone)){ String dictCode = phone.get("dict").toString();//正确音标组件 String recCode = phone.get("rec").toString();//用户音标组件 //音标转换 dictCode = EnglishToPhoneticUtil.phoneticValue(dictCode); recCode = EnglishToPhoneticUtil.phoneticValue(recCode); //拼接成音标 dict += dictCode; rec += recCode; } } } } } } //将单词的音标存入words数组里 word.put("word_dict",dict.trim()); word.put("word_rec",rec.trim()); //生成单词的正确读音音频文件 String word_name = wordObject.get("name").toString(); //用户单词音频的开始时间, word.put("rec_start",wordObject.get("start"));//单位:毫秒 word.put("rec_end",wordObject.get("end"));//单位:毫秒 word.put("word_score",wordScore);//单词的得分 errArray.add(word); } log.info("错词详细信息为:----->"+word.toString()); } } } } } /** * 请求打分接口 * @param * @param * @param */ public JSONObject getSpeechScoreData(String reqUrl,String filePath,String text)throws IOException{ File file = new File(filePath); MultipartUtility multipartUtility = new MultipartUtility(reqUrl,"UTF-8",token); multipartUtility.addFilePart("myWavfile",file); multipartUtility.addFormField("word_name",text); List<String> pListResponse = multipartUtility.finish(); String voiceData = pListResponse.get(0); JSONObject voiceObt = com.alibaba.fastjson.JSONObject.parseObject(voiceData); return voiceObt; } /** * 请求打分接口 * @param * @param * @param */ @RequestMapping("/test") public JSONObject text()throws IOException{ File file = new File("F:\workspace\zhenlianService\src\main\resources\1542878441365.wav"); MultipartUtility multipartUtility = new MultipartUtility(reqUrl,"UTF-8",token); multipartUtility.addFilePart("myWavfile",file); multipartUtility.addFormField("word_name","111"); List<String> pListResponse = multipartUtility.finish(); String voiceData = pListResponse.get(0); JSONObject voiceObt = com.alibaba.fastjson.JSONObject.parseObject(voiceData); return voiceObt; } }