2018-08-31 15:49:45 qq_42986378 阅读数 351
  • 微信公众平台企业号开发Java版第4课——管理通讯录与...

    "微信公众平台企业号开发Java版"系列课程,采用java语言细致、详尽、全面地讲解微信企业号开发的相关知识点。该套课程,在"微信公众平台深度开发Java版v2.0"的基础上,对企业号开发的“回调模式”、“主动调用模式”、“JSAPI模式”分类讲解。贯彻“简单、高效、快捷”的课程特色,采用“一课两知识点”的课程进度,保证课程质量的同时,尽可能的压缩课程时间,让学员“以短的时间,学到多的知识”。课程的知识点包括:建立连接;接收消息与响应消息;被动响应消息;接收事件(菜单事件、关注/取消关注事件、坐标事件、异步任务完成事件);发送消息(消息推送);自定义菜单;OAuth验证;Userid与openid互换;微信JS-SDK接口(重点);企业会话服务(重点);基础样式库(重点);企业号登录授权(重点),等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 详情 qq2326321088

    28244 人正在学习 去看看 翟东平

1.我们要接入js安全接口(公众号设置=》功能设置=》js安全域名)
2.引入js是必要的(http://res.wx.qq.com/open/js/jweixin-1.2.0.js)
3配置wx.config

wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名
    jsApiList: [] // 必填,需要使用的JS接口列表
});

公众号中有appID和appsecret然后进入(https://mp.weixin.qq.com/debug/cgi-bin/apiinfo)
公众号中的appID和appsecret
生成Token/access_token注意有效时间是7200秒
Token/access_token
采用https get方式获取jsapi_ticket
(https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi)
成功返回json

{"errcode":0,
"errmsg":"ok",
"ticket":"LIKLcA",
"expires_in":7200}

获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了也就是 timestamp,nonceStr,signature这三个参数,jsApiList这个参数可以到公众号平台中附录2去找需要用哪个js就调用那个
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115
4.通过ready接口处理成功验证/通过error接口处理失败验证。
成功也就可以正常调用,失败那就自己找找哪里有错误吧。

2016-06-26 18:03:24 shiyuqiong 阅读数 8169
  • 微信公众平台企业号开发Java版第4课——管理通讯录与...

    "微信公众平台企业号开发Java版"系列课程,采用java语言细致、详尽、全面地讲解微信企业号开发的相关知识点。该套课程,在"微信公众平台深度开发Java版v2.0"的基础上,对企业号开发的“回调模式”、“主动调用模式”、“JSAPI模式”分类讲解。贯彻“简单、高效、快捷”的课程特色,采用“一课两知识点”的课程进度,保证课程质量的同时,尽可能的压缩课程时间,让学员“以短的时间,学到多的知识”。课程的知识点包括:建立连接;接收消息与响应消息;被动响应消息;接收事件(菜单事件、关注/取消关注事件、坐标事件、异步任务完成事件);发送消息(消息推送);自定义菜单;OAuth验证;Userid与openid互换;微信JS-SDK接口(重点);企业会话服务(重点);基础样式库(重点);企业号登录授权(重点),等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 详情 qq2326321088

    28244 人正在学习 去看看 翟东平

一、申请微信公众号

    获取公众号的appid ,先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。


二、获取填写网页授权页面


三、引入JS文件

在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js

请注意,如果你的页面启用了https,务必引入 https://res.wx.qq.com/open/js/jweixin-1.0.0.js ,否则将无法在iOS9.0以上系统中成功使用JSSDK


、通过config接口注入权限验证配置

所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。


wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名,见附录1
    jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});

步骤五:通过ready接口处理成功验证

wx.ready(function(){

    // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,
所以如果需要在页面加载时就
调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});


六、调用jssdk时需要获取jssdk的临时调用凭证。

jsapi_ticket的有效期为7200秒,通过access_token(有效期为7200秒)来获取。因此jsapi_ticket和access_token需缓存在服务器中。本例使用redis缓存。

七、调用微信分享接口的例子


1、wxshare.js文件内容

function getRandom(){//生成签名的随机串
	var random = "";	 
    for (var i = 1; i <= 32; i++) {
        var n = Math.floor(Math.random() * 16.0).toString(16);
        random += n;
        if ((i == 8) || (i == 12) || (i == 16) || (i == 20)) random += "";
    }
   
    return random;
}

