java微信企业号开发之开发模式的开启
程序员文章站
2024-03-13 08:17:27
首先说微信企业号的开发模式分为:编辑模式(普通模式)和开发模式(回调模式) ,在编辑模式下,只能做简单的自定义菜单和自动回复消息,要想实现其他功能还得开启开发者模式。
一...
首先说微信企业号的开发模式分为:编辑模式(普通模式)和开发模式(回调模式) ,在编辑模式下,只能做简单的自定义菜单和自动回复消息,要想实现其他功能还得开启开发者模式。
一、编辑模式和开发模式对消息的处理流程
1.编辑模式下,所有的业务流程都配置在微信服务器上,由它处理
2.开发模式,消息通过第三方服务器处理,最后经过微信服务器把消息发送给用户
开发模式能处理的消息比编辑模式多,所以要先开启开发模式才能开发更多功能。
二、开发模式的开启
在回调模式下,企业不仅可以主动调用企业号接口,还可以接收用户的消息或事件。接收的信息使用xml数据格式、utf8编码,并以aes方式加密。
1.开启回调模式后要配置参数如下:
其中url是要访问的servlet,token和encodingaeskey是随机获取的,但要和项目中保持一致。
2.验证url的有效性
当你提交以上信息时,企业号将发送get请求到填写的url上,get请求携带四个参数,企业在获取时需要做urldecode处理,否则会验证不成功。
3.代码
coreservlet1类
public class coreservlet1 extends httpservlet { private static final long serialversionuid = 4440739483644821986l; string stoken = "weixincourse"; string scorpid = "wxe510946434680dab"; string sencodingaeskey = "djlyzxgkiwresiw2vnv9dsr7hss7uswdfnwa8q1ove1"; public void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { wxbizmsgcrypt wxcpt; try { wxcpt = new wxbizmsgcrypt(stoken, sencodingaeskey, scorpid); string sverifymsgsig = request.getparameter("msg_signature"); string sverifytimestamp = request.getparameter("timestamp"); string sverifynonce = request.getparameter("nonce"); string sverifyechostr = request.getparameter("echostr"); string sechostr; sechostr = wxcpt.verifyurl(sverifymsgsig, sverifytimestamp, sverifynonce, sverifyechostr); system.out.println("verifyurl echostr: " + sechostr); printwriter out = response.getwriter(); out.print(sechostr); out.close(); out = null; } catch (aesexception e1) { e1.printstacktrace(); } } }
工具类:
/** * 对公众平台发送给公众账号的消息加解密示例代码. * * @copyright copyright (c) 1998-2014 tencent inc. */ // ------------------------------------------------------------------------ /** * 针对org.apache.commons.codec.binary.base64, * 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本) * 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi */ package com.qq.weixin.mp.aes; import java.nio.charset.charset; import java.util.arrays; import java.util.random; import javax.crypto.cipher; import javax.crypto.spec.ivparameterspec; import javax.crypto.spec.secretkeyspec; import org.apache.commons.codec.binary.base64; /** * 提供接收和推送给公众平台消息的加解密接口(utf8编码的字符串). * <ol> * <li>第三方回复加密消息给公众平台</li> * <li>第三方收到公众平台发送的消息,验证消息的安全性,并对消息进行解密。</li> * </ol> * 说明:异常java.security.invalidkeyexception:illegal key size的解决方案 * <ol> * <li>在官方网站下载jce无限制权限策略文件(jdk7的下载地址: * http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html</li> * <li>下载后解压,可以看到local_policy.jar和us_export_policy.jar以及readme.txt</li> * <li>如果安装了jre,将两个jar文件放到%jre_home%\lib\security目录下覆盖原来的文件</li> * <li>如果安装了jdk,将两个jar文件放到%jdk_home%\jre\lib\security目录下覆盖原来文件</li> * </ol> */ public class wxbizmsgcrypt { static charset charset = charset.forname("utf-8"); base64 base64 = new base64(); byte[] aeskey; string token; string corpid; /** * 构造函数 * @param token 公众平台上,开发者设置的token * @param encodingaeskey 公众平台上,开发者设置的encodingaeskey * @param corpid 企业的corpid * * @throws aesexception 执行失败,请查看该异常的错误码和具体的错误信息 */ public wxbizmsgcrypt(string token, string encodingaeskey, string corpid) throws aesexception { if (encodingaeskey.length() != 43) { throw new aesexception(aesexception.illegalaeskey); } this.token = token; this.corpid = corpid; aeskey = base64.decodebase64(encodingaeskey + "="); } /** * 对密文进行解密. * * @param text 需要解密的密文 * @return 解密得到的明文 * @throws aesexception aes解密失败 */ string decrypt(string text) throws aesexception { byte[] original; try { // 设置解密模式为aes的cbc模式 cipher cipher = cipher.getinstance("aes/cbc/nopadding"); secretkeyspec key_spec = new secretkeyspec(aeskey, "aes"); ivparameterspec iv = new ivparameterspec(arrays.copyofrange(aeskey, 0, 16)); cipher.init(cipher.decrypt_mode, key_spec, iv); // 使用base64对密文进行解码 byte[] encrypted = base64.decodebase64(text); // 解密 original = cipher.dofinal(encrypted); } catch (exception e) { e.printstacktrace(); throw new aesexception(aesexception.decryptaeserror); } string xmlcontent, from_corpid; try { // 去除补位字符 byte[] bytes = pkcs7encoder.decode(original); // 分离16位随机字符串,网络字节序和corpid byte[] networkorder = arrays.copyofrange(bytes, 16, 20); int xmllength = recovernetworkbytesorder(networkorder); xmlcontent = new string(arrays.copyofrange(bytes, 20, 20 + xmllength), charset); from_corpid = new string(arrays.copyofrange(bytes, 20 + xmllength, bytes.length), charset); } catch (exception e) { e.printstacktrace(); throw new aesexception(aesexception.illegalbuffer); } // corpid不相同的情况 if (!from_corpid.equals(corpid)) { throw new aesexception(aesexception.validatecorpiderror); } return xmlcontent; } /** * 验证url * @param msgsignature 签名串,对应url参数的msg_signature * @param timestamp 时间戳,对应url参数的timestamp * @param nonce 随机串,对应url参数的nonce * @param echostr 随机串,对应url参数的echostr * * @return 解密之后的echostr * @throws aesexception 执行失败,请查看该异常的错误码和具体的错误信息 */ public string verifyurl(string msgsignature, string timestamp, string nonce, string echostr) throws aesexception { string signature = sha1.getsha1(token, timestamp, nonce, echostr); if (!signature.equals(msgsignature)) { throw new aesexception(aesexception.validatesignatureerror); } string result = decrypt(echostr); return result; } } /** * 对公众平台发送给公众账号的消息加解密示例代码. * * @copyright copyright (c) 1998-2014 tencent inc. */ // ------------------------------------------------------------------------ package com.qq.weixin.mp.aes; import java.security.messagedigest; import java.util.arrays; /** * sha1 class * * 计算公众平台的消息签名接口. */ class sha1 { /** * 用sha1算法生成安全签名 * @param token 票据 * @param timestamp 时间戳 * @param nonce 随机字符串 * @param encrypt 密文 * @return 安全签名 * @throws aesexception */ public static string getsha1(string token, string timestamp, string nonce, string encrypt) throws aesexception { try { string[] array = new string[] { token, timestamp, nonce, encrypt }; stringbuffer sb = new stringbuffer(); // 字符串排序 arrays.sort(array); for (int i = 0; i < 4; i++) { sb.append(array[i]); } string str = sb.tostring(); // sha1签名生成 messagedigest md = messagedigest.getinstance("sha-1"); md.update(str.getbytes()); byte[] digest = md.digest(); stringbuffer hexstr = new stringbuffer(); string shahex = ""; for (int i = 0; i < digest.length; i++) { shahex = integer.tohexstring(digest[i] & 0xff); if (shahex.length() < 2) { hexstr.append(0); } hexstr.append(shahex); } return hexstr.tostring(); } catch (exception e) { e.printstacktrace(); throw new aesexception(aesexception.computesignatureerror); } } } class pkcs7encoder { static charset charset = charset.forname("utf-8"); static int block_size = 32; /** * 删除解密后明文的补位字符 * * @param decrypted 解密后的明文 * @return 删除补位字符后的明文 */ static byte[] decode(byte[] decrypted) { int pad = (int) decrypted[decrypted.length - 1]; if (pad < 1 || pad > 32) { pad = 0; } return arrays.copyofrange(decrypted, 0, decrypted.length - pad); } }
三、总结
企业通过参数msg_signature对请求进行校验,如果确认此次get请求来自企业号,那么企业应用对echostr参数解密并原样返回echostr明文(不能加引号),则接入验证生效,回调模式才能开启。开启后一些功能会陆续实现,敬请期待!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Java环境变量配置教程
下一篇: php获取excel文件数据