面向微信开发

在做一个在微信分享文章的项目,在微信分享的链接要有描述图片必须调用微信的JS-SDK。而且现在(201904)只有企业认证的微信公众号/服务号微信才给分享接口的调用权限,普通/个人微信号公众号没有。

而且现在(201904)只有企业认证的微信公众号/服务号微信才给分享接口的调用权限,普通/个人微信号公众号没有,某宝光买一个认证的企业号就是几大百,微信开发真不容易ε=(´ο`*)))

还有一个需要注意的是,微信封域名可厉害了,普通域名撑不住多久,得想办法搞到备过案二级不死(主域名被封,二级域名一样可以用,换个前缀就行)域名。

基本调用流程是这样的,进入要分享页面的时候调用后台接口,后台接口请求微信获取调用凭证(Ticket)(注意Ticket调用获取是有调用上限的,两小时失效,也就是说两小时就得调用一次),JS-SDK拿到凭证后注册相关函数,点击分享到朋友圈或分享给朋友时触发相关函数设置描述图片

搞到企业认证的微信公众号

有企业认证的号才有权调用微信分享接口,查看自己有哪些接口可在下面网址查看,如果你的业务需要的接口个人号也能满足,那就不要搞,具体哪搞就看你有没有渠道和够不够聪明了┓( ´∀` )┏
查看有哪些接口调用权限(登录微信公众号->导航到左下角->接口权限):https://mp.weixin.qq.com/advanced/advanced?action=table&token=192206203&lang=zh_CN

设置安全域名

登录公众号->左边导航找到设置->功能设置->JS接口安全域名,会让你在你的服务器目录添加认证文件,就是一个普通的文本你文件

获取appID和AppSecret

登录公众号->左边导航找到开发->基本配置->公众号开发信息,注意AppSecret需自己保存

设置IP白名单

登录公众号->左边导航找到开发->基本配置->公众号开发信息->设置IP白名单,获取微信凭证时需要指定白名单里面的IP

前台调用

  • 页面引入js
<script src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script> // 备注:切记一定要是 https 不然后面会使IOS系统不好用
var wxshare =  function (aid) {
	var url = window.location.href.split('#')[0] // 当前页面的url ps:'#'前边的路径
	url = encodeURIComponent(url); //强烈注意:这里需要这样写
	var req = basePath + 'front/wxshare';
	$.ajax({
		url: req,
		type: 'post',
		data: {url:url,aid:aid},
		dataType: 'jsonp',
		success: function (_data_) {
			if (_data_ && _data_.resCode == 0){
				var res = _data_.res;
				wx.config({
					debug: true, //是否 开启调试模式,建议调试的时候debug 改为true,页面会自动弹窗说明调用成功或失败
					appId: res.appId, // 必填,公众号的唯一标识
					timestamp: res.timestamp, // 必填,生成签名的时间戳
					nonceStr: res.nonceStr, // 必填,生成签名的随机串
					signature: res.signature, // 必填,签名,见附录1
					jsApiList: [
						'checkJsApi',
						'updateAppMessageShareData',
						'updateTimelineShareData',
						'onMenuShareAppMessage',
						'onMenuShareTimeline',
						'showOptionMenu',
					] // 必填,需要使用的JS接口列表 声明
				});
				wx.error(function(res) {
					console.log("微信接口初始化失败;错误信息:"+res.toString());
				});
				window.onload = function() {
					console.log("当前域名是:"+res.url);
				}
				wx.ready(function() {
					//自定义“分享给朋友”及“分享到QQ”按钮的分享内容(1.4.0)
					wx.updateAppMessageShareData({
						debug: true,
						title: res.title, // 分享标题
						desc: res.desc, // 分享描述
						link: res.url, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
						imgUrl: res.cover, // 分享图标
						success: function() {
							// 用户点击了分享后执行的回调函数
						}
					});
					//自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容(1.4.0)
					wx.updateTimelineShareData({
						debug: true,
						title: res.title, // 分享标题
						desc: res.desc, // 分享描述
						link: res.url, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
						imgUrl: res.cover, // 分享图标
						success: function() {
							// 用户点击了分享后执行的回调函数
						}
					});
				});
			} else {
				console.log(req + '请求失败!' + _data_.msg);
			}
		},
		error: function (err) {
			console.log(req + '请求错误!' + err);
		}
	});
};
wxshare(aid);//aid为文章id

后台调用

