您的位置:首页 > 移动开发 > 微信开发

JAVA微信开放平台授权

2016-03-25 09:51 447 查看
刚开发完微信授权接入,这里做个分享,供大家参考。

授权流程可以参照微信官方api,流程图如下:



1.准备工作

导入微信官方的加解密算法(下载地址),之后要做:

(1) 在java官方网站下载JCE无限制权限策略文件(JDK7的下载地址: * http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html)
下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt。

如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件。

如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件。

(2) 修改解密算法。由于微信发来的XML消息体中可能包含ToUserName或AppId,而微信提供的解密算法中的XML节点只有ToUserName一种形式。所以需要修改XMLParse类中的extract方法:

[java] view
plain copy

/**

* 提取出xml数据包中的加密消息

*

* @param xmltext 待提取的xml字符串

* @param element xml中参数名称 可选 "ToUserName","AppId"(自己创建的枚举AnotherElement,有ToUserName和AppId俩个成员)

* @return 提取出的加密消息字符串

* @throws AesException

*/

public static Object[] extract(String xmltext, WXBizMsgCrypt.AnotherElement element) throws AesException {

Object[] result = new Object[3];

try {

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

DocumentBuilder db = dbf.newDocumentBuilder();

StringReader sr = new StringReader(xmltext);

InputSource is = new InputSource(sr);

Document document = db.parse(is);

Element root = document.getDocumentElement();

NodeList nodelist1 = root.getElementsByTagName("Encrypt");

NodeList nodelist2 = root.getElementsByTagName(element.name());

result[0] = 0;

result[1] = nodelist1.item(0).getTextContent();

result[2] = nodelist2.item(0).getTextContent();

return result;

} catch (Exception e) {

e.printStackTrace();

throw new AesException(AesException.ParseXmlError);

}

}

2.流程图代码解释

①⑨授权事件URL接收到微信的请求,包括ticket推送和授权消息通知:

[java] view
plain copy

@Override

public void handleWechatEventPush (HttpServletRequest request){

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

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

String msgSignature = request.getParameter("msg_signature");

StringWriter writer = new StringWriter();

try {

//获得微信发来的加密消息

IOUtils.copy(request.getInputStream(), writer, "UTF-8");

String fromXML = writer.toString();

WXBizMsgCrypt pc = new WXBizMsgCrypt(componentToken, encodingAESKey, componentAppId);

//获得解密后的XML消息体

String result = pc.decryptMsg(msgSignature, timestamp, nonce, fromXML, WXBizMsgCrypt.AnotherElement.AppId);

LOGGER.info(" authorize decrypt result {}", result);

Map<String, String> map = MessageUtil.parseXml(result);

//消息类型

String infoType = map.get("InfoType");

switch (InfoType.valueOf(infoType)) {

//授权成功,可以获得授权码;授权码也可以在流程图⑤中获得,所以可以忽略

case authorized:

break;

//取消授权,可以删除本地保存的已授权公众号

case unauthorized:

String appId = map.get("AuthorizerAppid");

//todo 删除本地授权的公众号

break;

//更新授权,可以更新授权方令牌authorizer_access_token,刷新令牌authorizer_refresh_token,权限集列表等

case updateauthorized:

//todo 更新令牌等

break;

//推送ticket,妥善保存ticket,用于获取component_access_token

case component_verify_ticket:

String ticket = map.get("ComponentVerifyTicket");

//存储ticket

break;

default:

break;

}

} catch (Exception e) {

LOGGER.error(e.toString(), e);

}

}

⑤点击链接后进入授权页如下(切记要配置测试ip地址和保证pre_auth_code有效):完成授权后,会进入redirect_url,可以从url中获取authorization_code和过期时间



⑥⑦⑧获得authorizer_access_token和authorizer_refresh_token。authorizer_access_token和开发微信公众平台的access_token功能一致,可以调用菜单设置等接口;另外还可以获得公众号的基本信息和其他选项设置。

3.代公众号实现消息处理

授权成功后,微信会将消息和事件通知发送到公众号消息与事件接收URL上,与公众号开发者模式不同的是,第三方处理消息和事件通知,需要对数据进行加解密。代码如下:

[java] view
plain copy

@Override

public String thirdPlatformPrecessRequest(HttpServletRequest request, String appId) {

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

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

String msgSignature = request.getParameter("msg_signature");

StringWriter writer = new StringWriter();

try {

IOUtils.copy(request.getInputStream(), writer, "UTF-8");

String fromXML = writer.toString();

WXBizMsgCrypt pc = new WXBizMsgCrypt(componentToken, encodingAESKey, componentAppId);

String result = pc.decryptMsg(msgSignature, timestamp, nonce, fromXML, WXBizMsgCrypt.AnotherElement.ToUserName);//这里传入的是ToUserName,参见上面的准备工作

Map<String, String> resultMap = MessageUtil.parseXml(result);

String respMessage = getRespMessage(resultMap);

return pc.encryptMsg(respMessage, timestamp, nonce);

} catch (Exception e) {

LOGGER.error(e.toString(), e);

return "";

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: