介紹下應用場景
技術框架:前端是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[]圖片,此處做法應該與前端溝通,再根據情況選擇。
!!!拒絕搬運,創作不易,有幫助請點個贊