Java生成微信小程序二維碼完整實例代碼
1. java 二維碼生成工具類
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.pdatao.api.controller.file.FileController;
import com.pdatao.api.error.CommunityException;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
@Component
public class MpQrCodeUtil {
@Resource
FileController fileController;
@Value("${mp.wechat.appid}")
private String mpAppId;
@Value("${mp.wechat.secret}")
private String mpSecretId;
@Value("${qrcode.pageHome}")
private String pageHome;
@Value("${spring.profiles.active:}")
private String activeProfile;
private static final String API_GET_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
private static final String API_GET_QR_CODE = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s";
private static String cachedToken = null;
private static long tokenExpireTime = 0;
public String getMpQRCode(Long orderId, HttpServletRequest request) throws Exception {
String scenes = "id=" + orderId + "&v=1";
String envVersion = "";
if ("prod-plus".equals(activeProfile)) {
envVersion = "release";
}
return this.getQRCodeWeb(scenes,envVersion,orderId,request);
}
public String getQRCodeWeb(String scenes, String envVersion, Long orderId, HttpServletRequest request) throws Exception {
String accessToken = getToken(mpAppId, mpSecretId);
return getQRCode(accessToken, scenes, envVersion, orderId, request);
}
public static String getToken(String appId, String appSecret) throws Exception {
// 1. 檢查緩存是否有效
if (cachedToken != null && System.currentTimeMillis() < tokenExpireTime) {
return cachedToken;
}
HttpURLConnection conn = null;
try {
String url = String.format(API_GET_TOKEN, appId, appSecret);
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.setRequestMethod("GET");
int statusCode = conn.getResponseCode();
if (statusCode != 200) {
// 讀取錯誤流
String errorJson = IOUtils.toString(conn.getErrorStream(), StandardCharsets.UTF_8);
throw new CommunityException("微信接口錯誤: " + errorJson);
}
JSONObject result = new JSONObject(IOUtils.toString(conn.getInputStream(), StandardCharsets.UTF_8));
cachedToken = result.getStr("access_token");
long expiresIn = result.getLong("expires_in") * 1000; // 轉(zhuǎn)為毫秒
tokenExpireTime = System.currentTimeMillis() + expiresIn - 600_000;
return cachedToken;
} finally {
if (conn != null) conn.disconnect();
}
}
public String getQRCode(String accessToken, String scenes, String envVersion, Long orderId, HttpServletRequest request) throws Exception {
HttpURLConnection httpURLConnection = null;
try {
URL url = new URL(String.format(API_GET_QR_CODE, accessToken));
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("POST");// 提交模式
// 發(fā)送POST請求必須設置如下兩行
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
// 發(fā)送請求參數(shù)
com.alibaba.fastjson.JSONObject paramJson = new com.alibaba.fastjson.JSONObject();
paramJson.put("scene", scenes);
paramJson.put("page", pageHome);
paramJson.put("env_version", StrUtil.isNotEmpty(envVersion) ? envVersion : "trial");
paramJson.put("check_path", false);
try (PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream())) {
printWriter.write(paramJson.toString());
printWriter.flush();
}
// 檢查響應碼
int responseCode = httpURLConnection.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
cachedToken = null;
throw new CommunityException("生成二維碼失?。篐TTP錯誤碼 " + responseCode);
}
// 檢查內(nèi)容類型
String contentType = httpURLConnection.getContentType();
if (contentType == null || !contentType.startsWith("image/")) {
cachedToken = null;
throw new CommunityException("生成二維碼失?。航涌诜祷胤菆D片數(shù)據(jù)(" + (contentType != null ? contentType : "未知內(nèi)容類型") + ")");
}
try (InputStream is = httpURLConnection.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();) {
byte[] buffer = new byte[1024];
int len = -1;
while ((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
byte[] imageData = baos.toByteArray();
// 簡單驗證是否是有效圖片(可選)
if (imageData.length == 0) {
cachedToken = null;
throw new CommunityException("生成二維碼失?。悍祷乜請D片數(shù)據(jù)");
}
MultipartFile multipartFile = new ByteArrayMultipartFile(
orderId + "_mpqrcode", // 表單字段名
orderId + "_mpqrcode.png", // 文件名
"image/png", // 內(nèi)容類型
imageData // 內(nèi)容
);
com.alibaba.fastjson.JSONObject json = fileController.upload(multipartFile,request);
if (json == null || !json.containsKey("url")) {
throw new CommunityException("上傳圖片失敗:響應數(shù)據(jù)異常");
}
return json.getString("url");
}
} catch (Exception e) {
e.printStackTrace();
throw new CommunityException("生成二維碼失?。?+e.getMessage());
} finally {
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
}
}
2. 部分可自行調(diào)整的代碼解釋
FileController: 我自己的上傳圖片到服務器的類
mpAppId: 小程序appid
mpSecretId: 小程序 SecretId
pageHome: 要跳轉(zhuǎn)的小程序的頁面地址(例如: ‘pages/userInfo/userInfoHome’)
activeProfile: 我自己的判斷當前運行環(huán)境的配置(可以忽略)
@Resource
FileController fileController;
@Value("${mp.wechat.appid}")
private String mpAppId;
@Value("${mp.wechat.secret}")
private String mpSecretId;
@Value("${qrcode.pageHome}")
private String pageHome;
@Value("${spring.profiles.active:}")
private String activeProfile;getMpQRCode 外部調(diào)用的方法,自定義自己需要傳入什么值
Long orderId : 這個是我為了生成二維碼路徑時攜帶的參數(shù)
HttpServletRequest request: 這個參數(shù),和二維碼生成邏輯沒有任何關(guān)系,我這里使用只是因為上傳圖片的地方需要這個值,這個比較冗余
scenes: 定義頁面地址攜帶什么參數(shù)
if ("prod-plus".equals(activeProfile)) {
envVersion = "release";
} 這個是為了判斷生成什么環(huán)境的二維碼圖片(正式版/ 體驗版) public String getMpQRCode(Long orderId, HttpServletRequest request) throws Exception {
String scenes = "id=" + orderId + "&v=1";
String envVersion = "";
if ("prod-plus".equals(activeProfile)) {
envVersion = "release";
}
return this.getQRCodeWeb(scenes,envVersion,orderId,request);
}imageData : 這個就是生成的二維碼圖片信息
下面的其他信息,都是為了把這個圖片的信息,上傳到自己項目中保存,最終返回圖片地址
byte[] imageData = baos.toByteArray();
// 簡單驗證是否是有效圖片(可選)
if (imageData.length == 0) {
throw new CommunityException("生成核銷二維碼失?。悍祷乜請D片數(shù)據(jù)");
}
MultipartFile multipartFile = new ByteArrayMultipartFile(
orderId + "_mpqrcode", // 表單字段名
orderId + "_mpqrcode.png", // 文件名
"image/png", // 內(nèi)容類型
imageData // 內(nèi)容
);
com.alibaba.fastjson.JSONObject json = fileController.upload(multipartFile,request);
if (json == null || !json.containsKey("url")) {
throw new CommunityException("上傳二維碼失敗:響應數(shù)據(jù)異常");
}
return json.getString("url");3.小程序中獲取攜帶的參數(shù)
以我上述的參數(shù)為例:(微信小程序使用的 uniapp)
onLoad(option) {
if (option.scene) {
const scene = decodeURIComponent(option.scene);
const params = this.parseSceneParams(scene);
console.log(params.id)
console.log(params.v)
}
},
methods: {
parseSceneParams(scene) {
const params = {};
if (!scene) return params;
const pairs = scene.split('&');
pairs.forEach(pair => {
const [key, value] = pair.split('=');
if (key) params[key] = value;
});
return params;
},
}總結(jié)
到此這篇關(guān)于Java生成微信小程序二維碼完整的文章就介紹到這了,更多相關(guān)Java生成微信小程序二維碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot+mybatis+枚舉處理器的實現(xiàn)
在Spring?boot項目開發(fā)中經(jīng)常遇到需要使用枚舉的場景,本文就介紹了springboot+mybatis+枚舉處理器的實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03
ConstraintValidator類如何實現(xiàn)自定義注解校驗前端傳參
這篇文章主要介紹了ConstraintValidator類實現(xiàn)自定義注解校驗前端傳參的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
SpringCloud中的@FeignClient注解使用詳解
在Spring Cloud中使用Feign進行服務間的調(diào)用時,通常會使用@FeignClient注解來標記Feign客戶端接口,這篇文章給大家介紹SpringCloud中的@FeignClient注解使用詳解,感興趣的朋友一起看看吧2025-06-06
Java的分支結(jié)構(gòu)與循環(huán)你知道多少
這篇文章主要為大家詳細介紹了Java的分支結(jié)構(gòu)與循環(huán),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-02-02

