All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.anyline.wechat.util.WechatUtil Maven / Gradle / Ivy

There is a newer version: 8.7.2-20240916
Show newest version
/*
 * Copyright 2006-2023 www.anyline.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */




package org.anyline.wechat.util;

import org.anyline.entity.DataRow;
import org.anyline.entity.DataSet;
import org.anyline.net.HttpBuilder;
import org.anyline.net.HttpUtil;
import org.anyline.util.BasicUtil;
import org.anyline.util.BeanUtil;
import org.anyline.util.ConfigTable;
import org.anyline.util.encrypt.MD5Util;
import org.anyline.wechat.entity.WechatAuthInfo;
import org.anyline.wechat.entity.WechatUserInfo;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.anyline.log.Log;
import org.anyline.log.LogProxy;

import java.io.File;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
 
public class WechatUtil {
	protected static final Log log = LogProxy.get(WechatUtil.class);
	private static DataSet accessTokens = new DataSet();
	/** 
	 * 参数签名 
	 *  
	 * @param secret  secret
	 * @param params  params
	 * @return String
	 */ 
	public static String sign(String secret, Map params) {
		String sign = ""; 
		sign = BeanUtil.map2string(params);
		sign += "&key=" + secret; 
		sign = MD5Util.crypto(sign).toUpperCase(); 
		return sign; 
	} 
	public static boolean validateSign(String secret, Map map){
		String sign = (String)map.get("sign"); 
		if(BasicUtil.isEmpty(sign)){
			return false; 
		} 
		map.remove("sign"); 
		String chkSign = sign(secret, map); 
		return chkSign.equals(sign); 
	} 
	public static boolean validateSign(String secret, String xml){
		return validateSign(secret,BeanUtil.xml2map(xml)); 
	} 
	/** 
	 * 获取RSA公钥 
	 * @param mch  mch
	 * @param apiSecret  apiSecret
	 * @param keyStoreFile  keyStoreFile
	 * @param keyStorePassword  keyStorePassword
	 * @return String
	 */ 
	public static String getPublicKey(String mch, String apiSecret, File keyStoreFile, String keyStorePassword) {
		Map parameters = new HashMap<>(); 
		parameters.put("mch_id", mch); 
		parameters.put("nonce_str", BasicUtil.getRandomLowerString(20)); 
		parameters.put("sign_type", "MD5"); 
		String sign = WechatUtil.sign(apiSecret, parameters);
		parameters.put("sign", sign); 
		String xml = BeanUtil.map2xml(parameters);
		CloseableHttpClient httpclient = HttpUtil.createSSLClient(keyStoreFile, HttpUtil.PROTOCOL_TLSV1, keyStorePassword);
		StringEntity reqEntity = new StringEntity(xml, "UTF-8"); 
		reqEntity.setContentType("application/x-www-form-urlencoded");

		String txt = HttpBuilder.init()
				.setClient(httpclient)
				.setUrl(WechatConfig.API_URL_GET_PUBLIC_SECRET)
				.setCharset("UTF-8")
				.setEntity(reqEntity)
				.build().get().getText();
		// String txt = HttpUtil.post(httpclient, WechatConfig.API_URL_GET_PUBLIC_SECRET, "UTF-8", reqEntity).getText();
		if(ConfigTable.IS_DEBUG && log.isWarnEnabled()){
			log.warn("[获取RSA公钥][\n{}\n]",txt);
		}
		return txt;
	}





	public static String getAccessToken(WechatConfig config){
		if(BasicUtil.isNotEmpty(config.SERVER_WHITELIST)){
			try{
				String ip = InetAddress.getLocalHost().getHostAddress();
				if(!config.SERVER_WHITELIST.contains(ip)){
					log.warn("[白名单验证失败][白名单:{}][本机IP:{}]", config.SERVER_WHITELIST, ip);
					return null;
				}
			}catch (Exception e){
				log.warn("[白名单验证异常]");
			}
		}
		String result = "";
		DataRow row = accessTokens.getRow("APP_ID", config.APP_ID);
		if(null == row || row.isExpire()){
			accessTokens.remove(row);
			row = newAccessToken(config);
		}
		if(null != row){
			result = row.getString("ACCESS_TOKEN");
		}
		return result;
	}

