微信公众号开发接入
微信公众号开发
准备工作
你要有一个微信公众号,一个内网穿透工具
相关网站
- 微信公众号:https://mp.weixin.qq.com/
- 官网文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
需要资料
- 服务器配置:设置与开发-->基本配置-->服务器配置
- token:3-32字符,自己生成配置到服务器配置
- 公网 IP:云服务器一般都有公网IP
- 内网穿透工具:本地测试需要穿透,否则无法对接。花生壳、natapp 等自行百度
注意事项
- 请求URL超时,说明内网穿透有问题
- 微信验证消息和推送消息事件接口是同一地址,验证消息是
GET
请求 ,事件推送消息是POST
。 - 验证成功接口需要给微信原样返回随机字符串(echostr)内容,否则配置失败
- 响应类型(Content-Type) 一定要是
text/plan
- 切记自己对接的系统要是有权鉴,一定要放行微信消息验证接口
代码示例
消息验证
public void pushGet(HttpServletRequest request, HttpServletResponse response) { String signature = request.getParameter("signature"); // 签名 String echostr = request.getParameter("echostr"); // 随机字符串 String timestamp = request.getParameter("timestamp"); // 时间戳 String nonce = request.getParameter("nonce"); // 随机数 log.debug("signature:{}", signature); log.debug("echostr:{}", echostr); log.debug("timestamp:{}", timestamp); log.debug("nonce:{}", nonce); System.out.println("signature:" + signature); String sha1 = getSHA1(token, timestamp, nonce); System.out.println("sha1:" + sha1); if (sha1.equals(signature)) { log.debug("成功"); this.responseText(echostr, response); } }
事件推送
public void pushPost(HttpServletRequest request, HttpServletResponse response) { String signature = request.getParameter("signature"); // 签名 String timestamp = request.getParameter("timestamp"); // 时间戳 String nonce = request.getParameter("nonce"); // 随机数 String sha1 = getSHA1(token, timestamp, nonce); if (sha1.equals(signature)) { Map<String, Object> map = null; try { map = XmlUtil.parseXMLToMap(request.getInputStream()); } catch (IOException e) { e.printStackTrace(); } log.debug("事件消息体:{}", map); this.responseText("", response); // 回复空串,微信服务器不会对此作任何处理 } }
完整代码
import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.security.MessageDigest; import java.util.*; /** * @description: 微信配置 * @author: Mr.Fang * @create: 2023-05-26 **/ @Api(tags = "微信配置") @Slf4j @RestController @RequestMapping("/wx/") public class WxController { String token="78******23"; @ApiOperation(value = "微信 token URL 验证") @GetMapping(value = "push") public void pushGet(HttpServletRequest request, HttpServletResponse response) { String signature = request.getParameter("signature"); // 签名 String echostr = request.getParameter("echostr"); // 随机字符串 String timestamp = request.getParameter("timestamp"); // 时间戳 String nonce = request.getParameter("nonce"); // 随机数 log.debug("signature:{}", signature); log.debug("echostr:{}", echostr); log.debug("timestamp:{}", timestamp); log.debug("nonce:{}", nonce); System.out.println("signature:" + signature); String sha1 = getSHA1(token, timestamp, nonce); System.out.println("sha1:" + sha1); if (sha1.equals(signature)) { log.debug("成功"); this.responseText(echostr, response); } } @ApiOperation(value = "接收微信事件") @PostMapping(value = "push") public void pushPost(HttpServletRequest request, HttpServletResponse response) { String signature = request.getParameter("signature"); // 签名 String timestamp = request.getParameter("timestamp"); // 时间戳 String nonce = request.getParameter("nonce"); // 随机数 String sha1 = getSHA1(token, timestamp, nonce); if (sha1.equals(signature)) { Map<String, Object> map = null; try { // input 流返回是 xml 格式 这里转 map 了 map = XmlUtil.parseXMLToMap(request.getInputStream()); } catch (IOException e) { e.printStackTrace(); } log.debug("事件消息体:{}", map); this.responseText("", response); // 回复空串,微信服务器不会对此作任何处理 } } /** * 返回响应结果 * * @param text 响应内容 * @param response */ public void responseText(String text, HttpServletResponse response) { response.setCharacterEncoding("UTF-8"); response.setContentType("text/plan;charset=UTF-8"); PrintWriter writer = null; try { writer = response.getWriter(); } catch (IOException e) { e.printStackTrace(); } writer.write(text); writer.flush(); writer.close(); } /** * 用SHA1算法生成安全签名 * * @param token 票据 * @param timestamp 时间戳 * @param nonce 随机字符串 * @return 安全签名 */ public String getSHA1(String token, String timestamp, String nonce) { try { String[] array = new String[]{token, timestamp, nonce}; StringBuffer sb = new StringBuffer(); // 字符串排序 Arrays.sort(array); for (int i = 0; i < 3; 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(); } return null; } }
响应结果
消息验证
signature:207e05105427e1203e769245b3860212c0ffcc56 echostr:5692172970033782203 timestamp:1685068850 nonce:499790541 signature:207e05105427e1203e769245b3860212c0ffcc56 sha1:207e05105427e1203e769245b3860212c0ffcc56 成功
事件推送
打开公众号发送消息,接口就可以获取到推送事件消息内容了
{"Content":"嘻嘻嘻","CreateTime":"1685068967","ToUserName":"gh_2121212a95","FromUserName":"333333333nSg8OlaSuB0d-f8FKZo","MsgType":"text","MsgId":"24124387253374797"}
其他信息
公众号配置
内网穿透
哇!又赚了一天人民币
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 在缓慢中沉淀,在挑战中重生!2024个人总结!
· 大人,时代变了! 赶快把自有业务的本地AI“模型”训练起来!
· 从 Windows Forms 到微服务的经验教训