接入微信公共号接口流程

SSM框架接入微信公共号

准备微信服务器项目、数据库

百度云:https://pan.baidu.com/s/1qGkvaYntr2ODlEy2h03k9Q记得配置文件修改正确

把内网映射到外网:在映射软件里cmd进入输入下面第一句命令

ngrok -config=ngrok.cfg -subdomain yygwxtest 80

yygwxtest -->你自己想要的子网域名

80-->监听的80端口

记住导入项目后配置的tomcat端口要一致

显示以下,使用http开头的网址,它被映射到外网上

正式号接入认证

告知微信服务器我的公众号使用那个服务器的相关配置

主要有两大步骤:

1: 先进入公共测试平台认证

url是映射的外网地址,token随便写,但要与基本配置一样

 

IndexContrller的后台打印显示,代码在下面

2认证完才能基本信息配置(点击修改配置)

点击提交会传入几个参数到controller接收:并启用

timestamp 时间戳

nonce 随机数

echostr 随机字符串

signature 微信加密签名

3:验证服务器地址的有效性

验证代码实现

@Controller
@RequestMapping("/index")
public class IndexController {
	/**
	 * 处理微信认证,get提交
	 * 微信公众号的接入验证
	 */
	@RequestMapping(method = RequestMethod.GET)
	public void signature(HttpServletRequest request, HttpServletResponse response) throws Exception {
		System.out.println("index......");
		String token = "weixin";
		String timestamp = request.getParameter("timestamp");//时间戳
		String nonce = request.getParameter("nonce");//随机数
		String echostr = request.getParameter("echostr");//随机字符串
		String signature = request.getParameter("signature");//微信加密签名
		System.out.println(timestamp);
		System.out.println(nonce);
		System.out.println(echostr);
		System.out.println(signature);
		// response.getWriter().print(echostr);//不能直接输出,虽然可以成功提交,但是不能保证请求来自微信
		// 1)将token、timestamp、nonce三个参数进行字典序排序
		String[] arr={token,timestamp,nonce};
		Arrays.sort(arr);
		System.out.println(arr);
		// 2)将三个参数字符串拼接成一个字符串进行sha1加密
		StringBuffer sb=new StringBuffer();
		for (String str : arr) {
			sb.append(str);
		}
		String shaStr = SecurityUtil.sha1(sb.toString());
		// 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
		if(signature.equals(shaStr)){
			System.out.println("验证正常。。。。。");
			//来自于微信:
			response.getWriter().println(echostr);
		}else{
			throw new RuntimeException("非法的请求,不受理。。。。。");
		}
	}
}

sha1加密工具

public class SecurityUtil {
public static String sha1(String str) {
try {
StringBuilder sb = new StringBuilder();
MessageDigest digest = MessageDigest.getInstance("sha1");
    // 放入加密字符串
    digest.update(str.getBytes());
    //进行加密
    byte[] digestMsg = digest.digest();
    // byte转换16进制
    for (byte b : digestMsg) {
        sb.append(String.format("%02x", b));
    }
        return sb.toString();
} catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
}
    return str;
    }
}

可以参考接入指南,开发者工具->开发者文档->开始开发->接入指南

微信公众号交互响应

需要导入Jar包:xmlpull-1.1.3.1.jar ;kxml2-2.3.0.jar

请求解析器工具

package cn.itsource.weixin.utils;
import java.io.Reader;
import java.io.StringReader;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections.map.HashedMap;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
/**
 * 解析xml,使用xmlpullparser
 * @param reader io流
 * @return
 * @throws Exception
 */
public class XmlParserUtils {
public static Map<String, String> parserXml(Reader reader){
    //创建map容器存储解析的数据
    Map<String, String> map=new HashedMap();
try {
    //得到一个xml解析器
    XmlPullParser pullParser = XmlPullParserFactory.newInstance().newPullParser();
//设置解析的输入流
pullParser.setInput(reader);
    /*int START_DOCUMENT = 0; 文档开始
    int END_DOCUMENT = 1; 文档结束
    int START_TAG = 2; 标签开始
    int END_TAG = 3; 标签结束*/
//获取当前的事件类型
int eventType = pullParser.getEventType();
//判断如果不是文档结束的事件类型就一直解析
while(eventType!=XmlPullParser.END_DOCUMENT){
//获取当前标签名称
String tagName = pullParser.getName();
//当标签是开始xml直接跳过,并且是开始事件类型
    if(!"xml".equals(tagName)&&eventType==XmlPullParser.START_TAG){
    //获取当前的值
    String text = pullParser.nextText();
    map.put(tagName, text);
    }
//把下一个节点的状态值赋给eventype
eventType= pullParser.next();
    }
} catch (Exception e) {
    e.printStackTrace();
    }
    return map;
}
//测试
public static void main(String[] args) {
    String xmlData = "<xml><ToUserName><![CDATA[gh_55e547acb71e]]></ToUserName>"
        + "<FromUserName><![CDATA[o9cEf0iZn8aKK4-MKWmqO2fs36xE]]></FromUserName>"
        + "<CreateTime>1505114547</CreateTime>" + "<MsgType><![CDATA[text]]></MsgType>"
        + "<Content><![CDATA[水电费三分]]></Content>" + "            
                                      <MsgId>6464417756529124601</MsgId>" + "</xml>";
  Map<String, String> map = parserXml(new StringReader(xmlData));
      Set<String> keySet = map.keySet();
      for (String key : keySet) {
            System.out.println(key+":"+map.get(key));
   }
}
}