//微信接口配置
var wxShare={
		isReady:false,//是否初始化完成
		access_token:"",//公众号token,令牌
		ticket:"",//调用jssdk的临时凭证
		readySuccessCall:[],//微信初始化成功后的执行事务
		appName:"saasCollection",//项目名称
		config:{
	   
	    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来。
	    appId: "", // 必填,公众号的唯一标识
	    timestamp: Math.ceil(new Date().getTime()/1000).toString(), // 必填,生成签名的时间戳
	    nonceStr: getRandom(), // 必填,生成签名的随机串
	    signature: "",// 必填,签名,见附录1
	    jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','chooseWXPay'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
	
         },
        init:function(){//初始化
        	  
        	 if(!wx){
        		 
        		 zfalert("系统提示","微信接口调用失败",false);
        		 return false;
        	 }
        	 
        	 var that=this;//保存作用域
        	 
        	 this.wx_get_appid(function(data){//获取appid 
        		 
        		  
        		 
        		 if(data.appId){
        			 
//        			 Cookie.Set("appId",data.appId,3600);
        			 that.config.appId=data.appId;
        			 
        		 }
        		  
        		 that.wx_get_access_token(function(data){//获取token,通过token获取jsapi_ticket
        			 
        			 if(data.access_token){
        				 
//        				 Cookie.Set("access_token",data.access_token,3600);
        				 
        				 that.access_token=data.access_token;
        				 
        			 }
        			 
        			 that.wx_get_ticket(function(data){//获取jsapi_ticket
        				 
        				 if(data.ticket){
        					 
//        					 Cookie.Set("ticket",data.ticket,3600);
        					 
        					 that.ticket=data.ticket;
        					 
        				 }
        				 
        			   that.wx_get_sign(function(data){//根据noncestr, jsapi_ticket, timestamp, url获取签名
        				   
        				   that.config.signature=data.signature;
        				   
        				   that.initWx(function(){//初始化微信接口
        					   
        				   });
        				   
        				   
        				   
        			   });	 
        				 
        				 
        			 });
        			 
        			 
        		 });

        		 
        	 });
        	 
        	 
        	 
         },
       
         wx_get_appid:function(call){   //获取微信公众号的appid
        	 this.appId=Cookie.Get("appId");//从cookie中获取appId
        	 if(!this.appId){
        		 
               $.get(getRootPath()+"/api/wxApi/getAppId.WX?time="+new Date(),{},function(data){
        			 call && call(data);
        		 },"json");//请求后台获取access_token
        		 
        		 return ;
        		 
        	 }
        	 
        	  call && call({});
        	 
         },
        
         wx_get_access_token:function(call){ //获取公众号访问令牌
        	 
        	 this.access_token=Cookie.Get("access_token");//从Cookie中获取
        	 
        	 if(!this.access_token){//Cookie中
        		 
        		 $.get(getRootPath()+"/api/wxApi/getWxToken.WX?time="+new Date(),{},function(data){
        			 
        			 call && call(data);
        			 
        		 },"json");//请求后台获取access_token
        		 
        		 return ;
        		
        	   }
        	  call && call({});
        		 
        		 
          },
         
          wx_get_ticket:function(call){ //获取票据使用ajax的get请求获取签名
        	  
        	  this.ticket=Cookie.Get("ticket");
        	  
        	  if(! this.ticket){
        		  
        		  $.get(getRootPath()+"/api/wxApi/getJsApiTicket.WX?time="+new Date(),{},
        				  function(data){
        			          call && call(data);
        			  },"json");//请求获取调用jssdk的临时单据
        		  
        		  return;
        	  }
        	  call && call({});
        	  
        	  
          },
        
          wx_get_sign:function(call){  //获取签名
        	  
        	   
        	  while(!this.config.appId || !this.ticket){
        		  
        		 this.init();
        	  }
        
        	  $.post(getRootPath()+"/api/wxApi/getSign.WX",{//通过ajax请求后台获取签名
        		 "noncestr":this.config.nonceStr,
        		 "ticket":this.ticket,
        		 "timestamp":this.config.timestamp,
        		 "url":location.href.split('#')[0]
        	  },function(data){
        		  
        		  call && call(data);
        		  
        	  },"json");//请求获取调用jssdk的临时单据
        	  
        	  
          },
          initWx:function(call,errorCall){//初始化微信接口
        	   
        	  var that=this;
        	  wx.config(this.config);//初始化微信配置
        	  this.isReady=true;
        	  wx.ready(function(){
        		  
        		  this.isReady=true;
        		  
        		  if(that.readySuccessCall.length>0){
        			  
        			  $.each(that.readySuccessCall,function(i,n){
        				  
        				  n();
        			  })
        			  
        		  }
        		  
        		  call && call();
        		  
        	  });
        	  
        	  wx.error(function(res){
        		  
        		  this.isReady=false;
        		  
        		  errorCall && errorCall();
        		  
        	  });
        	  
        	  
          }
          


}

