java调用微信小程序服务器API获取小程序码

一、实现思路

1.登录微信https://mp.weixin.qq.com获取小程序AppID和AppSecret;
2.根据小程序AppID和AppSecret获取accesstoken
3.调用小程序码API接口:

接口地址:https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN

并添加post请求参数

4.请求成功,会直接返回图片二进制内容
5.对返回的数据进行处理,把返回的图片 Buffer转换成图片并存入服务器,然后返回服务器图片地址信息

二、java 获取小程序码工具类代码实现

1.创建Spring boot项目,添加httpclient、web依赖

 <!--HttpClient:只能以编程的方式通过其API用于传输和接受HTTP消息-->
<dependency>
     <groupId>org.apache.httpcomponents</groupId>
     <artifactId>httpclient</artifactId>
 </dependency>
 <!--alibaba json工具类-->
 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.62</version>
 </dependency>
 <!--web-->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
 </dependency>

2.配置静态资源访问

2.1 在application.properties文件中配置静态资源路径

#设置项目ContextPath  项目访问前缀
server.context-path=/
#设置Tomcat编码
server.tomcat.uri-encoding=UTF-8
#设置视图解析器路径
spring.mvc.view.prefix=/WEB-INF/views/
#设置视图解析器后缀
spring.mvc.view.suffix=.jsp


#静态资源路径
web.upload-path=D:/mimi/
spring.mvc.static-path-pattern=/**
spring.web.resources.static-locations=classpath\:/META-INF/resources/,classpath\:/resources/,classpath\:/static/,classpath\:/public/,file\:${web.upload-path}
2.2 配置静态资源映射路径

创建配置类继承WebMvcConfigurationSupport ,重写addResourceHandlers方法实现静态资源映射路径

package com.example.qrdemo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

/**
 * @author qzz
 */
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurationSupport {


    /**
     * 添加静态资源映射路径,css、js等都放在classpath下的static中
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        /**
         * addResourceHandler 指的是对外暴露的访问路径
         * addResourceLocations 指的是文件配置的目录
         */

        //文件上传路径映射
        registry.addResourceHandler("/mimi/upload/**")
                .addResourceLocations("file:D:/mimi/upload/");

        super.addResourceHandlers(registry);
    }
}


3.代码实现获取小程序二维码

小程序二维码的生成需要几个工具类:

3.1 判断字符串为空、不为空工具类
package com.example.qrdemo.util;

/**
 * @author qzz
 */
public class Tool {


    /**
     * 检测字符串是否为空(null,"","null")
     * @param s
     * @return 为空返回true,否则返回false
     */
    public static boolean isEmpty(String s){
        return s == null || "".equals(s) || "null".equals(s);
    }

    /**
     * 检测字符串是否不为空(null,"","null")
     * @param s
     * @return 不为空返回true,否则返回false
     */
    public static boolean notEmpty(String s){
        return s != null && !"".equals(s) && !"null".equals(s);
    }
}

3.2 HttpRequest 请求封装类:get\post请求
package com.example.qrdemo.util;


import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;

/**
 * 用于发送HTTP请求-----返回值为json
 * @author JH
 * @date 2018年9月21日 16:09:36
 */
public class HttpRequestUtil {
    /**
     * 调用接口查询数据 get
     *
     * @param action
     * @return
     * @throws MalformedURLException
     */
    public JSONObject sendUrlGet(String action) {
        URL url;
        JSONObject json = null;
        try {
            url = new URL(action.toString());
            HttpURLConnection http = (HttpURLConnection) url.openConnection();
            // 设定请求的方法为"POST",默认是GET
            http.setRequestMethod("GET");
            // 设定传送的内容类型是可序列化的java对象
            // (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)
            http.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            // 设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在
            // http正文内,因此需要设为true, 默认情况下是false;
            http.setDoOutput(false);
            // 设置是否从httpUrlConnection读入,默认情况下是true;
            http.setDoInput(true);
            InputStream is = http.getInputStream();
            int size = is.available();
            byte[] buf = new byte[size];
            is.read(buf);
            String resp = new String(buf, "UTF-8");
            json = JSONObject.parseObject(resp);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return json;
        } catch (ProtocolException e) {
            e.printStackTrace();
            return json;
        } catch (IOException e) {
            e.printStackTrace();
            return json;
        }
        return json;
    }

