这篇文章主要为大家详细介绍了java微信企业号开发之开发模式的开启方法,感兴趣的小伙伴们可以参考一下

首先说微信企业号的开发模式分为:编辑模式(普通模式)和开发模式(回调模式) ,在编辑模式下,只能做简单的自定义菜单和自动回复消息,要想实现其他功能还得开启开发者模式。

一、编辑模式和开发模式对消息的处理流程

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://www.php.cn/

*/

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编码的字符串).

*

*

第三方回复加密消息给公众平台

*

第三方收到公众平台发送的消息,验证消息的安全性,并对消息进行解密。

*

* 说明:异常java.security.InvalidKeyException:illegal Key Size的解决方案

*

*

在官方网站下载JCE无限制权限策略文件(JDK7的下载地址:

* http://www.php.cn/;/li>

*

下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt

*

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

*

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

*

*/

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企业号开发教程_详解java微信企业号开发之开发模式的开启步骤相关推荐

  1. java 配置文件的路径_详解java配置文件的路径问题

    详解java配置文件的路径问题 详解java配置文件的路径问题 各种语言都有自己所支持的配置文件,配置文件中有很多变量是经常改变的.不将程序中的各种变量写死,这样能更方便地脱离程序本身去修改相关变量设 ...

  2. java注解 源码_详解Java注解教程及自定义注解

    详解Java注解教程及自定义注解 更新时间:2016-02-26 11:47:06   作者:佚名   我要评论(0) Java注解提供了关于代码的一些信息,但并不直接作用于它所注解的代码内容.在这个 ...

  3. java的注解方式_详解Java注解的实现与使用方法

    详解Java注解的实现与使用方法 Java注解是java5版本发布的,其作用就是节省配置文件,增强代码可读性.在如今各种框架及开发中非常常见,特此说明一下. 如何创建一个注解 每一个自定义的注解都由四 ...

  4. java使用集合存储过程_详解java调用存储过程并封装成map

    详解java调用存储过程并封装成map 发布于 2020-5-1| 复制链接 摘记: 详解java调用存储过程并封装成map           本文代码中注释写的比较清楚不在单独说明,希望能帮助到大 ...

  5. java同步异步调用_详解java 三种调用机制(同步、回调、异步)

    1:同步调用:一种阻塞式调用,调用方要等待对方执行完毕才返回,jsPwwCe它是一种单向调用 2:回调:一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口: 3:异步调用:一种类似消 ...

  6. java 死锁 内存消耗_详解Java中synchronized关键字的死锁和内存占用问题

    先看一段synchronized 的详解: synchronized 是 java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并 ...

  7. java 线程一直运行状态_详解JAVA 线程-线程的状态有哪些?它是如何工作的?

    线程(Thread)是并发编程的基础,也是程序执行的最小单元,它依托进程而存在. 一个进程中可以包含多个线程,多线程可以共享一块内存空间和一组系统资源,因此线程之间的切换更加节省资源.更加轻量化,也因 ...

  8. java集合for循环_详解Java中list,set,map的遍历与增强for循环

    详解Java中list,set,map的遍历与增强for循环 Java集合类可分为三大块,分别是从Collection接口延伸出的List.Set和以键值对形式作存储的Map类型集合. 关于增强for ...

  9. java访问本地文件_详解Java读取本地文件并显示在JSP文件中

    详解Java读取本地文件并显示在JSP文件中 当我们初学IMG标签时,我们知道通过设置img标签的src属性,能够在页面中显示想要展示的图片.其中src的值,可以是磁盘目录上的绝对,也可以是项目下的相 ...

  10. java的自动装箱_详解Java 自动装箱与拆箱的实现原理

    详解Java 自动装箱与拆箱的实现原理 发布于 2020-7-4| 复制链接 本篇文章主要介绍了详解Java 自动装箱与拆箱的实现原理,小妖觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小妖 ...

最新文章

  1. 让VisualSVN Server支持匿名访问
  2. windowswps怎么以文件形式发送_一个招投标项目出现了履约争议,但是没有签订合同,怎么办?...
  3. 为你的集成需求选择合适的ESB
  4. IBM斥资3.6亿美元建史上最复杂云计算中心
  5. python cpython关系_第3篇:CPython内部探究:PyASCIIObject的初始化
  6. 在Python中使用Seaborn和WordCloud可视化YouTube视频
  7. android AVB2.0(六)Super动态分区介绍
  8. 具体的压栈指令,例子
  9. vmware虚拟机克隆后不能联网
  10. TiDB-新一代数据库入门介绍
  11. Python使用颜色块覆盖视频中指定区域的内容
  12. 汇编@data_汇编语言(4)--内存段
  13. 公司绝不会告诉你的20大秘密 转载
  14. 基于JQUERY的WEB在线流程图设计器GOOFLOW 0.6版
  15. 6轴游戏手柄测试python程序
  16. 淘宝天猫融合能拉回“出淘”的用户吗?
  17. ARM Cortex-M0+Kinetis L系列学习笔记_MKL25Z4.h
  18. ppt如何将表格转化为饼图?
  19. Profinet Commander下载方法
  20. cad角度怎么画_女孩都喜欢的公主抱怎么画?各种不同角度公主抱漫画素材绘画教程...

热门文章

  1. ​在线问题反馈模块实战(十二)​:实现图片删除功能
  2. 【雷达与对抗】【2011.07】穿墙超宽带雷达成像
  3. 4399Q版泡泡堂(DEVC++实现+解析)
  4. Centos6系统yum无法使用-最新解决办法
  5. 项目工作绩效数据、项目工作绩效信息、项目工作绩效报告
  6. matlab正序零序负序,史上最完美的图形和公式带你搞懂正序负序零序!
  7. 郑州大学计算机翟雨轩,郑州大学文件-20210331220732.doc-原创力文档
  8. 打造数字化转型IT生态系统的IT管理方法:IT4IT一瞥
  9. Android Studio 配置 Http Proxy
  10. SE5_FALSR超分辨率图像模型移植与测试