资讯专栏INFORMATION COLUMN

java版本微信jssdk、微信验证签名demo(Servlet)

codecook / 2127人阅读

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

开发背景

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

一、 获取acess_token以及jsapiTicket

新建一个类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";


    @Override
    public 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() {
                @Override
                public boolean verify(String arg0, SSLSession arg1) {
                    return true;
                }
            });


            con.setDoInput(true); //允许输入流,即允许下载

            //在android中必须将此项设置为false
            con.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 + "
";
            }
            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() {
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
            // TODO Auto-generated method stub

        }

        @Override
        public 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



    
        wechatServlet
        com.wecahtServlet
    
    
        wechatServlet
        /wechat
    
    
        GetConfigServlet
        com.GetConfigServlet
    
    
        GetConfigServlet
        /getConfig
    
    
        ReturnRobotServlet
        com.ReturnRobotServlet
    
    
        ReturnRobotServlet
        /doReturn
    
    
        initAccessTokenServlet
        
            com.AccessTokenServlet
        
        
            appid
            xxxx
        
        
            appsecret
            xxxx
        
        0
    
    
        returnRobot.jsp
    

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和appsecret
        TokenThread.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配置

创建一个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 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 main(String jsapiTicket,String posturl) {
        String jsapi_ticket = jsapiTicket;

        // 注意 URL 一定要动态获取,不能 hardcode
        String url = posturl;
        Map ret = sign(jsapi_ticket, url);
//        for (Map.Entry entry : ret.entrySet()) {
//            System.out.println(entry.getKey() + ", " + entry.getValue());
//        }
        return ret;
    };

    public static Map sign(String jsapi_ticket, String url) {
        Map ret = new HashMap();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";

        //注意这里参数名必须全部小写,且必须有序
        string1 = "jsapi_ticket=" + jsapi_ticket +
                "&noncestr=" + nonce_str +
                "×tamp=" + 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

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 String
            StringBuffer 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 block
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if(st!=null)
                    st.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            finally
            {
                if(conn!=null)
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
            }
        }
    }
}

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/70268.html

相关文章

  • 微信公众平台JSSDK分享接口开发(PHP实现)

    摘要:最近做个移动端的应用,要实现自定义微信分享功能,实现过程中遇到一些小小的坑,这里分享一下。后来微信放出了,开始对端提供丰富强大的官方接口支持,也逐渐淡出了开发者的视野。 最近做个移动端的H5应用,要实现自定义微信分享功能,实现过程中遇到一些小小的坑,这里分享一下。 以前微信官方是没有正式支持微信分享的自定义接口(包括图片、标题、描述)的,然而有一些大神找到了WeixinJSBridge...

    MonoLog 评论0 收藏0
  • 微信公众平台JSSDK分享接口开发(PHP实现)

    摘要:最近做个移动端的应用,要实现自定义微信分享功能,实现过程中遇到一些小小的坑,这里分享一下。后来微信放出了,开始对端提供丰富强大的官方接口支持,也逐渐淡出了开发者的视野。 最近做个移动端的H5应用,要实现自定义微信分享功能,实现过程中遇到一些小小的坑,这里分享一下。 以前微信官方是没有正式支持微信分享的自定义接口(包括图片、标题、描述)的,然而有一些大神找到了WeixinJSBridge...

    banana_pi 评论0 收藏0
  • vue+微信支付目录+JSSDK签名解决方案

    摘要:主要是用,每当用户第一次进来时,去获取一次签名验证。注意只获取一次,这样签名就解决了。 vue+微信支付目录+JSSDK签名解决方案 遇坑如下 注意:此方法仅为个人总结,并非唯一解决方案 微信JSSDK签名出错 微信支付 调起支付缺少API参数 微信支付目录配置,只有5个配置,可能超过5个地方有配置,路由规划 微信授权回调处理 我所使用的技术 vue路由模式 history 模...

    Little_XM 评论0 收藏0
  • 微信开发总结之JSSDK

    摘要:签名用的必须是调用接口页面的完整。出于安全考虑,开发者必须在服务器端实现签名的逻辑。以上为服务器的步骤,根据以上内容实现了一个简单的中间件,详见客户端使用接口注入权限验证配置待续 关键名词解释 安全域名: 用于JSSDK,开发者即可在该域名(包括二级域名)下调用微信开放的JS接口 access_token: · 普通access_token:JSSDK和微信公众号后台...

    happyhuangjinjin 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<