//初始化
wxShare.init();
 


2、初始化config后调用分享接口的shareopt.js中的代码
$(function(){
 wxShare.shareApi=function(shareList){

	 if(wxShare.isReady){//判断微信config是否被初始化
		    
		 if(shareList.onMenuShareTimeline){//分享到朋友圈
			 
			 var timelineParameter=shareList.onMenuShareTimeline;//获取传入的参数
			 
			     wx.onMenuShareTimeline({//调用微信接口
			    	 
				    title: timelineParameter.title, // 分享标题
				    link: timelineParameter.link, // 分享链接
				    imgUrl: timelineParameter.imgUrl, // 分享图标
				    success: function () { 
				        // 用户确认分享后执行的回调函数
			    	 
			    	 timelineParameter.success && timelineParameter.success();
			    	 
				    },
				    cancel: function () { 
				        // 用户取消分享后执行的回调函数
				    	
				      timelineParameter.cancel && timelineParameter.cancel();
				    	
				    	
				    }
				});
			  
			 
		 } if(shareList.onMenuShareAppMessage){//分享给朋友
			 
			 var appMessageParameter=shareList.onMenuShareAppMessage;//获取传入的参数
			 
		    	 wx.onMenuShareAppMessage({
				    title:appMessageParameter.title, // 分享标题
				    desc: appMessageParameter.desc, // 分享描述
				    link: appMessageParameter.link, // 分享链接
				    imgUrl: appMessageParameter.imgUrl, // 分享图标
				    type: appMessageParameter.type, // 分享类型,music、video或link,
                                                                    //不填默认为link
				    dataUrl: appMessageParameter.dataUrl, // 如果type是music或video,
                                                                          //则要提供数据链接,默认为空
				    success: function () { 
				        // 用户确认分享后执行的回调函数
		    		 appMessageParameter.success && appMessageParameter.success();
		    		 
				    },
				    cancel: function () { 
				        // 用户取消分享后执行的回调函数
				    	
				    	appMessageParameter.cancel && appMessageParameter.cancel();
				    }
				});	 
			 
			 
		 }  if(shareList.onMenuShareQQ){//分享给qq
			 
			 var shareQQParameter=shareList.onMenuShareQQ;//获取传入的参数
			 
				 wx.onMenuShareQQ({
					    title: shareQQParameter.title, // 分享标题
					    desc: shareQQParameter.desc, // 分享描述
					    link: shareQQParameter.link, // 分享链接
					    imgUrl: shareQQParameter.imgUrl, // 分享图标
					    success: function () { 
					       // 用户确认分享后执行的回调函数
					    },
					    cancel: function () { 
					       // 用户取消分享后执行的回调函数
					    }
					});
			 
			
		 }
		 
		 
		 
		 
		 
	 }else{
		 
		//初始化
		 wxShare.init();
		 wxShare.isReady=true;
		 
		 console.log("系统提示,微信分享接口调用失败");
	 }
	 
 }
  
   
//成功初始化后执行api 分享事务
 wxShare.readySuccessCall.push(function(){
     var title = "分享接口测试标题",
        link = window.location.href,
         imgUrl = getRootPath()+"/images/front/bg/wxlog.jpg",//分享接口显示的图片
         desc = "分享接口测试",
         success = function(){
           alert("系统提示","分享成功",false);
         },
         cancel = function(){
        	 alert("系统提示","分享取消分享",false);
         };
    
         var inp_title=$("input[name='title']").val();
         if(inp_title){
        	 title=inp_title ;
         }
         
         var inp_imgUrl=$("input[name='imgUrl']").val();
         if(inp_imgUrl){
        	 
        	 imgUrl=inp_imgUrl;
         }
         
         var inp_desc=$("input[name='desc']").val();
         if(inp_desc){
        	 
        	 desc=inp_desc;
         }
         
         wxShare.shareApi({
         onMenuShareTimeline : {//分享到朋友圈
             title: title, // 分享标题
             link: link, // 分享链接
             imgUrl: imgUrl, // 分享图标
             success: function () {
                 success();

             },
             cancel: function () {
                 cancel();

             }
         },
         onMenuShareAppMessage:{//分享给朋友
             title: title, // 分享标题
             desc: desc, // 分享描述
             link: link, // 分享链接
             imgUrl: imgUrl, // 分享图标
             type: "link", // 分享类型,music、video或link,不填默认为link
             dataUrl:  "", // 如果type是music或video,则要提供数据链接,默认为空
             success: function () {
                 success();
             },
             cancel: function () {
                 cancel();
             }
         },
         onMenuShareQQ:{//分享给qq
             title: title, // 分享标题
             desc: desc, // 分享描述
             link: link, // 分享链接
             imgUrl: imgUrl, // 分享图标
             success: function () {
                 success();
             },
             cancel: function () {
                 cancel();
             }
         },
         onMenuShareWeibo:{
             title: title, // 分享标题
             desc: desc, // 分享描述
             link: link, // 分享链接
             imgUrl: imgUrl, // 分享图标
             success: function () {
                 success();
             },
             cancel: function () {
                 cancel();
             }
         }
     });
 });
 
});


