Java微信分享接口开发详解

本文实例为大家分享了Java微信分享接口开发的具体代码,供大家参考,具体内容如下

Java微信分享,步骤是

1、根据当前的url,获取signature,nonceStr,timestamp 和appId。
2、通过signature,nonceStr,timestamp 和appId来配置微信 wx.config。
3、通过wx.ready实现微信分享功能。

1、html端

引入微信JS-SDK.

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
//分享核心js代码
$(document).ready(function () {
  //通过ajax,在页面加载的时候获取微信分享接口signature,nonceStr,timestamp 和appId
  $.ajax({
    type: "post",
    url: "/weixin/share",
    dataType: "json",
    data:"url="+window.location.href,
    success: function (data) {
      wx.config({
        debug: false,
        appId: data.appId,
        timestamp: data.timestamp,
        nonceStr: data.nonceStr,
        signature: data.signature,
        jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline', 'hideAllNonBaseMenuItem', 'showMenuItems']
        // 功能列表,我们要使用JS-SDK的什么功能
      });
      wx.ready(function () {
        // 获取“分享给朋友”按钮点击状态及自定义分享内容接口
        wx.onMenuShareAppMessage({
          title: "分享自定义标题", // 分享标题
          desc: "分享自定义描述", // 分享描述
          link: "http://localhost/weixin/share?openId=1",//分享点击之后的链接
          imgUrl:'/images/photo/1.jpg', // 分享图标
          type: 'link', // 分享类型,music、video或link,不填默认为link
          success: function () {
            //成功之后的回调
          }
        });
        wx.hideAllNonBaseMenuItem();
        wx.showMenuItems({
          menuList: ['menuItem:share:appMessage', 'menuItem:share:timeline'] // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
        });
        wx.onMenuShareTimeline({
          title: "分享自定义标题", // 分享标题
          desc: "分享自定义描述", // 分享描述
          link: "http://localhost/weixin/share?openId=1",//分享点击之后的链接
          imgUrl:'/images/photo/1.jpg', // 分享图标
          type: 'link', // 分享类型,music、video或link,不填默认为link
          success: function () {
            //成功之后的回调
          }
          cancel: function () {
            // 用户取消分享后执行的回调函数
          }
        });
      });
      wx.error(function (res) {
        //打印错误消息。及把 debug:false,设置为debug:ture就可以直接在网页上看到弹出的错误提示
      });
    }
  })
});

2、Java代码,获取 signature,nonceStr,timestamp 和appId

@RequestMapping(value = "/share", method = RequestMethod.POST)
  @ResponseBody
  public Map<String, Object> share(HttpServletRequest request) {
    String urlTemp = "http://" + request.getServerName() + request.getContextPath();
    String urlpath = "http://" + request.getServerName();
    String appUrl = request.getParameter("url");
    if (request.getParameter("code") != null) {
      appUrl += "&code=" + request.getParameter("code");
    }
    if (request.getParameter("state") != null) {
      appUrl += "&state=" + request.getParameter("state");
    }
    return WxConfigUtil.getSignature(appUrl, ContentValues.APPID, ContentValues.SECRET, urlTemp, urlpath);
  }

工具类我就把整个贴上来了,其中有些方法是没有用到的。

getSignature()整个方法是微信分享中的核心方法,用来获取signature,nonceStr,timestamp 和appId这几个核心参数。

package com.blog.common.util;

import com.alibaba.fastjson.JSONObject;
import com.blog.common.model.Token;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * 公众平台通用接口工具类
 *
 * @author james
 * @date 2015-02-27
 */
public class WxConfigUtil {
  // 获取access_token的接口地址(GET) 限2000(次/天)
  public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
  // 获取jsapi_ticket的接口地址(GET) 限2000(次/天)
  public final static String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
  // 缓存添加的时间
  public static String cacheAddTime = null;
  // token,ticket缓存
  public static Map<String, Token> TOKEN_TICKET_CACHE = new HashMap<String, Token>();
  // token对应的key
  private static final String TOKEN = "token";
  // ticket对应的key
  private static final String TICKET = "ticket";

