欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

微信分享接口 博客分类: wap q 

程序员文章站 2024-02-09 22:04:58
...

使用说明:

   在使用微信JS-SDK之前必须确认公众号已经获得使用微信js接口的权限,并且已填写安全域名,可登陆微信公众号平台查看。

1、引入微信js

<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js"></script>

2、根据需求添加js功能

<script type="text/javascript">
    var id = '${id}';//服务端设置的id,用于下面拼接生成需要分享的link
    var timestamp = parseInt('${ret.timestamp}');//因为服务端是String类型,此处转化成数值类型
    var nonceStr = '${ret.nonceStr}';
    var signature = '${ret.signature}';
    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: 'wxa034b7003154ee6c', // 必填,公众号的唯一标识
        timestamp: timestamp, // 必填,生成签名的时间戳
        nonceStr: nonceStr, // 必填,生成签名的随机串
        signature: signature,// 必填,签名,见附录1
        jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
    });

    wx.ready(function(){
        // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
        wx.onMenuShareTimeline({
            title: 'xxxxxxxxxxxxx', // 分享标题
            link: 'http://www.xxxxx.com:8082/xxx/xxx.do?id='+id, // 分享链接
            imgUrl: 'http://www.xxxxx.com:8080/xxx/xxx.jpg', // 分享图标
            success: function () { 
                // 用户确认分享后执行的回调函数
            },
            cancel: function () { 
                // 用户取消分享后执行的回调函数
            }
        });

        wx.onMenuShareAppMessage({
            title: 'xxxxxxx', // 分享标题
            desc: 'xxxxxxx', // 分享描述
            link: 'http://www.xxxxx.com:8082/xxx/xxx.do?id='+id, // 分享链接
            imgUrl: 'http://www.xxxxx.com:8080/xxx/xxx.jpg', // 分享图标
            type: '', // 分享类型,music、video或link,不填默认为link
            dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
            success: function () { 
                // 用户确认分享后执行的回调函数
            },
            cancel: function () { 
                // 用户取消分享后执行的回调函数
            }
        });
    });

</script>

 生成js页面需要的参数 及签名的生成:

   1、获取access_token, 因为一般有效期是7200s,所以添加到了ehcache中,默认先从缓存中获取,失效后再发送GET请求获取

Object act = EhcacheUtil.getInstance().get("weixin_jsapi", "access_token");
Object apiticket = EhcacheUtil.getInstance().get("weixin_jsapi", "ticket");
logger.debug("[act] = " + act + " [apiticket] = " + apiticket);
if (null == act) {

    String url = "https://api.weixin.qq.com/cgi-bin/token";
    String jsonStrToken = Tools.sendGet(url, "grant_type=client_credential&appid="+ appId + "&secret=" + appSecret);

    logger.debug("[jsonStrToken] = " + jsonStrToken);

    JSONObject json = JSONObject.fromObject(jsonStrToken);

    access_token = (String) json.getString("access_token");
    if (access_token == null) {
        return null;
    }
    EhcacheUtil.getInstance().put("weixin_jsapi", "access_token", access_token);
} else {
    access_token = (String) act;
}

   2、根据上一步中的access_token获取jsapi_ticket:

  

if (null == apiticket) {
    String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
    String jsonStrTicket = Tools.sendGet(url, "access_token=" + access_token + "&type=jsapi");

    logger.debug("[jsonStrTicket] = " + jsonStrTicket);

    JSONObject json = JSONObject.fromObject(jsonStrTicket);
    ticket = (String) json.get("ticket");

} else {
    ticket = (String) apiticket;
}

  3、获取当前需要分享的网页的URL:

  

//获取URL
String url = request.getRequestURL().toString();

  4、最终生成签名:

   (1)获取时间戳:

   

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

   (2)获取随机字符串:

  

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

  (3)将jsapi_ticket、noncestr、timestamp、url拼接,使用SHA1加密算法,最终生成签名

  

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

logger.debug("[string1] = " + string1);

try {
    MessageDigest crypt = MessageDigest.getInstance("SHA-1");
    crypt.reset();
    crypt.update(string1.getBytes("UTF-8"));
    signature = byteToHex(crypt.digest());

    logger.debug("[signature] = " + signature);

} catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}

  5、将服务端生成的noncestr、timestamp、signature设置到model(使用的是spring mvc)中,返回到页面:

  

Map<String, String> ret = sign.sign(jsapi_ticket, url);
mav.addObject("ret", ret);

var timestamp = parseInt('${ret.timestamp}');
var nonceStr = '${ret.nonceStr}';
var signature = '${ret.signature}';
wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: 'wxa034b7003154ee6c', // 必填,公众号的唯一标识
    timestamp: timestamp, // 必填,生成签名的时间戳
    nonceStr: nonceStr, // 必填,生成签名的随机串
    signature: signature,// 必填,签名,见附录1
    jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});

 完整的服务端代码:

  1、controller层:

