Rumah >applet WeChat >pembangunan WeChat >详解微信开发微信jsapi与java初步接入方法

详解微信开发微信jsapi与java初步接入方法

高洛峰
高洛峰asal
2017-03-26 14:08:422284semak imbas

参数名

http://www.php.cn/wiki/835.html" target="_blank">width="346" valign="top" style="word-break:break-all">  描述
appId 应用ID 登录微信公众号管理平台可查询
timestamp  必填,生成签名的时间戳 
nonceStr 必填,生成签名的随机串 
signature 必填,签名,见附录1 

上述表格中的参数,我们在前一章节已经说的很明白,之所以做出一个表格是因为如果想要成功接入微信jsapi这四个参数是凭证,也就是相当于一个门必须要有四把钥匙才能打开,缺一不可 。

接下来的案例采用java的servlet做的跳转页面,没有用到springMVC,大家可把请求的路径更换成controller路径即可。

WxJsAPIServlet代码:

package com.test;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.Map;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.test.util.JsapiTicketUtil;

import com.test.util.Sign;

public class WxJsAPIServlet extends HttpServlet {

/**

     * Constructor of the object.

     */

    public WxJsAPIServlet() {

        super();

    }

/**

     * Destruction of the servlet. 

     */

    public void destroy() {

        super.destroy(); // Just puts "destroy" string in log

        // Put your code here

    }

    /**

     * The doGet method of the servlet. 

     *

     * This method is called when a form has its tag value method equals to get.

     * 

     * @param request the request send by the client to the server

     * @param response the response send by the server to the client

     * @throws ServletException if an error occurred

     * @throws IOException if an error occurred

     */

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        System.out.println("wxJSAPI====================");

        String jsapi_ticket =JsapiTicketUtil.getJSApiTicket();;

        Map map = Sign.sign(jsapi_ticket, "http://www.vxzsk.com/weChat/wxJsAPIServlet");

        String timestamp = map.get("timestamp");

        String nonceStr = map.get("nonceStr");

        String signature = map.get("signature");

        String appId = "应用Id";

        request.setAttribute("appId", appId);

        request.setAttribute("timestamp", timestamp);

        request.setAttribute("signature",signature);

        request.setAttribute("nonceStr", nonceStr);

        request.getRequestDispatcher("jsapi/jsapi.jsp").forward(request, response);

    }

    /**

     * The doPost method of the servlet. 

     *

     * This method is called when a form has its tag value method equals to post.

     * 

     * @param request the request send by the client to the server

     * @param response the response send by the server to the client

     * @throws ServletException if an error occurred

     * @throws IOException if an error occurred

     */

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

       this.doGet(request, response);

       }

/**

     * Initialization of the servlet. 

     *

     * @throws ServletException if an error occurs

     */

    public void init() throws ServletException {

        // Put your code here

    }

}

第44行是生成 jsapi_ticket的工具类,在下面有贴出工具类的代码。

第45行 Sign类的sign方法,把表格中的最后三个参数封装放到Map集合中了。其中参数就是请求的servlet地址并跳转到调用微信jsapi的jsp界面。

第49行 appId替换成你自己的应用id,如果不知道应用id 可登陆微信公众平台管理中心查询。

servlet对应的web.xml代码

    This is the description of my J2EE component

    <display-name>This is the display name of my J2EE component

    WxJsAPIServlet

    com.test.WxJsAPIServlet

  

    WxJsAPIServlet

    /wxJsAPIServlet

  

生成签名算法类Sign代码:

package com.test.util;

/***

 * V型知识库 www.vxzsk.com

 */

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 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("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);

    }

    public static void main(String[] args) {

        String jsapi_ticket =JsapiTicketUtil.getJSApiTicket();

        // 注意 URL 一定要动态获取,不能 hardcode

        String url = "http://www.vxzsk.com/xx/x.do";//url是你请求的一个action或者controller地址,并且方法直接跳转到使用jsapi的jsp界面

        Map ret = sign(jsapi_ticket, url);

        for (Map.Entry entry : ret.entrySet()) {

            System.out.println(entry.getKey() + ", " + entry.getValue());

        }

    };

}

生成jsapi_ticket参数的工具类JsapiTicketUtil代码

