钉钉提供的内网穿透之HTTP穿透:https://www.cnblogs.com/pxblog/p/13862376.html

网页分享到微信中如何显示标题图,如果自定义标题图,描述,显示效果如下

官网接口地址;https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html

加入maven依赖

    <dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>[4.1.12,)</version>
</dependency> <dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20171018</version>
</dependency>
HttpClientUtil.java
package com.test.cms.share;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager; import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
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.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils; public class HttpClientUtil { private static class SingletonHolder{
private final static HttpClientUtil INSTANCE=new HttpClientUtil();
} private HttpClientUtil(){} public static HttpClientUtil getInstance(){
return SingletonHolder.INSTANCE;
} public String get(String url){
CharsetHandler handler = new CharsetHandler("UTF-8");
CloseableHttpClient client = null;
try {
HttpGet httpget = new HttpGet(new URI(url));
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
client= httpClientBuilder.build();
client = (CloseableHttpClient) wrapClient(client);
return client.execute(httpget, handler);
} catch (Exception e) {
//e.printStackTrace();
return "";
}finally {
try {
if(client!=null){
client.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} public static String post(String url, String params,String contentType)
{ //创建HttpClientBuilder
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
//HttpClient
CloseableHttpClient client = httpClientBuilder.build();
client = (CloseableHttpClient) wrapClient(client); HttpPost post = new HttpPost(url);
CloseableHttpResponse res = null;
try
{
StringEntity s = new StringEntity(params,"UTF-8");
if(StringUtils.isBlank(contentType)){
s.setContentType("application/json");
}
s.setContentType(contentType);
s.setContentEncoding("utf-8");
post.setEntity(s);
res = client.execute(post);
HttpEntity entity = res.getEntity();
return EntityUtils.toString(entity, "utf-8");
}
catch (Exception e)
{
e.printStackTrace();
} finally {
try {
res.close();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return "";
} public static String post(String urlStr,String xmlInfo) {
String line1 = "";
try {
URL url = new URL(urlStr);
URLConnection con = url.openConnection();
con.setDoOutput(true);
//con.setRequestProperty("Pragma:", "no-cache");
con.setRequestProperty("Cache-Control", "no-cache");
con.setRequestProperty("Content-Type", "text/xml"); OutputStreamWriter out = new OutputStreamWriter(con
.getOutputStream());
out.write(new String(xmlInfo.getBytes("utf-8")));
out.flush();
out.close();
BufferedReader br = new BufferedReader(new InputStreamReader(con
.getInputStream()));
String line = "";
for (line = br.readLine(); line != null; line = br.readLine()) {
line1+=line;
}
return new String(line1.getBytes(),"utf-8");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
} private class CharsetHandler implements ResponseHandler<String> {
private String charset; public CharsetHandler(String charset) {
this.charset = charset;
} public String handleResponse(HttpResponse response)
throws ClientProtocolException, IOException {
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() >= 300) {
throw new HttpResponseException(statusLine.getStatusCode(),
statusLine.getReasonPhrase());
}
HttpEntity entity = response.getEntity();
if (entity != null) {
if (!StringUtils.isBlank(charset)) {
return EntityUtils.toString(entity, charset);
} else {
return EntityUtils.toString(entity);
}
} else {
return null;
}
}
} private static HttpClient wrapClient(HttpClient base) {
try {
SSLContext ctx = SSLContext.getInstance("TLSv1");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs,
String string) throws CertificateException {
} public void checkServerTrusted(X509Certificate[] xcs,
String string) throws CertificateException {
} public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[] { tm }, null);
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx, new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
return httpclient; } catch (Exception ex) {
return null;
}
} }
RandomStr.java
package com.test.cms.share;

import java.util.Random;

public class RandomStr {

    private static char ch[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '0', '1' };//最后又重复两个0和1,因为需要凑足数组长度为64 private static Random random = new Random(); //生成指定长度的随机字符串
public static String createRandomString(int length) {
if (length > 0) {
int index = 0;
char[] temp = new char[length];
int num = random.nextInt();
for (int i = 0; i < length % 5; i++) {
temp[index++] = ch[num & 63];//取后面六位,记得对应的二进制是以补码形式存在的。
num >>= 6;//63的二进制为:111111
// 为什么要右移6位?因为数组里面一共有64个有效字符。为什么要除5取余?因为一个int型要用4个字节表示,也就是32位。
}
for (int i = 0; i < length / 5; i++) {
num = random.nextInt();
for (int j = 0; j < 5; j++) {
temp[index++] = ch[num & 63];
num >>= 6;
}
}
return new String(temp, 0, length);
}
else if (length == 0) {
return "";
}
else {
throw new IllegalArgumentException();
}
} public static void main(String[] args) {
System.out.println(createRandomString(16));
}
}
Sha1.java
package com.test.cms.share;

import java.security.MessageDigest;

public class Sha1 {

    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; private static String getFormattedText(byte[] bytes) {
int len = bytes.length;
StringBuilder buf = new StringBuilder(len * 2);
// 把密文转换成十六进制的字符串形式
for (int j = 0; j < len; j++) {
buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
}
return buf.toString();
} public static String encode(String str) {
if (str == null) {
return null;
}
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
messageDigest.update(str.getBytes());
return getFormattedText(messageDigest.digest());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

控制器类

ShareController.java

package com.test.cms.share;

import cn.hutool.json.JSONUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.URI;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map; @Controller
public class ShareController { /**
* 微信公众号的appid
*/
private String appid="wxd"; /**
* 微信公众号的appSecret
*/
private String secret="ebded33"; /**
* 这是跳转到分享的页面
* @return
*/
@RequestMapping(value = "/to_detail")
public String share(){
return "/index/share";
} /**
* 获取微信分享配置的请求 方法只写了主要方法,需要根据自己的要求 完善代码
* @param url 前台传过来的当前页面的请求地址
* @return
*/
@RequestMapping(value = "/get_wx_config")
@ResponseBody
public String share(String url){
long timestamp = System.currentTimeMillis() / 1000;
String noncestr = RandomStr.createRandomString(16);
String ticket =getJsapiTicket();
String str = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;
System.out.println("签名str:" + str);
String signature = Sha1.encode(str); //这只是简单写法,没有做错误判断
Map map=new HashMap();
map.put("appId",appid);
map.put("timestamp",timestamp);
map.put("nonceStr",noncestr);
map.put("signature",signature); //这里使用了hutool工具将map转为String
String json = JSONUtil.toJsonStr(map); return json;
} /**
* 官方文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#62
*
* 获取jsapi_ticket
*
*
* 生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。
* 正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。
* 由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。
*
* 参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):
* https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
*
* 用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):
* https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
*
* @return
*/
public String getJsapiTicket() {
String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
tokenUrl = tokenUrl + "&appid=" + appid + "&secret=" + secret;
JSONObject tokenJson=new JSONObject();
tokenJson=getUrlResponse(tokenUrl);
System.out.println("tokenJson:"+tokenJson.toString());
String token="";
try {
token=tokenJson.getString("access_token");
} catch (JSONException e) {
e.printStackTrace();
System.out.println("报错了");
return null;
} String jsapiTicketUrl="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
JSONObject jsapiTickeJson=new JSONObject();
System.out.println("getJsapiTicket:获取token:"+token);
if(StringUtils.isNotBlank(token)){
jsapiTicketUrl = jsapiTicketUrl.replace("ACCESS_TOKEN",token);
jsapiTickeJson=getUrlResponse(jsapiTicketUrl);
System.out.println("tokenJson:"+jsapiTickeJson.toString());
try {
return (String) jsapiTickeJson.get("ticket");
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}else{
return null;
}
} private JSONObject getUrlResponse(String url){
CharsetHandler handler = new CharsetHandler("UTF-8");
try {
HttpGet httpget = new HttpGet(new URI(url));
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
//HttpClient
CloseableHttpClient client = httpClientBuilder.build();
client = (CloseableHttpClient) wrapClient(client);
return new JSONObject(client.execute(httpget, handler));
} catch (Exception e) {
e.printStackTrace();
return null;
}
} private static HttpClient wrapClient(HttpClient base) {
try {
SSLContext ctx = SSLContext.getInstance("TLSv1");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs,
String string) throws CertificateException {
} public void checkServerTrusted(X509Certificate[] xcs,
String string) throws CertificateException {
} public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[] { tm }, null);
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx, new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
return httpclient; } catch (Exception ex) {
return null;
}
} private class CharsetHandler implements ResponseHandler<String> {
private String charset; public CharsetHandler(String charset) {
this.charset = charset;
} public String handleResponse(HttpResponse response)
throws ClientProtocolException, IOException {
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() >= 300) {
throw new HttpResponseException(statusLine.getStatusCode(),
statusLine.getReasonPhrase());
}
HttpEntity entity = response.getEntity();
if (entity != null) {
if (!StringUtils.isBlank(charset)) {
return EntityUtils.toString(entity, charset);
} else {
return EntityUtils.toString(entity);
}
} else {
return null;
}
}
} }

页面主要代码、这里展示的是分享给朋友、分享到朋友圈代码,其他分享可以具体看官方接口代码

share.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>分享页面给朋友,朋友圈</title>
</head> <body> </body>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
<script type="text/javascript">
$(function () {
//当前页面的url地址
var currUrl = decodeURIComponent(location.href.split('#')[0]);
$.ajax({
url: "/get_wx_config",
dataType : "json",
data: {
'url': currUrl
},
error: function (res) {
console.log(res);
alert("发生错误");
},
success: function (res) {
console.log(res);
var appId = res.appId;
var nonceStr = res.nonceStr;
var timestamp = res.timestamp;
var signature = res.signature;
wx.config({
debug: false, //开启调试模式,开发阶段可以改成true,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: appId, //必填,公众号的唯一标识
timestamp: timestamp, // 必填,生成签名的时间戳
nonceStr: nonceStr, //必填,生成签名的随机串
signature: signature, // 必填,签名,见附录1
jsApiList: [ //必填,需要使用的JS接口列表,所有JS接口列表 见附录2
'updateAppMessageShareData',
'updateTimelineShareData'
]
}); wx.ready(function () { //需在用户可能点击分享按钮前就先调用
//分享给朋友”及“分享到QQ”
wx.updateAppMessageShareData({
title: '朋友我是标题', // 分享标题
desc: '朋友 我是描述', // 分享描述
link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: '', // 分享图标
success: function (res) {
// 设置成功
}
}) //分享到朋友圈”及“分享到QQ空间
wx.updateTimelineShareData({
title: '朋友圈我是标题', // 分享标题
link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: '', // 分享图标
success: function (res) {
// 设置成功
}
}) }); wx.error(function (res) { });
}
}); }); </script>
</html>

设置公众号的js安全域名

把域名放进去,不用加http的前缀,点击保存即可

保存之前要把文件下载下来放到项目根目录下,如果是开发环境的springboot项目可以参照这个教程做

https://www.cnblogs.com/pxblog/p/13445128.html

JAVA调用微信接口实现页面分享功能(分享到朋友圈显示图片,分享给朋友)的更多相关文章

  1. [实例]JAVA调用微信接口发送图文消息,不用跳到详情页

    package com.test; import java.io.IOException; import java.io.InputStream; import java.io.OutputStrea ...

  2. C# 调用微信接口的代码

    调用微信接口前需要准备的内容. 1.微信公众平台的appid 2.微信公众平台的secret 3..获取tokenid 4.获取ticket 5.生成签名的随机串 6.生成签名的时间戳 7.生成签名 ...

  3. C# 关于调用微信接口的代码

    调用微信接口前需要准备的内容. 1.微信公众平台的appid 2.微信公众平台的secret 3..获取tokenid 4.获取ticket 5.生成签名的随机串 6.生成签名的时间戳 7.生成签名 ...

  4. Java 调用http接口(基于OkHttp的Http工具类方法示例)

    目录 Java 调用http接口(基于OkHttp的Http工具类方法示例) OkHttp3 MAVEN依赖 Http get操作示例 Http Post操作示例 Http 超时控制 工具类示例 Ja ...

  5. Java调用webservice接口方法

                             java调用webservice接口   webservice的 发布一般都是使用WSDL(web service descriptive langu ...

  6. C# 调用微信接口上传素材和发送图文消息

    using Common;using Newtonsoft.Json.Linq;using System;using System.IO;using System.Net;using System.T ...

  7. (二)通过JAVA调用SAP接口 (增加一二级参数)

    (二)通过JAVA调用SAP接口 (增加一二级参数) 一.建立sap连接 请参考我的上一篇博客 JAVA连接SAP 二.测试项目环境准备 在上一篇操作下已经建好的环境后,在上面的基础上新增类即可 三. ...

  8. Java调用RestFul接口

    使用Java调用RestFul接口,以POST请求为例,以下提供几种方法: 一.通过HttpURLConnection调用 1 public String postRequest(String url ...

  9. Android 仿微信朋友圈发表图片拖拽和删除功能

    朋友圈实现原理 我们使用 Android Device Monitor 来分析朋友圈发布图片的界面实现原理.如果需要分析其他应用的界面实现也是采用这种方法哦. 打开 Android Device Mo ...

随机推荐

  1. 【豆科基因组】木豆Pigeonpea (Cajanus cajan) 292个自然群体重测序2017NG

    目录 一.来源 二.结果 一.来源 Whole-genome resequencing of 292 pigeonpea accessions identifies genomic regions a ...

  2. [R] 如何在Linux命令行进行参数传入?

    以前由于R命令行传参不友好,经常嵌套在其他程序语言(如Perl/Python)中来进行传参,但现在也陆续有一些方式来实现R的传参了,这里简单罗列下. 方法一 最传统的方法就是使用系统自带的comman ...

  3. rust shadow

    1 fn main() { 2 let mut demo = 12; 3 println!("{}",demo); 4 demo = 21; // 值可变,数据类型不可变 5 pr ...

  4. header 301,显示302

    header 301,显示302 一定要注意Location 后面的":"前后都不能有空格 header('HTTP/1.1 301 Moved Permanently'); he ...

  5. C++面试基础篇(一)

    1. static关键字的作用 (1)全局静态变量 在全局变量前面加上关键字static, 全局变量就定义为一个全局静态变量 在静态存储区,在整个程序运行期间一致存在. 初始化:未初始化的全局静态变量 ...

  6. (转载)SQL Server 2008 连接JDBC详细图文教程

    点评:SQL Server 2008是目前windows上使用最多的sql数据库,2008的安装机制是基于framework重写的,特点是非常耗时间SQL Server 2008是目前windows上 ...

  7. 非标准的xml解析器的C++实现:三、解析器的初步实现

    如同我之前的一篇文章说的那样,我没有支持DTD与命名空间, 当前实现出来的解析器,只能与xmlhttp对比,因为chrome浏览器解析大文档有bug,至于其他人实现的,我就不一一测试了,既然都决定自己 ...

  8. 34、在排序数组中查找元素的第一个和最后一个位置 | 算法(leetode,附思维导图 + 全部解法)300题

    零 标题:算法(leetode,附思维导图 + 全部解法)300题之(34)在排序数组中查找元素的第一个和最后一个位置 一 题目描述 二 解法总览(思维导图) 三 全部解法 1 方案1 1)代码: / ...

  9. a这个词根

    a是个词根,有三种意思:1. 以某种状态或方式,如: ablaze, afire, aflame, alight, aloud, alive, afloat等2. at, in, on, to sth ...

  10. 【Reverse】每日必逆0x01

    附件:https://files.buuoj.cn/files/7458c5c0ce999ac491df13cf7a7ed9f1/SimpleRev 题解 查壳 64位ELF文件,无壳 IDApro处 ...