|
|
@@ -8,8 +8,13 @@ import com.tencent.wework.Finance;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
+import java.io.File;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
import java.util.Locale;
|
|
|
|
|
|
/**
|
|
|
@@ -22,12 +27,19 @@ import java.util.Locale;
|
|
|
@Slf4j
|
|
|
public class QwMsgMediaFileService {
|
|
|
|
|
|
+ private static final Object FINANCE_NATIVE_LOCK = new Object();
|
|
|
+ private static volatile boolean financeNativeLoaded;
|
|
|
+
|
|
|
@Value("${qw.msg-audit.ffmpeg-path}")
|
|
|
private String ffmpegPath;
|
|
|
|
|
|
@Value("${qw.msg-audit.voice-amr-to-mp3:true}")
|
|
|
private boolean voiceAmrToMp3Enabled;
|
|
|
|
|
|
+ /** 与 QwMsgAuditWxCpFactory 一致,调用 Finance JNI 前必须先按此路径 loadingLibraries */
|
|
|
+ @Value("${qw.msg-audit.sdk-lib-path:}")
|
|
|
+ private String msgAuditSdkLibPath;
|
|
|
+
|
|
|
/**
|
|
|
* 下载后上传 OSS。后缀为 .amr 且开启转换时,会先转为 mp3 再上传,返回的 URL 指向 mp3。
|
|
|
*
|
|
|
@@ -40,6 +52,8 @@ public class QwMsgMediaFileService {
|
|
|
if (sdkfileid == null || sdkfileid.isEmpty()) {
|
|
|
return null;
|
|
|
}
|
|
|
+ // 先要加载 Finance SDK 原生库,才能NewSdk 然后下载媒体文件
|
|
|
+ ensureFinanceNativeLoaded(msgAuditSdkLibPath);
|
|
|
long sdk = Finance.NewSdk();
|
|
|
long ret = Finance.Init(sdk, company.getCorpId(), company.getMsgSecret());
|
|
|
if (ret != 0) {
|
|
|
@@ -77,6 +91,79 @@ public class QwMsgMediaFileService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Finance JNI 须先 loadingLibraries 再 NewSdk;仅走媒体下载、未先跑 WxJava 拉取时也要加载。
|
|
|
+ * 配置格式与 qw.msg-audit.sdk-lib-path 一致:目录、单文件路径,或逗号分隔多 DLL(首项为第一个库的绝对路径)。
|
|
|
+ */
|
|
|
+ private static void ensureFinanceNativeLoaded(String sdkLibPathConfig) {
|
|
|
+ if (financeNativeLoaded) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ synchronized (FINANCE_NATIVE_LOCK) {
|
|
|
+ if (financeNativeLoaded) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!StringUtils.hasText(sdkLibPathConfig)) {
|
|
|
+ throw new IllegalStateException("未配置 qw.msg-audit.sdk-lib-path,无法加载企微 Finance 原生库");
|
|
|
+ }
|
|
|
+ String raw = sdkLibPathConfig.trim();
|
|
|
+ try {
|
|
|
+ if (raw.contains(",")) {
|
|
|
+ loadFinanceNativeMulti(raw);
|
|
|
+ } else {
|
|
|
+ loadFinanceNativeSingle(raw);
|
|
|
+ }
|
|
|
+ } catch (UnsatisfiedLinkError e) {
|
|
|
+ String msg = e.getMessage();
|
|
|
+ if (msg != null && msg.contains("already loaded")) {
|
|
|
+ log.debug("Finance SDK 原生库已加载: {}", msg);
|
|
|
+ } else {
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ financeNativeLoaded = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void loadFinanceNativeMulti(String raw) {
|
|
|
+ String[] segments = raw.split(",");
|
|
|
+ List<String> trimmed = new ArrayList<>();
|
|
|
+ for (String s : segments) {
|
|
|
+ if (StringUtils.hasText(s)) {
|
|
|
+ trimmed.add(s.trim());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (trimmed.isEmpty()) {
|
|
|
+ throw new IllegalStateException("qw.msg-audit.sdk-lib-path 多文件配置为空");
|
|
|
+ }
|
|
|
+ String anchor = trimmed.get(0);
|
|
|
+ File anchorFile = new File(anchor);
|
|
|
+ List<String> libs = new ArrayList<>();
|
|
|
+ if (anchorFile.isAbsolute() && anchor.contains(".")) {
|
|
|
+ libs.add(anchorFile.getName());
|
|
|
+ for (int i = 1; i < trimmed.size(); i++) {
|
|
|
+ libs.add(trimmed.get(i));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ libs.addAll(trimmed);
|
|
|
+ }
|
|
|
+ Finance.loadingLibraries(libs, anchor);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void loadFinanceNativeSingle(String raw) {
|
|
|
+ String os = System.getProperty("os.name", "").toLowerCase(Locale.ROOT);
|
|
|
+ boolean win = os.contains("win");
|
|
|
+ String lower = raw.toLowerCase(Locale.ROOT);
|
|
|
+ boolean looksLikeFile = lower.endsWith(".dll") || lower.endsWith(".so");
|
|
|
+ File f = new File(raw);
|
|
|
+ if (looksLikeFile || f.isFile()) {
|
|
|
+ Finance.loadingLibraries(Collections.singletonList(f.getName()), raw);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String name = win ? "WeWorkFinanceSdk.dll" : "libWeWorkFinanceSdk.so";
|
|
|
+ Finance.loadingLibraries(Collections.singletonList(name), raw);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 循环分片拉取媒体二进制数据,直到 isFinish
|
|
|
*/
|