八、java代码实现部分及工具类


import java.io.IOException;

/**
 * HttpClient工具类
 * 
 * @author shi
 */
public class HttpClientUtil {
	
	
	public  static String get(String url) throws IOException{
		
		String returnVal="";
		// 定义httpClient的实例
		CloseableHttpClient httpclient = HttpClients.createDefault();
		HttpGet httpGet=new HttpGet(url);

			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();//设置请求和传输超时时间
			httpGet.setConfig(requestConfig);
			try {
				CloseableHttpResponse response2 = httpclient.execute(httpGet);//执行请求
				RmProjectHelper.logError("response2:", response2);
				HttpEntity entity2 = (HttpEntity) response2.getEntity();
				if(entity2!=null){
					
					returnVal = EntityUtils.toString(entity2, "UTF-8");
					
				}else{
					returnVal = null;
				}
				
			} catch (ClientProtocolException e) {
				
				RmProjectHelper.logError("retVal", e.getMessage());
			} catch (IOException e) {
				// TODO Auto-generated catch block
				RmProjectHelper.logError("retVal", e.getMessage());
				
			}finally{
				
				if(httpclient!=null){
					
					httpclient.close();
				}
				
			}
			
		
		return returnVal;
		
	}
	
	public static Map<String, Object> parseJSON2Map(String bizData) {
		Map<String, Object> ret = new HashMap<String, Object>();
		
    	try{
    		JSONObject bizDataJson = JSONObject.parseObject(bizData);
    		for(Object key:bizDataJson.keySet()){
    			Object value = bizDataJson.get(key);
    			if(value instanceof JSONArray){
    				List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();  
                    Iterator<Object> it = ((JSONArray) value).iterator();

                    while(it.hasNext()){  
                        JSONObject json2 = (JSONObject)it.next();  
                        list.add(parseJSON2Map(json2.toString()));  
                    }  
                    ret.put(String.valueOf(key),list);  
    			}else{
    				ret.put(String.valueOf(key), String.valueOf(value));
    			}
    		}
    	}catch(Exception e){
    		RmProjectHelper.logError("系统异常", e);
    	}
		return ret;
	}
	
	
	/**
	 * 使用post 提交到url
	 * 
	 * @param url  目标url
	 * @param postDataXML 表体数据
	 * @throws Exception
	 */
	public static String post(String url, String postDataXML)
			throws Exception {
		// 定义httpClient的实例
		CloseableHttpClient httpclient = HttpClients.createDefault();
		String retVal;
		try {
			HttpPost httpPost = new HttpPost(url);
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();//设置请求和传输超时时间
			httpPost.setConfig(requestConfig);
		    StringEntity postEntity = new StringEntity(postDataXML, "UTF-8");
	        httpPost.addHeader("Content-Type", "text/xml");
	        httpPost.setEntity(postEntity);
			CloseableHttpResponse response2 = httpclient.execute(httpPost);
			
			try {
				RmProjectHelper.logError("系统调试",response2.getStatusLine());
				HttpEntity entity2 = (HttpEntity) response2.getEntity();
				if(entity2!=null){
					retVal = EntityUtils.toString(entity2, "UTF-8");
				}else{
					retVal = null;
				}
				// do something useful with the response body
				// and ensure it is fully consumed
				EntityUtils.consume( entity2);
				return retVal;
			} finally {
				response2.close();
			}
		} finally {
			httpclient.close();
		}

	}
	
	
}





4、wxshare.js中ajax请求获取appi、access_token、jsapi_ticket和sign签名请求的实现

import java.io.IOException;

@Controller
@RequestMapping(value="/api/wxApi")
public class WxApi {
	
	

