重庆小潘seo博客

当前位置:首页 > 重庆网络营销 > 小潘杂谈 >

小潘杂谈

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

时间:2020-09-16 23:00:10 作者:重庆seo小潘 来源:
参数名http://www.php.cn/wiki/835.html target=_blankwidth=346 valign=top style=word-break:break-all 描述appId应用ID 登录微信公众号管理平台可查询timestamp 必填,生成签名的时间戳 nonceStr必填,生成签名的随机串 signature必填,签名,见附录1 上

参数名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. <br>

*/

public void destroy() {

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

// Put your code here

}

/**

* The doGet method of the servlet. <br>

*

* 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<String,String> 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. <br>

*

* 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. <br>

*

* @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代码

<servlet>

<description>This is the description of my J2EE component</description>

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

<servlet-name>WxJsAPIServlet</servlet-name>

<servlet-class>com.test.WxJsAPIServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>WxJsAPIServlet</servlet-name>

<url-pattern>/wxJsAPIServlet</url-pattern>

</servlet-mapping>

生成签名算法类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<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("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<String, String> 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");

returnticket;

}

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+"/";

%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<base href="<%=basePath%>">

<title>微信jsapi测试-V型知识库</title>

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

<script alt="详解微信开发微信jsapi与java初步接入方法" src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js"> </script>

</head>

<body>

<center><h3>欢迎来到微信jsapi测试界面-V型知识库</h3></center>

<br>

<p>timestamp:${ timestamp}</p>

<p>nonceStr:${ nonceStr}</p>

<p>signature:${ signature}</p>

<p>appId:${ appId}</p>

<input type="button" value="upload" onclick="uploadImg();"/>

<input type="button" value="获取当前位置" onclick="getLocation();"/>

<br>

<script type="text/javascript">

wx.config({

debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。

appId: '${appId}', // 必填,公众号的唯一标识

timestamp: '${ timestamp}' , // 必填,生成签名的时间戳

nonceStr: '${ nonceStr}', // 必填,生成签名的随机串

signature: '${ signature}',// 必填,签名,见附录1

jsApiList: ['chooseImage','getLocation','openLocation'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2

});

wx.ready(function(){

alert("ready");

});

wx.error(function (res) {

alert("调用微信jsapi返回的状态:"+res.errMsg);

});

function uploadImg() {

wx.checkJsApi({

jsApiList: ['chooseImage','openLocation','getLocation'], // 需要检测的JS接口列表,所有JS接口列表见附录2,

success: function(res) {

// 以键值对的形式返回,可用的api值true,不可用为false

// 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}

alert(res);

wx.chooseImage({

count: 1, // 默认9

sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有

sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有

success: function (res) {

var localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片

alert(localIds);

}

});

}

});

}

function getLocation() {

var latitude = "";

var longitude = "";

wx.getLocation({

type: 'gcj02', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'

success: function (res) {

latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90

longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。

var speed = res.speed; // 速度,以米/每秒计

var accuracy = res.accuracy; // 位置精度

wx.openLocation({

latitude: latitude, // 纬度,浮点数,范围为90 ~ -90

longitude: longitude, // 经度,浮点数,范围为180 ~ -180。

name: '你当前的位置', // 位置名

address: 'currentLocation', // 地址详情说明

scale: 26, // 地图缩放级别,整形值,范围从1~28。默认为最大

infoUrl: '' // 在查看位置界面底部显示的超链接,可点击跳转

});

}

});

}

</script>

</body>

</html>

测试场景:打开微信公众号,点击菜单回复带有请求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<String, String> 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("<a href="http://www.vxzsk.com/weChat/wxJsAPIServlet">微信jsapi测试界面</a>").append("nn");

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<String, String> parseXml(HttpServletRequest request) throws Exception {

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

Map<String, String> map = new HashMap<String, String>();

// 从request中取得输入流

InputStream inputStream = request.getInputStream();

// 读取输入流

SAXReader reader = new SAXReader();

Document document = reader.read(inputStream);

// 得到xml根元素

Element root = document.getRootElement();

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

List<Element> 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("<![CDATA[");

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初步接入方法以上就是详解微信开发微信jsapi与java初步接入方法的详细内容,更多请关注小潘博客其它相关文章!