java获取微信小程序码(太阳码)使用base64编码后返回附带处理异常情况
·
获取不限制的小程序码
接口地址:接口应在服务器端调用,详细说明参见服务端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>
更多推荐



所有评论(0)