	/**
	 * 微信公共服务
	 */
	@Autowired
	private WxService wxService;
	

	
	/**
	 * 获取
	 * @param model
	 * @param request
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value="/getAppId"+ISystemConstant.SUFFIX_WX,produces = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public Map<String,Object> getAppId(Model model, HttpServletRequest request){
		
		Map<String,Object> result=new HashMap<String,Object>();
		String  appId="1233456";//获取微信公众号的appid,根据自己具体业务写
		
		result.put("appId", appId);
		
		
		return result;
		
		
	}
	
	
	
	
	/**
	 * 获取token
	 * {
	 *	    "expires_in": "7200",
	 *	    "access_token": "TmKDWukZhk_2SVVLIuSMieu57J9i9CyDHBu01rLBjnfcOxeqLnpkLt。。。
	 * @param model
	 * @param request
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value="/getWxToken"+ISystemConstant.SUFFIX_WX,produces = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public Map<String,Object> getWxToken(Model model, HttpServletRequest request){
		
		 Map<String,Object> result=new HashMap<String,Object>();
		  
//		String uri="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" +appID+
//				"&secret="+appsecret;
		
		    String  token=wxService.getToken();
		    
		    result.put("access_token", token);

			
		 return result;
		
		
	}
	
	/**
	 * 获取调用jssdk的临时票据
	 * @param model
	 * @param request
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value="/getJsApiTicket"+ISystemConstant.SUFFIX_WX,produces = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public Map<String,Object> getJsApiTicket(Model model, HttpServletRequest request) throws IOException{
		
		Map<String,Object> result=new HashMap<String,Object>();
		
//		String uri="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" +appID+
//				"&secret="+appsecret;
		
		String  jsApiTicket=wxService.getJsApiTicket();
		
		result.put("ticket", jsApiTicket);
		
		
		return result;
		
		
	}
	
	/**
	 * 获取签名
	 * @param model
	 * @param request
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value="/getSign"+ISystemConstant.SUFFIX_WX,produces = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public Map<String,Object> getSign(Model model, HttpServletRequest request){
		
		Map<String,Object> result=new HashMap<String,Object>();
		
		String noncestr=request.getParameter("noncestr");
	
		String jsapi_ticket=request.getParameter("ticket");
		
		String timestamp=request.getParameter("timestamp");
	
		String url=request.getParameter("url");
		   
		String  sign=wxService.getSign(noncestr, jsapi_ticket, timestamp, url);
		
		result.put("signature", sign);
		
		
		return result;
		
		
	}
	

}

5、WxService 具体代码,在service中根据httpclient工具类发送请求获取access_token 和 jsapi_ticket,将access_token 和 jsapi_ticket存入redis中


注:使用jedis,具体jedis在这不在贴出代码。


 

import java.io.IOException;

@Service
//默认将类中的所有public函数纳入事务管理
@Transactional(readOnly = true)

/**
 * 微信接口服务
 */
public class WxService {
	

