最近完成了两个小业务的项目,一个是公司的接的报纸html新闻页面需要做带图标的微信分享,一个是公司的报纸库,
简单说就是一个报社的报纸电子化后,在网上展示,然后想添加注册、登录、实现权限不同能点击的也不同。
外带一个简单的后台对用户,管理员,权限进行处理。几周前做完,而这篇先讲一下微信分享。
博主也是之前没有接触过微信开发,虽然开发后,发现这个微信分享就是很简单的调用,但这也算是我的第一次。
首先感谢菜鸡ha:https://blog.csdn.net/weixin_38666555/article/details/82835087
先说明一下,微信分享从无到有,我的步骤是
第一步:申请微信公众平台的测试号
登录微信后就可以申请,用于开发时候测试用的,我们的公众号是客户的,麻烦,如果是自己的话直接用正式的也行。
测试号的话 每个都是服务器或者需要调用微信api的页面所在的域名,我的是服务器和页面不在一个域名底下,所以图一的url和安全域名不是一个域名,因为微信要用80端口。
第二步:部署服务器
我的是tomcat服务器,微信要用80端口,所以把默认8080改为80,然后微信还需要在公网能接到请求,所以需要一个域名,我的用的是natapp免费的内网穿透,还可以,主要我的业务不麻烦,所以natapp每天域名一变,不怎么影响我,具体设置百度就行,截个图。
第三步:开发
对于使用测试号的,需要编写两个接口,一个是token验证,一个是自己的业务请求。
1、token验证:
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class WeiXinController2 {
private static String WECHAT_TOKEN = "wx";//与微信设置的Token要相同
@RequestMapping(value = "/wx.action")
public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {
String echostr = request.getParameter("echostr"); // 随机字符串
PrintWriter out = response.getWriter();
out.print(echostr);
out.close();
}
}
2、自己的业务请求:
bean
public class WinXinEntity {
private String access_token;
private String ticket;
private String noncestr;
private String timestamp;
private String str;
private String signature;
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getTicket() {
return ticket;
}
public void setTicket(String ticket) {
this.ticket = ticket;
}
public String getNoncestr() {
return noncestr;
}
public void setNoncestr(String noncestr) {
this.noncestr = noncestr;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
}
控制类action:
package com.weixinserver.action;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.google.gson.Gson;
import com.weixinserver.bean.WinXinEntity;
import com.weixinserver.filter.WXUnitl;
import com.weixinserver.filter.WeiXinUnitl;
@Controller
public class WeiXinController {
@RequestMapping("getfour.action")
@ResponseBody
public String sgture(@RequestParam("ps") String ps,HttpServletRequest request) {
Gson gson=new Gson();
String strUrl=request.getParameter("url");
WinXinEntity wx = WeiXinUnitl.getWinXinEntity(strUrl);
// 将wx的信息到给页面
Map<String, Object> map = new HashMap<String, Object>();
String sgture = WXUnitl.getSignature(wx.getTicket(), wx.getNoncestr(), wx.getTimestamp(), strUrl);
map.put("sgture", sgture.trim());//签名
map.put("timestamp", wx.getTimestamp().trim());//时间戳
map.put("noncestr", wx.getNoncestr().trim());//随即串
map.put("appid","xxxxxxxxxxxxxxxxxx");//appID自己的
return ps+"("+gson.toJson(map)+")";
}
}
工具类sign.java
package com.weixinserver.filter;
import java.util.UUID;
import java.util.Map;
import java.util.HashMap;
import java.util.Formatter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;
public class Sign {
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 + "×tamp=" + timestamp + "&url=" + url;
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature= WXUnitl.getSignature(jsapi_ticket, nonce_str, timestamp, url);
} 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;
}
// 生成nonce_str
private static String create_nonce_str() {
return UUID.randomUUID().toString();
}
// 生成timestamp
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
工具类WeiXinUnitl.java
package com.weixinserver.filter;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import com.weixinserver.bean.WinXinEntity;
import net.sf.json.JSONObject;
public class WeiXinUnitl {
public static WinXinEntity getWinXinEntity(String url) {
WinXinEntity wx = new WinXinEntity();
String access_token = getAccessToken();
String ticket = getTicket(access_token);
Map<String, String> ret = Sign.sign(ticket, url);
wx.setTicket(ret.get("jsapi_ticket"));
wx.setSignature(ret.get("signature"));
wx.setNoncestr(ret.get("nonceStr"));
wx.setTimestamp(ret.get("timestamp"));
return wx;
}
// 获取token
private static String getAccessToken() {
String access_token = "";
String grant_type = "client_credential";//获取access_token填写client_credential
String AppId="xxxxxxxxxxxxxxxxxxxxxxxxxx";//第三方用户唯一凭证 appid自己的
String secret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";//第三方用户唯一凭证密钥,即appsecret 自己的
//这个url链接地址和参数皆不能变
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type="+grant_type+"&appid="+AppId+"&secret="+secret; //访问链接
try {
URL urlGet = new URL(url);
HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
http.setRequestMethod("GET"); // 必须是get方式请求
http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
http.connect();
InputStream is = http.getInputStream();
int size = is.available();
byte[] jsonBytes = new byte[size];
is.read(jsonBytes);
String message = new String(jsonBytes);
JSONObject demoJson = JSONObject.fromObject(message);
access_token = demoJson.getString("access_token");
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return access_token;
}
// 获取ticket
private static String getTicket(String access_token) {
String ticket = null;
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token + "&type=jsapi";// 这个url链接和参数不能变
try {
URL urlGet = new URL(url);
HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
http.setRequestMethod("GET"); // 必须是get方式请求
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
http.connect();
InputStream is = http.getInputStream();
int size = is.available();
byte[] jsonBytes = new byte[size];
is.read(jsonBytes);
String message = new String(jsonBytes, "UTF-8");
JSONObject demoJson = JSONObject.fromObject(message);
ticket = demoJson.getString("ticket");
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return ticket;
}
}
工具类WXUnitl.java
package com.weixinserver.filter;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
public class WXUnitl {
public static String getSignature(String jsapi_ticket, String nonce_str, String timestamp, String url) {
// 注意这里参数名必须全部小写,且必须有序
String string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url="
+ url;
String signature = "";
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();
}
return signature;
}
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;
}
}
页面调用:要导入jweixin的js,其他就是调用的问题了
代码如下:
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>//必须导入
<script type="text/javascript">
$(function () {
alert(window.location.href.split('#')[0]);
getSgt(window.location.href.split('#')[0]);
})
//-------------begin
//设置分享内容
var title=gettitle();
var desc=getcontent();
var indexHref = window.location.href;
var shareLink=indexHref.toString();//分享链接
var shareImgUrl="mages/defaultimg.png";//分享图片
//-------------end
//获取title方法
function gettitle(){
var gettitle = $("#main-title").text();
return gettitle;
}
//获取desc方法
function getcontent(){
var getcontent = $("#content").text();
return getcontent;
}
function getshareImgUrl(){
var defaultimg="mages/defaultimg.png";
var contentimg=($("#content").find('img').length);
alert(contentimg);
if(contentimg==0){
alert("528575");
return defaultimg;
}else{
alert("数据");
var firstimg=window.location.href.split('#')[0].split('content_')[0]+$("#content").find('img').eq(0).attr("src").split('/')[1];
alert(firstimg);
return firstimg;
}
}
function getSgt(currUrl) {
$.ajax({
type: "GET",
url: "http://xxxxxxxxxxx.com.cn/weixinserver/getfour.action?url="+encodeURIComponent(window.location.href.split('#')[0]),
dataType:"jsonp",
jsonp:"ps",
success: function (response) {
alert(response.sgture);
alert(response.appid);
alert(response.timestamp);
alert(response.noncestr);
initWeChat(response.sgture,response.appid,response.timestamp,response.noncestr);
ready();
},
failure : function(response,options) {
alert('failure response.responseText:'+response.responseText);
return;
}
});
}
function ready() {
wx.ready(function () {
if (title == null || title == '') {
alert("title is not null")
}
if (shareLink == null || shareLink == '') {
alert("shareLink is not null")
}
//分享到---朋友圈,微信好友
onMenuShareAppMessage(title, desc, shareLink, shareImgUrl);
onMenuShareTimeline(title, desc, shareLink, shareImgUrl);
onMenuShareQQ(title, desc, shareLink, shareImgUrl);
onMenuShareQZone(title, desc, shareLink, shareImgUrl);
});
}
function initWeChat(signature, appId,timestamp,noncestr) {
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: appId, // 必填,公众号的唯一标识
timestamp: timestamp, // 必填,生成签名的时间戳
nonceStr: noncestr, // 必填,生成签名的随机串
signature: signature,//必填,签名
jsApiList: [// 必填,需要使用的JS接口列表,所有JS接口列表见附录2
'checkJsApi',
'onMenuShareTimeline',//-----------------我们这里用了分享朋友圈
'onMenuShareAppMessage',//----------------好友
'onMenuShareQQ',
'onMenuShareQZone',
]
});
}
//分享给微信朋友
function onMenuShareAppMessage(title, desc, shareLink, imgUrl) {
wx.onMenuShareAppMessage({
title: title,
desc: desc,
link: shareLink,
imgUrl: imgUrl,
trigger: function (res) {
// 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回
// alert('用户点击发送给朋友'+JSON.stringify(res));
},
success: function (res) {
// alert('已分享'+JSON.stringify(res));
},
cancel: function (res) {
// alert('已取消'+JSON.stringify(res));
},
fail: function (res) {
// alert(JSON.stringify(res));
}
});
}
//分享到微信朋友圈
function onMenuShareTimeline(title, desc, shareLink, imgUrl) {
wx.onMenuShareTimeline({
title: title, // 分享标题
link: shareLink,// 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: imgUrl,// 分享图标
desc: desc,
trigger: function (res) {
// 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回
// alert('用户点击分享到朋友圈'+JSON.stringify(res));
},
success: function (res) {
// alert('已分享'+JSON.stringify(res));
},
cancel: function (res) {
// alert('已取消'+JSON.stringify(res));
},
fail: function (res) {
//
//alert(JSON.stringify(res));
}
});
}
//分享给qq朋友
function onMenuShareQQ(title, desc, shareLink, imgUrl) {
wx.onMenuShareQQ({
title: title,
desc: desc,
link: shareLink,
imgUrl: imgUrl,
trigger: function (res) {
// 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回
// alert('用户点击发送给朋友'+JSON.stringify(res));
},
success: function (res) {
// alert('已分享'+JSON.stringify(res));
},
cancel: function (res) {
// alert('已取消'+JSON.stringify(res));
},
fail: function (res) {
// alert(JSON.stringify(res));
}
});
}
//分享给qq空间
function onMenuShareQZone(title, desc, shareLink, imgUrl) {
wx.onMenuShareQZone({
title: title,
desc: desc,
link: shareLink,
imgUrl: imgUrl,
trigger: function (res) {
// 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回
// alert('用户点击发送给朋友'+JSON.stringify(res));
},
success: function (res) {
// alert('已分享'+JSON.stringify(res));
},
cancel: function (res) {
// alert('已取消'+JSON.stringify(res));
},
fail: function (res) {
// alert(JSON.stringify(res));
}
});
}
</script>
总结:微信分享的报错,大部分都是设置的问题比如安全域名,ip白名单等,可以就错误信息查找。
上面已经把前后台说了一遍,代码大部分不是自己写的,感谢下面两个博主,游客们也可以看看。
https://www.cnblogs.com/xjbBill/p/7868095.html
https://blog.csdn.net/weixin_38666555/article/details/82835087