diff --git a/src/main/java/com/dpkj/modules/scanface/ali/config/AliFaceConfig.java b/src/main/java/com/dpkj/modules/scanface/ali/config/AliFaceConfig.java new file mode 100644 index 0000000..ceda812 --- /dev/null +++ b/src/main/java/com/dpkj/modules/scanface/ali/config/AliFaceConfig.java @@ -0,0 +1,27 @@ +package com.dpkj.modules.scanface.ali.config; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @description: 支付宝刷脸配置信息 + * @author: Zhangxue + * @time: 2025/4/16 20:23 + */ +@Data +@Component +@ConfigurationProperties(prefix = "dpkj.ali.face") +public class AliFaceConfig { + + private String appId; + + private String appVersion; + + private String merchantId; + + private String deviceNum; + + private String partnerId; +} diff --git a/src/main/java/com/dpkj/modules/scanface/ali/controller/AliScanFaceController.java b/src/main/java/com/dpkj/modules/scanface/ali/controller/AliScanFaceController.java index c188861..a236330 100644 --- a/src/main/java/com/dpkj/modules/scanface/ali/controller/AliScanFaceController.java +++ b/src/main/java/com/dpkj/modules/scanface/ali/controller/AliScanFaceController.java @@ -6,8 +6,11 @@ import com.dpkj.common.constant.ChsConst; import com.dpkj.common.vo.Result; import com.dpkj.modules.chs.dll.AlipayDll; import com.dpkj.modules.chs.entity.AlipayEcRequestData; +import com.dpkj.modules.scanface.ali.config.AliFaceConfig; +import com.dpkj.modules.scanface.ali.dll.AbcpInvoke; import com.dpkj.modules.scanface.ali.dll.AliScanFaceDll; import com.dpkj.modules.scanface.ali.service.IAliScanFaceService; +import com.dpkj.modules.scanface.vo.MyCallbackRsp; import com.sun.jna.Callback; import com.sun.jna.Memory; import com.sun.jna.Pointer; @@ -17,6 +20,9 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; +import java.io.File; + /** * @Auther: 萧道子 * @Date: 2025/4/16 16:47 @@ -30,27 +36,61 @@ public class AliScanFaceController { private final IAliScanFaceService aliScanFaceService; + @Resource + private AliFaceConfig aliFaceConfig; + + /** + * 初始化, + * @return + * @throws AliScanFaceDll.DllRegistrationException + */ + @GetMapping("iniAbcp") + Result iniAbcp() throws AliScanFaceDll.DllRegistrationException { + return aliScanFaceService.iniAbcp(); + } + + + //测试使用绝对路径 + public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, AliScanFaceDll.DllRegistrationException { + File dllFile = new File("C:\\opt\\ant-abcp\\bpaas_api.dll"); + System.out.println("DLL 存在: " + dllFile.exists()); + + //System.setProperty("java.library.path", "C:/opt/ant-abcp"); + // 加载DLL(直接指定绝对路径) + System.load("C:/opt/ant-abcp/bpaas_api.dll"); + + String appId = "2021005138692337"; + String appVersion = "1.0.0.0"; + JSONObject params = new JSONObject() + .fluentPut("appId", appId) //应用ID + .fluentPut("merchantId", "2088641941653700") //签约商家的 PID,以 2088 开头 + .fluentPut("deviceNum", "P060003750")//商家机具终端编号,每台设备保持唯一 + .fluentPut("partnerId", "2088641941653700");//服务商的 PID + String json = params.toJSONString(); + // 指定支付宝LOT SDK的本地库路径 + AbcpInvoke.SetAPIPathFile("C:\\opt\\ant-abcp\\bpaas_api.dll"); + // 2. 创建回调实例 + MyCallbackRsp callback = new MyCallbackRsp(); + AbcpInvoke.AbcpInit(appId, appVersion, json, callback); + } @GetMapping("test") public Result test() { try { AliScanFaceDll.Dll dll = AliScanFaceDll.instance(); - dll.bp_api_set_isv_lan(1); + dll.bp_api_set_isv_lan(3); - dll.abcp_init(null, null, null, null, - new AliScanFaceDll.ProcessCallback() { - @Override - public void invoke(Object obj) { - Console.log(obj); - } - }, - new AliScanFaceDll.FinishCallback() { - @Override - public void invoke(Object obj) { - Console.log(obj); - } - }); + JSONObject params = new JSONObject() + .fluentPut("appId", "2021005138692337") //应用ID + .fluentPut("merchantId", "2088641941653700") //签约商家的 PID,以 2088 开头 + .fluentPut("deviceNum", "P060003750")//商家机具终端编号,每台设备保持唯一 + .fluentPut("partnerId", "2088641941653700");//服务商的 PID + String json = params.toJSONString(); + + AbcpInvoke.ABCPProcess msABCPProcess = new AbcpInvoke.ABCPProcess(); + AbcpInvoke.ABCPFinish msABCPFinish = new AbcpInvoke.ABCPFinish(); + dll.abcp_init(256, "2021005138692337", "1.0.0.0", json, msABCPProcess, msABCPFinish); return Result.ok("成功"); } catch (Exception e) { diff --git a/src/main/java/com/dpkj/modules/scanface/ali/dll/AbcpInvoke.java b/src/main/java/com/dpkj/modules/scanface/ali/dll/AbcpInvoke.java new file mode 100644 index 0000000..ed8945b --- /dev/null +++ b/src/main/java/com/dpkj/modules/scanface/ali/dll/AbcpInvoke.java @@ -0,0 +1,293 @@ +package com.dpkj.modules.scanface.ali.dll; + +import com.sun.jna.Callback; +import com.sun.jna.Native; +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +@Slf4j +public class AbcpInvoke { + + /** + * 获取 Dll 实例,同时注册 Dll 控件。 + * + * @return AlipayDll 实例 + * @throws AliScanFaceDll.DllRegistrationException 如果注册控件失败,抛出此异常 + */ + public static AliScanFaceDll.Dll instance() throws AliScanFaceDll.DllRegistrationException { + try { + return Native.load("AliScanFace", AliScanFaceDll.Dll.class); + } catch (UnsatisfiedLinkError e) { + log.info("[AliScanFaceDll][instance][阿里扫脸动态库] SDK注册失败:{}", e.getMessage()); + throw new AliScanFaceDll.DllRegistrationException("Failed to load AliScanFace library: ", e); + } + } + + public interface CallbackStr { + public void OnString(String result); + } + + public interface CallbackRsp { + public void OnProcess(int code, String subCode, String subMsg, String result); + + public void OnFinish(int code, String subCode, String subMsg, String result); + } + + + + public static void SetAPIPathFile(String fileDylib) { + if (msAbcpNativeDll == null) { + File file = new File(fileDylib); + if (file.exists()) { + try { + msAbcpNativeDll = (AbcpNativeDll) Native.load(fileDylib, AbcpNativeDll.class); + } catch (Throwable e) { + msAbcpNativeDll = null; + System.out.printf("## ERROR : load. ## [%s][%s] %n", fileDylib, e.getMessage()); + } + } else { + System.out.printf("## ERROR : dylib NOT exist ## %s %n", fileDylib); + } + } + } + + public static void AbcpInit(String appId, String appVersion, String json, CallbackRsp callback) { + if (msAbcpNativeDll == null) { + callback.OnFinish(3, "E69001", "[java] api load failed!", ""); + return; + } + + appId = FixNullString(appId); // involved null ptr! + appVersion = FixNullString(appVersion); // involved null ptr! + json = FixNullString(json); // involved null ptr! + msLock.lock(); + Integer seedId = msSeedId++; + msMapAbcpReponse.put(seedId, callback); + msLock.unlock(); + try { + msAbcpNativeDll.bp_api_set_isv_lan(3);// 0:cpp | 1:cshap | 2:jni | 3:jna + } catch (Throwable e) { + System.out.printf("## ERROR ## %s %n", e.getMessage()); + } + try { + msAbcpNativeDll.abcp_init(seedId, appId, appVersion, json, msABCPProcess, msABCPFinish); + } catch (Throwable e) { + callback.OnFinish(3, "E69001", e.getMessage(), ""); + System.out.printf("## ERROR ## %s %n", e.getMessage()); + } + } + + public static void AbcpGetMetaInfo(String appId, String json, CallbackRsp callback) { + if (msAbcpNativeDll == null) { + callback.OnFinish(3, "E69001", "[java] api load failed!", ""); + return; + } + appId = FixNullString(appId); // involved null ptr! + json = FixNullString(json); // involved null ptr! + msLock.lock(); + Integer seedId = msSeedId++; + msMapAbcpReponse.put(seedId, callback); + msLock.unlock(); + + try { + msAbcpNativeDll.abcp_get_meta_info(seedId, appId, json, msABCPProcess, msABCPFinish); + } catch (Throwable e) { + callback.OnFinish(3, "E69001", e.getMessage(), ""); + System.out.printf("## ERROR ## %s %n", e.getMessage()); + } + } + + public static void AbcpStartService(String appId, String serviceCode, String json, CallbackRsp callback) { + if (msAbcpNativeDll == null) { + callback.OnFinish(3, "E69001", "[java] api load failed!", ""); + return; + } + appId = FixNullString(appId); // involved null ptr! + serviceCode = FixNullString(serviceCode); // involved null ptr! + json = FixNullString(json); // involved null ptr! + msLock.lock(); + Integer seedId = msSeedId++; + msMapAbcpReponse.put(seedId, callback); + msLock.unlock(); + + try { + msAbcpNativeDll.abcp_start_service(seedId, appId, serviceCode, json, msABCPProcess, msABCPFinish); + } catch (Throwable e) { + callback.OnFinish(3, "E69001", e.getMessage(), ""); + System.out.printf("## ERROR ## %s %n", e.getMessage()); + } + } + + public static void AbcpTaskStopService(String appId, String serviceCode, String json, CallbackRsp callback) { + if (msAbcpNativeDll == null) { + callback.OnFinish(3, "E69001", "[java] api load failed!", ""); + return; + } + appId = FixNullString(appId); // involved null ptr! + serviceCode = FixNullString(serviceCode); // involved null ptr! + json = FixNullString(json); // involved null ptr! + msLock.lock(); + Integer seedId = msSeedId++; + msMapAbcpReponse.put(seedId, callback); + msLock.unlock(); + + try { + msAbcpNativeDll.abcp_stop_service(seedId, appId, serviceCode, json, msABCPProcess, msABCPFinish); + } catch (Throwable e) { + callback.OnFinish(3, "E69001", e.getMessage(), ""); + System.out.printf("## ERROR ## %s %n", e.getMessage()); + } + } + + public static void AbcpZimIdInitTest(String metainfo, String smileType, String smileFlag, CallbackStr callback) { + if (msAbcpNativeDll == null) { + callback.OnString("{}"); + return; + } + metainfo = FixNullString(metainfo); // involved null ptr! + smileType = FixNullString(smileType); // involved null ptr! + smileFlag = FixNullString(smileFlag); // involved null ptr! + msLock.lock(); + Integer seedId = msSeedId++; + msMapAbcpString.put(seedId, callback); + msLock.unlock(); + + try { + msAbcpNativeDll.abcp_zimid_init_for_test(seedId, metainfo, smileType, smileFlag, msABCPString); + } catch (Throwable e) { + callback.OnString("{}"); + System.out.printf("## ERROR ## %s %n", e.getMessage()); + } + } + + public static void AbcpTaskSubscribeEvent(String appId, String json, CallbackRsp callback) { + if (msAbcpNativeDll == null) { + callback.OnFinish(3, "E69001", "[java] api load failed!", ""); + return; + } + appId = FixNullString(appId); // involved null ptr! + json = FixNullString(json); // involved null ptr! + msLock.lock(); + Integer seedId = msSeedId++; + msMapAbcpReponse.put(seedId, callback); + msLock.unlock(); + + try { + msAbcpNativeDll.abcp_call(seedId, appId, "SubscribeEvent", json, msABCPProcess, msABCPFinish); + } catch (Throwable e) { + callback.OnFinish(3, "E69001", e.getMessage(), ""); + System.out.printf("## ERROR ## %s %n", e.getMessage()); + } + } + + public static void AbcpTaskUnsubscribeEvent(String appId, String json, CallbackRsp callback) { + if (msAbcpNativeDll == null) { + callback.OnFinish(3, "E69001", "[java] api load failed!", ""); + return; + } + appId = FixNullString(appId); // involved null ptr! + json = FixNullString(json); // involved null ptr! + msLock.lock(); + Integer seedId = msSeedId++; + msMapAbcpReponse.put(seedId, callback); + msLock.unlock(); + + try { + msAbcpNativeDll.abcp_call(seedId, appId, "UnsubscribeEvent", json, msABCPProcess, msABCPFinish); + } catch (Throwable e) { + callback.OnFinish(3, "E69001", e.getMessage(), ""); + System.out.printf("## ERROR ## %s %n", e.getMessage()); + } + } + + // ===================================== + private static AbcpNativeDll msAbcpNativeDll = null; + private static ABCPProcess msABCPProcess = new ABCPProcess(); + private static ABCPFinish msABCPFinish = new ABCPFinish(); + private static ABCPString msABCPString = new ABCPString(); + private static Lock msLock = new ReentrantLock(); + private static Integer msSeedId = Integer.valueOf(256); + private static Map msMapAbcpString = new HashMap(); + private static Map msMapAbcpReponse = new HashMap(); + + private static String FixNullString(String str) { + if (str.equals(null)) { + return ""; + } + return str; + } + + public static Integer getMsSeedId(){ + return msSeedId; + } + + // ===================================== + public interface FuncProcess extends Callback { + public void onProcess(int seed_id, int code, String subCode, String subMsg, String result); + } + + public interface FuncFinish extends Callback { + public void onFinish(int seed_id, int code, String subCode, String subMsg, String result); + } + + public interface FuncString extends Callback { + public void onString(int seed_id, String result); + } + + public static class ABCPProcess implements FuncProcess { + public void onProcess(int seed_id, int _code, String subCode, String subMsg, String result) { + Integer seedId = Integer.valueOf(seed_id); + CallbackRsp callback = null; + msLock.lock(); + if (msMapAbcpReponse.containsKey(seedId)) { + callback = msMapAbcpReponse.get(seedId); + } + msLock.unlock(); + + if (callback != null) { + Integer code = Integer.valueOf(_code); + callback.OnProcess(code, subCode, subMsg, result); + } + } + } + + public static class ABCPFinish implements FuncFinish { + public void onFinish(int seed_id, int _code, String subCode, String subMsg, String result) { + Integer seedId = Integer.valueOf(seed_id); + CallbackRsp callback = null; + + msLock.lock(); + if (msMapAbcpReponse.containsKey(seedId)) { + callback = msMapAbcpReponse.remove(seedId); + } + msLock.unlock(); + + if (callback != null) { + Integer code = Integer.valueOf(_code); + callback.OnFinish(code, subCode, subMsg, result); + } + } + } + + public static class ABCPString implements FuncString { + public void onString(int seed_id, String result) { + Integer seedId = Integer.valueOf(seed_id); + CallbackStr callback = null; + + msLock.lock(); + if (msMapAbcpString.containsKey(seedId)) { + callback = msMapAbcpString.remove(seedId); + } + msLock.unlock(); + + if (callback != null) { + callback.OnString(result); + } + } + } +} diff --git a/src/main/java/com/dpkj/modules/scanface/ali/dll/AbcpNativeDll.java b/src/main/java/com/dpkj/modules/scanface/ali/dll/AbcpNativeDll.java new file mode 100644 index 0000000..37f3bf0 --- /dev/null +++ b/src/main/java/com/dpkj/modules/scanface/ali/dll/AbcpNativeDll.java @@ -0,0 +1,22 @@ +package com.dpkj.modules.scanface.ali.dll; + +import com.sun.jna.Callback; +import com.sun.jna.Library; + +public interface AbcpNativeDll extends Library { + void bp_api_set_isv_lan(Integer type_isv_language);// 0:cpp | 1:cshap | 2:jni | 3:jna + + void abcp_init(Integer arg, String app_id, String app_version, String json_param, Callback on_process, Callback on_finish); + + void abcp_start_service(Integer arg, String app_id, String service_code, String json_param, Callback on_process, Callback on_finish); + + void abcp_stop_service(Integer arg, String app_id, String service_code, String json_param, Callback on_process, Callback on_finish); + + void abcp_get_meta_info(Integer arg, String app_id, String json_param, Callback on_process, Callback on_finish); + + void abcp_stop_smile(Integer arg, String app_id, String json_param, Callback on_process, Callback on_finish); + + void abcp_zimid_init_for_test(Integer arg, String zimmetainfo, String smileType, String smileFlag, Callback callback); + + void abcp_call(Integer arg, String app_id, String call_method, String json_param, Callback on_process, Callback on_finish); +} diff --git a/src/main/java/com/dpkj/modules/scanface/ali/service/IAliScanFaceService.java b/src/main/java/com/dpkj/modules/scanface/ali/service/IAliScanFaceService.java index c14f821..7f5f571 100644 --- a/src/main/java/com/dpkj/modules/scanface/ali/service/IAliScanFaceService.java +++ b/src/main/java/com/dpkj/modules/scanface/ali/service/IAliScanFaceService.java @@ -1,4 +1,12 @@ package com.dpkj.modules.scanface.ali.service; +import com.dpkj.common.vo.Result; +import com.dpkj.modules.scanface.ali.dll.AliScanFaceDll; + public interface IAliScanFaceService { + + /** + * 初始化,调用阿里的ABCP_SDK部署出来的代码中的API文件 + */ + Result iniAbcp() throws AliScanFaceDll.DllRegistrationException; } diff --git a/src/main/java/com/dpkj/modules/scanface/ali/service/impl/AliScanFaceServiceImpl.java b/src/main/java/com/dpkj/modules/scanface/ali/service/impl/AliScanFaceServiceImpl.java index abc52a8..dc54c56 100644 --- a/src/main/java/com/dpkj/modules/scanface/ali/service/impl/AliScanFaceServiceImpl.java +++ b/src/main/java/com/dpkj/modules/scanface/ali/service/impl/AliScanFaceServiceImpl.java @@ -1,17 +1,60 @@ package com.dpkj.modules.scanface.ali.service.impl; +import com.alibaba.fastjson.JSONObject; +import com.dpkj.common.config.PrinterConfig; +import com.dpkj.common.vo.Result; +import com.dpkj.modules.scanface.ali.config.AliFaceConfig; +import com.dpkj.modules.scanface.ali.dll.AbcpInvoke; +import com.dpkj.modules.scanface.ali.dll.AliScanFaceDll; import com.dpkj.modules.scanface.ali.service.IAliScanFaceService; +import com.dpkj.modules.scanface.vo.MyCallbackRsp; import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import javax.annotation.Resource; + /** * @Auther: 萧道子 * @Date: 2025/4/16 16:47 * @Description: */ +@Slf4j @Service -@AllArgsConstructor public class AliScanFaceServiceImpl implements IAliScanFaceService { + @Resource + private AliFaceConfig aliFaceConfig; + + @Override + public Result iniAbcp() { + try { + log.info("[AliScanFaceServiceImpl][iniAbcpAli][26][appId:{}],[merchantId:{}],[deviceNum:{}],[partnerId:{}]", + aliFaceConfig.getAppId(), aliFaceConfig.getMerchantId(), aliFaceConfig.getDeviceNum(), aliFaceConfig.getPartnerId()); + + AliScanFaceDll.Dll dll = AliScanFaceDll.instance(); + dll.bp_api_set_isv_lan(3);// 0:cpp | 1:cshap | 2:jni | 3:jna + + JSONObject params = new JSONObject() + .fluentPut("appId", aliFaceConfig.getAppId()) //应用ID + .fluentPut("merchantId", aliFaceConfig.getMerchantId()) //签约商家的 PID,以 2088 开头 + .fluentPut("deviceNum", aliFaceConfig.getDeviceNum())//商家机具终端编号,每台设备保持唯一 + .fluentPut("partnerId", aliFaceConfig.getPartnerId());//服务商的 PID + String json = params.toJSONString(); + + + AbcpInvoke.ABCPProcess msABCPProcess = new AbcpInvoke.ABCPProcess(); + AbcpInvoke.ABCPFinish msABCPFinish = new AbcpInvoke.ABCPFinish(); + Integer seedId = AbcpInvoke.getMsSeedId(); + dll.abcp_init(seedId, "aliFaceConfig.getAppId()", aliFaceConfig.getAppVersion(), json, msABCPProcess, msABCPFinish); + + return Result.ok("成功"); + } catch (Exception e) { + e.printStackTrace(); + return Result.error("失败"); + } + } } diff --git a/src/main/java/com/dpkj/modules/scanface/vo/MyCallbackRsp.java b/src/main/java/com/dpkj/modules/scanface/vo/MyCallbackRsp.java new file mode 100644 index 0000000..331eba4 --- /dev/null +++ b/src/main/java/com/dpkj/modules/scanface/vo/MyCallbackRsp.java @@ -0,0 +1,28 @@ +package com.dpkj.modules.scanface.vo; + +import com.dpkj.modules.scanface.ali.dll.AbcpInvoke; + +/** + * @description: 自定义回调实现类 + * @author: Zhangxue + * @time: 2025/4/15 20:41 + */ +public class MyCallbackRsp implements AbcpInvoke.CallbackRsp { + @Override + public void OnProcess(int code, String subCode, String subMsg, String result) { + // 处理初始化过程中的中间状态(如进度更新) + System.out.printf("[OnProcess] code=%d, subCode=%s, subMsg=%s, result=%s%n", + code, subCode, subMsg, result); + } + + @Override + public void OnFinish(int code, String subCode, String subMsg, String result) { + // 处理初始化完成结果 + if (code == 0) { + System.out.println("初始化成功!"); + System.out.println("返回结果: " + result); + } else { + System.err.printf("初始化失败!错误码: %s, 错误信息: %s%n", subCode, subMsg); + } + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index a3f4e01..2216a04 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -1,5 +1,5 @@ server: - port: 5946 + port: 5948 dpkj: # 医保配置 @@ -23,6 +23,19 @@ dpkj: baud-rate: # 指定打印机第一层是a4还是a5 level-one: A5 + #支付宝刷脸 + ali: + face: + #IOT 应用管理-appid + app-id: 2021005138692337 + #IOT应用版本 + app-version: 1.0.0 + #签约商家的 PID,以 2088 开头,企业主体 + merchant-id: 2088641941653700 + #商家机具终端编号,每台设备保持唯一 + device-num: P060003750 + #服务商的 PID + partner-id: 2088641941653700 # 自定义app参数 app: diff --git a/src/main/resources/application-pro.yml b/src/main/resources/application-pro.yml index a326ba4..bc1c71f 100644 --- a/src/main/resources/application-pro.yml +++ b/src/main/resources/application-pro.yml @@ -1,5 +1,5 @@ server: - port: 5946 + port: 5948 dpkj: # 医保配置 @@ -23,6 +23,19 @@ dpkj: baud-rate: # 指定打印机第一层是a4还是a5 level-one: A5 + #支付宝刷脸 + ali: + face: + #IOT 应用管理-appid + app-id: 2021005138692337 + #IOT应用版本 + app-version: 1.0.0 + #签约商家的 PID,以 2088 开头,企业主体 + merchant-id: 2088641941653700 + #商家机具终端编号,每台设备保持唯一 + device-num: P060003750 + #服务商的 PID + partner-id: 2088641941653700 # 自定义app参数 app: