0
# QR Code Generation
1
2
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.
3
4
## Capabilities
5
6
### QR Code Service Interface
7
8
Main service for generating mini program codes and traditional QR codes with various customization options.
9
10
```java { .api }
11
public interface WxMaQrcodeService {
12
// Interface A - Mini Program Codes (Limited quantity)
13
File createWxaCode(String path) throws WxErrorException;
14
File createWxaCode(String path, int width) throws WxErrorException;
15
File createWxaCode(String path, String envVersion, int width, boolean autoColor,
16
WxMaCodeLineColor lineColor, boolean isHyaline) throws WxErrorException;
17
18
byte[] createWxaCodeBytes(String path, String envVersion, int width, boolean autoColor,
19
WxMaCodeLineColor lineColor, boolean isHyaline) throws WxErrorException;
20
21
// Interface B - Unlimited Mini Program Codes
22
File createWxaCodeUnlimit(String scene, String page) throws WxErrorException;
23
File createWxaCodeUnlimit(String scene, String page, String saveDir) throws WxErrorException;
24
File createWxaCodeUnlimit(String scene, String page, boolean checkPath, String envVersion,
25
int width, boolean autoColor, WxMaCodeLineColor lineColor,
26
boolean isHyaline) throws WxErrorException;
27
28
byte[] createWxaCodeUnlimitBytes(String scene, String page, boolean checkPath,
29
String envVersion, int width, boolean autoColor,
30
WxMaCodeLineColor lineColor, boolean isHyaline) throws WxErrorException;
31
32
// Interface C - Traditional QR Codes (Limited quantity)
33
File createQrcode(String path, int width) throws WxErrorException;
34
byte[] createQrcodeBytes(String path, int width) throws WxErrorException;
35
File createQrcode(String path, int width, String saveDir) throws WxErrorException;
36
}
37
```
38
39
### QR Code Styling
40
41
Customization options for QR code appearance and behavior.
42
43
```java { .api }
44
public class WxMaCodeLineColor implements Serializable {
45
private String r; // Red component (0-255)
46
private String g; // Green component (0-255)
47
private String b; // Blue component (0-255)
48
49
public WxMaCodeLineColor();
50
public WxMaCodeLineColor(String r, String g, String b);
51
52
// Getters and setters
53
public String getR();
54
public void setR(String r);
55
public String getG();
56
public void setG(String g);
57
public String getB();
58
public void setB(String b);
59
60
// Utility methods
61
public String toJson();
62
public static WxMaCodeLineColor fromJson(String json);
63
64
// Predefined colors
65
public static WxMaCodeLineColor black() { return new WxMaCodeLineColor("0", "0", "0"); }
66
public static WxMaCodeLineColor white() { return new WxMaCodeLineColor("255", "255", "255"); }
67
public static WxMaCodeLineColor red() { return new WxMaCodeLineColor("255", "0", "0"); }
68
public static WxMaCodeLineColor green() { return new WxMaCodeLineColor("0", "255", "0"); }
69
public static WxMaCodeLineColor blue() { return new WxMaCodeLineColor("0", "0", "255"); }
70
}
71
```
72
73
## Interface Differences & Use Cases
74
75
### Interface A - Mini Program Codes (createWxaCode)
76
- **Limit**: Combined with Interface C, maximum 100,000 codes total
77
- **Use Case**: Static pages, limited scenarios
78
- **Parameters**: Direct path to mini program page
79
- **Best For**: Fixed navigation, menu items, static content
80
81
### Interface B - Unlimited Codes (createWxaCodeUnlimit)
82
- **Limit**: Unlimited generation
83
- **Use Case**: Dynamic content, user-specific codes, mass generation
84
- **Parameters**: Scene parameter (custom data up to 32 characters)
85
- **Best For**: User profiles, dynamic content, personalized sharing
86
87
### Interface C - Traditional QR Codes (createQrcode)
88
- **Limit**: Combined with Interface A, maximum 100,000 codes total
89
- **Use Case**: Traditional QR code appearance
90
- **Parameters**: Direct path to mini program page
91
- **Best For**: Print materials, traditional QR code scanners
92
93
## Usage Examples
94
95
### Basic Mini Program Code Generation
96
97
#### Simple Mini Program Code (Interface A)
98
99
```java
100
try {
101
// Basic mini program code - default settings
102
File qrFile = wxService.getQrcodeService().createWxaCode("pages/index/index");
103
104
// Save to specific directory with custom width
105
File qrFile2 = wxService.getQrcodeService().createWxaCode(
106
"pages/product/detail?id=123",
107
280 // Width in pixels
108
);
109
110
logger.info("Mini program code saved to: {}", qrFile2.getAbsolutePath());
111
112
} catch (WxErrorException e) {
113
logger.error("Failed to create mini program code: {}", e.getMessage());
114
}
115
```
116
117
#### Advanced Mini Program Code with Styling
118
119
```java
120
// Custom color for QR code lines
121
WxMaCodeLineColor lineColor = new WxMaCodeLineColor("255", "0", "0"); // Red lines
122
123
try {
124
File qrFile = wxService.getQrcodeService().createWxaCode(
125
"pages/user/profile", // Page path
126
"release", // Environment: develop, trial, release
127
430, // Width in pixels (default 430)
128
false, // Auto color (false = use lineColor)
129
lineColor, // Custom line color
130
true // Transparent background
131
);
132
133
logger.info("Styled mini program code created: {}", qrFile.getAbsolutePath());
134
135
} catch (WxErrorException e) {
136
logger.error("Failed to create styled code: {}", e.getMessage());
137
}
138
```
139
140
#### Get QR Code as Byte Array
141
142
```java
143
try {
144
byte[] qrBytes = wxService.getQrcodeService().createWxaCodeBytes(
145
"pages/shop/product?id=456",
146
"release", // Environment version
147
300, // Width
148
true, // Auto color
149
null, // Line color (null when auto color = true)
150
false // Not transparent
151
);
152
153
// Save to custom location or return to client
154
Files.write(Paths.get("/custom/path/qrcode.png"), qrBytes);
155
156
// Or return as HTTP response
157
return ResponseEntity.ok()
158
.contentType(MediaType.IMAGE_PNG)
159
.body(qrBytes);
160
161
} catch (WxErrorException | IOException e) {
162
logger.error("Failed to create QR code bytes: {}", e.getMessage());
163
}
164
```
165
166
### Unlimited Mini Program Codes (Interface B)
167
168
#### User-Specific QR Codes
169
170
```java
171
// Generate unlimited codes for each user
172
String userId = "user123";
173
String scene = "u=" + userId; // Scene parameter (max 32 characters)
174
175
try {
176
File userQR = wxService.getQrcodeService().createWxaCodeUnlimit(
177
scene, // Scene data
178
"pages/user/invite" // Landing page
179
);
180
181
// The mini program can retrieve scene data using:
182
// wx.getLaunchOptionsSync().scene or wx.getEnterOptionsSync().scene
183
184
logger.info("User QR code created: {}", userQR.getAbsolutePath());
185
186
} catch (WxErrorException e) {
187
logger.error("Failed to create user QR code: {}", e.getMessage());
188
}
189
```
190
191
#### Product QR Codes with Custom Styling
192
193
```java
194
public byte[] generateProductQR(String productId, String color) {
195
String scene = "pid=" + productId;
196
197
// Parse color
198
WxMaCodeLineColor lineColor = null;
199
if ("red".equals(color)) {
200
lineColor = WxMaCodeLineColor.red();
201
} else if ("blue".equals(color)) {
202
lineColor = WxMaCodeLineColor.blue();
203
} else {
204
lineColor = WxMaCodeLineColor.black();
205
}
206
207
try {
208
return wxService.getQrcodeService().createWxaCodeUnlimitBytes(
209
scene, // Product scene data
210
"pages/product/detail", // Product detail page
211
true, // Check path validity
212
"release", // Environment
213
400, // Width
214
false, // Manual color (use lineColor)
215
lineColor, // Custom color
216
true // Transparent background
217
);
218
219
} catch (WxErrorException e) {
220
logger.error("Failed to create product QR: {}", e.getMessage());
221
return null;
222
}
223
}
224
```
225
226
#### Bulk QR Code Generation
227
228
```java
229
@Service
230
public class QRCodeBulkService {
231
232
@Async
233
public void generateBulkUserCodes(List<String> userIds) {
234
for (String userId : userIds) {
235
try {
236
String scene = "uid=" + userId;
237
238
File qrFile = wxService.getQrcodeService().createWxaCodeUnlimit(
239
scene,
240
"pages/user/profile",
241
"/qrcodes/users/" // Save directory
242
);
243
244
// Rename file to include user ID
245
File namedFile = new File(qrFile.getParent(), "user_" + userId + ".png");
246
qrFile.renameTo(namedFile);
247
248
logger.info("Generated QR for user: {}", userId);
249
250
// Small delay to avoid rate limiting
251
Thread.sleep(100);
252
253
} catch (WxErrorException | InterruptedException e) {
254
logger.error("Failed to generate QR for user {}: {}", userId, e.getMessage());
255
}
256
}
257
}
258
}
259
```
260
261
### Traditional QR Codes (Interface C)
262
263
```java
264
try {
265
// Simple traditional QR code
266
File traditionalQR = wxService.getQrcodeService().createQrcode(
267
"pages/home/index",
268
280 // Width
269
);
270
271
// As byte array
272
byte[] qrBytes = wxService.getQrcodeService().createQrcodeBytes(
273
"pages/contact/us",
274
300
275
);
276
277
logger.info("Traditional QR code created");
278
279
} catch (WxErrorException e) {
280
logger.error("Failed to create traditional QR code: {}", e.getMessage());
281
}
282
```
283
284
### Practical Examples
285
286
#### E-commerce Product QR Codes
287
288
```java
289
@RestController
290
@RequestMapping("/api/qr")
291
public class QRCodeController {
292
293
@GetMapping("/product/{productId}")
294
public ResponseEntity<byte[]> getProductQR(@PathVariable String productId,
295
@RequestParam(defaultValue = "430") int width,
296
@RequestParam(defaultValue = "false") boolean transparent) {
297
try {
298
String scene = "pid=" + productId + "&src=qr";
299
300
byte[] qrBytes = wxService.getQrcodeService().createWxaCodeUnlimitBytes(
301
scene,
302
"pages/product/detail",
303
true, // Check path
304
"release", // Environment
305
width,
306
true, // Auto color
307
null,
308
transparent
309
);
310
311
return ResponseEntity.ok()
312
.contentType(MediaType.IMAGE_PNG)
313
.header("Cache-Control", "public, max-age=86400") // Cache 1 day
314
.body(qrBytes);
315
316
} catch (WxErrorException e) {
317
logger.error("Failed to generate product QR: {}", e.getMessage());
318
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
319
}
320
}
321
}
322
```
323
324
#### User Invitation System
325
326
```java
327
@Service
328
public class InvitationService {
329
330
public String generateInviteQR(String inviterId, String campaignId) {
331
String scene = String.format("inv=%s&cmp=%s", inviterId, campaignId);
332
333
// Validate scene length (max 32 characters)
334
if (scene.length() > 32) {
335
// Use shorter encoding or hash
336
scene = "inv=" + hashCode(inviterId + campaignId);
337
}
338
339
try {
340
File qrFile = wxService.getQrcodeService().createWxaCodeUnlimit(
341
scene,
342
"pages/invite/landing",
343
"/tmp/invites/"
344
);
345
346
// Upload to CDN or cloud storage
347
String qrUrl = uploadToCDN(qrFile);
348
349
// Store mapping for analytics
350
inviteRepository.save(new Invite(inviterId, campaignId, scene, qrUrl));
351
352
return qrUrl;
353
354
} catch (WxErrorException e) {
355
logger.error("Failed to generate invite QR: {}", e.getMessage());
356
throw new QRGenerationException("Could not generate invitation QR code");
357
}
358
}
359
360
private String hashCode(String input) {
361
// Simple hash for scene parameter
362
return Integer.toHexString(input.hashCode()).substring(0, 8);
363
}
364
}
365
```
366
367
#### Event Check-in QR Codes
368
369
```java
370
@Component
371
public class EventQRGenerator {
372
373
public Map<String, Object> generateEventQRs(String eventId, List<String> sessions) {
374
Map<String, Object> result = new HashMap<>();
375
List<String> qrUrls = new ArrayList<>();
376
377
for (String sessionId : sessions) {
378
try {
379
String scene = "evt=" + eventId + "&ses=" + sessionId;
380
381
// Custom styling for events
382
WxMaCodeLineColor eventColor = new WxMaCodeLineColor("0", "123", "255"); // Blue
383
384
byte[] qrBytes = wxService.getQrcodeService().createWxaCodeUnlimitBytes(
385
scene,
386
"pages/event/checkin",
387
true, // Check path
388
"release",
389
350, // Larger size for scanning
390
false, // Custom color
391
eventColor, // Event brand color
392
false // Solid background
393
);
394
395
// Save with descriptive name
396
String filename = String.format("event_%s_session_%s.png", eventId, sessionId);
397
String qrPath = saveQRCode(qrBytes, filename);
398
qrUrls.add(qrPath);
399
400
} catch (WxErrorException e) {
401
logger.error("Failed to generate QR for event {} session {}: {}",
402
eventId, sessionId, e.getMessage());
403
}
404
}
405
406
result.put("eventId", eventId);
407
result.put("qrCodes", qrUrls);
408
result.put("count", qrUrls.size());
409
410
return result;
411
}
412
}
413
```
414
415
### Error Handling
416
417
```java
418
public class QRCodeService {
419
420
public byte[] generateQRWithFallback(String scene, String page) {
421
try {
422
// Try unlimited interface first (preferred)
423
return wxService.getQrcodeService().createWxaCodeUnlimitBytes(
424
scene, page, true, "release", 430, true, null, false
425
);
426
427
} catch (WxErrorException e) {
428
int errorCode = e.getError().getErrorCode();
429
430
switch (errorCode) {
431
case 45009:
432
logger.warn("API quota exceeded for unlimited codes");
433
// Fall back to limited interface
434
return generateLimitedQR(page);
435
436
case 41030:
437
logger.error("Invalid scene parameter: {}", scene);
438
throw new IllegalArgumentException("Invalid scene parameter");
439
440
case 45006:
441
logger.error("Invalid page path: {}", page);
442
throw new IllegalArgumentException("Invalid page path");
443
444
default:
445
logger.error("QR generation failed: {} - {}",
446
errorCode, e.getError().getErrorMsg());
447
throw new QRGenerationException("Failed to generate QR code", e);
448
}
449
}
450
}
451
452
private byte[] generateLimitedQR(String page) {
453
try {
454
return wxService.getQrcodeService().createWxaCodeBytes(
455
page, "release", 430, true, null, false
456
);
457
} catch (WxErrorException e) {
458
logger.error("Fallback QR generation also failed: {}", e.getMessage());
459
throw new QRGenerationException("All QR generation methods failed", e);
460
}
461
}
462
}
463
```
464
465
### Performance Optimization
466
467
```java
468
@Service
469
public class OptimizedQRService {
470
471
private final RedisTemplate<String, byte[]> redisTemplate;
472
private final ExecutorService qrExecutor = Executors.newFixedThreadPool(5);
473
474
@Cacheable(value = "qrcodes", key = "#scene + '_' + #page + '_' + #width")
475
public byte[] getCachedQR(String scene, String page, int width) {
476
try {
477
return wxService.getQrcodeService().createWxaCodeUnlimitBytes(
478
scene, page, true, "release", width, true, null, false
479
);
480
} catch (WxErrorException e) {
481
logger.error("QR generation failed: {}", e.getMessage());
482
return null;
483
}
484
}
485
486
@Async
487
public CompletableFuture<String> generateQRAsync(String scene, String page) {
488
return CompletableFuture.supplyAsync(() -> {
489
try {
490
File qrFile = wxService.getQrcodeService().createWxaCodeUnlimit(scene, page);
491
return uploadToStorage(qrFile);
492
} catch (WxErrorException e) {
493
logger.error("Async QR generation failed: {}", e.getMessage());
494
return null;
495
}
496
}, qrExecutor);
497
}
498
}
499
```
500
501
This QR code service provides comprehensive code generation capabilities with proper error handling, caching strategies, and support for all WeChat QR code interfaces.