微信第三方平台代小程序实现业务(2)

        微信开发文档写得不够详细,而且跳屏比较严重,对于整天忙于开发,并且第一次接触的小伙伴来说,真的是太痛苦了,本人就是这样过来的,并且看了很多网上的材料,最后意识到,是自己对于这种开发文档接触的太少,研读的不够精细导致的,苦笑...

今天任务:第三方平台方获取预授权码(pre_auth_code)

步骤1:第三方平台方获取预授权码(pre_auth_code)

预授权码是第三方平台方实现授权托管的必备信息,可以通过本文第3部分获取。(——摘自微信开发文档)

获取预授权码pre_auth_code

该API用于获取预授权码。预授权码用于公众号或小程序授权时的第三方平台方安全验证。

接口调用请求说明

http请求方式: POST(请使用https协议)
https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=xxx

POST数据示例:

{
"component_appid":"appid_value" 
}

请求参数说明

参数说明
component_appid第三方平台方appid

返回结果示例

{"pre_auth_code":"Cx_Dk6qiBE0Dmx4EmlT3oRfArPvwSQ-oa3NL_fwHM7VI08r52wazoZX2Rhpz1dEw","expires_in":600}

结果参数说明

参数说明
pre_auth_code预授权码
expires_in有效期,为10分钟

很多人到这步,看得云里雾里,不知道怎么获取component_access_token,其实component_access_token需要通过微信推送过来的消息间接的获取,也就是前文提交审核材料中的授权事件接收URL这个你提交材料中所设置的路径,微信服务器会推送一个票据component_verify_ticket,通过这个票据再去获取component_access_token。

此处给出我的实现方法

此方法就是授权事件接收URL接受component_verify_ticket操作,因为微信服务端推送的是xml的加密文件,所以需要我们自己去解析,给出微信提供的各种语言demo,点击示例下载就可获取。

	@RequestMapping(value = "/wx/sysMsgCallback")
	@ResponseBody
	public ResponseEntity<String> wechatSysMsgCallback(HttpServletRequest request, HttpServletResponse response,
			@RequestBody String xml, @RequestParam(value = "signature", required = false) String signature,
			@RequestParam(value = "timestamp", required = false) String timeStamp,
			@RequestParam(value = "nonce", required = false) String nonce,
			@RequestParam(value = "encrypt_type", required = false) String encryptType,
			@RequestParam(value = "msg_signature", required = false) String msgSignature) throws Exception {

		logger.info("解密前明文:" + xml);
		logger.info("signature = " + signature + " timeStamp =" + timeStamp + " nonce = " + nonce + " msgSignature =" + msgSignature);
		String encodingAesKey = "***"; // 加解密秘钥,自行定义
		String token = "***"; // 加解密token,自行定义
		String appId = "***"; // 第三方平台appid,提交申请第三方平台时微信服务器分发的appid
        // 微信提供的源代码
		WXBizMsgCrypt pc = new WXBizMsgCrypt(token, encodingAesKey, appId);

		// 第三方收到公众号平台发送的消息
		String result2 = "";
		if(xml.contains("ToUserName")) {
			result2 = pc.decryptMsgTwo(msgSignature, timeStamp, nonce, xml);
		} else if(xml.contains("AppId")) {
			result2 = pc.decryptMsg(msgSignature, timeStamp, nonce, xml);
		}
		System.out.println("解密后明文: " + result2);
		logger.info("【success】 =" + result2);
		// 微信每10分钟推送给我们的ticket
		this.saveTicketToRedis(result2);
		response.getWriter().write("success");
		response.getWriter().flush();
		response.getWriter().close();
		return null;
	}

 给出自己修改的两个解密操作

1、decryptMsg

public String decryptMsg(String msgSignature, String timeStamp, String nonce, String postData)
			throws AesException {
    // 密钥,公众账号的app secret
	// 提取密文
	Object[] encrypt = XMLParse.extract(postData);
	// 验证安全签名
	String signature = SHA1.getSHA1(token, timeStamp, nonce, encrypt[1].toString());
	// 和URL中的签名比较是否相等
	if (!signature.equals(msgSignature)) {
		throw new AesException(AesException.ValidateSignatureError);
	}

	// 解密
	String result = decrypt(encrypt[1].toString());
	return result;
}

public static Object[] extract(String xmltext) throws AesException {
		Object[] result = new Object[3];
    try {
	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
	dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
	dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
	dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
	dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
	dbf.setXIncludeAware(false);
	dbf.setExpandEntityReferences(false);
	DocumentBuilder db = dbf.newDocumentBuilder();
	StringReader sr = new StringReader(xmltext);
	InputSource is = new InputSource(sr);
	Document document = db.parse(is);

	Element root = document.getDocumentElement();
	NodeList nodelist1 = root.getElementsByTagName("Encrypt");
	// 修改后的代码
	NodeList nodelist2 = root.getElementsByTagName("AppId");
			
	result[0] = 0;
	result[1] = nodelist1.item(0).getTextContent();
	result[2] = nodelist2.item(0).getTextContent();
	return result;
    } catch (Exception e) {
	e.printStackTrace();
	throw new AesException(AesException.ParseXmlError);
    }
}

2、decryptMsgTwo

public String decryptMsgTwo(String msgSignature, String timeStamp, String nonce, String postData)
			throws AesException {
		
		// 密钥,公众账号的app secret
		// 提取密文
		Object[] encrypt = XMLParse.extractTwo(postData);
		
		// 验证安全签名
		String signature = SHA1.getSHA1(token, timeStamp, nonce, encrypt[1].toString());
		
		// 和URL中的签名比较是否相等
		if (!signature.equals(msgSignature)) {
			throw new AesException(AesException.ValidateSignatureError);
		}
		
		// 解密
		String result = decrypt(encrypt[1].toString());
		return result;
	}

public static Object[] extractTwo(String xmltext) throws AesException {
		Object[] result = new Object[3];
		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
			dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
			dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
			dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
			dbf.setXIncludeAware(false);
			dbf.setExpandEntityReferences(false);
			DocumentBuilder db = dbf.newDocumentBuilder();
			StringReader sr = new StringReader(xmltext);
			InputSource is = new InputSource(sr);
			Document document = db.parse(is);
			
			Element root = document.getDocumentElement();
			NodeList nodelist1 = root.getElementsByTagName("Encrypt");
			
			// 微信原始代码
			NodeList nodelist2 = root.getElementsByTagName("ToUserName");
//			
			result[0] = 0;
			result[1] = nodelist1.item(0).getTextContent();
			result[2] = nodelist2.item(0).getTextContent();
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			throw new AesException(AesException.ParseXmlError);
		}
	}

注意:解析报异常java.security.InvalidKeyException:illegal Key Size的解决方案

在官方网站下载JCE无限制权限策略文件(JDK6的下载地址)(JDK7的下载地址)(JDK8的下载地址

下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt,如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件;如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件

掉坑1:

解析出来获取的component_verify_ticket是一串带有@@@的字符串,需要自行将@前面不要的信息截取掉,很多人在这里被坑的很惨。

通过以下这个接口获取component_access_token

http请求方式: POST(请使用https协议) 
https://api.weixin.qq.com/cgi-bin/component/api_component_token

POST数据示例:

{
"component_appid":"appid_value" ,
"component_appsecret": "appsecret_value",
"component_verify_ticket": "ticket_value"
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值