uniapp微信小程序 生成小程序码scene参数踩坑全指南@杨章隐

微信生成二维码官方文档地址:获取小程序码 | 微信开放文档 (qq.com)

这里采用的是获取不限制的小程序码

注意事项

  • 如果调用成功,会直接返回图片二进制内容,如果请求失败,会返回 JSON 格式的数据。

  • POST 参数需要转成 JSON 字符串,不支持 form 表单提交。

  • 调用分钟频率受限(5000次/分钟),如需大量小程序码,建议预生成

获取 scene 值
  • scene 字段的值会作为 query 参数传递给小程序/小游戏。用户扫描该码进入小程序/小游戏后,开发者可以获取到二维码中的 scene 值,再做处理逻辑。

  • 调试阶段可以使用开发工具的条件编译自定义参数 scene=xxxx 进行模拟,开发工具模拟时的 scene 的参数值需要进行 encodeURIComponent

Page({
  onLoad (query) {
    // scene 需要使用 decodeURIComponent 才能获取到生成二维码时传入的 scene
    const scene = decodeURIComponent(query.scene)
  }
})
POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN //服务端调用

Java服务端代码实例(可以直接复制使用)

//这里返回base64 前端可以通过 <image src = "">直接展示
public byte[] remoteWxApiCreateQrcode(MiniQrCodeParamVo paramVo) throws Exception {
        String accessToken = "";//这里去获取accessToken
        RestTemplate rest = new RestTemplate();
        String url = "";
        Map<String, Object> param = new HashMap<String, Object>();
        url = WxMiniApiServiceConstants.GET_WXA_CODE_UNLIMIT_URL.replace("ACCESS_TOKEN", accessToken);
        // 输入参数 最大32字符
        param.put("scene", paramVo.getScene());
        // 路径 如果没有默认跳转到首页面微信小程序发布后才可以使用不能添加参数
        param.put("page", paramVo.getPage());
        // 二维码尺寸
        param.put("width", paramVo.getWidth());
        param.put("is_hyaline", paramVo.isHyaline()); // 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 参数仅对小程序码生效
        param.put("auto_color", paramVo.isAutoColor()); // 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 参数仅对小程序码生效
        // 颜色 auto_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"}
        param.put("line_color", paramVo.getLineColor());
        log.info("调用生成微信URL接口传参:" + param);
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
        headers.put(HttpHeaders.CONTENT_TYPE, Collections.singletonList("application/json"));
        org.springframework.http.HttpEntity<Object> requestEntity = new org.springframework.http.HttpEntity<Object>(
                param, headers);
        ResponseEntity<byte[]> response = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class);

        // 返回的不是图片,则说明接口报错了
        if (!"image".equals(Objects.requireNonNull(response.getHeaders().getContentType()).getType())) {
            String str = new String(Objects.requireNonNull(response.getBody()), StandardCharsets.UTF_8);
            log.error("调用小程序生成微信永久小程序码报错,接口响应内容:{}", str);
            JSONObject resultParams = JSON.parseObject(str);
            String errorCode = resultParams.getString("errcode");
            if (StringUtils.isNotBlank(errorCode)) {
                log.info("errorCode={}" + errorCode);
                if (ObjectUtil.equal("42001", errorCode) || ObjectUtil.equal("40001", errorCode) || ObjectUtil.equal("40014", errorCode)) {
                    // 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token
                    Lock lock = this.wxService.getWxMpConfigStorage().getAccessTokenLock();
                    lock.lock();
                    try {
                        if (StringUtils.equals(this.wxService.getWxMpConfigStorage().getAccessToken(), accessToken)) {
                            this.wxService.getWxMpConfigStorage().expireAccessToken();
                        }
                    } catch (Exception ex) {
                        this.wxService.getWxMpConfigStorage().expireAccessToken();
                    } finally {
                        lock.unlock();
                    }
                    if (this.wxService.getWxMpConfigStorage().autoRefreshToken()) {
                        return this.execute(paramVo);
                    }
                } else if (ObjectUtil.equal("-1", errorCode)) {
                    log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", url, JSON.toJSONString(param), str);
                    throw new Exception(errorCode);
                } else {
                    log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", url, JSON.toJSONString(param), str);
                    throw new Exception(str);
                }
            }
        }
        return response.getBody();
    }
MiniQrCodeParamVo

import java.util.HashMap;
import java.util.Map;

public class MiniQrCodeParamVo {

    private String flag;   //默认为伊店通  2伊美通
    private String scene;   // 输入参数 最大32字符
    private String page;    // 路径 如果没有默认跳转到首页面微信小程序发布后才可以使用不能添加参数
    private String width = "430"; // 二维码尺寸
    private String path;
    private boolean isHyaline = true; // 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 参数仅对小程序码生效
    private boolean autoColor = false;  // 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 参数仅对小程序码生效
    private Map<String, Object> lineColor;  // 颜色 auto_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"}

    public String getFlag() {
        return flag;
    }

    public void setFlag(String flag) {
        this.flag = flag;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getScene() {
        return scene;
    }

    public void setScene(String scene) {
        this.scene = scene;
    }

    public String getPage() {
        return page;
    }

    public void setPage(String page) {
        this.page = page;
    }

    public String getWidth() {
        return width;
    }

    public void setWidth(String width) {
        this.width = width;
    }

    public boolean isHyaline() {
        return isHyaline;
    }

    public void setHyaline(boolean isHyaline) {
        this.isHyaline = isHyaline;
    }

    public boolean isAutoColor() {
        return autoColor;
    }

    public void setAutoColor(boolean autoColor) {
        this.autoColor = autoColor;
    }

    public Map<String, Object> getLineColor() {
        if (null == lineColor) {
            lineColor = new HashMap<String, Object>();
            lineColor.put("r", 0);
            lineColor.put("g", 0);
            lineColor.put("b", 0);
        }
        return lineColor;
    }

    public void setLineColor(Map<String, Object> lineColor) {
        this.lineColor = lineColor;
    }

}
  1. 坑1:参数长度

异常信息:

这是因为scene长度仅仅有32发挥的空间,所以最好的话参数用分割

例如:orderID=123456789&userId=123456789简化为123456789-123456789

为什么要用横杠?参考第二个坑

  1. 坑2:转码异常

首先onload解析参数的时候需要url转码,

但是如果生命周期二次刷新,我们使用&符号会被自动拼接上%25这时候url转码就会失败

解决方法1:用横杠代替URL常用字符

解决方法2:用点心,把所有URL字符全部特殊处理一次参考如下

Java开发笔记之%被转码为%25导致url无法请求 - 腾讯云开发者社区-腾讯云 (tencent.com)

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨章隐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值