	/**
	 * 新建access_token,
	 * 如果多个应用使用同一个公众号,多个应用应该通过一个中心服务器创建access token
	 * 不应该每个应用单独创建access token
	 * @param config WechatConfig
	 * @return DataRow
	 */
	private static DataRow newAccessToken(WechatConfig config){
		if(ConfigTable.IS_DEBUG && log.isWarnEnabled()){
			log.warn("[CREATE NEW ACCESS TOKEN][appid:{}][secret:{}]",config.APP_ID, config.APP_SECRET);
		}
		String appid = config.APP_ID;
		String secret = config.APP_SECRET;
		DataRow row = null;
		String url = null;
		if(BasicUtil.isEmpty(config.ACCESS_TOKEN_SERVER)){
			url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+secret;
		}else{
			url = config.ACCESS_TOKEN_SERVER+ "?grant_type=client_credential&appid="+appid+"&secret="+secret;
		}
		String text = HttpUtil.post(url).getText();
		if(ConfigTable.IS_DEBUG && log.isWarnEnabled()){
			log.warn("[CREATE NEW ACCESS TOKEN][result:{}]",text);
		}
		DataRow json = DataRow.parseJson(text);
		if(null != json && json.containsKey("access_token")){
			row = new DataRow();
			row.put("APP_ID", appid);
			row.put("ACCESS_TOKEN", json.getString("access_token"));
			row.setExpires(json.getInt("expires_in", 0)*800);
			row.setExpires(1000*60*5); // 5分钟内有效
			if(ConfigTable.IS_DEBUG && log.isWarnEnabled()){
				log.warn("[CREATE NEW ACCESS TOKEN][ACCESS_TOKEN:{}]",row.getString("ACCESS_TOKEN"));
			}
			accessTokens.addRow(row);
		}else{
			if(ConfigTable.IS_DEBUG && log.isWarnEnabled()){
				log.warn("[CREATE NEW ACCESS TOKEN][FAIL]");
			}
			return null;
		}
		return row;
	}
	/**
	 * 用户授权信息 主要包含openid
	 * @param config config
	 * @param code code
	 * @return AuthInfo
	 */
	public static WechatAuthInfo getAuthInfo(WechatConfig config, String code){
		WechatAuthInfo result = null;
		String url = WechatConfig.API_URL_GET_AUTH_INFO + "?appid="+config.APP_ID+"&secret="+config.APP_SECRET+"&code="+code+"&grant_type=authorization_code";
		String txt = HttpUtil.get(url).getText();
		log.warn("[get auth info][txt:{}]",txt);
		result = BeanUtil.json2oject(txt, WechatAuthInfo.class);
		if(BasicUtil.isNotEmpty(result.getOpenid())){
			result.setResult(true);
		}
		return result;
	}

	/**
	 * 用户详细信息 主要包括用户昵称 头像 unionid
	 * @param config config
	 * @param openid openid
	 * @return UserInfo
	 */
	public static WechatUserInfo getUserInfo(WechatConfig config, String openid){
		WechatUserInfo result = null;
		String url = WechatConfig.API_URL_GET_USER_INFO + "?access_token="+getAccessToken(config)+"&openid="+openid+"&lang=zh_CN";
		String txt = HttpUtil.get(url).getText();
		log.warn("[wechar get user info][result:{}]",txt);
		result = BeanUtil.json2oject(txt, WechatUserInfo.class);
		if(BasicUtil.isNotEmpty(result.getOpenid())){
			result.setResult(true);
		}
		return result;
	}

	public static void profit(){

    }
} 




© 2015 - 2024 Weber Informatics LLC | Privacy Policy