Solo  当前访客:3 登录 注册

喧哗博客-http://blog.xuahua.com

繁华过后的沉寂--技术经验分享
浏览次数: 95,037    文章总数: 91    评论总数: 3
存档:
2016 年 06 月 (6)

微信接口开发系列之五微信支付服务器接收通知 有更新!

微信服务器 异步通知服务器接收通知

1,业务防止多次重复;

2,以此通知到账为准,实现到账业务逻辑实现。

注意事项:

 微信服务器 通知消息,以流形式接收消息;

  校验消息;

  解析消息按状态,实现对应业务处理。

接收消息关键代码:

response.setCharacterEncoding("utf-8");
			request.setCharacterEncoding("utf-8");
			//response.setContentType("text/xml");
			pw = response.getWriter();
			InputStream in = request.getInputStream();
			BufferedInputStream bis = new BufferedInputStream(in);
			byte[] bytes = new byte[2048];
			int len = -1;
			StringBuilder sb = new StringBuilder();
			while ((len = bis.read(bytes)) != -1) {
				sb.append(new String(bytes, 0, len));
			}
			bis.close();
			String result = sb.toString();


解析消息关键代码:

    

 Document doc = null;		
try {
			// 读取并解析XML文档
			// SAXReader就是一个管道,用一个流的方式,把xml文件读出来
			// SAXReader reader = new SAXReader(); //aa.xml表示你要解析的xml文档
			// Document document = reader.read(new File("aa.xml"));
			// 下面的是通过解析xml字符串的
			doc = DocumentHelper.parseText(xmlstring); // 将字符串转为XML
			Element root = doc.getRootElement(); // 获取根节点
			if(root.element("result_code")!=null){
				vo.setResult_code(trims(root.elementTextTrim("result_code")));
			}
}catch(Exception e){
 
}

微信接口开发系列之四模版消息

发送模版消息,必须从模版库取得匹配的模版template_id并模版内容以及发送给谁的openid

在开发环境中,可在 测试号管理 -- 测试号二维码 扫码添加测试微信号,并在右侧可见 此微信号即测试开发中的openid。此处openid仅用于测试与生产不同。

测试例子

 状态更新提醒模版  template_id => zdcmSDVbJ9SQvUVLeAeWF9XsoWBvE29QR42Tx9gcSaE

模版内容 

{{first.DATA}}
状态来源:{{keyword1.DATA}}
处理进度:{{keyword2.DATA}}
提交时间:{{keyword3.DATA}}
{{remark.DATA}}

代码实现如下

	/**
	 * 状态更新提醒  zdcmSDVbJ9SQvUVLeAeWF9XsoWBvE29QR42Tx9gcSaE

{{first.DATA}}
状态来源:{{keyword1.DATA}}
处理进度:{{keyword2.DATA}}
提交时间:{{keyword3.DATA}}
{{remark.DATA}}
	 */
	public static Map<String,Object> notifyEventChange(String openid,String templateid,String url,String title,String key1,String key2,String key3,String remark){
		Map<String,Object> data =  new HashMap<String,Object>();
		data.put("touser",openid);
		if(StringUtils.isBlank(templateid)){
			templateid = "zdcmSDVbJ9SQvUVLeAeWF9XsoWBvE29QR42Tx9gcSaE";
		}
		data.put("template_id",templateid);
		data.put("url",url);

		Map<String,Object> datasub  = new HashMap<String,Object>();
		
		Map<String,String> firstmap = new HashMap<String,String>();
		firstmap.put("value",title);
		 
		firstmap.put("color","#173177");
		datasub.put("first", JSON.toJSON(firstmap));
		
		Map<String,String> ordermap = new HashMap<String,String>();
		ordermap.put("value",key1);
		ordermap.put("color","#173177");
		datasub.put("keyword1", JSON.toJSON(ordermap));
		
		Map<String,String> statusmap = new HashMap<String,String>();
		statusmap.put("value",key2);
		statusmap.put("color","#173177");
		datasub.put("keyword2", JSON.toJSON(statusmap));
		
		Map<String,String> key3map = new HashMap<String,String>();
		key3map.put("value",key3);
		key3map.put("color","#173177");
		datasub.put("keyword3", JSON.toJSON(key3map));
		
		Map<String,String> remarkmap = new HashMap<String,String>();
		remarkmap.put("value",remark);
		remarkmap.put("color","#173177");
		
		datasub.put("remark",JSON.toJSON(remarkmap));
		data.put("data",JSON.toJSON(datasub));
		return data;
	} 

 

