0
# Media & Content
1
2
Media file management, content security, and content moderation services for images, videos, audio files, and other media types in WeChat MiniApp applications.
3
4
## Capabilities
5
6
### Media Service Interface
7
8
Core media operations for uploading, managing, and processing media files.
9
10
```java { .api }
11
public interface WxMaMediaService {
12
// Media Upload
13
WxMediaUploadResult uploadMedia(String type, File media) throws WxErrorException;
14
WxMediaUploadResult uploadMedia(String type, InputStream inputStream, String fileName) throws WxErrorException;
15
16
// Media Download
17
File downloadMedia(String mediaId, File file) throws WxErrorException;
18
InputStream downloadMedia(String mediaId) throws WxErrorException;
19
20
// Temporary Media (3 days retention)
21
WxMediaUploadResult uploadTempMedia(String type, File media) throws WxErrorException;
22
WxMediaUploadResult uploadTempMedia(String type, InputStream inputStream, String fileName) throws WxErrorException;
23
24
// Image Upload (permanent)
25
WxMediaUploadResult uploadImg(File media) throws WxErrorException;
26
WxMediaUploadResult uploadImg(InputStream inputStream, String fileName) throws WxErrorException;
27
}
28
```
29
30
### Security Service Interface
31
32
Content security and moderation operations for text, images, and other media content.
33
34
```java { .api }
35
public interface WxMaSecurityService {
36
// Text Security Check
37
boolean checkText(String content) throws WxErrorException;
38
boolean checkText(String content, Integer scene, Integer version) throws WxErrorException;
39
40
// Image Security Check
41
boolean checkImage(File imageFile) throws WxErrorException;
42
boolean checkImage(String mediaId) throws WxErrorException;
43
boolean checkImage(InputStream inputStream, String fileName) throws WxErrorException;
44
45
// Audio Security Check
46
boolean checkAudio(File audioFile) throws WxErrorException;
47
boolean checkAudio(String mediaId) throws WxErrorException;
48
49
// User Risk Assessment
50
WxMaUserRiskRank getUserRiskRank(String openid, Integer scene) throws WxErrorException;
51
}
52
```
53
54
### Media Upload Models
55
56
Data models for media upload operations and responses.
57
58
```java { .api }
59
public class WxMediaUploadResult implements Serializable {
60
private String type; // Media type (image, voice, video, thumb)
61
private String mediaId; // Media ID for subsequent operations
62
private Long createdAt; // Upload timestamp
63
private String url; // Media URL (for permanent images)
64
65
// Getters and setters
66
public String getType();
67
public void setType(String type);
68
public String getMediaId();
69
public void setMediaId(String mediaId);
70
public Long getCreatedAt();
71
public void setCreatedAt(Long createdAt);
72
public String getUrl();
73
public void setUrl(String url);
74
75
// Utility methods
76
public Date getCreatedAtAsDate();
77
public static WxMediaUploadResult fromJson(String json);
78
public String toJson();
79
}
80
```
81
82
### Security Check Models
83
84
Data models for content security and user risk assessment.
85
86
```java { .api }
87
public class WxMaSecurityCheckResult implements Serializable {
88
private Integer errCode; // Error code (0: pass, 87014: risky content)
89
private String errMsg; // Error message
90
private String traceId; // Trace ID for tracking
91
private SecurityResult result; // Detailed security check result
92
93
public static class SecurityResult {
94
private String suggest; // Suggestion (pass, review, risky)
95
private String label; // Risk label (if any)
96
97
public String getSuggest();
98
public void setSuggest(String suggest);
99
public String getLabel();
100
public void setLabel(String label);
101
}
102
103
// Getters and setters
104
public Integer getErrCode();
105
public void setErrCode(Integer errCode);
106
public String getErrMsg();
107
public void setErrMsg(String errMsg);
108
public String getTraceId();
109
public void setTraceId(String traceId);
110
public SecurityResult getResult();
111
public void setResult(SecurityResult result);
112
113
// Convenience methods
114
public boolean isPassed();
115
public boolean isRisky();
116
public boolean needsReview();
117
}
118
119
public class WxMaUserRiskRank implements Serializable {
120
private Integer riskRank; // Risk rank (0: normal, 1-4: increasing risk levels)
121
private String openid; // User OpenID
122
private Long timestamp; // Assessment timestamp
123
124
// Getters and setters
125
public Integer getRiskRank();
126
public void setRiskRank(Integer riskRank);
127
public String getOpenid();
128
public void setOpenid(String openid);
129
public Long getTimestamp();
130
public void setTimestamp(Long timestamp);
131
132
// Convenience methods
133
public boolean isHighRisk();
134
public boolean isNormalRisk();
135
public String getRiskLevel();
136
}
137
```
138
139
### Media Type Constants
140
141
Constants for different media types and security check parameters.
142
143
```java { .api }
144
public class WxMaMediaConstants {
145
// Media Types
146
public static final String IMAGE = "image";
147
public static final String VOICE = "voice";
148
public static final String VIDEO = "video";
149
public static final String THUMB = "thumb";
150
151
// Security Check Scenes
152
public static final Integer SCENE_SOCIAL = 1; // Social scenarios
153
public static final Integer SCENE_COMMENT = 2; // Comment scenarios
154
public static final Integer SCENE_FORUM = 3; // Forum scenarios
155
public static final Integer SCENE_OPEN_API = 4; // Open API scenarios
156
157
// Security Check Versions
158
public static final Integer VERSION_LATEST = 2; // Latest version
159
160
// Risk Levels
161
public static final Integer RISK_NORMAL = 0; // Normal user
162
public static final Integer RISK_LOW = 1; // Low risk
163
public static final Integer RISK_MEDIUM = 2; // Medium risk
164
public static final Integer RISK_HIGH = 3; // High risk
165
public static final Integer RISK_VERY_HIGH = 4; // Very high risk
166
}
167
```
168
169
## Usage Examples
170
171
### Media Upload and Management
172
173
#### Upload Images
174
175
```java
176
@Service
177
public class MediaUploadService {
178
179
@Autowired
180
private WxMaService wxMaService;
181
182
public String uploadUserAvatar(File avatarFile) {
183
try {
184
// Upload as permanent image (no expiration)
185
WxMediaUploadResult result = wxMaService.getMediaService()
186
.uploadImg(avatarFile);
187
188
String mediaUrl = result.getUrl();
189
logger.info("Avatar uploaded successfully: {}", mediaUrl);
190
191
return mediaUrl;
192
193
} catch (WxErrorException e) {
194
logger.error("Avatar upload failed: {}", e.getMessage());
195
throw new MediaUploadException("Failed to upload avatar", e);
196
}
197
}
198
199
public String uploadTemporaryImage(MultipartFile file) {
200
try {
201
// Upload as temporary media (3 days retention)
202
WxMediaUploadResult result = wxMaService.getMediaService()
203
.uploadTempMedia(WxMaMediaConstants.IMAGE,
204
file.getInputStream(),
205
file.getOriginalFilename());
206
207
String mediaId = result.getMediaId();
208
logger.info("Temporary image uploaded: {}", mediaId);
209
210
return mediaId;
211
212
} catch (WxErrorException | IOException e) {
213
logger.error("Temporary image upload failed: {}", e.getMessage());
214
throw new MediaUploadException("Failed to upload temporary image", e);
215
}
216
}
217
218
public String uploadProductImage(File productImage) {
219
try {
220
// First check image content for security
221
boolean isSecure = wxMaService.getSecurityService()
222
.checkImage(productImage);
223
224
if (!isSecure) {
225
throw new SecurityCheckException("Image contains inappropriate content");
226
}
227
228
// Upload if security check passes
229
WxMediaUploadResult result = wxMaService.getMediaService()
230
.uploadImg(productImage);
231
232
return result.getUrl();
233
234
} catch (WxErrorException e) {
235
logger.error("Product image upload failed: {}", e.getMessage());
236
throw new MediaUploadException("Failed to upload product image", e);
237
}
238
}
239
}
240
```
241
242
#### Upload Audio and Video
243
244
```java
245
public class MultiMediaService {
246
247
public String uploadVoiceMessage(File voiceFile) {
248
try {
249
// Check audio content first
250
boolean isSecure = wxMaService.getSecurityService()
251
.checkAudio(voiceFile);
252
253
if (!isSecure) {
254
throw new SecurityCheckException("Audio contains inappropriate content");
255
}
256
257
// Upload voice as temporary media
258
WxMediaUploadResult result = wxMaService.getMediaService()
259
.uploadTempMedia(WxMaMediaConstants.VOICE, voiceFile);
260
261
String mediaId = result.getMediaId();
262
logger.info("Voice message uploaded: {}", mediaId);
263
264
return mediaId;
265
266
} catch (WxErrorException e) {
267
logger.error("Voice upload failed: {}", e.getMessage());
268
throw new MediaUploadException("Failed to upload voice message", e);
269
}
270
}
271
272
public String uploadVideo(File videoFile) {
273
try {
274
// Upload video as temporary media
275
WxMediaUploadResult result = wxMaService.getMediaService()
276
.uploadTempMedia(WxMaMediaConstants.VIDEO, videoFile);
277
278
String mediaId = result.getMediaId();
279
logger.info("Video uploaded: {}", mediaId);
280
281
return mediaId;
282
283
} catch (WxErrorException e) {
284
logger.error("Video upload failed: {}", e.getMessage());
285
throw new MediaUploadException("Failed to upload video", e);
286
}
287
}
288
289
public String uploadThumbnail(File thumbnailFile) {
290
try {
291
// Upload thumbnail for video
292
WxMediaUploadResult result = wxMaService.getMediaService()
293
.uploadTempMedia(WxMaMediaConstants.THUMB, thumbnailFile);
294
295
return result.getMediaId();
296
297
} catch (WxErrorException e) {
298
logger.error("Thumbnail upload failed: {}", e.getMessage());
299
throw new MediaUploadException("Failed to upload thumbnail", e);
300
}
301
}
302
}
303
```
304
305
#### Media Download and Processing
306
307
```java
308
public class MediaDownloadService {
309
310
public File downloadMedia(String mediaId, String targetDirectory) {
311
try {
312
// Create target file
313
File targetFile = new File(targetDirectory, "media_" + mediaId + ".dat");
314
315
// Download media
316
File downloadedFile = wxMaService.getMediaService()
317
.downloadMedia(mediaId, targetFile);
318
319
logger.info("Media downloaded: {} -> {}", mediaId, downloadedFile.getPath());
320
return downloadedFile;
321
322
} catch (WxErrorException e) {
323
logger.error("Media download failed for {}: {}", mediaId, e.getMessage());
324
throw new MediaDownloadException("Failed to download media", e);
325
}
326
}
327
328
public byte[] downloadMediaAsBytes(String mediaId) {
329
try (InputStream inputStream = wxMaService.getMediaService().downloadMedia(mediaId)) {
330
return IOUtils.toByteArray(inputStream);
331
332
} catch (WxErrorException | IOException e) {
333
logger.error("Media download as bytes failed for {}: {}", mediaId, e.getMessage());
334
throw new MediaDownloadException("Failed to download media as bytes", e);
335
}
336
}
337
338
@Async
339
public CompletableFuture<String> processAndUpload(File originalFile, ImageProcessingOptions options) {
340
return CompletableFuture.supplyAsync(() -> {
341
try {
342
// Process image (resize, crop, etc.)
343
File processedFile = imageProcessor.process(originalFile, options);
344
345
// Upload processed image
346
WxMediaUploadResult result = wxMaService.getMediaService()
347
.uploadImg(processedFile);
348
349
// Clean up temporary file
350
processedFile.delete();
351
352
return result.getUrl();
353
354
} catch (Exception e) {
355
logger.error("Async media processing failed: {}", e.getMessage());
356
return null;
357
}
358
});
359
}
360
}
361
```
362
363
### Content Security and Moderation
364
365
#### Text Content Security Check
366
367
```java
368
@Service
369
public class ContentModerationService {
370
371
public boolean checkTextContent(String content, ContentScene scene) {
372
try {
373
Integer sceneCode = getSceneCode(scene);
374
375
boolean isSecure = wxMaService.getSecurityService()
376
.checkText(content, sceneCode, WxMaMediaConstants.VERSION_LATEST);
377
378
if (!isSecure) {
379
logger.warn("Text content failed security check: {}",
380
content.substring(0, Math.min(50, content.length())));
381
}
382
383
return isSecure;
384
385
} catch (WxErrorException e) {
386
logger.error("Text security check failed: {}", e.getMessage());
387
// Default to rejecting on error for safety
388
return false;
389
}
390
}
391
392
public ContentModerationResult moderateUserComment(String comment, String openid) {
393
try {
394
// Check text content
395
boolean textSecure = wxMaService.getSecurityService()
396
.checkText(comment, WxMaMediaConstants.SCENE_COMMENT,
397
WxMaMediaConstants.VERSION_LATEST);
398
399
// Check user risk level
400
WxMaUserRiskRank userRisk = wxMaService.getSecurityService()
401
.getUserRiskRank(openid, WxMaMediaConstants.SCENE_COMMENT);
402
403
ContentModerationResult result = new ContentModerationResult();
404
result.setTextSecure(textSecure);
405
result.setUserRiskLevel(userRisk.getRiskRank());
406
result.setApproved(textSecure && !userRisk.isHighRisk());
407
408
if (result.isApproved()) {
409
result.setAction("approve");
410
} else if (!textSecure) {
411
result.setAction("reject_content");
412
} else if (userRisk.isHighRisk()) {
413
result.setAction("manual_review");
414
}
415
416
return result;
417
418
} catch (WxErrorException e) {
419
logger.error("Comment moderation failed: {}", e.getMessage());
420
// Default to manual review on error
421
ContentModerationResult result = new ContentModerationResult();
422
result.setAction("manual_review");
423
result.setApproved(false);
424
return result;
425
}
426
}
427
428
private Integer getSceneCode(ContentScene scene) {
429
switch (scene) {
430
case SOCIAL: return WxMaMediaConstants.SCENE_SOCIAL;
431
case COMMENT: return WxMaMediaConstants.SCENE_COMMENT;
432
case FORUM: return WxMaMediaConstants.SCENE_FORUM;
433
case OPEN_API: return WxMaMediaConstants.SCENE_OPEN_API;
434
default: return WxMaMediaConstants.SCENE_SOCIAL;
435
}
436
}
437
}
438
```
439
440
#### Image Content Security Check
441
442
```java
443
public class ImageModerationService {
444
445
public boolean checkUploadedImage(MultipartFile imageFile) {
446
try {
447
// Check image content
448
boolean isSecure = wxMaService.getSecurityService()
449
.checkImage(imageFile.getInputStream(), imageFile.getOriginalFilename());
450
451
if (!isSecure) {
452
logger.warn("Uploaded image failed security check: {}",
453
imageFile.getOriginalFilename());
454
}
455
456
return isSecure;
457
458
} catch (WxErrorException | IOException e) {
459
logger.error("Image security check failed: {}", e.getMessage());
460
return false;
461
}
462
}
463
464
public ImageModerationResult moderateUserAvatar(File avatarFile, String openid) {
465
try {
466
// Check image content
467
boolean imageSecure = wxMaService.getSecurityService()
468
.checkImage(avatarFile);
469
470
// Check user risk level
471
WxMaUserRiskRank userRisk = wxMaService.getSecurityService()
472
.getUserRiskRank(openid, WxMaMediaConstants.SCENE_SOCIAL);
473
474
ImageModerationResult result = new ImageModerationResult();
475
result.setImageSecure(imageSecure);
476
result.setUserRiskLevel(userRisk.getRiskRank());
477
478
// Decision logic
479
if (imageSecure && userRisk.getRiskRank() <= WxMaMediaConstants.RISK_LOW) {
480
result.setApproved(true);
481
result.setAction("approve");
482
} else if (!imageSecure) {
483
result.setApproved(false);
484
result.setAction("reject_inappropriate");
485
} else {
486
result.setApproved(false);
487
result.setAction("manual_review");
488
}
489
490
return result;
491
492
} catch (WxErrorException e) {
493
logger.error("Avatar moderation failed: {}", e.getMessage());
494
ImageModerationResult result = new ImageModerationResult();
495
result.setApproved(false);
496
result.setAction("error_occurred");
497
return result;
498
}
499
}
500
501
@Async
502
public void batchCheckImages(List<String> mediaIds) {
503
for (String mediaId : mediaIds) {
504
try {
505
boolean isSecure = wxMaService.getSecurityService()
506
.checkImage(mediaId);
507
508
// Update database with security status
509
mediaSecurityRepository.updateSecurityStatus(mediaId, isSecure);
510
511
if (!isSecure) {
512
// Handle inappropriate content
513
handleInappropriateMedia(mediaId);
514
}
515
516
// Rate limiting - small delay between checks
517
Thread.sleep(100);
518
519
} catch (WxErrorException | InterruptedException e) {
520
logger.error("Batch image check failed for {}: {}", mediaId, e.getMessage());
521
}
522
}
523
}
524
}
525
```
526
527
### User Risk Assessment
528
529
```java
530
@Service
531
public class UserRiskAssessmentService {
532
533
public UserRiskProfile assessUserRisk(String openid, RiskAssessmentContext context) {
534
try {
535
Integer scene = getSceneFromContext(context);
536
537
WxMaUserRiskRank riskResult = wxMaService.getSecurityService()
538
.getUserRiskRank(openid, scene);
539
540
UserRiskProfile profile = new UserRiskProfile();
541
profile.setOpenid(openid);
542
profile.setRiskRank(riskResult.getRiskRank());
543
profile.setRiskLevel(getRiskLevelDescription(riskResult.getRiskRank()));
544
profile.setAssessmentTime(new Date(riskResult.getTimestamp() * 1000));
545
profile.setRecommendations(generateRecommendations(riskResult.getRiskRank()));
546
547
// Store assessment for future reference
548
userRiskRepository.save(profile);
549
550
return profile;
551
552
} catch (WxErrorException e) {
553
logger.error("User risk assessment failed for {}: {}", openid, e.getMessage());
554
555
// Return default safe assessment on error
556
UserRiskProfile profile = new UserRiskProfile();
557
profile.setOpenid(openid);
558
profile.setRiskRank(WxMaMediaConstants.RISK_MEDIUM);
559
profile.setRiskLevel("Unknown (Assessment Failed)");
560
profile.setAssessmentTime(new Date());
561
return profile;
562
}
563
}
564
565
public boolean shouldAllowOperation(String openid, UserOperation operation) {
566
try {
567
Integer scene = getSceneFromOperation(operation);
568
WxMaUserRiskRank riskResult = wxMaService.getSecurityService()
569
.getUserRiskRank(openid, scene);
570
571
// Define operation permissions based on risk level
572
switch (operation) {
573
case POST_COMMENT:
574
return riskResult.getRiskRank() <= WxMaMediaConstants.RISK_MEDIUM;
575
case UPLOAD_IMAGE:
576
return riskResult.getRiskRank() <= WxMaMediaConstants.RISK_HIGH;
577
case SEND_MESSAGE:
578
return riskResult.getRiskRank() <= WxMaMediaConstants.RISK_LOW;
579
case CREATE_CONTENT:
580
return riskResult.getRiskRank() <= WxMaMediaConstants.RISK_MEDIUM;
581
default:
582
return riskResult.getRiskRank() <= WxMaMediaConstants.RISK_LOW;
583
}
584
585
} catch (WxErrorException e) {
586
logger.error("Risk check failed for {} operation {}: {}",
587
openid, operation, e.getMessage());
588
// Default to disallow on error for safety
589
return false;
590
}
591
}
592
593
private String getRiskLevelDescription(Integer riskRank) {
594
switch (riskRank) {
595
case 0: return "Normal";
596
case 1: return "Low Risk";
597
case 2: return "Medium Risk";
598
case 3: return "High Risk";
599
case 4: return "Very High Risk";
600
default: return "Unknown";
601
}
602
}
603
604
private List<String> generateRecommendations(Integer riskRank) {
605
List<String> recommendations = new ArrayList<>();
606
607
if (riskRank >= WxMaMediaConstants.RISK_MEDIUM) {
608
recommendations.add("Enable manual review for user-generated content");
609
recommendations.add("Increase monitoring frequency");
610
}
611
612
if (riskRank >= WxMaMediaConstants.RISK_HIGH) {
613
recommendations.add("Restrict content creation abilities");
614
recommendations.add("Require additional verification");
615
}
616
617
if (riskRank >= WxMaMediaConstants.RISK_VERY_HIGH) {
618
recommendations.add("Consider temporary restrictions");
619
recommendations.add("Flag for admin review");
620
}
621
622
return recommendations;
623
}
624
}
625
```
626
627
### Media Processing Pipeline
628
629
```java
630
@Service
631
public class MediaProcessingPipeline {
632
633
@Async
634
public CompletableFuture<ProcessedMediaResult> processUploadedMedia(
635
MultipartFile file, String openid, MediaProcessingOptions options) {
636
637
return CompletableFuture.supplyAsync(() -> {
638
try {
639
ProcessedMediaResult result = new ProcessedMediaResult();
640
641
// Step 1: Basic validation
642
if (!validateFile(file)) {
643
result.setSuccess(false);
644
result.setError("Invalid file format or size");
645
return result;
646
}
647
648
// Step 2: Security check
649
boolean isSecure = wxMaService.getSecurityService()
650
.checkImage(file.getInputStream(), file.getOriginalFilename());
651
652
if (!isSecure) {
653
result.setSuccess(false);
654
result.setError("Content security check failed");
655
return result;
656
}
657
658
// Step 3: User risk assessment
659
WxMaUserRiskRank userRisk = wxMaService.getSecurityService()
660
.getUserRiskRank(openid, WxMaMediaConstants.SCENE_SOCIAL);
661
662
if (userRisk.isHighRisk()) {
663
result.setSuccess(false);
664
result.setError("User risk level too high");
665
return result;
666
}
667
668
// Step 4: Process image if needed
669
File processedFile = file instanceof File ? (File) file :
670
convertMultipartToFile(file);
671
672
if (options.isResizeRequired()) {
673
processedFile = imageProcessor.resize(processedFile,
674
options.getTargetWidth(),
675
options.getTargetHeight());
676
}
677
678
// Step 5: Upload to WeChat
679
WxMediaUploadResult uploadResult;
680
if (options.isPermanent()) {
681
uploadResult = wxMaService.getMediaService().uploadImg(processedFile);
682
} else {
683
uploadResult = wxMaService.getMediaService()
684
.uploadTempMedia(WxMaMediaConstants.IMAGE, processedFile);
685
}
686
687
// Step 6: Build result
688
result.setSuccess(true);
689
result.setMediaId(uploadResult.getMediaId());
690
result.setMediaUrl(uploadResult.getUrl());
691
result.setProcessingTime(System.currentTimeMillis() - startTime);
692
693
// Clean up temporary files
694
if (processedFile != file) {
695
processedFile.delete();
696
}
697
698
return result;
699
700
} catch (Exception e) {
701
logger.error("Media processing pipeline failed: {}", e.getMessage());
702
ProcessedMediaResult result = new ProcessedMediaResult();
703
result.setSuccess(false);
704
result.setError("Processing pipeline error: " + e.getMessage());
705
return result;
706
}
707
});
708
}
709
710
private boolean validateFile(MultipartFile file) {
711
// Check file size (e.g., max 10MB)
712
if (file.getSize() > 10 * 1024 * 1024) {
713
return false;
714
}
715
716
// Check file type
717
String contentType = file.getContentType();
718
return contentType != null && contentType.startsWith("image/");
719
}
720
}
721
```
722
723
### Content Moderation Dashboard
724
725
```java
726
@RestController
727
@RequestMapping("/api/moderation")
728
public class ModerationController {
729
730
@PostMapping("/check/text")
731
public ResponseEntity<ModerationResult> checkText(
732
@RequestBody TextModerationRequest request) {
733
734
try {
735
boolean isSecure = wxMaService.getSecurityService()
736
.checkText(request.getContent(),
737
request.getScene(),
738
WxMaMediaConstants.VERSION_LATEST);
739
740
ModerationResult result = new ModerationResult();
741
result.setSecure(isSecure);
742
result.setAction(isSecure ? "approve" : "reject");
743
744
return ResponseEntity.ok(result);
745
746
} catch (WxErrorException e) {
747
logger.error("Text moderation API failed: {}", e.getMessage());
748
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
749
.body(new ModerationResult(false, "error", e.getMessage()));
750
}
751
}
752
753
@PostMapping("/check/image")
754
public ResponseEntity<ModerationResult> checkImage(
755
@RequestParam("file") MultipartFile file) {
756
757
try {
758
boolean isSecure = wxMaService.getSecurityService()
759
.checkImage(file.getInputStream(), file.getOriginalFilename());
760
761
ModerationResult result = new ModerationResult();
762
result.setSecure(isSecure);
763
result.setAction(isSecure ? "approve" : "reject");
764
765
return ResponseEntity.ok(result);
766
767
} catch (WxErrorException | IOException e) {
768
logger.error("Image moderation API failed: {}", e.getMessage());
769
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
770
.body(new ModerationResult(false, "error", e.getMessage()));
771
}
772
}
773
774
@GetMapping("/user/{openid}/risk")
775
public ResponseEntity<UserRiskProfile> getUserRisk(
776
@PathVariable String openid,
777
@RequestParam(defaultValue = "1") Integer scene) {
778
779
try {
780
WxMaUserRiskRank riskResult = wxMaService.getSecurityService()
781
.getUserRiskRank(openid, scene);
782
783
UserRiskProfile profile = new UserRiskProfile();
784
profile.setOpenid(openid);
785
profile.setRiskRank(riskResult.getRiskRank());
786
profile.setRiskLevel(getRiskLevelDescription(riskResult.getRiskRank()));
787
profile.setAssessmentTime(new Date(riskResult.getTimestamp() * 1000));
788
789
return ResponseEntity.ok(profile);
790
791
} catch (WxErrorException e) {
792
logger.error("User risk API failed: {}", e.getMessage());
793
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
794
}
795
}
796
}
797
```
798
799
This media and content module provides comprehensive functionality for media file management, content security checks, and user risk assessment with automated moderation capabilities for WeChat MiniApp applications.