开发背景

  1. 最近在学习java,所以从网上看了一些别人的代码,再加入了自己的一些理解,主要是担心之后会忘记,所以写下一篇东西记录一下思路。

一、 获取acess_token以及jsapiTicket

  1. 新建一个类TokenThread,实现线程的Runnable接口,代码如下:

TokenThread

package util;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import model.AccessToken;
import model.JsapiTicket;/*** Created by xu on 2017/7/10.*/
public class TokenThread implements Runnable {public static String appId = "xxx";public static String appSecret= "xxx";public static AccessToken accessToken = null;public static JsapiTicket jsapiTicket = null;public final static String js_api_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";@Overridepublic void run() {while (true) {try {accessToken = this.getAccessToken();jsapiTicket = this.getJsapiTicket();//获取到accessToken后,休眠7000秒,保证不会重复的获取,超过了每天的最大次数if (null != accessToken) {System.out.println(accessToken.getAccessToken());System.out.println(jsapiTicket.getJsapiTicket());Thread.sleep(7000 * 1000); //获取到access_token 休眠7000秒} else {Thread.sleep(1000 * 3); //获取的access_token为空 休眠3秒}} catch (Exception e) {System.out.println("发生异常:" + e.getMessage());e.printStackTrace();try {Thread.sleep(1000 * 10); //发生异常休眠1秒} catch (Exception e1) {}}}}/*** 获取access_token* @return*/private AccessToken getAccessToken(){NetWorkHelper netHelper = new NetWorkHelper();String Url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",this.appId,this.appSecret);String result = netHelper.getHttpsResponse(Url,"");System.out.println(result);//response.getWriter().println(result);JSONObject json = JSONObject.parseObject(result);System.out.println(json);AccessToken token = new AccessToken();token.setAccessToken(json.getString("access_token"));token.setExpiresin(json.getInteger("expires_in"));return token;}/*** 获取jsapi_ticket* @return*/private JsapiTicket getJsapiTicket(){NetWorkHelper netHelper = new NetWorkHelper();String Url = js_api_ticket_url.replace("ACCESS_TOKEN",this.getAccessToken().getAccessToken());String result = netHelper.getHttpsResponse(Url,"");System.out.println(result);JSONObject json = JSONObject.parseObject(result);System.out.println(json);JsapiTicket jsapiTicket = new JsapiTicket();jsapiTicket.setJsapiTicket(json.getString("ticket"));jsapiTicket.setExpiresin(json.getInteger("expires_in"));return jsapiTicket;}}

这里用到了两个工具类NetWorkHelper,发起网络请求网上有封装好的,我做一下搬运工:

NetWorkHelper

