大家好,我是菜鸡Ha 

前端时间的业务需求有微信分享,那么我光荣的接下了这个任务,现在跟大家分享下心得,最容易出错的地方:

1.签名

2.分享的时候没有显示分享标题,分享内容,这里是分享链接有误,所以大家要仔细

3.仔细仔细再仔细,按照下面的方法,应该问题不大

官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

开始之前,我们先配置一点小东西

java微信转发功能 java 微信分享_java

                                   

java微信转发功能 java 微信分享_java微信转发功能_02

                

java微信转发功能 java 微信分享_JSON_03

设置完成后,我们开始吧

1,js代码

java微信转发功能 java 微信分享_java_04

 1.1 引用官方js

<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>

1.2 js代码(这个只提供了分享朋友圈跟好友,如果你要做QQ分享,微博什么的,那么继续在下面添加代码,官方文档里有)

$(function () {
    getSgt(window.location.href.split('#')[0]);
})
//-------------begin
//设置分享内容
        var title="分享标题";
	    var desc="分享内容";
	    var indexHref = window.location.href;
	    var shareLink=indexHref.toString();//分享链接
		var  shareImgUrl="http://img2.imgtn.bdimg.com/it/u=314418824,598838400&fm=26&gp=0.jpg";//分享图片
//-------------end
function getSgt(currUrl) {
    $.ajax({
        type: "POST",
        url: "/weixin/sgture.do?url="+encodeURIComponent(window.location.href.split('#')[0]),
        dataType: "json",
        success: function (response) {
             initWeChat(response.sgture,response.appid,response.shijianchuo,response.suijichuan);
            ready();
        }
    });
}

function ready() {
    wx.ready(function () {
        if (title == null || title == '') {
              alert("title is not null")
        }

        if (shareLink == null || shareLink == '') {
             alert("shareLink is not null")
        }
        //分享到---朋友圈,微信好友
        onMenuShareAppMessage(title, desc, shareLink, shareImgUrl);
        onMenuShareTimeline(title, desc, shareLink, shareImgUrl);
    });

}

function initWeChat(signature, appId,timestamp,noncestr) {
    wx.config({
        debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: appId, // 必填,公众号的唯一标识
        timestamp: "", // 必填,生成签名的时间戳
        nonceStr: "", // 必填,生成签名的随机串
        signature:"",//必填,签名
        jsApiList: [// 必填,需要使用的JS接口列表,所有JS接口列表见附录2
            'checkJsApi',
            'onMenuShareTimeline',//-----------------我们这里用了分享朋友圈
            'onMenuShareAppMessage',//----------------好友
            ]
    });
}

//分享给朋友
function onMenuShareAppMessage(title, desc, shareLink, imgUrl) {
    wx.onMenuShareAppMessage({
        title: title,
        desc: desc,
        link: shareLink,
        imgUrl: imgUrl,
        trigger: function (res) {
            // 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回
            // alert('用户点击发送给朋友'+JSON.stringify(res));
            wechatActionCallback('SHARE_FRIEND', 'CLICK');

        },
        success: function (res) {
            // alert('已分享'+JSON.stringify(res));
            wechatActionCallback('SHARE_FRIEND', 'SUCESS');
        },
        cancel: function (res) {
            wechatActionCallback('SHARE_FRIEND', 'CANCEL');
            // alert('已取消'+JSON.stringify(res));
        },
        fail: function (res) {
            wechatActionCallback('SHARE_FRIEND', 'FAIL');
            // alert(JSON.stringify(res));
        }
    });
}

//分享到朋友圈
function onMenuShareTimeline(title, desc, shareLink, imgUrl) {
    wx.onMenuShareTimeline({
        title: title, // 分享标题
        link: shareLink,// 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
        imgUrl: imgUrl,// 分享图标
        desc: desc,
        trigger: function (res) {
            // 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回
           //  alert('用户点击分享到朋友圈'+JSON.stringify(res));
            wechatActionCallback('SHARE_TIME_LINE', 'CLICK');
        },
        success: function (res) {
          //   alert('已分享'+JSON.stringify(res));
            wechatActionCallback('SHARE_TIME_LINE', 'SUCESS');
        },
        cancel: function (res) {
           //  alert('已取消'+JSON.stringify(res));
            wechatActionCallback('SHARE_TIME_LINE', 'CANCEL');
        },
        fail: function (res) {
          //
        	alert(JSON.stringify(res));
            wechatActionCallback('SHARE_TIME_LINE', 'FAIL');
        }
    });
}

 2,java后台代码

2.1 控制器

package com.xxx.xxx;

import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping(value = "/weixin")
public class WeiXinController {

	@RequestMapping("/sgture.do")
	@ResponseBody
	public Map<String, Object> sgture(HttpServletRequest request) {
		String strUrl=request.getParameter("url");
		WinXinEntity wx = WeiXinUnitl.getWinXinEntity(strUrl);
		// 将wx的信息到给页面
		Map<String, Object> map = new HashMap<String, Object>();
		String sgture = WXUnitl.getSignature(wx.getTicket(), wx.getNoncestr(), wx.getTimestamp(), strUrl);
		map.put("sgture", sgture.trim());//签名
		map.put("timestamp", wx.getTimestamp().trim());//时间戳
		map.put("noncestr",  wx.getNoncestr().trim());//随即串
        map.put("appid","这里写appid");//appID
		return map;
	}

}

