java+vue element 小程序码后端生成和前端展示
- 介绍下应用场景
- 接口介绍:
- java 后端
- 注意
- 前端
介绍下应用场景
技术框架:前端是vue+element 后端为spring cloud,使用腾讯制码接口类型B,使用restTemplate作为请求框架。
业务场景: 前端查看某个页面,本页面生成小程序码,将参数传入小程序码,用户扫码后查看页面数据。(这个应该是通用场景吧)😅😅😅😅
接口介绍:
罗列几个知识点:
1.小程序码生成,腾讯分为4种类型,详细区别官方文档里解释得很详细,此处不再复述。
接口文档链接
链接: 接口文档.
此处我们选用接口B(无限数量,永久有效)。
java 后端
调用图如下
先请求接口凭证,获取凭证后,再使用凭证去调用制码接口,生成小程序码。
后端代码如下。
实体类,用于接收图片
public class WxCodeUnlimitedResponseParam implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 请求失败错误码
*/
private String errCode;
/**
* 请求失败错误信息
*/
private String errMsg;
/**
* 图片信息
*/
private byte[] buffer;
public String getErrCode() {
return errCode;
}
public void setErrCode(String errCode) {
this.errCode = errCode;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public byte[] getBuffer() {
return buffer;
}
public void setBuffer(byte[] buffer) {
this.buffer = buffer;
}
}
生成凭证
/**
* 获取微信的appId的工具类,字符串之后需要JSON.parseObject转化。
*
* @param appId
* @param secret
* @return 获取结果
*/
public static String getAccessToken(String appId, String secret) {
String accesstoken="";
String requestUrl = ACCESS_TOKEN_URL;
//传入参数替换
requestUrl = requestUrl.replaceAll("APPID", appId);
requestUrl = requestUrl.replaceAll("SECRET", secret);
//超时,需要重新请求接口
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(requestUrl, String.class);
JSONObject jsonObject = JSON.parseObject(result.toString());
accesstoken = jsonObject.getString("access_token");
return result;
}
注意
此处是简单可用代码,实际上获取凭证后我们应该将凭证保存在我们数据库中,原因是接口凭证一天有调用次数上限,且两小时后失效。我们需要在调用前检查数据库中得凭证是否过期,过期后再重新请求新的凭证,而不是每次都去请求。
实际上正确的做法是使用redis保存accessToken(凭证),之后再起定时任务去专门维护此凭证。这样得做法可避免高并发下得脏读等问题(项目没用redis,放弃)。
//生成二维码接口
public static WxCodeUnlimitedResponseParam getUnlimitedCode(String accessToken, String scene, String page) {
// url请求参数值
Map<String, Object> params = new HashMap<String, Object>();
//**注意:接口文档错误需要将access_token参数放到url中,否则请求会失败
//scene为你需要传入得参数类似“id=????&code=222”,为参数名和值组成得字符串。
params.put("scene", scene);
params.put("page", page);
params.put("width", 200);
params.put("auto_color", true);
params.put("line_color", null);
params.put("is_hyaline", false);
byte[] byteArray = null;
/** 第一种方式:使用RestTemplate。项目采用了这种方式。 **/
// 调用微信接口
WxCodeUnlimitedResponseParam res = new WxCodeUnlimitedResponseParam();
try {
RestTemplate restTemplate = new RestTemplate();
String request =WX_CODE_URL.replaceAll("AccessToken",accessToken);
ResponseEntity<byte[]> entity = restTemplate.postForEntity(
request,
JSONObject.toJSONString(params), byte[].class);
// 如果你十分确认微信正确返回了图片,那么byteArray已经是你想要的结果了。
byteArray = entity.getBody();
// 微信返回内容,byte[]转为string
String wxReturnStr = new String(byteArray);
if (wxReturnStr.indexOf("errcode") != -1) {
JSONObject json = JSONObject.parseObject(wxReturnStr);
res.setErrCode(json.get("errcode").toString());
res.setErrMsg(json.get("errmsg").toString());
} else {
res.setErrCode("0");
res.setErrMsg("ok");
res.setBuffer(byteArray);
}
} catch (Exception e) {
LOGGER.error("微信小程序码getUnlimited接口调用失败", e);
}
return res;
}
此处之后整个后端请求流程就完成了,剩下的是如何返回给前端了。
前端
此处博主是以图片流的方式返回给前端。
后端是这样的
String accessToken=wxacodeService.getAccessToken(type);
WxCodeUnlimitedResponseParam res= wxacodeService.getUnlimited(accessToken,id,type);
//以流的方式返回给前端
InputStream inputStream = new ByteArrayInputStream(res.getBuffer());
BufferedImage bufferedImage = ImageIO.read(inputStream);
if (bufferedImage != null){
String format = "jpg";
return ImageIO.write(bufferedImage, format, response.getOutputStream());
}
此处将图片转化流传输
前端有两种方式获取图片
一种是将当前接口地址看作一种图片资源链接
在 image组件中将src直接指向后端接口路径。
<div class="block">
<span class="demonstration">默认</span>
<el-image :src="QRcodeSrc"></el-image>
</div>
//获取二维码
getQRcode:function () {
var appId ="";
var secret ="ceshi";
this.QRcodeSrc="/api/makeWxCode?appId="+appId+"&secret="+secret;
}
},
此处注意需要前台在路由中允许访问后台任意路径
即 路径后为/*
2.如果不允许可在前台将流转化为图片显示
转码为
let params = {
id: this.id,
};
axios({
method: 'GET',
url: '/api/makeWxCode',
params: params,
responseType: 'arraybuffer'
})
.then(res => {
console.log(res);
const bufferUrl = btoa(new Uint8Array(res.data).reduce((body, byte) => body + String.fromCharCode(byte), ''));
this.QRcodeSrc = 'data:image/png;base64,' + bufferUrl;
this.loading = false;
})
.catch(err => {
this.$message('请求失败!');
this.loading = false;
});
当然,此种做法,后台就无需返回图片流了,可以在最开始便返回byte[]图片,此处做法应该与前端沟通,再根据情况选择。