java實現小程式獲取二維碼(介面B)
應用場景:
- 實際應用場景:比如分享助力、名片分享之類的頁面需要生成二維碼
- 為滿足不同需求和場景,小程式提供了三個介面,開發者可挑選適合自己的介面
- 介面A:適用於需要的碼數量較少的業務場景
- 生成小程式碼,可接受 path 引數較長,生成個數受限,數量限制見 下面注意事項,請謹慎使用。
- 介面B:適用於需要的碼數量極多的業務場景
- 生成小程式碼,可接受頁面引數較短,生成個數不受限。
- 介面C:適用於需要的碼數量較少的業務場景
- 生成二維碼,可接受 path 引數較長,生成個數受限,數量限制見 注意事項。
注意事項:
- 介面只能生成已釋出的小程式的二維碼
- 介面 A 加上介面 C,總共生成的碼數量限制為 100,000,請謹慎呼叫
- 介面 B 呼叫分鐘頻率受限(5000次/分鐘),如需大量小程式碼,建議預生成
小程式生成二維碼兩種樣式:
我這裡因為業務需求選擇的是介面B ,下面是具體實現例項。
準備:
- 小程式appId
- 小程式appSecret
第一步:獲取呼叫介面憑證,獲取小程式 asscess_token
請求方式:GET
請求地址: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
請求引數:String grant_type(這裡預設填寫client_credential)
String appid(你自己的小程式appId)
String secret(你自己的小程式appSecret)
java程式碼實現:
//獲取access_token Map<String, Object> param = new HashMap<>(); param.put("grant_type", Element.grant_type); param.put("appid", appid); param.put("secret", secret); String result = HttpClientUtil.doGet(Element.GET_ACCESS_TOKEND_URL, param); logger.info("獲取access_token返回引數{}:" + result); Map<String, Object> resultMap = (Map<String, Object>) JSONUtil.jsonToObject(result, Map.class); String accessToken = MapUtils.getString(resultMap, "access_token"); logger.info("access_token=" + accessToken);
這裡的引數通過定義常量和傳參的方式,傳送請求定義了一個工具類,會在下面附上HttpClientUtil.java
小程式提供的網頁除錯工具除錯該介面也能獲取access_token
第二步:獲取二維碼
請求方式:POST
請求地址:POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN
請求引數:String access_token(上面第一步獲取的access_token)
String scene(最大32個可見字元)
String page(必須是已經發布的小程式存在的頁面(否則報錯),例如
pages/index/index
)int width(二維碼的寬度,預設為 430px,最小 280px,最大 1280px)
boolean auto_color(自動配置線條顏色,如果顏色依然是黑色,則說明不建議配置主色調,預設 false)
Object line_color(auto_color 為 false 時生效,使用 rgb 設定顏色 例如
{"r":"xxx","g":"xxx","b":"xxx"}
十進位制表示,預設全 0)boolean is_hyaline(是否需要透明底色,為 true 時,生成透明底色的小程式碼,預設 false)
java實現 :
//獲取二維碼 URL url = new URL(Element.QR_CODE_URL + accessToken); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setRequestMethod("POST");// 提交模式 // conn.setConnectTimeout(10000);//連線超時 單位毫秒 // conn.setReadTimeout(2000);//讀取超時 單位毫秒 // 傳送POST請求必須設定如下兩行 httpURLConnection.setDoOutput(true); httpURLConnection.setDoInput(true); // 獲取URLConnection物件對應的輸出流 PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream()); // 傳送請求引數 JSONObject paramJson = new JSONObject(); paramJson.put("scene", userUuid); paramJson.put("page", page); paramJson.put("width", Element.width); paramJson.put("auto_color", Element.auto_color); /** * line_color生效 * paramJson.put("auto_color", false); * JSONObject lineColor = new JSONObject(); * lineColor.put("r", 0); * lineColor.put("g", 0); * lineColor.put("b", 0); * paramJson.put("line_color", lineColor); * */ printWriter.write(paramJson.toString()); // flush輸出流的緩衝 printWriter.flush(); //獲取二維碼檔案流 InputStream inputStream = httpURLConnection.getInputStream(); String qrCodePath = String.format(qRCodePath, userUuid); if (!uploadService.exsitFile(qrCodePath)) { String path = uploadService.uploadIsToOSS(inputStream, qrCodePath); IOUtils.closeQuietly(inputStream); if (StringUtils.isNotBlank(path)) { return imageAddress + "/" + path; } } return imageAddress + "/" + qrCodePath;
這裡已經獲取到二維碼的流了,怎麼處理就看實際需求,我這裡是將流寫到OSS上面返回的OSS上面二維碼地址
HttpClientUtil.java:
package com.xgt.util;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSONObject;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import okhttp3.*;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import static com.xgt.util.wechat.WxPayUtil.XML;
/**
* Author:wwei
* DESC:HttpClient工具類
*/
public class HttpClientUtil {
private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
public static String doGet(String url) {
// 建立HttpClientBuilder
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
String tempTitle = null;
try {
HttpGet httpGet = new HttpGet(url);
// 執行get請求
HttpResponse httpResponse;
httpResponse = closeableHttpClient.execute(httpGet);
// 獲取響應訊息實體
HttpEntity entity = httpResponse.getEntity();
// 判斷響應實體是否為空
if (entity != null) {
return EntityUtils.toString(entity, "UTF-8");
} else {
return null;
}
} catch (Exception e) {
logger.error(tempTitle);
logger.error(""+ e);
} finally {
try {
// 關閉流並釋放資源
closeableHttpClient.close();
} catch (IOException e) {
logger.error(""+ e);
}
}
return null;
}
public static String doGet(String url, Map<String, Object> params) {
if(!StringUtils.hasText(url)){
return "";
}
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
try {
if (params != null && !params.isEmpty()) {
List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());
for (String key : params.keySet()) {
pairs.add(new BasicNameValuePair(key, params.get(key).toString()));
}
url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, "UTF-8"));
}
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = closeableHttpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
// 判斷響應實體是否為空
if (entity != null) {
return EntityUtils.toString(entity, "UTF-8");
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 關閉流並釋放資源
closeableHttpClient.close();
} catch (IOException e) {
logger.error(e.toString());
}
}
return null;
}
public static String doPost(RequestObject object) {
// 建立HttpClientBuilder
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
String tempTitle = null;
try {
HttpPost httpPost = new HttpPost(object.toUrl());
// 執行get請求
HttpResponse httpResponse;
httpResponse = closeableHttpClient.execute(httpPost);
// 獲取響應訊息實體
HttpEntity entity = httpResponse.getEntity();
// 判斷響應實體是否為空
if (entity != null) {
return EntityUtils.toString(entity, "UTF-8");
} else {
return null;
}
} catch (Exception e) {
logger.error(tempTitle);
logger.error(e.toString());
} finally {
try {
// 關閉流並釋放資源
closeableHttpClient.close();
} catch (IOException e) {
logger.error(e.toString());
}
}
return null;
}
public static String doPost(String url,Map<String,Object> map,String charset){
HttpClient httpClient = null;
HttpPost httpPost = null;
String result = null;
try{
httpClient = new SSLClient();
httpPost = new HttpPost(url);
httpPost.addHeader("Content-Type", "application/json");
httpPost.addHeader("Authorization", "Basic YWRtaW46");
//設定引數
String paramStr = JSONUtils.toJSONString(map);
logger.info("....請求引數:{}....",paramStr);
StringEntity entity = new StringEntity(paramStr, "utf-8");
entity.setContentEncoding(new BasicHeader("Content-Type",
"application/json"));
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
if(response != null){
HttpEntity resEntity = response.getEntity();
if(resEntity != null){
result = EntityUtils.toString(resEntity,charset);
}
}
}catch(Exception ex){
ex.printStackTrace();
}
logger.info("....返回結果:{}.......",result);
return result;
}
/**
* restful post 請求
* @author liuao
* @date 2018/7/19 11:13
*/
public static Map doPost(String url, Map param){
try {
Client client = Client.create();
URI u = new URI(url);
WebResource resource = client.resource(u);
MultivaluedMap<String, String> params = new MultivaluedMapImpl();
Iterator i$ = param.entrySet().iterator();
while(i$.hasNext()) {
Map.Entry<String, List<String>> e = (Map.Entry)i$.next();
params.add(e.getKey(), String.valueOf(e.getValue()) );
}
logger.info("查詢引數:" + params.toString());
String result = resource.type(MediaType.APPLICATION_FORM_URLENCODED).post(String.class, params);
logger.info("url = :{},返回結果:{}", url, result);
JSONObject jasonObject = JSONObject.parseObject(result);
return (Map)jasonObject;
} catch (Exception e) {
logger.error("..........",e );
}
return null;
}
/**
* post str
* @author liuao
* @date 2018/9/26 14:24
*/
public static String postXML(String url, String xmlData) {
logger.info(".....unifiedOrder.....請求引數..:{}", xmlData);
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody body = RequestBody.create(XML, xmlData);
Request request = new Request.Builder()
.post(body)
.url(url)
.addHeader("Accept", "application/xml")
.build();
Call call = okHttpClient.newCall(request);
try {
Response response1 = call.execute();
String result = response1.body().string();
logger.info("..postXML..返回結果....{}", result);
return result;
} catch (IOException e) {
logger.error("..........",e );
}
return null;
}
}
補充:
想通過auto_color設定為false,line_color設定rgb來調一個自定義主色調二維碼,但是一直是黑色,後來仔細看了一下官方文件,上面有句話是“如果顏色依然是黑色,則說明不建議配置主色調”,不知道可有人遇見,在此備註一下。