美文网首页
Java实现微信分享自定义文案和图片

Java实现微信分享自定义文案和图片

作者: 初心myp | 来源:发表于2019-07-17 16:37 被阅读0次

    【链接】微信公众平台接口测试帐号申请

    http://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index

    首先获取access_token,然后获取jsapi_ticket,最后获取签名

    jsapi_ticket

    生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。

    1.参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):获取access_token

    2.用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

    成功返回如下JSON:

    {"errcode":0,"errmsg":"ok","ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA","expires_in":7200}
    

    获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。

    签名算法

    签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。

    即signature=sha1(string1)。 示例:

    noncestr=Wm3WZYTPz0wzccnWjsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qgtimestamp=1414587457url=http://mp.weixin.qq.com?params=value
    

    步骤1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:

    jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://mp.weixin.qq.com?params=value
    

    步骤2. 对string1进行sha1签名,得到signature:

    0f9de62fce790f9a083d5c99e95740ceb90c27ed
    

    注意事项

    1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。

    2.签名用的url必须是调用JS接口页面的完整URL。

    3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。

    如出现invalid signature 等错误详见附录5常见错误及解决办法。

    Java代码如下:

    //需要准备APP_ID 和SECRET 
    private static final String GET_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
    private static final String GET_SIGNATURE_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
    private static final String APP_ID = "******";
    private static final String SECRET = "*****";
    
    //提供的主方法
        @RequestMapping(value = "/getSignature", method = RequestMethod.POST)
        @ResponseBody
        public Map WeixinController(HttpServletRequest request, HttpServletResponse response) {
            response.setHeader("Access-Control-Allow-Origin", "*");
            Map ret = new HashMap();
            //获取前台传来的三个参数
            String timestamp = request.getParameter("timestamp");
            String nonce_str = request.getParameter("nonce_str");
            String url = request.getParameter("url");
            System.out.println("url"+url+"==============="+nonce_str+"============"+timestamp);
            String accessToken = null;
    
    //        accessToken = redisTemplate.opsForValue().get("accessToken")+"";
            accessToken =  this.getToken(GET_TOKEN_URL, APP_ID, SECRET);// 获取token
            String ticket = this.getTicket(GET_SIGNATURE_URL,accessToken);    // 获取ticket
            String signature = this.getSignature(ticket,url,nonce_str,timestamp); //获取签名
    
            ret.put("nonceStr", nonce_str);
            ret.put("timestamp", timestamp);
            ret.put("signature", signature);
            return ret;
        }
    

    工具类(获取token、ticket、sign方法)

    import com.google.gson.JsonObject;
    import com.google.gson.JsonParser;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.codec.digest.DigestUtils;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.HttpStatus;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.util.EntityUtils;
    
    import java.io.UnsupportedEncodingException;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @FileName: WeChatSignUtil
     * @Description: 微信签名的工具类
     * @author: <a href="mailto: muyuanpei@camelotchina.com">myp</a>
     * @create: 2019-07-17 15:56
     * @Copyright: (c) 2018年 北京柯莱特科技有限公司
     */
    @Slf4j
    public class WeChatSignUtil {
    
        // 获取access_token
        public static String getToken(String apiurl, String appid, String secret){
            //拼接访问地址
            String turl = String.format("%s?grant_type=client_credential&appid=%s&secret=%s", apiurl,appid, secret);
    
            HttpClient client = new DefaultHttpClient();
            //get请求
            HttpGet get = new HttpGet(turl);
            // 初始化解析json格式的对象
            JsonParser jsonparer = new JsonParser();
            String result = null;
            try
            {
                HttpResponse res = client.execute(get);
                String responseContent = null; // 初始化响应内容
                HttpEntity entity = (HttpEntity) res.getEntity();
                //设置编码格式
                responseContent = EntityUtils.toString((org.apache.http.HttpEntity) entity, "UTF-8");
                // 将json字符串转换为json对象
                JsonObject json = jsonparer.parse(responseContent).getAsJsonObject();
    
                if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
                {
                    if (json.get("errcode") != null){
                        // 错误时微信会返回错误码等信息,{"errcode":40013,"errmsg":"invalid appid"}
                    }
                    else{
                        // 正常情况下{"access_token":"ACCESS_TOKEN","expires_in":7200}
                        result = json.get("access_token").getAsString();
                    }
                }
            }
            catch (Exception e){
                e.printStackTrace();
            }
            finally{
                // 关闭连接 ,释放资源
                client.getConnectionManager().shutdown();
                return result;
            }
        }
    
        // 获取getTicket
        public static String getTicket(String apiurl,String access_token){
    
            String turl = String.format("%s?access_token=%s&type=jsapi",apiurl,access_token);
    
            HttpClient client = new DefaultHttpClient();
            HttpGet get = new HttpGet(turl);
    
            JsonParser jsonparer = new JsonParser();// 初始化解析json格式的对象
            String result = null;
            try
            {
                HttpResponse res = client.execute(get);
                String responseContent = null; // 响应内容
                HttpEntity entity = res.getEntity();
                responseContent = EntityUtils.toString(entity, "UTF-8");
                JsonObject json = jsonparer.parse(responseContent).getAsJsonObject();
    
                // 将json字符串转换为json对象
                if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                    if (json.get("errcode") == null){
                        // 错误时微信会返回错误码等信息,{"errcode":40013,"errmsg":"invalid appid"}
                    }
                    else{
                        // 正常情况下{"access_token":"ACCESS_TOKEN","expires_in":7200}
                        result = json.get("ticket").getAsString();
                    }
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                // 关闭连接 ,释放资源
                client.getConnectionManager().shutdown();
                return result;
            }
        }
    
        /**
         * <p>Discription: [生成签名]</p>
         *
         * @param ticket  jsapi_ticket
         * @param url url
         * @param nonce_str 随机字符串
         * @param timestamp 时间戳
         * @return 签名结果
         */
        public static String getSignature(String ticket,String url,String nonce_str,String timestamp) {
            Map<String, String> signParams = new HashMap<>();
            signParams.put("noncestr",nonce_str);
            signParams.put("jsapi_ticket",ticket);
            signParams.put("timestamp",timestamp);
            signParams.put("url", url);
            // 对请求参数排序,并生成签名原文
            String original = sort(signParams);
            // 使用sha1生成签名
            String signStr = DigestUtils.shaHex(original);
            return signStr;
        }
    
        /***
         *  MD5
         * @param original 原文
         * @return 哈希结果
         */
        private static String md5(String original) throws NoSuchAlgorithmException, UnsupportedEncodingException {
            MessageDigest messageDigest;
            messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.update(original.getBytes("UTF-8"));
            return byte2hex(messageDigest.digest());
        }
    
        /***
         *  sha1
         * @param original 原文
         * @return 加密结果
         */
        private static String sha1(String original){
            String sign = DigestUtils.shaHex(original);
            return sign;
        }
    
        /**
         * <p>Discription: [转换为16进制]</p>
         *
         * @param bytes 二进制
         * @return 16进制
         */
        private static String byte2hex(byte[] bytes) {
            StringBuilder sign = new StringBuilder();
            for (int i = 0; i < bytes.length; i++) {
                String hex = Integer.toHexString(bytes[i] & 0xFF);
                if (hex.length() == 1) {
                    sign.append("0");
                }
                sign.append(hex.toUpperCase());
            }
            return sign.toString();
        }
    
        /**
         * <p>Discription: [字典排序]</p>
         *
         * @param params 参数集合
         * @return 排序后的字符串,格式为:a=value1&b=value2&Secret
         */
        private static String sort(Map<String, String> params) {
            String[] keys = params.keySet().toArray(new String[0]);
            Arrays.sort(keys);
    
            StringBuilder query = new StringBuilder();
            for (String key : keys) {
                if (query.length() > 0) {
                    query.append("&");
                }
    
                String value = params.get(key);
                query.append(key).append("=").append(value);
            }
            return query.toString();
        }
    
    }
    

    相关文章

      网友评论

          本文标题:Java实现微信分享自定义文案和图片

          本文链接:https://www.haomeiwen.com/subject/azzhkctx.html