package com.nova.sankuai.service.impl; import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSONArray; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.nova.sankuai.domain.api.baofu.BaofuCheckVo; import com.nova.sankuai.domain.api.baofu.BaofuRecordPayInfo; import com.nova.sankuai.domain.api.baofu.RecordDto; import com.nova.sankuai.domain.api.yinsheng.enums.SignStatusEnum; import com.nova.sankuai.domain.entity.*; import com.nova.sankuai.domain.enums.vipservice.VipCardOrderEnum; import com.nova.sankuai.domain.vo.VipEffectiveTimeVo; import com.nova.sankuai.infra.config.CommonException; import com.nova.sankuai.infra.mapper.CustomerMapper; import com.nova.sankuai.infra.mapper.VipCardOrderMapper; import com.nova.sankuai.infra.utils.UserUtil; import com.nova.sankuai.infra.utils.baofu.FormatUtil; import com.nova.sankuai.infra.utils.baofu.PayHttpUtil; import com.nova.sankuai.infra.utils.baofu.SecurityUtil; import com.nova.sankuai.infra.utils.baofu.rsa.RsaCodingUtil; import com.nova.sankuai.infra.utils.baofu.rsa.SignatureUtils; import com.nova.sankuai.security.UserDetail; import com.nova.sankuai.service.IBaofuService; import com.nova.sankuai.service.IBaofuSignRecordService; import com.nova.sankuai.service.ICustomerUserService; import com.nova.sankuai.service.IVipCardService; import lombok.RequiredArgsConstructor; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.util.*; @Service @RequiredArgsConstructor public class BaofuServiceImpl implements IBaofuService { @Value("${baofu.pfx}") private String pfxpath; @Value("${baofu.cer}") private String cerpath; @Value("${baofu.aes-key}") private String AesKey; @Value("${baofu.version}") private String version; @Value("${baofu.url}") private String url; @Value("${baofu.terminal_id}") private String terminalId; @Value("${baofu.member_id}") private String memberId; @Value("${shantai.notificationDomain}") private String notiUrl; // private final CustomerUserMapper customerUserMapper; private final ICustomerUserService customerUserService; private final CustomerMapper customerMapper; private final VipCardOrderMapper vipCardOrderMapper; private final IVipCardService vipCardService; private final IBaofuSignRecordService baofuSignRecordService; // private final IVipCardOrderService vipCardOrderService; //私钥密码 private static final String priKeyPass = "zBb3B8"; // "100025773_286941"; private static final Logger log = LoggerFactory.getLogger("baofuLogger"); @Resource private PayHttpUtil payHttpUtil; private BaofuRecordPayInfo recordPayInfo(String uniqueCode, String error) { BaofuRecordPayInfo recordPayInfo = new BaofuRecordPayInfo(); recordPayInfo.setError(error); recordPayInfo.setUniqueCode(uniqueCode); return recordPayInfo; } private Map paramImpl(Map DateArry) { DateArry.put("terminal_id", terminalId);// 终端号 DateArry.put("member_id", memberId);// 商户号,宝付提供给商户的唯一编号 return DateArry; } @Override public BaofuCheckVo checkProtocolSignByBf(HttpServletRequest request) { String token = request.getHeader("Authorization"); UserDetail user = UserUtil.getUser(token); if (user == null || user.getId() == null) { throw new CommonException("Token无效"); } CustomerUser customerUser = customerUserService.getById(user.getId()); if (customerUser == null) { throw new CommonException("用户不存在"); } BaofuCheckVo checkVo = new BaofuCheckVo(); BaofuSignRecord signRecord = null; List signRecords = baofuSignRecordService.list(Wrappers.lambdaQuery(BaofuSignRecord.class). eq(BaofuSignRecord::getCustomerUserId, customerUser.getId()).orderByDesc(BaofuSignRecord::getCreationDate)); if (!signRecords.isEmpty()) { signRecord = signRecords.get(0); } Customer customer = customerMapper.getLatestCustomerRecord(customerUser.getPhone()); if (signRecord != null && SignStatusEnum.SUCCESS.getCode().equals(signRecord.getSignResult())) { checkVo.setSign(true); checkVo.setSignCardNumber(signRecord.getSignCardNumber()); checkVo.setSignIdNo(signRecord.getSignIdNo()); checkVo.setSignName(signRecord.getSignName()); checkVo.setSignPhone(signRecord.getSignPhone()); } else { checkVo.setSign(false); if (customer != null) { checkVo.setSignName(customer.getName()); checkVo.setSignIdNo(customer.getIdCard()); } } if (customer != null) { checkVo.setBankName(customer.getBankName()); checkVo.setBankCode(customer.getBankCode()); } return checkVo; } /** * 预绑卡 * @param recordDto * @param userDetail * @return */ @Override public BaofuRecordPayInfo startAuth(RecordDto recordDto, UserDetail userDetail) { CustomerUser userByPhone = getUser(userDetail.getPhone()); BaofuSignRecord baofuSignRecordDb = null; List signRecords = baofuSignRecordService.list(Wrappers. lambdaQuery(BaofuSignRecord.class).eq(BaofuSignRecord::getCustomerUserId, userByPhone.getId()) .orderByDesc(BaofuSignRecord::getCreationDate)); if (!signRecords.isEmpty()) { baofuSignRecordDb = signRecords.get(0); } if (baofuSignRecordDb != null && SignStatusEnum.SUCCESS.getCode().equals(baofuSignRecordDb.getSignResult())) { throw new CommonException("该用户已是宝付成功签约用户"); } try { String signName = recordDto.getSignName();// 签约用户姓名 String signCardNumber = FormatUtil.toStringTrim(recordDto.getSignCardNumber());// 签约银行卡号 String signPhone = recordDto.getSignPhone();// 签约银行预留手机号 String signIdNo = FormatUtil.toStringTrim(recordDto.getSignIdNo());// 签约身份证号 String userId = String.valueOf(userByPhone.getId()); if (StringUtils.isBlank(signName) || StringUtils.isBlank(signCardNumber) || StringUtils.isBlank(signPhone) || StringUtils.isBlank(signIdNo) || StringUtils.isBlank(userId)) { return recordPayInfo(null,"宝付预绑卡参数不正确!"); } // String Cardinfo = "6222022201002502849||460028197610126094|15289944674||";//账户信息[银行卡号|持卡人姓名|证件号|手机号|银行卡安全码|银行卡有效期] String Cardinfo = signCardNumber + "|" + signName + "|" + signIdNo + "|" + signPhone + "||";//账户信息[银行卡号|持卡人姓名|证件号|手机号|银行卡安全码|银行卡有效期] String send_time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());//报文发送日期时间 // String pfxpath ="D:\\CER_EN_DECODE\\AgreementPay\\bfkey_100025773@@200001173.pfx";//商户私钥 // String cerpath = "D:\\CER_EN_DECODE\\AgreementPay\\bfkey_100025773@@200001173.cer";//宝付公钥 // String AesKey = "4f66405c4f66405c";//商户自定义(可随机生成 商户自定义(AES key长度为=16位)) String dgtl_envlp = "01|"+AesKey;//使用接收方的公钥加密后的对称密钥,并做Base64转码,明文01|对称密钥,01代表AES[密码商户自定义] // log.info("密码dgtl_envlp:"+dgtl_envlp); dgtl_envlp = RsaCodingUtil.encryptByPubCerFile(SecurityUtil.Base64Encode(dgtl_envlp), cerpath);//公钥加密 // log.info("SHA-1摘要[Cardinfo]结果:"+SecurityUtil.sha1X16(Cardinfo, "UTF-8")); // // log.info("卡信息:"+Cardinfo+",长度:"+Cardinfo.length()); String outTradeNo = IdUtil.fastSimpleUUID().substring(0, 24);// 报文流水号 Cardinfo = SecurityUtil.AesEncrypt(SecurityUtil.Base64Encode(Cardinfo), AesKey);//先BASE64后进行AES加密 Map DateArry = new TreeMap(); DateArry.put("send_time", send_time); DateArry.put("msg_id", outTradeNo);//报文流水号 DateArry.put("version", version); DateArry.put("txn_type", "01");//交易类型 DateArry.put("dgtl_envlp", dgtl_envlp); DateArry.put("user_id", userId);//用户在商户平台唯一ID DateArry.put("card_type", "101");//卡类型 101 借记卡,102 信用卡 DateArry.put("id_card_type", "01");//证件类型 DateArry.put("acc_info",Cardinfo); DateArry = paramImpl(DateArry); String SignVStr = FormatUtil.coverMap2String(DateArry); // log.info("SHA-1摘要字串:"+SignVStr); String signature = SecurityUtil.sha1X16(SignVStr, "UTF-8");//签名 // log.info("SHA-1摘要结果:"+signature); String Sign = SignatureUtils.encryptByRSA(signature, pfxpath, priKeyPass); // log.info("RSA签名结果:"+Sign); DateArry.put("signature", Sign);//签名域 // log.info("宝付支付预绑卡入参:{}", JSON.toJSONString(DateArry)); String PostString = payHttpUtil.RequestForm(url + "/cutpayment/protocol/backTransRequest", DateArry); // log.info("宝付支付预绑卡返回结果:{}", PostString); Map ReturnData = FormatUtil.getParm(PostString); Map returnDataBase = FormatUtil.getParm(PostString);// 当有异常时录入数据表的返回数据 returnDataBase.remove("dgtl_envlp"); returnDataBase.put("outTradeNo", outTradeNo); if(!ReturnData.containsKey("signature")){ log.error("宝付支付预绑卡缺少验签参数:{}", PostString); payRecord(DateArry, "bp", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, null); return recordPayInfo(null,"宝付预绑卡缺少验签参数"); } String RSign=ReturnData.get("signature"); // log.info("返回的验签值:"+RSign); ReturnData.remove("signature");//需要删除签名字段 returnDataBase.remove("signature"); String RSignVStr = FormatUtil.coverMap2String(ReturnData); // log.info("返回SHA-1摘要字串:"+RSignVStr); String RSignature = SecurityUtil.sha1X16(RSignVStr, "UTF-8");//签名 // log.info("返回SHA-1摘要结果:"+RSignature); if(!SignatureUtils.verifySignature(cerpath,RSignature,RSign)){ log.error("宝付支付预绑卡验签失败:{}", PostString);//验签成功 payRecord(DateArry, "bp", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, null); return recordPayInfo(null,"宝付预绑卡验签失败"); } if(!ReturnData.containsKey("resp_code")){ log.error("宝付支付预绑卡缺少resp_code参数:{}", PostString); payRecord(DateArry, "bp", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, null); return recordPayInfo(null,"宝付预绑卡缺少resp_code参数"); } if(ReturnData.get("resp_code").toString().equals("S")){ if(!ReturnData.containsKey("dgtl_envlp")){ log.error("宝付支付预绑卡缺少dgtl_envlp参数:{}", PostString); payRecord(DateArry, "bp", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, null); return recordPayInfo(null,"宝付预绑卡缺少dgtl_envlp参数"); } String RDgtlEnvlp = SecurityUtil.Base64Decode(RsaCodingUtil.decryptByPriPfxFile(ReturnData.get("dgtl_envlp"), pfxpath, priKeyPass)); // log.info("返回数字信封:"+RDgtlEnvlp); String RAesKey=FormatUtil.getAesKey(RDgtlEnvlp);//获取返回的AESkey // log.info("返回的AESkey:"+RAesKey); String uniqueCode = SecurityUtil.Base64Decode(SecurityUtil.AesDecrypt(ReturnData.get("unique_code"),RAesKey)); log.info("宝付支付预绑卡成功:{}", PostString); payRecord(DateArry, "bp", "宝付支付预绑卡成功", ReturnData.get("biz_resp_code"), 1, null); // 开始入库操作 BaofuSignRecord baofuSignRecord; if (baofuSignRecordDb == null) { baofuSignRecord = new BaofuSignRecord(); baofuSignRecord.setCustomerUserId(userByPhone.getId()); baofuSignRecord.setSignIdNo(signIdNo); baofuSignRecord.setSignName(recordDto.getSignName()); baofuSignRecord.setSignPhone(recordDto.getSignPhone()); baofuSignRecord.setCreationDate(new Date()); } else { baofuSignRecord = baofuSignRecordDb; } baofuSignRecord.setSignResult(SignStatusEnum.WAIT_CONFIRM.getCode()); baofuSignRecord.setLastUpdatedDate(new Date()); baofuSignRecord.setSignCardNumber(signCardNumber); baofuSignRecordService.saveOrUpdate(baofuSignRecord); return recordPayInfo(uniqueCode,null); } else { log.info("宝付支付预绑卡失败:{}", PostString); payRecord(DateArry, "bp", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, null); return recordPayInfo(null,"宝付预绑卡失败!"); } } catch(Exception ex) { log.error("宝付支付预绑卡异常:{}",ex); throw new CommonException("宝付支付预绑卡出现错误!"); } } private void recordImpl(BaofuSignRecord baofuSignRecord, Boolean isSucc) { baofuSignRecord.setLastUpdatedDate(new Date()); if (isSucc != null) { baofuSignRecord.setSignResult(isSucc?SignStatusEnum.SUCCESS.getCode():SignStatusEnum.FAILED.getCode()); } baofuSignRecordService.saveOrUpdate(baofuSignRecord); } /** * 确认绑卡 * @param recordDto * @param userDetail * @return */ @Override public BaofuRecordPayInfo auth(RecordDto recordDto, UserDetail userDetail) { CustomerUser userByPhone = getUser(userDetail.getPhone()); BaofuSignRecord baofuSignRecordDb = null; List baofuRecords = baofuSignRecordService.list(Wrappers. lambdaQuery(BaofuSignRecord.class).eq(BaofuSignRecord::getCustomerUserId, userByPhone.getId()). orderByDesc(BaofuSignRecord::getCreationDate)); if (!baofuRecords.isEmpty()) { baofuSignRecordDb = baofuRecords.get(0); } if (baofuSignRecordDb == null) { throw new CommonException("请先进行宝付预绑卡操作!"); } try { String SMSStr = recordDto.getValidateCode();// 短信验证码 String uniqueCodeStr = recordDto.getUniqueCode();// 预绑卡唯一码 String userId = String.valueOf(userByPhone.getId()); if (StringUtils.isBlank(userId) || StringUtils.isBlank(uniqueCodeStr) || StringUtils.isBlank(SMSStr)) { return recordPayInfo(null,"宝付确认绑卡参数不正确!"); } String send_time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());//报文发送日期时间 // String pfxpath ="D:\\CER_EN_DECODE\\AgreementPay\\bfkey_100025773@@200001173.pfx";//商户私钥 // String cerpath = "D:\\CER_EN_DECODE\\AgreementPay\\bfkey_100025773@@200001173.cer";//宝付公钥 // String SMSStr="123456";//短信验证码,测试环境随机6位数;生产环境验证码预绑卡成功后发到用户手机。确认绑卡时回传。 // String AesKey = "4f66405c4f66405c";//商户自定义(可随机生成 商户自定义(AES key长度为=16位)) String dgtl_envlp = "01|"+AesKey;//使用接收方的公钥加密后的对称密钥,并做Base64转码,明文01|对称密钥,01代表AES[密码商户自定义] // log.info("密码dgtl_envlp:"+dgtl_envlp); dgtl_envlp = RsaCodingUtil.encryptByPubCerFile(SecurityUtil.Base64Encode(dgtl_envlp), cerpath);//公钥加密 String UniqueCode = uniqueCodeStr + "|" + SMSStr;//预支付唯一码(预绑卡返回的值)[格式:预签约唯一码|短信验证码] // log.info("预签约唯一码:"+UniqueCode); UniqueCode = SecurityUtil.AesEncrypt(SecurityUtil.Base64Encode(UniqueCode), AesKey);//先BASE64后进行AES加密 // log.info("AES结果:"+UniqueCode); String outTradeNo = IdUtil.fastSimpleUUID().substring(0, 24);// 报文流水号 Map DateArry = new TreeMap(); DateArry.put("send_time", send_time); DateArry.put("msg_id", outTradeNo);//报文流水号 DateArry.put("version", version); DateArry.put("txn_type", "02");//交易类型 DateArry.put("dgtl_envlp", dgtl_envlp); DateArry.put("unique_code", UniqueCode);//预签约唯一码 DateArry = paramImpl(DateArry); String SignVStr = FormatUtil.coverMap2String(DateArry); // log.info("SHA-1摘要字串:"+SignVStr); String signature = SecurityUtil.sha1X16(SignVStr, "UTF-8");//签名 // log.info("SHA-1摘要结果:"+signature); String Sign = SignatureUtils.encryptByRSA(signature, pfxpath, priKeyPass); // log.info("RSA签名结果:"+Sign); DateArry.put("signature", Sign);//签名域 String PostString = payHttpUtil.RequestForm(url + "/cutpayment/protocol/backTransRequest", DateArry); // log.info("请求返回:"+PostString); Map ReturnData = FormatUtil.getParm(PostString); Map returnDataBase = FormatUtil.getParm(PostString);// 当有异常时录入数据表的返回数据 returnDataBase.remove("dgtl_envlp"); returnDataBase.put("outTradeNo", outTradeNo); if(!ReturnData.containsKey("signature")){ log.error("宝付支付确认绑卡缺少验签参数:{}", PostString); payRecord(DateArry, "bc", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, userId); recordImpl(baofuSignRecordDb, false); return recordPayInfo(null,"宝付确认绑卡缺少验签参数!"); } String RSign=ReturnData.get("signature"); // log.info("返回的验签值:"+RSign); ReturnData.remove("signature");//需要删除签名字段 String RSignVStr = FormatUtil.coverMap2String(ReturnData); // log.info("返回SHA-1摘要字串:"+RSignVStr); String RSignature = SecurityUtil.sha1X16(RSignVStr, "UTF-8");//签名 // log.info("返回SHA-1摘要结果:"+RSignature); if(!SignatureUtils.verifySignature(cerpath,RSignature,RSign)){ log.error("宝付支付确认绑卡验签失败:{}", PostString); payRecord(DateArry, "bc", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, userId); recordImpl(baofuSignRecordDb, false); return recordPayInfo(null,"宝付确认绑卡缺少验签参数!"); } if(!ReturnData.containsKey("resp_code")){ log.error("宝付支付确认绑卡缺少resp_code参数:{}", PostString); payRecord(DateArry, "bc", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, userId); recordImpl(baofuSignRecordDb, false); return recordPayInfo(null,"宝付确认绑卡缺少resp_code参数!"); } // log.info("protocol_no:" + ReturnData.get("protocol_no")); if(ReturnData.get("resp_code").toString().equals("S")){ if(!ReturnData.containsKey("dgtl_envlp")){ log.error("宝付支付确认绑卡缺少dgtl_envlp参数:{}", PostString); payRecord(DateArry, "bc", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, userId); recordImpl(baofuSignRecordDb, false); return recordPayInfo(null,"宝付确认绑卡缺少dgtl_envlp参数!"); } String RDgtlEnvlp = SecurityUtil.Base64Decode(RsaCodingUtil.decryptByPriPfxFile(ReturnData.get("dgtl_envlp"), pfxpath, priKeyPass)); // log.info("返回数字信封:"+RDgtlEnvlp); String RAesKey=FormatUtil.getAesKey(RDgtlEnvlp);//获取返回的AESkey // log.info("返回的AESkey:"+RAesKey); String protocolNo = SecurityUtil.Base64Decode(SecurityUtil.AesDecrypt(ReturnData.get("protocol_no"),RAesKey)); log.info("宝付支付确认绑卡成功:"+PostString); payRecord(DateArry, "bc", "宝付支付确认绑卡成功", ReturnData.get("biz_resp_code"), 1, userId); baofuSignRecordDb.setSignUniqueCode(protocolNo); recordImpl(baofuSignRecordDb, true); return recordPayInfo(protocolNo,null); }else if(ReturnData.get("resp_code").toString().equals("I")){ log.info("宝付支付确认绑卡处理中:{}", PostString); payRecord(DateArry, "bc", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 3, userId); recordImpl(baofuSignRecordDb, null); return recordPayInfo("wait","宝付确认绑卡处理中!"); }else if(ReturnData.get("resp_code").toString().equals("F")){ log.error("宝付支付确认绑卡失败:{}", PostString); payRecord(DateArry, "bc", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, userId); recordImpl(baofuSignRecordDb, false); return recordPayInfo(null,"宝付确认绑卡失败!"); }else{ //异常不得做为订单状态。 log.error("宝付支付确认绑卡异常不得做为订单状态:{}", PostString); payRecord(DateArry, "bc", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, userId); recordImpl(baofuSignRecordDb, false); return recordPayInfo(null,"宝付确认绑卡异常!"); } } catch (Exception ex) { log.error("宝付支付确认绑卡异常:{}",ex); throw new CommonException("宝付支付确认绑卡出现错误!"); } } /** * 预支付 * @param recordDto * @param userDetail * @return */ @Override public BaofuRecordPayInfo readyPay(RecordDto recordDto, UserDetail userDetail) { CustomerUser userByPhone = getUser(userDetail.getPhone()); BaofuSignRecord baofuSignRecordDb = null; List baofuRecords = baofuSignRecordService.list(Wrappers. lambdaQuery(BaofuSignRecord.class).eq(BaofuSignRecord::getCustomerUserId, userByPhone.getId()). orderByDesc(BaofuSignRecord::getCreationDate)); if (!baofuRecords.isEmpty()) { baofuSignRecordDb = baofuRecords.get(0); } if (baofuSignRecordDb == null) { throw new CommonException("请先进行宝付绑卡操作!"); } // 判断是否绑卡成功 if (!SignStatusEnum.SUCCESS.getCode().equals(baofuSignRecordDb.getSignResult())) { throw new CommonException("请重新进行宝付绑卡操作!"); } // 获致到确认绑卡的唯一码 String uniqueCode = baofuSignRecordDb.getSignUniqueCode(); if (StringUtils.isBlank(uniqueCode)) { throw new CommonException("请再次进行宝付绑卡操作!"); } Customer customer = customerMapper.getLatestCustomerRecord(userByPhone.getPhone()); try { String userId = String.valueOf(userByPhone.getId()); if (StringUtils.isBlank(userId)) { return recordPayInfo(null,"宝付预支付参数不正确!"); } String send_time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());//报文发送日期时间 String dgtl_envlp = "01|"+AesKey;//使用接收方的公钥加密后的对称密钥,并做Base64转码,明文01|对称密钥,01代表AES[密码商户自定义] // log.info("密码dgtl_envlp:"+dgtl_envlp); dgtl_envlp = RsaCodingUtil.encryptByPubCerFile(SecurityUtil.Base64Encode(dgtl_envlp), cerpath);//公钥加密 String ProtocolNo = uniqueCode;//签约协议号(确认绑卡返回) // log.info("签约协议号:"+ProtocolNo); ProtocolNo = SecurityUtil.AesEncrypt(SecurityUtil.Base64Encode(ProtocolNo), AesKey);//先BASE64后进行AES加密 // log.info("签约协议号AES结果:"+ProtocolNo); String ReturnUrl= notiUrl + "/api/v2/callback/bf/pushAuditCallback"; String outTradeNo = recordDto.getPartnerThirdOrderId(); //生成订单号,36位字符 // String outTradeNo = ConstantsUtil.getOrder();// 商户订单号 Map DateArry = new TreeMap(); DateArry.put("send_time", send_time); DateArry.put("msg_id", recordDto.getOrderId());//报文流水号 DateArry.put("version", version); DateArry.put("txn_type", "05");//交易类型(参看:文档中《交易类型枚举》) DateArry.put("trans_id", outTradeNo);// 商户订单号 DateArry.put("dgtl_envlp", dgtl_envlp); DateArry.put("user_id", userId);//用户在商户平台唯一ID (和绑卡时要一致) DateArry.put("protocol_no", ProtocolNo);//签约协议号(密文) DateArry.put("txn_amt", String.valueOf(recordDto.getAmount()));//交易金额 [单位:分 例:1元则提交100],此处注意数据类型的转转,建议使用BigDecimal类弄进行转换为字串 Map RiskItem = new HashMap(); RiskItem.put("goodsCategory", "02");//行业类目 详见附录《行业类目》 RiskItem.put("userLoginId", userDetail.getPhone());//用户在商户系统中的登陆名(手机号、邮箱等标识) RiskItem.put("userEmail", ""); RiskItem.put("userMobile", userDetail.getPhone());//用户手机号 RiskItem.put("registerUserName", userByPhone.getName());//用户在商户系统中注册使用的名字 RiskItem.put("identifyState", "1");//用户在平台是否已实名,1:是 ;0:不是 RiskItem.put("userIdNo", baofuSignRecordDb.getSignIdNo());//用户身份证号 RiskItem.put("registerTime", new SimpleDateFormat("YYYYMMDDHHMMSS").format(userByPhone.getCreationDate()));//格式为:YYYYMMDDHHMMSS RiskItem.put("registerIp", customer.getClientIp());//用户在商户端注册时留存的IP RiskItem.put("chName", baofuSignRecordDb.getSignName());//持卡人姓名 RiskItem.put("chIdNo", baofuSignRecordDb.getSignIdNo());//持卡人身份证号 RiskItem.put("chCardNo", baofuSignRecordDb.getSignCardNumber());//持卡人银行卡号 RiskItem.put("chMobile", baofuSignRecordDb.getSignPhone());//持卡人手机 RiskItem.put("chPayIp", customer.getClientIp());//持卡人支付IP RiskItem.put("deviceOrderNo", "");//加载设备指纹中的订单号 DateArry.put("risk_item", JSONArray.toJSON(RiskItem).toString());//放入风控参数 DateArry.put("return_url", ReturnUrl);//最多填写三个地址,不同地址用间使用‘|’分隔 DateArry = paramImpl(DateArry); String SignVStr = FormatUtil.coverMap2String(DateArry); // log.info("SHA-1摘要字串:"+SignVStr); String signature = SecurityUtil.sha1X16(SignVStr, "UTF-8");//签名 // log.info("SHA-1摘要结果:"+signature); String Sign = SignatureUtils.encryptByRSA(signature, pfxpath, priKeyPass); // log.info("RSA签名结果:"+Sign); DateArry.put("signature", Sign);//签名域 // 开始创建订单 String PostString = payHttpUtil.RequestForm(url + "/cutpayment/protocol/backTransRequest", DateArry); // log.info("请求返回:"+PostString); Map ReturnData = FormatUtil.getParm(PostString); Map returnDataBase = FormatUtil.getParm(PostString);// 当有异常时录入数据表的返回数据 returnDataBase.remove("dgtl_envlp"); returnDataBase.put("outTradeNo", outTradeNo); if(!ReturnData.containsKey("signature")){ log.error("宝付支付预支付缺少验签参数:{}", PostString); payRecord(DateArry, "bs", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, null); return recordPayInfo(null,"宝付预支付缺少验签参数!"); } String RSign=ReturnData.get("signature"); // log.info("返回的验签值:"+RSign); ReturnData.remove("signature");//需要删除签名字段 String RSignVStr = FormatUtil.coverMap2String(ReturnData); // log.info("返回SHA-1摘要字串:"+RSignVStr); String RSignature = SecurityUtil.sha1X16(RSignVStr, "UTF-8");//签名 // log.info("返回SHA-1摘要结果:"+RSignature); if(!SignatureUtils.verifySignature(cerpath,RSignature,RSign)){ log.error("宝付支付预支付验签失败:{}", PostString); payRecord(DateArry, "bs", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, null); return recordPayInfo(null,"宝付预支付验签失败!"); } if(!ReturnData.containsKey("resp_code")){ log.error("宝付支付预支付缺少resp_code参数:{}", PostString); payRecord(DateArry, "bs", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, null); return recordPayInfo(null,"宝付预支付缺少resp_code参数!"); } if(ReturnData.get("resp_code").toString().equals("S")){ if(!ReturnData.containsKey("dgtl_envlp")){ log.error("宝付支付预支付缺少dgtl_envlp参数:{}", PostString); payRecord(DateArry, "bs", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, null); return recordPayInfo(null,"宝付预支付缺少dgtl_envlp参数!"); } if(!ReturnData.containsKey("unique_code")){ // throw new Exception("缺少unique_code参数!"); log.error("宝付支付预支付缺少unique_code参数:{}", PostString); payRecord(DateArry, "bs", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, null); return recordPayInfo(null,"宝付预支付缺少unique_code参数!"); } String RDgtlEnvlp = SecurityUtil.Base64Decode(RsaCodingUtil.decryptByPriPfxFile(ReturnData.get("dgtl_envlp"), pfxpath, priKeyPass)); // log.info("返回数字信封:"+RDgtlEnvlp); String RAesKey=FormatUtil.getAesKey(RDgtlEnvlp);//获取返回的AESkey // log.info("返回的AESkey:"+RAesKey); String returnUniqueCode = SecurityUtil.Base64Decode(SecurityUtil.AesDecrypt(ReturnData.get("unique_code"),RAesKey)); log.info("宝付支付预支付成功:"+PostString); payRecord(DateArry, "bs", "宝付支付预支付成功", ReturnData.get("biz_resp_code"), 1, null); return recordPayInfo(returnUniqueCode,null); }else{ log.error("宝付支付预支付失败:{}", PostString); payRecord(DateArry, "bs", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, null); return recordPayInfo(null,"宝付预支付失败!"); } } catch (Exception ex) { log.error("宝付支付预支付失败:{}", ex); throw new CommonException("宝付预支付失败!"); } } private void vipCardOrderImpl(VipCardOrder vipCardOrder) { vipCardOrderMapper.update(null, Wrappers.lambdaUpdate() .set(VipCardOrder::getStatus, vipCardOrder.getStatus()) .eq(VipCardOrder::getId, vipCardOrder.getId())); } public String callBack(HttpServletRequest request) { String result = "OK"; try { request.setCharacterEncoding("utf-8");//utf-8编码接收 Map RDateArry = new TreeMap(); Enumeration e = request.getParameterNames(); while(e.hasMoreElements()) { String paraStr = e.nextElement(); if(paraStr != null){ RDateArry.put(paraStr, request.getParameter(paraStr));//接收参数,(使用TreeMap自动排序) } } log.info("宝付支付回调返回参数:{}", JSONArray.toJSONString(RDateArry)); String transId = RDateArry.get("trans_id");// 获取订单号 if (StringUtils.isBlank(transId)) { log.error("宝付支付回调缺少订单号:{}", JSONArray.toJSON(RDateArry)); return "NO"; } // 根据订单号获取userId VipCardOrder vipCardOrder = vipCardOrderMapper.selectOne(new LambdaQueryWrapper() .eq(VipCardOrder::getPartnerThirdOrderId, transId)); if (vipCardOrder == null) { log.error("宝付支付回调数据表中没有相关数据:{}", JSONArray.toJSON(RDateArry)); return "NO"; } if (VipCardOrderEnum.STATUS_END.getCode().equals(vipCardOrder.getStatus())) {// 已成功了 log.info("宝付支付回调已成功过:{},返回参数:{}", vipCardOrder, JSONArray.toJSON(RDateArry)); return "OK"; } String userId = String.valueOf(vipCardOrder.getUserId()); if(!RDateArry.containsKey("signature")){ // throw new Exception("缺少验签参数!"); log.error("宝付支付回调缺少验签参数:{}", JSONArray.toJSON(RDateArry)); payRecord(RDateArry, "be", RDateArry.get("biz_resp_msg"), RDateArry.get("biz_resp_code"), 2, userId); vipCardOrder.setStatus(VipCardOrderEnum.STATUS_INVALID.getCode()); vipCardOrderImpl(vipCardOrder); result = "NO"; return result; } String RSign=RDateArry.get("signature"); RDateArry.remove("signature");//需要删除签名字段 String RSignVStr = FormatUtil.coverMap2String(RDateArry); String RSignature = SecurityUtil.sha1X16(RSignVStr, "UTF-8");//签名 if(!SignatureUtils.verifySignature(cerpath,RSignature,RSign)){ // log.info("Yes");//验签失败 log.error("宝付支付回调验签失败:{}", JSONArray.toJSON(RDateArry)); payRecord(RDateArry, "be", RDateArry.get("biz_resp_msg"), RDateArry.get("biz_resp_code"), 2, userId); vipCardOrder.setStatus(VipCardOrderEnum.STATUS_INVALID.getCode()); vipCardOrderImpl(vipCardOrder); result = "NO"; return result; } if(!RDateArry.containsKey("resp_code")){ // throw new Exception("缺少resp_code参数!"); log.error("宝付支付回调缺少resp_code参数:{}", JSONArray.toJSON(RDateArry)); payRecord(RDateArry, "be", RDateArry.get("biz_resp_msg"), RDateArry.get("biz_resp_code"), 2, userId); vipCardOrder.setStatus(VipCardOrderEnum.STATUS_INVALID.getCode()); vipCardOrderImpl(vipCardOrder); result = "NO"; return result; } if(RDateArry.get("resp_code").toString().equals("S")){ VipCard card = vipCardService.getOne(Wrappers.lambdaQuery() .eq(VipCard::getCardId, vipCardOrder.getCardId()).last(" limit 1 ")); if (card == null) { payRecord(RDateArry, "be", "对应会员卡不存在", "bf00003", 2, userId); log.error("宝付支付回调失败,对应会员卡不存在,原始数据:" + vipCardOrder); result = "NO"; return result; // throw new CommonException("对应会员卡不存在"); } log.info("宝付支付回调成功:[trans_id:"+RDateArry.get("trans_id")+"]"); payRecord(RDateArry, "br", "宝付支付回调成功", RDateArry.get("biz_resp_code"), 1, userId); vipCardOrder.setStatus(VipCardOrderEnum.STATUS_END.getCode()); vipCardOrderImpl(vipCardOrder); VipEffectiveTimeVo vipEffectiveTimeVo = customerUserService.calculateExpiredDate(vipCardOrder.getUserId(), card.getValidDate(), null, null); customerUserService.updateVipEffectiveTime(vipCardOrder, vipEffectiveTimeVo); }else if(RDateArry.get("resp_code").toString().equals("I")){ // log.info("订单处理中!"); log.info("宝付支付回调处理中:{}", JSONArray.toJSON(RDateArry)); payRecord(RDateArry, "be", RDateArry.get("biz_resp_msg"), RDateArry.get("biz_resp_code"), 3, userId); vipCardOrder.setStatus(VipCardOrderEnum.STATUS_INVALID.getCode()); vipCardOrderImpl(vipCardOrder); result = "NO"; }else if(RDateArry.get("resp_code").toString().equals("F")){ // log.info("订单失败!"); log.error("宝付支付回调失败:{}", JSONArray.toJSON(RDateArry)); payRecord(RDateArry, "be", RDateArry.get("biz_resp_msg"), RDateArry.get("biz_resp_code"), 2, userId); vipCardOrder.setStatus(VipCardOrderEnum.STATUS_INVALID.getCode()); vipCardOrderImpl(vipCardOrder); result = "NO"; }else{ // throw new Exception("反回异常!");//异常不得做为订单状态。 //异常不得做为订单状态。 log.error("宝付支付回调不得做为订单状态:{}", JSONArray.toJSON(RDateArry)); payRecord(RDateArry, "be", RDateArry.get("biz_resp_msg"), RDateArry.get("biz_resp_code"), 2, userId); vipCardOrder.setStatus(VipCardOrderEnum.STATUS_INVALID.getCode()); vipCardOrderImpl(vipCardOrder); result = "NO"; } } catch (Exception ex) { log.error("宝付支付回调出现异常:{}", ex); result = "NO"; } return result; } /** * 确认支付 * @param recordDto * @param userDetail * @return */ @Override public BaofuRecordPayInfo confirmPay(RecordDto recordDto, UserDetail userDetail) { CustomerUser userByPhone = getUser(userDetail.getPhone()); if (StringUtils.isBlank(recordDto.getPartnerThirdOrderId())) { throw new CommonException("订单号不能为空!"); } VipCardOrder vipCardOrder = vipCardOrderMapper.selectOne(new LambdaQueryWrapper() .eq(VipCardOrder::getPartnerThirdOrderId, recordDto.getPartnerThirdOrderId())); if (vipCardOrder == null) { throw new CommonException("订单不存在!"); } VipCard card = vipCardService.getOne(new LambdaQueryWrapper() .eq(VipCard::getCardId, vipCardOrder.getCardId())); if (card == null) { throw new CommonException("不存在此类会员卡!"); } try { String userId = String.valueOf(userByPhone.getId()); String SMSStr = recordDto.getValidateCode(); String uniqueCodeStr = recordDto.getUniqueCode(); if (StringUtils.isBlank(userId) || StringUtils.isBlank(SMSStr) || StringUtils.isBlank(uniqueCodeStr)) { return recordPayInfo(null,"宝付确认支付参数不正确!"); } String send_time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());//报文发送日期时间 // String SMSStr="123456";//短信验证码,测试环境随机6位数;生产环境验证码预绑卡成功后发到用户手机。确认绑卡时回传。 String dgtl_envlp = "01|"+AesKey;//使用接收方的公钥加密后的对称密钥,并做Base64转码,明文01|对称密钥,01代表AES[密码商户自定义] dgtl_envlp = RsaCodingUtil.encryptByPubCerFile(SecurityUtil.Base64Encode(dgtl_envlp), cerpath);//公钥加密 String UniqueCode = uniqueCodeStr + "|"+SMSStr;//预支付唯一码(预支付返回的值)[格式:预支付一码|短信验证码] UniqueCode = SecurityUtil.AesEncrypt(SecurityUtil.Base64Encode(UniqueCode), AesKey);//先BASE64后进行AES加密 String CardInfo="";//信用卡(格式):信用卡有效期|安全码;借记卡:传空 //暂不支持信用卡 //CardInfo = SecurityUtil.AesEncrypt(SecurityUtil.Base64Encode(CardInfo), AesKey);//先BASE64后进行AES加密 Map DateArry = new TreeMap(); DateArry.put("send_time", send_time); DateArry.put("msg_id", "TISN"+System.currentTimeMillis());//报文流水号 DateArry.put("version", version); DateArry.put("txn_type", "06");//交易类型 DateArry.put("dgtl_envlp", dgtl_envlp); DateArry.put("unique_code", UniqueCode);//预支付唯一码 DateArry.put("card_info", CardInfo);//卡信息 DateArry = paramImpl(DateArry); String SignVStr = FormatUtil.coverMap2String(DateArry); String signature = SecurityUtil.sha1X16(SignVStr, "UTF-8");//签名 String Sign = SignatureUtils.encryptByRSA(signature, pfxpath, priKeyPass); DateArry.put("signature", Sign);//签名域 String PostString = payHttpUtil.RequestForm(url + "/cutpayment/protocol/backTransRequest", DateArry); Map ReturnData = FormatUtil.getParm(PostString); if(!ReturnData.containsKey("signature")){ log.error("宝付支付确认支付缺少验签参数:{}", PostString); payRecord(DateArry, "bf", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, userId); return recordPayInfo(null,"宝付确认支付缺少验签参数!"); } String RSign=ReturnData.get("signature"); // log.info("返回的验签值:"+RSign); ReturnData.remove("signature");//需要删除签名字段 String RSignVStr = FormatUtil.coverMap2String(ReturnData); // log.info("返回SHA-1摘要字串:"+RSignVStr); String RSignature = SecurityUtil.sha1X16(RSignVStr, "UTF-8");//签名 // log.info("返回SHA-1摘要结果:"+RSignature); DateArry.put("trans_id", vipCardOrder.getPartnerThirdOrderId());// 订单号 if(!SignatureUtils.verifySignature(cerpath,RSignature,RSign)){ log.error("宝付支付确认支付验签失败:{}", PostString); payRecord(DateArry, "bf", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, userId); vipCardOrder.setStatus(VipCardOrderEnum.STATUS_INVALID.getCode()); vipCardOrderImpl(vipCardOrder); return recordPayInfo(null,"宝付确认支付验签失败!"); } if(!ReturnData.containsKey("resp_code")){ log.error("宝付支付确认绑卡缺少resp_code参数:{}", PostString); payRecord(DateArry, "bf", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, userId); vipCardOrder.setStatus(VipCardOrderEnum.STATUS_INVALID.getCode()); vipCardOrderImpl(vipCardOrder); return recordPayInfo(null,"宝付确认绑卡缺少resp_code参数!"); } if(ReturnData.get("resp_code").toString().equals("S")){ log.info("宝付支付确认支付成功:{}", PostString); payRecord(DateArry, "bf", "宝付支付确认支付成功", ReturnData.get("biz_resp_code"), 1, userId); vipCardOrder.setOrderId(ReturnData.get("order_id")); vipCardOrder.setStatus(VipCardOrderEnum.STATUS_END.getCode()); vipCardOrderImpl(vipCardOrder); VipEffectiveTimeVo vipEffectiveTimeVo = customerUserService.calculateExpiredDate(vipCardOrder.getUserId(), card.getValidDate(), null, null); customerUserService.updateVipEffectiveTime(vipCardOrder, vipEffectiveTimeVo); return recordPayInfo("ok",null); }else if(ReturnData.get("resp_code").toString().equals("I")){ log.info("宝付支付确认支付处理中:{}", PostString); payRecord(DateArry, "bf", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 3, userId); vipCardOrder.setOrderId(ReturnData.get("order_id")); vipCardOrder.setStatus(VipCardOrderEnum.STATUS_WAIT.getCode()); vipCardOrderImpl(vipCardOrder); return recordPayInfo("wait",null); }else if(ReturnData.get("resp_code").toString().equals("F")){ log.error("宝付支付确认支付失败:{}", PostString); payRecord(DateArry, "bf", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, userId); vipCardOrder.setStatus(VipCardOrderEnum.STATUS_INVALID.getCode()); vipCardOrderImpl(vipCardOrder); return recordPayInfo(null,"宝付支付确认支付失败"); }else{ //异常不得做为订单状态。 log.error("宝付支付确认支付异常不得做为订单状态:{}", PostString); payRecord(DateArry, "bf", ReturnData.get("biz_resp_msg"), ReturnData.get("biz_resp_code"), 2, userId); vipCardOrder.setStatus(VipCardOrderEnum.STATUS_INVALID.getCode()); vipCardOrderImpl(vipCardOrder); return recordPayInfo(null,"宝付支付确认支付失败!"); } } catch (Exception ex) { log.error("宝付支付确认支付异常:{}",ex); throw new CommonException("宝付支付确认支付异常!"); } } private CustomerUser getUser(String phone) { LambdaQueryWrapper customerUserWrapper = new LambdaQueryWrapper<>(); customerUserWrapper.eq(CustomerUser::getPhone, phone).eq(CustomerUser::getDeleteFlag, 0); CustomerUser customerUser = customerUserService.getOne(customerUserWrapper); if (customerUser == null) { throw new CommonException("用户不存在"); } return customerUser; } /** * 支付前用户校验 * * @param userId * @return */ public boolean checkBeforePayment(Long userId) { BaofuSignRecord signRecord = null; List signRecords = baofuSignRecordService.list(Wrappers. lambdaQuery(BaofuSignRecord.class).eq(BaofuSignRecord::getCustomerUserId, userId) .orderByDesc(BaofuSignRecord::getCreationDate)); if (!signRecords.isEmpty()) { signRecord = signRecords.get(0); } return signRecord != null && SignStatusEnum.SUCCESS.getCode().equals(signRecord.getSignResult()); } private void payRecord(Map Parms, String recordType, String erroMsg,String code,Integer payStatus, String userId) { userId = userId == null ? Parms.get("user_id") : userId; if (userId != null) { PayRecord payRecord = new PayRecord(); LocalDateTime payDate = LocalDateTime.now(); payRecord.setPayDate(payDate); payRecord.setUserId(Long.parseLong(userId)); payRecord.setPayType(recordType); payRecord.setPayStatus(payStatus == null ? 3 : payStatus); payRecord.setPayError(erroMsg); payRecord.setPayErrorCode(code == null ? "bf00002" : code); payRecord.setOutTradeNo(Parms.get("trans_id")==null?Parms.get("msg_id"):Parms.get("trans_id")); payHttpUtil.payRecordImpl(payRecord); } } }