全文目录,一步到位
- 1.前言简介
- 1.1 专栏传送门
- 1.1.1 上文小总结
- 1.1.2 上文传送门
- 2. 获取不限制二维码操作
- 2.1 准备工作
- 2.1.1 请先复制00篇的统一封装代码
- 2.1.2 修改配置文件中的参数
- 2.2 具体代码使用与注释如下
- 2.2.1 业务代码如下
- 2.2.2 代码解释(一)[无需复制]
- 2.2.3 创建Base64类
- 2.3 运行并检查结果
- 2.3.1 controller代码
- 2.3.2 二维码请求对象dto代码
- 2.4 异常总结与解决(相对全面)
- 2.4.0 直接测试后发现问题
- 2.4.1 (核心排查)使用微信官方接口测试查看问题
- 导入curl数据方法(如图所示)
- curl: 抓包数据如下(导入即可)
- 2.4.2 解决方案
- 异常一: (异常码41030)导入curl后, 报这个错误
- 异常二: (异常码41030)无效的page参数(`很坑`)
- 异常三: (异常码40169)scene过长无法生成
- 异常N(`跳过`): 网络波动等访问超时/异常
- 2.4.3 正确结果(微信扫码测试一下)
- 2.4.4 接口请求测试
- 特殊: 如果只能显示出一半
- 3. 文章的总结与预告
- 3.1 本文总结
- 3.2 下文预告
1.前言简介
本篇细节很多, 我会在文章
最后统一总结
1.1 专栏传送门
=> 小程序相关操作专栏 <=
1.1.1 上文小总结
上文主要是大多数微信小程序的整体封装, 代码共用, 而本篇只需要关心业务本身即可, 使用前请先复制上文的代码后使用(请看1.1.2文章传送门)
1.1.2 上文传送门
微信小程序00: 公共封装配置(核心篇)
2. 获取不限制二维码操作
2.1 准备工作
2.1.1 请先复制00篇的统一封装代码
这里强调一下
请先复制核心篇: ===> 微信小程序-00 小程序统一封装类
请先阅读上一篇: ===> 微信小程序01: springboot获取accessToken方式
2.1.2 修改配置文件中的参数
例如
appid
等, 均在
2.2 具体代码使用与注释如下
2.2.1 业务代码如下
AjaxResult统一返回值
对象 随意写
第二步的userService代表您的业务
, 随意写
记得@Autowired一下
/**
* 获取注册二维码
*
* @param wxCodeUnlimitedReqDTO 请求对象
* @return AjaxResult
*/
@SneakyThrows
public AjaxResult getRegisterQrcode(WxCodeUnlimitedReqDTO wxCodeUnlimitedReqDTO) {
//1.获取access_token
String accessToken = wechatServiceUtils.getRedisCacheAccessToken();
//2. 处理scene值
String scene = userService.getUserRelationScene(wxCodeUnlimitedReqDTO);
//3. 获取微信不限制二维码的input输入流
InputStream inputStream = wechatServiceUtils.getUnlimitedWxQrCode(wxCodeUnlimitedReqDTO.setScene(scene), accessToken);
//3. byte的nio流直接转换为base64
String base64Str = Base64.changeInputIOToBase64A(inputStream);
Map<String, String> map = new HashMap<>();
map.put("imgBase64", "data:image/png;base64," + base64Str);
map.put("scene", scene);
//4. 返回结果
return AjaxResult.success("操作成功!", map);
}
2.2.2 代码解释(一)[无需复制]
wechatServiceUtils.
getUnlimitedWxQrCode
() 统一封装 获取不限制二维码操作
其中使用了restTemplate
远程调用微信官方接口
通过ByteArrayInputStream直接将byte转换为InputStream
- 这块还是有其他写法的 (import org.springframework.core.io.Resource;)
- 这个能看到整个接口的返回信息 报错信息等
二选一即可
//方案二:(需要替换WechatServiceUtils类中对应方法)
ResponseEntity<Resource> responseEntity = restTemplate.exchange(wechatConfigProperties.getWxACodeUnLimitUrl(accessToken), HttpMethod.POST, new HttpEntity<>(params, headers), Resource.class);
log.info("==> 微信二维码返回参数: {} <==", responseEntity);
// 从响应体中获取输入流
InputStream inputStream = Objects.requireNonNull(responseEntity.getBody()).getInputStream();
微信文档位置: => 微信小程序获取不限制二维码 <=
/**
* 生成小程序带参数二维码
*/
@SneakyThrows
public InputStream getUnlimitedWxQrCode(WxCodeUnlimitedReqDTO wxCodeUnlimitedReqDTO, String accessToken) {
Map<String, Object> params = new HashMap<>();
params.put("scene", wxCodeUnlimitedReqDTO.getScene());
params.put("page", wxCodeUnlimitedReqDTO.getPage());
params.put("path", wxCodeUnlimitedReqDTO.getPage());
params.put("env_version", wxCodeUnlimitedReqDTO.getEnvVersion());
params.put("width", wxCodeUnlimitedReqDTO.getWidth());
params.put("auto_color", wxCodeUnlimitedReqDTO.getAutoColor());//自动配置线条颜色
ResponseEntity<byte[]> response = restTemplate.postForEntity(wechatConfigProperties.getWxACodeUnLimitUrl(accessToken), JSON.toJSONString(params), byte[].class);
System.out.println(JSON.toJSONString(params));
byte[] buffer = response.getBody();
assert buffer != null;
return new ByteArrayInputStream(buffer);
}
/**
* 远程调用 restTemplate方法 post请求
*/
public <T> T sendPostRestTemplate(String url, Map<String, Object> body, Class<T> responseType) {
return restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, null), responseType).getBody();
}
2.2.3 创建Base64类
里面有几个方法 选一个即可
changeInputIOToBase64A()
/**
* 方法一: IO: 转换输入流->Base64
* @param in
* @return
*/
public static String changeInputIOToBase64A(InputStream in) {// 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
byte[] data = null;
String encode = null; // 返回Base64编码过的字节数组字符串
// 对字节数组Base64编码
org.apache.commons.codec.binary.Base64 encoder = new org.apache.commons.codec.binary.Base64();
try {
// 读取图片字节数组
data = new byte[in.available()];
in.read(data);
encode = encoder.encodeToString(data);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return encode;
}
/**
* 方法二: IO: 转换输入流->Base64
*/
public static String changeInputIOToBase64B(InputStream inputStream) {
byte[] data = null;
try (ByteArrayOutputStream swapStream = new ByteArrayOutputStream()) {
byte[] buff = new byte[100];
int rc = 0;
while ((rc = inputStream.read(buff, 0, 100)) > 0) {
swapStream.write(buff, 0, rc);
}
data = swapStream.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return java.util.Base64.getEncoder().encodeToString(data);
}
/**
* 关流功能
*
* @param inputStream 输入流
* @throws IOException 异常
*/
public static void closeInputStream(InputStream inputStream) throws IOException {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
2.3 运行并检查结果
2.3.1 controller代码
模拟-获取注册二维码
/**
* 获取注册二维码
*/
@PostMapping("/getQrcode")
public AjaxResult getQrcode(@RequestBody WxCodeUnlimitedReqDTO wxCodeUnlimitedReqDTO) {
log.info("===> 获取注册二维码 <===");
log.info(JSONObject.toJSONString(wxCodeUnlimitedReqDTO));
return loginService.getQrcode(wxCodeUnlimitedReqDTO);
}
2.3.2 二维码请求对象dto代码
微信生成不限制小程序二维码请求dto
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* 微信生成不限制小程序二维码请求dto
* @author pzy
* @version 0.1.0
* @description: TODO
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class WxCodeUnlimitedReqDTO {
/**
* 最大32个可见字符,只支持数字,
* 大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,
* 其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)
*/
private String scene;
/**
* 页面 page,例如 pages/index/index
*/
private String page;
/**
* 检查 page 是否存在,为 true 时 page 必须是已经发布的小程序存在的页面
*/
private Boolean checkPath = Boolean.FALSE;
/**
* 要打开的小程序版本。正式版为 release,体验版为 trial,开发版为 develop
*/
private String envVersion = "release";
/**
* 二维码的宽度,单位 px,最小 280px,最大 1280px
*/
private Integer width;
/**
* 自动配置线条颜色
*/
private Boolean autoColor = Boolean.FALSE;
/**
* 注册的用户角色
*/
private Integer registerUserRole;
/**
* (平台业务员1)帮助注册的公司id
*/
private Long registerCompanyId;
}
2.4 异常总结与解决(相对全面)
2.4.0 直接测试后发现问题
base64很短 访问后是这样的 如图所示
先看2.4.1(很重要)
不行在排查代码
2.4.1 (核心排查)使用微信官方接口测试查看问题
直接使用
postman/apipost
等 进行测试访问
如果返回的base64
能在浏览器展示出来 则代码出现问题
反之 则您的accessToken/path
路径存在问题
curl
(抓包数据)如下: 直接导入即可 修改accessToken和path
导入curl数据方法(如图所示)
curl: 抓包数据如下(导入即可)
curl --request POST \
--url 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=77_TUdWM60vBoa3FofIKUQ8piUkH4Jd555A4Mknt19tKVyEPNUJ2bOyAHVGc_7iXiJs7ElXXjhs9IrOSD2JI1E5_Q3vWUXbRX0Z9YrDeLC9hEqSentISFSBRv9sbZgXMBjABAAP6' \
--header 'content-type: application/json' \
--data '{
"width": 480,
"auto_color": false,
"page": "pages/index/index",
"scene": "762350390017339392",
"env_version": "trial"
}'
2.4.2 解决方案
场景: 用
postman/apipost导入curl直接请求
官方接口报错信息
异常一: (异常码41030)导入curl后, 报这个错误
则为: accessToken过期了
更换一个新的即可(如图所示)
文章传送门: => 微信小程序01: springboot获取accessToken方式
异常二: (异常码41030)无效的page参数(很坑
)
特别注意: 这个page必须是
正式版中存在
的路径(pages/index/index
是默认存在的)
其他路径需要上传并发布正式版
后 并且验证路径真实存在
后才可以使用
否则不可以生成二维码
如果默认的可以生成
其他路径均不可以生成 请联系前端打正式版并发布
解决
异常三: (异常码40169)scene过长无法生成
微信文档中 不限制类型的scene有长度限制32位字符 超过则无法生成
异常N(跳过
): 网络波动等访问超时/异常
换个网络试试, 代理关了等等(跳过)
2.4.3 正确结果(微信扫码测试一下)
其中 scene和env_version均可调整
2.4.4 接口请求测试
将
成功的参数
复制到java接口参数json中进行代码测试
如果能正确展示base64 并且在网页中展示正常 则为成功(如图)
特殊: 如果只能显示出一半
- 调整width大小(一般没用)
- 调整base64方法
- 调整restTemplate方法
3. 文章的总结与预告
3.1 本文总结
- 使用00篇中的方法获取accessToken
- 获取不限制二维码
- 调整部分参数, 遇到问题 如
2.4中提到及解决方案
- base64转换
- restTemplate使用
3.2 下文预告
微信小程序04: 获取openId与unionId
@author: pingzhuyan
@description: ok
@year: 2024