Comprehensive Java SDK for WeChat MiniApp development with complete platform integration
—
Generate various types of QR codes and mini program codes with customizable styling and parameters. WeChat provides three different interfaces for QR code generation, each with specific use cases and limitations.
Main service for generating mini program codes and traditional QR codes with various customization options.
public interface WxMaQrcodeService {
// Interface A - Mini Program Codes (Limited quantity)
File createWxaCode(String path) throws WxErrorException;
File createWxaCode(String path, int width) throws WxErrorException;
File createWxaCode(String path, String envVersion, int width, boolean autoColor,
WxMaCodeLineColor lineColor, boolean isHyaline) throws WxErrorException;
byte[] createWxaCodeBytes(String path, String envVersion, int width, boolean autoColor,
WxMaCodeLineColor lineColor, boolean isHyaline) throws WxErrorException;
// Interface B - Unlimited Mini Program Codes
File createWxaCodeUnlimit(String scene, String page) throws WxErrorException;
File createWxaCodeUnlimit(String scene, String page, String saveDir) throws WxErrorException;
File createWxaCodeUnlimit(String scene, String page, boolean checkPath, String envVersion,
int width, boolean autoColor, WxMaCodeLineColor lineColor,
boolean isHyaline) throws WxErrorException;
byte[] createWxaCodeUnlimitBytes(String scene, String page, boolean checkPath,
String envVersion, int width, boolean autoColor,
WxMaCodeLineColor lineColor, boolean isHyaline) throws WxErrorException;
// Interface C - Traditional QR Codes (Limited quantity)
File createQrcode(String path, int width) throws WxErrorException;
byte[] createQrcodeBytes(String path, int width) throws WxErrorException;
File createQrcode(String path, int width, String saveDir) throws WxErrorException;
}Customization options for QR code appearance and behavior.
public class WxMaCodeLineColor implements Serializable {
private String r; // Red component (0-255)
private String g; // Green component (0-255)
private String b; // Blue component (0-255)
public WxMaCodeLineColor();
public WxMaCodeLineColor(String r, String g, String b);
// Getters and setters
public String getR();
public void setR(String r);
public String getG();
public void setG(String g);
public String getB();
public void setB(String b);
// Utility methods
public String toJson();
public static WxMaCodeLineColor fromJson(String json);
// Predefined colors
public static WxMaCodeLineColor black() { return new WxMaCodeLineColor("0", "0", "0"); }
public static WxMaCodeLineColor white() { return new WxMaCodeLineColor("255", "255", "255"); }
public static WxMaCodeLineColor red() { return new WxMaCodeLineColor("255", "0", "0"); }
public static WxMaCodeLineColor green() { return new WxMaCodeLineColor("0", "255", "0"); }
public static WxMaCodeLineColor blue() { return new WxMaCodeLineColor("0", "0", "255"); }
}try {
// Basic mini program code - default settings
File qrFile = wxService.getQrcodeService().createWxaCode("pages/index/index");
// Save to specific directory with custom width
File qrFile2 = wxService.getQrcodeService().createWxaCode(
"pages/product/detail?id=123",
280 // Width in pixels
);
logger.info("Mini program code saved to: {}", qrFile2.getAbsolutePath());
} catch (WxErrorException e) {
logger.error("Failed to create mini program code: {}", e.getMessage());
}// Custom color for QR code lines
WxMaCodeLineColor lineColor = new WxMaCodeLineColor("255", "0", "0"); // Red lines
try {
File qrFile = wxService.getQrcodeService().createWxaCode(
"pages/user/profile", // Page path
"release", // Environment: develop, trial, release
430, // Width in pixels (default 430)
false, // Auto color (false = use lineColor)
lineColor, // Custom line color
true // Transparent background
);
logger.info("Styled mini program code created: {}", qrFile.getAbsolutePath());
} catch (WxErrorException e) {
logger.error("Failed to create styled code: {}", e.getMessage());
}try {
byte[] qrBytes = wxService.getQrcodeService().createWxaCodeBytes(
"pages/shop/product?id=456",
"release", // Environment version
300, // Width
true, // Auto color
null, // Line color (null when auto color = true)
false // Not transparent
);
// Save to custom location or return to client
Files.write(Paths.get("/custom/path/qrcode.png"), qrBytes);
// Or return as HTTP response
return ResponseEntity.ok()
.contentType(MediaType.IMAGE_PNG)
.body(qrBytes);
} catch (WxErrorException | IOException e) {
logger.error("Failed to create QR code bytes: {}", e.getMessage());
}// Generate unlimited codes for each user
String userId = "user123";
String scene = "u=" + userId; // Scene parameter (max 32 characters)
try {
File userQR = wxService.getQrcodeService().createWxaCodeUnlimit(
scene, // Scene data
"pages/user/invite" // Landing page
);
// The mini program can retrieve scene data using:
// wx.getLaunchOptionsSync().scene or wx.getEnterOptionsSync().scene
logger.info("User QR code created: {}", userQR.getAbsolutePath());
} catch (WxErrorException e) {
logger.error("Failed to create user QR code: {}", e.getMessage());
}public byte[] generateProductQR(String productId, String color) {
String scene = "pid=" + productId;
// Parse color
WxMaCodeLineColor lineColor = null;
if ("red".equals(color)) {
lineColor = WxMaCodeLineColor.red();
} else if ("blue".equals(color)) {
lineColor = WxMaCodeLineColor.blue();
} else {
lineColor = WxMaCodeLineColor.black();
}
try {
return wxService.getQrcodeService().createWxaCodeUnlimitBytes(
scene, // Product scene data
"pages/product/detail", // Product detail page
true, // Check path validity
"release", // Environment
400, // Width
false, // Manual color (use lineColor)
lineColor, // Custom color
true // Transparent background
);
} catch (WxErrorException e) {
logger.error("Failed to create product QR: {}", e.getMessage());
return null;
}
}@Service
public class QRCodeBulkService {
@Async
public void generateBulkUserCodes(List<String> userIds) {
for (String userId : userIds) {
try {
String scene = "uid=" + userId;
File qrFile = wxService.getQrcodeService().createWxaCodeUnlimit(
scene,
"pages/user/profile",
"/qrcodes/users/" // Save directory
);
// Rename file to include user ID
File namedFile = new File(qrFile.getParent(), "user_" + userId + ".png");
qrFile.renameTo(namedFile);
logger.info("Generated QR for user: {}", userId);
// Small delay to avoid rate limiting
Thread.sleep(100);
} catch (WxErrorException | InterruptedException e) {
logger.error("Failed to generate QR for user {}: {}", userId, e.getMessage());
}
}
}
}try {
// Simple traditional QR code
File traditionalQR = wxService.getQrcodeService().createQrcode(
"pages/home/index",
280 // Width
);
// As byte array
byte[] qrBytes = wxService.getQrcodeService().createQrcodeBytes(
"pages/contact/us",
300
);
logger.info("Traditional QR code created");
} catch (WxErrorException e) {
logger.error("Failed to create traditional QR code: {}", e.getMessage());
}@RestController
@RequestMapping("/api/qr")
public class QRCodeController {
@GetMapping("/product/{productId}")
public ResponseEntity<byte[]> getProductQR(@PathVariable String productId,
@RequestParam(defaultValue = "430") int width,
@RequestParam(defaultValue = "false") boolean transparent) {
try {
String scene = "pid=" + productId + "&src=qr";
byte[] qrBytes = wxService.getQrcodeService().createWxaCodeUnlimitBytes(
scene,
"pages/product/detail",
true, // Check path
"release", // Environment
width,
true, // Auto color
null,
transparent
);
return ResponseEntity.ok()
.contentType(MediaType.IMAGE_PNG)
.header("Cache-Control", "public, max-age=86400") // Cache 1 day
.body(qrBytes);
} catch (WxErrorException e) {
logger.error("Failed to generate product QR: {}", e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
}@Service
public class InvitationService {
public String generateInviteQR(String inviterId, String campaignId) {
String scene = String.format("inv=%s&cmp=%s", inviterId, campaignId);
// Validate scene length (max 32 characters)
if (scene.length() > 32) {
// Use shorter encoding or hash
scene = "inv=" + hashCode(inviterId + campaignId);
}
try {
File qrFile = wxService.getQrcodeService().createWxaCodeUnlimit(
scene,
"pages/invite/landing",
"/tmp/invites/"
);
// Upload to CDN or cloud storage
String qrUrl = uploadToCDN(qrFile);
// Store mapping for analytics
inviteRepository.save(new Invite(inviterId, campaignId, scene, qrUrl));
return qrUrl;
} catch (WxErrorException e) {
logger.error("Failed to generate invite QR: {}", e.getMessage());
throw new QRGenerationException("Could not generate invitation QR code");
}
}
private String hashCode(String input) {
// Simple hash for scene parameter
return Integer.toHexString(input.hashCode()).substring(0, 8);
}
}@Component
public class EventQRGenerator {
public Map<String, Object> generateEventQRs(String eventId, List<String> sessions) {
Map<String, Object> result = new HashMap<>();
List<String> qrUrls = new ArrayList<>();
for (String sessionId : sessions) {
try {
String scene = "evt=" + eventId + "&ses=" + sessionId;
// Custom styling for events
WxMaCodeLineColor eventColor = new WxMaCodeLineColor("0", "123", "255"); // Blue
byte[] qrBytes = wxService.getQrcodeService().createWxaCodeUnlimitBytes(
scene,
"pages/event/checkin",
true, // Check path
"release",
350, // Larger size for scanning
false, // Custom color
eventColor, // Event brand color
false // Solid background
);
// Save with descriptive name
String filename = String.format("event_%s_session_%s.png", eventId, sessionId);
String qrPath = saveQRCode(qrBytes, filename);
qrUrls.add(qrPath);
} catch (WxErrorException e) {
logger.error("Failed to generate QR for event {} session {}: {}",
eventId, sessionId, e.getMessage());
}
}
result.put("eventId", eventId);
result.put("qrCodes", qrUrls);
result.put("count", qrUrls.size());
return result;
}
}public class QRCodeService {
public byte[] generateQRWithFallback(String scene, String page) {
try {
// Try unlimited interface first (preferred)
return wxService.getQrcodeService().createWxaCodeUnlimitBytes(
scene, page, true, "release", 430, true, null, false
);
} catch (WxErrorException e) {
int errorCode = e.getError().getErrorCode();
switch (errorCode) {
case 45009:
logger.warn("API quota exceeded for unlimited codes");
// Fall back to limited interface
return generateLimitedQR(page);
case 41030:
logger.error("Invalid scene parameter: {}", scene);
throw new IllegalArgumentException("Invalid scene parameter");
case 45006:
logger.error("Invalid page path: {}", page);
throw new IllegalArgumentException("Invalid page path");
default:
logger.error("QR generation failed: {} - {}",
errorCode, e.getError().getErrorMsg());
throw new QRGenerationException("Failed to generate QR code", e);
}
}
}
private byte[] generateLimitedQR(String page) {
try {
return wxService.getQrcodeService().createWxaCodeBytes(
page, "release", 430, true, null, false
);
} catch (WxErrorException e) {
logger.error("Fallback QR generation also failed: {}", e.getMessage());
throw new QRGenerationException("All QR generation methods failed", e);
}
}
}@Service
public class OptimizedQRService {
private final RedisTemplate<String, byte[]> redisTemplate;
private final ExecutorService qrExecutor = Executors.newFixedThreadPool(5);
@Cacheable(value = "qrcodes", key = "#scene + '_' + #page + '_' + #width")
public byte[] getCachedQR(String scene, String page, int width) {
try {
return wxService.getQrcodeService().createWxaCodeUnlimitBytes(
scene, page, true, "release", width, true, null, false
);
} catch (WxErrorException e) {
logger.error("QR generation failed: {}", e.getMessage());
return null;
}
}
@Async
public CompletableFuture<String> generateQRAsync(String scene, String page) {
return CompletableFuture.supplyAsync(() -> {
try {
File qrFile = wxService.getQrcodeService().createWxaCodeUnlimit(scene, page);
return uploadToStorage(qrFile);
} catch (WxErrorException e) {
logger.error("Async QR generation failed: {}", e.getMessage());
return null;
}
}, qrExecutor);
}
}This QR code service provides comprehensive code generation capabilities with proper error handling, caching strategies, and support for all WeChat QR code interfaces.
Install with Tessl CLI
npx tessl i tessl/maven-com-github-binarywang--weixin-java-miniapp