1. 程式人生 > >呼叫微信介面實現網頁分享小功能

呼叫微信介面實現網頁分享小功能

// 獲取access_token  *注意* 經過實際開發測試,微信分享不支援跨域請求,因此獲取access_token的請求必須從伺服器發起,否則無法獲取到access_token所以以下都是服務端操作

一、微信util類

public class ShareConstants {
    //微信獲取ticket的介面
    public static final String TICKET_URL_TEST = "https://api.weixin.qq.com/cgi-bin/ticket/getticket" ;
    public static final String type = "jsapi" ;
    //微信獲取token的介面
    public static final String GET_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
    public static final String grant_type = "client_credential" ;

}
public class WeixinUtil {

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

    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) ;
        logger.info("token:{},timestamp:{},nonce:{},testStr:{}");
        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) ;
        logger.info("signature url:{}",str);
        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", ShareConstants.grant_type) ;
        maps.put("appid",appId) ;
        maps.put("secret",secret) ;
        try{
            String result = HttpInvokeUtil.httpGet(ShareConstants.GET_TOKEN_URL,maps) ;
            JSONObject jsonObject = JSONObject.parseObject(result) ;
            String access_token = (String) jsonObject.get("access_token") ;
            Integer expires_in = (Integer) jsonObject.get("expires_in") ;
            logger.debug("getToken access_token:{},expires_in:{}",access_token,expires_in);
            if(access_token !=null && expires_in!=null && expires_in==7200)
                return access_token ;
            else
                return null ;
        }catch (Exception ex){
            logger.error("ex:stack:{}",ex.getStackTrace().toString());
            throw new Exception("get Token failed");
        }
    }

    public static String getJsApiTicket(String token) throws Exception{
        Map<String,String> maps = new HashMap<String,String>() ;
        maps.put("access_token",token);
        maps.put("type",ShareConstants.type);
        try{
            String result = HttpInvokeUtil.httpGet(ShareConstants.TICKET_URL_TEST,maps) ;
            JSONObject jsonObject = JSONObject.parseObject(result) ;
            Integer errcode = (Integer) jsonObject.get("errcode") ;
            if(errcode==null || (errcode!=null &&errcode!=0)){
                logger.error("get jsapiTicket is failed, errcode:{}",errcode);
                return null ;
            }else{
                String ticket = (String) jsonObject.get("ticket") ;
                return  ticket ;
            }
        }catch (Exception ex){
            logger.error("ex.stack:{}",ex.getStackTrace().toString());
            throw new Exception("getJsApi Ticket is failed") ;
        }
    }

}

注意上面HttpInvokeUtil.httpGet()是httpclint這個可以自己去寫,只要能發請求就行,

二、controller層

    //currUrl ==前端想要分享的網頁地址
    @RequestMapping(value = "/getWConfig", method = RequestMethod.GET)
    @ResponseBody
    //@RequiredLogin
    public FrameResp getWConfig(@Param("currUrl") String currUrl) throws UserException, Exception {
        if (currUrl == null) {
            return buildErrorResp(ErrorCodeConst.ERROR_PARAM_ERROR);
        }
        logger.info("get the encode currUrl {}", currUrl);

        String urlTmp = URLDecoder.decode(currUrl, "UTF-8");

        logger.info("decode currUrl {}", currUrl);

        Long timestamp = new Date().getTime() / 1000;
        String url = urlTmp.split("#")[0];

        WConfigResp wConfigResp = new WConfigResp();

        //修改為本地載入分享
        //shareConfig.getAppId()==自己的appid
        //shareConfig.getUxinAppSecret()==自己的AppSecret
        String token = WeixinUtil.getWeiXinShareToken(shareConfig.getAppId(), shareConfig.getUxinAppSecret());
        String ticket = WeixinUtil.getJsApiTicket(token);
        if (ticket == null) {
            logger.error("get jsApiTicketSec is failed");
            throw new Exception("get jsApi is failed");
        }
        wConfigResp.setAppid(shareConfig.getAppId());
        wConfigResp.setTimestamp(timestamp);
        wConfigResp.setNonceStr(RandomStringUtils.random(10, true, true));

        logger.info("appid:{},ticket:{},timestamp:{},nonceStr:{},url:{}", shareConfig.getAppId(), ticket, timestamp, wConfigResp.getNonceStr(), url);

        String signature = WeixinUtil.signature(ticket, wConfigResp.getNonceStr(), wConfigResp.getTimestamp(), url);
        if (signature != null) {
            wConfigResp.setSignature(signature);
            return buildSuccessResp(wConfigResp);
        } else {
            logger.error("getWcConfig is failed");
            throw new Exception("error getWConfig");
        }
    }

三、自定義的返回值類-WConfigResp

@Data
public class WConfigResp extends BaseModel{
    private String appid ;
    private Long  timestamp ;
    private String nonceStr;
    private String signature ;
}