package com.test.util;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.net.MalformedURLException;

import java.net.URL;

import java.net.URLConnection;

import net.sf.json.JSONObject;

import com.test.weixin.TestAcessToken;

public class JsapiTicketUtil {

    /***

     * 模拟get请求

     * @param url

     * @param charset

     * @param timeout

     * @return

     */

     public static String sendGet(String url, String charset, int timeout)

      {

        String result = "";

        try

        {

          URL u = new URL(url);

          try

          {

            URLConnection conn = u.openConnection();

            conn.connect();

            conn.setConnectTimeout(timeout);

            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));

            String line="";

            while ((line = in.readLine()) != null)

            {

              result = result + line;

            }

            in.close();

          } catch (IOException e) {

            return result;

          }

        }

        catch (MalformedURLException e)

        {

          return result;

        }

        return result;

      }

     public static String getAccessToken(){

            String appid="你公众号基本设置里的应用id";//应用ID

            String appSecret="你公众号基本设置里的应用密钥";//(应用密钥)

            String url ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+appSecret+"";

            String backData=TestAcessToken.sendGet(url, "utf-8", 10000);

            String accessToken = (String) JSONObject.fromObject(backData).get("access_token");  

            return accessToken;

     }

    public static String getJSApiTicket(){ 

        //获取token

        String acess_token= JsapiTicketUtil.getAccessToken();

        String urlStr = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+acess_token+"&type=jsapi";  

        String backData=TestAcessToken.sendGet(urlStr, "utf-8", 10000);  

        String ticket = (String) JSONObject.fromObject(backData).get("ticket");  

        return  ticket;  

    }  

    public static void main(String[] args) {

        String jsapiTicket = JsapiTicketUtil.getJSApiTicket();

        System.out.println("调用微信jsapi的凭证票为:"+jsapiTicket);

    }

}

上述代码中有个获取access_token的方法,请读者更换自己的参数即可

jsapi.jsp代码

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

W3C//DTD HTML 4.01 Transitional//EN">

  <head>

    

    微信jsapi测试-V型知识库

    viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">

    

  

  

  

欢迎来到微信jsapi测试界面-V型知识库

  

     

timestamp:${ timestamp}

  

     

nonceStr:${ nonceStr}

  

     

signature:${ signature}

  

     

appId:${ appId}

  

    onclick="uploadImg();"/>  

    获取当前位置" onclick="getLocation();"/>  

  

  

  


测试场景:打开微信公众号,点击菜单回复带有请求servlet地址,跳转到jsapi.jsp界面链接地址,然后界面会弹出调用微信jsapi成功或失败的窗口信息,所以还需要接下来的代码:

WeChatServlet为微信接入的servlet,不清楚的同学可学习我们的微信开发教程。

package com.test;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.Date;

import java.util.Map;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.test.message.resp.TextMessage;

import com.test.util.MessageUtil;

/**

 * 核心请求处理类

 * doGet方法里 有个weixinTest,这个是公众管理平台里面自己设置的token 大家根据自己的token替换

 */

public class WeChatServlet extends HttpServlet {

    private static final long serialVersionUID = 1508798736675904038L;

    /**

     * 确认请求来自微信服务器

     */

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("V型知识库原创www.vxzsk.com");

        // 微信加密签名

        String signature = request.getParameter("signature");

        System.out.println("微信加密签名signature:-----------------------"+signature);

        // 时间戳

        String timestamp = request.getParameter("timestamp");

        System.out.println("时间戳timestamp:-----------------------"+timestamp);

        // 随机数

        String nonce = request.getParameter("nonce");

        System.out.println("随机数nonce:-----------------------"+nonce);

        // 随机字符串

        String echostr = request.getParameter("echostr");

        System.out.println("随机字符串echostr:-----------------------"+echostr);

        //System.out.println("token-----------------------:"+token);

        PrintWriter out = response.getWriter();

        // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败

        if (SignUtil.checkSignature("weixinTest", signature, timestamp, nonce)) {

            out.print(echostr);

            //System.out.println("这是:"+echostr);

        }

        out.close();