@RequestMapping(value = "/wxshare",produces="text/html;charset=UTF-8")
@ResponseBody
public Object wxshare(String url,String aid){
	try{
		String ticket = "";//注意此处TICKET需全局保存,微信有调用上限,可以写定时任务一小时或者两小时调用一次
		url = URLDecoder.decode(url,"UTF-8");//注意URL需解码
		Map<String,String> res = WeixinUtil.sign(ticket,url);//签名后获取JS-SDK获取的一系列参数
		//你的逻辑
		return suc(res);
	} catch (Exception e){
		logger.error(e.getMessage(),e);
		return err(e.getMessage());
	}
}

WeixinUtil代码

package com.top.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import net.sf.json.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.MessageDigest;
import java.util.*;

public class WeixinUtil {

    private static Logger logger = LogManager.getLogger(WeixinUtil.class);

    private static ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 获取微信Ticket相关常量
     */
    public static String appId = "你的appid";
    public static String secret = "你的appsecret";
    public static String GRANT_TYPE = "client_credential";
    public static String GET_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
    public static String API_TYPE = "jsapi";
    public static String TICKET_URL_TEST = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";


    public static void main(String[] args) throws Exception{
        String url= "url=http%3A%2F%2Faaa.crhmovie.cn%2Farticle%2F1";
        String token = getWeiXinShareToken(appId,secret);
        String ticket = getJsApiTicket(token);
        Map<String,String> res = sign(ticket,url);
        System.out.println(res);
    }


    public static boolean signatureCheck(String token,String timeStamp,String nonce,String signature) throws Exception{
        List<String > list = new ArrayList<String>(3){
            public String toString(){
                return this.get(0)+this.get(1)+this.get(2) ;
            }
        } ;
        list.add(token) ;
        list.add(timeStamp) ;
        list.add(nonce) ;
        Collections.sort(list) ;
        MessageDigest md = MessageDigest.getInstance("SHA-1") ;
        byte[] digest = md.digest(list.toString().getBytes()) ;
        String testStr = WeixinUtil.byteArrayToHexString(digest) ;
        if(testStr.equalsIgnoreCase(signature.toUpperCase())){
            return true;
        }else{
            return false ;
        }
    }
    public static String signature(String jsapiTicket,String nonceStr,Long timestamp,String url) throws Exception{
        String str = String.format("jsapi_ticket=%s&noncestr=%s&timestamp=%d&url=%s",
                jsapiTicket,nonceStr,timestamp,url) ;
        MessageDigest md = MessageDigest.getInstance("SHA-1") ;
        byte[] digest = md.digest(str.getBytes()) ;

        String sigStr = WeixinUtil.byteArrayToHexString(digest) ;
        return sigStr ;
    }
    public static String byteArrayToHexString(byte[] array){
        String strDigest = "" ;
        for(int i = 0 ;i<array.length;i++){
            strDigest+=byteToHexString(array[i]) ;
        }
        return strDigest ;
    }
    public static String byteToHexString(byte ib){
        char[] Digit = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'} ;
        char [] ob = new char[2] ;
        ob[0] = Digit[(ib >>> 4) & 0X0F] ;
        ob[1] = Digit[ib &0X0F] ;
        String s = new String(ob) ;
        return s ;
    }
    public static String getWeiXinShareToken(String appId,String secret) throws Exception{
        Map<String,String> maps = new HashMap<String,String>() ;
        maps.put("grant_type", GRANT_TYPE) ;
        maps.put("appid",appId) ;
        maps.put("secret",secret);
        String result = httpGet(GET_TOKEN_URL,maps) ;
        JSONObject jsonObject = JSONObject.fromObject(result) ;
        String access_token = (String) jsonObject.get("access_token") ;
        Integer expires_in = (Integer) jsonObject.get("expires_in") ;
        logger.info("weixin---get--token--"+result);
        if(access_token !=null && expires_in!=null && expires_in==7200)
            return access_token;
        else
            throw new Exception(result);
    }

    public static String getJsApiTicket(String token) throws Exception{
        Map<String,String> maps = new HashMap<String,String>() ;
        maps.put("access_token",token);
        maps.put("type", API_TYPE);
        String result = httpGet(TICKET_URL_TEST,maps) ;
        System.out.println("weixin---get--ticket--"+result);
        JSONObject jsonObject = JSONObject.fromObject(result) ;
        Integer errcode = (Integer) jsonObject.get("errcode") ;
        if(errcode==null || (errcode!=null &&errcode!=0)){
            throw new Exception("getJsApi Ticket is failed:" + result) ;
        }else{
            String ticket = (String) jsonObject.get("ticket") ;
            return  ticket ;
        }
    }

