微信开发 授权登录_微信开发微信小程序授权登录 - CSDN
  • 微信授权登录开发

    2018-04-10 22:48:57
    问题:这几天公司要搞一个微信授权验证,之前没有接触过,不过没有办法,只能够自己硬着头皮去看,幸好文档很多很丰富,最后这几天终于搞出来了,下面的代码还需要进行一些封装以便日后重复使用!第一:微信公众平台...

    问题:这几天公司要搞一个微信授权验证,之前没有接触过,不过没有办法,只能够自己硬着头皮去看,幸好文档很多很丰富,最后这几天终于搞出来了,下面的代码还需要进行一些封装以便日后重复使用!

    第一:微信公众平台API地址点击打开链接

    第二:手机微信扫码登录申请测试账号APPID APPSERCET等点击打开链接

    第三:还需要一个域名可以实现内网穿透做本地测试!点击打开链接

    第四:具体的开发步骤看第一步,下面是具体的代码,可以借鉴!但是不要复制

    <!--微信使用的maven包-->
        <dependencies>
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>4.5.5</version>
            </dependency>
        </dependencies>
    package com.chaimao.base.utils;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.util.EntityUtils;
    
    import java.io.IOException;
    
    /**
     * 微信开发工具
     * @author hp
     * @data 2018/4/4
     */
    public class WXAuthUtil {
        public static final String APPID="";
        public static final String APPSECRET ="";
        private static final String TOKEN = "";
        public static JSONObject doGetJson(String url) throws ClientProtocolException, IOException {
            JSONObject jsonObject =null;
            DefaultHttpClient client = new DefaultHttpClient();
            HttpGet httpGet =new HttpGet(url);
            HttpResponse response =  client.execute(httpGet);
            HttpEntity entity =response.getEntity();
            if(entity!=null)
            {
                //把返回的结果转换为JSON对象
                String result = EntityUtils.toString(entity, "UTF-8");
                jsonObject = JSON.parseObject(result);
            }
            return jsonObject;
        }
    }
    
    package com.publish.weixin.controller;
    
    import com.alibaba.fastjson.JSONObject;
    import com.chaimao.base.utils.Sha1Degist;
    import com.chaimao.base.utils.Utils;
    import com.chaimao.base.utils.WXAuthUtil;
    import com.publish.user.UserService;
    import com.publish.weixin.WeiXinService;
    import org.apache.http.ParseException;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.net.URLEncoder;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 微信接口开发
     * @author gwm
     * @data 2018/4/4
     */
    
    @CrossOrigin
    @RestController
    @RequestMapping("/weixin")
    public class WeiXinController {
    
        @Autowired
        private WeiXinService weixinService;
    
        @Autowired
        private UserService userService;
    
        //这个token是自己随便生成的token
        public static final String TOKEN="gwm0818";
    
        private static Logger logger= LoggerFactory.getLogger(WeiXinController.class);
    
        //验证这个url是否正确
        @RequestMapping("/init")
        public void init(HttpServletRequest request, HttpServletResponse response){
            //		timestamp	时间戳
            //		signature	微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
            logger.info("微信init开始");
            //		nonce	随机数
            //		echostr
            String signature = request.getParameter("signature");
            String timestamp = request.getParameter("timestamp");
            String nonce = request.getParameter("nonce");
            String echostr = request.getParameter("echostr");
            String[] arrs = {WeiXinController.TOKEN,nonce,timestamp};
            Arrays.sort(arrs);
            StringBuffer sb = new StringBuffer();
            for(String a:arrs) {
                sb.append(a);
            }
            String sha1 = Sha1Degist.getString(sb.toString());
            logger.info("sha1="+sha1.equals(signature));
            if(sha1.equals(signature)) {
                try {
                    response.getWriter().println(echostr);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 公众号微信登录授权
         * @param request
         * @param response
         * @return
         * @throws ParseException
         * @author  lbh
         * @date 创建时间:2018年1月18日 下午7:33:59
         * @parameter
         */
        @RequestMapping(value = "/wxLogin", method = RequestMethod.GET)
        public void wxLogin(HttpServletRequest request,
                              HttpServletResponse response)
                throws ParseException {
            //这个url的域名必须要进行再公众号中进行注册验证,这个地址是成功后的回调地址
            String backUrl="http://你的域名/weixin/callBack";
            // 第一步:用户同意授权,获取code
            String url ="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+ WXAuthUtil.APPID
                    + "&redirect_uri="+ URLEncoder.encode(backUrl)
                    + "&response_type=code"
                    + "&scope=snsapi_userinfo"
                    + "&state=STATE#wechat_redirect";
    
            try {
                logger.info("微信重定向");
                response.sendRedirect(url);
                logger.info("现在回调");
            } catch (IOException e) {
                e.printStackTrace();
            }
            //return "redirect:"+url;//必须重定向,否则不能成功
        }
    
    
        /**
         * 公众号微信登录授权回调函数
         * @param req
         * @param resp
         * @return
         * @throws ServletException
         * @throws IOException
         * @author  lbh
         * @date 创建时间:2018年1月18日 下午7:33:53
         * @parameter
         */
        @RequestMapping(value = "/callBack", method = RequestMethod.GET)
        public void callBack(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            /*
             * start 获取微信用户基本信息
             */
            String code =req.getParameter("code");
            logger.info("//"+code);
            //第二步:通过code换取网页授权access_token
            String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+WXAuthUtil.APPID
                    + "&secret="+WXAuthUtil.APPSECRET
                    + "&code="+code
                    + "&grant_type=authorization_code";
    
    
            logger.info("url:"+url);
            JSONObject jsonObject = WXAuthUtil.doGetJson(url);
            /*返回的样式
             { "access_token":"ACCESS_TOKEN",
                "expires_in":7200,
                "refresh_token":"REFRESH_TOKEN",
                "openid":"OPENID",
                "scope":"SCOPE"
               }
             */
            String openid = jsonObject.getString("openid");
            String access_token = jsonObject.getString("access_token");
            String refresh_token = jsonObject.getString("refresh_token");
            //第五步验证access_token是否失效;展示都不需要
            String chickUrl="https://api.weixin.qq.com/sns/auth?access_token="+access_token+"&openid="+openid;
    
            JSONObject chickuserInfo = WXAuthUtil.doGetJson(chickUrl);
            logger.info(chickuserInfo.toString());
            if(!"0".equals(chickuserInfo.getString("errcode"))){
                // 第三步:刷新access_token(如果需要)-----暂时没有使用,参考文档https://mp.weixin.qq.com/wiki,
                String refreshTokenUrl="https://api.weixin.qq.com/sns/oauth2/refresh_token?appid="+openid+"&grant_type=refresh_token&refresh_token="+refresh_token;
    
                JSONObject refreshInfo = WXAuthUtil.doGetJson(chickUrl);
                /*
                 * { "access_token":"ACCESS_TOKEN",
                    "expires_in":7200,
                    "refresh_token":"REFRESH_TOKEN",
                    "openid":"OPENID",
                    "scope":"SCOPE" }
                 */
                logger.info(refreshInfo.toString());
                access_token=refreshInfo.getString("access_token");
            }
    
            // 第四步:拉取用户信息(需scope为 snsapi_userinfo)
            String infoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token="+access_token
                    + "&openid="+openid
                    + "&lang=zh_CN";
            logger.info("infoUrl:"+infoUrl);
            JSONObject userInfo = WXAuthUtil.doGetJson(infoUrl);
            /*
             {    "openid":" OPENID",
                " nickname": NICKNAME,
                "sex":"1",
                "province":"PROVINCE"
                "city":"CITY",
                "country":"COUNTRY",
                "headimgurl":    "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
                "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],
                "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
                }
             */
            logger.info("JSON-----"+userInfo.toString());
            logger.info("名字-----"+userInfo.getString("nickname"));
            logger.info("头像-----"+userInfo.getString("headimgurl"));
            /*
             * end 获取微信用户基本信息
             * 将用户信息存入数据库
             */
            Map<String,Object> params=new HashMap<String,Object>();
            params.put("openid",userInfo.getString("openid"));
            params.put("nickname",userInfo.getString("nickname"));
            params.put("headimgurl",userInfo.getString("headimgurl"));
            params.put("sex",userInfo.getString("sex"));
            params.put("city",userInfo.getString("city"));
            params.put("unionid",userInfo.getString("unionid"));
            params.put("province",userInfo.getString("province"));
            params.put("country",userInfo.getString("country"));
    
            //开始赋值ID给weixin_user_id;
            Utils.WEIXIN_USER_ID=Utils.createID();
            params.put("user_id",Utils.WEIXIN_USER_ID);
            logger.info("微信用户的ID"+Utils.WEIXIN_USER_ID);
            try{
                if(userService.getUserInfoById(params.get("openid")+"")==null){
                    userService.addUserInfo(params);
                }
                //获取到用户信息后就可以进行重定向,实现自己业务逻辑了。。。。。。
                //接来的逻辑就是系统逻辑
                resp.sendRedirect("http://localhost:8080/HUARUN_project/index.html");
                System.out.println("重定向到自己的页面!");
            }catch (Exception e){
                e.printStackTrace();
                return ;
            }
        }
    
        /**
         * 查询所有的用户信息
         * @return
         */
        @PostMapping("/getAllUserInfo")
        public Object getAllUserInfo(@RequestBody Map<String,Object> params) {
            logger.info("user_id="+params.get("user_id"));
            Utils.myTrimAndLike(params, "nickname");
            return userService.getAllUserInfo(params);
        }
    
    
        @RequestMapping("/testStr")
        public String testStr(){
            Map<String,Object> params=new HashMap<String,Object>();
            params.put("openid","openid");
            params.put("nickname","nkname");
            params.put("headimgurl","headimgurl");
            params.put("sex","sex");
            params.put("city","city");
            params.put("unionid","unionid");
            params.put("province","province");
            params.put("country","country");
    
            //开始赋值ID给weixin_user_id;
            Utils.WEIXIN_USER_ID=Utils.createID();
            params.put("user_id",Utils.WEIXIN_USER_ID);
    
            try{
                //插入之前先查询有没有该用户存在
                if(userService.getUserInfoById(params.get("openid")+"")!=null){
                    return "userIsExist";
                }
                if(userService.addUserInfo(params)>0){
                    //获取到用户信息后就可以进行重定向,实现自己业务逻辑了。。。。。。
                    //接来的逻辑就是系统逻辑
                    logger.info("验证登录成功!");
                    //resp.sendRedirect("我自己的上传页面!");
                }
            }catch (Exception e){
                e.printStackTrace();
                return "errors";
            }
            return "errors";
        }
    }
    
    ☞☛总结:微信授权无非就是第三方请求我们获取返回数据然后处理自己的业务,不要看得太难!





    展开全文
  • 微信开放平台开发系列文章: 微信开放平台开发第三方授权登陆(一):开发前期准备 微信开放平台开发第三方授权登陆(二):PC网页端 微信开放平台开发第三方授权登陆(三):Android客户端 微信开放平台开发第...

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

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

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

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

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

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

     

    目录

    一、需求

    二、开发流程

    1.网站应用:(微信客户端扫码授权登陆)

    三、开发使用的技术及工具

    四、具体实现步骤

    1、网站应用

    1)请求获取Code

    2)用户同意授权与否

    3)获取access_token

    4)通过access_token调用接口获取用户个人信息(UnionID机制)

    5)刷新access_token

    五、测试结果

    1、网站应用

    六、应用关键参数位置


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

      当微信开放平台开发第三方授权登陆(一):开发前期准备完成后,已经获取到应用的AppID和AppSecret、且已经成功申请到微信登陆功能。可以进行第三方登陆授权开发。

    网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。

    一、需求

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

    二、开发流程

    1.网站应用:(微信客户端扫码授权登陆)

    1)第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;

    2)通过code参数加上AppID和AppSecret等,通过API换取access_token;

    3)通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

    网站应用第三方授权登陆获取用户信息

    三、开发使用的技术及工具

    1、使用IDEA2017.2进行开发

    2、使用SpringBoot进行快速开发

    3、使用redis进行缓存。

    4、使用fastJson对json数据进行处理

    5、使用Maven对项目进行管理

    四、具体实现步骤

    1、网站应用

    创建工程

    打开IDEA,新建一个工程,选择Spring Initializr,Next。然后填写工程基本信息

    选择SpringBoot的版本已经需要添加的依赖,也可以直接跳过,手动添加依赖。由于是web工程,需要添加web相关依赖。模板引擎采用springboot推荐的thymeleaf。最后点击确认,进入工程。

     

    添加相关依赖

       <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-lang3</artifactId>
          <version>3.5</version>
       </dependency>
       <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>1.2.4</version>
       </dependency>
       <!-- 添加httpclient支持 -->
       <dependency>
          <groupId>org.apache.httpcomponents</groupId>
          <artifactId>httpclient</artifactId>
          <version>4.5.2</version>
       </dependency>
       <dependency>
          <groupId>redis.clients</groupId>
          <artifactId>jedis</artifactId>
          <version>2.8.1</version>
          <type>jar</type>
       </dependency>

    添加配置文件

    SpringBoot默认会将resources下的application名字开头的properties作为配置文件。所以只需要添加application.properties就可以了

    由于是使用thymeleaf作为模板引擎。可以添加相应的配置:

    #thymelea模板配置
    spring.thymeleaf.prefix=classpath:/templates/
    spring.thymeleaf.suffix=.html
    spring.thymeleaf.mode=HTML5
    spring.thymeleaf.encoding=UTF-8
    spring.thymeleaf.content-type=text/html
    spring.thymeleaf.cache=false
    spring.resources.chain.strategy.content.enabled=true
    spring.resources.chain.strategy.content.paths=/**

    为了让系统更具有通用性,分别创建application-dev.properties、application-prod.properties对不同的环境进行配置。

    在application.properties中,使用spring.profiles.active进行配置环境的选择。

    如:spring.profiles.active = prod

     

    如:application-prod.properties

    ## 微信开放平台
    # APPID
    wechat.open.appid =
    # APPSECRET
    wechat.open.appsecret =
    # 回调地址
    wechat.open.redirect_uri =

    新建javaBean:WeChatUserInfo.java

    @Getter @Setter @ToString
    public class WeChatUserInfo {
        String openid;
        String nickname;
        Integer sex;
        String province;
        String city;
        String country;
        String headimgurl;
        String privilege;
        String unionid;
    
    }

    新建WeChatOpenLoginController.java实现微信开放平台第三方登录的主要逻辑。

    根据文档进行编写代码。

     

    1)请求获取Code

    前提:应用已经获取相应的网页授权作用域(scope=snsapi_login)

    开发:第三方网站引导用户打开链接

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

    参数说明:

    参数

    必须

    说明

    appid

    应用唯一标识

    redirect_uri

    请使用urlEncode对链接进行处理

    response_type

    填code

    scope

    应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可

    state

    用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验

     

    注意:若提示“该链接无法访问”,请检查参数是否填写错误,如redirect_uri的域名与审核时填写的授权域名不一致或scope不为snsapi_login。


      

      @RequestMapping("/login")
        public String openWeChatLogin(HttpServletRequest httpServletRequest) {
            // 防止csrf攻击(跨站请求伪造攻击)
            String state = UUID.randomUUID().toString().replaceAll("-", "");
            // 采用redis等进行缓存state 使用sessionId为key 30分钟后过期,可配置
            RedisPoolUtil.setEx("wechat-open-state-" + httpServletRequest.getSession().getId(), state, Integer.parseInt(env.getProperty("wechat.open.exTime", "1800")));
            String url = "https://open.weixin.qq.com/connect/qrconnect?" +
                    "appid=" +
                    env.getProperty("wechat.open.pc.appid").trim() +
                    "&redirect_uri=" +
                    env.getProperty("application.url") +
                    env.getProperty("wechat.open.pc.redirect_uri").trim() +
                    "&response_type=code" +
                    "&scope=snsapi_login" +
                    "&state=" +
                    state +     // 由后台自动生成
                    "#wechat_redirect";
            return "redirect:" + url;
        }

    2)用户同意授权与否

    用户允许授权后,将会重定向到redirect_uri的网址上,并且带上code和state参数

    redirect_uri?code=CODE&state=STATE

    若用户禁止授权,则不会重定向到我们提供的回调地址中

     

    成功授权后,将获得Code,通过Code可以获取access_token

     

    3)获取access_token

    通过上述方法获取的code获取access_token.

    Http Get请求

    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

     

    请求后,

    返回成功的json串为(样例):

    {
    "access_token":"ACCESS_TOKEN",        // 接口调用凭证
    "expires_in":7200,                      // access_token接口调用凭证超时时间,单位(秒)
    "refresh_token":"REFRESH_TOKEN",       //用户刷新access_token
    "openid":"OPENID",                                  //授权用户唯一标识
    "scope":"SCOPE",                                     //用户授权的作用域,使用逗号(,)分隔
    "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"  //当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段
    }

    失败返回的样例:

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

    失败可能原因:  暂时不明

        @RequestMapping("/callback/pc")
        public String openWeChatCallback(HttpServletRequest httpServletRequest, Model model) {
            String code = httpServletRequest.getParameter("code");
            String state = httpServletRequest.getParameter("state");
            String url = null;
            // 判断state是否合法
            String stateStr = RedisPoolUtil.get("wechat-open-state-" + httpServletRequest.getSession().getId());
            if (StringUtils.isEmpty(code) || StringUtils.isEmpty(stateStr) || !state.equals(stateStr)) {
                throw new WechatParamException("非法参数,请重新登陆", "/");
            }
            url = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                    "appid=" +
                    env.getProperty("wechat.open.pc.appid").trim() +
                    "&secret=" +
                    env.getProperty("wechat.open.pc.appsecret").trim() +
                    "&code=" +
                    code +
                    "&grant_type=authorization_code";
            JSONObject wechatAccessToken = HttpClientUtils.httpGet(url);
            if (wechatAccessToken.get("errcode") != null) {
                throw new WechatParamException("获取accessToken失败", "/wechat/open/login");
            }
            String accessToken = (String) wechatAccessToken.get("access_token");
            String openid = (String) wechatAccessToken.get("openid");
            String unionid = (String) wechatAccessToken.get("unionid");
            if (StringUtils.isEmpty(accessToken) || StringUtils.isEmpty(openid) || StringUtils.isEmpty(unionid)) {
                throw new WechatParamException("获取accessToken失败", "/wechat/open/login");
            }
            // TODO:根据Openid或Unionid对数据库进行查询,如果查询到对应的用户数据,则不需要再向微信服务器发送请求去返回数据。
            // TODO: 建议使用Unionid作为查询条件。
            WeChatUserInfo weChatUserInfo = null;
            wechatAccessToken = null;  // FIXME: 这里应该是从数据库中查询获取用户信息逻辑。
            if (wechatAccessToken == null) {
                // 新用户
                weChatUserInfo = getUserInfoByAccessToken(accessToken);
                // 数据库插入的操作
            }
            if (weChatUserInfo != null) {
                model.addAttribute(weChatUserInfo);
                return "wechatUser";
            }
            throw new WechatParamException("获取用户信息失败", "/wechat/open/login");
        }

    4)通过access_token调用接口获取用户个人信息(UnionID机制)

    前提:

    1. access_token有效且未超时;

    2. 微信用户已授权给第三方应用帐号相应接口作用域(scope)。

    Http Get请求:

    https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID

    参数

    是否必须

    说明

    access_token

    调用凭证

    openid

    普通用户的标识,对当前开发者帐号唯一

    lang

    国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语,默认为zh-CN

     

    返回成功的json结果(样例):

    {
    "openid":"OPENID",        //普通用户的标识,对当前开发者帐号唯一
    "nickname":"NICKNAME",   //普通用户昵称
    "sex":1,                                //普通用户性别,1为男性,2为女性
    "province":"PROVINCE",      //普通用户个人资料填写的省份
    "city":"CITY",                        //普通用户个人资料填写的城市
    "country":"COUNTRY",         //国家,如中国为CN
    "headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",       //用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空
    "privilege":[   //用户特权信息,json数组,如微信沃卡用户为(chinaunicom)
    "PRIVILEGE1",
    "PRIVILEGE2"
    ],
    "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"   //用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的
    }

     

    失败JSON样例:

    {"errcode":40003,"errmsg":"invalid openid"}

     

    注意:在用户修改微信头像后,旧的微信头像URL将会失效,因此开发者应该自己在获取用户信息后,将头像图片保存下来,避免微信头像URL失效后的异常情况

    最好保存用户unionID信息,以便以后在不同应用中进行用户信息互通。

    private WeChatUserInfo getUserInfoByAccessToken(String accessToken) {
            if (StringUtils.isEmpty(accessToken)) {
                return null;  //"accessToken为空";
            }
            String get_userInfo_url = null;
            get_userInfo_url = "https://api.weixin.qq.com/sns/userinfo?" +
                    "access_token=" +
                    accessToken +
                    "&openid=" +
                    env.getProperty("wechat.open.pc.appid").trim();
            String userInfo_result = HttpClientUtils.httpGet(get_userInfo_url, "utf-8");
            if (!userInfo_result.equals("errcode")) {
                WeChatUserInfo weChatUserInfo = JSON.parseObject(userInfo_result, new TypeReference<WeChatUserInfo>() {
                });
                // TODO: 需要把头像信息下载到文件服务器,然后替换掉头像URL。微信的或许不可靠,假设微信用户更换了头像,旧头像URL是否会保存?而这个URL信息却存放在我们的数据库中,不可靠
                return weChatUserInfo;
            }
            return null;  //"获取用户信息失败"
        }

    5)刷新access_token

    由于access_token有效期(目前为2个小时)较短,当access_token超时后,可以使用refresh_token进行刷新,access_token刷新结果有两种:

    1. 若access_token已超时,那么进行refresh_token会获取一个新的access_token,新的超时时间;
    2. 若access_token未超时,那么进行refresh_token不会改变access_token,但超时时间会刷新,相当于续期access_token。

    refresh_token拥有较长的有效期(30天),当refresh_token失效的后,需要用户重新授权。

     

    请求方法:

    获取第一步的code后,请求以下链接进行refresh_token:

    https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

    参数说明:

    参数

    是否必须

    说明

    appid

    应用唯一标识

    grant_type

    填refresh_token

    refresh_token

    填写通过access_token获取到的refresh_token参数

     

    成功返回的结果:

    {
    "access_token":"ACCESS_TOKEN",    //接口调用凭证
    "expires_in":7200,                             // access_token接口调用凭证超时时间,单位(秒)
    "refresh_token":"REFRESH_TOKEN",   //用户刷新access_token
    "openid":"OPENID",                          //授权用户唯一标识
    "scope":"SCOPE"                              //用户授权的作用域,使用逗号(,)分隔
    }

    失败样例:

    {"errcode":40030,"errmsg":"invalid refresh_token"}

     

    注意:

    1、Appsecret 是应用接口使用密钥,泄漏后将可能导致应用数据泄漏、应用的用户数据泄漏等高风险后果;存储在客户端,极有可能被恶意窃取(如反编译获取Appsecret);
    2、access_token 为用户授权第三方应用发起接口调用的凭证(相当于用户登录态),存储在客户端,可能出现恶意获取access_token 后导致的用户数据泄漏、用户微信相关接口功能被恶意发起等行为;
    3、refresh_token 为用户授权第三方应用的长效凭证,仅用于刷新access_token,但泄漏后相当于access_token 泄漏,风险同上。

    建议将secret、用户数据(如access_token)放在App云端服务器,由云端中转接口调用请求。

     

    五、测试结果

    1、网站应用

    首先开启redis。然后运行代码。由于SpringBoot会使用内置的Tomcat容器进行管理,直接运行就可以了,然后点击微信登录。弹出扫码登录窗口,手机扫码同意登录后就可以获取到用户信息了.

     

    六、应用关键参数位置

    APPID和APPSecret以及回调地址位置,注:需要修改授权回调域,即回调地址

     

    展开全文
  • 微信开放平台“开发资源”中网站... 据开发者资质认证处介绍:开发者资质认证通过后,微信开放平台帐号下的应用,将获得微信登录、智能接口、第三方平台开发等高级能力。 所以在微信第三方授权登陆获取用户信息...

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

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

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

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

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

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

     

    目录

    一、前期准备流程

    二、具体实现步骤

    1、注册邮箱账号

    2、注册微信开放平台账号、完善开发者资料

    3、申请开发者资质认证

    1)申请开发者资质认证

    2)选定类型

    3)填写“认证资料”

    4)填写“管理员信息”

    5)上传“企业基本信息”材料:

    6)进入填写发票及支付费用

    4、创建应用

    1)创建网站应用

    2)创建移动应用

    5、申请微信登陆功能

    三、注意事项

    四.主要提供材料

    五、特殊情况处理方案


    据微信开放平台“开发资源”中网站应用微信登陆功能开发指南描述:进行授权登陆接入前,需要先注册一个开发者账号,并拥有一个已经审核通过的网站应用,并获取AppID和APPSecret,然后申请微信登陆并通过审核后,可以接入流程进行开发。

    据开发者资质认证处介绍:开发者资质认证通过后,微信开放平台帐号下的应用,将获得微信登录、智能接口、第三方平台开发等高级能力。

    所以在微信第三方授权登陆获取用户信息开发前,需要做一些前期准备。目的是获取到AppID以及AppSecret,并成功申请微信登陆功能

    一、前期准备流程

    1、注册邮箱账号。

    2、根据邮箱账号注册微信开放平台账号,完善开发者资料。

    3、申请开发者资质认证、填写相关资料、填写发票、支付认证金额。提交并等待认证结果

    4、认证成功后,创建网站应用,填写基本信息、下载网站信息登记表填写并上传扫描件、填写授权回调域等。提交审核等待结果。

    5、认证成功后,创建移动应用,至少选择安卓、IOS、WP8其中一种平台

    6、创建应用成功后,申请微信登陆,等待审核结果,待审核通过后,可进行微信登陆的开发。

    注:创建应用和开发者资质认证可同时进行

    准备工作大致流程图

    二、具体实现步骤

    1、注册邮箱账号

    支持网易邮箱、QQ邮箱等常规邮箱。此邮箱将成为日后登陆开放平台的账号

     

    2、注册微信开放平台账号、完善开发者资料

    1)填写邮箱进行注册、开放平台将发送邮件到填写邮箱中,点击邮件上的地址进行开发者资料的完善。(开放平台注册地址:https://open.weixin.qq.com/cgi-bin/readtemplate?t=regist/regist_tmpl&lang=zh_CN

    2)开发者资料完善:主要填写注册人信息。如真实姓名、真实手机号码、联系地址、身份证号码。使用注册人的微信扫码绑定为管理员。提交信息。(邮件信息包含地址,点击后进行资料完善)

    3)完善资料后,根据邮箱及密码进行登录

     

    3、申请开发者资质认证

    1)申请开发者资质认证

    登录后,点击右上角邮箱号进入“基本资料”,点击“开发者资质认证”,显示未认证,点击“现在申请”。

    认证成功后,这里将变成认证成功:

    2)选定类型

    同意“微信开放平台开发者资质认证服务协议”,点击下一步。选择类型为“企业”,点击确定。

    注:类型包含了企业、网店商家、媒体(事业单位媒体、其他媒体)、政府及事业单位、其他组织(社会团体、民办非企业、其他组织)

    3)填写“认证资料”

    包括企业全称、组织机构代码、工商执照注册号、法定代表人/企业负责人姓名、经营范围(一般经营范围)、企业规模(选填)、企业开户名称、企业开户银行、企业银行账号。

    4)填写“管理员信息”

    包括账号管理员姓名、账号管理员部门与职位、账号管理员手机号、管理员座机、管理员电子邮件、身份证号。最后需要使用管理员的微信进行扫码。

    5)上传“企业基本信息”材料:

    需要准备的材料及要求如下

    I.组织机构代码证

    组织机构代码证必须在有效期范围内。必须是原件照片、扫描件或复印件加盖企业公章后的扫描件。图片不超2M

    II.企业工商营业执照

    中国大陆工商局或市场监督管理局颁发的工商营业执照,且必须在有效期内。要求原件照片、扫描件或者复印件加盖企业公章后的扫描件

    III.申请公函下载打印

    如果是一般企业需要先下载“一般企业申请认证公函”,个体下载“个体工商户申请认证公函”(见附件中“一般企业申请认证公函.doc”及“个体工商户申请认证公函.doc”或于网站中下载)。对下载的申请公函进行打印。

    IV.填写申请公函信息

    填写内容主要有(根据不同企业类型进行填写,只需要填写其中一个就可以):

    A.一般企业申请认证公函:

    a.企业信息:申请企业全称、官网(可缺省)、办公电话、办公地址、企业规模、企业简介(要说明企业经营范围,重要历程,主要产品和服务及覆盖区域等事项)、

    b.法定代表信息:法定代表人姓名、身份证号码、应用的Appid(这时还没有Appid,此项不填)、登陆Email、

    c.申请相关信息:申请认证理由、提供的服务、

    d.账号运营者信息 : 账号运营者姓名、部门及职位、身份证号、手机号、办公联系电话、电子邮箱

    e.填写认证申请公函:最后运营者签字并加盖企业章

    B.个体工商户申请认证公函:

    a.个体工商户信息:个体工商户全称、官网(可缺省)、办公电话、办公地址、规模、简介(主要说明经营范围,重要历程,主要产品和服务及覆盖区域等事项)

    b.经营者信息:经营者姓名、身份证号码、应用的Appid(这时还没有Appid,此项不填)、登陆Email

    c.申请相关信息:申请认证理由、提供的服务、

    d.账号运营者信息:账号运营者姓名、部门及职位、身份证号、手机号、办公联系电话、电子邮箱

    e.填写认证申请公函:最后运营者签字并加盖企业章

    V.对填写好的申请公函进行上传图片:

    上传加盖企业公章的原件照片或扫描件

    点击下一步。

    6)进入填写发票及支付费用

    等待认证结果。

    注:开发者认证费用为300.有效期一年,可在最后三个月申请年审续期

     

    4、创建应用

    1)创建网站应用

    进入开放平台首页(https://open.weixin.qq.com),点击上方“管理中心”,点击“网站应用”,点击“创建网站应用

    I.填写基本信息

    包括网站应用名称、英文名(选填)、应用简介、英文简介(选填)、应用官网。

    II.上传网站信息登记表扫描件及网站应用图片

           A. 网站信息登记表

    先下载《微信开放平台网站信息登记表》(见附件”微信开放平台网站信息登记表.doc”).然后进行填写打印。最后盖章,上传扫描件。图片不超过2M

    网站开放平台信息登记表填写内容包括:

    a. 网站信息:

    1)网站网址:要创建第三方准备使用的网址。

    2)网站备案号/许可证号

    3)主板单位名称/个人姓名

    4)单位/个人官网网址

    5)单位/个人所在地: 

    6)单位/个人简介:

    b. 开发者账户信息

    1)邮箱:注册微信开放平台的注册邮箱

    2)网站应用名称:与开放平台填写的网站应用名称一致

    c. 负责人信息

    1)  姓名

    2)  职务

    3)  联系人手机

    4)  责任人个人邮箱

    然后填写责任人签名。职务。以及填写日期,最后盖上申请公司的章

           B. 网站应用图片

    上传网站应用水印招聘。28*28像素以及108*108像素的png图片,大小不超过300k。

    上传完成后,点击下一步

    III.填写授权回调域

    填写合法的域名。第三方授权登陆后,只能回调到该域名下的页面。(即,开发的网站上线后的域名)

    审核时间大概7个工作日内(审核资料完整正确的话,大概3天左右能审核通过)

    审核不通过的话,会显示驳回,并且告知哪个环节审核不通过,可以重新修改再审,

    审核成功页面:

    2)创建移动应用

    进入开放平台首页(https://open.weixin.qq.com),点击上方“管理中心”,点击“移动应用”,点击“创建移动应用

    I.填写基本信息

    包括移动应用名称、英文名(选填)、应用简介、英文简介(选填)、应用官网。

    II.上传移动应用图片

        上传移动应用水印图片28*28像素的png图片,以及移动应用高清图片108*108像素的png图片。大小均不超过300k

    III.填写平台信息

         选择平台,一共有三种平台:ISO应用、Android应用和WP8应用

         至少选择一个平台,可以多选。

    A. IOS应用

           细分为iPhone和iPad,可多选

           这两种设备类型均需要提供“Bundle ID”(ISO应用唯一标识)、“测试版本Bundle ID”(ISO应用测试版本的BundleID)、“AppStore下载地址”(选填)

    B.Android应用

            需要提供 “应用签名” 和 “应用包名”,以及“应用下载地址(选填)”

         应用签名可以使用签名生成工具直接从安装当前应用的手机获取,应用签名由开发者签名该应用的keystore文件决定

         应用包名在manifest文件里声明,要和正式发布应用的包名一致。

    C.WP8 应用

            WP8应用只需要填写“应用下载地址(选填)”就可以了。

    注意:应用若还没有提交到应用市场,下载地址等可以暂时为空,提交到应用市场后,可修改下载地址。

     

    注:

    1.审核将在三个工作日内完成,目前只审核开发者的资质和真实性,不涉及应用内容本部,不需要开发者提交ipa文件或将含微信SDK的版本在AppStore上线后再审核,但要求开发者提供该应用已经上线的版本的下载地址

    2.同一应用在不同平台的版本应共用一个AppID

    审核成功后的页面(Android)

    5、申请微信登陆功能

    成功创建应用并审核通过后,点击应用右方“查看”可以查看应用详情。

    在“接口信息”一栏中,查看当前应用拥有的接口权限。

    选中“微信登陆”接口,点击右方申请开通,开通微信登陆功能。

     

    三、注意事项

    1、开发者资质认证结果只有成功或失败两种情况。审核费用与最终是否审核通过无关。每申请一次,就需要支付一次审核服务费用

    2、我方在完成在线申请及资料提交流程,并完成审核服务费用支付后,腾讯会在15个工作日内展开认证工作,我方应积极配合腾讯及第三方审核公司的认证需求,并有权随时了解、查询认证进度

    3.认证失败原因可能情况:

    1)由于我方原因,经腾讯三次系统通知用户调整申请内容,我方仍未能满足开发者资质认证要求的;

    2)由于我方原因:自用户付费之日起三十日,我方仍未能满足开发者资质认证要求之一;

    3)因其他原因而不能认证成功的情形

    4、网站应用和移动应用一个开发者最多只能登记10个。

     

    四.主要提供材料

    主要提供材料,详情见“具体实现步骤

    1. 微信开放平台登陆邮箱
    2. 开发者个人详细信息
    3. 企业信息及法人(负责人)信息(包括官网等)
    4. 企业账号管理员信息(包括微信扫码)
    5. 企业章
    6. 应用官网及备案号/许可证。 应用图标。

     

    五、特殊情况处理方案

    1.若我方向腾讯或者第三方审核机构提供的资料和信息如有变更的,应当及时采取以下措施:

    1)如处于认证过程中的资料和信息发生变更,用户应立即通知腾讯或负责认证订单的第三方审核机构更新有关资料及信息;

    2)如认证成功后资料和信息发生变更,用户应及时申请补充订单变更有关资料及信息;

    3)如认证成功后腾讯发现资料和信息存在错误,用户应及时申请补充订单更正有关资料及信息。

    展开全文
  • 1 微信开放平台:https://open.weixin.qq.com/ 2 微信官方教程:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&...

    1 微信开放平台:https://open.weixin.qq.com/

    2 微信官方教程:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN

    3.pc页面显示

    4. 通过官方提供的文档,我们可以看出一共分4个步骤

    第一步:请求CODE
    第二步:通过code获取access_token
    第三步:通过access_token调用接口
    第4步:获取用户个人信息(UnionID机制)

     

     5.源码下载地址:http://pan.baidu.com/s/1pLyG66J

    因代码加密:现贴出代码如下(下载后替换):

    Controllers--》DefaultController.cs

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Configuration;
      4 using System.Text;
      5 using System.Web;
      6 using System.Web.Mvc;
      7 
      8 using WebWeChat.Models;
      9 
     10 namespace WebWeChat.Controllers
     11 {
     12     public class DefaultController : Controller
     13     {
     14         #region 微信登录
     15 
     16         /// <summary>
     17         /// 微信登录
     18         /// </summary>
     19         public ActionResult WeChat()
     20         {
     21             //获得配置信息
     22             string oauthAppId = ConfigurationManager.AppSettings["oauth_app_id"];
     23             string redirectUri = ConfigurationManager.AppSettings["Redirect_uri"];
     24             if (oauthAppId == null)
     25             {
     26                 return this.Content("出错了,您尚未配置微信相关的API信息!");
     27             }
     28             string state = Guid.NewGuid().ToString().Replace("-", "");
     29             this.Session["oauth_state"] = state;
     30             string sendUrl =
     31                 "https://open.weixin.qq.com/connect/qrconnect?appid=" + oauthAppId +
     32                 "&redirect_uri=" + HttpUtility.UrlEncode(redirectUri.ToLower()) +
     33                 "&response_type=code&scope=snsapi_login&state=" + state +
     34                 "#wechat_redirect";
     35 
     36             //开始发送
     37             return this.Redirect(sendUrl); //跳转到微信自己 指定的关联登陆页面
     38         }
     39 
     40         /// <summary>
     41         /// 微信登录返回action
     42         /// </summary>
     43         public ActionResult WeChatReturnUrl(string state, string code)
     44         {
     45             //取得返回参数
     46 
     47             if (this.Session["oauth_state"] == null || this.Session["oauth_state"].ToString() == "" ||
     48                 state != this.Session["oauth_state"].ToString() || string.IsNullOrEmpty(code)) //若返回参数中未包含code或者state没有通过验证则提示出错
     49             {
     50                 return this.Content("出错啦,state未初始化!");
     51             }
     52 
     53             //第一步:通过code来获取Access Token以及openid
     54             Dictionary<string, object> dic1 = WeixinHelper.get_access_token(code, state);
     55             if (dic1 == null || !dic1.ContainsKey("access_token"))
     56             {
     57                 return this.Content("错误代码:,无法获取Access Token,请检查App Key是否正确!");
     58             }
     59             if (!dic1.ContainsKey("openid"))
     60             {
     61                 return dic1.ContainsKey("errmsg")
     62                     ? this.Content("errcode:" + dic1["errcode"] + ",errmsg:" + dic1["errmsg"])
     63                     : this.Content("出错啦,无法获取用户授权Openid!");
     64             }
     65 
     66             var accessToken = dic1["access_token"].ToString();
     67             var refreshToken = dic1["refresh_token"].ToString();
     68             var openid = dic1["openid"].ToString();
     69 
     70             //储存获取数据用到的信息
     71             this.Session["oauth_name"] = "webchat";
     72             this.Session["oauth_access_token"] = accessToken;
     73             this.Session["oauth_openid"] = openid;
     74             this.Session["oauth_refresh_token"] = refreshToken;
     75 
     76             #region todo 将获取到的用户信息保存到数据库中
     77 
     78             #endregion
     79 
     80             //第二步:通过Access Token以及openid来获取用户的基本信息
     81             //Dictionary<string, object> dic2 = weixin_helper.get_user_info(access_token,openid);
     82 
     83             //第三步:跳转到指定页面
     84             return this.Content(this.WeChatResultJson());
     85         }
     86 
     87         /// <summary>
     88         /// 微信登录返回action, 处理用户信息
     89         /// </summary>
     90         public string WeChatResultJson()
     91         {
     92             if (this.Session["oauth_name"] == null || this.Session["oauth_access_token"] == null ||
     93                 this.Session["oauth_openid"] == null)
     94             {
     95                 return "{\"ret\":\"1\", \"msg\":\"出错啦,Access Token已过期或不存在!\"}";
     96             }
     97             var oauthName = this.Session["oauth_name"].ToString();
     98             var oauthAccessToken = this.Session["oauth_access_token"].ToString();
     99             var oauthOpenid = this.Session["oauth_openid"].ToString();
    100             var oauthRefreshToken = this.Session["oauth_refresh_token"].ToString();
    101 
    102             if (!WeixinHelper.check_access_token(oauthAccessToken)) //调用access_token前需判断是否过期
    103             {
    104                 Dictionary<string, object> dic1 = WeixinHelper.get_refresh_token(oauthRefreshToken); //如果已过期则重新换取新的access_token
    105                 if (dic1 == null || !dic1.ContainsKey("access_token"))
    106                 {
    107                     return "{\"openid\":\"0\", \"msg\":\"出错啦,无法获取access_token!\"}";
    108                 }
    109                 oauthAccessToken = dic1["access_token"].ToString();
    110             }
    111 
    112             Dictionary<string, object> dic = WeixinHelper.get_user_info(oauthAccessToken, oauthOpenid);
    113             if (dic == null)
    114             {
    115                 return "{\"openid\":\"0\", \"msg\":\"出错啦,无法获取授权用户信息!\"}";
    116             }
    117             try
    118             {
    119                 StringBuilder str = new StringBuilder();
    120                 str.Append("{");
    121                 str.Append("\"openid\": \"" + dic["openid"] + "\", ");
    122                 str.Append("\"nickname\": \"" + dic["nickname"] + "\", ");
    123                 str.Append("\"sex\": \"" + dic["sex"] + "\", ");
    124                 str.Append("\"province\": \"" + dic["province"] + "\", ");
    125                 str.Append("\"city\": \"" + dic["city"] + "\", ");
    126                 str.Append("\"country\": \"" + dic["country"] + "\", ");
    127                 str.Append("\"headimgurl\": \"" + dic["headimgurl"] + "\", ");
    128                 str.Append("\"privilege\": \"" + dic["privilege"] + "\", ");
    129                 str.Append("\"unionid\": \"" + dic["unionid"] + "\"");
    130                 str.Append("\"oauth_name\": \"" + oauthName + "\"");
    131                 str.Append("\"oauth_access_token\": \"" + oauthAccessToken + "\"");
    132                 str.Append("\"oauth_openid\": \"" + oauthOpenid + "\"");
    133                 str.Append("}");
    134                 return str.ToString();
    135             }
    136             catch
    137             {
    138                 return "{\"ret\":\"0\", \"msg\":\"出错啦,无法获取授权用户信息!\"}";
    139             }
    140         }
    141 
    142         #endregion
    143     }
    144 }

    Models---》HttpMethods

      1 using System;
      2 using System.Collections.Generic;
      3 using System.IO;
      4 using System.Net;
      5 using System.Text;
      6 
      7 namespace WebWeChat.Models
      8 {
      9     ////////////////////////////////////////////////////////////////////////////////////////////////////
     10     /// <summary>   A HTTP methods. </summary>
     11     ///
     12     /// <remarks>   xiaop, 2014/12/16. </remarks>
     13     ////////////////////////////////////////////////////////////////////////////////////////////////////
     14     public static class HttpMethods
     15     {
     16         #region POST
     17 
     18         /// <summary>
     19         /// HTTP POST方式请求数据
     20         /// </summary>
     21         /// <param name="url">URL.</param>
     22         /// <param name="param">POST的数据</param>
     23         /// <returns></returns>
     24         public static string HttpPost(string url, string param)
     25         {
     26             HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
     27             request.Method = "POST";
     28             request.ContentType = "application/x-www-form-urlencoded";
     29             request.Accept = "*/*";
     30             request.Timeout = 15000;
     31             request.AllowAutoRedirect = false;
     32 
     33             string responseStr;
     34 
     35             var requestStream = new StreamWriter(request.GetRequestStream());
     36             requestStream.Write(param);
     37             requestStream.Close();
     38 
     39             var response = request.GetResponse();
     40             {
     41                 // ReSharper disable once AssignNullToNotNullAttribute
     42                 StreamReader reader = new StreamReader(stream: response.GetResponseStream(), encoding: Encoding.UTF8);
     43                 responseStr = reader.ReadToEnd();
     44                 reader.Close();
     45             }
     46 
     47             return responseStr;
     48         }
     49 
     50         #endregion
     51 
     52         #region Get
     53 
     54         /// <summary>
     55         /// HTTP GET方式请求数据.
     56         /// </summary>
     57         /// <param name="url">URL.</param>
     58         /// <returns></returns>
     59         public static string HttpGet(string url)
     60         {
     61             HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
     62             request.Method = "GET";
     63 
     64             //request.ContentType = "application/x-www-form-urlencoded";
     65             request.Accept = "*/*";
     66             request.Timeout = 15000;
     67             request.AllowAutoRedirect = false;
     68 
     69             string responseStr;
     70 
     71             var response = request.GetResponse();
     72 
     73             {
     74                 // ReSharper disable once AssignNullToNotNullAttribute
     75                 StreamReader reader = new StreamReader(stream: response.GetResponseStream(), encoding: Encoding.UTF8);
     76                 responseStr = reader.ReadToEnd();
     77                 reader.Close();
     78             }
     79 
     80             return responseStr;
     81         }
     82 
     83         #endregion
     84 
     85         #region Post With Pic
     86 
     87         public static string HttpPost(string url, IDictionary<object, object> param, string filePath)
     88         {
     89             string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
     90             byte[] boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
     91 
     92             HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
     93             wr.ContentType = "multipart/form-data; boundary=" + boundary;
     94             wr.Method = "POST";
     95             wr.KeepAlive = true;
     96             wr.Credentials = CredentialCache.DefaultCredentials;
     97 
     98             Stream rs = wr.GetRequestStream();
     99             string responseStr = null;
    100 
    101             string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
    102             foreach (string key in param.Keys)
    103             {
    104                 rs.Write(boundarybytes, 0, boundarybytes.Length);
    105                 string formitem = string.Format(formdataTemplate, key, param[key]);
    106                 byte[] formitembytes = Encoding.UTF8.GetBytes(formitem);
    107                 rs.Write(formitembytes, 0, formitembytes.Length);
    108             }
    109             rs.Write(boundarybytes, 0, boundarybytes.Length);
    110 
    111             string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
    112             string header = string.Format(headerTemplate, "pic", filePath, "text/plain");
    113             byte[] headerbytes = Encoding.UTF8.GetBytes(header);
    114             rs.Write(headerbytes, 0, headerbytes.Length);
    115 
    116             FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
    117             byte[] buffer = new byte[4096];
    118             int bytesRead;
    119             while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
    120             {
    121                 rs.Write(buffer, 0, bytesRead);
    122             }
    123             fileStream.Close();
    124 
    125             byte[] trailer = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
    126             rs.Write(trailer, 0, trailer.Length);
    127             rs.Close();
    128 
    129             WebResponse wresp = null;
    130             try
    131             {
    132                 wresp = wr.GetResponse();
    133                 Stream stream2 = wresp.GetResponseStream();
    134                 if (stream2 != null)
    135                 {
    136                     StreamReader reader2 = new StreamReader(stream2);
    137                     responseStr = reader2.ReadToEnd();
    138                 }
    139 
    140                 //logger.Debug(string.Format("File uploaded, server response is: {0}", responseStr));
    141             }
    142             catch (Exception)
    143             {
    144                 //logger.Error("Error uploading file", ex);
    145                 if (wresp != null)
    146                 {
    147                     wresp.Close();
    148                 }
    149             }
    150             return responseStr;
    151         }
    152 
    153         #endregion
    154 
    155         #region Post With Pic
    156 
    157         /// <summary>
    158         /// HTTP POST方式请求数据(带图片)
    159         /// </summary>
    160         /// <param name="url">URL</param>        
    161         /// <param name="param">POST的数据</param>
    162         /// <param name="fileByte">图片</param>
    163         /// <returns></returns>
    164         public static string HttpPost(string url, IDictionary<object, object> param, byte[] fileByte)
    165         {
    166             string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
    167             byte[] boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
    168 
    169             HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
    170             wr.ContentType = "multipart/form-data; boundary=" + boundary;
    171             wr.Method = "POST";
    172             wr.KeepAlive = true;
    173             wr.Credentials = CredentialCache.DefaultCredentials;
    174 
    175             Stream rs = wr.GetRequestStream();
    176             string responseStr = null;
    177 
    178             string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
    179             foreach (string key in param.Keys)
    180             {
    181                 rs.Write(boundarybytes, 0, boundarybytes.Length);
    182                 string formitem = string.Format(formdataTemplate, key, param[key]);
    183                 byte[] formitembytes = Encoding.UTF8.GetBytes(formitem);
    184                 rs.Write(formitembytes, 0, formitembytes.Length);
    185             }
    186             rs.Write(boundarybytes, 0, boundarybytes.Length);
    187 
    188             string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
    189             string header = string.Format(headerTemplate, "pic", fileByte, "text/plain"); //image/jpeg
    190             byte[] headerbytes = Encoding.UTF8.GetBytes(header);
    191             rs.Write(headerbytes, 0, headerbytes.Length);
    192 
    193             rs.Write(fileByte, 0, fileByte.Length);
    194 
    195             byte[] trailer = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
    196             rs.Write(trailer, 0, trailer.Length);
    197             rs.Close();
    198 
    199             WebResponse wresp = null;
    200             try
    201             {
    202                 wresp = wr.GetResponse();
    203                 Stream stream2 = wresp.GetResponseStream();
    204                 if (stream2 != null)
    205                 {
    206                     StreamReader reader2 = new StreamReader(stream2);
    207                     responseStr = reader2.ReadToEnd();
    208                 }
    209 
    210                 // logger.Error(string.Format("File uploaded, server response is: {0}", responseStr));
    211             }
    212             catch (Exception)
    213             {
    214                 //logger.Error("Error uploading file", ex);
    215                 if (wresp != null)
    216                 {
    217                     wresp.Close();
    218                 }
    219             }
    220             return responseStr;
    221         }
    222 
    223         #endregion
    224     }
    225 }

    Models---》WeixinHelper

      1 using System.Collections.Generic;
      2 using System.Configuration;
      3 
      4 using Newtonsoft.Json;
      5 
      6 namespace WebWeChat.Models
      7 {
      8     public static class WeixinHelper
      9     {
     10         #region 获得配置信息
     11 
     12         private static readonly string OauthAppId = ConfigurationManager.AppSettings["oauth_app_id"];
     13         private static readonly string OauthAppKey = ConfigurationManager.AppSettings["oauth_app_key"];
     14 
     15         #endregion
     16 
     17         /// <summary>
     18         /// 根据AppID和AppSecret获得access token(默认过期时间为2小时)
     19         /// </summary>
     20         /// <returns>Dictionary</returns>
     21         public static Dictionary<string, object> get_access_token()
     22         {
     23             string sendUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" +
     24                              WeixinHelper.OauthAppId + "&secret=" + WeixinHelper.OauthAppKey + "";
     25 
     26             //发送并接受返回值
     27             string result = HttpMethods.HttpGet(sendUrl);
     28             if (result.Contains("errmsg"))
     29             {
     30                 return null;
     31             }
     32             try
     33             {
     34                 Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(result);
     35                 return dic;
     36             }
     37             catch
     38             {
     39                 return null;
     40             }
     41         }
     42 
     43         /// <summary>
     44         /// 取得临时的Access Token(默认过期时间为2小时)
     45         /// </summary>
     46         /// <param name="code">临时Authorization Code</param>
     47         /// <param name="state">防止CSRF攻击,成功授权后回调时会原样带回</param>
     48         /// <returns>Dictionary</returns>
     49         public static Dictionary<string, object> get_access_token(string code, string state)
     50         {
     51             string sendUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" +
     52                              WeixinHelper.OauthAppId + "&secret=" + WeixinHelper.OauthAppKey + "&code=" + code +
     53                              "&grant_type=authorization_code";
     54 
     55             //发送并接受返回值
     56             string result = HttpMethods.HttpGet(sendUrl);
     57             if (result.Contains("errmsg"))
     58             {
     59                 return null;
     60             }
     61             try
     62             {
     63                 Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(result);
     64                 return dic;
     65             }
     66             catch
     67             {
     68                 return null;
     69             }
     70         }
     71 
     72         /// <summary>
     73         /// 根据access_token判断access_token是否过期
     74         /// </summary>
     75         /// <param name="accessToken"></param>
     76         /// <returns>true表示未失效</returns>
     77         public static bool check_access_token(string accessToken)
     78         {
     79             string sendUrl = "https://api.weixin.qq.com/sns/auth?access_token=" + accessToken + "&openid=" + WeixinHelper.OauthAppId;
     80 
     81             //发送并接受返回值
     82             string result = HttpMethods.HttpGet(sendUrl);
     83             try
     84             {
     85                 Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(result);
     86                 if (dic.ContainsKey("errmsg"))
     87                 {
     88                     return dic["errmsg"].ToString() == "ok";
     89                 }
     90                 return false;
     91             }
     92             catch
     93             {
     94                 return false;
     95             }
     96         }
     97 
     98         /// <summary>
     99         /// 若fresh_token已过期则根据refresh_token取得新的refresh_token
    100         /// </summary>
    101         /// <param name="refreshToken">refresh_token</param>
    102         /// <returns>Dictionary</returns>
    103         public static Dictionary<string, object> get_refresh_token(string refreshToken)
    104         {
    105             string sendUrl =
    106                 "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" +
    107                 WeixinHelper.OauthAppId + "&grant_type=refresh_token&refresh_token=" + refreshToken;
    108 
    109             //发送并接受返回值
    110             string result = HttpMethods.HttpGet(sendUrl);
    111             if (result.Contains("errmsg"))
    112             {
    113                 return null;
    114             }
    115             try
    116             {
    117                 return JsonConvert.DeserializeObject<Dictionary<string, object>>(result);
    118             }
    119             catch
    120             {
    121                 return null;
    122             }
    123         }
    124 
    125         /// <summary>
    126         /// 获取登录用户自己的基本资料
    127         /// </summary>
    128         /// <param name="accessToken">临时的Access Token</param>
    129         /// <param name="openId">用户openid</param>
    130         /// <returns>Dictionary</returns>
    131         public static Dictionary<string, object> get_user_info(string accessToken, string openId)
    132         {
    133             //发送并接受返回值   
    134             string sendUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId;
    135 
    136             //发送并接受返回值
    137             string result = HttpMethods.HttpGet(sendUrl);
    138             if (result.Contains("errmsg"))
    139             {
    140                 return null;
    141             }
    142 
    143             //反序列化JSON
    144             Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(result);
    145             return dic;
    146         }
    147     }
    148 }

     

    我的签名:坚持赚钱,顺便理想

    转载于:https://www.cnblogs.com/xxpeng/p/4832051.html

    展开全文
  • 以前写过一篇公众号的授权登录https://blog.csdn.net/dsn727455218/article/details/65630151,今天给大家分享一下企业微信授权登录。 大致都差不多流程 注意事项: 1.网页授权及JS-SDK需要在企业微信上配置可信...
  • http://www.cnblogs.com/0201zcr/p/5131602.html 1、OAuth2.0简介  OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而...
  • Java实现微信授权登录

    2017-09-29 22:38:26
    这篇文章出了介绍微信授权登录之外,还简单介绍QQ登录的相关流程。 首先要开发微信授权登录操作,必须有一个微信公众平台注册一个账号,具体网址在微信公众平台。在这里仅对于个人开发者而言,订阅号应该是个人...
  • 第三方授权登录能够直接使用已有的QQ号、微信等登录。减少了注册环节,减少了因为注册而流失的用户。可以直接获取用户昵称、头像等信息,省去再次填写昵称、上传头像的麻烦。下面说说第三方授权登录正确的开发方式。...
  • 微信开发——网页授权 项目需求:通过用户在微信中打开网页获取用户的openid来实现绑定消费卡的功能。 项目开发:首先我们需要配置微信的运行环境,这里请参考我的第一篇关于微信开发的日志。 第一步我们得去平台...
  • 微信公众号开发授权登录 1、微信公众号技术开发文档阅读 微信公众号的开发首先对开发文档的阅读,技术版本可能有变化,博客里面的内容一段时间过后,可能就出现有些小问题。 微信公众号技术开发文档:...
  • 微信网页授权登录
  • 微信公众号授权登录

    2019-03-11 10:06:00
    课程目标 学会用微信授权登录,绑定自己的业务系统 适用人群 ...让同学们快速撑握OAuth2.0,实现微信授权登录开发工具采用SpringBoot2.x,通过HttpClient调用微信授权接口 ,通过本次5节视频轻松学习 
  • 微信授权登录基本流程微信oauth2.0授权登录流程说明让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(access_token),...
  • 引进微信PC登录微信公众号登录功能 1.微信PC登录 需要前往微信开放平台注册一个账号,并创建一个网站应用,成功后这个拿到这个网站应用的appid与secrect String APPID=(String) weixinLogin.get("appid"...
  • 所有微信开发的相关内容,都需要参考官方文档。 [微信公众平台|开发文档] http://mp.weixin.qq.com/wiki/home/。 一、通过网页授权,可以获取用户微信的基本信息。 二、总共有5个步骤: 1 :用户同意授权,...
  • 微信登录最重要的两个返回信息,一个是UnionId,一个是OpenId。两者之间有着必然的联系。 首先,先来理一下微信开放平台的架构。开发微信登录,必须有一个开放平台账号(公众号授权可以不用,后面会讲到)。开放...
  • 微信公众号网页授权登录: 前端时间做了一个微信公众号的项目,就是微信公众号的菜单点击我的个人中心,就向用户授权登录 获取用户的信息,进行业务逻辑的操作,微信公众号官方文档,这是我写的文章,里面有很多...
  • 微信公众平台开发微信网页授权开发是子恒老师《微信公众平台开发》视频教程的第10部。详细讲解了用php进行微信网页授的开发。内容包含构造授权uri,实现网页授权,优化微信网页授,获取用户信息等等。
  • IOS实现微信授权登录

    2017-03-20 11:09:20
    IOS实现微信授权登录 微信是一个在开发中经常会使用到的平台,比如微信登录、授权、支付、分享。今天我们来看看如何在自己的应用里面集成微信授权。 1、微信授权的定义 微信OAuth2.0授权登录微信用户...
  • (一)java微信授权登录

    2018-05-07 09:34:55
    微信公众平台开发文档接下来,我们要使用微信来进行授权登录微信授权的话,获取用户信息有两种:1.静默获取用户信息、2.弹出授权界面,用户确认之后获取用户信息(这种方法能够获取到更多信息)。开发准备,登录微信...
1 2 3 4 5 ... 20
收藏数 41,620
精华内容 16,648
关键字:

微信开发 授权登录