package util;import javax.net.ssl.*;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;/*** Created by xu on 2017/7/10.*/
public class NetWorkHelper {public String getHttpsResponse(String hsUrl,String requestMethod) {URL url;InputStream is = null;String resultData = "";try {url = new URL(hsUrl);HttpsURLConnection con = (HttpsURLConnection) url.openConnection();TrustManager[] tm = {xtm};SSLContext ctx = SSLContext.getInstance("TLS");ctx.init(null, tm, null);con.setSSLSocketFactory(ctx.getSocketFactory());con.setHostnameVerifier(new HostnameVerifier() {@Overridepublic boolean verify(String arg0, SSLSession arg1) {return true;}});con.setDoInput(true); //允许输入流,即允许下载//在android中必须将此项设置为falsecon.setDoOutput(false); //允许输出流,即允许上传con.setUseCaches(false); //不使用缓冲if(null!=requestMethod && !requestMethod.equals("")) {con.setRequestMethod(requestMethod); //使用指定的方式}else{con.setRequestMethod("GET"); //使用get请求}is = con.getInputStream(); //获取输入流,此时才真正建立链接InputStreamReader isr = new InputStreamReader(is);BufferedReader bufferReader = new BufferedReader(isr);String inputLine = "";while ((inputLine = bufferReader.readLine()) != null) {resultData += inputLine + "\n";}System.out.println(resultData);Certificate[] certs = con.getServerCertificates();int certNum = 1;for (Certificate cert : certs) {X509Certificate xcert = (X509Certificate) cert;}} catch (Exception e) {e.printStackTrace();}return resultData;}X509TrustManager xtm = new X509TrustManager() {@Overridepublic X509Certificate[] getAcceptedIssuers() {// TODO Auto-generated method stubreturn null;}@Overridepublic void checkServerTrusted(X509Certificate[] arg0, String arg1)throws CertificateException {// TODO Auto-generated method stub}@Overridepublic void checkClientTrusted(X509Certificate[] arg0, String arg1)throws CertificateException {// TODO Auto-generated method stub}};
}

上面还引入了阿里巴巴的json解析包import com.alibaba.fastjson.JSONObject;自行上网搜索就好。
上面的获取accessToken的过程中,new了一个AccessToken和JsapiTicket对象,我把她们放进了一个model类里。

AccessToken

package model;/*** Created by xu on 2017/7/10.*/
public class AccessToken {public String getAccessToken() {return accessToken;}public void setAccessToken(String accessToken) {this.accessToken = accessToken;}public int getExpiresin() {return expiresin;}public void setExpiresin(int expiresin) {this.expiresin = expiresin;}private String accessToken;private int expiresin;
}

JsapiTicket

package model;/*** Created by xu on 2017/7/12.*/
public class JsapiTicket {private String jsapiTicket;private int expiresin;public String getJsapiTicket() {return jsapiTicket;}public void setJsapiTicket(String jsapiTicket) {this.jsapiTicket = jsapiTicket;}public int getExpiresin() {return expiresin;}public void setExpiresin(int expiresin) {this.expiresin = expiresin;}}

新建一个HttpServlet,AccessTokenServlet,用来执行获取,初始化的过程中执行,这里需要配置web.xml

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><servlet><servlet-name>wechatServlet</servlet-name><servlet-class>com.wecahtServlet</servlet-class></servlet><servlet-mapping><servlet-name>wechatServlet</servlet-name><url-pattern>/wechat</url-pattern></servlet-mapping><servlet><servlet-name>GetConfigServlet</servlet-name><servlet-class>com.GetConfigServlet</servlet-class></servlet><servlet-mapping><servlet-name>GetConfigServlet</servlet-name><url-pattern>/getConfig</url-pattern></servlet-mapping><servlet><servlet-name>ReturnRobotServlet</servlet-name><servlet-class>com.ReturnRobotServlet</servlet-class></servlet><servlet-mapping><servlet-name>ReturnRobotServlet</servlet-name><url-pattern>/doReturn</url-pattern></servlet-mapping><servlet><servlet-name>initAccessTokenServlet</servlet-name><servlet-class>com.AccessTokenServlet</servlet-class><init-param><param-name>appid</param-name><param-value>xxxx</param-value></init-param><init-param><param-name>appsecret</param-name><param-value>xxxx</param-value></init-param><load-on-startup>0</load-on-startup></servlet><welcome-file-list><welcome-file>returnRobot.jsp</welcome-file></welcome-file-list>
</web-app>

AccessTokenServlet

package com;import util.TokenThread;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** Created by xu on 2017/7/10.*/
@WebServlet(name = "AccessTokenServlet")
public class AccessTokenServlet extends HttpServlet {public void init() throws ServletException {TokenThread.appId = getInitParameter("appid"); //获取servlet初始参数appid和appsecretTokenThread.appSecret = getInitParameter("appsecret");System.out.println("appid:"+TokenThread.appId);System.out.println("appSecret:"+TokenThread.appSecret);new Thread(new TokenThread()).start(); //启动进程}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}

二、获取jssdk配置