    /**
     * 调用接口查询数据 post
     *
     * @param action
     * @return
     * @throws MalformedURLException
     */
    public JSONObject sendUrlPost(String action, Map inMap) {
        HttpURLConnection conn = null;
        InputStream is = null;
        InputStreamReader reader = null;
        BufferedReader br = null;
        String str = "";
        try {
            URL url = new URL(action);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            // 默认为false的,所以需要设置
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            conn.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            conn.connect();
            // 开始访问
            StringBuilder postData = new StringBuilder();
            OutputStream outStream = conn.getOutputStream();
            DataOutputStream out = new DataOutputStream(outStream);
            JSONObject jso = new JSONObject();
            //把参数转换成json字符串
            String params = jso.toJSONString(inMap);
            //传输参数
            out.writeBytes(params);
            out.close();

            is = conn.getInputStream();
            reader = new InputStreamReader(is, "UTF-8");
            br = new BufferedReader(reader);
            String readLine = "";
            while ((readLine = br.readLine()) != null) {
                str += readLine + "\n";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
                if (conn != null) {
                    conn.disconnect();
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
        return JSONObject.parseObject(str);
    }



    /**
     * 从网络Url中下载文件
     * @param urlStr
     * @param fileName
     * @param savePath
     * @throws IOException
     */
    public static void  downLoadFromUrl(String urlStr,String fileName,String savePath) throws IOException{
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        //设置超时间为3秒
        conn.setConnectTimeout(8*1000);
        //防止屏蔽程序抓取而返回403错误
        conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

        //得到输入流
        InputStream inputStream = conn.getInputStream();
        //获取自己数组
        byte[] getData = readInputStream(inputStream);

        //文件保存位置
        File saveDir = new File(savePath);
        if(!saveDir.exists()){
            saveDir.mkdir();
        }
        File file = new File(saveDir+File.separator+fileName);
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(getData);
        if(fos!=null){
            fos.close();
        }
        if(inputStream!=null){
            inputStream.close();
        }


        System.out.println("info:"+url+" download success");

    }
    /**
     * 从输入流中获取字节数组
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static  byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }
}

3.3 编写生成小程序码的代码实现工具类
package com.example.qrdemo.util;


import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;


/**
 * 微信小程序 工具类
 * @author Administrator
 *
 */
public class WxUtil {

    /**
     * 获取小程序全局唯一后台接口调用凭据(access_token)
     * @return
     */
    public static String getWxAccessToken(){
        //从redis缓存中获取AccessToken,有且未过期,直接返回;否则重新获取
//        String accessToken =RedisManager.get("accessToken");
//        if(Tool.notEmpty(accessToken)){
//            return accessToken;
//        }
        //重新获取accessToken,并存入redis
        String newToken = getAccessToken();
        //存入redis
        //RedisManager.set("accessToken", newToken, 7000);
        return newToken;
    }
    /**
     * 调用微信开放接口 获取小程序全局唯一后台接口调用凭据(access_token)
     * @return
     */
    public static String getAccessToken(){
        String APPID="wx81fb97ab6ezxqc2d";
        String APPSECRET="2699261e75db9498339567828f53123";
        String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+APPID+"&secret="+APPSECRET;
        HttpRequestUtil hru = new HttpRequestUtil();
        JSONObject json = hru.sendUrlGet(accessTokenUrl);
        String access_token = json.getString("access_token");
        if(Tool.isEmpty(access_token)){
            access_token="";
        }

        System.out.println("json:"+json.toString());

        return access_token;
    }




    /**
     * 调用微信开放接口wxacode.getUnlimited获取小程序码
     * 通过该接口生成的小程序码,永久有效,数量暂无限制
     * @param sceneStr 参数
     * @param pageUrl 小程序页面链接---不能携带参数(参数请放在scene字段里)
     * @param accessToken 小程序全局唯一后台接口调用凭据
     * @return true:含敏感信息   false:正常
     */
    public static Map<String,Object> getWXAcode2(String sceneStr,String pageUrl) {
        Map<String, Object>  returnData= new HashMap<String, Object>();
        try {
            //获取token  小程序全局唯一后台接口调用凭据
            String accessToken = getWxAccessToken();
            URL url = new URL("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+accessToken);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            // conn.setConnectTimeout(10000);//连接超时 单位毫秒
            // conn.setReadTimeout(2000);//读取超时 单位毫秒
            // 发送POST请求必须设置如下两行
            httpURLConnection.setDoOutput(true); // 打开写入属性
            httpURLConnection.setDoInput(true); // 打开读取属性
            httpURLConnection.setRequestMethod("POST");// 提交方式
            // 不得不说一下这个提交方式转换!!真的坑。。改了好长时间!!一定要记得加响应头
            httpURLConnection.setRequestProperty("Content-Type", "application/x-javascript; charset=UTF-8");// 设置响应头
            // 获取URLConnection对象对应的输出流
            PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
            // 发送请求参数
            JSONObject paramJson = new JSONObject();
            paramJson.put("scene", sceneStr); // 你要放的内容
            paramJson.put("path", pageUrl);
            paramJson.put("width", 280); //二维码的宽度,单位 px,默认430px,最小 280px,最大 1280px
            paramJson.put("auto_color", false);//自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认 false
            Map<String,Object> line_color = new HashMap<>();
            line_color.put("r", 0);
            line_color.put("g", 0);
            line_color.put("b", 0);
            paramJson.put("line_color", line_color);//auto_color 为 false 时生效,使用 rgb 设置颜色
            paramJson.put("is_hyaline", false);//是否需要透明底色,为 true 时,生成透明底色的小程序

            printWriter.write(paramJson.toString());
            // flush输出流的缓冲
            printWriter.flush();
            BufferedInputStream inputStream = new BufferedInputStream(httpURLConnection.getInputStream());

            //小程序码图片文件夹位置
            //设置文件存储路径,可以存放在你想要指定的路径里面
            String rootPath = "D:/mimi/upload/images/";
            Long res = System.currentTimeMillis();
            String newFileName =res + ".png";
            // 新文件
            File newFile = new File(rootPath +File.separator+ newFileName);
            // 判断目标文件所在目录是否存在
            if( !newFile.getParentFile().exists()) {
                // 如果目标文件所在的目录不存在,则创建父目录
                newFile.getParentFile().mkdirs();
            }

            //-------把图片文件写入磁盘 start ----------------
            FileOutputStream fos = new FileOutputStream(newFile);
            //写入目标文件
            byte[] buffer=new byte[1024*1024];
            int byteRead=0;
            //stream.read(buffer) 每次读到的数据存放在 buffer 数组中
            while((byteRead=inputStream.read(buffer))!=-1){
                //在 buffer 数组中 取出数据 写到 (输出流)磁盘上
                fos.write(buffer, 0, byteRead);
                fos.flush();
            }
            fos.close();
            inputStream.close();
            //-------把图片文件写入磁盘 end ----------------
            // 完整的url(图片映射地址)
            //小程序码保存路径
            String fileUrl = "http://localhost:8080/mimi/upload/images/" + newFileName;
            returnData.put("codeURL", fileUrl);
            returnData.put("state", "200");
            return  returnData;

        }  catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        returnData.put("msg", "生成失败");
        returnData.put("state", "400");
        return  returnData;
    }

    public static void main(String[] args) {

    }
}



3.4 编写一个controller,调用工具类获取小程序码并返回图片地址
package com.example.qrdemo.controller;

import com.example.qrdemo.util.WxUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @author qzz
 */
@RestController
@RequestMapping("/wx")
public class WxController {

    /**
     * 获取小程序码
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getWxQRCode", method = { RequestMethod.POST })
    public Map<String, Object> getWxQRCode(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //参数
        String sceneStr="m_id=1";
        //跳转页面
        String pageUrl="pages/index/index";
        //调用微信开放接口wxacode.getUnlimited获取小程序码
        return WxUtil.getWXAcode2(sceneStr, pageUrl);
    }
}

三、测试

启动项目,Post请求访问地址http:localhost:8080/wx/getWxQRCode,返回结果如下:

在这里插入图片描述
浏览器访问返回的图片地址:
在这里插入图片描述

说明,小程序码生成获取成功!

三、代码下载

可点击此处下载源码

更多推荐