        out = null;

    }

    /**

     * 处理微信服务器发来的消息

     * 实例源码在文章顶部有下载连接

     */

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 

        System.out.println("V型知识库原创www.vxzsk.com");

        System.out.println("微信服务器发来消息------------");

        // 将请求、响应的编码均设置为UTF-8(防止中文乱码)

        request.setCharacterEncoding("UTF-8");

        response.setCharacterEncoding("UTF-8");

        String respMessage = null;

        try{

        //xml请求解析

        Map requestMap = MessageUtil.parseXml(request);//接收微信发过来的xml格式

        //发送方帐号(open_id)

        String fromUserName = requestMap.get("FromUserName");

        //公众帐号

        String toUserName = requestMap.get("ToUserName");

        //消息类型

        String msgType = requestMap.get("MsgType");

        //消息创建时间

        String createTime = requestMap.get("CreateTime");

        //微信服务器post过来的内容

        String weixinContent = requestMap.get("Content");

        System.out.println("公众号用户发送过来的文本消息内容:"+weixinContent);

        //接下来我们用上一章节自己封装好的工具类

        if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {//文本类型 用户回复 “hh” 微信自动回复此条消息

        //回复换行的文本消息

        TextMessage textMessage = new TextMessage();

        textMessage.setToUserName(fromUserName);

        textMessage.setFromUserName(toUserName);

        textMessage.setCreateTime(new Date().getTime());

        textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);

        textMessage.setFuncFlag(0);

        //回复用户的换行字符串 \n表示换行

        StringBuffer buffer = new StringBuffer();

        if(weixinContent.equals("hh")){//如果用户发送”hh“

        buffer.append("欢迎访问").append("\n");

        buffer.append("微信jsapi测试界面").append("\n\n");

        buffer.append("回复'hh'二字即可能显示此条消息");

        }else{

        buffer.append("您好我是V型知识库");

        }

        textMessage.setContent(buffer.toString());

        respMessage = MessageUtil.textMessageToXml(textMessage);//转换成xml格式

        }

        // 响应回复消息

        PrintWriter out = response.getWriter();

        out.print(respMessage);

        out.close();

         }catch(Exception e){

          e.printStackTrace();

         }

    }

}

MessageUtil工具类

package com.test.util;

import java.io.InputStream;

import java.io.Writer;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;

import org.dom4j.Element;

import org.dom4j.io.SAXReader;

import com.test.message.resp.Article;

import com.test.message.resp.MusicMessage;

import com.test.message.resp.NewsMessage;

import com.test.message.resp.TextMessage;

import com.thoughtworks.xstream.XStream;

import com.thoughtworks.xstream.core.util.QuickWriter;

import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;

import com.thoughtworks.xstream.io.xml.XppDriver;

/**

 * 消息工具类

 */

public class MessageUtil {

    /**

     * 返回消息类型:文本

     */

    public static final String RESP_MESSAGE_TYPE_TEXT = "text";

    /**

     * 返回消息类型:音乐

     */

    public static final String RESP_MESSAGE_TYPE_MUSIC = "music";

    /**

     * 返回消息类型:图文

     */

    public static final String RESP_MESSAGE_TYPE_NEWS = "news";

    /**

     * 请求消息类型:文本

     */

    public static final String REQ_MESSAGE_TYPE_TEXT = "text";

    /**

     * 请求消息类型:图片

     */

    public static final String REQ_MESSAGE_TYPE_IMAGE = "image";

    /**

     * 请求消息类型:链接

     */

    public static final String REQ_MESSAGE_TYPE_LINK = "link";

    /**

     * 请求消息类型:地理位置

     */

    public static final String REQ_MESSAGE_TYPE_LOCATION = "location";

    /**

     * 请求消息类型:音频

     */

    public static final String REQ_MESSAGE_TYPE_VOICE = "voice";

    /**

     * 请求消息类型:推送

     */

    public static final String REQ_MESSAGE_TYPE_EVENT = "event";

    /**

     * 事件类型:subscribe(订阅)

     */

    public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";

    /**

     * 事件类型:unsubscribe(取消订阅)

     */

    public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";

    /**

     * 事件类型:CLICK(自定义菜单点击事件)

     */

    public static final String EVENT_TYPE_CLICK = "CLICK";

