From 73b3813c2d110bf446f251350f120bb1e2b51d0c Mon Sep 17 00:00:00 2001 From: xiaoyong931011 <15274802129@163.com> Date: Tue, 10 Jan 2023 10:45:14 +0800 Subject: [PATCH] 20221227 充值归集 --- src/main/java/cc/mrbird/febs/pay/service/impl/UnipayServiceImpl.java | 421 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 416 insertions(+), 5 deletions(-) diff --git a/src/main/java/cc/mrbird/febs/pay/service/impl/UnipayServiceImpl.java b/src/main/java/cc/mrbird/febs/pay/service/impl/UnipayServiceImpl.java index 0aad1b6..f479a2d 100644 --- a/src/main/java/cc/mrbird/febs/pay/service/impl/UnipayServiceImpl.java +++ b/src/main/java/cc/mrbird/febs/pay/service/impl/UnipayServiceImpl.java @@ -1,25 +1,59 @@ package cc.mrbird.febs.pay.service.impl; -import cc.mrbird.febs.common.entity.FebsResponse; -import cc.mrbird.febs.pay.model.UnipayDto; +import cc.mrbird.febs.mall.entity.MallOrderInfo; +import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper; +import cc.mrbird.febs.pay.model.*; import cc.mrbird.febs.pay.service.UnipayService; -import cc.mrbird.febs.pay.util.HttpRequester; -import cc.mrbird.febs.pay.util.HttpRespons; +import cc.mrbird.febs.pay.util.*; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.IOException; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; import java.util.*; @Slf4j @Service public class UnipayServiceImpl implements UnipayService { + //汇聚支付平台公钥 + public static final String platformPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwSAEXsiC0IYh" + + "a6a94imKq8VfOkk7WjDRAQWMBRnoKOZeEUeMrHYiblcrqeMYXGpV13288iUOkuyKwkPXkYXyIQK8emvJIbQOhtB5bS" + + "lAbodsPgncM9Ney1GFiz+7ogBxyt58mP8AA9UHtMw7u78zZoQ1+dUWwUUowVXml3Q0cVQIDAQAB"; + //本地生成的公钥 + public static final String paySecretKey = + "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJSsoLHAy4P+H76l4i6IMZ/JKKTVphvrJBSB777N8h" + + "gzN38M+66IqazRQLNjjyn2UZxm4eSfuJ4OBxCTGLJgDOw8B9l9lVo+0bzhNxsy5ae20EOlQa3h8xfCjCCU" + + "Xb8VP8yknG43Wk1WtwLX5VYWmJFTwA1I0dWQR4RlbHH2q2aVAgMBAAECgYBZNyoK4JV/tFwaTHLo12Nn7g" + + "9MssRGFpmFEN/sEKuJKBrSS9kvx+SBxuPbgg/j72LTxs0hI1NmzSYiJRL53zeBFM0wM2/D2zW0pZfogUPN" + + "7Mb3FkFOoE0CxFwn7pjjBkvAsZQJS2fZFY6cf/WYhVI+XCMzjiQWJSQUXKEfWzUflQJBAMpLzinyAsBHKe" + + "6lmAkSh/yaQX76cnxNZGmfc/gj62qM5YDzpt3+Za5Y4NSq5kYu36NAgorf2ipJPRwpgS13fK8CQQC8JKVP" + + "2YgZ39fa+xVJu3yTT48k9EnYIEfsv/Bc7AVdpaZKDeEBuGpBb0JQzuIg3Zd6yNQCzH3oBqp8l6l/fgn7Ak" + + "EAtFluvHB4yWjoVk0lRPlTaP0w5P5ssKrimVPBtPh4+a4RMayHGKSjjBLKpm6SCwHg+Q8bEqpNOqO+qmvK" + + "MXm0GwJAZd4Bk8ZYJopIOUyRLibRQIFnI78Q7HAuAUW7QtSX4yh5bMcu+Nt8zIkNAuvBC8Ju7hAmmo1V7n" + + "cNgAAtydXYWQJALLOFCjCkRgeRVL8YE8bVi4U16b8ltAN1DlbWEzui6VFy2vIga3IryesNVAOOdornyAwf" + + "1huqB2lYfuQwtrIBKg=="; + public static final String MD5KEY = "2e95f6a3e11e47fa8a4386d6aefe1735"; public static final String notifyUrl = "http://47.111.90.145:8800/api/unipay/unipayCallBack"; + public static final String agreementPayNotifyUrl = "http://47.111.90.145:8800/api/unipay/agreeMentPayCallBack"; + public static final String singlePayNotifyUrl = "http://47.111.90.145:8800/api/unipay/singlePayCallBack"; + public static final String p1MerchantNo = "888118000001971";/** 商户编号 */ + public static final String aesKey = "1234567891234567";/** 商户编号 */ + + @Autowired + private MallOrderInfoMapper orderInfoMapper; @Override @Transactional @@ -27,7 +61,7 @@ String key = "2e95f6a3e11e47fa8a4386d6aefe1735";/** md5密钥商户后台-商户中心-商户设置-密钥管理获取 必填!*/ Map<String, String> map = new HashMap<String, String>(); map.put("p0_Version", "1.0");/** 版本号 */ - map.put("p1_MerchantNo", "888118000001971");/** 商户编号 */ + map.put("p1_MerchantNo", p1MerchantNo);/** 商户编号 */ map.put("p2_OrderNo", unipayDto.getOrderNo()); /**商户订单号*/ map.put("p3_Amount", unipayDto.getAmount().toString());/**订单金额*/ map.put("p4_Cur", "1"); /**交易币种 */ @@ -131,4 +165,381 @@ } + + + @Override + @Transactional + public String agreementPay(AgreementPayDto agreementPayDto) { + + String secretKey =paySecretKey; + String key = aesKey;//敏感信息加密key + + Map<String, Object> map = new HashMap<>(); + RequestParam requestParam = new RequestParam(); + requestParam.setMch_no(p1MerchantNo);// 商户编号 + requestParam.setMethod("fastPay.agreement.pay");// 固定方法名 + requestParam.setVersion("1.0");// 版本号 + requestParam.setRand_str("12345678901234567890123456789012");// 随机字符串 + requestParam.setSign_type("2");// 签名类型 + try { + requestParam.setSec_key(RSAUtil.encryptByPublicKey(platformPublicKey,aesKey));//加密密钥 + } catch (Exception e) { + e.printStackTrace(); + } + + map.put("mch_order_no",agreementPayDto.getOrderNo()); // 商户订单号 + map.put("order_amount", agreementPayDto.getOrderAmount()); // 订单金额;金额保留两位小数 + map.put("mch_req_time", agreementPayDto.getOrderTime()); // 订单时间 + map.put("order_desc", agreementPayDto.getOrderDesc()); // 商品名称 + map.put("callback_url", agreementPayNotifyUrl); // 异步通知地址 + map.put("bank_card_no", AESUtil.Aes256Encode(agreementPayDto.getBankNo(),aesKey)); // 签约银行卡号 + + requestParam.setData(JsonUtil.toString(map)); + + String signStr = null; + try { + signStr = getSortedString(requestParam); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("待签名字符串:"+signStr);// 待签名字符串 + + // 签名 + if (SignTypeEnum.RSA.getValue().equals(requestParam.getSign_type())) { + try { + signStr =(RSAUtil.sign(signStr, secretKey, false)); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + signStr = ""; + System.out.println("未预期的签名类型:" + requestParam.getSign_type()); + } + requestParam.setSign(signStr); + + // Map转json字符串 + String reqBodyJson = JSON.toJSONString(requestParam); + System.out.println(reqBodyJson); + String httpResponseJson = null; + try { + httpResponseJson = HttpClientUtil.sendHttpPost("https://api.joinpay.com/fastpay", reqBodyJson); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println(httpResponseJson); + + if(StrUtil.isNotBlank(httpResponseJson)){ + return httpResponseJson; + }else{ + return "fail"; + } + } + + @Override + @Transactional + public String singlePay(SinglePayDto singlePayDto) { + String singlePay = null; + String key = MD5KEY; + + Map<String, Object> map = new HashMap<>(); + map.put("userNo", p1MerchantNo);// 商户编号 + map.put("productCode", "BANK_PAY_DAILY_ORDER");//产品类型 + map.put("requestTime", DateUtil.now()); // 交易请求时间 + map.put("merchantOrderNo", singlePayDto.getMerchantOrderNo());//商户订单号 + map.put("receiverAccountNoEnc", singlePayDto.getReceiverAccountNoEncBankNo()); // 收款账户号 + map.put("receiverNameEnc", singlePayDto.getReceiverAccountNoEncName()); // 收款人 + map.put("receiverAccountType", singlePayDto.getReceiverAccountType());//账户类型 + map.put("paidAmount", singlePayDto.getPaidAmount()); //交易金额 + map.put("currency", singlePayDto.getCurrency());//币种 + map.put("isChecked", singlePayDto.getIsChecked());//是否复核 + map.put("paidDesc", singlePayDto.getPaidDesc());//代付说明 + map.put("paidUse", singlePayDto.getPaidUse());//代付用途 + map.put("callbackUrl", singlePayNotifyUrl);//商户通知地址 + + String reqSign = getRequestSign(map); + // 签名 + String hmac = Md5_Sign.SignByMD5(reqSign, key); + map.put("hmac", hmac);/** 签名数据 */ + + // Map转json字符串 + String reqBodyJson = JSON.toJSONString(map); + System.out.println("reqBodyJson:" + reqBodyJson); + String httpResponseJson = null; + try { + httpResponseJson = HttpClientUtil + .sendHttpPost("https://www.joinpay.com/payment/pay/singlePay",reqBodyJson); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println(httpResponseJson); + if(StrUtil.isNotBlank(httpResponseJson)){ + try { + singlePay = doResponseInfo(httpResponseJson, key); + } catch (Exception e) { + e.printStackTrace(); + } + return singlePay; + }else{ + return "fail"; + } + } + + /** + * 对单笔代付响应信息的处理 + * + * @param httpResponseJson 响应信息json字符串 + * @param key 商户秘钥 + * @throws Exception 异常实体类 + */ + @SuppressWarnings("unchecked") + private static String doResponseInfo(String httpResponseJson, String key) throws Exception { + // 响应信息map集合 + Map<String, Object> httpResponseMap = (Map<String, Object>) JSONObject.parse(httpResponseJson); + // 业务数据map集合 + Map<String, Object> dataMap = (Map<String, Object>) httpResponseMap.get("data"); + dataMap.put("statusCode", httpResponseMap.get("statusCode")); + dataMap.put("message", httpResponseMap.get("message")); + + // 请求签名串 + String reqSign = getRequestSign(httpResponseMap); + // 响应签名串 + String respSign = getResponseSign(dataMap); + // 请求数据的加密签名 + String reqHmac = Md5_Sign.SignByMD5(respSign, key); + // 请求数据的加密签名 + String respHmac = (String) dataMap.get("hmac"); + System.out.println("reqHmac:" + reqHmac); + System.out.println("respSign:" + respHmac); + + reqHmac=reqHmac.toUpperCase(); + respHmac=respHmac.toUpperCase(); + boolean isMatch = reqHmac.equals(respHmac); + if (isMatch) { + if("2001".equals(httpResponseMap.get("statusCode").toString()) + && ObjectUtil.isEmpty(dataMap.get("errorCode"))){ + System.out.println("验签成功"); + return dataMap.get("merchantOrderNo").toString(); + } + } + return "fail"; + } + + /** + * 获取响应数据签名串信息 + * 必须按新代付接口文档应答参数信息顺序来进行字符串的拼接,详情请参考新代付接口文档的应答报文 + * + * @param params 响应数据参数 + * @return 返回响应签名串 + */ + public static String getResponseSign(Map<String, Object> params) { + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(params.get("statusCode")).append(params.get("message")).append(params.get("errorCode")) + .append(params.get("errorDesc")).append(params.get("userNo")).append(params.get("merchantOrderNo")); + + return stringBuilder.toString(); + } + + /** + * 获取请求数据签名串信息 + * 必须按新代付接口文档请求参数信息顺序来进行字符串的拼接,详情请参考新代付接口文档请求报文 + * + * @param params 请求数据参数 + * @return 返回请求签名串 + */ + public static String getRequestSign(Map<String, Object> params) { + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(params.get("userNo")) + .append(params.get("productCode")) + .append(params.get("requestTime")) + .append(params.get("merchantOrderNo")) + .append(params.get("receiverAccountNoEnc")) + .append(params.get("receiverNameEnc")) + .append(params.get("receiverAccountType")) + .append(params.get("paidAmount")) + .append(params.get("currency")) + .append(params.get("isChecked")) + .append(params.get("paidDesc")) + .append(params.get("paidUse")) + .append(params.get("callbackUrl")); + System.out.println("reqSign:" + stringBuilder.toString()); + return stringBuilder.toString(); + } + + public static void main(String[] args) { +// BigDecimal value = new BigDecimal("0.10858").setScale(2,BigDecimal.ROUND_HALF_UP); + BigDecimal value = new BigDecimal("1231.1").setScale(2, BigDecimal.ROUND_DOWN); + DecimalFormat decimalFormat = new DecimalFormat("0.00#"); + String strVal = decimalFormat.format(value); + System.out.println(strVal); + } + + @Override + public String getAgreeMentPaySms(AgreeMentPaySmsDto agreeMentPaySmsDto) { + String secretKey = paySecretKey; + + Map<String, Object> map = new HashMap<>(); + RequestParam requestParam = new RequestParam(); + requestParam.setMch_no(p1MerchantNo);// 商户编号 + requestParam.setMethod("fastPay.agreement.signSms");// 固定方法名 + requestParam.setVersion("1.0");// 版本号 + requestParam.setRand_str("12345678901234567890123456789012");// 随机字符串 + requestParam.setSign_type("2");// 签名类型 + try { + requestParam.setSec_key(RSAUtil.encryptByPublicKey(platformPublicKey,aesKey));//加密密钥 + } catch (Exception e) { + e.printStackTrace(); + } + + + MallOrderInfo orderInfo = orderInfoMapper.selectByOrderNo(agreeMentPaySmsDto.getOrderNo()); + map.put("mch_order_no", "NO_"+orderInfo.getOrderNo()); // 商户订单号 + + BigDecimal value = orderInfo.getAmount().setScale(2, BigDecimal.ROUND_DOWN); + DecimalFormat decimalFormat = new DecimalFormat("0.00#"); + String strVal = decimalFormat.format(value); + map.put("order_amount", strVal); // 订单金额 + map.put("mch_req_time", DateUtil.now()); // 下单时间 + map.put("payer_name",AESUtil.Aes256Encode(agreeMentPaySmsDto.getName(),aesKey)); // 姓名 + map.put("id_type", agreeMentPaySmsDto.getIdType()); // 证件类型 + map.put("id_no", AESUtil.Aes256Encode(agreeMentPaySmsDto.getIdCardNum(),aesKey)); // 证件号码 + map.put("bank_card_no", AESUtil.Aes256Encode(agreeMentPaySmsDto.getBankNo(),aesKey)); // 银行卡号 + map.put("mobile_no", AESUtil.Aes256Encode(agreeMentPaySmsDto.getPhone(), aesKey)); // 手机号 + + requestParam.setData(JsonUtil.toString(map)); + + String signStr = null; + try { + signStr = getSortedString(requestParam); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("待签名字符串:"+signStr);// 待签名字符串 + + // 签名 + if (SignTypeEnum.RSA.getValue().equals(requestParam.getSign_type())) { + try { + signStr =(RSAUtil.sign(signStr, secretKey, false)); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + signStr = ""; + System.out.println("未预期的签名类型:" + requestParam.getSign_type()); + } + requestParam.setSign(signStr); + + + // Map转json字符串 + String reqBodyJson = JSON.toJSONString(requestParam); + System.out.println(reqBodyJson); + String httpResponseJson = null; + try { + httpResponseJson = HttpClientUtil.sendHttpPost("https://api.joinpay.com/fastpay", reqBodyJson); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println(httpResponseJson); + cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(httpResponseJson); + System.out.println(jsonObject); + String biz_code = jsonObject.get("biz_code").toString(); + String biz_msg = jsonObject.get("biz_msg").toString(); + if("JS000000".equals(biz_code)){ + return biz_code; + }else{ + return biz_msg; + } + } + + @Override + public String agreementSign(AgreementSignDto agreementSignDto) { + String secretKey = paySecretKey; + + Map<String, Object> map = new HashMap<>(); + RequestParam requestParam = new RequestParam(); + requestParam.setMch_no(p1MerchantNo);// 商户编号 + requestParam.setMethod("fastPay.agreement.smsSign");// 固定方法名 + requestParam.setVersion("1.0");// 版本号 + requestParam.setRand_str("12345678901234567890123456789012");// 随机字符串 + requestParam.setSign_type("2");// 签名类型 + try { + requestParam.setSec_key(RSAUtil.encryptByPublicKey(platformPublicKey,aesKey)); + } catch (Exception e) { + e.printStackTrace(); + } + + map.put("mch_order_no", "NO_"+agreementSignDto.getOrderNo()); // 商户订单号 + map.put("sms_code", agreementSignDto.getSmsCode()); // 签约短信验证码 + + requestParam.setData(JsonUtil.toString(map)); + + String signStr = null; + try { + signStr = getSortedString(requestParam); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println(signStr);// 待签名字符串 + + // 签名 + if (SignTypeEnum.RSA.getValue().equals(requestParam.getSign_type())) { + try { + signStr =(RSAUtil.sign(signStr, secretKey, false)); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + signStr = ""; + System.out.println("未预期的签名类型:" + requestParam.getSign_type()); + } + requestParam.setSign(signStr); + + + // Map转json字符串 + String reqBodyJson = JSON.toJSONString(requestParam); + System.out.println(reqBodyJson); + String httpResponseJson = null; + try { + httpResponseJson = HttpClientUtil.sendHttpPost("https://api.joinpay.com/fastpay", reqBodyJson); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println(httpResponseJson); + + if(StrUtil.isNotBlank(httpResponseJson)){ + return httpResponseJson; + }else{ + return "fail"; + } + } + + protected static String getSortedString(Object obj) throws Exception { + Field[] fields = obj.getClass().getDeclaredFields(); + + Map<String, String> map = new HashMap<String, String>(); + for (int i = 0; i < fields.length; i++) { + Field filed = fields[i]; + String name = filed.getName(); + if (SignUtil.NOT_SIGN_PARAM.contains(name)) {// 不参与签名或验签的参数直接跳过 + continue; + } + filed.setAccessible(true); + map.put(name, String.valueOf(filed.get(obj))); + } + StringBuffer content = new StringBuffer(); + List<String> keys = new ArrayList(map.keySet()); + Collections.sort(keys); // 排序map + for (int i = 0; i < keys.size(); i++) { + String key = keys.get(i); + String value = map.get(key); + + if (i != 0) { + content.append(SignUtil.SIGN_SEPARATOR); + } + content.append(key).append(SignUtil.SIGN_EQUAL).append(value); + } + return content.toString(); + } + } -- Gitblit v1.9.1