//获取ticket
String jsapi_ticket = weiXinRequest.getWeiXinTicket();

logger.debug("[jsapi_ticket] = " + jsapi_ticket);

//获取URL
String url = request.getRequestURL().toString();

Map<String, String> ret = sign.sign(jsapi_ticket, url);
mav.addObject("ret", ret);
logger.debug("[ret] = " + ret);
return mav;

 2、weiXinRequest

  

import net.sf.json.JSONObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;

@Component("WeiXinRequest")
public class WeiXinRequest {

    private String appId = "wxa034b7003154ee6c";
    private String appSecret = "7fce4f1ee0f63b62f20fe8321a31dea8";

    private Log logger = LogFactory.getLog(WeiXinRequest.class);

    public String getWeiXinTicket() throws Exception {
        String access_token = "";
        String ticket = "";
        Object act = EhcacheUtil.getInstance().get("weixin_jsapi", "access_token");
        Object apiticket = EhcacheUtil.getInstance().get("weixin_jsapi", "ticket");
        logger.debug("[act] = " + act + " [apiticket] = " + apiticket);
        if (null == act) {

            String url = "https://api.weixin.qq.com/cgi-bin/token";
            String jsonStrToken = Tools.sendGet(url, "grant_type=client_credential&appid="+ appId + "&secret=" + appSecret);

            logger.debug("[jsonStrToken] = " + jsonStrToken);

            JSONObject json = JSONObject.fromObject(jsonStrToken);

            access_token = (String) json.getString("access_token");
            if (access_token == null) {
                return null;
            }
            EhcacheUtil.getInstance().put("weixin_jsapi", "access_token", access_token);
        } else {
            access_token = (String) act;
        }

        if (null == apiticket) {
            String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
            String jsonStrTicket = Tools.sendGet(url, "access_token=" + access_token + "&type=jsapi");

            logger.debug("[jsonStrTicket] = " + jsonStrTicket);

            JSONObject json = JSONObject.fromObject(jsonStrTicket);
            ticket = (String) json.get("ticket");

        } else {
            ticket = (String) apiticket;
        }

        return ticket;
        // 断开连接

    }
}

 3、Sign签名类:

 

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("Sign")
public class Sign {

    @Autowired
    private WeiXinRequest weiXinRequest;

    private Log logger = LogFactory.getLog(Sign.class);

    public Map<String, String> test(HttpServletRequest requesturl) throws Exception {
        String ticket = weiXinRequest.getWeiXinTicket();

        // 注意 URL 一定要动态获取,不能 hardcode
        String url = requesturl.getRequestURL().toString();
        Map<String, String> ret = sign(ticket, url);
        for (Map.Entry entry : ret.entrySet()) {
            System.out.println(entry.getKey() + ", " + entry.getValue());
        }
//      ret.put("appId", weiXinRequest.appId);
        return ret;
    };

    public 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;

        logger.debug("[string1] = " + string1);

        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());

            logger.debug("[signature] = " + signature);

        } 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);

        logger.debug("[ret] = " + ret);

        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);
    }

    /**
     * 用SHA1算法生成安全签名
     * 
     * @param token
     *            票据
     * @param timestamp
     *            时间戳
     * @param nonce
     *            随机字符串
     * @param encrypt
     *            密文
     * @return 安全签名
     * @throws NoSuchAlgorithmException
     * @throws AesException
     */
    public String getSHA1(String token, String timestamp, String nonce)
            throws NoSuchAlgorithmException {
        String[] array = new String[] { token, timestamp, nonce };
        StringBuffer sb = new StringBuffer();
        // 字符串排序
        Arrays.sort(array);
        for (int i = 0; i < 3; i++) {
            sb.append(array[i]);
        }
        String str = sb.toString();
        // SHA1签名生成
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        md.update(str.getBytes());
        byte[] digest = md.digest();

        StringBuffer hexstr = new StringBuffer();
        String shaHex = "";
        for (int i = 0; i < digest.length; i++) {
            shaHex = Integer.toHexString(digest[i] & 0xFF);
            if (shaHex.length() < 2) {
                hexstr.append(0);
            }
            hexstr.append(shaHex);
        }
        return hexstr.toString();
    }
}

 4、发送请求类Tools  这里用的是 Url 、UrlConnection 类 类似于httpClient

  

/**
     * 向指定URL发送GET方法的请求
     * 
     * @param url
     *            发送请求的URL
     * @param param
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.out.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }

        } catch (Exception e) {
            System.out.println("发送GET请求出现异常!" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 向指定 URL 发送POST方法的请求
     * 
     * @param url
     *            发送请求的 URL
     * @param param
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常!"+e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;
    }

 

  

 

相关标签: q