springMVC中微信公众平台开发

码农的世界

期待各位码友在欣赏我的无私创作之时,也请大家多多支持我码农的世界,谢谢各位!

service

package cn.bluemobi.service;

import java.util.Arrays;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.bluemobi.entity.weixin.CheckModel;
import cn.bluemobi.util.sha1;

/**
 * Description: <br/>
 * Date: 2015年7月8日 下午12:05:54 <br/>
 * 
 * @author fang
 * @version
 * @see
 */
@Service
public class TokenService {
    /**
     * 微信开发者验证
     * 
     * @param wxAccount
     * 
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @return
     */
    @Transactional
    public String validate(String wxToken, CheckModel tokenModel) {
        String signature = tokenModel.getSignature();
        String timestamp = tokenModel.getTimestamp();
        String nonce = tokenModel.getNonce();
        String echostr = tokenModel.getEchostr();
        if (signature != null && timestamp != null & nonce != null) {
            String[] str = { wxToken, timestamp + "", nonce + "" };
            Arrays.sort(str); // 字典序排序
            String bigStr = str[0] + str[1] + str[2];
            // SHA1加密
            String digest = sha1.encode("SHA1", bigStr).toLowerCase();
            // 确认请求来至微信
            if (digest.equals(signature)) {
                // 最好此处将echostr存起来,以后每次校验消息来源都需要用到
                return echostr;
            }
        }
        return "error";
    }
}

sha1加密类

package cn.bluemobi.util;

import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * 
 * 验证微信响应过来的参数以及拼接成字符串进行sha1加密 <br/>
 * date: 2015年7月7日 下午4:44:51 <br/>
 * 
 * @author fang
 * @version
 */
public class sha1 {
    // 与接口配置信息中的Token要一致
    private static String token = "2013wh";

    /**
     * 验证微信响应过来的参数以及拼接成字符串进行sha1加密
     * 
     * @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 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;
    }

    /**
     * 将字节数组转换为十六进制字符串
     * 
     * @param byteArray
     * @return
     */
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    /**
     * 解析XML
     * 
     * 
     * @param req
     * @return
     */
    public static Map<String, String> parseWikiMsg(HttpServletRequest req) throws Exception {

        // 将解析结果存储在HashMap中
        Map<String, String> map = new HashMap<String, String>();

        // 从request中取得输入流
        InputStream inputStream = req.getInputStream();
        // 读取输入流
        SAXReader reader = new SAXReader();
        Document document = reader.read(inputStream);
        // 得到xml根元素
        Element root = document.getRootElement();
        // 得到根元素的所有子节点
        List<Element> elementList = root.elements();
        // 遍历所有子节点
        for (Element e : elementList)
            map.put(e.getName(), e.getText());
        // 释放资源
        inputStream.close();
        inputStream = null;
        return map;
    }

    /**
     * @author fanglf 需要微信端自行输入token,也就是随意输入token。
     */
    private static final String ALGORITHM = "MD5";

