一、獲取小程序碼的三個接口
不同的接口對應不同的業務場景,接口B用的較多,接口C官方不推薦使用,也就是說根據需碼量來決定選擇A接口還是B接口。
(1)、接口 A: 適用於需要的碼數量較少的業務場景
生成小程序碼,可接受 path 參數較長,生成個數受限
(1)、接口 B:適用於需要的碼數量極多的業務場景
生成小程序碼,可接受頁面參數較短,生成個數不受限.
就以接口B來展開說明
二、思路介紹
(1)、獲取 ACCESS_TOKEN 憑證。
根據文檔可以看出來,一個Token最多可用2小時並且只能存在一個可用Token,即使本Token並沒有失效,再次獲取新的Token也會使上一個Token失效。
為了保證高可用,不能2小時刷新一次token吧,太呆逼。可以1個半小時刷新一次,獲取Token存入Redis,如果Redis中獲取不到就重新獲取Token存入Redis。
(2)、帶參入碼
請求方式
POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=你的微信Token
參數
常用的有 scene 、 page 其他的具體細節並不做過多控制
scene傳參有些許特殊
{
"scene": "a=1"
}
多個參數 :scene=shop=382number=3這樣傳 有的手機就把 = 轉義了,有的沒有,所以定義統一解析規則 a=1 改為 az1 或者 ak1等等 由前端去拆分字符解析
(3)、保存圖片
操作成功后 返回的圖片 Buffer 而不是圖片地址,因此需要做一些處理,保存到本地、然后上傳到服務器
(4)、異常處理
失敗的話會返回錯誤碼,根據具體的錯誤碼去做處理
如果是Token失效所導致的異常40001,就在獲取一遍Token重新執行操作,提高容錯率,保證高可用
三、編碼
(1)、獲取 ACCESS_TOKEN 憑證。
開發環境一般都有配置Redis頭,實例代碼並不規范,僅供參考。
//從Yml配置文件讀取關於微信的配置
@Resource
private WechatConfig wxConfig;
@Override
public String getWeChatToken() throws IOException {
//1、從Redis獲取微信的Token
String accessToken = RedisHelper.get(RedisKey.getKey("存入的微信Token"));
//2、不為空則返回Redis中的微信Token
if (StringUtils.isNotBlank(accessToken)) {
return accessToken;
}
//3、為空則獲取Token
accessToken = this.obtainToken();
return accessToken;
}
/**
* 獲取 access_token
*/
@Override
public synchronized String obtainToken() throws IOException {
//1、從配置文件讀取到下面的參數 並發送Get請求就可以獲取到Token
String getToken = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
//2、獲取到請求的結果轉成指定的格式
//(接口只返回access_token和錯誤碼expires_in,因此該param只封裝這兩個參數)
returnTokenParam token = JSONObject.parseObject(s, returnTokenParam .class);
String accessToken = token .getAccessToken();
//3、獲取Token成功存入Redis 失敗拋出異常,當然也可以做異常處理
if ("".equals(accessToken) || StringUtils.isBlank(accessToken)) {
log.error("獲取微信Access_Token失敗");
throw new BizException(ErrorCode.WECHAT_ACCESSTOKEN_ERROR);
}
RedisHelper.set(token自定義名稱, accessToken, 過期時間 60*60*30 1個半小時);
return accessToken;
}
(2)、帶參入碼、異常處理
//1、校驗,准備參數
//因Token只能生效一個所以 非線上環境不去獲取token
//(邏輯~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
//生成的用戶邀請小程序碼會被持久化,查詢是否持久化,是的話返回結果
//(邏輯~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
//獲取微信accessToken
String accessToken = 第一步的getWeChatToken();
//2、創建請求參數
JSONObject params = new JSONObject();
//讓前端通過 "y" 解析參數 也可以是別的
params.put("scene","cy"+customer.getRecommendCode());
//掃碼后進入小程序的頁面位置(從yml讀)
params.put("page", page);
//3、發起 post json請求 (按自己的方式發請求,接收結果就行)
Response response = 你自己的請求工具類.POST請求("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken, params);
//4、獲取結果進行處理(成功默認返回image/jpeg)
String contentType = response.header("Content-Type");
if (!"image/jpeg".equals(contentType)) {
//處理錯誤(獲取返回結果的body)
String body = response.body().string();
JSONObject jsonObject = new JSONObject(body);
String errcode = jsonObject.get("errcode").toString();
//如果為 40001 錯誤碼 極可能是token出現問題,保證高可用再去重新獲取
if (!"40001".equals(errcode)) {
String errmsg = jsonObject.get("errmsg").toString();
log.error("記錄錯誤日志");
//拋出異常
throw new .....;
}
//重新獲取token
accessToken = 第一步的getWeChatToken();
//重新發起 post json請求
Response response = 你自己的請求工具類.POST請求("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken, params);
//獲取結果進行處理
contentType = response.header("Content-Type");
if (!"image/jpeg".equals(contentType)) {
String errmsg = jsonObject.get("errmsg").toString();
log.error("記錄錯誤日志");
//拋出異常
throw new .....;
}
}
//5、保存圖片
saveToImgByInputStream(得到的流,保存路徑)
//上傳到服務器
//(邏輯~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
//持久化圖片地址
//(邏輯~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
3、保存圖片
/**
* 將二進制轉換成文件保存
* @param instreams 二進制流
* @param imgPath 圖片的保存路徑
* @return
* 1:保存正常
* 0:保存失敗
*/
public static int saveToImgByInputStream(InputStream instreams, String imgPath){
int stateInt = 1;
if(instreams != null){
try {
//可以是任何圖片格式.jpg,.png等
File file = new File(imgPath);
FileOutputStream fos=new FileOutputStream(file);
byte[] b = new byte[1024];
int nRead = 0;
while ((nRead = instreams.read(b)) != -1) {
fos.write(b, 0, nRead);
}
fos.flush();
fos.close();
} catch (Exception e) {
stateInt = 0;
e.printStackTrace();
}
}
//1 成功,0 失敗
return stateInt;
}
一定不能忘了,微信Token只能同時存在一個,且過期時間默認走最大時間(2小時)