From 237cf8dbe3ee9c177ed671fb0251a0eb974d9a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E9=9B=AA?= <1044122544@qq.com> Date: Wed, 7 May 2025 10:06:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E4=BB=98=E5=AE=9D=E5=88=B7=E8=84=B8?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ali/controller/AliScanFaceController.java | 25 ++++- .../ali/service/IAliScanFaceService.java | 12 ++- .../service/impl/AliScanFaceServiceImpl.java | 94 ++++++++++++++++--- .../modules/scanface/ali/vo/AliOrderVo.java | 81 ++++++++++++++++ .../scanface/ali/vo/MyCallbackRsp.java | 30 ------ src/main/resources/application-dev.yml | 2 + src/main/resources/application-pro.yml | 3 + src/main/resources/application.yml | 2 +- 8 files changed, 204 insertions(+), 45 deletions(-) create mode 100644 src/main/java/com/dpkj/modules/scanface/ali/vo/AliOrderVo.java delete mode 100644 src/main/java/com/dpkj/modules/scanface/ali/vo/MyCallbackRsp.java 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 9ab79df..895c899 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 @@ -1,16 +1,22 @@ package com.dpkj.modules.scanface.ali.controller; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.http.ContentType; +import cn.hutool.http.Header; +import cn.hutool.http.HttpRequest; import com.alibaba.fastjson.JSONObject; import com.dpkj.common.vo.Result; import com.dpkj.modules.scanface.ali.config.AliFaceConfig; import com.dpkj.modules.scanface.ali.constants.AliFaceConstants; import com.dpkj.modules.scanface.ali.dll.AbcpInvoke; import com.dpkj.modules.scanface.ali.service.IAliScanFaceService; -import com.dpkj.modules.scanface.ali.vo.MyCallbackRsp; +import com.dpkj.modules.scanface.ali.vo.AliOrderVo; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -35,6 +41,21 @@ public class AliScanFaceController { @Resource private AliFaceConfig aliFaceConfig; + + /** + * 完整的统一的支付宝刷脸支付 + * 1、调用硬件刷脸获取到ftoken + * 2、调用后端的支付宝支付、存入hispay + * @param aliOrderVo + * @return + * @throws Exception + */ + @PostMapping("/aliFacePay") + public Result aliFacePay(@RequestBody AliOrderVo aliOrderVo) throws Exception { + return aliScanFaceService.aliFacePay(aliOrderVo); + } + + /** * ABCP初始化, * 文档地址:https://opendocs.alipay.com/iot/05e9ye @@ -73,6 +94,8 @@ public class AliScanFaceController { /** * ABCP服务停用 + * 终止正在进行中的某次(service_code + traceId)或某类(service_code)服务调用 + * 如处于支付环节,此次服务调用将不接受停止。 * @param traceId * @return */ 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 e68d280..9de13eb 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,13 +1,20 @@ package com.dpkj.modules.scanface.ali.service; +import com.alibaba.fastjson.JSONObject; import com.dpkj.common.vo.Result; +import com.dpkj.modules.scanface.ali.vo.AliOrderVo; public interface IAliScanFaceService { /** - * 初始化 - Result iniAbcp() ; + * 完整的统一的支付宝刷脸支付 + * 1、调用硬件刷脸获取到ftoken + * 2、调用后端的支付宝支付、存入hispay记录 + * @param aliOrderVo + * @return + * @throws Exception */ + Result aliFacePay(AliOrderVo aliOrderVo); /** * 初始化,调用阿里的ABCP_SDK部署出来的代码中的API文件 @@ -31,6 +38,7 @@ public interface IAliScanFaceService { /** * ABCP服务停用 * 终止正在进行中的某次(service_code + traceId)或某类(service_code)服务调用,然后通过回调返回服务终止结果 + * 如处于支付环节,此次服务调用将不接受停止。 * @param json 组装参数 * @param service_code 组件编码 * @return 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 e002dec..8a228bb 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,14 +1,21 @@ package com.dpkj.modules.scanface.ali.service.impl; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.http.ContentType; +import cn.hutool.http.Header; +import cn.hutool.http.HttpRequest; import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSON; import com.dpkj.common.vo.Result; import com.dpkj.modules.scanface.ali.config.AliFaceConfig; import com.dpkj.modules.scanface.ali.constants.AliFaceConstants; import com.dpkj.modules.scanface.ali.dll.AbcpInvoke; import com.dpkj.modules.scanface.ali.service.IAliScanFaceService; -import com.dpkj.modules.scanface.ali.vo.MyCallbackRsp; +import com.dpkj.modules.scanface.ali.vo.AliOrderVo; import jodd.util.StringUtil; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import org.thymeleaf.util.StringUtils; @@ -20,6 +27,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; + /** * @Auther: 萧道子 * @Date: 2025/4/16 16:47 @@ -27,16 +35,78 @@ import java.util.concurrent.atomic.AtomicReference; */ @Slf4j @Service +@Component public class AliScanFaceServiceImpl implements IAliScanFaceService { + @Value("${dpkj.serverurl}") + private String serverUrl; @Resource private AliFaceConfig aliFaceConfig; + /** - * 使用绝对路径调用ABCP_SDK部署出来的AbcpInvoke类 - * - * @return + * @description: * 完整的统一的支付宝刷脸支付 + * 1、调用硬件刷脸获取到ftoken + * 2、调用后端的支付宝支付、存入hispay + * @author: zhangxue + * @date: 2025/5/7 9:45 + * @Param [aliOrderVo] + * @return: com.dpkj.common.vo.Result + */ + @Override + public Result aliFacePay(AliOrderVo aliOrderVo) { + try { + /** + * 1、获取刷脸"刷脸去初始化服务"的ftoken返回值 + */ + this.iniAbcpAbsolute(); + //参数 + JSONObject zolozConfig = new JSONObject().fluentPut("installAngle", 90); + JSONObject params = new JSONObject() + .fluentPut("serviceId", aliFaceConfig.getServiceId()) + .fluentPut("zolozConfig", zolozConfig); + String json = params.toJSONString(); + String service_code = AliFaceConstants.SMILEVERIFYNIN_V1; //调用的组件编码:初始化 + Result startServiceIniResult = this.startServiceIni(json, service_code); + if (startServiceIniResult.isSuccess()) { + Map res = (Map) startServiceIniResult.getResult(); + String ftoken = res.get("ftoken"); + + /** + * 2、调用后端的支付宝统一收单交易支付接口、存入hisPay + */ + aliOrderVo.setAuthCode(ftoken);//Demo值:"fp128d26333fa66e66e7f34c493d30cdh76" + JSONObject serverParams = (JSONObject) JSON.toJSON(aliOrderVo); + + String url = serverUrl + "openapi/aliPayOrderApi/createOrder"; + String req = HttpRequest.post(url) + .header(Header.CONTENT_TYPE, ContentType.JSON.toString(CharsetUtil.CHARSET_UTF_8)) + .body(serverParams.toJSONString()) + .execute() + .body(); + JSONObject serverResult = JSONObject.parseObject(req); + + return Result.ok(serverResult); + } else { + //调用ABCP 刷脸初始化服务失败 + log.error("[AliScanFaceServiceImpl][aliFacePay][299]调用ABCP 刷脸初始化服务失败 :{}", startServiceIniResult.getMessage()); + return Result.error(startServiceIniResult.getMessage()); + } + } catch (Exception e) { + log.error("[AliScanFaceServiceImpl][aliFacePay][302][整个支付宝刷脸模块出现失败:] :{}", e.getMessage()); + return Result.error("支付宝刷脸失败:" + e.getMessage()); + } + + } + + + /** + * @description: 使用绝对路径调用ABCP_SDK部署出来的AbcpInvoke类 + * @author: zhangxue + * @date: 2025/5/7 9:45 + * @Param [] + * @return: com.dpkj.common.vo.Result */ @Override public Result iniAbcpAbsolute() { @@ -87,6 +157,7 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService { * ABCP服务调用 刷脸初始化服务,获取ftoken * 接受调用者传入的参数信息,执行指定服务(service_code),然后通过回调返回服务结果。 * https://opendocs.alipay.com/iot/05e9ye#ABCP%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8 + * * @param json 组装参数 * @param service_code 所要调用的组件编码 * @return @@ -114,7 +185,7 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService { AbcpInvoke.CallbackRsp callbackRsp = new AbcpInvoke.CallbackRsp() { @Override public void OnProcess(int code, String subCode, String subMsg, String result) { - log.info("[AliScanFaceServiceImpl][OnProcess][123][service_code:{}][code:{}][subCode:{}][subMsg:{}][result:{}]",service_code, code, subCode, subMsg, result); + log.info("[AliScanFaceServiceImpl][OnProcess][123][service_code:{}][code:{}][subCode:{}][subMsg:{}][result:{}]", service_code, code, subCode, subMsg, result); try { processCode.set(code); processResult.set(result); @@ -125,7 +196,7 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService { @Override public void OnFinish(int code, String subCode, String subMsg, String result) { - log.info("[AliScanFaceServiceImpl][OnFinish][128][service_code:{}][code:{}][subCode:{}][subMsg:{}][result:{}]",service_code, code, subCode, subMsg, result); + log.info("[AliScanFaceServiceImpl][OnFinish][128][service_code:{}][code:{}][subCode:{}][subMsg:{}][result:{}]", service_code, code, subCode, subMsg, result); /**Demo示例记录 * [service_code:BPaaSSmileVerifyNonInitV1][code:1000][subCode:E00000][subMsg:SUCCESS][result:{"code":1000,"subCode":"OK_SUCCESS","subMessage":"SUCCESS","barCode":"281215320962898068","ftoken":"fp1efd3d4c0230a28f5261efe7c5050eh28","alipayUid":"2088812449506047","accountList":"[\"104***@qq.com\"]","authToken":"44686f7195c77ee2e09c09bcdc657dd5h28i","result":{"accountList":["104***@qq.com"],"alipayUid":"2088812449506047","allowRetry":false,"authToken":"44686f7195c77ee2e09c09bcdc657dd5h28i","barCode":"281215320962898068","certName":"您好,*雪","ftoken":"fp1efd3d4c0230a28f5261efe7c5050eh28","type":"selectUid"},"easterEgg":false,"zolozConfig":{"installAngle":90},"serviceId":"pay","traceId":"2444-44-1745802328","callStartTimeMs":1745802328114,"localTime":"2025-04-28-09-05-41-791"}] @@ -168,7 +239,7 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService { if (finishCode.get() == 1000) { JSONObject jsonObject = JSONObject.parseObject(finishResult.get()); if (jsonObject.containsKey("ftoken")) { - res.put("ftoken", jsonObject.getString("ftoken")); + res.put("ftoken", jsonObject.getString("ftoken"));//ftoken参数的有效期为2分钟 res.put("barCode", jsonObject.getString("barCode")); finishResultRef.set(Result.ok("ABCP调用刷脸初始化finish服务成功", res)); } else { @@ -188,10 +259,11 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService { } - /** * ABCP服务停用 * 终止正在进行中的某次(service_code + traceId)或某类(service_code)服务调用,然后通过回调返回服务终止结果 + * 如处于支付环节,此次服务调用将不接受停止。 + * * @param json 组装参数 * @param service_code 组件编码 * @return @@ -209,12 +281,12 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService { AbcpInvoke.CallbackRsp callbackRsp = new AbcpInvoke.CallbackRsp() { @Override public void OnProcess(int code, String subCode, String subMsg, String result) { - log.info("[AliScanFaceServiceImpl][261][ABCP服务停用-OnProcess][code:{}][subCode:{}][subMsg:{}][result:{}]", code, subCode, subMsg, result); + log.info("[AliScanFaceServiceImpl][261][ABCP服务停用-OnProcess][code:{}][subCode:{}][subMsg:{}][result:{}]", code, subCode, subMsg, result); } @Override public void OnFinish(int code, String subCode, String subMsg, String result) { - log.info("[AliScanFaceServiceImpl][OnFinish][266][ABCP服务停用-OnFinish] [code:{}][subCode:{}][subMsg:{}][result:{}]", code, subCode, subMsg, result); + log.info("[AliScanFaceServiceImpl][OnFinish][266][ABCP服务停用-OnFinish] [code:{}][subCode:{}][subMsg:{}][result:{}]", code, subCode, subMsg, result); try { returnCode.set(code); returnResult.set(result); @@ -234,7 +306,7 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService { return Result.error("等待回调超时"); } else { if (returnCode.get() == 0) { - System.out.println("停止结果:"+returnResult.get()); + System.out.println("停止结果:" + returnResult.get()); } else { return Result.error("ABCP停止服务失败"); } diff --git a/src/main/java/com/dpkj/modules/scanface/ali/vo/AliOrderVo.java b/src/main/java/com/dpkj/modules/scanface/ali/vo/AliOrderVo.java new file mode 100644 index 0000000..7eeb922 --- /dev/null +++ b/src/main/java/com/dpkj/modules/scanface/ali/vo/AliOrderVo.java @@ -0,0 +1,81 @@ +package com.dpkj.modules.scanface.ali.vo; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @description: 支付宝支付参数,传入统一下单接口 + * @author: Zhangxue + * @time: 2025/4/29 14:24 + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +public class AliOrderVo implements Serializable { + + /** + * 付款模块 + */ + private String eventModule; + + /** + * 患者Id + */ + private String patientId; + + /** + * 商户机具终端编号 + */ + private String terminalId; + + /** + * 系统订单编号 + */ + private String outTradeNo; + + /** + * 用户支付金额 + */ + //@ApiModelProperty(value = "用户支付金额") + private String totalAmount; + + /** + * 订单标题 + */ + //@ApiModelProperty(value = "订单标题") + private String subject; + + /** + * 支付授权码 + * 刷脸标识串(fp开头的35位字符串) + * 从调用"BPaaSSmileVerifyNonInitV1"服务中获取 + */ + //@ApiModelProperty(value = "支付授权码") + private String authCode; + + /** + * 支付场景 + * bar_code:当面付条码支付场景;默认值 + * security_code:当面付刷脸支付场景,对应的auth_code为fp开头的刷脸标识串; + */ + //@ApiModelProperty(value = "支付授权码") + private String scene; + + /** + * 产品码:商家和支付宝签约的产品码 + * 当面付场景下,如果签约的是当面付快捷版,则传 OFFLINE_PAYMENT; + * 其它支付宝当面付产品传 FACE_TO_FACE_PAYMENT; + * 不传则默认使用FACE_TO_FACE_PAYMENT。 + */ + //@ApiModelProperty(value = "订单标题") + private String productCode; + + /** + * 卖家支付宝用户ID + */ + //@ApiModelProperty(value = "订单标题") + private String sellerId; +} diff --git a/src/main/java/com/dpkj/modules/scanface/ali/vo/MyCallbackRsp.java b/src/main/java/com/dpkj/modules/scanface/ali/vo/MyCallbackRsp.java deleted file mode 100644 index 8ded108..0000000 --- a/src/main/java/com/dpkj/modules/scanface/ali/vo/MyCallbackRsp.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.dpkj.modules.scanface.ali.vo; - -import com.dpkj.common.vo.Result; -import com.dpkj.modules.scanface.ali.dll.AbcpInvoke; -import lombok.extern.slf4j.Slf4j; - -/** - * @description: 自定义回调实现类 - * @author: Zhangxue - * @time: 2025/4/15 20:41 - */ -@Slf4j -public class MyCallbackRsp implements AbcpInvoke.CallbackRsp { - - @Override - public void OnProcess(int code, String subCode, String subMsg, String result) { - // 处理初始化过程中的中间状态(如进度更新) - log.info("[MyCallbackRsp][OnProcess][18][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) { - log.info("[MyCallbackRsp][OnFinish][27][返回结果:] :{}", result); - } else { - log.info("[MyCallbackRsp][OnFinish][29] :初始化失败!错误码: %s, 错误信息: %s%n", subCode, subMsg); - } - } -} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 01c42a6..e5ea8b5 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -2,6 +2,8 @@ server: port: 5948 dpkj: + #后端项目访问地址 #https://yinyitong.yzqingyan.cn/ http://172.16.11.13:15946/ ttps://yinyitong.yzqingyan.cn + serverurl: http://localhost:5946/api/ # 医保配置 chs: # 医保机构编码 diff --git a/src/main/resources/application-pro.yml b/src/main/resources/application-pro.yml index 6c6f999..274d741 100644 --- a/src/main/resources/application-pro.yml +++ b/src/main/resources/application-pro.yml @@ -2,6 +2,9 @@ server: port: 5946 dpkj: + #后端项目访问地址 + #TODO 改为正式的地址 http://www.lczyyy.com/api + serverurl: http://127.0.0.1:15946/api # 医保配置 chs: # 医保机构编码 diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index a7109ea..ec034ed 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -22,4 +22,4 @@ spring: application: name: ems-express-bridge profiles: - active: pro + active: dev