java优化微信分享

刚刚做了一个微信的分享。因为微信现在是很普及的APP,几乎是每个人都会有微信号,用户量何其大!!!!所以我写了一个简单的连接微信的工具类,其中包含获取token,ticket,等等。。。

1、微信通用的工具类

package com.solian.web.util;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

import com.solian.web.bean.Token;
import com.solian.web.bean.WinXinEntity;

import net.sf.json.JSONObject;

/**
 * 微信通用工具类
 * 
 * @author wukaikai
 *
 */
public class WeiXinUtils {
	 // 获取access_token的接口地址(GET) 限2000(次/天)
    public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    // 获取jsapi_ticket的接口地址(GET) 限2000(次/天)
    public final static String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
    // 缓存添加的时间
    public static String cacheAddTime = null;
    // token,ticket缓存
    public static Map<String, Token> TOKEN_TICKET_CACHE = new HashMap<String, Token>();
    // token对应的key
    private static final String TOKEN = "token";
    // ticket对应的key
    private static final String TICKET = "ticket";
	
	
    public static WinXinEntity getWinXinEntity(String url) {
        WinXinEntity wx = new WinXinEntity();
        String access_token = getToken("APPID", "AppSecret");
        String ticket = getTicket(access_token);
        Map<String, String> ret = Sign.sign(ticket, url);
        System.out.println(ret.toString());
        wx.setTicket(ret.get("jsapi_ticket"));
        wx.setSignature(ret.get("signature"));
        wx.setNoncestr(ret.get("nonceStr"));
        wx.setTimestamp(ret.get("timestamp"));
        wx.setStr(ret.get("url"));
        return wx;
    }

    /**
     * 获得Token
     *
     * @return
     */
    public static String getToken(String appId, String secret) {
        Token accessTocken = getToken(appId, secret, System.currentTimeMillis() / 1000);
        return accessTocken.getToken();
    }
    /**
     * 获得ticket
     *
     * @return
     */
    public static String getTicket(String token) {
        Token accessTocken = getTicket(token, System.currentTimeMillis() / 1000);
        return accessTocken.getTicket();
    }
    
    /**
     * 获取access_token
     * 
     * @param appid
     * @param appsecret
     * @param currentTime
     * @return
     */
    public static Token getToken(String appid, String appsecret, long currentTime) {
    	Token tokenTicketCache = getTokenTicket(TOKEN);
    	Token token = null;
    	if (tokenTicketCache != null && (currentTime - tokenTicketCache.getAddTime() <= tokenTicketCache.getExpiresTime())) {
    		System.out.println("==========缓存中token已获取时长为:" + (currentTime - tokenTicketCache.getAddTime()) + "毫秒,可以重新使用");
    		return tokenTicketCache;
		}
    	 System.out.println("==========缓存中token不存在或已过期===============正在重新请求===========");
    	String token_url = access_token_url.replaceAll("APPID", appid).replaceFirst("APPSECRET", appsecret);
    	JSONObject jsonObject = httpRequest(token_url, "GET", null);
    	 if (null != jsonObject) {
             token = new Token();
             token.setToken(jsonObject.getString("access_token"));
             token.setExpiresTime(jsonObject.getLong(("expires_in"))/2);// 正常过期时间是7200秒,此处设置3600秒读取一次
             System.out.println("==========tocket缓存过期时间为:" + token.getExpiresTime() + "毫秒");
             token.setAddTime(currentTime);
             updateToken(TOKEN, token);
         }
    	return token;
    }
    
