1. 引入微信 JS-SDK js文件
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
2. 绑定域名
(1)先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
备注:登录后可在“开发者中心”查看对应的接口权限。
(2)先登录微信公众平台进入“公众号设置”的“基本设置”里填写“JS接口安全域名”。
3. 通过config接口注入权限验证配置
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名,见附录1
jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
注,1. 所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用。
2. 上传图片有效期3天,可用微信多媒体接口下载图片到自己的服务器,此处获得的 serverId 即 media_id。
4. 通过config接口注入权限验证配置--- morePictureUpload.js
var staffid=GetQueryString('staffid');
var sessionid=GetQueryString('sessionid');
var flag=GetQueryString('flag');
//获取URL地址参数
function GetQueryString(name){
var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if(r!=null)return unescape(r[2]); return null;
}
$(function(){
getEchoPicture(staffid);
$.ajax({
type : "post",
url : "/admin/weixinToken/getJsApiTicket",
dataType : "json",
async : false,
success : function(data) {
var jsApiTicket = data.ticket;
var url = location.href.split('#').toString();//url不能写死
$.ajax({
type : "post",
url : "/admin/weixinToken/makeWXTicket",
dataType : "json",
async : false,
data:{
jsApiTicket:jsApiTicket,
url:url
},
success : function(data) {
wx.config({
debug: false,//生产环境需要关闭debug模式
appId: data.appid,//appId通过微信服务号后台查看
timestamp: data.timestamp,//生成签名的时间戳
nonceStr: data.nonceStr,//生成签名的随机字符串
signature: data.signature,//签名
jsApiList: [//需要调用的JS接口列表
'chooseImage',
'previewImage',
'uploadImage'
]
});
},
error: function(xhr, status, error) {
//alert(status);
//alert(xhr.responseText);
}
});
},
error: function(xhr, status, error) {
}
})
});
wx.ready(function(){
//页面加载时就调用相关接口
});
var images = {
localId : [],
serverId : []
};
$('.chooseImage').on('click', function() {
images.serverId = [];//清空serverid集合
wx.chooseImage({
count : 9, // 默认9
sizeType : [ 'compressed' ], // 压缩图
sourceType : [ 'album', 'camera' ], // 可以指定来源是相册还是相机,默认二者都有
success : function(res) {
$('.wxChooseImages ').remove();
var localIds = res.localIds;
if(localIds != ""){
for(var i = 0;i<localIds .length;i++){
var imgDivStr = '<div class="bankPage wxChooseImages multiselect"><img src="'+localIds[i]+'" class="pageImg" /></div>';
$(".chooseImage").before(imgDivStr);
}
}
images.localId = res.localIds;
uploadImage(res.localIds);
}
});
});
var uploadImage = function(localIds) {
var localId = localIds.pop();
wx.uploadImage({
localId : localId,
isShowProgressTips : 1,
success : function(res) {
var serverId = res.serverId; // 返回图片的服务器端ID
images.serverId.push(serverId);
//其他对serverId做处理的代码
if (localIds.length > 0) {
uploadImage(localIds);
}else if(localIds.length == 0 && images.serverId != ""){
var serverId = images.serverId;
var serverIdStr = "";
for(var i = 0;i<serverId.length;i++){
serverIdStr += serverId[i]+",";
}
uploadToQiniu(staffid,serverIdStr);
}
}
});
};
//页面回显数据
function getEchoPicture(staffid){
$.ajax({
type : "post",
url : "/admin/weixinToken/getEchoPictureList",
dataType : "json",
async : false,
data:{
staffId:staffid,
type:$("#CredentialsEnum_OLDUS").val()
},
success : function(data) {
if(data != ""){
var imgDivStr = '';
$.each($.parseJSON(data),function(i,item){
var url = item.url;
imgDivStr += '<div class="householdPage wxChooseImages multiselect"><img src="'+url+'" class="pageImg" /></div>';
});
$(".chooseImage").before(imgDivStr);
}
},
error: function(xhr, status, error) {
}
});
}
//从微信服务器保存到七牛云服务器
function uploadToQiniu(staffid,serverIds){
$.ajax({
type : "post",
url : "/admin/weixinToken/wechatJsSDKUploadToQiniu",
dataType : "json",
async : false,
data:{
staffId:staffid,
mediaIds:serverIds,
sessionid:sessionid,
type:$("#CredentialsEnum_OLDUS").val()
},
success : function(data) {
},
error: function(xhr, status, error) {
}
});
}
//删除同类型的其他兄弟节点
function deleteBrotherEle(obj){
obj.nextAll().remove();
}
//返回前一页
function returnPage(){
window.location.href='/appmobileus/USFilming.html?staffid='+ staffid+'&sessionid='+sessionid+'&flag='+flag;
}
5.前端页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>过期美签上传</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<meta name="format-detection" content="telephone=no">
<!--公共样式-->
<link rel="stylesheet" href="css/common.css" />
<!--本页css-->
<link rel="stylesheet" href="css/filming.css" />
</head>
<body>
<header>
<div class="filming">
<a onclick="returnPage()"><i> </i><span>过期美签上传</span></a>
</div>
</header>
<section>
<div class="household">
<div class="householdPage householdExpain">
<img alt="" src="img/icon-overdue.jpeg" width="100%" height="100%">
<div class="signdialog"></div>
<span class="digntitle">图例</span>
</div>
<!-- 过期美签 图片类型枚举 -->
<input id="CredentialsEnum_OLDUS" type="hidden" value=11>
<!--可多选上传-->
<div class="householdPage multiselect chooseImage">
<span class="homePageTitle">可多选上传</span>
<img src="img/camera.png" class="camera" />
<img src="" class="pageImg" />
</div>
</div>
<div class="savetitle">
<a class="savebutton">保存</a>
</div>
</section>
<script type="text/javascript" src="js/jquery-1.10.2.js"></script>
<script type="text/javascript" src="js/rem(750).js"></script>
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script type="text/javascript" src="js/saveButton.js" ></script>
<!-- 微信多图上传 js -->
<script type="text/javascript" src="js/morePictureUpload.js"></script>
</body>
</html>
6. 后端java代码
(1)Module层---WeiXinTokenModule.java
package com.juyo.visa.admin.weixinToken.module;
import java.util.Map;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Filters;
import org.nutz.mvc.annotation.POST;
import org.nutz.mvc.annotation.Param;
import com.alibaba.fastjson.JSONObject;
import com.juyo.visa.admin.weixinToken.service.WeXinTokenViewService;
@IocBean
@Filters
@At("admin/weixinToken")
public class WeiXinTokenModule {
@Inject
private WeXinTokenViewService weXinTokenViewService;
/**
*获取 AccessToken
* <p>
*/
@At
@POST
public Object getAccessToken() {
return weXinTokenViewService.getAccessToken();
}
//获取ticket
@At
@POST
public JSONObject getJsApiTicket() {
return weXinTokenViewService.getJsApiTicket();
}
//生成微信权限验证的参数
@At
@POST
public Map<String, String> makeWXTicket(@Param("jsApiTicket") String jsApiTicket, @Param("url") String url) {
return weXinTokenViewService.makeWXTicket(jsApiTicket, url);
}
//微信JSSDK上传的文件需要重新下载后上传到七牛云
@At
@POST
public Object wechatJsSDKUploadToQiniu(@Param("staffId") Integer staffId, @Param("mediaIds") String mediaIds, @Param("sessionid") String sessionid, @Param("type")Integer type) {
return weXinTokenViewService.wechatJsSDKUploadToQiniu(staffId,mediaIds,sessionid,type);
}
//获取图片集合
@At
@POST
public Object getEchoPictureList(@Param("staffId") Integer staffId, @Param("type") Integer type) {
return weXinTokenViewService.getEchoPictureList(staffId, type);
}
}
(2)Service层---WeXinTokenViewService.java
package com.juyo.visa.admin.weixinToken.service;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.nutz.dao.Cnd;
import org.nutz.ioc.loader.annotation.Inject;
import org.springframework.web.socket.TextMessage;
import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.alibaba.fastjson.JSONObject;
import com.juyo.visa.admin.weixinToken.module.WeiXinTokenModule;
import com.juyo.visa.common.base.UploadService;
import com.juyo.visa.common.comstants.CommonConstants;
import com.juyo.visa.common.util.HttpUtil;
import com.juyo.visa.common.util.SpringContextUtil;
import com.juyo.visa.entities.TAppStaffCredentialsEntity;
import com.juyo.visa.entities.TConfWxEntity;
import com.juyo.visa.websocket.SimpleSendInfoWSHandler;
import com.uxuexi.core.common.util.DateUtil;
import com.uxuexi.core.common.util.JsonUtil;
import com.uxuexi.core.common.util.Util;
import com.uxuexi.core.redis.RedisDao;
import com.uxuexi.core.web.base.service.BaseService;
import com.uxuexi.core.web.chain.support.JsonResult;
public class WeXinTokenViewService extends BaseService<TConfWxEntity> {
@Inject
private RedisDao redisDao;
@Inject
private UploadService qiniuUploadService;//文件上传
private SimpleSendInfoWSHandler simpleSendInfoWSHandler = (SimpleSendInfoWSHandler) SpringContextUtil.getBean(
"mySimpleSendInfoWSHandler", SimpleSendInfoWSHandler.class);
public static Log logger = LogFactory.getLog(WeiXinTokenModule.class);
//获取accessToken
public Object getAccessToken() {
TConfWxEntity wx = dbDao.fetch(TConfWxEntity.class, 1);
String WX_APPID = wx.getAppid();
String WX_APPSECRET = wx.getAppsecret();
String WX_TOKENKEY = wx.getAccesstokenkey();
String accessTokenUrl;
if (wx == null) {
accessTokenUrl = "请联系管理员配置微信公众号!";
} else {
accessTokenUrl = redisDao.get(WX_TOKENKEY);
if (Util.isEmpty(accessTokenUrl)) {
accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
String requestUrl = accessTokenUrl.replace("APPID", WX_APPID).replace("APPSECRET", WX_APPSECRET);
JSONObject result = HttpUtil.doGet(requestUrl);
//redis中设置 access_token
accessTokenUrl = result.getString("access_token");
redisDao.set(WX_TOKENKEY, accessTokenUrl);
redisDao.expire(WX_TOKENKEY, 5000);
accessTokenUrl = requestUrl;
}
}
return accessTokenUrl;
}
//获取ticket
public JSONObject getJsApiTicket() {
String accessToken = (String) getAccessToken();
String apiTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
String requestUrl = apiTicketUrl.replace("ACCESS_TOKEN", accessToken);
JSONObject result = HttpUtil.doGet(requestUrl);
return result;
}
//生成微信权限验证的参数
public Map<String, String> makeWXTicket(String jsApiTicket, String url) {
TConfWxEntity wx = dbDao.fetch(TConfWxEntity.class, 1);
String WX_APPID = wx.getAppid();
String WX_APPSECRET = wx.getAppsecret();
String WX_TOKENKEY = wx.getAccesstokenkey();
Map<String, String> ret = new HashMap<String, String>();
String nonceStr = createNonceStr();
String timestamp = createTimestamp();
String string1;
String signature = "";
//注意这里参数名必须全部小写,且必须有序
string1 = "jsapi_ticket=" + jsApiTicket + "&noncestr=" + nonceStr + "×tamp=" + timestamp + "&url=" + url;
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
//logger.info("signature=====>" + signature);
} catch (NoSuchAlgorithmException e) {
logger.error("WeChatController.makeWXTicket=====Start");
logger.error(e.getMessage(), e);
logger.error("WeChatController.makeWXTicket=====End");
} catch (UnsupportedEncodingException e) {
logger.error("WeChatController.makeWXTicket=====Start");
logger.error(e.getMessage(), e);
logger.error("WeChatController.makeWXTicket=====End");
}
ret.put("url", url);
ret.put("jsapi_ticket", jsApiTicket);
ret.put("nonceStr", nonceStr);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
ret.put("appid", WX_APPID);
return ret;
}
/**
* 微信JSSDK上传的文件需要重新下载后上传到七牛云
*
* @param
* @param
* @param mediaIds
* @param
* @return
*/
public Object wechatJsSDKUploadToQiniu(Integer staffId, String mediaIds, String sessionid, Integer type) {
Date nowDate = DateUtil.nowDate();
List<TAppStaffCredentialsEntity> celist_old = dbDao.query(TAppStaffCredentialsEntity.class, Cnd.where("staffid","=",staffId).and("type", "=", type), null);
if(!Util.isEmpty(celist_old)) {
dbDao.delete(celist_old);
}
List<TAppStaffCredentialsEntity> celist_new = new ArrayList<TAppStaffCredentialsEntity>();
String[] split = mediaIds.split(",");
if (!Util.isEmpty(split)) {
for (String mediaId : split) {
String accessToken = (String) getAccessToken();
String extName = getExtName(accessToken, mediaId);//获取扩展名
InputStream inputStream = getInputStream(accessToken, mediaId);//获取输入流
String url = CommonConstants.IMAGES_SERVER_ADDR
+ qiniuUploadService.uploadImage(inputStream, extName, mediaId);
TAppStaffCredentialsEntity credentialEntity = new TAppStaffCredentialsEntity();
credentialEntity.setStaffid(staffId);
credentialEntity.setUrl(url);
credentialEntity.setType(type);
credentialEntity.setCreatetime(nowDate);
credentialEntity.setUpdatetime(nowDate);
celist_new.add(credentialEntity);
}
}
if (!Util.isEmpty(celist_new)) {
dbDao.insert(celist_new);
}
//webSocket发消息
try {
simpleSendInfoWSHandler.sendMsg(new TextMessage("200"), sessionid);
} catch (IOException e) {
e.printStackTrace();
}
return JsonResult.success("SUCCESS");
}
/**
*
* @param staffId 人员id
* @param type 图片枚举类型
* @return
*/
public Object getEchoPictureList(Integer staffId, Integer type) {
List<TAppStaffCredentialsEntity> celist = dbDao.query(TAppStaffCredentialsEntity.class,
Cnd.where("staffid", "=", staffId).and("type", "=", type), null);
String jsonStr = "";
if (!Util.isEmpty(celist)) {
jsonStr = JsonUtil.toJson(celist);
}
return jsonStr;
}
/**
* 获取媒体文件
* @param accessToken 接口访问凭证
* @param mediaId 媒体文件id
* @param savePath 文件在本地服务器上的存储路径
* */
public static String downloadMedia(String accessToken, String mediaId, String savePath) {
String filePath = null;
// 拼接请求地址
String requestUrl = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID";
requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("MEDIA_ID", mediaId);
try {
URL url = new URL(requestUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setRequestMethod("GET");
if (!savePath.endsWith("/")) {
savePath += "/";
}
// 根据内容类型获取扩展名
String fileExt = getFileexpandedName(conn.getHeaderField("Content-Type"));
// 将mediaId作为文件名
filePath = savePath + mediaId + fileExt;
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
FileOutputStream fos = new FileOutputStream(new File(filePath));
byte[] buf = new byte[8096];
int size = 0;
while ((size = bis.read(buf)) != -1)
fos.write(buf, 0, size);
fos.close();
bis.close();
conn.disconnect();
String info = String.format("下载媒体文件成功,filePath=" + filePath);
System.out.println(info);
} catch (Exception e) {
filePath = null;
String error = String.format("下载媒体文件失败:%s", e);
System.out.println(error);
}
return filePath;
}
/**
* 获取扩展名
*/
public static String getExtName(String accessToken, String mediaId) {
String fileExt = null;
// 拼接请求地址
String requestUrl = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID";
requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("MEDIA_ID", mediaId);
HttpURLConnection conn;
try {
URL url = new URL(requestUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setRequestMethod("GET");
// 根据内容类型获取扩展名
fileExt = getFileexpandedName(conn.getHeaderField("Content-Type"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return fileExt;
}
/**
* 根据内容类型判断文件扩展名
*
* @param contentType 内容类型
* @return
*/
public static String getFileexpandedName(String contentType) {
String fileEndWitsh = "";
if ("image/jpeg".equals(contentType)) {
fileEndWitsh = ".jpeg";
} else if ("application/x-jpg".equals(contentType)) {
fileEndWitsh = ".jpg";
} else if ("application/x-png".equals(contentType)) {
fileEndWitsh = ".png";
} else if ("image/gif".equals(contentType)) {
fileEndWitsh = ".gif";
} else if ("application/x-bmp".equals(contentType)) {
fileEndWitsh = ".bmp";
} else if ("image/fax".equals(contentType)) {
fileEndWitsh = ".fax";
} else if ("image/x-icon".equals(contentType)) {
fileEndWitsh = ".ico";
} else if ("image/pnetvue".equals(contentType)) {
fileEndWitsh = ".net";
}
return fileEndWitsh;
}
/**
*
* 根据文件id下载文件
* @param mediaId 媒体id
*
* @throws Exception
*/
public static InputStream getInputStream(String accessToken, String mediaId) {
InputStream is = null;
String url = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=" + accessToken + "&media_id="
+ mediaId;
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();
// 获取文件转化为byte流
is = http.getInputStream();
} catch (Exception e) {
e.printStackTrace();
}
return is;
}
//字节数组转换为十六进制字符串
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 createNonceStr() {
return UUID.randomUUID().toString();
}
//生成时间戳
private static String createTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
7. 微信公众号配置信息,数据库设计