  1. 创建一个GetConfigServlet用以页面获取jssdk的配置信息

GetConfigServlet

package com;import com.alibaba.fastjson.JSON;
import util.Sign;
import util.TokenThread;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;/*** Created by xu on 2017/7/12.*/
@WebServlet(name = "GetConfigServlet")
public class GetConfigServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String url = request.getParameter("url");String jsapi_tickec = TokenThread.jsapiTicket.getJsapiTicket();Map<String, String> jssdk = Sign.main(jsapi_tickec,url);String str = JSON.toJSONString(jssdk);response.setCharacterEncoding("UTF-8");response.setContentType("application/json; charset=utf-8");PrintWriter out = null;try {out = response.getWriter();out.write(str);} catch (IOException e) {e.printStackTrace();} finally {if (out != null) {out.close();}}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("get config test success");}
}

上文中引用了sign工具类:

Sign

package util;import java.util.UUID;
import java.util.Map;
import java.util.HashMap;
import java.util.Formatter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;public class Sign {public static Map<String, String> main(String jsapiTicket,String posturl) {String jsapi_ticket = jsapiTicket;// 注意 URL 一定要动态获取,不能 hardcodeString url = posturl;Map<String, String> ret = sign(jsapi_ticket, url);
//        for (Map.Entry entry : ret.entrySet()) {
//            System.out.println(entry.getKey() + ", " + entry.getValue());
//        }return ret;};public static Map<String, String> sign(String jsapi_ticket, String url) {Map<String, String> ret = new HashMap<String, String>();String nonce_str = create_nonce_str();String timestamp = create_timestamp();String string1;String signature = "";//注意这里参数名必须全部小写,且必须有序string1 = "jsapi_ticket=" + jsapi_ticket +"&noncestr=" + nonce_str +"&timestamp=" + timestamp +"&url=" + url;System.out.println(string1);try{MessageDigest crypt = MessageDigest.getInstance("SHA-1");crypt.reset();crypt.update(string1.getBytes("UTF-8"));signature = byteToHex(crypt.digest());}catch (NoSuchAlgorithmException e){e.printStackTrace();}catch (UnsupportedEncodingException e){e.printStackTrace();}ret.put("url", url);ret.put("appId", TokenThread.appId);ret.put("jsapi_ticket", jsapi_ticket);ret.put("nonceStr", nonce_str);ret.put("timestamp", timestamp);ret.put("signature", signature);return ret;}private static String byteToHex(final byte[] hash) {Formatter formatter = new Formatter();for (byte b : hash){formatter.format("%02x", b);}String result = formatter.toString();formatter.close();return result;}private static String create_nonce_str() {return UUID.randomUUID().toString();}private static String create_timestamp() {return Long.toString(System.currentTimeMillis() / 1000);}
}

前段js:

$(document).ready(function () {//获取配置信息$.ajax({url : "http://120.77.43.103/wechat/getConfig",type : 'post',dataType : 'json',contentType : "application/x-www-form-urlencoded; charset=utf-8",data : {'url' : location.href.split('#')[0]},success : function(data) {console.log(data);wx.config({debug : true,appId : data.appId,timestamp : data.timestamp,nonceStr : data.nonceStr,signature : data.signature,jsApiList : [ 'checkJsApi', 'onMenuShareTimeline','onMenuShareAppMessage', 'onMenuShareQQ','onMenuShareWeibo', 'hideMenuItems','showMenuItems', 'hideAllNonBaseMenuItem','showAllNonBaseMenuItem', 'translateVoice','startRecord', 'stopRecord', 'onRecordEnd','playVoice', 'pauseVoice', 'stopVoice','uploadVoice', 'downloadVoice', 'chooseImage','previewImage', 'uploadImage', 'downloadImage','getNetworkType', 'openLocation', 'getLocation','hideOptionMenu', 'showOptionMenu', 'closeWindow','scanQRCode', 'chooseWXPay','openProductSpecificView', 'addCard', 'chooseCard','openCard' ]});},error: function (xhr, type) {showAlert("getJSSDKSignature出错");},});checkUserDeposit();
});
function checkUserDeposit() {wx.ready(function () {scanQRCode();});
}
function scanQRCode() {wx.scanQRCode({needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有success: function (res) {var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果//var result = "linuxserl.honeybot.cn:5120/download/?id=bind@104@10V1BLH100040478054";//var result = "CODE_128,10V1BLH100261";var postCode = "";var robotCodeType = 0;if (result.indexOf(",") > -1) {//条形码var codes = result.split(',');if (codes != null && codes.length > 1) {postCode = codes[1];robotCodeType = 1;}} else {//二维码var reg = /@(.*?)@/;var codes = reg.exec(result);if (codes.length > 1) {postCode = codes[1];robotCodeType = 0;}}showConfirm("是否确认退还?",function () {returnRobot(robotCodeType, postCode);});}});
}
function returnRobot(robotCodeType, robotCodeValue) {var dialogLoading = null;var postData = {robot_code:{robot_code_type: robotCodeType,robot_code_value: robotCodeValue}}$.ajax({type: 'POST',cache: false,url: "http://120.77.43.103/wechat/doReturn",data: "json_body=" + JSON.stringify(postData),dataType: 'json',beforeSend: function (XHR) {dialogLoading = showLoading();},success: function (data) {if (data.result_code == 0) {setTimeout(function() {showAlert("申请退还机器人成功,请点击确定支付租金", function () {goTo(config.page_url.return_robot_wait_confrm);});}, 500);} else {setTimeout(function () {showAlert(data.result_message);}, 500);}},error: function (xhr, type) {showAlert('error')},complete: function (xhr, type) {dialogLoading.hide();}});
}
wx.error(function (res) {showAlert("微信接口出错");
});

三、额外的一些签名,验证配置

wecahtServlet

package com;import com.sun.tools.classfile.Signature;
import util.CheckUtil;
import util.Sign;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** Created by xu on 2017/7/10.*/
@WebServlet(name = "wecahtServlet")
public class wecahtServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String signature = request.getParameter("signature");String timestamp = request.getParameter("timestamp");String nonce = request.getParameter("nonce");String echostr = request.getParameter("echostr");if( CheckUtil.checkSignature(signature,timestamp,nonce)){response.getWriter().println(echostr);}}}

工具类CheckUtil

package util;import java.util.Arrays;/*** Created by xu on 2017/7/10.*/
public class CheckUtil
{private static final String token = "test";public static boolean checkSignature(String signature,String timestamp,String nonce){String[] arr = new String[]{token,timestamp,nonce};//排序Arrays.sort(arr);//生成字符串StringBuffer content = new StringBuffer();for (int i=0;i<arr.length;i++){content.append(arr[i]);}//sha1加密String temp = Decript.SHA1(content.toString());//校验签名return temp.equals(signature);}
}

sha1

package util;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;/*** Created by xu on 2017/7/10.*/
public class Decript {public static String SHA1(String decript) {try {MessageDigest digest = MessageDigest.getInstance("SHA-1");digest.update(decript.getBytes());byte messageDigest[] = digest.digest();// Create Hex StringStringBuffer hexString = new StringBuffer();// 字节数组转换为 十六进制 数for (int i = 0; i < messageDigest.length; i++) {String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);if (shaHex.length() < 2) {hexString.append(0);}hexString.append(shaHex);}return hexString.toString();} catch (NoSuchAlgorithmException e) {e.printStackTrace();}return "";}
}

引用JdbcUtils jdbc连接工具类

package util;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class JdbcUtils
{private static String url="jdbc:mysql://xxx.xxx.xxx/weixin?useUnicode=true&characterEncoding=utf-8";private static String user="xxx";private static String password="xxx";private JdbcUtils(){}static{try{Class.forName("com.mysql.jdbc.Driver");}catch(ClassNotFoundException e){throw new ExceptionInInitializerError(e);}}public static Connection getConnection() throws SQLException{return DriverManager.getConnection(url, user, password);}public static void free(ResultSet resultset,Statement st,Connection conn){//6.释放资源try{if(resultset!=null)resultset.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{try{if(st!=null)st.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{if(conn!=null)try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
}

完整项目地址:https://github.com/345632699/...

java版本微信jssdk、微信验证签名demo(Servlet)相关推荐

  1. ##iOS中的微信支付 支付验证签名失败

    iOS中的微信支付 支付验证签名失败 今天要在项目中添加微信支付,iOS端的所有东西都已经按照文档搞好了,可就是跳转到微信的时候显示"支付验证签名失败",可是安卓端的都没有问题,就 ...

  2. 视频教程-微信公众号实战(Java版本,带前后台)-微信开发

    微信公众号实战(Java版本,带前后台) 2018年5月创办 威海科进网络科技有限公司,这里的视频主要是为了做个记录,方便员工提升自己的水平 陈健 ¥29.00 立即订阅 扫码下载「CSDN程序员学院 ...

  3. 微信js扫一扫,扫条形码去掉code_128。在vue中封装全局对象的方法,封装微信js-sdk权限验证的方法

    微信公众号在调用扫一扫功能时,一维码(条形码)在直接返回结果时会在结果前带上EAN_8, EAN_13, CODE_25, CODE_39, CODE_128, UPC_A, UPC_E wx.sca ...

  4. php 微信支付md5签名,微信支付回调验证签名处理

    微信支付回调验证签名:一定要验证签名,可能不造成伪造数据,或者数据库造到灌水: /** * 微信支付回调类 * @name callbackaction.class.php * @author yan ...

  5. 微信JSSDK invalid signature签名错误的解决方法

    导致签名错误的原因: 微信文档给出以下原因. invalid signature签名错误:建议按如下顺序检查: 确认签名算法正确,可用 http://mp.weixin.qq.com/debug/cg ...

  6. 微信jssdk ajax 获取签名,【Golang版】微信access_token、jsapi_ticket、signature签名算法生成示例,开箱即用...

    # WXToken 项目地址:[https://github.com/henson/WXToken](https://github.com/henson/WXToken) 因为手上有一个项目需要用到微 ...

  7. ios不行安卓可以 微信签名_微信支付-支付验证签名失败(iOS)

    在项目中添加微信支付,iOS端的所有东西都已经按照文档搞好了,可就是跳转到微信的时候显示"支付验证签名失败",可是安卓端的都没有问题,就很郁闷了. 后来在对文档的时候发现... 6 ...

  8. 微信支付 支付验证签名失败

    公众号支付,WeixinJSBridge.invoke()方法,返回错误:支付验证签名失败 检查后台签名参数.支付密钥均正确,却还是错误,最后询问微信支付技术才解决,问题所在就是微信给的java sd ...

  9. 对hash签名失败_vue项目中微信jssdk在ios签名失败

    一.问题描述 1. vue项目中微信jssdk签名时,在安卓和ios是有差异的,签名时使用的url=window.location.href.split('#')[0],此时在安卓没问题,在ios会导 ...

最新文章

  1. 基于Spring AOP的JDK动态代理和CGLIB代理
  2. vs shortcut
  3. System.arraycopy用法
  4. Andriod UI设计之度量单位说明(DIP,DP,PX,SP)
  5. Javascript特效:利用封装动画函数模拟关闭安全管家弹窗
  6. NVMe驱动解析-DMA传输
  7. js拆分百分数_计算百分比Javascript
  8. 自己做的js甘特图插件
  9. matlab绘图 作业,实验作业2 - -MATLAB作图
  10. Spring bean解析 - refresh
  11. 谈谈Android 6.0 的动态权限管理
  12. 教师如何创建在线查分系统
  13. PHP 将xml文件解析为数组
  14. SecureCRT的下载安装
  15. 第一篇Blog:电动汽车与燃料电池汽车
  16. Linux下安装rar解压
  17. Docker镜像与仓库(四)
  18. 在easydl平台上传已经标注好的数据,怎么按照要求进行json和图片格式配置。是用labellmg图片标注工具生成的xml文件。
  19. STM32F103C8 TIM1 CHN PWM输出代码
  20. 论文写作 3: 慎用的单词与短语

热门文章

  1. Please verify you invoked Maven from the correct directory
  2. 处理上百万条的数据库如何提高处理查询速度
  3. 发现不错的文章,推!
  4. Codeforces.1110E.Magic Stones(思路 差分)
  5. python基础——变量
  6. js确保正确this的几种写法
  7. JavaWeb基础—项目名的写法
  8. 如何删除webstrom中生成的.idea wrokspace
  9. 利用UDP19端口实施DOS攻击的真实案例
  10. openal 基础知识4