有些场景需要生成带参数的小程序二维码,比如商城为每个商品生成小程序二维码,通过微信扫码直接跳转到该商品所在的展示页面。微信为开发者们提供了相应接口。
![]()
  请求参数以及返回参数等请参考官方文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html
一、pom 依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>
二、后端接口示例
package club.jiajiajia.nwsp.controller;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class TestController {
    static final String grant_type="grant_type";
    static final String appid="appid";
    static final String secret="secret";
    /**
     * 获取 acessToken
     * @return
     */
    private static String getAcessToken(){
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type="+grant_type+"&appid="+appid+"&secret="+secret;
        RestTemplate restTemplate  = new RestTemplate();
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
        HttpEntity requestEntity = new HttpEntity(null, headers);
        ResponseEntity<String> entity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class, new Object[0]);
        String result = entity.getBody();
        log.info("获取token:"+result);
        Map<String, Object> resultObj = JSONObject.parseObject(result);
        String accessToken = (String) resultObj.get("access_token");
        return accessToken;
    }
    public static void main(String[] args) {
        getminiqrQr("123");
    }
    /**
     * @param sceneStr 微信二维码参数
     */
    private static void getminiqrQr(String sceneStr) {
        String acessToken = getAcessToken();
        RestTemplate restTemplate  = new RestTemplate();
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+acessToken;
            Map<String,Object> param = new HashMap<>();
            // scene:参数
            param.put("scene", sceneStr);
            // page:微信小程序页面
            param.put("page", "pages/productDetails");
            param.put("width", 430);
            param.put("auto_color", false);
            Map<String,Object> line_color = new HashMap<>();
            line_color.put("r", 0);
            line_color.put("g", 0);
            line_color.put("b", 0);
            param.put("line_color", line_color);
            MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
            HttpEntity requestEntity = new HttpEntity(param, headers);
            // 请求数据
            ResponseEntity<byte[]> entity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
            byte[] result = entity.getBody();
            // 如果生成失败,可以打印返回的错误信息
            // System.out.println(new String(result,"utf-8"));
            inputStream = new ByteArrayInputStream(result);
            // 二维码存放路径
            File file = new File("d:/data/1.png");
            if (!file.exists()){
                file.createNewFile();
            }
            outputStream = new FileOutputStream(file);
            int len = 0;
            byte[] buf = new byte[1024];
            while ((len = inputStream.read(buf, 0, 1024)) != -1) {
                outputStream.write(buf, 0, len);
            }
            outputStream.flush();
        } catch (Exception e) {
            log.error("调用小程序生成微信永久小程序码URL接口异常",e);
        } finally {
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
在springboot项目中测试,用到了RestTemplate等类。
  通过该接口生成的小程序码,永久有效,数量暂无限制。用户扫描该码进入小程序后,开发者需在对应页面获取的码中 scene 字段的值,再做处理逻辑。使用如下代码可以获取到二维码中的 scene 字段的值。调试阶段可以使用开发工具的条件编译自定义参数 scene=xxxx 进行模拟,开发工具模拟时的 scene 的参数值需要进行 urlencode。同时需要注意,此接口的page参数中不能带任何参数,参数都在scene 参数中处理。
![]()
![]()
三、前端页面
Page({
  onLoad: function(options) {
    // options 中的 scene 需要使用 decodeURIComponent 才能获取到生成二维码时传入的 scene
    var scene = decodeURIComponent(options.scene)
  }
})