    /**
     * 获取ticket
     *
     * @param token
     * @return
     */
    private static Token getTicket(String token, long currentTime) {
        Token tockenTicketCache = getTokenTicket(TICKET);
        Token Token = null;
        if (tockenTicketCache != null && (currentTime - tockenTicketCache.getAddTime() <= tockenTicketCache.getExpiresTime())) {// 缓存中有ticket
            System.out.println("==========缓存中ticket已获取时长为:" + (currentTime - tockenTicketCache.getAddTime()) + "毫秒,可以重新使用");
            return tockenTicketCache;
        }
        System.out.println("==========缓存中ticket不存在或已过期===============");
        String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN", token);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        // 如果请求成功
        if (null != jsonObject) {
            Token = new Token();
            Token.setTicket(jsonObject.getString("ticket"));
            Token.setExpiresTime(jsonObject.getLong("expires_in") / 2);// 正常过期时间是7200秒,此处设置3600秒读取一次
            System.out.println("==========ticket缓存过期时间为:" + Token.getExpiresTime() + "毫秒");
            Token.setAddTime(currentTime);
            updateToken(TICKET, Token);
        }
        return Token;
    }
    
    /**
     * 从缓存中读取token或者ticket
     *
     * @return
     */
    private static Token getTokenTicket(String key) {
        if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {
            System.out.println("==========从缓存中获取到了" + key + "成功===============");
            return TOKEN_TICKET_CACHE.get(key);
        }
        return null;
    }
    
    /**
     * 更新缓存中token或者ticket
     *
     * @return
     */
    private static void updateToken(String key, Token accessTocken) {
        if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {
            TOKEN_TICKET_CACHE.remove(key);
            System.out.println("==========从缓存中删除" + key + "成功===============");
        }
        TOKEN_TICKET_CACHE.put(key, accessTocken);
        cacheAddTime = String.valueOf(accessTocken.getAddTime());// 更新缓存修改的时间
        System.out.println("==========更新缓存中" + key + "成功===============");
    }
    
    /**
     * 发起https请求并获取结果
     *
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param outputStr     提交的数据
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    private static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        StringBuffer buffer = new StringBuffer();
        try {
            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            // 设置请求方式(GET/POST)
            httpUrlConn.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod))
                httpUrlConn.connect();

            // 当有数据需要提交时
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式,防止中文乱码
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException ce) {
            System.out.println("Weixin server connection timed out.");
        } catch (Exception e) {
            System.out.println("https request error:{}" + e.getMessage());
        }
        return jsonObject;
    }
}

2、验证,进行签名的工具类。这个是官方提供。(不建议自己写)

package com.solian.web.util;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;  

class Sign {

    public static Map<String, String> sign(String jsapi_ticket, String url) {
        Map<String, String> ret = new HashMap<String, String>();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";

        //注意这里参数名必须全部小写,且必须有序
        string1 = "jsapi_ticket=" + jsapi_ticket +
                  "&noncestr=" + nonce_str +
                  "&timestamp=" + timestamp +
                  "&url=" + url;
        System.out.println(string1);

        try
        {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }

        ret.put("url", url);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);

        return ret;
    }

    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
}

 3.Token类。主要是做存储。因为官方微信有一个次数的限制,和有效期限制。。。所以这里用到了一个存储类。做缓存使用

package com.solian.web.bean;

/**
 * @author wukaikai
 * 微信通用(限制为每日只可以调取2000次)
 * token(有效期2个小时7200秒)获取和ticket缓存
 * 为了减少频繁的刷微信,导致微信那边限制。给项目带来不必要的损失
 * 
 */
public class Token {
	
	/**
	 * token
	 */
	private String token;
	/**
	 * 生成的ticket
	 */
	private String ticket;
	/**
	 * 过期时间,自己定义为了不影响项目的正常运行,我这里定位3600秒
	 */
	private Long expiresTime;
	/**
	 * 增加时间
	 */
	private Long addTime;
	public String getToken() {
		return token;
	}
	public void setToken(String token) {
		this.token = token;
	}
	public String getTicket() {
		return ticket;
	}
	public void setTicket(String ticket) {
		this.ticket = ticket;
	}
	public Long getExpiresTime() {
		return expiresTime;
	}
	public void setExpiresTime(Long expiresTime) {
		this.expiresTime = expiresTime;
	}
	public Long getAddTime() {
		return addTime;
	}
	public void setAddTime(Long addTime) {
		this.addTime = addTime;
	}
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值