获取小程序二维码,实现PC端微信扫码登录

news/2024/7/20 3:22:23 标签: 小程序, 微信

思路:

1.前端生成随机字符串(有数字或字母组成,最好不要有特殊字符,不是所有的特殊字符都支持)

2.PC端调用后端接口,获取小程序二维码,并开始轮询访问接口获取小程序授权的信息

3.微信扫码登录,获取包含在二维码中的参数key(上面的随机字符串),将key和用户信息作为请求参数,调用授权接口

public WxTokenResponse getToken() {
        if (wxTokenResponse != null &&
                !StringUtils.isEmpty(wxTokenResponse.getAccessToken())) {
            Date curDate = new Date();
            int span = (int) ((curDate.getTime() - updateTime.getTime()) / 1000);
            if (span < wxTokenResponse.getExpiresIn() - 15) {
                return wxTokenResponse;
            }
        }

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("grant_type", "client_credential");
        params.put("appid", wxPayConfig.getAppid());
        params.put("secret", wxPayConfig.getSecret());
        wxTokenResponse = null;
        String jsonStr = apiService.invokeGet(weChartConfig.getUrl(), "cgi-bin/token", null, params);
        if (!StringUtils.isEmpty(jsonStr)) {
            wxTokenResponse = JSONObject.parseObject(jsonStr, new TypeReference<WxTokenResponse>() {
            });
            updateTime = new Date();
            return wxTokenResponse;
        }
        return null;
    }


/**
     * 
     * @param request
     * @param resp
     * @param key
     * @param path 不传的话,默认跳转小程序的主页,只有在跳转的页面才能获得自定义的参数
     */
    public void getAppletCodeStream(HttpServletRequest request, HttpServletResponse resp, String key, String path) {
        wxTokenResponse = getToken();
       
        String accessToken = wxTokenResponse.getAccessToken();
       
        //获取小程序码
        String codeUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN"
                .replace("ACCESS_TOKEN", accessToken);
        Map<String, Object> map = new HashMap<>();
        map.put("scene", key);
        if (path != null && !path.equals("")) {
            map.put("page", key);
        }
        try {
            CloseableHttpResponse response = null;
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                HttpPost httpPost = new HttpPost(codeUrl);
                httpPost.addHeader("Content-type", "application/json; charset=utf-8");
                httpPost.setEntity(new StringEntity(objectMapper.writeValueAsString(map),
                        ContentType.create("text/json", "UTF-8")));
                response = HttpClients.createDefault().execute(httpPost);
                if (response.getStatusLine().getStatusCode() == 200) {
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        //这里不一定需要转为byte,根据你的项目自己选择
                        BufferedImage read = ImageIO.read(entity.getContent());
                        ImageIO.write(read, "JPEG", resp.getOutputStream());
                        
                    }
                }
            } finally {
                if (response != null) {
                    response.close();
                }
            }
        } catch (Exception e) {
            LoggerUtil.logError("调用HttpUtils.sendPostRequest Exception, url=" + codeUrl + ",map=" + map, e);
        }

    }

    private static final Map<String, UserToken> AUTH_KEY = new ConcurrentHashMap();

    @ApiOperation(value = "获取小程序二维码图片流", notes = "", produces = "application/json")
    @RequestMapping(value = "/getAppletCodeStream", method = RequestMethod.POST)
    public void getAppletCodeStream(HttpServletRequest request, HttpServletResponse response,
                                    @ApiParam(name = "key", value = "唯一的识别码", required = true) @RequestParam String key,
                                    @ApiParam(name = "path", value = "路径", required = true) @RequestParam String path) throws Exception {

        //设置相应类型,告诉浏览器输出的内容为图片
        response.setContentType("image/jpeg");
        //设置响应头信息,告诉浏览器不要缓存此内容
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expire", 0);
        response.setHeader("key", request.getSession().getId());
        wxCommonService.getAppletCodeStream(request, response, key, path);

    }

    @ApiOperation(value = "9-小程序授权登录", notes = "", produces = "application/json")
    @RequestMapping(value = "/appletPutAuth", method = RequestMethod.POST)
    public Response<String> appletPutAuth(
            @ApiParam(name = "request", value = "请求参数", required = true) @RequestBody Request<TokenQuery> request) throws Exception {
        TokenQuery entity = request.getEntity();
        ParamUtil.INSTANCE.checkObjectNull(entity, "entity")
                .checkStrNull(entity.getKey(), "key")
                .checkObjectNull(entity.getToken(), "token");

        UserToken token = entity.getToken();
        Long expire = System.currentTimeMillis() + 60 * 1000;
        token.setExpire(expire);
        AUTH_KEY.put(entity.getKey(), entity.getToken());

        return ResponseUtil.outSuccess();
    }

    @ApiOperation(value = "10-获取小程序授权", notes = "", produces = "application/json")
    @RequestMapping(value = "/getAppletAuth")
    public Response<UserToken> getAppletAuth(
            @ApiParam(name = "key", value = "唯一的识别码", required = true) @RequestParam String key) throws Exception {
        ParamUtil.INSTANCE.checkStrNull(key, "key");
        if (!AUTH_KEY.containsKey(key)) {
            throw new CustomerException("key已经过期");
        }
        UserToken userToken = AUTH_KEY.get(key);
        if (userToken.getExpire() < System.currentTimeMillis()) {
            throw new CustomerException("key已经过期");
        }

        AUTH_KEY.remove(key);
        return ResponseUtil.out(userToken);
    }

    @Scheduled(cron = "0 0/1 * * * ?")
    private void clearnAuthKey() {

        for (String key : AUTH_KEY.keySet()) {
            UserToken userToken = AUTH_KEY.get(key);
            if (userToken.getExpire() < System.currentTimeMillis()) {
                AUTH_KEY.remove(key);
            }

        }
    }