    /**
     * 获取调用jsApi的签名
     * @param noncestr:随机数
     * @param jsapi_ticket:临时票据
     * @param timestamp:时间戳
     * @param url:请求url
     * @return
     */
    public  String getSign(String noncestr,String jsapi_ticket,String  timestamp,String url ){
    	
		  if(StringHelper.isEmpty(noncestr)){
			
			throw new PjException("随机数不可为空");
	      }
		  if(StringHelper.isEmpty(jsapi_ticket)){
				
				throw new PjException("调用微信的要获取的凭证失败");
			}
			
		    if(StringHelper.isEmpty(timestamp)){
				
				throw new PjException("时间戳不可为空");
			}
		    
			
		   if(StringHelper.isEmpty(url)){
				
				throw new PjException("要分享的连接不可为空");
			}
    	   String sign="";
    	   Map<String,String> signMap=new HashMap<String,String>();
    	   
    	   signMap.put("noncestr", noncestr);
    	   signMap.put("jsapi_ticket", jsapi_ticket);
    	   signMap.put("timestamp", timestamp);
    	   signMap.put("url", url);
    	   
    	   sign= SignUtil.getSignature(signMap);
    	   
    	   return sign;
    	
    }
    
    
	
	
	/**
	 * 获取微信公众号的token
	 * @return
	 */
	public String    getToken(){
		
		  Jedis jedis = null;
    	  String accessToken="";
    	
      try {
			
	
		  jedis = RedisCacheService.getJedis();//获取redis连接
		
		  accessToken =jedis.get("ACCESS_TOKEN");//获取redis中的access_token
		  
		  if(StringHelper.isEmpty(accessToken)){//redis中没有,去请求微信服务器
			  
				     
				  
					 String  appid="appid";//微信公众号的appid,登录微信公众号查看,填入自己微信公众号的实际appid
				     String   appsecret="appsecret";//填入自己公众号对应的appsecret
				     
				     String url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";//获取公共号token的url
				     
				     StringBuilder sb=new StringBuilder();
				     sb.append(url);
				     sb.append("&appid=");
				     sb.append(appid);
				     sb.append("&secret=");
				     sb.append(appsecret);
				     url=sb.toString();
				
				    	 
					 String returnVal=HttpClientUtil.get(url);//发送请求获取访问token
					
					 if(!StringHelper.isEmpty(returnVal)){
						
						Map<String,Object> result=HttpClientUtil.parseJSON2Map(returnVal);
						
						accessToken=(String)result.get("access_token");
					    jedis.setex("ACCESS_TOKEN", 7000, accessToken);//将access_token放入redis中默认7000秒后失效获取新的access_token
					    return accessToken;
						 
					}else{
						
						throw new PjException("没有获取到返回值");
					}
			
			 
		     
			  
		  }
		  
		  return accessToken;
		 
	  	} catch (Exception e) {
	  		
	  		RmProjectHelper.logError("获取微信token", e.getMessage());
	  		
		}finally{
			
		
			RedisCacheService.returnResource(jedis);
			
		}
	  	
	  	
		 return accessToken;
	  	
	}

	
	/**
	 * 获取调用jsapi的ticket临时凭证 
	 * @return
	 */
	public String getJsApiTicket(){
		  Jedis jedis = null;
    	  String jsApiTicket="";
    	
       try {
    	   
    		  jedis = RedisCacheService.getJedis();
    		  
    		  jsApiTicket =jedis.get("jsapi_ticket");
    		  
    		  if(StringHelper.isEmpty(jsApiTicket)){
    			  
    		
    				  
//    				  https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
    				  
    				     jsApiTicket =jedis.get("jsapi_ticket");
    				     
    				     if(!StringHelper.isEmpty(jsApiTicket)){//再次判断是否为空,获取jsApiTicket返回
    				    	 
    				    	 return jsApiTicket;
    				     }
    				  
    					 String  ticketUrl="https://api.weixin.qq.com/cgi-bin/ticket/getticket";
    					 
    					 String access_token=getToken();
    					 
    					 StringBuilder sb=new StringBuilder();
    					 
    					 sb.append(ticketUrl);
    					 sb.append("?access_token=");
    					 sb.append(access_token);
    					 sb.append("&type=jsapi");
    					 
    					 String returnVal=HttpClientUtil.get(sb.toString());
    					 
    					 if(!StringHelper.isEmpty(returnVal)){
    						 
    						    Map<String,Object> result=HttpClientUtil.parseJSON2Map(returnVal);
    							
    						    jsApiTicket=(String)result.get("ticket");
    						    jedis.setex("jsapi_ticket", ISystemConstant.TOKE_OUT_TIME, jsApiTicket);
    						    return jsApiTicket;
    						    
    						 
    					 }else{
    						 throw new PjException("请求获取jsApiTicket失败!");
    					 }
    
    		  }
    	  
       }catch (Exception e) {
	  		
	  		RmProjectHelper.logError("获取调用jsapi的ticket临时凭证 ", e.getMessage());
	  		
		}finally{
			
			RedisCacheService.returnResource(jedis);
			
		}
	  	
			
	
		return jsApiTicket;
	

	
	}
	
}



九、json解析工具类下载地址http://download.csdn.net/detail/shiyuqiong/9560191
         
        














 

2017-05-01 16:41:08 y_f_raquelle 阅读数 3540
  • 微信公众平台企业号开发Java版第4课——管理通讯录与...

    "微信公众平台企业号开发Java版"系列课程,采用java语言细致、详尽、全面地讲解微信企业号开发的相关知识点。该套课程,在"微信公众平台深度开发Java版v2.0"的基础上,对企业号开发的“回调模式”、“主动调用模式”、“JSAPI模式”分类讲解。贯彻“简单、高效、快捷”的课程特色,采用“一课两知识点”的课程进度,保证课程质量的同时,尽可能的压缩课程时间,让学员“以短的时间,学到多的知识”。课程的知识点包括:建立连接;接收消息与响应消息;被动响应消息;接收事件(菜单事件、关注/取消关注事件、坐标事件、异步任务完成事件);发送消息(消息推送);自定义菜单;OAuth验证;Userid与openid互换;微信JS-SDK接口(重点);企业会话服务(重点);基础样式库(重点);企业号登录授权(重点),等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 详情 qq2326321088