  /**
   * 外部获取签名入口类
   *
   * @param appUrl  应用的url
   * @return
   */
  public static Map<String, Object> getSignature(String appUrl, String appId, String secret, String url, String urlpath) {
    // 生成签名的随机串
    String noncestr = RandomUtil.getStringRandom(4);
    if (appUrl == null || "".equals(appUrl)) {
      return null;
    }
    String signature = null;
    Token accessTocken = getToken(appId, secret, System.currentTimeMillis() / 1000);
    Token accessTicket = getTicket(accessTocken.getToken(), System.currentTimeMillis() / 1000);
    signature = signature(accessTicket.getTicket(), cacheAddTime, noncestr, appUrl);
    System.out.println("-=-=-=-=-=-=-=-=appUrl:" + appUrl);
    System.out.println("-=-=-=-=-=-=-=-=token:" + accessTocken.getToken());
    System.out.println("-=-=-=-=-=-=-=-=ticket:" + accessTicket.getTicket());
    System.out.println("-=-=-=-=-=-=-=-=signature:" + signature);
    System.out.println("-=-=-=-=-=-=-=-=timestamp:" + cacheAddTime);
    Map<String, Object> map = new HashMap<>();
    map.put("appId", appId);
    map.put("timestamp", cacheAddTime);
    map.put("nonceStr", noncestr);
    map.put("appUrl", appUrl);
    map.put("signature", signature);
    map.put("url", url);
    map.put("urlpath", urlpath);
    return map;
  }

  /**
   * 获得Token
   *
   * @return
   */
  public static String getToken(String appId, String secret) {
    Token accessTocken = getToken(appId, secret, System.currentTimeMillis() / 1000);
    return accessTocken.getToken();
  }

  /**
   * 签名
   *
   * @param timestamp
   * @return
   */
  private static String signature(String jsapi_ticket, String timestamp, String noncestr, String url) {
    jsapi_ticket = "jsapi_ticket=" + jsapi_ticket;
    timestamp = "timestamp=" + timestamp;
    noncestr = "noncestr=" + noncestr;
    url = "url=" + url;
    String[] arr = new String[]{jsapi_ticket, noncestr, timestamp, url};
    // 将token、timestamp、nonce,url参数进行字典序排序
    Arrays.sort(arr);
    StringBuilder content = new StringBuilder();
    for (int i = 0; i < arr.length; i++) {
      content.append(arr[i]);
      if (i != arr.length - 1) {
        content.append("&");
      }
    }
    MessageDigest md = null;
    String tmpStr = null;

    try {
      md = MessageDigest.getInstance("SHA-1");
      // 将三个参数字符串拼接成一个字符串进行sha1加密
      byte[] digest = md.digest(content.toString().getBytes());
      tmpStr = byteToStr(digest);
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    }

    content = null;
    return tmpStr;
  }

  /**
   * 获取access_token
   *
   * @param appid   凭证
   * @param appsecret 密钥
   * @return
   */
  public static Token getToken(String appid, String appsecret, long currentTime) {
    Token tockenTicketCache = getTokenTicket(TOKEN);
    Token Token = null;

    if (tockenTicketCache != null && (currentTime - tockenTicketCache.getAddTime() <= tockenTicketCache.getExpiresIn())) {// 缓存存在并且没过期
      System.out.println("==========缓存中token已获取时长为:" + (currentTime - tockenTicketCache.getAddTime()) + "毫秒,可以重新使用");
      return tockenTicketCache;
    }
    System.out.println("==========缓存中token不存在或已过期===============");
    String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
    JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
    // 如果请求成功
    if (null != jsonObject) {
      Token = new Token();
      Token.setToken(jsonObject.getString("access_token"));
      Token.setExpiresIn(jsonObject.getIntValue("expires_in") / 2);// 正常过期时间是7200秒,此处设置3600秒读取一次
      System.out.println("==========tocket缓存过期时间为:" + Token.getExpiresIn() + "毫秒");
      Token.setAddTime(currentTime);
      updateToken(TOKEN, Token);
    }
    return Token;
  }

