Java微信公众平台开发_07_JSSDK图片上传
一、本节要点
1.获取jsapi_ticket
//2.获取getJsapiTicket的接口地址,有效期为7200秒
private static final String GET_JSAPITICKET_URL="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; /**
* @desc :2.获取JsapiTicket
*
* @param accessToken 有效凭证
* @return
* @throws Exception String
*/
public static String getJsapiTicket(String accessToken) throws Exception {
//1.获取请求url
String url=GET_JSAPITICKET_URL.replace("ACCESS_TOKEN", accessToken); //2.发起GET请求,获取返回结果
JSONObject jsonObject=HttpHelper.doGet(url);
logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取accessToken
String jsapiTicket="";
if (null != jsonObject) {
//4.错误消息处理
if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//5.成功获取jsapiTicket
}else {
jsapiTicket=jsonObject.getString("ticket");
}
} return jsapiTicket;
}
2.JS-SDK 使用权限签名算法
/**
* @desc :4.获取前端jsapi需要的配置参数
*
* @param request
* @return String
*/
public static String getJsapiConfig(HttpServletRequest request){ //1.准备好参与签名的字段
//1.1 url
/*
*以http://localhost/test.do?a=b&c=d为例
*request.getRequestURL的结果是http://localhost/test.do
*request.getQueryString的返回值是a=b&c=d
*/
String urlString = request.getRequestURL().toString();
String queryString = request.getQueryString();
String queryStringEncode = null;
String url;
if (queryString != null) {
queryStringEncode = URLDecoder.decode(queryString);
url = urlString + "?" + queryStringEncode;
} else {
url = urlString;
} //1.2 noncestr
String nonceStr=UUID.randomUUID().toString(); //随机数
//1.3 timestamp
long timeStamp = System.currentTimeMillis() / 1000; //时间戳参数 String signedUrl = url; String accessToken = null;
String ticket = null; String signature = null; //签名 try {
//1.4 jsapi_ticket
accessToken=getAccessToken(Env.APP_ID, Env.APP_SECRET);
ticket=getJsapiTicket(accessToken); //2.进行签名,获取signature
signature=getSign(ticket,nonceStr,timeStamp,signedUrl); } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} logger.info("accessToken:"+accessToken);
logger.info("ticket:"+ticket);
logger.info("nonceStr:"+nonceStr);
logger.info("timeStamp:"+timeStamp);
logger.info("signedUrl:"+signedUrl);
logger.info("signature:"+signature);
logger.info("appId:"+Env.APP_ID); String configValue = "{signature:'" + signature + "',nonceStr:'" + nonceStr + "',timeStamp:'"
+ timeStamp + "',appId:'" + Env.APP_ID + "'}";
logger.info("configValue:"+configValue); return configValue;
} /**
* @desc : 4.1 生成签名的函数
*
* @param ticket jsticket
* @param nonceStr 随机串,自己定义
* @param timeStamp 生成签名用的时间戳
* @param url 需要进行免登鉴权的页面地址,也就是执行dd.config的页面地址
* @return
* @throws Exception String
*/ public static String getSign(String jsTicket, String nonceStr, Long timeStamp, String url) throws Exception {
String plainTex = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "×tamp=" + timeStamp + "&url=" + url;
System.out.println(plainTex);
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(plainTex.getBytes("UTF-8"));
return byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
throw new Exception(e.getMessage());
} catch (UnsupportedEncodingException e) {
throw new Exception(e.getMessage());
}
} /**
* @desc :4.2 将bytes类型的数据转化为16进制类型
*
* @param hash
* @return
* String
*/
private static String byteToHex(byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", new Object[] { Byte.valueOf(b) });
}
String result = formatter.toString();
formatter.close();
return result;
}
2.1 签名生成规则
(1)参与签名的字段包括:
noncestr(随机字符串),
有效的jsapi_ticket,
timestamp(时间戳),
url(当前网页的URL,不包含#及其后面部分) 。
(2)对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式 (即 key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
(3)对string1进行sha1签名,得到signature:
2.2 签名算法应用实例
(1)待签名参数:
noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=1414587457
url=http://mp.weixin.qq.com
(2)字典序
string1=jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-
HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com
(3)sha1加密
signature=sha1(string1)
3.JS-SDK使用步骤
(1)绑定域名
测试号:
(2)引入JS文件
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.2.0.js
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
(3)通过config接口注入权限验证配置
//1.jsapi签名校验
wx.config({
beta: true,// 必须这么写,否则在微信插件有些jsapi会有问题
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: _config.appId, // 必填,公众号的唯一标识
timestamp: _config.timeStamp, // 必填,生成签名的时间戳
nonceStr: _config.nonceStr, // 必填,生成签名的随机串
signature: _config.signature,// 必填,签名,见附录1
jsApiList: [ 'checkJsApi', 'onMenuShareAppMessage',
'onMenuShareWechat', 'startRecord', 'stopRecord',
'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice',
'uploadVoice', 'downloadVoice', 'chooseImage',
'previewImage', 'uploadImage', 'downloadImage',
'getNetworkType', 'openLocation', 'getLocation',
'hideOptionMenu', 'showOptionMenu', 'hideMenuItems',
'showMenuItems', 'hideAllNonBaseMenuItem',
'showAllNonBaseMenuItem', 'closeWindow', 'scanQRCode',
'previewFile', 'openEnterpriseChat',
'selectEnterpriseContact','chooseInvoice' ]// 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
(4)通过ready接口处理成功验证
(5) 通过error接口处理失败验证
//2.jsapi签名校验失败后执行error
wx.error(function(err){
alert('wx error: ' + JSON.stringify(err));
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
4.图片上传
4.1 图片上传的流程
(1)使用 jssdk 上传图片到微信服务器,返回图片对应的mediaId( 即 serverId)
//2.2 上传图片
var images = {
localId : [],
serverId : []
};
$("#uploadImg").click(function(){
//2.2.1拍照或从手机相册中选图
wx.chooseImage({
success : function(res) {
images.localId = res.localIds;
alert('已选择 ' + res.localIds.length + ' 张图片');
//2.2.2 上传图片
uploadImg();
}
});
}); // 2.2.2 上传图片
function uploadImg() {
if (images.localId.length == 0) {
alert('请先使用 chooseImage 接口选择图片');
return;
}
var i = 0, length = images.localId.length;
images.serverId = []; function upload() {
wx.uploadImage({
localId : images.localId[i],
success : function(res) {
i++;
alert('已上传:' + i + '/' + length);
images.serverId.push(res.serverId);
//将serverId上传至服务器
alert("ajax请求即将执行--"); $.ajax({
type : "POST",
url : "http://se9mxs.natappfree.cc/weixin_gz/uploadimg",
data : {
serverId : res.serverId
},
dataType : "text",
success : function(data) {
alert(data);
} }); if (i < length) {
upload();
}
},
fail : function(res) {
alert(JSON.stringify(res));
}
});
}
upload();
};
(2)使用素材管理接口,根据 mediaId 从微信服务器将图片下载至服务器本地。参见:Java微信公众平台开发_06_素材管理
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String mediaId=request.getParameter("serverId");
System.out.println("serverId:"+mediaId); try {
String accessToken=AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET); //String savePath=System.getProperty("user.dir").replaceAll("\\\\", "/")+"/WebContent/img/"+mediaId+".png";
String fileDir=request.getSession().getServletContext().getRealPath("").replaceAll("\\\\", "/")+"/img/";
System.out.println("fileDir:"+fileDir); //2.调用业务类,获取临时素材
TempMaterialService.getTempMaterial(accessToken, mediaId, fileDir); } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} PrintWriter out = response.getWriter();
out.print("HHHHHHHHHH");
out.close();
out = null; }
二、代码实现
1.前端页面—uploadImg.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSSDK之上传图片</title>
<script src="js/jquery-3.2.1.min.js"></script>
<script type="text/javascript"
src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script> <script type="text/javascript">
var _config =
<%=com.ray.weixin.gz.util.AuthHelper.getJsapiConfig(request)%>
;
</script> <script type="text/javascript" src="js/auth.js"></script> </head>
<body> <div align="center">
<img id="userImg" alt="头像" src="">
</div> <div align="center">
<span>UserName:</span>
<div id="userName" style="display: inline-block"></div>
</div> <div align="center">
<span>UserId:</span>
<div id="userId" style="display: inline-block"></div>
</div> <div align="center">
<span class="desc">是否验证成功</span>
<button class="btn btn_primary" id="yanzheng">验证</button>
</div> <div align="center">
<span class="desc">测试按钮</span>
<button class="btn btn_primary" id="ceshi">测试</button>
</div> <div align="center">
<span class="desc">上传图片按钮</span>
<button class="btn btn_primary" id="uploadImg">上传图片</button>
</div> <div align="center">
<span class="desc">拍照上传图片按钮</span>
<button class="btn btn_primary" id="uploadImgFromCamera">拍照上传</button>
</div> <div align="center">
<span class="desc">扫码按钮</span>
<button class="btn btn_primary" id="qrcode" >扫码</button>
</div>
</body>
</html>
auth.js
//1.jsapi签名校验
wx.config({
beta: true,// 必须这么写,否则在微信插件有些jsapi会有问题
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: _config.appId, // 必填,公众号的唯一标识
timestamp: _config.timeStamp, // 必填,生成签名的时间戳
nonceStr: _config.nonceStr, // 必填,生成签名的随机串
signature: _config.signature,// 必填,签名,见附录1
jsApiList: [ 'checkJsApi', 'onMenuShareAppMessage',
'onMenuShareWechat', 'startRecord', 'stopRecord',
'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice',
'uploadVoice', 'downloadVoice', 'chooseImage',
'previewImage', 'uploadImage', 'downloadImage',
'getNetworkType', 'openLocation', 'getLocation',
'hideOptionMenu', 'showOptionMenu', 'hideMenuItems',
'showMenuItems', 'hideAllNonBaseMenuItem',
'showAllNonBaseMenuItem', 'closeWindow', 'scanQRCode',
'previewFile', 'openEnterpriseChat',
'selectEnterpriseContact','chooseInvoice' ]// 必填,需要使用的JS接口列表,所有JS接口列表见附录2
}); //2.jsapi签名校验成功后执行ready
wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 //2.1 提示jsapi签名验证成功
$("#yanzheng").html("验证成功"); $("#ceshi").click(function(){
alert("ceshiaaa"); }); $("#checkJsApi").click(function(){
wx.checkJsApi({
jsApiList: [ 'checkJsApi', 'onMenuShareAppMessage',
'onMenuShareWechat', 'startRecord', 'stopRecord',
'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice',
'uploadVoice', 'downloadVoice', 'chooseImage',
'previewImage', 'uploadImage', 'downloadImage',
'getNetworkType', 'openLocation', 'getLocation',
'hideOptionMenu', 'showOptionMenu', 'hideMenuItems',
'showMenuItems', 'hideAllNonBaseMenuItem',
'showAllNonBaseMenuItem', 'closeWindow', 'scanQRCode',
'previewFile', 'openEnterpriseChat',
'selectEnterpriseContact','chooseInvoice' ], // 需要检测的JS接口列表,所有JS接口列表见附录2,
success: function(res) {
// 以键值对的形式返回,可用的api值true,不可用为false
// 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
}
}); }); //2.2 上传图片
var images = {
localId : [],
serverId : []
};
$("#uploadImg").click(function(){
//2.2.1拍照或从手机相册中选图
wx.chooseImage({
success : function(res) {
images.localId = res.localIds;
alert('已选择 ' + res.localIds.length + ' 张图片');
//2.2.2 上传图片
uploadImg();
}
});
}); // 2.2.2 上传图片
function uploadImg() {
if (images.localId.length == 0) {
alert('请先使用 chooseImage 接口选择图片');
return;
}
var i = 0, length = images.localId.length;
images.serverId = []; function upload() {
wx.uploadImage({
localId : images.localId[i],
success : function(res) {
i++;
alert('已上传:' + i + '/' + length);
images.serverId.push(res.serverId);
//将serverId上传至服务器
alert("ajax请求即将执行--"); $.ajax({
type : "POST",
url : "http://se9mxs.natappfree.cc/weixin_gz/uploadimg",
data : {
serverId : res.serverId
},
dataType : "text",
success : function(data) {
alert(data);
} }); if (i < length) {
upload();
}
},
fail : function(res) {
alert(JSON.stringify(res));
}
});
}
upload();
}; //2.3 扫一扫
$("#qrcode").click(function(){
wx.scanQRCode({
needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有
success: function (res) {
var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
alert(result); },
fail:function (res) {
var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
alert(result); }
}); }); //2.4 拉起发票列表
//注意,调用此接口时,config接口必须传入beta参数。
$("#showInvoice").click(function(){
alert("timestamp:"+invoice_config.timestamp);
alert("nonceStr:"+invoice_config.nonceStr);
alert("signType:"+invoice_config.signType);
alert("cardSign:"+invoice_config.cardSign); wx.invoke('chooseInvoice', {
'timestamp': invoice_config.timestamp, // 卡券签名时间戳
'nonceStr' : invoice_config.nonceStr, // 卡券签名随机串
'signType' : invoice_config.signType, // 签名方式,默认'SHA1'
'cardSign' : invoice_config.cardSign, // 卡券签名
}, function(res) {
// 这里是回调函数
alert("aaaaaa");
alert(JSON.stringify(res)); // 返回的结果
}); }); }); //2.jsapi签名校验失败后执行error
wx.error(function(err){
alert('wx error: ' + JSON.stringify(err));
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
2.web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>weixin_gz</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list> <!--微信公众号回调-->
<servlet>
<servlet-name>weixin</servlet-name>
<servlet-class>com.ray.weixin.gz.controller.WeiXinServlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>weixin</servlet-name>
<url-pattern>/weixin</url-pattern>
</servlet-mapping>
<!-- 微信公众号回调--> <servlet>
<description></description>
<display-name>uploadimg</display-name>
<servlet-name>uploadimg</servlet-name>
<servlet-class>com.ray.weixin.gz.controller.UploadImgServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>uploadimg</servlet-name>
<url-pattern>/uploadimg</url-pattern>
</servlet-mapping> </web-app>
3.上传图片servlet—UploadImgServlet
package com.ray.weixin.gz.controller; import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ray.weixin.gz.config.Env;
import com.ray.weixin.gz.service.tempmaterial.TempMaterialService;
import com.ray.weixin.gz.util.AuthHelper; /**
* Servlet implementation class UploadImgServlet
*/
public class UploadImgServlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#HttpServlet()
*/
public UploadImgServlet() {
super();
// TODO Auto-generated constructor stub
} /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
} /**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String mediaId=request.getParameter("serverId");
System.out.println("serverId:"+mediaId); try {
String accessToken=AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET); //String savePath=System.getProperty("user.dir").replaceAll("\\\\", "/")+"/WebContent/img/"+mediaId+".png";
String fileDir=request.getSession().getServletContext().getRealPath("").replaceAll("\\\\", "/")+"/img/";
System.out.println("fileDir:"+fileDir); //2.调用业务类,获取临时素材
TempMaterialService.getTempMaterial(accessToken, mediaId, fileDir); } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} PrintWriter out = response.getWriter();
out.print("HHHHHHHHHH");
out.close();
out = null; } }
4.素材管理业务类—TempMaterialService.java
package com.ray.weixin.gz.controller; import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ray.weixin.gz.config.Env;
import com.ray.weixin.gz.service.tempmaterial.TempMaterialService;
import com.ray.weixin.gz.util.AuthHelper; /**
* Servlet implementation class UploadImgServlet
*/
public class UploadImgServlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#HttpServlet()
*/
public UploadImgServlet() {
super();
// TODO Auto-generated constructor stub
} /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
} /**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String mediaId=request.getParameter("serverId");
System.out.println("serverId:"+mediaId); try {
String accessToken=AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET); //String savePath=System.getProperty("user.dir").replaceAll("\\\\", "/")+"/WebContent/img/"+mediaId+".png";
String fileDir=request.getSession().getServletContext().getRealPath("").replaceAll("\\\\", "/")+"/img/";
System.out.println("fileDir:"+fileDir); //2.调用业务类,获取临时素材
TempMaterialService.getTempMaterial(accessToken, mediaId, fileDir); } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} PrintWriter out = response.getWriter();
out.print("HHHHHHHHHH");
out.close();
out = null; } }
其他的同上一节
Java微信公众平台开发_07_JSSDK图片上传的更多相关文章
- Java微信公众平台开发_02_启用服务器配置
源码将在晚上上传到 github 一.准备阶段 需要准备事项: 1.一个能在公网上访问的项目: 见:[ Java微信公众平台开发_01_本地服务器映射外网 ] 2.一个微信公众平台账号: 去注册: ...
- Java微信公众平台开发【番外篇】(七)--公众平台测试帐号的申请
转自:http://www.cuiyongzhi.com/post/45.html 前面几篇一直都在写一些比较基础接口的使用,在这个过程中一直使用的都是我个人微博认证的一个个人账号,原本准备这篇是写[ ...
- Java微信公众平台开发--番外篇,对GlobalConstants文件的补充
转自:http://www.cuiyongzhi.com/post/63.html 之前发过一个[微信开发]系列性的文章,也引来了不少朋友观看和点评交流,可能我在写文章时有所疏忽,对部分文件给出的不是 ...
- Java微信公众平台开发(十二)--微信用户信息的获取
转自:http://www.cuiyongzhi.com/post/56.html 前面的文章有讲到微信的一系列开发文章,包括token获取.菜单创建等,在这一篇将讲述在微信公众平台开发中如何获取微信 ...
- Java微信公众平台开发(十)--微信用户信息的获取
前面的文章有讲到微信的一系列开发文章,包括token获取.菜单创建等,在这一篇将讲述在微信公众平台开发中如何获取微信用户的信息,在上一篇我们有说道微信用户和微信公众账号之间的联系可以通过Openid关 ...
- Java微信公众平台开发(一)--接入微信公众平台
转自:http://www.cuiyongzhi.com/post/38.html (一)接入流程解析 在我们的开发过程中无论如何最好的参考工具当然是我们的官方文档了:http://mp.weixin ...
- Java微信公众平台开发(七)--多媒体消息回复之图片回复
之前我们在做消息回复的时候我们对回复的消息简单做了分类,前面也有讲述如何回复[普通消息类型消息],这里将讲述多媒体消息的回复方法,[多媒体消息]包含回复图片消息/回复语音消息/回复视频消息/回复音乐消 ...
- Java微信公众平台开发_03_消息管理之被动回复消息
GitHub源码:https://github.com/shirayner/weixin_gz 一.本节要点 1.回调url 上一节,我们启用服务器配置的时候,填写了一个服务器地址(url),如下图, ...
- Java微信公众平台开发之获取地理位置
本部分需要用到微信的JS-SDK,微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包.通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统 ...
随机推荐
- zookeeper curator选主(Leader)
在分布式系统设计中,选主是一个常见的场景.选主是一个这样的过程,通过选主,主节点被选择出来控制其他节点或者是分配任务. 选主算法要满足的几个特征: 1)各个节点均衡的获得成为主节点的权利,一旦主节点被 ...
- js系列教程1-数组操作全解
全栈工程师开发手册 (作者:栾鹏) 快捷链接: js系列教程1-数组操作全解 js系列教程2-对象和属性全解 js系列教程3-字符串和正则全解 js系列教程4-函数与参数全解 js系列教程5-容器和算 ...
- http中错误代码的含义整理
HTTP网页错误代码大全带解释 HTTP 400 - 请求无效HTTP 401.1 - 未授权:登录失败HTTP 401.2 - 未授权:服务器配置问题导致登录失败HTTP 401.3 - ACL 禁 ...
- Java策略模式以及来自lambda的优化
前言 设计模式是软件工程中一些问题的统一解决方案的模型,它的出现是为了解决一些普遍存在的,却不能被语言特性直接解决的问题,随着软件工程的发展,设计模式也会不断的进行更新,本文介绍的是经典设计模式 ...
- win10 uwp 随着数字变化颜色控件
我朋友在做一个控件,是显示异常,那么异常多就变为颜色,大概就是下面的图,很简单 首先是一个Ellipse,然后把他的颜色绑定到Int,需要一个转换,UWP的转换和WPF差不多,因为我现在还不会转换,就 ...
- win10应用 UWP 使用MD5算法
windows有自带的算法来计算MD5 原本在WPF是 private string get_MD5(string str) { System.Security.Cryptography.MD5Cry ...
- linux udev、mdev 介绍
Udev介绍 Udev的下载网址:http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev/ Udev分为三个子计划:namedev,libs ...
- Xamarin.Forms 开发IOS、Android、UWP应用
C#语言特点,简单.快速.高效.本次我们通过C#以及Xaml来做移动开发. 1.开发工具visual studio 2015或visual studio 2017.当然visual studio 20 ...
- jfinal使用jstl表达的存在的问及解决
问题 使用jstl 的el表达式 传递数据刷新页面,页面数据不显示,经过验证,数据的确传递过去,但是官方文档并没有详细描述,getModel() 不需要设get set() ,但是使用jstl el表 ...
- java选择结构
/**选择结构*/ public class Demo06{ public static void main(String []args){ // if...else...型 String name ...