2018-09-28 14:11:09 qq_29914837 阅读数 1434
  • 微信公众号开发9-公众JSSDK开发-微信开发php

    微信公众平台开发之公众号JSSDK开发是子恒老师《微信公众平台开发》视频教程的第9部。详细讲解了用php开发微信公众号,对微信公众平台中的JSSDK开发。内容包含用JSSDK获取网络状态,地理位置,分享到朋友圈,QQ,空间设置等等。欢迎反馈,微信/QQ:68183131

    14923 人正在学习 去看看 秦子恒

本节要求:

①微信公众号申请
②测试公众号的注册
③准备微信公众号开发的环境


微信公众号开发入门指引

微信公众号的接入在微信公众平台-微信公众平台技术文档中有着详细的介绍。在进行微信开发前,建议先完整的浏览下这个文档,可以帮助你有一个对微信开发的整体意识。


一、微信公众号申请

进入申请公众号网页,点击右上角 【立即注册】
在这里插入图片描述
 
 选择注册的账号类型(一般个人选择订阅号)
在这里插入图片描述
按照要求填写注册信息即可
在这里插入图片描述

备注:
 1.微信公众号分为服务号、订阅号、企业号。不同的公众号拥有不同的能力订阅号可以个人申请,服务号和企业号要有企业资质才可以。
 2.如果是服务号和企业号申请,会进入审核状态,一般审核在五个工作日内完成,实际上当天申请,一般第二天就可看到是否通过。


申请成功后进入
在这里插入图片描述

微信公众号开发主要指的是订阅号和服务号的开发:
  关于订阅号和服务器的区别,官方是这样解释的
  服务号:主要偏向于服务交互(功能类似12315,114,银行,提供绑定信息,服务交互),每月可群发4条消息;服务号适用人群:媒体、企业、政府或其他组织。
  订阅号:主要偏向于为用户传达资讯,(功能类似报纸杂志,为用户提供新闻信息或娱乐趣事),每天可群发1条消息;订阅号适用人群:个人、媒体、企业、政府或其他组织。
  个人订阅号有一些接口是没有权限的,也就是说个人订阅号无法调用一些高级的权限接口。


二、测试公众号的注册

但是一些高级接口,如生成二维码、网页授权、自定义菜单、微信支付这样的接口权限个人订阅号是没有调用权限的。因此微信公众平台提供了测试公众账号。
测试公众号的注册地址为:
http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login,
只需要到这个页面,点击登录,并用自己的微信客户端扫码,并授权登录,就可以获得属于自己的测试公众号。
或者 通过开发者工具-公众平台测试账号 进入
在这里插入图片描述
测试公众号具备几乎所有的接口,所以平时学习微信公众号开发时,就可以去注册一个测试公众号,然后使用这个测试公众号做开发就可以了。

注册测试公众号的步骤如下图所示:
在这里插入图片描述  
在这里插入图片描述
测试公众号的所拥有的接口权限如下:
在这里插入图片描述

可以看到,测试公众号拥有大部分的接口调用权限,因此用测试公众号来学习微信开发是完全可以的。


三、微信开发服务器准备

①微信公众号开发难点:调试问题
②原因:每次实现一个功能后都需要部署到一个公网服务器进行测试,因为微信用户每次向公众号发起请求时,微信服务器会先接收到用户的请求,然后再转发到我们的服务器上,也就是说,微信服务器是要和我们的服务器进行网络交互,所以我们必须保证我们的服务器外网可以访问到,这种部署到公网服务器进行测试的做法对于我们开发者来说简直是噩梦。
③解决思路:要想一个办法可以做到本地部署,本地调试代码,而要做到这一点,那么我们要解决的问题就是将内网的部署服务器映射到外网,让微信服务器可以正常访问到。
④解决办法:借助于第三方软件Ngrok,我们就可以做得到。Ngrok是一个免费的软件Ngrok,使用Ngrok后,我们就可以实现内网穿透,也就是说我们可以将内网的服务器映射到外网给别人访问,这对于我们在本地开发环境中调试微信代码是以及给用户演示一些东西非常快速和有帮助的,因为可以直接使用我们自己的内网的电脑作为服务器。
下载链接:(附使用方法)
https://download.csdn.net/download/qq_29914837/10692027

