前段时间在项目中,写了一个生成微信二微码的功能,之所以会开发这个功能,是因为我们做的小程序要进行推广让用户扫我们做的小程序的二微码进行去体验,功能实现的场景大概是: 后台生成小程序二微码,返回到后台页面进行展示,然后在点击下载二微码图片,下载到本地进行保存,业务场景就是这样,好了现在我们来看看微信小程序生成二微码。
微信开发文档
首先我先看微信开发文档的API,和接口描述,其实微信开发很简单只要我们花时间去看文档的一些介绍和接口的规则和一些常见会放的错误,这样就可以很好完成所有的微信开发,主要是能看懂开发文档和会看文档
首先进入微信开发文档的框架这里 : https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/qr-code.html
这里是获取二微码的一些场景和一些注意事项大家仔细的去看一下,我这里只需要接口B的场景,生成个数不受限制,大家要根据自己的业务场景去选择相对的接口去实现,不要随意去调用接口,接口是有请求的限制的
看完规则我们就来看一下API接口描述:
https://developers.weixin.qq.com/miniprogram/dev/api/createWXAQRCode.html
这里是不受限制获取二微码的接口,看上面的图我们就能看出来,调用这个接口:
1.接口请求必须是POST请求方式
2.调用接口需要先获取到接口凭证,这就是说前面还需要在调用一个接口(接口凭证接口请看)
3.参数 scene 这个是调用接口参数,请看说明进行处理,我们这里是放入是景区id
4.参数page 这个是小程序的路径,就是生成二微码后用户扫描进入的首页是哪个页面的意思返回值:
这里要注意了返回值如果是json数据格式就是错误的,如果是图片二进制的就是调用成功了,这样我们就用流的方式(字节流)把数据读到了我们的图片中然后在页面中展示进行下载就可以了
下面看代码:
Controller层:
/**
* 获取小程序码,适用于需要的码数量极多的业务场景
* @param spotid 这里是接口参数 scene (我这里是景区id)
* @param path 这里是接口参数 pages/index/index (主页的意思)
* @return
*/
@RequestMapping("/getwxacodeunlimit.do")
@ResponseBody
public Object getwxacodeunlimit(String spotid,String path,HttpServletRequest request) {
//这里是我的service层的代码,我从后台页面传入 spotid 景区id 和path 二微码主页 和 request 传到service中进行业务处理
//request 传入的原因是我需要获取到当前项目的路径
HttpRequestResult getwxacode = theMicrocodeServiceImpl.getwxacodeunlimit(spotid,path,request);
Map<String,Object> map = new HashMap<String,Object>();
map.put("image", getwxacode.getContent()); //接口调用成功 把图片返回到页面中
map.put("success", getwxacode.isSuccess());//是否成功 true false
return map;
}
Service层:
//获取小程序二维码,适用于需要的码数量较少的业务场景 接口
private final String CREATEWXAQRCODE= "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=";
//获取接口凭证
private final String GRANT_TYPE="https://api.weixin.qq.com/cgi-bin/token";
/**
* 获取小程序码,适用于需要的码数量极多的业务场景
* scene 景区id
* path 主页
*/
@Override
public HttpRequestResult getwxacodeunlimit(String scene,String path,HttpServletRequest request) {
//这里要说一下 这个代码的意思是我要调用接口获取接口凭证
//adminAppConfig.getWxLiteAppid() appid adminAppConfig.getWxLiteAppSecret(); secret 这个都是后台给的填上就好了
String param="grant_type=client_credential&appid="+adminAppConfig.getWxLiteAppid()+"&secret="+adminAppConfig.getWxLiteAppSecret();
HttpRequestResult doPost =null;
//发送请求 获取接口凭证
String setGet = HttpUtils.setGet(GRANT_TYPE, param);
//json转换成对象
JSONObject json = JSONObject.parseObject(setGet);
//获取接口凭证
String access_token = json.get("access_token").toString();
HttpRequest httpRequest = new HttpRequest();
//拼接接口 获取二微码
String url=API_GETWXACODEUNLIMIT+access_token;
//参数
Map<String, String> params = new HashMap<String, String>();
params.put("scene",scene);
params.put("path", path);
HttpRequestParams httpRequestParams = httpRequest.new HttpRequestParams(url,params);
//获取当前路径
String realPath = request.getSession().getServletContext().getRealPath("/");
//判断当前目录是否存在 不存在就创建
File file = new File(realPath);
if (!file.getParentFile().exists()) {
boolean result = file.getParentFile().mkdirs();
if (!result) {
doPost.setSuccess(false);
return doPost;
}
}
String uuid = UUID.randomUUID().toString().replaceAll("-","");
String filename="/qrcode/"+uuid+"."+"png";
realPath=realPath+filename;
//给工具类进行操作
//httpRequestParams 接口和参数
//realPath 路径 成功后把流写入到这个.png图片中
doPost = httpRequest.doPosts(httpRequestParams,true,realPath);
doPost.setContent(filename);
return doPost;
}
工具类:
public HttpRequestResult doPosts(HttpRequestParams requestParams,boolean postJson,String file) {
PrintWriter out = null;
BufferedReader ins = null;
BufferedInputStream in =null;
StringBuffer result = new StringBuffer("");
HttpRequestResult httpResult = new HttpRequestResult();
try {
// 打开和URL之间的连接
HttpURLConnection conn = getHttpURLConnection(requestParams.getUrl(), requestParams.getProxy());
// 设置通用的请求属性
if (TIMEOUT_IN_MILLIONS > 0) {
conn.setReadTimeout(TIMEOUT_IN_MILLIONS);
conn.setConnectTimeout(TIMEOUT_IN_MILLIONS);
}
// cookie设置
if (KEEP_COOKIE)
conn.setRequestProperty("Cookie", getCookieStr());
// 请求头设置
Map<String, String> headers = new HashMap<String, String>();
headers.putAll(defaultHeaders);
headers.putAll(requestParams.getHeaders());
if (headers != null && headers.size() > 0) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
conn.addRequestProperty(entry.getKey(), entry.getValue());
}
}
conn.setUseCaches(false);
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setInstanceFollowRedirects(true);
if(postJson) {
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(JSON.toJSONString(requestParams.getParams()));
// flush输出流的缓冲
out.flush();
}else {
String paramStr = requestParams.getParams() == null ? null : prepareParam(requestParams.getParams());
if (paramStr != null && !paramStr.trim().equals("")) {
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(paramStr);
// flush输出流的缓冲
out.flush();
}
}
// conn.setRequestProperty("Content-type", "application/json");
// String requestProperty = conn.getRequestProperty("Content-Type");
String headerField = conn.getHeaderField("Content-Type");
System.out.println(headerField+"-------------------------" +JSON.toJSONString(conn.getHeaderFields()));
if(headerField.equals("application/json")) {
httpResult.setStatus(conn.getResponseCode());
// 定义BufferedReader输入流来读取URL的响应
if (conn.getResponseCode() == 200) {
ins = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = ins.readLine()) != null) {
result.append(line);
}
httpResult.setSuccess(false);
httpResult.setContent(result.toString());
} else {
throw new Exception("request is not 200");
}
}
httpResult.setStatus(conn.getResponseCode());
// 定义BufferedReader输入流来读取URL的响应
if (conn.getResponseCode() == 200) {
in = new BufferedInputStream(conn.getInputStream());
//C:/Program Files/Desktop/3.png
FileOutputStream fileOut = new FileOutputStream(file);
DataOutputStream dataOut = new DataOutputStream(fileOut);
String line;
int temp;
while ((temp = in.read()) != -1) {
dataOut.write(temp);
}
dataOut.flush();
dataOut.close();
httpResult.setSuccess(true);
httpResult.setContent(result.toString());
} else {
throw new Exception("request is not 200");
}
if (KEEP_COOKIE)
storeCookie(conn);
} catch (Exception e) {
e.printStackTrace();
httpResult.setError(e);
}
// 使用finally块来关闭输出流、输入流
finally {
try {
if (out != null)
out.close();
if (in != null)
in.close();
} catch (IOException ex) {
}
}
return httpResult;
}
好了大概就是这样了这只是一个实例,大家看我上面的描述自己都可以去手写了,我的代码可能有些工具类没有,很麻烦就不写上去了,代码大概就是这样了,有什么问题就在下方评论我会一一回复