获取不限制的小程序码
接口地址:接口应在服务器端调用,详细说明参见服务端API。
调用方式
HTTPS 调用
POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN
请求参数
属性 | 类型 | 必填 | 说明 | |
---|---|---|---|---|
access_token | string | 是 | 接口调用凭证,该参数为 URL 参数,非 Body 参数。使用getAccessToken 或者 authorizer_access_token | |
scene | string | 是 | 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) | |
page | string | 否 | 默认是主页,页面 page,例如 pages/index/index,根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面。scancode_time为系统保留参数,不允许配置 | |
check_path | bool | 否 | 默认是true,检查page 是否存在,为 true 时 page 必须是已经发布的小程序存在的页面(否则报错);为 false 时允许小程序未发布或者 page 不存在, 但page 有数量上限(60000个)请勿滥用。 | |
env_version | string | 否 | 要打开的小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop"。默认是正式版。 | |
width | number | 否 | 默认430,二维码的宽度,单位 px,最小 280px,最大 1280px | |
auto_color | bool | 否 | 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认 false | |
line_color | object | 否 | 默认是{"r":0,"g":0,"b":0} 。auto_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} 十进制表示 | |
is_hyaline | bool | 否 | 默认是false,是否需要透明底色,为 true 时,生成透明底色的小程序 |
返回参数
属性 | 类型 | 说明 |
---|---|---|
buffer | buffer | 图片 Buffer |
errcode | number | 错误码 |
errmsg | string | 错误信息 |
请求数据示例
{
"page": "pages/index/index",
"scene": "a=1",
"check_path": true,
"env_version": "release"
}
成功返回数据示例
图片 Buffer
失败数据示例
{
"errcode": 40097,
"errmsg": "invalid args"
}
错误码
错误码 | 错误描述 | 解决方案 |
---|---|---|
-1 | system error | 系统繁忙,此时请开发者稍候再试 |
40001 | invalid credential access_token isinvalid or not latest | 获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口 |
40129 | invalid scene | 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) |
41030 | invalid page | page路径不正确:根路径前不要填加 /,不能携带参数(参数请放在scene字段里),需要保证在现网版本小程序中存在,与app.json保持一致。 设置check_path=false可不检查page参数。 |
85096 | not allow include scancode_time field | scancode_time为系统保留参数,不允许配置 |
40097 | invalid args | 参数错误 |
40169 | invalid length for scene or thedata is not json string | scene 不合法 |
*****具体代码****
token的获取与自动刷新
@Value("${wx.service.configs.appid}") private String appId; @Value("${wx.service.configs.secret}") private String secret; @Value("${wechat.interface_sendURL}") private String sendURL; public TokenAndExpires getTokenAndExpires() { TokenAndExpires tokenAndExpires = new TokenAndExpires(); Map<String, String> accToken = redisCache.getCacheMap(WxConstants.MESSAGETOKEN_SESSION); String acc_token = accToken.get(WxConstants.ACC_TOKEN); String expiresTime = accToken.get(WxConstants.EXPIRESTIME); Long nowTime = System.currentTimeMillis(); if (acc_token != null && accToken.size() > 0) { Long time = Long.valueOf(expiresTime); if (time < nowTime) { String refreshToken = this.refreshToken(); tokenAndExpires.setAccessToken(refreshToken); tokenAndExpires.setExpires(7200L); return tokenAndExpires; } tokenAndExpires.setAccessToken(acc_token); tokenAndExpires.setExpires(7200L); return tokenAndExpires; } else { String refreshToken = this.refreshToken(); tokenAndExpires.setAccessToken(refreshToken); tokenAndExpires.setExpires(7200L); return tokenAndExpires; } } /** * 刷新token */ public String refreshToken() { TokenAndExpires tokenAndExpires = new TokenAndExpires(); String tokenUrl = sendURL + "/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + secret; String s = HttpUtils.sendGet(tokenUrl); JSONObject object = JSONObject.parseObject(s.trim()); String accessToken = object.getString("access_token"); Long expires_in = object.getLong("expires_in"); if (accessToken == null) { System.out.println("无法获取token,请添加白名单IP"); throw new XftException(XftError.ERROR_NO_TOKEN); } Long expirationTime = expires_in * 1000 + System.currentTimeMillis(); tokenAndExpires.setAccessToken(accessToken); tokenAndExpires.setExpires(expires_in); Map<String, String> map = new HashMap<>(); map.put(WxConstants.ACC_TOKEN, accessToken); map.put(WxConstants.EXPIRESTIME, expirationTime.toString()); redisCache.setCacheMap(WxConstants.MESSAGETOKEN_SESSION, map); redisCache.expire(WxConstants.MESSAGETOKEN_SESSION, 1, TimeUnit.DAYS); return accessToken; }
请求参数VO
@Data public class WxQrCodeVO { private String token; /** * string 是 * 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~, * 其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) */ private String scene; /** * string 否 * 默认是主页,页面 page,例如 pages/index/index, * 根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面。scancode_time为系统保留参数,不允许配置 */ private String page; /** * bool 否 * 默认是true,检查page 是否存在,为 true 时 page 必须是已经发布的小程序存在的页面(否则报错); * 为 false 时允许小程序未发布或者 page 不存在, 但page 有数量上限(60000个)请勿滥用。 */ private Boolean checkPath; /** * string 否 * 要打开的小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop"。默认是正式版。 */ private String envVersion; /** * number 否 * 默认430,二维码的宽度,单位 px,最小 280px,最大 1280px */ private Integer width; /** * bool 否 * 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认 false */ private Boolean autoColor; /** * object 否 * 默认是{"r":0,"g":0,"b":0} 。auto_color 为 false 时生效, * 使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} 十进制表示 */ private LineColor lineColor; /** * bool 否 * 默认是false,是否需要透明底色,为 true 时,生成透明底色的小程序 */ private Boolean isHyaline; }
@Data public class LineColor { private Integer r; private Integer g; private Integer b; }
获取二维码方法--通过响应类型判断是否生成成功
public String createWxQR(WxQrCodeVO vo) throws Exception { String token = vo.getToken(); if (token == null){ TokenAndExpires tokenAndExpires = accessTokenService.getTokenAndExpires(); token = tokenAndExpires.getAccessToken(); } String sendUrl = createWxQrUrl.replace("TOKEN", token); Map<String, Object> map = new HashMap<>(); map.put("scene", vo.getScene()); map.put("page", vo.getPage()); map.put("env_version", vo.getEnvVersion()); map.put("width", vo.getWidth()); map.put("auto_color", vo.getAutoColor()); map.put("line_color", vo.getLineColor()); map.put("is_hyaline", vo.getIsHyaline()); String mapJson = JSON.toJSONString(map); URL url = new URL(sendUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); // 发送请求体 conn.getOutputStream().write(mapJson.getBytes("UTF-8")); conn.connect(); // 读取返回的图片数据 String contentType = conn.getContentType(); if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { InputStream inputStream = conn.getInputStream(); if (contentType.startsWith("image")) { // 正常情况 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { byteArrayOutputStream.write(buffer, 0, bytesRead); } byte[] bytes = byteArrayOutputStream.toByteArray(); String encode = Base64.getEncoder().encodeToString(bytes); inputStream.close(); byteArrayOutputStream.close(); return encode; } else { String responseBody = readInputStream(inputStream); JSONObject jsonObject = JSON.parseObject(responseBody); Integer errcode = (Integer) jsonObject.get("errcode"); String errmsg = (String) jsonObject.get("errmsg"); if (errcode != null) { throw new ServiceException(errmsg, errcode); } } } conn.disconnect(); return null; }
private static String readInputStream(InputStream inputStream) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder stringBuilder = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line); } reader.close(); return stringBuilder.toString(); }
HTML测试小程序显示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Display Base64 Image</title>
</head>
<body>
<img src="data:image/png;base64,
替换为base64字符串即可显示
"/>
</body>
</html>