微信分享

微信分享后台功能处理:

1、获取微信jsapi_ticket,以及加密的基础类

import   org.springframework.beans.factory.annotation.Autowired;
import  org.springframework.stereotype.Component;  
@Component
public  class  PublicJsapiTicketURL {
     @Autowired
     WeixinConfig weixinConfig;
 
     /**
      * 获取jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据
      * @param access_token
      */
     public  String getJsapiTicketUrl(String access_token){
         return  weixinConfig.getApiHost()+ "/cgi-bin/ticket/getticket?access_token=" +access_token+ "&type=jsapi" ;
     }
 
}
 
 
import  net.sf.json.JSONObject;
import  org.springframework.beans.factory.annotation.Autowired;
import  org.springframework.stereotype.Component;
 
import  java.io.UnsupportedEncodingException;
import  java.security.MessageDigest;
import  java.security.NoSuchAlgorithmException;
import  java.text.ParseException;
import  java.util.Formatter;
import  java.util.HashMap;
import  java.util.Map;
import  java.util.UUID;
 
 
@Component
public  class  PublicJsapiTicketAPI {
 
     @Autowired
     PublicAPI publicAPI;
 
     @Autowired
     PublicJsapiTicketURL publicJsapiTicketURL;
 
     public  JSONObject getJsapiTicket(WXAccount wxAccount)  throws  WeixinRequestException, ParseException {
         JSONObject jsonObject = WeixinUtil.doGetStr(publicJsapiTicketURL.getJsapiTicketUrl(publicAPI.getAccess_token(wxAccount)));
         Integer errorCode = WeixinUtil.hasWxError(jsonObject);
         if  (errorCode !=  null ) {
             throw  new  WeixinRequestException(wxAccount.getAppId(), errorCode);
         }
         return  jsonObject;
     }
 
     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 +
                 "&timestamp="  + timestamp +
                 "&url="  + url;
         System.out.println(string1);
 
         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();
         }
 
         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;
     }
 
     private  static  String create_nonce_str() {
         return  UUID.randomUUID().toString();
     }
 
     private  static  String create_timestamp() {
         return  Long.toString(System.currentTimeMillis() /  1000 );
     }
 
 
}

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

Map<String,String> shareContent = new HashMap<String, String>();
shareContent.put("title","我申请了免费试用");//分享的title
shareContent.put("link","www.baidu.com");//分享的链接
shareContent.put("imgUrl","http://img.xxx.com/shop/images/201610/466_G_1476655499133.png");//分享的图标

url = "http://beta.weixin.xxx.com/xx.html";//当前的页面地址,测试地址,正式得获取当前的url
String appId = wxConfig.getAppid();//公众号的appId
ModuleRedisWeiXinPrefix.Prefix prefix = ModuleRedisWeiXinPrefix.Prefix.JSAPITICKET;
String jsApiTicket = redisSession.get(prefix.getCode());
if (StringUtils.isEmpty(jsApiTicket)){
    WXAccount wxAccount = storeService.getWXAccountFromAppId(appId);
 JSONObject jsonObject = publicJsapiTicketAPI.getJsapiTicket(wxAccount);
 jsApiTicket = (String)jsonObject.get("ticket");
 redisSession.set(prefix.getCode(),jsApiTicket,prefix.getTime());//把jsApiTicket存缓存
}

Map<String,String> signMap = PublicJsapiTicketAPI.sign(jsApiTicket, url);
signMap.put("appId",appId);
model.addAttribute("signMap", signMap);
model.addAttribute("shareContent",shareContent);

微信分享前台处理:

业务需求:分享后台设置的特定的分享链接,分享标题,分享图标到朋友圈。

结合微信JS-SDK文档:

1、在微信的公众号管理平台进行设置,进行了的设置后,才能改域名下进行微信开发的JS接口调用:

2、在需要调用微信JS的页面引入下面的js文件:

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

3、

<script>
     wx.config({
         debug:  true // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
         appId: '${signMap.appId}' // 必填,公众号的唯一标识
         timestamp:  '${signMap.timestamp}'  // 必填,生成签名的时间戳
         nonceStr:  '${signMap.nonceStr}' // 必填,生成签名的随机串
         signature:  '${signMap.signature}' , // 必填,签名,见附录1
         jsApiList: [
             'checkJsApi' ,
             'hideMenuItems' ,
             'onMenuShareTimeline' // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
     });
 
     wx.ready( function  () {
         wx.checkJsApi({
             jsApiList: [ 'onMenuShareTimeline' , 'hideOptionMenu' , 'hideMenuItems' ],  // 需要检测的JS接口列表,所有JS接口列表见附录2,
             success:  function (res) {
                 // 以键值对的形式返回,可用的api值true,不可用为false
                 // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
             }
         });
         wx.hideMenuItems({
             menuList: [ 'menuItem:share:appMessage' ,
                         'menuItem:share:qq' ,
                         'menuItem:share:weiboApp' ,
                         'menuItem:favorite' ,
                         'menuItem:share:facebook' ,
                         'menuItem:share:QZone' ,
                         'menuItem:editTag' , 'menuItem:delete' , 'menuItem:copyUrl' , 'menuItem:originPage' , 'menuItem:readMode' ,
                         'menuItem:openWithQQBrowser' , 'menuItem:openWithSafari' , 'menuItem:share:email' , 'menuItem:share:brand'
                         // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
         });
 
         config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,
         // config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。
         // 对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
         wx.onMenuShareTimeline({
             title:  '${shareContent.title}' // 分享标题
             link:  '${shareContent.link}' // 分享链接
             imgUrl:  '${shareContent.imgUrl}' // 分享图标
             success:  function  () {
                 alert( "分享成功1" );
                 // 用户确认分享后执行的回调函数
             },
             cancel:  function  () {
                 alert( "取消了分享1" )
                 // 用户取消分享后执行的回调函数
             }
         });
 
     });
 
 
     wx.error( function (res){
 
         // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
 
     });
 
 
 
</script>

该文中涉及的工具类如下:


import com.thoughtworks.xstream.XStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
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.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class WeixinUtil {
    @Autowired
    WeixinConfig weixinConfig;

    public WeixinUtil() {
    }

    public static Integer hasWxError(JSONObject jsonObject) {
        Object o = jsonObject.get("errcode");
        if(o != null && NumberUtil.isNumber(o.toString())) {
            Integer errorCode = Integer.valueOf(Integer.parseInt(o.toString()));
            return errorCode.intValue() == 0?null:errorCode;
        } else {
            return null;
        }
    }


    public static JSONObject doGetStr(String url) throws ParseException {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        JSONObject jsonObject = null;

        try {
            CloseableHttpResponse e = httpClient.execute(httpGet);
            HttpEntity entity = e.getEntity();
            if(entity != null) {
                String result = EntityUtils.toString(entity, "UTF-8");
                jsonObject = JSONObject.fromObject(result);
            }
        } catch (Exception var15) {
            var15.printStackTrace();
        } finally {
            httpGet.abort();

            try {
                httpClient.close();
            } catch (IOException var14) {
                var14.printStackTrace();
            }

        }

        return jsonObject;
    }

    public static String doPostStr(String outStr, String url) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(new StringEntity(outStr, "UTF-8"));
        String result = null;

        try {
            CloseableHttpResponse e = httpClient.execute(httpPost);
            result = EntityUtils.toString(e.getEntity(), "UTF-8");
        } catch (Exception var14) {
            var14.printStackTrace();
        } finally {
            httpPost.abort();

            try {
                httpClient.close();
            } catch (IOException var13) {
                var13.printStackTrace();
            }

        }

        return result;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值