    private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
            'e', 'f' };

    /**
     * encode string
     * 
     * @param algorithm
     * @param str
     * @return String
     */
    public static String encode(String algorithm, String str) {
        if (str == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
            messageDigest.update(str.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * encode By MD5
     * 
     * @param str
     * @return String
     */
    public static String encodeByMD5(String str) {
        if (str == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance(ALGORITHM);
            messageDigest.update(str.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * Takes the raw bytes from the digest and formats them correct.
     * 
     * @param bytes the raw bytes from the digest.
     * @return the formatted bytes.
     */
    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        // 把密文转换成十六进制的字符串形式
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }
}

Controller类

/**
 * Project Name:xbrcw
 * File Name:TokenController.java
 * Package Name:cn.bluemobi.controller.weixin
 * Date:2015年7月8日下午12:04:57
 * Copyright (c) 2015, bluemobi.cn All Rights Reserved.
 *
 */

package cn.bluemobi.controller.weixin;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.ParseException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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.ResponseBody;

import cn.bluemobi.MicroServiceUtil.MicroServiceUtil;
import cn.bluemobi.entity.weixin.CheckModel;
import cn.bluemobi.service.TokenService;

/**
 * Description: <br/>
 * Date: 2015年7月8日 下午12:04:57 <br/>
 * 
 * @author fang
 * @version
 * @see
 */
@Controller
@RequestMapping("/wechat")
public class TokenController {
    @Autowired
    private TokenService tokenService;

    // private Logger log = Logger.getLogger(TokenController.class);
    /**
     * 开发者模式token校验
     * 
     * @param wxAccount 开发者url后缀
     * @param response
     * @param tokenModel
     * @throws ParseException
     * @throws IOException
     */
    @RequestMapping(method = { RequestMethod.GET })
    @ResponseBody
    public String validate(String wxToken, CheckModel tokenModel) throws ParseException, IOException {
        return tokenService.validate(wxToken, tokenModel);
    }

    /**
     * 微信消息的处理
     * 
     * @param request
     * @param out
     * @throws IOException
     */
    @RequestMapping(method = { RequestMethod.POST })
    public void dispose(HttpServletRequest request, HttpServletResponse response) throws IOException {
        /* 消息的接收、处理、响应 */

        // 将请求、响应的编码均设置为UTF-8(防止中文乱码)
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        // 调用核心业务类接收消息、处理消息
        String respMessage = MicroServiceUtil.processRequest(request);
        // log.info(respMessage);
        // 响应消息
        PrintWriter out = response.getWriter();
        out.print(respMessage);
        out.close();
    }
}

以上代码即可实现通过springmvc的方式和微信公众平台token对接。需要的相对应jar包,请自行下载。找不到的留言,我会提供。
码农的世界

期待各位码友在欣赏我的无私创作之时,也请大家多多支持我码农的世界,谢谢各位!

发布了41 篇原创文章 · 获赞 29 · 访问量 5万+
展开阅读全文

使用Springmvc开发微信公众号数据传输问题

06-26

返回给微信服务器的XML格式的字符串,发现在公网Linux服务器中,tomcat的catalina.out文件打印的该字符串少了<ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[FromUser]]></FromUserName> <CreateTime>123456789</CreateTime> 这几行标签,手机微信提示该订阅号无法提供服务,请稍后再试。 该问题找了好久都找不出原因。是springmvc的数据传输有问题吗? 我贴一下springmvc.xml配置,求帮忙解答!!~ <!-- 自动扫描controller包下的所有类,使其认为spring mvc的控制器 --> <!-- 加载controller的时候,不加载service,因为此时事物并未生效,若此时加载了service,那么事物无法对service进行拦截 --> <context:component-scan base-package="org.jeecgframework.web.*,weixin.*"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" /> </context:component-scan> <!-- ApplicationContext --> <bean class="org.jeecgframework.core.util.ApplicationContextUtil"></bean> <!-- 避免IE执行AJAX时,返回JSON出现下载文件 --> <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射, 配置一个基于注解的定制的WebBindingInitializer,解决日期转换问题,方法级别的处理器映射 --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="cacheSeconds" value="0" /> <property name="messageConverters"> <list> <ref bean="mappingJacksonHttpMessageConverter" /><!-- json转换器 --> </list> </property> <property name="webBindingInitializer"> <bean class="org.jeecgframework.core.interceptors.MyWebBinding" /> </property> </bean> <!-- 默认的视图解析器 在上边的解析错误时使用 (默认使用html)- --> <bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:order="3"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="contentType" value="text/html" /> <property name="prefix" value="/webpage/" /> <property name="suffix" value=".jsp" /> </bean> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="UTF-8"> <property name="maxUploadSize"> <value>104857600</value> </property> <property name="maxInMemorySize"> <value>4096</value> </property> </bean> <!-- Bean解析器,级别高于默认解析器,寻找bean对象进行二次处理 --> <bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="0"> </bean> <!-- Excel 处理 根据用户输入进行对象处理 --> <bean id="jeecgExcelView" class="org.jeecgframework.poi.excel.view.JeecgSingleExcelView" /> <!-- 方言 --> <bean id="dialect" class="org.jeecgframework.core.common.hibernate.dialect.DialectFactoryBean"> <property name="dbType" value="${jdbc.dbType}" /> </bean> <!-- 异常处理类 --> <bean id="exceptionHandler" class="org.jeecgframework.core.common.exception.MyExceptionHandler" /> <!-- 系统错误转发配置[并记录错误日志] --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="defaultErrorView" value="500"></property> <!-- 默认为500,系统错误(error.jsp) --> <property name="defaultStatusCode" value="404"></property> <property name="statusCodes"><!-- 配置多个statusCode --> <props> <prop key="error">500</prop> <!-- error.jsp --> <prop key="error1">404</prop> <!-- error1.jsp --> </props> </property> <property name="exceptionMappings"> <props> <!-- 这里你可以根据需要定义N多个错误异常转发 --> <prop key="java.sql.SQLException">dbError</prop> <!-- 数据库错误(dbError.jsp) --> <prop key="org.springframework.web.bind.ServletRequestBindingException">bizError</prop> <!-- 参数绑定错误(如:必须参数没传递)(bizError.jsp) --> <prop key="java.lang.IllegalArgumentException">bizError</prop> <!-- 参数错误(bizError.jsp) --> <prop key="org.springframework.validation.BindException">bizError</prop> <!-- 参数类型有误(bizError.jsp) --> <prop key="java.lang.Exception">unknowError</prop> <!-- 其他错误为'未定义错误'(unknowError.jsp) --> </props> </property> </bean> <!-- 拦截器 --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**" /> <bean class="org.jeecgframework.core.interceptors.EncodingInterceptor" /> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**" /> <bean class="org.jeecgframework.core.interceptors.AuthInterceptor"> <property name="excludeUrls"> <list> <value>loginController.do?goPwdInit</value> <value>loginController.do?pwdInit</value> <value>loginController.do?login</value> <value>loginController.do?checkuser</value> <value>repairController.do?repair</value> <value>repairController.do?deleteAndRepair</value> <value>cmsMenuController.do?index</value> <value>cmsArticleController.do?cmsArticleListShow</value> <value>cmsArticleController.do?datagridwx</value> <value>cmsArticleController.do?cmsArticleShow</value> <value>cmsController.do?goPage</value> <value>cmsController.do?getMenuList</value> <value>wechatController.do?wechat</value> <value>zpController.do?iscontinue</value> <value>zpController.do?saveZpPrize</value> <value>zpController.do?getZpPize</value> <value>zpController.do?saverecord</value> <value>zpController.do?ggl_new</value> <value>zpController.do?ggl</value> <value>zpController.do?zp</value> <value>zpController.do?goZhuanpan</value> <value>weixinCmsStyleController.do?upload</value> <value>newsItemController.do?newscontent</value> <!-- 保存用户 --> <value>userController.do?saveUser</value> </list> </property> </bean> </mvc:interceptor> </mvc:interceptors> 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览