1.1 在微信公众平台中的配置
在你刚申请公众号之后你还不是开发者,需要你在微信公众平台的基本配置里面授权成为开发者
授权之后你就会看到这样的界面:
在这个页面里面拿到开发时所必要的信息:appid、appsecret、
获取appsecret需要点击启用后通过管理员或者长期运营者授权之后才可以查看,授权之后你会看到下面这样的页面,你需要把appsecret保存起来以便于后续开发。
在查看appsecret之后会出现ip白名单的选项:
点击配置ip白名单,ip白名单里面填写的ip是你当前服务器的网络ip可以通过腾讯的提供的http://ip.qq.com进行查看。
Ip白名单的作用:在后续创建菜单获取access_token的时候需要用到,还有在支付,调取相册,回复模板消息等都需要用到,如果ip白名单配置的和你实际服务器上的不一致,以上的功能都无法使用。切记这个也是个坑
以上三个参数获取(appid、appsecret)配好(ip白名单)后就需要对接口进行配置了。
这里需要填写URL和Token两个值。URL指的是能够接收处理微信服务器发送的GET/POST请求的地址,并且是已经存在的,现在就能够在浏览器访问到的地址,这就要求我们先把公众帐号后台处理程序开发好(至少应该完成了对GET请求的处理)并部署在公网服务器上。在接口配置信息中的Token就要填写什么值,两边保持一致即可,没有其他要求,建议用项目名称、公司名称缩写等,我在这里用的是项目名称weixinCourse。也就是说要完成接口配置,只需要先完成微信服务器的GET请求处理就可以?是的。 那这是为什么呢?因为这是微信公众平台接口中定义的。
具体请参考API文档-消息接口-消息接口指南中的网址接入部分。文档连接如下:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432
上面写的很清楚,其实你只要能理解上面在说什么就OK了,至于怎么编写相关代码,我已经帮你完成了,请继续往下看。
1.2创建公众号后台接口程序
首先创建一个web项目,在web项目中依赖进去Spring+Springmvc+SpringDataJpa+Hibernate+mysql+log4日志依赖(框架和数据库根据实际情况来我这里用的是这些框架)。
注:依赖就不附上讲解了,这里主要以微信公众号开发为主。
直接上代码:
首先创建一个核心处理类,核心处理类的请求路径必须要和你在微信公众号的基本配置下面服务器配置中的请求路径一致(下图红色框内的请求路径配置一致),否则校验不会通过,校验的时候微信会给你在下图中配置的服务器地址发送一个get请求进行校验。
然后在该类写上get,和post的请求方法,你在微信公众号配置或者修改基本配置中的服务器配置完成后点击提交的时候微信会给你配置的url发送一个get请求,请求的带过来的数有四个(signature,timestamp,nonce,echostr)程序里面通过这四个参数来判断当前请求是否是微信发送过来的,是就原样返回echostr 不是就把传过来的参数打印成日志并给出提示,如下图所示:
下面代码是对微信传来的参数验证工具类,这里需要你在公众号服务器配置中配置的token来进行验证
注意:程序中的token必须要和服务器配置中的保持一致,不然配置会失败
package com.xing.payment.weixinUtils.Util;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
/**
* 请求校验工具类
*
* @author xr
* @date 2018-05-28
*/
@Component
public class SignUtil {
// 与接口配置信息中的Token要一致
private static String token = "";
@Value("${server.token}")
public void setToken(String token) {
SignUtil.token = token;
}
/**
* 验证签名
*
* @param signature
* @param timestamp
* @param nonce
* @return
*/
public static boolean checkSignature(String signature, String timestamp, String nonce) {
String[] arr = new String[] { token, timestamp, nonce };
// 将token、timestamp、nonce三个参数进行字典序排序
Arrays.sort(arr);
StringBuilder content = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
MessageDigest md = null;
String tmpStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
// 将三个参数字符串拼接成一个字符串进行sha1加密
byte[] digest = md.digest(content.toString().getBytes());
tmpStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
content = null;
// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信
return tmpStr !=null ?
tmpStr.equals(signature.toUpperCase()) :false;
}
/**
* 将字节数组转换为十六进制字符串
*
* @param byteArray
* @return
*/
public static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
/**
* 将字节转换为十六进制字符串
*
* @param mByte
* @return
*/
private static String byteToHexStr(byte mByte) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char[] tempArr = new char[2];
tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
}
当把get请求写好后就可以点击提交了如下图所示:
成功会给出这个提示:
到这里,接口配置、开发模式的开启就都完成了,接下来要讲的就是如何接收、处理、响应由微信服务器转发的用户发送给公众帐号的消息,也就是完成Post请求方法的编写
以下是post,get请求的完整代码:
package com.xing.payment.weixinUtils.Controller;
import com.xing.payment.weixinUtils.Service.MessageCoreService;
import com.xing.payment.weixinUtils.Util.SignUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
/**
* 核心请求处理类
* @author xr
* @date 2018-05-29
*/
@Controller
@RequestMapping("/wechat/portal")
@Slf4j
public class WechatController {
@Autowired
private MessageCoreService messageCoreService;
/**
* 确认请求来自微信服务器
* @param signature 微信加密签名
* @param timestamp 时间戳
* @param nonce 随机数
* @param echostr 随机字符串
* @return echostr
*/
@RequestMapping(method = {RequestMethod.GET})
@ResponseBody
public String doGet(
@RequestParam(value = "signature",required = false) String signature,
@RequestParam(value = "timestamp",required = false) String timestamp,
@RequestParam(value = "nonce",required = false) String nonce,
@RequestParam(value = "echostr",required = false) String echostr) {
log.info("\n接收到来自微信服务器的认证消息:[{}, {},{},{}]", signature,timestamp, nonce, echostr);
System.err.println("echostr值是:"+echostr);
// 通过检验signature对请求进行校验,若校验成功则原样返回 echostr,表示接入成功,否则接入失败
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
return echostr;
}
log.info("请求失败:\n接收到来自微信服务器的认证消息:[{}, {}, {}, {}]", signature,
timestamp, nonce, echostr);
return "请求非法";
}
/**
* 处理微信服务器发来的消息
* @return
*/
@RequestMapping(method={RequestMethod.POST},produces="application/xml; charset=UTF-8")
@ResponseBody
public String dopost(HttpServletRequest request) throws UnsupportedEncodingException {
// 调用核心业务类接收消息、处理消息
String respMessage = messageCoreService.processRequest(request);
//响应消息
return respMessage;
}
}
post请求主要用于处理用户想公众号发送的消息:
可以通过该链接进行查看微信文档,主要关注下图中红框内的两项:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140453