    /**
     *
     * @param jsapi_ticket
     * @param url
     * @return
     * @throws Exception
     */
    public static Map<String, String> sign(String jsapi_ticket, String url) throws Exception {
        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;
        MessageDigest crypt = MessageDigest.getInstance("SHA-1");
        crypt.reset();
        crypt.update(string1.getBytes("UTF-8"));
        signature = byteToHex(crypt.digest());
        ret.put("url", url);
        //注意这里 要加上自己的appId
        ret.put("appId", appId);
        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);
    }


    /**
     * http请求工具类,post请求
     *
     * @param url    url
     * @param params 参数值 仅支持String和list两种类型
     * @return
     * @throws Exception
     */
    public static String httpPost(String url, Map<String, Object> params) throws Exception {
        DefaultHttpClient defaultHttpClient = null;
        BufferedReader bufferedReader = null;
        try {
            defaultHttpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", "application/json;charset=ut-8");
            if (params != null) {
                //转换为json格式并打印,不需要的你们可以不要
                String jsonParams = objectMapper.writeValueAsString(params);
                logger.info("参数值:{}", jsonParams);
                HttpEntity httpEntity = new StringEntity(jsonParams, "utf-8");
                httpPost.setEntity(httpEntity);
            }
            HttpResponse httpResponse = defaultHttpClient.execute(httpPost);
            if (httpResponse.getStatusLine().getStatusCode() != 200) {
                String errorLog="请求失败,errorCode:"+httpResponse.getStatusLine().getStatusCode();
                logger.info(errorLog);
                throw new Exception(url+errorLog);
            }
            //读取返回信息
            String output;
            bufferedReader=new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(),"utf-8"));
            StringBuilder stringBuilder=new StringBuilder();
            while ((output=bufferedReader.readLine())!=null){
                stringBuilder.append(output);
            }
            return stringBuilder.toString();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
            throw e;
        }catch (IOException e){
            e.printStackTrace();
            throw e;
        }finally {
            if(defaultHttpClient!=null)
                defaultHttpClient.getConnectionManager().shutdown();
            if(bufferedReader!=null)
                bufferedReader.close();
        }
    }

    /**
     * http请求工具类,get请求
     * @param url
     * @param params
     * @return
     * @throws Exception
     */
    public static String httpGet(String url, Map<String, String> params) throws Exception {
        DefaultHttpClient defaultHttpClient = null;
        BufferedReader bufferedReader = null;
        try {
            defaultHttpClient = new DefaultHttpClient();
            if(params!=null){
                StringBuilder stringBuilder=new StringBuilder();
                Iterator<String> iterator=params.keySet().iterator();
                String key;
                while (iterator.hasNext()){
                    key=iterator.next();
                    Object val=params.get(key);
                    if(val instanceof List){
                        List v= (List) val;
                        for (Object o:v){
                            stringBuilder.append(key).append("=").append(o.toString()).append("&");
                        }
                    }else{
                        stringBuilder.append(key).append("=").append(val.toString()).append("&");
                    }
                }
                stringBuilder.deleteCharAt(stringBuilder.length()-1);
                url=url+"?"+stringBuilder.toString();
                logger.info("url:{}",url);
            }
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("Content-Type", "application/json;charset=ut-8");
            HttpResponse httpResponse = defaultHttpClient.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() != 200) {
                String errorLog="请求失败,errorCode:"+httpResponse.getStatusLine().getStatusCode();
                logger.info(errorLog);
                throw new Exception(url+errorLog);
            }
            //读取返回信息
            String charSet="utf-8";
//            if(resonseCharSet!=null && resonseCharSet.length>0)
//                charSet=resonseCharSet[0];
            String output;
            bufferedReader=new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(),charSet));

            StringBuilder dataBuilder=new StringBuilder();
            while ((output=bufferedReader.readLine())!=null){
                dataBuilder.append(output);
            }
            return dataBuilder.toString();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
            throw e;
        }catch (IOException e){
            e.printStackTrace();
            throw e;
        }finally {
            if(defaultHttpClient!=null)
                defaultHttpClient.getConnectionManager().shutdown();
            if(bufferedReader!=null)
                bufferedReader.close();
        }
    }

}


排错

请看微信开发文档的服务5:附录5-常见错误及解决方法
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码狂魔v

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值