http://www.niftyadmin.cn/n/4965424.html

相关文章

学习Python文件备份和恢复技术,让您的数据永不丢失!

在进行Python的文件IO操作时&#xff0c;文件的安全性和保护是非常重要的。本篇文章主要介绍Python中文件权限管理以及文件备份和恢复的相关知识。 文件权限管理 1、文件权限的概念和作用 在Linux和Windows系统中&#xff0c;每个文件都有一定的权限&#xff0c;这些权限决定…

基于jenkins构建生成CICD环境

目录 一、安装配置jenkins 1、环境配置 2、软件要求 3、jdk安装&#xff08;我是最小化安装&#xff0c;UI自带java要先删除rm -rf /usr/local/java 4、安装jenkins-2.419-1.1 二、Jenkins配置 1、修改jenkins初始密码 2、安装 Jenkins 必要插件 3、安装 Publish Over SS…

时间字符串对比

目录 需求场景 解决方案 Date对象方法 Moment.js库 Day.js库 简便方法 需求场景 在开发中&#xff0c;经常需要对比两个时间的先后顺序&#xff0c;或者计算两个时间之间的时间差。 例如&#xff1a; 在电商网站中&#xff0c;需要显示商品的上架时间和下架时间&#x…

使用钉钉的扫码会出现多个回调(DTFrameLogin)

官方&#xff1a;地址 标题 出现的问题解决后效果正常使用(按照官网的流程进行使用)自己的理解(路人可忽略该内容&#xff01;) 出现的问题 1692861955468 解决后效果 1692861665687 正常使用(按照官网的流程进行使用) fn.js 该文件就是钉钉官网的js文件&#xff0c;我下载到了…

无涯教程-PHP - intval() 函数

PHP 7引入了一个新函数 intdiv()&#xff0c;该函数对其操作数执行整数除法并将该除法返回为int。 <?php$valueintdiv(10,3);var_dump($value);print(" ");print($value); ?> 它产生以下浏览器输出- int(3) 3 PHP - intval() 函数 - 无涯教程网无涯教程网…

【Python】Python爬虫:网络数据的提取利器

随着互联网的快速发展&#xff0c;网络数据已经成为了一项重要的资源。如何从海量的网络数据中提取出我们需要的信息&#xff0c;就成为了各个行业都需要解决的问题。而Python爬虫&#xff0c;就是解决这个问题的利器。 首先&#xff0c;让我们了解一下什么是Python爬虫。Pyth…

Flink安装与使用

1.安装准备工作 下载flink Apache Flink: 下载 解压 [dodahost166 bigdata]$ tar -zxvf flink-1.12.0-bin-scala_2.11.tgz 2.Flinnk的standalone模式安装 2.1修改配置文件并启动 修改&#xff0c;好像使用默认的就可以了 [dodahost166 conf]$ more flink-conf.yaml 启动 …

代码评审(Code Review)规范

一、目的 Code Review是一种用来确认方案设计和代码实现的质量保证机制&#xff0c;通过这个机制我们 可以对代码、测试过程和注释进行检查。 Code Review主要用来在软件工程过程中改进代码质量&#xff0c;通过Code Review可以达到 如下目的&#xff1a; 1) 在项目早期就能够…