在这里插入图片描述

获得 http://037c75b7.ngrok.io
在这里插入图片描述

启动tomcat
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

发现输入:http://037c75b7.ngrok.io/和输入http://127.0.0.1:8080/ 都可以成功范围tomcat欢迎界面,表示内网映射成功

使用了ngrok之后,我们就可以把内网的服务器当成公网服务器来使用了.访问的速度也还在可以接受的范围内吧,截止到目前为止ngrok是可用的,微信公众号服务器是可以访问的,这样一来也就不妨碍我们做本地调式了。到此,我们的微信本地调试开发环境就算是搭建好了。


下一节内容

微信开发学习总结(二)——微信开发环境准备(1)
https://blog.csdn.net/qq_29914837/article/details/82891095

2017-09-24 07:35:58 towtotow 阅读数 162
  • 微信公众号开发9-公众JSSDK开发-微信开发php

    微信公众平台开发之公众号JSSDK开发是子恒老师《微信公众平台开发》视频教程的第9部。详细讲解了用php开发微信公众号,对微信公众平台中的JSSDK开发。内容包含用JSSDK获取网络状态,地理位置,分享到朋友圈,QQ,空间设置等等。欢迎反馈,微信/QQ:68183131

    14923 人正在学习 去看看 秦子恒

老子在道德经里说:道生一,一生二,二生三,三生万物,

也就量说任何事情都是有规律可循的。


不要看微信开发文档内容繁多,

但也是有规律,

当你抓住根本的东西,

再去看文档时,


14leixing.jpg


就会觉得很轻松了,

这一节微信开发教程中,

子恒老师告诉你微信开发中操作本质…

微信公众号开发的4大操作类型视频教程在线观看

http://edu.csdn.net/course/detail/2586/42231

2017-10-11 11:53:45 Liutt55 阅读数 2910
  • 微信公众号开发9-公众JSSDK开发-微信开发php

    微信公众平台开发之公众号JSSDK开发是子恒老师《微信公众平台开发》视频教程的第9部。详细讲解了用php开发微信公众号,对微信公众平台中的JSSDK开发。内容包含用JSSDK获取网络状态,地理位置,分享到朋友圈,QQ,空间设置等等。欢迎反馈,微信/QQ:68183131

    14923 人正在学习 去看看 秦子恒

(如需完整代码,开发遇到什么问题,可与本人联系,代码给大家下载并帮你解决问题,微信号:1131237188)

1.公众号开发,首先需要微信公众号的appId,secret 相当于账号密码

2.到公众号后台配置域名,微信用户授权,微信支付目录(在公众号平台配置不了,要到商户后台配置)

3.配置好了之后就可以开发了,直接上代码

微信用户授权

如果文章对您有帮助,请扫描最底下的二维码赞赏,你的支持是我最大的动力谢谢!

/**
* Desc:请求微信接口URL1获取code跳转到redirect_url,请求微信接口URL2获取openId
* param:
* return:openid
* Author:LiuChuanting
* Date:2017/9/14
**/
public void getUrlCode(){
String status = this.getRequest().getParameter("status");
if(StringUtils.isNotBlank(status)){
CacheKit.put("reder", "status_code","1");
}
String url = Constant.WECHAT_INFO.URL1;
   String appid= Constant.WECHAT_INFO.APP_ID;
   String REDIRECT_URI = Constant.WECHAT_INFO.REDIRECT_URL;
   url  = url.replace("APPID",ToolUtil.str2Encode(appid)); 
   url  = url.replace("REDIRECT_URI",ToolUtil.str2Encode(REDIRECT_URI));
   //getUserInfo();
   this.redirect(url);
}