微信接口开发系列之三获取用户信息

关键信息: 微信服务器返回的微信公众号  有效7200秒的access_token 凭据

在有效的时间内,根据access_token,用户openid,获取用户授权的用户信息

关键代码:

// 获取微信用户信息
	public String getUserinfoByTokenOpenid(String accesstoken, String openid) {
		String url = PropertiesUtil.getValue("wx.userinfo");
		// String url =
		// "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
		url = url.replace("ACCESS_TOKEN", accesstoken);
		url = url.replace("OPENID", openid);
		String result = "";
		try {
			// 定义HttpClient
			HttpClient client = new HttpClient();
			// 实例化HTTP方法
			GetMethod request = new GetMethod(url);
			// 定义访问地址的链接状态
			int statusCode = client.executeMethod(request);
			// 客户端请求url数据
			// 请求成功状态-200
			if (statusCode == HttpStatus.SC_OK) {
				// 解决微信用户信息返回乱码的问题
				result = new String(request.getResponseBody(), "utf-8");
			} else {
				log.info("请求返回状态:" + statusCode);
			}
			if (log.isInfoEnabled()) {
				log.info("获取微信用户信息---------" + result);
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

微信接口开发系列之二授权

授权  微信公众号用户显式授权

原理      用户关注公众号 或进入指定地址,前端JS-SDK 调用微信授权接口,用户显示确认授权后,微信会给予一个授权码code,通过授权码code 可以去微信服务器获取一个有效时长为7200秒的access-token;

此token具有很重要作用,且获取频率做了日限制100000次/天;测试号则只有2000次/天。

前端授权获取代码略。

服务器代码关键如下:

/**
	 * @param code
	 * @return 根据网页授权code 获取 openid,网页授权的access_token
	 */
	public String getUrlTokenBycode(String code) {
		// String url =
		// "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
		String url = PropertiesUtil.getValue("wx.accessTokenCode");

		// 微信正式公众号
		url = url.replace("APPID", PropertiesUtil.getValue("wx.appid"));
		url = url.replace("SECRET", PropertiesUtil.getValue("wx.appsecret"));
		url = url.replace("CODE", code);

		// 微信公众测试号
		// url = url.replace("APPID", "wxd39f718d218f90a1");
		// url = url.replace("SECRET", "71f7001a9c38fe13e5bb96bd8283f463");
		// url = url.replace("CODE", code);
		String result = "";
		try {
			result = Posturl.getRequest(url);
			if (log.isInfoEnabled()) {
				log.info("根据网页授权code,获取openid,网页授权access_token:---------" + result);
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

 

微信接口开发系列之一配置 有更新!

本题主要从技术实现来讲讲微信开发。

微信开发之前,必须先申请微信订阅号/服务号/企业号,不管哪种类型都是微信针对不同专业,领域做的区分,在某些功能上有所限制。

一般在开发之前,都是开发模式,所以在获得了微信号之后,先申请微信测试号进行测试。

第一步:进入公众平台,在左侧菜单栏找到 开发 -- 开发者工具 在右侧选择 公众平台测试帐号 进入

第二步:在 测试号信息 可以看到 appID  和 appsecret 此为后续接口开发重要账号与密钥。

第三步:在 接口配置信息 中,填写以后需要对接微信入口校验以及接收消息接口的url访问地址以及校验参数token。

第四步: 设完配置信息以后,需要在服务器建立一个应用,并对外暴露一个网址即在第三步中填写的访问地址。本人对外的地址为 http://xxx.com/wx/index

主要用于微信服务器校验,接收微信消息通知。

校验主要参数四个: 

signature,timestamp,nonce,echostr
微信消息通知则是需要通过流的接收方式,代码如下


 

public class XMLUtil {
	
	public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
		Map<String, String> map = new HashMap<String, String>();
		InputStream inputStream = request.getInputStream();
		SAXReader reader = new SAXReader();
		Document document = reader.read(inputStream);
		Element root = document.getRootElement();
		List<Element> elementList = root.elements();
		for (Element e : elementList)
			map.put(e.getName(), e.getTextTrim());
		inputStream.close();
		inputStream = null;
		return map;
	}

 下面为完整的具体接口关键代码:

/**
 * 
 * 类名称:WeixinController.java 类描述: 微信公共平台开发
 * 
 * @author wyong 
 *  联系方式:343886028
 *  创建时间:2016年1月10日
 * @version 1.0
 */
@Controller
@RequestMapping("/wx")
public class WeixinController extends BaseAction {
	Logger logger = Logger.getLogger(getClass());

	
	@Autowired
	MsgService msgService;
	/**
	 * 微信接口总入口
	 * @param out
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping(value = "/index")
	public void index(@RequestParam(value = "signature", defaultValue = "") String signature, @RequestParam(value = "timestamp", defaultValue = "") String timestamp,
			@RequestParam(value = "nonce", defaultValue = "") String nonce, @RequestParam(value = "echostr", defaultValue = "") String echostr, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

			if (logger.isInfoEnabled()) {
				logger.info("signature=" + signature + "|timestamp=" + timestamp + "|nonce=" + nonce + "|echostr=" + echostr);
			}
			 
			PrintWriter out = response.getWriter();
			if (StringUtils.isNotBlank(signature) && StringUtils.isNotBlank(timestamp) &&StringUtils.isNotBlank(nonce)&& StringUtils.isNotBlank(echostr)) {/* 接口验证 */
				logger.info("========进入身份验证");
				List<String> list = new ArrayList<String>(3) {
					private static final long serialVersionUID = 2621444383666420433L;
					
					public String toString() { // 重写toString方法,得到三个参数的拼接字符串
						return this.get(0) + this.get(1) + this.get(2);
					}
				};
				list.add(PropertiesUtil.getValue("wx.WEIXIN")); // 读取Token(令牌)
				list.add(timestamp);
				list.add(nonce);
				Collections.sort(list); // 排序
				String tmpStr = new MySecurity().encode(list.toString(), MySecurity.SHA_1); // SHA-1加密
				if (signature.equals(tmpStr)) {
					out.write(echostr); // 请求验证成功,返回随机码
				} else {
					out.write("");
				}
				out.flush();
				out.close();
			} else {/* 消息处理 */
				System.out.println("========进入消息处理");
				Map<String, String> requestMap = XMLUtil.parseXml(request);
				log.error("====="+JSON.toJSON(requestMap));
				//事件推送,是否是发送消息后的事件推送。
				if(requestMap!=null && requestMap.get("MsgType")!=null && "event".equalsIgnoreCase(requestMap.get("MsgType"))){
					String msgid  = requestMap.get("MsgID");
					if(StringUtils.isNotBlank(msgid)){
						TMemNotify notify = msgService.findNotify(msgid);
						if(notify!=null){
							notify.setUpdatetime(new Date());
							notify.setReturnmsg(requestMap.get("Status"));
							msgService.updateObj(notify);
						}
					}
				}
				response.reset();
				log.error(JSON.toJSON(requestMap));
			}
	}

 

   

 

spring--secrutiy--控制到按钮 有更新!

使用spring security taglib: 
Java代码 
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %> 
... 
<security:authorize ifAnyGranted="ROLE_ADMIN"> 
<a href="user/input/id/${nuId}.html">编辑</a> 
</security:authorize>

公告

喧哗博客--繁华过后的沉寂--技术经验分享^-^
Copyright (c) 2009-2019, b3log.org & hacpai.com