查看文档 点击 开发者工具->开发者文档->消息管理->被动返回消息格式

请求响应两种方式

拼接字符串

@RequestMapping(method = RequestMethod.POST)
public void index(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 获取请求的字节流
ServletInputStream inputStream = request.getInputStream();
    //转换为字符流
InputStreamReader inputStreamReader  = new InputStreamReader(inputStream,"utf-8");
    //得到缓冲流
    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
Map<String, String> map = XmlParserUtils.parserXml(bufferedReader);
    String content = null;
    // 一行一行读取
while ((content = bufferedReader.readLine()) != null) {
    System.out.println(content);
}
//拼接xml字符串响应请求
response.getWriter().println(createXml(map));
}
private String createXml(Map<String, String> map) {
    StringBuffer sBuffer=new StringBuffer();
    sBuffer.append("<xml>");
    sBuffer.append("<ToUserName>"+map.get("FromUserName")+"</ToUserName>");//回馈给谁
    sBuffer.append("<FromUserName>"+map.get("ToUserName")+"</FromUserName>");//从哪里请求来
    sBuffer.append("<CreateTime>"+map.get("CreateTime")+"</CreateTime>");//请求时间
    sBuffer.append("<MsgType>"+map.get("MsgType")+"</MsgType>");//回馈消息类型
if(map.get("MsgType").equals("text")){//回复文本类型
    sBuffer.append("<Content>"+map.get("Content")+"</Content>");
}else if(map.get("MsgType").equals("Image")){//回复图片类型
    sBuffer.append("<Image><MediaId><![CDATA["+map.get("MediaId")+"]]></MediaId></Image>");
}else if(map.get("MsgType").equals("voice")){//回复录音类型
    sBuffer.append("<Voice><MediaId><![CDATA["+map.get("MediaId")+"]]></MediaId></Voice>");
}else if(map.get("MsgType").equals("video")){//回复视频类型 有点小问题
    sBuffer.append("<Video><MediaId><![CDATA["+map.get("MediaId")+"]]></MediaId>"
        + "<Title><![CDATA["+map.get("Title")+"]]></Title>"
        + "<Description><![CDATA["+map.get("description")+"]]></Description>"
        + "</Video>");
}
    sBuffer.append("</xml>");
    return sBuffer.toString();//返回出去
}

Jsp模板返回视图

// 接收请求处理业务 响应回去
@RequestMapping(method = RequestMethod.POST)
public ModelAndView modelAndView(HttpServletRequest request, HttpServletResponse response) throws Exception {
//设置编码问题
response.setContentType("text/html; charset=UTF-8");
//获取字节流
ServletInputStream inputStream = request.getInputStream();
//转换字符流
InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"utf-8");
//缓冲流
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
//调用请求内容解析器工具类解析封装map
Map<String, String> map=XmlParserUtils.parserXml(bufferedReader);
//用于关注向用户提示(手机微信扫自己微信二维码时自动提示)
    String type = map.get("MsgType");
    String eve = map.get("Event");
 //判断是否属于关注事件
if("event".equals(type)&&"subscribe".equals(eve)){
    map.put("Content", "欢迎关注久城公共号,有你更美好");
    map.put("MsgType", "text");
}
    ModelAndView mv = new ModelAndView();//创建
    mv.addObject("map", map); //weixin.jsp可以从map取出
    mv.setViewName("weixin");//xml有视图解析器 会拼接访问地址到WEB-INF/views/weixin.jsp
    return mv;
}
<%@ page contentType="text/xml; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<xml>
<%把返回的xml写到jsp里,响应类型、内容从map取出%>
<ToUserName><![CDATA[${map['FromUserName']}]]></ToUserName>
<FromUserName><![CDATA[${map['ToUserName']}]]></FromUserName>
<CreateTime><![CDATA[${map['CreateTime']}]]></CreateTime>
<MsgType><![CDATA[${map['MsgType']}]]></MsgType>
<%判断响应给用户信息类型%>
<c:choose>
	<c:when test="${map['MsgType']=='image'}">
		<Image>
		    <MediaId><![CDATA[${map['MediaId']}]]></MediaId>
		</Image>
	</c:when>
	<c:when test="${map['MsgType']=='voice'}">
		<Voice>
		    <MediaId><![CDATA[${map['MediaId']}]]></MediaId>
		</Voice>
	</c:when>
	<c:when test="${map['MsgType']=='video'}">
		<Video>
			<MediaId><![CDATA[${map['MediaId']}]]></MediaId>
			<Title><![CDATA[${map['Title']}]]></Title>
			<Description><![CDATA[${map['Description']}]]></Description>
		</Video> 
	</c:when>
	<c:otherwise>
	   <Content><![CDATA[${map['Content']}]]></Content>
	</c:otherwise>
</c:choose> 
</xml>

测试 在公共测试开发平台扫码测试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值