/**
* Desc:请求微信接口URL2获取openId
* param:code
* return:无
* Author:LiuChuanting
* Date:2017/9/14
**/
public void getUrlOpenid(){
String code = this.getPara("code");
String openId = HttpClientConnectionManager.getOpendId(code);
this.setAttr("openId",openId);
String status = CacheKit.get("reder","status_code");
if("1".equals(status)){
//从菜单进入个人中心
CacheKit.remove("reder","status_code");
this.render("/admin/page/redirectCenter.jsp");
}else{
//去下单用户授权
this.render("/admin/page/redirect.jsp");
}

}

用户授权原理是后台获取openid 返回到第三方页面 在第三方页面进行跳转到H5页面,并且带上openId ,一般我们放到cookie

 

<script type="text/javascript"> 
function setCookie(key, value) {   
if(!key) return;
var option = {
Domain: "",
Path: "/"
};
if(/(\.cn|\.com)/.test(window.location.host)) {
var tmp = window.location.host.split("\.");
var t = tmp[tmp.length - 1].split(":");
option.Domain = "." + tmp[tmp.length - 2] + "." + t[0];
}
if(typeof(value) === "object") {
value = JSON.stringify(value);

var tmp = "";
for(var s in option ){
tmp += ";" + s + "=" + option[s]; 
}

document.cookie = key + "=" + escape(value) + tmp;
   /*  var Days = 30;  
    var exp = new Date();  
    exp.setTime(exp.getTime() + 60 * 5000);//过期时间5分钟  
   */
    //document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();  
}
setCookie("openId",'${openId}');
window.location.href = "http://wechat.qzt360.com/page/index.html";
 

</script>

获取微信用户的基本信息,根据页面传过来的openId查询ACCESS_TOKEN

在根据获取的ACCESS_TOKEN请求微信服务器获取用户信息并然后返回JSONObject对象

/**
* Desc:获取微信用户信息
* param:openid
* return:无
* Author:LiuChuanting
* Date:2017/9/14
**/
public void getUserInfo(){
String openId = getOpenId();
   String user = HttpClientConnectionManager.getUserInFo(openId);
   renderRb(user);
}

/**
* Desc:获取cookie openId
* param:
* return:无
* Author:LiuChuanting
* Date:2017/9/21
**/
public String getOpenId(){
String openId = "";
   javax.servlet.http.Cookie[] cookies = this.getRequest().getCookies();
   for(javax.servlet.http.Cookie cookie : cookies){
       if(cookie.getName().equals("openId")){
        openId = cookie.getValue();
       }
    }
return openId;
}

/**
* Desc:获取cookie 订单编号
* param:
* return:订单编号
* Author:LiuChuanting
* Date:2017/9/21
**/
public String getOrderCode(){
String orderCode = "";
   javax.servlet.http.Cookie[] cookies = this.getRequest().getCookies();
   for(javax.servlet.http.Cookie cookie : cookies){
       if(cookie.getName().equals("orderCode")){
        orderCode = cookie.getValue();
       }
    }
return orderCode;
}

获取access_token的原理是 先去缓存拿 如果缓存为空,去请求微信服务器,并更新到缓存中,如果从缓存拿到不为空 根据access_token请求用户信息,报access_token过期(默认两个小时过期)再去请求拿access_token并更新到缓存(获取access_token需要公众号的appid和secret的两个参数就可以请求到)

//根据用户ID和token获取用户信息
public static String getUserInFo(String openId){
DefaultHttpClient client = new DefaultHttpClient();
JSONObject jsonObject = null;
Object token = CacheKit.get("ACCESS_TOKEN","token");
//第一次请求token为空,需要去获取
if(token == null){
String accessToken = HttpClientConnectionManager.getAccessToken();
token = accessToken;
//token放到缓存
CacheKit.put("ACCESS_TOKEN","token", accessToken);
}
String url = Constant.WECHAT_INFO.GET_USERINFO_URL;
url = url.replace("ACCESS_TOKEN",token.toString()).replace("OPENID",openId);
HttpGet get = HttpClientConnectionManager.getGetMethod(url);
HttpResponse response;
try {
response = client.execute(get);
String jsonStr = EntityUtils.toString(response.getEntity(), "utf-8");
jsonObject= (JSONObject) JSON.parse(jsonStr);
if(jsonObject.get("errcode") != null){
//token过期重新获取
String accessToken = HttpClientConnectionManager.getAccessToken();
//token放到缓存
CacheKit.put("ACCESS_TOKEN","token", accessToken);
getUserInFo(openId);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return jsonObject.toString();
}

微信开发需要的一些参数

/**
* 微信接口参数snsapi_userinfo/snsapi_base
*/
public static class WECHAT_INFO {
public static final String APP_ID = ""; //公众号ID
public static final String SECRET= ""; //公众号秘钥
public static final String ACCESS_TOKEN= "NaR8fNK4LXfaqUekYQhViOpEszPo8mIszyWYA58hKtF5hdxW_0ropKxmR4VeThq8jspiA8Y76-fn8bZZOTnDcG5mCle0ifd19IZPqVED0UCz81dm3P7cpYK3TbZh-HtiHUAcAFAWJP"; //公众号token
public static final String URL1= "https://open.weixin.qq.com/connect/oauth2/authorize?"
+ "appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";//获取code的url
public static final String REDIRECT_URL= "http://wechat.qzt360.com/api/weTrack/getUrlOpenid";//重定向的本地URL返回code
public static final String URL2= "https://api.weixin.qq.com/sns/oauth2/access_token?appid=AppId&secret=AppSecret&code=CODE&grant_type=authorization_code";//获取用户openid的URL
public static final String GET_TOKEN_URL= "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";//获取用户公众号token
public static final String GET_USERINFO_URL= "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID";//获取用户信息
}
/**
* 微信支付参数
*/
public static class WECHAT_PAY {
public static final String CALLBACK_URL = "http://wechat.qzt360.com/api/weTrack/getPayResult"; //请求支付后回调路径
public static final String DESCRIPTION = "企智通设备购买"; //商品描述
public static final String ATTACH = "qztgm"; //附加数据
public static final String MCH_ID = "1488893999"; //商户号
public static final String USER_IP = "192.168.1.1"; //用户终端IP
public static final String PAY_KEY= "BA6B005BEF79E7B95F3E097887HGHGH"; //支付KEY
public static final String SIGN_TYPE= "MD5"; //签名类型
public static final Integer LOGISTICE_MONEY= 15; //运费
public static final String ORDER_URL= "https://api.mch.weixin.qq.com/pay/unifiedorder"; //统一下单URL
}

接下来就是微信支付接口了,支付接口非常简单,首先要先预下单去请求微信服务器,返回prepay_id,通过这个ID进行封装,和生成签名返回给H5页面调用微信支付页面弹窗支付密码的窗口,支付成功后 进行回调修改后台业务状态就OK了。

/**
* Desc:微信支付获取支付配置参数
* param:code
* return:无
* Author:LiuChuanting
* Date:2017/9/19
**/
public void getPayConfig(){
String ipurl = this.getRequest().getRemoteAddr();
String openId = getOpenId();
String orderCode = getOrderCode();
JSONObject json = new JSONObject();


   try {
   //调用微信接口统一下单,获取prepayId
String prepayId = WeChatService.me.getPrepayId(openId,ipurl,orderCode);
//生成支付参数返回到页面请求
json = WeChatService.me.createPayConfig(prepayId);
} catch (Exception e) {
logger.error(e.getMessage());
}
renderRb(json);
}

  /**
     * 统一下单
* @param ipurl 
* @param orderCode2 
     * @Title: unifiedOrder 
     * @Description: TODO 
     * @param: @param openId 微信用户openId
     * @param: @param callbackUrl 回调路径
     * @param: @return
     * @return: PrepayId
     */
public String getPrepayId(String openId, String ipurl, String orderCode) {
Record order = Order.me.selectOrderDetail(orderCode);
Integer price = order.getInt("pay_money");
UnifiedOrder unifiedOrder = new UnifiedOrder();
       unifiedOrder.setAppid(Constant.WECHAT_INFO.APP_ID);
       unifiedOrder.setAttach(Constant.WECHAT_PAY.ATTACH);


       unifiedOrder.setBody(Constant.WECHAT_PAY.DESCRIPTION);
       unifiedOrder.setMch_id(Constant.WECHAT_PAY.MCH_ID);


       String nonce = UUID.randomUUID().toString().substring(0, 30);
       unifiedOrder.setNonce_str(nonce);
       unifiedOrder.setNotify_url(Constant.WECHAT_PAY.CALLBACK_URL);


       unifiedOrder.setOpenid(openId);
       unifiedOrder.setOut_trade_no(orderCode);


       unifiedOrder.setSpbill_create_ip(ipurl);
       unifiedOrder.setTotal_fee(1);
       
       String sign = createUnifiedOrderSign(unifiedOrder);
       unifiedOrder.setSign(sign);
       unifiedOrder.setSign_type(Constant.WECHAT_PAY.SIGN_TYPE);


       /**
        * 转成XML格式
        */
       String xml = XmlKit.getBeanXml(unifiedOrder);


       String response = null;
try {
response = HttpConnection.post(Constant.WECHAT_PAY.ORDER_URL, xml);
} catch (Exception e) {
e.printStackTrace();
}
       Map<String, String> responseMap = XmlKit.getXml2Map(response);


       return responseMap.get("prepay_id");
}

注意签名的参数要跟请求统一下单的参数要保持一致除了key,sign以外,因为你自己生成的签名,和你统一下单的参数一起请求微信服务器接口,微信根据你的参数也生存一个签名,然后跟你的签名进行对比,如果不一致会返回 “签名错误” 状态信息

  /**
     * 获取统一下单签名
     * @Title: createUnifiedOrderSign
     * @Description: TODO
     * @param @param unifiedOrder
     * @param @return    
     * @return String    
     * @throws
     */
    public String createUnifiedOrderSign(UnifiedOrder unifiedOrder){
        StringBuffer sign = new StringBuffer();
        sign.append("appid=").append(unifiedOrder.getAppid());
        /*sign.append("&attach=").append(unifiedOrder.getAttach());*/
        sign.append("&body=").append(unifiedOrder.getBody());
        sign.append("&mch_id=").append(unifiedOrder.getMch_id());
        sign.append("&nonce_str=").append(unifiedOrder.getNonce_str());
        sign.append("&notify_url=").append(unifiedOrder.getNotify_url());
        sign.append("&openid=").append(unifiedOrder.getOpenid());
        sign.append("&out_trade_no=").append(unifiedOrder.getOut_trade_no());
        sign.append("&spbill_create_ip=").append(unifiedOrder.getSpbill_create_ip());
        sign.append("&total_fee=").append(unifiedOrder.getTotal_fee());
        sign.append("&trade_type=").append(unifiedOrder.getTrade_type());
        sign.append("&key=").append(Constant.WECHAT_PAY.PAY_KEY);
        return DigestUtils.md5Hex(sign.toString()).toUpperCase();
    }

微信支付回调

    /**
     * 获取支付配置
     * @Title: createPayConfig
     * @Description: TODO
     * @param @param preayId 统一下单prepay_id
     * @param @return 返回json参数到H5页面调起微信支付
     * @param @throws Exception    
     * @return JsAPIConfig    
     * @throws
     */
    public JSONObject createPayConfig(String prepayId){
    JsAPIConfig config = new JsAPIConfig();
    JSONObject json = new JSONObject();
    try {
            String nonce = UUID.randomUUID().toString();
            String timestamp = Long.toString(System.currentTimeMillis() / 1000);
            String packageName = "prepay_id="+prepayId;
            StringBuffer sign = new StringBuffer();
            sign.append("appId=").append(Constant.WECHAT_INFO.APP_ID);
            sign.append("&nonceStr=").append(nonce);
            sign.append("&package=").append(packageName);
            sign.append("&signType=").append(config.getSignType());
            sign.append("&timeStamp=").append(timestamp);
            sign.append("&key=").append(Constant.WECHAT_PAY.PAY_KEY);
            String signature = DigestUtils.md5Hex(sign.toString()).toUpperCase();


            json.put("appId",Constant.WECHAT_INFO.APP_ID);
            json.put("timeStamp",timestamp);
            json.put("nonceStr",nonce);
            json.put("package",packageName);
            json.put("signType",config.getSignType());
            json.put("paySign",signature);
} catch (Exception e) {
logger.error(e.getMessage());
}
        return json;
    }

    /**
     * 微信支付回调页面
     * @Title: wechatPayNotify
     * @Description: TODO
     * @param @param request
     * @param @param trade_status
     * @param @param out_trade_no
     * @param @param trade_no    
     * @return void    
     * @throws
     */
    public String getPayResult(){
    try {
            Map<String, String> map = XmlKit.getCallbackParams(this.getRequest());
            if (map.get(Constant.RESULT_CODE).toString().equalsIgnoreCase(Constant.STATUS)) {
            //这里写成功后的业务逻辑
            WeChatService.me.finishOrder(map,0);
            logger.equals("支付成功");
            }else{
            logger.equals("支付失败");
            WeChatService.me.finishOrder(map,1);
            }
       } catch (Exception e) {
      logger.error(e.getMessage());
       }
return XmlKit.getPayCallback();
    }

如果文章对您有帮助,请扫描最底下的二维码赞赏,你的支持是我最大的动力谢谢!

 

2018-08-24 14:33:38 qq_34190023 阅读数 5429
  • 微信公众号开发9-公众JSSDK开发-微信开发php

    微信公众平台开发之公众号JSSDK开发是子恒老师《微信公众平台开发》视频教程的第9部。详细讲解了用php开发微信公众号,对微信公众平台中的JSSDK开发。内容包含用JSSDK获取网络状态,地理位置,分享到朋友圈,QQ,空间设置等等。欢迎反馈,微信/QQ:68183131

    14923 人正在学习 去看看 秦子恒

 

微信开放平台开发系列文章:

微信开放平台开发第三方授权登陆(一):开发前期准备

微信开放平台开发第三方授权登陆(二):PC网页端

微信开放平台开发第三方授权登陆(三):Android客户端

微信开放平台开发第三方授权登陆(四):微信公众号

微信开放平台开发第三方授权登陆(五):微信小程序

 

 

目录

一、需求

二、开发流程

三、具体实现步骤

1.引导用户跳转到微信授权网页

2. 通过code换取网页授权access_token

3.根据token获取用户信息

四、参数位置:


一、需求

根据需求,需要拥有第三方微信登录功能,并获取到用户信息。

二、开发流程

微信公众平台第三方授权登录的应用场景在于 : 在微信客户端(PC或APP)访问第三方网页,公众号可以通过网页授权机制,获取用户基本信息,实现业务逻辑。

1用户同意授权,获取code

2通过code换取网页授权access_token

3通过access_token拉取用户信息(需scope为 snsapi_userinfo)

公众号第三方授权获取用户信息基本流程

三、具体实现步骤

1.引导用户跳转到微信授权网页

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

参数

说明

appid

公众号的唯一标识

redirect_uri

授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理

response_type

返回类型,请填写code

scope

应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )

state

重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节

#wechat_redirect

无论直接打开还是做页面302重定向时候,必须带此参数

如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。

注意:code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期

 @RequestMapping("/login")
    public String wechatLogin(HttpServletRequest httpServletRequest) {

        // 应用授权作用域:
        // 当为snsapi_base时,不弹出授权页面,直接跳转,只能获取用户openid。
        // 当为snsapi_userinfo时,弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息
        String scope = "snsapi_userinfo";

        String state = UUID.randomUUID().toString().replaceAll("-","");

        // 采用redis等进行缓存state 使用sessionId为key 30分钟后过期,可配置
        RedisPoolUtil.setEx("wechat-mp-state-"+httpServletRequest.getSession().getId(), state, Integer.parseInt(env.getProperty("wechat.mp.exTime", "1800")));

        log.info("state= "+state);

        // 微信公众平台
        String get_auth_url = "https://open.weixin.qq.com/connect/oauth2/authorize?"
                + "appid="
                + env.getProperty("wechat.mp.appid")
                + "&redirect_uri="
                + env.getProperty("application.url")
                + env.getProperty("wechat.mp.redirect_uri")
                + "&response_type=code"
                + "&scope="
                + scope
                + "&state="
                + state
                + "#wechat_redirect";

        log.info("URL:"+get_auth_url);

        return "redirect:" + get_auth_url;
    }

2. 通过code换取网页授权access_token

用户同意授权后,通过code换取网页授权access_token

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数

说明

appid

公众号的唯一标识

secret

公众号的appsecret

code

填写第一步获取的code参数

grant_type

填写为authorization_code

请求正确返回的结果样例:

{ "access_token":"ACCESS_TOKEN", //网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同

"expires_in":7200,  // access_token接口调用凭证超时时间,单位(秒)

"refresh_token":"REFRESH_TOKEN", //用户刷新access_token

"openid":"OPENID",  //用户唯一标识

"scope":"SCOPE" }   //用户授权的作用域,使用逗号(,)分隔

错误返回样例:

{"errcode":40029,"errmsg":"invalid code"}


 

@RequestMapping("/getInfo")
    public String getInfo(HttpServletRequest httpServletRequest, Model model) {

        String code = httpServletRequest.getParameter("code");
        String state = httpServletRequest.getParameter("state");

        String value = RedisPoolUtil.get("wechat-mp-state-"+httpServletRequest.getSession().getId());

        log.info("Code = " + code+"  . State="+state+"    value="+value);

        /* 如果state值不匹配,则为非法请求,抛出异常 */
        if (StringUtils.isEmpty(code)||StringUtils.isEmpty(state)||value==null || !state.equals(value)){
            throw new RuntimeException("非法请求");
        }

        // 通过code换取网页授权access_token
        String get_access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                "appid=" +
                env.getProperty("wechat.mp.appid") +
                "&secret=" +
                env.getProperty("wechat.mp.secret") +
                "&code=" +
                code +
                "&grant_type=authorization_code";

        log.info(get_access_token_url);


        JSONObject accessTokenJsonObject = HttpClientUtils.httpGet(get_access_token_url);

        checkResult(accessTokenJsonObject);
        // 成功获取
        String access_token = (String) accessTokenJsonObject.get("access_token");
        Integer expires_in = (Integer) accessTokenJsonObject.get("expires_in");//access_token接口调用凭证超时时间,单位(秒)
        String userOpenid = (String) accessTokenJsonObject.get("openid");//用户唯一标识
        String scope = (String) accessTokenJsonObject.get("scope");//用户授权的作用域,使用逗号(,)分隔

        // TODO:文档没有写返回unionid,需要在实际公众号中进行测试(绑定开放平台的会有),如果没有unionid,则用openid存储用户,虽然这并不是合理的做法。因为openid仅仅该公众号下的用户唯一标识。。。

//        access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,
//        refresh_token有效期为30天,当refresh_token失效之后,需要用户重新授权

        WeChatUserInfo weChatUserInfo = null;

        weChatUserInfo = null; //FIXME: 根据unionid从数据库中查询
        if (weChatUserInfo == null){
            weChatUserInfo = getMPWeChatUserInfo(access_token,userOpenid);
            // insert into database

        }

        if (weChatUserInfo.getUnionid()!=null){
            // 当前是绑定开放平台的公众号.Union将成为唯一标识

        }

        model.addAttribute(weChatUserInfo);
        return "wechatUser";
    }

3.根据token获取用户信息

http:GET(请使用https协议) https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

参数

描述

access_token

网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同

openid

用户的唯一标识

lang

返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语

正确时返回的JSON数据包如下:

{

"openid":" OPENID",
" nickname": NICKNAME,
"sex":"1",
"province":"PROVINCE"
"city":"CITY",
"country":"COUNTRY",
"headimgurl":    "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
"privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

private WeChatUserInfo getMPWeChatUserInfo(String accessToken, String openId){

        String get_userInfo_url = "https://api.weixin.qq.com/sns/userinfo?" +
                "access_token=" +
                accessToken +
                "&openid=" +
                openId +
                "&lang=zh_CN";

        JSONObject userInfoJsonObject = HttpClientUtils.httpGet(get_userInfo_url);

        checkResult(userInfoJsonObject);

        String user_openid = (String) userInfoJsonObject.get("openid");
        String user_nickname = (String) userInfoJsonObject.get("nickname");
        Integer user_sex = (Integer) userInfoJsonObject.get("sex");//用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
        String user_province = (String) userInfoJsonObject.get("province");
        String user_city = (String) userInfoJsonObject.get("city");
        String user_country = (String) userInfoJsonObject.get("country");//国家,如中国为CN,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
        String user_headimgurl = (String) userInfoJsonObject.get("headimgurl");//头像
        List user_privilege = (List) userInfoJsonObject.get("privilege");//用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
        String user_unionid = (String) userInfoJsonObject.get("unionid");


        WeChatUserInfo weChatUserInfo = new WeChatUserInfo();
        weChatUserInfo.setOpenid(user_openid);
        weChatUserInfo.setNickname(user_nickname);
        weChatUserInfo.setSex(user_sex);
        weChatUserInfo.setProvince(user_province);
        weChatUserInfo.setCity(user_city);
        weChatUserInfo.setCountry(user_country);
        weChatUserInfo.setHeadimgurl(user_headimgurl);
        weChatUserInfo.setPrivilege(StringTools.listToString(user_privilege));
        weChatUserInfo.setUnionid(user_unionid);

        log.info("用户信息如下:" +
                "   opeinId:" + user_openid +
                "   用户昵称:" + user_nickname +
                "   用户的性别:" + user_sex +
                "   省份:" + user_province +
                "   城市:" + user_city +
                "   国家:" + user_country +
                "   头像:" + user_headimgurl +
                "   用户特权信息:" + user_privilege +
                "   UnionId:" + user_unionid
        );

        return weChatUserInfo;
    }

四、参数位置:

开放平台绑定公众号:

2018-11-14 17:30:28 licheng989 阅读数 2277
  • 微信公众号开发9-公众JSSDK开发-微信开发php

    微信公众平台开发之公众号JSSDK开发是子恒老师《微信公众平台开发》视频教程的第9部。详细讲解了用php开发微信公众号,对微信公众平台中的JSSDK开发。内容包含用JSSDK获取网络状态,地理位置,分享到朋友圈,QQ,空间设置等等。欢迎反馈,微信/QQ:68183131

    14923 人正在学习 去看看 秦子恒

微信公众号开发分为微信公众平台和公众号第三方平台。
首先需要一个认证服务号,然后在设置,基本配置里面配置公众号开发信息和服务器配置。 这是我们会得到开发者ID(AppID),开发者密码(AppSecret),服务器地址(URL),令牌(token),消息加解密秘钥(EncodingAESKey)。通过以上信息,就可以获取的微信公众平台的访问令牌(access_token),调用微信公众平台接口时,都需要access_token.
当公众号交给第三方软件公司定制时,需告知以上信息。考虑到安全性,腾讯推出了公众号第三方平台。第三方软件公司通过开发者资质认证,创建第三方平台。调用公众号第三方平台提供的登录功能,公众号用户登录公众号之后,就会弹出授权弹出框,可以选择是否授权。授权之后,第三方软件公司就可以得到一个微信提供的登录令牌access_token。第三方软件公司就可以通过这个access_token调用公众号平台的api了.

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