  /**
   * 获取ticket
   *
   * @param token
   * @return
   */
  private static Token getTicket(String token, long currentTime) {
    Token tockenTicketCache = getTokenTicket(TICKET);
    Token Token = null;
    if (tockenTicketCache != null && (currentTime - tockenTicketCache.getAddTime() <= tockenTicketCache.getExpiresIn())) {// 缓存中有ticket
      System.out.println("==========缓存中ticket已获取时长为:" + (currentTime - tockenTicketCache.getAddTime()) + "毫秒,可以重新使用");
      return tockenTicketCache;
    }
    System.out.println("==========缓存中ticket不存在或已过期===============");
    String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN", token);
    JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
    // 如果请求成功
    if (null != jsonObject) {
      Token = new Token();
      Token.setTicket(jsonObject.getString("ticket"));
      Token.setExpiresIn(jsonObject.getIntValue("expires_in") / 2);// 正常过期时间是7200秒,此处设置3600秒读取一次
      System.out.println("==========ticket缓存过期时间为:" + Token.getExpiresIn() + "毫秒");
      Token.setAddTime(currentTime);
      updateToken(TICKET, Token);
    }
    return Token;
  }

  /**
   * 发起https请求并获取结果
   *
   * @param requestUrl  请求地址
   * @param requestMethod 请求方式(GET、POST)
   * @param outputStr   提交的数据
   * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
   */
  private static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
    JSONObject jsonObject = null;
    StringBuffer buffer = new StringBuffer();
    try {
      // 创建SSLContext对象,并使用我们指定的信任管理器初始化
      TrustManager[] tm = {new MyX509TrustManager()};
      SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
      sslContext.init(null, tm, new java.security.SecureRandom());
      // 从上述SSLContext对象中得到SSLSocketFactory对象
      SSLSocketFactory ssf = sslContext.getSocketFactory();

      URL url = new URL(requestUrl);
      HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
      httpUrlConn.setSSLSocketFactory(ssf);

      httpUrlConn.setDoOutput(true);
      httpUrlConn.setDoInput(true);
      httpUrlConn.setUseCaches(false);
      // 设置请求方式(GET/POST)
      httpUrlConn.setRequestMethod(requestMethod);

      if ("GET".equalsIgnoreCase(requestMethod))
        httpUrlConn.connect();

      // 当有数据需要提交时
      if (null != outputStr) {
        OutputStream outputStream = httpUrlConn.getOutputStream();
        // 注意编码格式,防止中文乱码
        outputStream.write(outputStr.getBytes("UTF-8"));
        outputStream.close();
      }

      // 将返回的输入流转换成字符串
      InputStream inputStream = httpUrlConn.getInputStream();
      InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
      BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

      String str = null;
      while ((str = bufferedReader.readLine()) != null) {
        buffer.append(str);
      }
      bufferedReader.close();
      inputStreamReader.close();
      // 释放资源
      inputStream.close();
      inputStream = null;
      httpUrlConn.disconnect();
      jsonObject = JSONObject.parseObject(buffer.toString());
      // jsonObject = JSONObject.fromObject(buffer.toString());
    } catch (ConnectException ce) {
      System.out.println("Weixin server connection timed out.");
    } catch (Exception e) {
      System.out.println("https request error:{}" + e.getMessage());
    }
    return jsonObject;
  }

  /**
   * 将字节数组转换为十六进制字符串
   *
   * @param byteArray
   * @return
   */
  private static String byteToStr(byte[] byteArray) {
    String strDigest = "";
    for (int i = 0; i < byteArray.length; i++) {
      strDigest += byteToHexStr(byteArray[i]);
    }
    return strDigest;
  }

  /**
   * 将字节转换为十六进制字符串
   *
   * @param mByte
   * @return
   */
  private static String byteToHexStr(byte mByte) {

    char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    char[] tempArr = new char[2];
    tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
    tempArr[1] = Digit[mByte & 0X0F];

    String s = new String(tempArr);
    return s;
  }

  /**
   * 从缓存中读取token或者ticket
   *
   * @return
   */
  private static Token getTokenTicket(String key) {
    if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {
      System.out.println("==========从缓存中获取到了" + key + "成功===============");
      return TOKEN_TICKET_CACHE.get(key);
    }
    return null;
  }

  /**
   * 更新缓存中token或者ticket
   *
   * @return
   */
  private static void updateToken(String key, Token accessTocken) {
    if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {
      TOKEN_TICKET_CACHE.remove(key);
      System.out.println("==========从缓存中删除" + key + "成功===============");
    }
    TOKEN_TICKET_CACHE.put(key, accessTocken);
    cacheAddTime = String.valueOf(accessTocken.getAddTime());// 更新缓存修改的时间
    System.out.println("==========更新缓存中" + key + "成功===============");
  }

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java编程调用微信分享功能示例

    本文实例讲述了Java编程调用微信分享功能.分享给大家供大家参考,具体如下: 这篇文章介绍如何使用java开发微信分享功能,因为工作,已经开发完成,可使用. 如果想要自定义微信的分享功能,首先在自己的页面内首先使用AJAX.下面我具体举例. 首先是在页面内写入请求后台的AJAX /** * 调用微信分享接口 * */ public void WXConfig(){ String url = getPara("href"); WXConfigController scan = new W

  • java开发微信分享到朋友圈功能

    微信分享功能开发 用了一天时间,把微信发送给朋友和分享到朋友圈功能开发出来,在这里给大家分享一下,避免大家走弯路. 一.服务器端程序 package com.wiimedia.controller; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.ParseException; import

  • Java实现微信公众平台朋友圈分享功能详细代码

    其实分享的方法在微信官网有较为详细的文档说明,现就其中一些比较绕的步骤进行总结,有问题随时交流哈. 首先微信其实已经自带分享到朋友圈,朋友,qq空间等功能,对于开发微信专门提供了一个接口,可以根据需要修改一些配置.例如修改要分享内容的头像,链接,描述等. 开发步骤: 1.在公众平台配置js-sdk接口 "公众号设置"--"功能设置"--"JS接口安全域名" 2.在要分享的页面引入js http://res.wx.qq.com/open/js/jw

  • 微信js-sdk+JAVA实现“分享到朋友圈”和“发送给朋友”功能详解

    主要为以下实现步骤: 1.绑定域名 先登录微信公众平台进入"公众号设置"的"功能设置"里填写"JS接口安全域名".(特别提示不需要加上http或者https,吃过亏) 2.页面引入js文件 <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>    <script src="https://res.wx

  • java开发微信分享接口的步骤

    微信分享接口的java开发的一些小步骤,具体内容如下 1.配置接口信息进行验证 代码如下: /** * 访问没认证的地址跳转 * * @param request * @return 登录页面 * @throws Exception */ @RequestMapping(value = "/checkWxDomainUrl", method = RequestMethod.GET) public void checkWxDomainUrl(HttpServletRequest requ

  • Java微信分享接口开发详解

    本文实例为大家分享了Java微信分享接口开发的具体代码,供大家参考,具体内容如下 Java微信分享,步骤是 1.根据当前的url,获取signature,nonceStr,timestamp 和appId. 2.通过signature,nonceStr,timestamp 和appId来配置微信 wx.config. 3.通过wx.ready实现微信分享功能. 1.html端 引入微信JS-SDK. <script src="http://res.wx.qq.com/open/js/jwe

  • js微信分享接口调用详解

    本文实例为大家分享了js微信分享接口调用的具体代码,供大家参考,具体内容如下 微信api直通车,仔细阅读官方文档问题都可以解决的 好吧,最近用到了,整理下发出来,就这个效果吧 1.设置js接口安全域名 这需要使用微信的jssdk,先需要在微信公众号后台进行设置:公众号设置-->功能设置-->JS接口安全域名.打开这个页面之后你会看到下面的提示.需要先下载这个文件并上传到指定域名的根目录. 这个文件里面是一个字符串,从名称看是用来校验用的.先上传了这个文件,你才能保存成功.这样你就可以使用jss

  • Java对象Serializable接口实现详解

    这篇文章主要介绍了Java对象Serializable接口实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 导读 最近这段时间一直在忙着编写Java业务代码,麻木地搬着Ctrl-C.Ctrl-V的砖,在不知道重复了多少次定义Java实体对象时"implements Serializable"的C/V大法后,脑海中突然冒出一个思维(A):问了自己一句"Java实体对象为什么一定要实现Serializable接口呢?&qu

  • 浅谈微信JS-SDK 微信分享接口开发(介绍版)

    本文主要是分享自己的开发过程,希望能给部分存在同样问题的朋友一点点帮助: 最近项目中的网页通过微信分享朋友或朋友圈等功能出现了无法显示分享图片等信息,后经过排查发现是微信版本升级导致,采用js-sdk完成分享接口,为了快速实现该功能效果,于是我打算通过前台js进行实现来看看分享效果. 通过查看微信公众平台文档,找到自己所需要的说明文档,明确开发步骤,说明文档截图如下: 开发步骤: 1.按照说明文档完成步骤1.1.1 2.引入js文件 在分享的页面中添加js文件 <script src="h

  • java中Serializable接口作用详解

    本文为大家解析java中Serializable接口的作用,具体内容如下 1.(serializable)主要支持对象的回复,所以可以用来保存当前的程序系统状态,远程方法调用RMI(远程机器必须含有必要的.class文件,否则将掷出classNotFound   Exception),但是因为它将对象数据自动全部保存,你根本无法插手,因此对于一些敏感字段(如:password)存在安全问题.但相应有很多解决的方法,例如可以在敏感字段的声明中使用transient关键字,或者去继承external

  • java微信支付接入流程详解

    背景 由于项目是采用java编写的,微信包括微信支付大都是php相关,于是微信支付官方文档对java的支持就不是很友好,在网上找了很多文章,基本上没有一篇是真正跑的通的,经过一番整理,先将java接入微信支付详细流程总结出来以便后续使用. 步骤一 准备阶段:已认证微信号,且通过微信支付认证,这个可以看微信文档,很详细,这里就不再重复. 步骤二 配置授权目录,官方推荐使用https类型的url,不知道http能不能行,个人也推荐使用https的保证不会错. 配置授权域名 步骤三 微信支付二次开发所

  • SpringBoot微信消息接口配置详解

    1.申请测试号,并记录appID和appsecret 2.关注测试号 3.添加消息模板 {{topic.DATA}} 用户名: {{user.DATA}} 单车编号:{{car.DATA}} 锁定时间:{{date.DATA}} {{remark.DATA}} 微信接口配置和代码 1.添加微信配置文件 import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframe

  • java 的Collection接口实例详解

    1. Collection是集合类的一个顶级接口,其直接继承接口有List与Set. Collection     |--List:元素是有序的,元素可以重复.因为该集合体系有索引.         |--ArrayList:底层的数据结构使用的是数组结构.特点:查询速度很快.但是增删稍慢.线程不同步.         |--LinkedList:底层使用的链表数据结构.特点:增删速度很快,查询稍慢.线程不同步.         |--Vector:底层是数组数据结构.线程同步.被ArrayLi

  • Java抽象类与接口区别详解

    很多常见的面试题都会出诸如抽象类和接口有什么区别,什么情况下会使用抽象类和什么情况你会使用接口这样的问题.本文我们将仔细讨论这些话题. 在讨论它们之间的不同点之前,我们先看看抽象类.接口各自的特性. 抽象类 抽象类是用来捕捉子类的通用特性的 .它不能被实例化,只能被用作子类的超类.抽象类是被用来创建继承层级里子类的模板.以JDK中的GenericServlet为例: public abstract class GenericServlet implements Servlet, ServletC

随机推荐