    /**

     * 解析微信发来的请求(XML)

     * 

     * @param request

     * @return

     * @throws Exception

     */

    @SuppressWarnings("unchecked")

    public static Map parseXml(HttpServletRequest request) throws Exception {

        // 将解析结果存储在HashMap中

        Map map = new HashMap();

        // 从request中取得输入流

        InputStream inputStream = request.getInputStream();

        // 读取输入流

        SAXReader reader = new SAXReader();

        Document document = reader.read(inputStream);

        // 得到xml根元素

        Element root = document.getRootElement();

        // 得到根元素的所有子节点

        List elementList = root.elements();

        // 遍历所有子节点

        for (Element e : elementList) {

            map.put(e.getName(), e.getText());

        }

        // 释放资源

        inputStream.close();

        inputStream = null;

        return map;

    }

    /**

     * 文本消息对象转换成xml  

     * @param textMessage 文本消息对象

     * @return xml

     */

    public static String textMessageToXml(TextMessage textMessage) {

        xstream.alias("xml", textMessage.getClass());

        return xstream.toXML(textMessage);

    }

    /**

     * 音乐消息对象转换成xml  

     * @param musicMessage 音乐消息对象

     * @return xml

     */

    public static String musicMessageToXml(MusicMessage musicMessage) {

        xstream.alias("xml", musicMessage.getClass());

        return xstream.toXML(musicMessage);

    }

    /**

     * 图文消息对象转换成xml  

     * @param newsMessage 图文消息对象

     * @return xml

     */

    public static String newsMessageToXml(NewsMessage newsMessage) {

        xstream.alias("xml", newsMessage.getClass());

        xstream.alias("item", new Article().getClass());

        return xstream.toXML(newsMessage);

    }

    /**

     * 扩展xstream,使其支持CDATA块  

     * @date

     */

    private static XStream xstream = new XStream(new XppDriver() {

        public HierarchicalStreamWriter createWriter(Writer out) {

            return new PrettyPrintWriter(out) {

                // 对所有xml节点的转换都增加CDATA标记

                boolean cdata = true;

                @SuppressWarnings("unchecked")

                public void startNode(String name, Class clazz) {

                    super.startNode(name, clazz);

                }

                protected void writeText(QuickWriter writer, String text) {

                    if (cdata) {

                        writer.write("

writer.write(text);

writer.write("]]>");

                    } else {

                        writer.write(text);

                    }

                }

            };

        }

    });

}

TextMessage代码

package com.test.message.resp;

public class TextMessage extends BaseMessage {

    // 回复的消息内容

    private String Content;

    public String getContent() {

        return Content;

    }

    public void setContent(String content) {

        Content = content;

    }

}

BaseMessage代码

package com.test.message.resp;

/**

 * 消息基类(公众帐号 -> 普通用户)

 */

public class BaseMessage {

    // 接收方帐号(收到的OpenID)

    private String ToUserName;

    // 开发者微信号

    private String FromUserName;

    // 消息创建时间 (整型)

    private long CreateTime;

    // 消息类型(text/music/news)

    private String MsgType;

    // 位0x0001被标志时,星标刚收到的消息

    private int FuncFlag;

    public String getToUserName() {

        return ToUserName;

    }

    public void setToUserName(String toUserName) {

        ToUserName = toUserName;

    }

    public String getFromUserName() {

        return FromUserName;

    }

    public void setFromUserName(String fromUserName) {

        FromUserName = fromUserName;

    }

    public long getCreateTime() {

        return CreateTime;

    }

    public void setCreateTime(long createTime) {

        CreateTime = createTime;

    }

    public String getMsgType() {

        return MsgType;

    }

    public void setMsgType(String msgType) {

        MsgType = msgType;

    }

    public int getFuncFlag() {

        return FuncFlag;

    }

    public void setFuncFlag(int funcFlag) {

        FuncFlag = funcFlag;

    }

}

效果如下:

详解微信开发微信jsapi与java初步接入方法

详解微信开发微信jsapi与java初步接入方法

详解微信开发微信jsapi与java初步接入方法

详解微信开发微信jsapi与java初步接入方法

Atas ialah kandungan terperinci 详解微信开发微信jsapi与java初步接入方法. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn