微信H5分享 代码和详细配置步骤 js + Java 代码

正常分享状态显示:

微信H5分享 代码和详细配置步骤 js + Java 代码_第1张图片

分享异常状态显示:

微信H5分享 代码和详细配置步骤 js + Java 代码_第2张图片

一切变得那么的。。。无助!!!

开始以为在H5页面上添加一些东西即可,后来发现,完全不是自己想象的那个样子。

这个东西,对于一个从未用过微信JS的码农来说,或许要被带坑里去卡个几天!!!

以下是本人的一点点经验拿来和各位分享,希望刚接触到的少走一些弯路!

 

思路:

1.需要公众号一个,得到appid,appkey等等

2.需要在H5页面添加一些js方法,作用:调用微信api,获取access_tokenjsapi_ticket【api的每天调用次数有限,每次调用返回的结果也不同,即,会改变之前的token,之前的就会失效,分享结果也失效】

3.调用api目的就是通过 access_token 和 jsapi_ticket 得到“nonceStr”和“signature”

4.将获得的参数注入H5页面中的【wx.config】中,加载、配置微信分享参数

over。。。

 

官方的示例代码:http://demo.open.weixin.qq.com/jssdk/sample.zip

 

官方文档:点击打开链接

微信H5分享 代码和详细配置步骤 js + Java 代码_第3张图片

【调用次数有限,请注意】


 

确认签名算法是否正确工具

http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign

 

=================以下是本人开发的全部代码,如有遗漏代码,麻烦留言提示一下,谢谢

 

JAVA代码:

 


/****************************** js请求接口 ***************/

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 用途描述:微信内部点击分享Controller
 *
 * @author 
 * @version 1.0.0
 */
@RestController
@RequestMapping(value = "/wechat")
public class WeChatShareController {

    private final static Logger LOG = LoggerFactory.getLogger(WeChatShareController.class);

    @Autowired
    private WeChatShareService weChatShareService;

    /**
     * 获取微信加密信息
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/getsignature", method = {RequestMethod.GET})
    public Map toTranscript(@RequestParam(value = "url", required = true) String url) {
        Map data = new HashMap();

        try {   
			// 去数据库查询已保存的微信加密信息token等等(调用微信api获取token和保存的代码下面都有)
            Map wxInfo = weChatShareService.queryWechatInfo(url);
			
			data.put("wxInfo", wxInfo);
			
            return MsgCodeUtil.createMsg(MsgCodeUtil.CODE_SUCCESS, data);
        } catch (Exception e) {
            LOG.error("获取微信加密信息" + e.getMessage(), e);
			return MsgCodeUtil.createMsg(MsgCodeUtil.CODE_UNKNOWN_ERROR);
        }

    }
}


/****************************** WeChatShareService ***************/

/**
 * 用途描述:微信内部点击分享Service
 *
 * @version 1.0.0
 */
@Service
public class WeChatShareService {

    @Autowired
    private WechatShareTokenDao wechatShareTokenDao;


    /**
     * 获取微信加密信息
     *
     * @param url
     * @return
     * @throws Exception
     */
    public Map queryWechatInfo(String url) throws Exception {
        Map wxInfo = new HashMap<>();

        String accessToken = "";
        String jsapiTicket = "";
        //1、获取AccessToken和jsapiTicket,先从数据库获取最近一次保存的。
//        Map result = wechatShareTokenDao.queryWechatInfo();
//        if (null != result && !result.isEmpty()) {
//            accessToken = this.objToString(result.get("wechat_access_token"), "");
//            jsapiTicket = this.objToString(result.get("wechat_jsapi_ticket"), "");
//        }

        // 先不存储,直接调用api查询测试(注意:每日查询token次数有限,所以我们要自己定时获取并存储到数据库,
        // 每个token是2小时过期,我们间隔30分钟去更新一个就差不多了,时间设置多久自己看着办)
        accessToken = WeChatUitl.getAccessToken();
        jsapiTicket = WeChatUitl.getTicket(accessToken);

        //3、时间戳和随机字符串
        long currentTimes = System.currentTimeMillis();  // 时间戳
        String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串
        String timestamp = String.valueOf(currentTimes / 1000);// 时间戳

        //5、将参数排序并拼接字符串
        String params = "jsapi_ticket=" + jsapiTicket + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + url;

        //6、将字符串进行sha1加密
        String signature = WeChatUitl.getSHA1(params);

        //7、微信appId
        String appId = WeChatUitl.appIdWx;

        wxInfo.put("appId", appId);
        wxInfo.put("accessToken", accessToken);
        wxInfo.put("jsapiTicket", jsapiTicket);
        wxInfo.put("timestamp", timestamp);
        wxInfo.put("nonceStr", noncestr);
        wxInfo.put("params", params);
        wxInfo.put("signature", signature);

        return wxInfo;
    }


    public static String objToString(Object obj, String def) {
        return obj == null ? def : obj.toString();
    }

}






****************************** WeChatUitl ***************


import net.sf.json.JSONObject;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

/**
 * 用途描述: 微信开发获取信息---微信开放平台
 * (这个方法内参数不要去改,说不定会出什么问题,除了tokenWx,appIdWx,appSecretWx,keyWx修改为自己对应值)
 *
 * @version 1.0.0
 */
public class WeChatUitl {
	// 获取token的描述,自己定义就可以了
    public static final String tokenWx = "*****_token";

    public static final String appIdWx = "wx700000000000000"; // 微信appid---微信公众平台
    public static final String appSecretWx = "71**************************4"; // 微信AppSecret---微信公众平台
	
	// 测试号,可以在微信公众平台直接创建一个,下面我会贴图考诉你怎么创建,这些都是要获取微信token用的
//    public static final String appIdWx = "wx500000000000000"; // 微信appid---微信公众平台--测试号
//    public static final String appSecretWx = "8e**************************ad"; // 微信AppSecret---微信公众平台--测试号

	

    /**
     * 获取access_token
     *
     * @return
     */
    public static String getAccessToken() {
        String access_token = "";
        String grant_type = "client_credential";//获取access_token填写client_credential
        String AppId = appIdWx;//第三方用户唯一凭证
        String secret = appSecretWx;//第三方用户唯一凭证密钥,即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);
            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);
            System.out.println("JSON字符串:" + demoJson);
            access_token = demoJson.getString("access_token");
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return access_token;
    }


    /**
     * 获取jsapi_ticket
     *
     * @param access_token
     * @return
     */
    public 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);
            System.out.println("JSON字符串:" + demoJson);
            ticket = demoJson.getString("ticket");
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ticket;
    }


    /**
     * SHA、SHA1加密
     *
     * @parameter: str:待加密字符串
     * @return: 加密串
     **/
    public static String getSHA1(String str) {
        try {
            MessageDigest digest = java.security.MessageDigest
                    .getInstance("SHA-1"); //如果是SHA加密只需要将"SHA-1"改成"SHA"即可
            digest.update(str.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexStr = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexStr.append(0);
                }
                hexStr.append(shaHex);
            }
            return hexStr.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    

    public static void main(String[] args) {
        //1、获取AccessToken
        String accessToken = getAccessToken();
//        String accessToken = "6_Exc9VRFdPMLeF-4gPaJJGmoo-BJUGzgSJcs3vkT_y4eXPiQzRf1vdMvlVXNE85sfYH9AtQcdd-zptyD5t5S98VXSwIapyMoYjBNfvH7A11GZOoWs2u6agFlLS9NMqzTgN1N5V16BZrL1BnV_WTIaAIAHET";

        //2、获取Ticket
        String jsapi_ticket = getTicket(accessToken);

        //3、时间戳和随机字符串
        String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳

        System.out.println("accessToken:" + accessToken + "\njsapi_ticket:" + jsapi_ticket + "\n时间戳:" + timestamp + "\n随机字符串:" + noncestr);

        //4、获取url
        String url = "http://localhost:8080/project/share";

        // 根据JSSDK上面的规则进行计算,这里比较简单,我就手动写啦
//        String[] ArrTmp = {"jsapi_ticket","timestamp","nonce","url"};
//        Arrays.sort(ArrTmp);
//        StringBuffer sf = new StringBuffer();
//        for(int i=0;i createMsg(int code, String msg, Object data) {
		Map message = new HashMap();
		message.put("code", code);
		message.put("msg", setMsg(code, msg));
		if (data != null) {
			message.put("data", data);
		}
		
		return message;
	}
	
	public static Map createMsg(int code, String msg) {
		return createMsg(code, msg, null);
	}
	
	public static Map createMsg(int code, Object obj) {
		return createMsg(code, null, obj);
	}
	
	public static Map createMsg(int code) {
		return createMsg(code, null, null);
	}
	
	private static String setMsg(int code, String msg) {
		if (code == CODE_SUCCESS) {
			return StringUtils.isBlank(msg) ? MSG_SUCCESS : msg;
		} 
		
		if (code == CODE_FAILED) {
			return StringUtils.isBlank(msg) ? MSG_FAILED : msg;
		}
		
		if (code == CODE_UNAUTHORIZED) {
			return StringUtils.isBlank(msg) ? MSG_UNAUTHORIZED : msg;
		}
		
		if (code == CODE_UNKNOWN_ERROR) {
			return StringUtils.isBlank(msg) ? MSG_UNKNOWN_ERROR : msg;
		}
		
		return msg;
	}
}

 

H5,js代码

在需要分享的页面加入以下代码:

1.引入微信分享必须用到的 js




<%----这个页面写公共的JS方法,在下面-----%>


<%----或者封装成js文件再引入-----%>
<%---------%>
<%--------------------------------------- 微信分享结束 ---------------------------------%>



/****************************** wechat_share.jsp ***************/



 

===========================代码结束,接下来就是一个最麻烦的步骤了,公众平台配置


 

第二步:

1.注册/登录微信公众号,获取AppID和AppSecret

微信H5分享 代码和详细配置步骤 js + Java 代码_第4张图片

 

2.配置公众号业务域名和js安全域名

微信H5分享 代码和详细配置步骤 js + Java 代码_第5张图片
微信H5分享 代码和详细配置步骤 js + Java 代码_第6张图片

 

3,在公众号后台添加IP白名单

微信H5分享 代码和详细配置步骤 js + Java 代码_第7张图片

 

本机IP获取方式

调用“获取access_token”接口,返回结果。

微信H5分享 代码和详细配置步骤 js + Java 代码_第8张图片

错误信息显示ip无权限,就是这个

在这里也一起把线上服务器的IP也一起设置进去,因为每次设置的时候都要找老板的手机来扫微信二维码,脑壳疼

注意,如果线上服务器ip地址有变动,必须修改微信公众号ip白名单配置

4.最好先去申请一个域名(花生壳),用于测试,不然只有发布到线上测试了【微信只认域名,不认ip+端口】

微信H5分享 代码和详细配置步骤 js + Java 代码_第9张图片

 

花生壳配置:

微信H5分享 代码和详细配置步骤 js + Java 代码_第10张图片

IDEA   Tomcat 配置:

微信H5分享 代码和详细配置步骤 js + Java 代码_第11张图片

a.按照步骤下载文件,将文件复制到项目根目录tomcat项目根目录

下载文件:MP_verify_1pnZudconNzHFayL.txt   注意不要修改文件名称

b.在浏览器能访问到文件就OK


比如项目名是:tb_project
本地测试调用:http://192.168.88.91:8080/tb_project/MP_verify_1pnZudconNzHFayL.txt

花生壳调用:http://5743xhb03479.xxx/MP_verify_1pnZudconNzHFayL.txt

 

 

到这里,就完全到位了,over

 

关于定时保存token到自己的服务器,推荐用 spring scheduled,简单,方便,实用

 

spring_scheduled.xml配置文件



    
    

    
    

    
    

    
    
          
    

    
    

配置文件加好之后,PickTask这个类下面的【tickers】方法,30分钟执行一次。

具体使用方法,问度娘。

有关数据存储做好之后,最好再存储一下缓存,比如redis,每次分享就不用去查询数据库了

 

祝君好运!!!

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(经历路程)