2.2 工具类

这里的AppId,secret,管项目经理要

package com.xxx.xxx;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import net.sf.json.JSONObject;

public class WeiXinUnitl {
	public static WinXinEntity getWinXinEntity(String url) {
		WinXinEntity wx = new WinXinEntity();
		String access_token = getAccessToken();
		String ticket = getTicket(access_token);
		Map<String, String> ret = Sign.sign(ticket, url);
		wx.setTicket(ret.get("jsapi_ticket"));
		wx.setSignature(ret.get("signature"));
		wx.setNoncestr(ret.get("nonceStr"));
		wx.setTimestamp(ret.get("timestamp"));
		return wx;
	}

	// 获取token
	private static String getAccessToken() { 
        String access_token = "";  
        String grant_type = "client_credential";//获取access_token填写client_credential   
        String AppId="找你们老大要";//第三方用户唯一凭证  
        String secret="找你们老大要";//第三方用户唯一凭证密钥,即appsecret   
        //这个url链接地址和参数皆不能变  
        
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type="+grant_type+"&appid="+AppId+"&secret="+secret;  //访问链接

        try {  
            URL urlGet = new URL(url);  
            HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();  
            http.setRequestMethod("GET"); // 必须是get方式请求  
            http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");  
            http.setDoOutput(true);  
            http.setDoInput(true);  
            http.connect();  
            InputStream is = http.getInputStream();  
            int size = is.available();  
            byte[] jsonBytes = new byte[size];  
            is.read(jsonBytes);  
            String message = new String(jsonBytes);  
            JSONObject demoJson = JSONObject.fromObject(message);  
            access_token = demoJson.getString("access_token");  
            is.close();  
        } catch (Exception e) {  
                e.printStackTrace();  
        }  
        return access_token;  
    }

	// 获取ticket
	private static String getTicket(String access_token) {
		String ticket = null;
		String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token + "&type=jsapi";// 这个url链接和参数不能变
		try {
			URL urlGet = new URL(url);
			HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
			http.setRequestMethod("GET"); // 必须是get方式请求
			http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			http.setDoOutput(true);
			http.setDoInput(true);
			System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
			System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
			http.connect();
			InputStream is = http.getInputStream();
			int size = is.available();
			byte[] jsonBytes = new byte[size];
			is.read(jsonBytes);
			String message = new String(jsonBytes, "UTF-8");
			JSONObject demoJson = JSONObject.fromObject(message);
			ticket = demoJson.getString("ticket");
			is.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ticket;
	}
}

2.3 创建一个实体类

package com.xxx.xxx;

public class WinXinEntity {
	private String access_token;
	private String ticket;
	private String noncestr;
	private String timestamp;
	private String str;
	private String signature;

	public String getAccess_token() {
		return access_token;
	}

	public void setAccess_token(String access_token) {
		this.access_token = access_token;
	}

	public String getTicket() {
		return ticket;
	}

	public void setTicket(String ticket) {
		this.ticket = ticket;
	}

	public String getNoncestr() {
		return noncestr;
	}

	public void setNoncestr(String noncestr) {
		this.noncestr = noncestr;
	}

	public String getTimestamp() {
		return timestamp;
	}

	public void setTimestamp(String timestamp) {
		this.timestamp = timestamp;
	}

	public String getStr() {
		return str;
	}

	public void setStr(String str) {
		this.str = str;
	}

	public String getSignature() {
		return signature;
	}

	public void setSignature(String signature) {
		this.signature = signature;
	}

}

2.4 生成签名,随机串,时间戳

package com.xxx.xxx;

import java.util.UUID;
import java.util.Map;
import java.util.HashMap;
import java.util.Formatter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;

public 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 + "×tamp=" + timestamp + "&url=" + url;

		try {
			MessageDigest crypt = MessageDigest.getInstance("SHA-1");
			crypt.reset();
			crypt.update(string1.getBytes("UTF-8"));
			signature=	WXUnitl.getSignature(jsapi_ticket, nonce_str, timestamp, url);
		} 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;
	}

	// 生成nonce_str
	private static String create_nonce_str() {
		return UUID.randomUUID().toString();
	}

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

2.5 获取签名,随机串

package com.xxx.xxx;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Formatter;
import java.util.logging.Logger;
import org.hibernate.validator.internal.util.logging.LoggerFactory;

public class WXUnitl {

	public static String getSignature(String jsapi_ticket, String nonce_str, String timestamp, String url) {
		// 注意这里参数名必须全部小写,且必须有序
		String string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url="
				+ url;

		String signature = "";
		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();
		}
		return signature;
	}

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

3.下面开始调试吧

调试之前需要一个web调试工具,没有的可以下载

官方地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html