    28244 人正在学习 去看看 翟东平

微信公众平台开发者文档:http://mp.weixin.qq.com/wiki/home/index.html


首先申请一个微信公众开发测试账号:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login


申请后会提供appID和appsecret,你需要在自己的代码中添加接口配置的处理。

但此处URL必须为一个公网地址,且使用80端口,这就涉及到之前讲到的公网映射的方式。通常使用ngrok,注册后获得authtoken并配置,使用ngrok http <port>即可将指定端口映射到公网80端口。

接口配置的java示例:(参考Journey的博客

@WebServlet(urlPatterns = "/wx", name = "wxHouseKeeperServlet")  
public class HouseKeeper extends HttpServlet {  
    public static final String TOKEN = "mzmzo";  
  
    @Override  
    protected void doGet(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException {  
        try {  
            // 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带参数  
            String signature = request.getParameter("signature");// 微信加密签名(token、timestamp、nonce。)  
            String timestamp = request.getParameter("timestamp");// 时间戳  
            String nonce = request.getParameter("nonce");// 随机数  
            String echostr = request.getParameter("echostr");// 随机字符串  
            PrintWriter out = response.getWriter();  
            // 将token、timestamp、nonce三个参数进行字典序排序  
            String[] params = new String[] { TOKEN, timestamp, nonce };  
            Arrays.sort(params);  
            // 将三个参数字符串拼接成一个字符串进行sha1加密  
            String clearText = params[0] + params[1] + params[2];  
            String algorithm = "SHA-1";  
            String sign = new String(  
                    Hex.encodeHex(MessageDigest.getInstance(algorithm).digest((clearText).getBytes()), true));  
            // 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信  
            if (signature.equals(sign)) {  
                response.getWriter().print(echostr);  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }     
}  

此处TOKEN与网页中填写的Token一致即可

接下来配置“网页授权获取用户基本信息


注意填写时不用加http://,只填写域名即可。

完成后扫描下方二维码即可关注自己的公众测试号,网页中会显示关注用户的Openid。

下载微信Web开发工具,即可模拟手机调试


完成登录和绑定后,开发者就可以开始调试微信网页授权,在地址栏直接输入URL

示例: https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx841a97238d9e17b2&redirect_uri=http://cps.dianping.com/weiXinRedirect&response_type=code&scope=snsapi_base&state=type%3Dquan%2Curl%3Dhttp%3A%2F%2Fmm.dianping.com%2Fweixin%2Faccount%2Fhome

这里appid填写之前注册后得到的,redirect_uri指向自己的公网域名下的url,response_type为code,scope为snsapi_base表示静默授权,state填写uri后的mapping。注意这里的redirect_uri和state可能需要urlencode。








2019-04-28 18:02:27 qq_21041889 阅读数 1088
  • 微信公众平台企业号开发Java版第4课——管理通讯录与...

    "微信公众平台企业号开发Java版"系列课程,采用java语言细致、详尽、全面地讲解微信企业号开发的相关知识点。该套课程,在"微信公众平台深度开发Java版v2.0"的基础上,对企业号开发的“回调模式”、“主动调用模式”、“JSAPI模式”分类讲解。贯彻“简单、高效、快捷”的课程特色,采用“一课两知识点”的课程进度,保证课程质量的同时,尽可能的压缩课程时间,让学员“以短的时间,学到多的知识”。课程的知识点包括:建立连接;接收消息与响应消息;被动响应消息;接收事件(菜单事件、关注/取消关注事件、坐标事件、异步任务完成事件);发送消息(消息推送);自定义菜单;OAuth验证;Userid与openid互换;微信JS-SDK接口(重点);企业会话服务(重点);基础样式库(重点);企业号登录授权(重点),等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 详情 qq2326321088

    28244 人正在学习 去看看 翟东平

在开发微信小程序的过程中,有调用接口的情况,(如果是想找免费接口用来测试或者玩的,可以去免费开放接口API找免费的API接口)


本篇文章 调用的接口是笑话大全  https://v.juhe.cn/joke/content/list.php

下面是pages/index/index.js的代码 

    //请求接口
    wx.request({
      //这里是你用到的接口
      url: 'https://v.juhe.cn/joke/content/list.php',
      data: {
        //这里是你请求需要发送的数据
        key: '**************',//key值需要申请
        page: '2',
        pagesize: '3',
        sort: 'asc',
        time: '1418745237',
      },
      success: function (res) {
        //请求成功后的回调
        console.log(res.data.result.data)// 服务器回包信息
        if(res.statusCode == '200'){
          // 赋值
          obj.setData({
            result_list: res.data.result.data,
          })
        }else{
          console.log("获取失败");
        }
      }
    })

接口返回的值

最后 我们在页面进行简单循环一下

<view wx:for="{{result_list}}" wx:key="navItems" wx:for-index="index" wx:for-item="item">
{{index+1}}、{{item.content}}
</view>

简简单单循环一下,就得到下面效果的页面

以上是直接请求接口,如何用get/post提交form数据 调用接口并循环显示在页面,下一篇文章或者直接点击链接访问~   

2016-04-10 18:20:25 ming_221 阅读数 13378
  • 微信公众平台企业号开发Java版第4课——管理通讯录与...

    "微信公众平台企业号开发Java版"系列课程,采用java语言细致、详尽、全面地讲解微信企业号开发的相关知识点。该套课程,在"微信公众平台深度开发Java版v2.0"的基础上,对企业号开发的“回调模式”、“主动调用模式”、“JSAPI模式”分类讲解。贯彻“简单、高效、快捷”的课程特色,采用“一课两知识点”的课程进度,保证课程质量的同时,尽可能的压缩课程时间,让学员“以短的时间,学到多的知识”。课程的知识点包括:建立连接;接收消息与响应消息;被动响应消息;接收事件(菜单事件、关注/取消关注事件、坐标事件、异步任务完成事件);发送消息(消息推送);自定义菜单;OAuth验证;Userid与openid互换;微信JS-SDK接口(重点);企业会话服务(重点);基础样式库(重点);企业号登录授权(重点),等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 详情 qq2326321088

    28244 人正在学习 去看看 翟东平

首先要注意的几点:

1.微信开放的分享接口到底是干什么的
微信分享接口文档:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
这个微信分享接口只是让你在微信内分享时配置要分享的内容用的,并不是在App里点分享时会弹出的那个有一排应用的分享框框,这个一定要明确。

2.微信分享的配置信息
如果是在公司里做微信分享相关的东西,那配置肯定是要找公司里管理微信公众账号的人去要的,其实就是一个标识,表明你的身份,让微信知道是谁在用TA的接口

微信分享接口的配置:
1.基本信息配置

wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名,见附录1
    jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});

2.设置要分享的内容

wx.ready(function(){

    // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});

经过这两步之后其实微信分享就结束了,但是我在这个过程中却踩了不少的坑,并不是微信分享本身多难,而是跟业务和框架有关。在使用微信接口的过程当中还应该注意几点:
1. 调试的时候开启debug模式,不然在移动端调试的时候根本不知道什么地方出错了。调试模式下,微信接口会把所有设置过的分享信息在concole里打出来,如果是在手机端,那么在配置微信接口,设置分享信息的时候都会有弹出框。但是不管配置正确还是不正确,弹出框的标题都是‘error message’,但是如果配置成功后半部分是‘config:ok’
2. 调用接口的时机。如果数据都是异步获取,那么一定要在数据都到位的情况下调用微信接口。我怀疑连续几次设置分享信息会导致只有第一条有效,还未进行验证。
3. 这跟微信接口无关。我是来吐槽一下公司的登录接口奇葩的一B,用户登录后会在本地存个用户标识,如果前端向服务端发起任何跟用户相关的数据请求,一定要带上本地的这个标识,因为服务端根本没有保存已登录用户的任何信息。那么问题来了,就算调试的时候手机可以直接连接电脑访问测试链接,但是获取不到用户标识,导致我死活获取不到分享出去的链接。就这破问题折腾了一晚上,想想都让人觉得想死。

接下来准备把代码结构再整理整理,将这个分享做成好用的组件

—-2016-04-10 18:20

这周分享又出现了两个bug,但是和微信分享并没有关系,是在调用App里分享的时候出了问题。

坑1:h5里调用app分享接口的时候需要根据url里的os参数判定当前是不是app环境,但是并不是所有app里的url都会带上os参数,比如登录之后再跳转回来os参数就不见了。解决:sessionStorage里存个标识

坑2:在微信分享里设置参数的时候,如果分享的链接为空,那么默认是当前页面链接,并且在测试环境下这么调用app分享接口也是好的,但是线上就报错了,分享不出去,并且设置成location.href也是报错了,根本设置不进去。原因是啥我也很想知道,但是拼个url字符串放进去就好了,猜测是因为ios开发对location这一类浏览器操作做了屏蔽,location.href取出来虽然是字符串,但是执行的时候才会去取值,毕竟是 跨域了,直接设置字符串放进去才是安全的。

—-2016.4.16 15:02

没有更多推荐了,返回首页