ソースを参照

支付优化中

wuxw 2 年 前
コミット
5494551a9e

+ 195 - 0
service-acct/src/main/java/com/java110/acct/payment/adapt/easypay/BasePay.java

@@ -0,0 +1,195 @@
+package com.java110.acct.payment.adapt.easypay;
+
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.java110.acct.payment.adapt.easypay.utils.RsaUtil;
+import com.java110.utils.util.StringUtil;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.*;
+
+/**
+ *  基础支付请求类,提供公共参数和方法信息
+ *
+ * @date: 2021/10/22 11:31
+ * @author: pandans
+ */
+public class BasePay extends Object{
+    /**
+     * 收银台请求地址
+     */
+    public static final String CASHIER_URL = "https://mtest.eycard.cn";
+//    public static final String CASHIER_URL = "http://10.10.14.128:8805";
+    /**
+     * 微收单优化业务请求地址
+     */
+    public static final String BASE_URL = "https://t-wapi.bhecard.com:8443";
+    /**
+     * 分账,退货地址
+     */
+    public static final String BASE_URL_LEDGER = "https://t-wapi.bhecard.com:6111";
+
+    /**
+     * 默认的接口签名方式
+     */
+    public static final String SIGN_TYPE_RSA256 = "RSA2";
+    public static final String SIGN_TYPE_RSA = "RSA";
+//
+
+    /**
+     * 接口返回成功代码
+     */
+    public static final String RET_CODE_SUCCESS = "000000";
+
+
+
+    /**
+     * 排序拼接需要签名的数据, !!参数值不为空且trim不为空。
+     *
+     * @param dataObj 数据对象 不能都为空
+     * @return 签名排序字符串
+     */
+    public static String getReqStr(Object dataObj) {
+
+        JSONObject data = (JSONObject) JSON.toJSON(dataObj);
+
+//        data = JSONObject.parseObject("{\"tradeAmt\":\"9\",\"orgBackUrl\":\"https://pay-test.jian9999.cn/gateway/notify/EASYPAYALIPAY\",\"splitSettleFlag\":\"1\",\"payerId\":\"123123123\",\"orderInfo\":\"购买苹果手机一个\",\"tradeCode\":\"WUJS1\"}");
+
+        Set<String> keySet = data.keySet();
+        String[] keyArray = keySet.toArray(new String[keySet.size()]);
+        Arrays.sort(keyArray);
+        StringBuilder sb = new StringBuilder();
+        for (String k : keyArray) {
+            // 参数值为空,则不参与签名
+            if (data.get(k) != null && data.get(k).toString().trim().length() > 0) {
+                sb.append(k).append("=").append(data.get(k).toString().trim()).append("&");
+            }
+        }
+        return sb.substring(0, sb.toString().lastIndexOf("&"));
+    }
+
+    /**
+     * 验证易生返回的报文数据. !!!使用data字段的内容验签
+     *
+     * @param response 易生返回的数据
+     * @return 验签是否成功
+     */
+    public static boolean checkSign(String response,String EASYPAY_PUBLIC_KEY) {
+        JSONObject json = JSON.parseObject(response);
+        // 云易收sysRetCode 和 微收单 sysRetcode
+        if ("000000".equals(json.getString("sysRetcode")) || "000000".equals(json.getString("sysRetCode"))) {
+            String sign = json.getString("sign");
+            if (StringUtil.isEmpty(sign)) {
+                System.out.println("=====> 签名失败,该报文未返回签名数据");
+                return false;
+            }
+            JSONObject jsonData = json.getJSONObject("data");
+            boolean ret = RsaUtil.verifyBySHA256WithRSA(getReqStr(jsonData), sign, EASYPAY_PUBLIC_KEY);
+
+            if (ret) {
+                System.out.println("=====> 验签成功,接口数据安全");
+                return true;
+            } else {
+                System.out.println("=====> 验签失败,请注意报文安全");
+                return false;
+            }
+        } else {
+            System.out.println("=====> 非00状态码,不需要验签");
+
+            return false;
+        }
+    }
+    public static boolean checkBizSign(String response,String EASYPAY_PUBLIC_KEY) {
+        JSONObject json = JSON.parseObject(response);
+        // 云易收sysRetCode 和 微收单 sysRetcode
+        if ("000000".equals(json.getString("sysRetcode")) || "000000".equals(json.getString("sysRetCode"))) {
+            String sign = json.getString("sign");
+            if (StringUtil.isEmpty(sign)) {
+                System.out.println("=====> 签名失败,该报文未返回签名数据");
+                return false;
+            }
+            JSONObject jsonData = json.getJSONObject("bizData");
+            boolean ret = RsaUtil.verifyBySHA256WithRSA(getReqStr(jsonData), sign, EASYPAY_PUBLIC_KEY);
+
+            if (ret) {
+                System.out.println("=====> 验签成功,接口数据安全");
+                return true;
+            } else {
+                System.out.println("=====> 验签失败,请注意报文安全");
+                return false;
+            }
+        } else {
+            System.out.println("=====> 非00状态码,不需要验签");
+
+            return false;
+        }
+    }
+
+    /**
+     * 使用商户的私钥进行加签
+     *
+     * @param data: 签名数据,注意这里仅仅是文档中data字段的内容
+     * @return java.lang.String 签名
+     */
+    public static String sign(Object data, String signKey) {
+        String reqStr = getReqStr(data);
+        String res = RsaUtil.signBySHA256WithRSA(reqStr, signKey);
+        return res;
+    }
+
+    public static String signStr(String data, String signKey) {
+        return sign(JSON.parseObject(data), signKey);
+    }
+
+    /**
+     * 计算sign
+     * @param request 请求内容不包含sign
+     * @param signKey 签名key
+     */
+    public static String calSign(Map<String, Object> request, String signKey) {
+        Set<String> keySet = request.keySet();
+        TreeSet<String> treeSet = new TreeSet<>(keySet);
+        StringBuilder stringBuilder = new StringBuilder();
+        for(String key : treeSet) {
+            if(!"MAC".equals(key) && !StringUtil.isEmpty(request.get(key).toString())) {
+                stringBuilder.append(key).append("=").append(request.get(key)).append("&");
+            }
+        }
+        stringBuilder.append("key=").append(signKey);
+        String str = stringBuilder.toString();
+        System.out.println("待签名字段::====>" + str);
+        String md5 = calMD5(str);
+        return md5;
+    }
+
+    /**
+     * MD5 算法
+     * @param data 待计算源数据
+     * @return md5值
+     */
+    public static String calMD5(String data) {
+        try {
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            md.update(data.getBytes(StandardCharsets.UTF_8));
+            return toHexString(md.digest()).toUpperCase();
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static final char[] HEX_CHAR = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+    public static String toHexString(byte[] bytes) {
+        char[] buf =  new char[bytes.length * 2];
+        int index = 0;
+        for(byte b: bytes) {
+            buf[index++] = HEX_CHAR[b >>> 4 & 0xf];
+            buf[index++] = HEX_CHAR[b & 0xf];
+        }
+        return new String(buf);
+    }
+
+}

+ 279 - 0
service-acct/src/main/java/com/java110/acct/payment/adapt/easypay/EasyNativeQrcodePaymentFactoryAdapt.java

@@ -0,0 +1,279 @@
+package com.java110.acct.payment.adapt.easypay;
+
+import com.alibaba.fastjson.JSONObject;
+import com.java110.acct.payment.IPaymentFactoryAdapt;
+import com.java110.acct.payment.adapt.bbgpay.EncryptDecryptFactory;
+import com.java110.acct.payment.adapt.bbgpay.lib.GmUtil;
+import com.java110.acct.payment.adapt.bbgpay.lib.JsonUtil;
+import com.java110.core.context.ICmdDataFlowContext;
+import com.java110.core.factory.GenerateCodeFactory;
+import com.java110.core.factory.WechatFactory;
+import com.java110.core.log.LoggerFactory;
+import com.java110.dto.payment.NotifyPaymentOrderDto;
+import com.java110.dto.payment.PaymentOrderDto;
+import com.java110.dto.paymentPoolValue.PaymentPoolValueDto;
+import com.java110.dto.wechat.OnlinePayDto;
+import com.java110.dto.wechat.SmallWeChatDto;
+import com.java110.intf.acct.IOnlinePayV1InnerServiceSMO;
+import com.java110.intf.acct.IPaymentPoolValueV1InnerServiceSMO;
+import com.java110.intf.store.ISmallWechatV1InnerServiceSMO;
+import com.java110.intf.user.IOwnerAppUserInnerServiceSMO;
+import com.java110.po.wechat.OnlinePayPo;
+import com.java110.utils.cache.MappingCache;
+import com.java110.utils.cache.UrlCache;
+import com.java110.utils.constant.MappingConstant;
+import com.java110.utils.constant.WechatConstant;
+import com.java110.utils.util.BeanConvertUtil;
+import com.java110.utils.util.PayUtil;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.*;
+
+/**
+ * 北部湾银行支付厂家
+ * https://doc.eycard.cn/web/#/285?page_id=4148
+ */
+@Service("easyNativeQrcodePaymentFactoryAdapt")
+public class EasyNativeQrcodePaymentFactoryAdapt implements IPaymentFactoryAdapt {
+
+    private static final Logger logger = LoggerFactory.getLogger(EasyNativeQrcodePaymentFactoryAdapt.class);
+
+
+    //微信支付
+    public static final String DOMAIN_WECHAT_PAY = "WECHAT_PAY";
+    // 微信服务商支付开关
+    public static final String WECHAT_SERVICE_PAY_SWITCH = "WECHAT_SERVICE_PAY_SWITCH";
+
+    //开关ON打开
+    public static final String WECHAT_SERVICE_PAY_SWITCH_ON = "ON";
+
+
+    private static final String WECHAT_SERVICE_APP_ID = "SERVICE_APP_ID";
+
+    private static final String WECHAT_SERVICE_MCH_ID = "SERVICE_MCH_ID";
+
+    public static final String TRADE_TYPE_NATIVE = "NATIVE";
+    public static final String TRADE_TYPE_JSAPI = "JSAPI";
+    public static final String TRADE_TYPE_MWEB = "MWEB";
+    public static final String TRADE_TYPE_APP = "APP";
+
+    private static String VERSION = "1.0";
+
+    private static String SIGN_TYPE = "RSA2";// 加密算法:SM4、RSA2
+
+    private static String gzhPayUrl = "https://mbank.bankofbbg.com/www/corepaycer/getQrcodeLink";
+
+    @Autowired
+    private ISmallWechatV1InnerServiceSMO smallWechatV1InnerServiceSMOImpl;
+
+
+    @Autowired
+    private IOwnerAppUserInnerServiceSMO ownerAppUserInnerServiceSMOImpl;
+
+
+    @Autowired
+    private IOnlinePayV1InnerServiceSMO onlinePayV1InnerServiceSMOImpl;
+
+    @Autowired
+    private RestTemplate outRestTemplate;
+    @Autowired
+    private IPaymentPoolValueV1InnerServiceSMO paymentPoolValueV1InnerServiceSMOImpl;
+
+    @Override
+    public Map java110Payment(PaymentOrderDto paymentOrderDto, JSONObject reqJson, ICmdDataFlowContext context) throws Exception {
+
+        SmallWeChatDto smallWeChatDto = getSmallWechat(reqJson);
+        String paymentPoolId = reqJson.getString("paymentPoolId");
+
+        String appId = context.getReqHeaders().get("app-id");
+        String userId = context.getReqHeaders().get("user-id");
+        String tradeType = reqJson.getString("tradeType");
+        String notifyUrl = UrlCache.getOwnerUrl() + "/app/payment/notify/nativeWechat/992020011134400001/" + paymentPoolId;
+
+
+        logger.debug("【小程序支付】 统一下单开始, 订单编号=" + paymentOrderDto.getOrderId());
+        SortedMap<String, String> resultMap = new TreeMap<String, String>();
+        //生成支付金额,开发环境处理支付金额数到0.01、0.02、0.03元
+        double payAmount = PayUtil.getPayAmountByEnv(MappingCache.getValue(MappingConstant.ENV_DOMAIN, "HC_ENV"), paymentOrderDto.getMoney());
+        //添加或更新支付记录(参数跟进自己业务需求添加)
+
+        Map<String, String> resMap = null;
+        resMap = this.java110UnifieldOrder(paymentOrderDto.getName(),
+                paymentOrderDto.getOrderId(),
+                payAmount,
+                smallWeChatDto,
+                paymentPoolId,
+                notifyUrl
+        );
+
+
+        return resMap;
+    }
+
+
+    private Map<String, String> java110UnifieldOrder(String feeName, String orderNum,
+                                                     double payAmount,
+                                                     SmallWeChatDto smallWeChatDto,
+                                                     String paymentPoolId,
+                                                     String notifyUrl) throws Exception {
+
+        PaymentPoolValueDto paymentPoolValueDto = new PaymentPoolValueDto();
+        paymentPoolValueDto.setPpId(paymentPoolId);
+        List<PaymentPoolValueDto> paymentPoolValueDtos = paymentPoolValueV1InnerServiceSMOImpl.queryPaymentPoolValues(paymentPoolValueDto);
+
+        if (paymentPoolValueDtos == null || paymentPoolValueDtos.isEmpty()) {
+            throw new IllegalArgumentException("配置错误,未配置参数");
+        }
+
+        String ORGID = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "ORGID"); // 客户编号
+        String ORGMERCODE = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "ORGMERCODE");
+        String ORGTERMNO = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "ORGTERMNO");
+        String EASYPAY_PUBLIC_KEY = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "EASYPAY_PUBLIC_KEY");
+        String MER_RSA_PRIVATE_KEY = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "MER_RSA_PRIVATE_KEY");
+
+        if (feeName.length() > 127) {
+            feeName = feeName.substring(0, 126);
+        }
+
+
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("version", VERSION);// 版本号 1.0
+        params.put("mcht_no", ORGID);// 收款商户编号
+        params.put("product_no", ORGMERCODE);// 产品编号
+        params.put("qr_type", "DYNAMIC");// 业务类型
+        params.put("txn_type", "0");// 交易类型 0-实时;1-担保
+        params.put("tran_no", orderNum);// 商户流水
+        params.put("amt", payAmount);// 交易金额
+        params.put("ware_name", feeName);// 商品名称
+        params.put("ware_describe", "");// 商户数据包
+        params.put("trx_trm_no", "");// 交易终端编号
+        params.put("trans_source", "09");// 08:商户线下扫码09:商户线上收银10:一案一户缴款11:维修资金缴款12:房屋预售缴款
+        params.put("asyn_url", notifyUrl + "?wId=" + WechatFactory.getWId(smallWeChatDto.getAppId()));// 通知地址
+
+        String decryParams = EncryptDecryptFactory.execute(paymentPoolValueDtos, gzhPayUrl, params);
+        JSONObject paramOut = JSONObject.parseObject(decryParams);
+        if (!"SUCCESS".equals(paramOut.getString("status"))
+                        || !"SUCCESS".equals(paramOut.getString("deal_status"))) {
+            throw new IllegalArgumentException("支付失败" + paramOut.getString("return_message"));
+        }
+
+        if (!"0000".equals(paramOut.getString("return_code"))
+                && !"0001".equals(paramOut.getString("return_code"))
+        ) {
+            throw new IllegalArgumentException("支付失败" + paramOut.getString("return_message"));
+        }
+        SortedMap<String, String> resultMap = new TreeMap<String, String>();
+        resultMap.put("prepayId", paramOut.getString("tran_no"));
+        resultMap.put("codeUrl", paramOut.getString("qr_link"));
+        resultMap.put("code", "0");
+        resultMap.put("msg", "下单成功");
+        doSaveOnlinePay(smallWeChatDto, "无", orderNum, feeName, payAmount, OnlinePayDto.STATE_WAIT, "待支付");
+
+        return resultMap;
+    }
+
+
+    @Override
+    public PaymentOrderDto java110NotifyPayment(NotifyPaymentOrderDto notifyPaymentOrderDto) {
+
+        PaymentPoolValueDto paymentPoolValueDto = new PaymentPoolValueDto();
+        paymentPoolValueDto.setPpId(notifyPaymentOrderDto.getPaymentPoolId());
+        paymentPoolValueDto.setCommunityId(notifyPaymentOrderDto.getCommunityId());
+        List<PaymentPoolValueDto> paymentPoolValueDtos = paymentPoolValueV1InnerServiceSMOImpl.queryPaymentPoolValues(paymentPoolValueDto);
+
+
+        if (paymentPoolValueDtos == null || paymentPoolValueDtos.isEmpty()) {
+            throw new IllegalArgumentException("配置错误,未配置参数");
+        }
+        String privateKey_SM4 = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "privateKey_SM4");
+
+        String resXml = "";
+        String param = notifyPaymentOrderDto.getParam();
+        PaymentOrderDto paymentOrderDto = new PaymentOrderDto();
+        // 开始解密
+        Map<String, Object> responseParams = JsonUtil.jsonToMap(param);
+        if (!responseParams.containsKey("enc_data")) {
+            System.err.println("通知失败");
+            throw new IllegalArgumentException("通知失败");
+        }
+        String decryptStr = (String) responseParams.get("enc_data");
+        String messageKey = (String) responseParams.get("message_key");
+        String secretKey = GmUtil.decryptSm2(messageKey, privateKey_SM4);
+        if (secretKey == null) {
+            System.err.println("解密失败");
+            throw new IllegalArgumentException("解密失败");
+        }
+        String decryParams = GmUtil.decryptSm4(decryptStr, secretKey);
+
+        System.out.println("支付结果返回值(解密后):" + decryParams);
+
+        JSONObject paramOut = JSONObject.parseObject(decryParams);
+        String outTradeNo = paramOut.get("tran_no").toString();
+        paymentOrderDto.setOrderId(outTradeNo);
+        paymentOrderDto.setTransactionId(paramOut.get("txn_no").toString());
+
+        doUpdateOnlinePay(outTradeNo, OnlinePayDto.STATE_COMPILE, "支付成功");
+
+        JSONObject resJson = new JSONObject();
+        resJson.put("return_code", "SUCCESS");
+        resJson.put("return message", "成功");
+
+        paymentOrderDto.setResponseEntity(new ResponseEntity<String>(resJson.toJSONString(), HttpStatus.OK));
+        return paymentOrderDto;
+    }
+
+    private SmallWeChatDto getSmallWechat(JSONObject paramIn) {
+
+        SmallWeChatDto smallWeChatDto = new SmallWeChatDto();
+        smallWeChatDto.setObjId(paramIn.getString("communityId"));
+        smallWeChatDto.setAppId(paramIn.getString("appId"));
+        smallWeChatDto.setPage(1);
+        smallWeChatDto.setRow(1);
+        List<SmallWeChatDto> smallWeChatDtos = smallWechatV1InnerServiceSMOImpl.querySmallWechats(smallWeChatDto);
+
+        if (smallWeChatDtos == null || smallWeChatDtos.size() < 1) {
+            smallWeChatDto = new SmallWeChatDto();
+            smallWeChatDto.setAppId(MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, "appId"));
+            smallWeChatDto.setAppSecret(MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, "appSecret"));
+            smallWeChatDto.setMchId(MappingCache.getValue(MappingConstant.WECHAT_STORE_DOMAIN, "mchId"));
+            smallWeChatDto.setPayPassword(MappingCache.getValue(MappingConstant.WECHAT_STORE_DOMAIN, "key"));
+            smallWeChatDto.setObjId(paramIn.getString("communityId"));
+
+            return smallWeChatDto;
+        }
+
+        return BeanConvertUtil.covertBean(smallWeChatDtos.get(0), SmallWeChatDto.class);
+    }
+
+
+    private void doUpdateOnlinePay(String orderId, String state, String message) {
+        OnlinePayPo onlinePayPo = new OnlinePayPo();
+        onlinePayPo.setMessage(message.length() > 1000 ? message.substring(0, 1000) : message);
+        onlinePayPo.setOrderId(orderId);
+        onlinePayPo.setState(state);
+        onlinePayV1InnerServiceSMOImpl.updateOnlinePay(onlinePayPo);
+    }
+
+    private void doSaveOnlinePay(SmallWeChatDto smallWeChatDto, String openId, String orderId, String feeName, double money, String state, String message) {
+        OnlinePayPo onlinePayPo = new OnlinePayPo();
+        onlinePayPo.setAppId(smallWeChatDto.getAppId());
+        onlinePayPo.setMchId(smallWeChatDto.getMchId());
+        onlinePayPo.setMessage(message.length() > 1000 ? message.substring(0, 1000) : message);
+        onlinePayPo.setOpenId(openId);
+        onlinePayPo.setOrderId(orderId);
+        onlinePayPo.setPayId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_orderId));
+        onlinePayPo.setPayName(feeName);
+        onlinePayPo.setRefundFee("0");
+        onlinePayPo.setState(state);
+        onlinePayPo.setTotalFee(money + "");
+        onlinePayPo.setTransactionId(orderId);
+        onlinePayV1InnerServiceSMOImpl.saveOnlinePay(onlinePayPo);
+    }
+
+}

+ 347 - 0
service-acct/src/main/java/com/java110/acct/payment/adapt/easypay/EasyPaymentFactoryAdapt.java

@@ -0,0 +1,347 @@
+package com.java110.acct.payment.adapt.easypay;
+
+import com.alibaba.fastjson.JSONObject;
+import com.java110.acct.payment.IPaymentFactoryAdapt;
+import com.java110.acct.payment.adapt.bbgpay.EncryptDecryptFactory;
+import com.java110.acct.payment.adapt.bbgpay.lib.GmUtil;
+import com.java110.acct.payment.adapt.bbgpay.lib.JsonUtil;
+import com.java110.acct.payment.adapt.easypay.utils.HttpConnectUtils;
+import com.java110.core.context.ICmdDataFlowContext;
+import com.java110.core.factory.GenerateCodeFactory;
+import com.java110.core.factory.WechatFactory;
+import com.java110.core.log.LoggerFactory;
+import com.java110.dto.app.AppDto;
+import com.java110.dto.owner.OwnerAppUserDto;
+import com.java110.dto.payment.NotifyPaymentOrderDto;
+import com.java110.dto.payment.PaymentOrderDto;
+import com.java110.dto.paymentPoolValue.PaymentPoolValueDto;
+import com.java110.dto.wechat.OnlinePayDto;
+import com.java110.dto.wechat.SmallWeChatDto;
+import com.java110.intf.acct.IOnlinePayV1InnerServiceSMO;
+import com.java110.intf.acct.IPaymentPoolValueV1InnerServiceSMO;
+import com.java110.intf.store.ISmallWechatV1InnerServiceSMO;
+import com.java110.intf.user.IOwnerAppUserInnerServiceSMO;
+import com.java110.po.wechat.OnlinePayPo;
+import com.java110.utils.cache.MappingCache;
+import com.java110.utils.cache.UrlCache;
+import com.java110.utils.constant.MappingConstant;
+import com.java110.utils.constant.WechatConstant;
+import com.java110.utils.util.BeanConvertUtil;
+import com.java110.utils.util.PayUtil;
+import com.java110.utils.util.StringUtil;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * 北部湾银行支付厂家
+ * <p>
+ * https://doc.eycard.cn/web/#/285?page_id=4149
+ */
+@Service("easyPaymentFactoryAdapt")
+public class EasyPaymentFactoryAdapt implements IPaymentFactoryAdapt {
+
+    private static final Logger logger = LoggerFactory.getLogger(EasyPaymentFactoryAdapt.class);
+
+
+    //微信支付
+    public static final String DOMAIN_WECHAT_PAY = "WECHAT_PAY";
+    // 微信服务商支付开关
+    public static final String WECHAT_SERVICE_PAY_SWITCH = "WECHAT_SERVICE_PAY_SWITCH";
+
+    //开关ON打开
+    public static final String WECHAT_SERVICE_PAY_SWITCH_ON = "ON";
+
+
+    private static final String WECHAT_SERVICE_APP_ID = "SERVICE_APP_ID";
+
+    private static final String WECHAT_SERVICE_MCH_ID = "SERVICE_MCH_ID";
+
+    public static final String TRADE_TYPE_NATIVE = "NATIVE";
+    public static final String TRADE_TYPE_JSAPI = "JSAPI";
+    public static final String TRADE_TYPE_MWEB = "MWEB";
+    public static final String TRADE_TYPE_APP = "APP";
+
+    private static String VERSION = "1.0";
+
+    private static String SIGN_TYPE = "RSA2";// 加密算法:SM4、RSA2
+
+    private static String gzhPayUrl = "https://mbank.bankofbbg.com/www/corepaycer/WxGzhPay";
+
+    @Autowired
+    private ISmallWechatV1InnerServiceSMO smallWechatV1InnerServiceSMOImpl;
+
+
+    @Autowired
+    private IOwnerAppUserInnerServiceSMO ownerAppUserInnerServiceSMOImpl;
+
+
+    @Autowired
+    private IOnlinePayV1InnerServiceSMO onlinePayV1InnerServiceSMOImpl;
+
+    @Autowired
+    private RestTemplate outRestTemplate;
+
+    @Autowired
+    private IPaymentPoolValueV1InnerServiceSMO paymentPoolValueV1InnerServiceSMOImpl;
+
+
+    @Override
+    public Map java110Payment(PaymentOrderDto paymentOrderDto, JSONObject reqJson, ICmdDataFlowContext context) throws Exception {
+
+        SmallWeChatDto smallWeChatDto = getSmallWechat(reqJson);
+        String paymentPoolId = reqJson.getString("paymentPoolId");
+
+
+        String appId = context.getReqHeaders().get("app-id");
+        String userId = context.getReqHeaders().get("user-id");
+        String tradeType = reqJson.getString("tradeType");
+        String notifyUrl = UrlCache.getOwnerUrl() + "/app/payment/notify/wechat/992020011134400001/" + paymentPoolId;
+
+        String openId = reqJson.getString("openId");
+
+
+        if (StringUtil.isEmpty(openId)) {
+            String appType = OwnerAppUserDto.APP_TYPE_WECHAT_MINA;
+            if (AppDto.WECHAT_OWNER_APP_ID.equals(appId)) {
+                appType = OwnerAppUserDto.APP_TYPE_WECHAT;
+            } else if (AppDto.WECHAT_MINA_OWNER_APP_ID.equals(appId)) {
+                appType = OwnerAppUserDto.APP_TYPE_WECHAT_MINA;
+            } else {
+                appType = OwnerAppUserDto.APP_TYPE_APP;
+            }
+
+            OwnerAppUserDto ownerAppUserDto = new OwnerAppUserDto();
+            ownerAppUserDto.setUserId(userId);
+            ownerAppUserDto.setAppType(appType);
+            List<OwnerAppUserDto> ownerAppUserDtos = ownerAppUserInnerServiceSMOImpl.queryOwnerAppUsers(ownerAppUserDto);
+
+            if (ownerAppUserDtos == null || ownerAppUserDtos.size() < 1) {
+                throw new IllegalArgumentException("未找到开放账号信息");
+            }
+            openId = ownerAppUserDtos.get(0).getOpenId();
+        }
+
+
+        logger.debug("【小程序支付】 统一下单开始, 订单编号=" + paymentOrderDto.getOrderId());
+        SortedMap<String, String> resultMap = new TreeMap<String, String>();
+        //生成支付金额,开发环境处理支付金额数到0.01、0.02、0.03元
+        double payAmount = PayUtil.getPayAmountByEnv(MappingCache.getValue(MappingConstant.ENV_DOMAIN, "HC_ENV"), paymentOrderDto.getMoney());
+        //添加或更新支付记录(参数跟进自己业务需求添加)
+
+        JSONObject resMap = null;
+        resMap = this.java110UnifieldOrder(paymentOrderDto.getName(),
+                paymentOrderDto.getOrderId(),
+                tradeType,
+                payAmount,
+                openId,
+                smallWeChatDto,
+                paymentPoolId,
+                notifyUrl
+        );
+
+
+        if (TRADE_TYPE_JSAPI.equals(tradeType)) {
+            resultMap.putAll(JSONObject.toJavaObject(resMap, Map.class));
+            resultMap.put("sign", resultMap.get("paySign"));
+        } else if (TRADE_TYPE_APP.equals(tradeType)) {
+            resultMap.put("appId", smallWeChatDto.getAppId());
+            resultMap.put("timeStamp", PayUtil.getCurrentTimeStamp());
+            resultMap.put("nonceStr", PayUtil.makeUUID(32));
+            resultMap.put("partnerid", smallWeChatDto.getMchId());
+            resultMap.put("prepayid", resMap.getString("session_id"));
+            //resultMap.put("signType", "MD5");
+            resultMap.put("sign", PayUtil.createSign(resultMap, smallWeChatDto.getPayPassword()));
+        } else if (TRADE_TYPE_NATIVE.equals(tradeType)) {
+            resultMap.put("prepayId", resMap.getString("session_id"));
+            resultMap.put("codeUrl", resMap.getString("qr_code"));
+        }
+        resultMap.put("code", "0");
+        resultMap.put("msg", "下单成功");
+        logger.info("【小程序支付】统一下单成功,返回参数:" + resultMap);
+        return resultMap;
+    }
+
+
+    private JSONObject java110UnifieldOrder(String feeName, String orderNum,
+                                            String tradeType, double payAmount, String openid,
+                                            SmallWeChatDto smallWeChatDto,
+                                            String paymentPoolId,
+                                            String notifyUrl) throws Exception {
+        PaymentPoolValueDto paymentPoolValueDto = new PaymentPoolValueDto();
+        paymentPoolValueDto.setPpId(paymentPoolId);
+        List<PaymentPoolValueDto> paymentPoolValueDtos = paymentPoolValueV1InnerServiceSMOImpl.queryPaymentPoolValues(paymentPoolValueDto);
+
+        if (paymentPoolValueDtos == null || paymentPoolValueDtos.isEmpty()) {
+            throw new IllegalArgumentException("配置错误,未配置参数");
+        }
+
+        String ORGID = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "ORGID"); // 客户编号
+        String ORGMERCODE = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "ORGMERCODE");
+        String ORGTERMNO = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "ORGTERMNO");
+        String EASYPAY_PUBLIC_KEY = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "EASYPAY_PUBLIC_KEY");
+        String MER_RSA_PRIVATE_KEY = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "MER_RSA_PRIVATE_KEY");
+
+
+        if (feeName.length() > 127) {
+            feeName = feeName.substring(0, 126);
+        }
+
+        JsApi.DataBean dataBean = new JsApi.DataBean();
+        dataBean.setOrgFrontUrl(UrlCache.getOwnerUrl());
+        dataBean.setOrgBackUrl(notifyUrl + "?wId=" + WechatFactory.getWId(smallWeChatDto.getAppId()));
+
+        // tradeCode 只有  WAJS1:支付宝-生活号支付;WAJS2:支付宝-小程序支付;WTJS1:微信-公众号支付;
+        // WTJS2:微信-小程序支付;WUJS1:银联二维码-JS支付(payerId 传入 仿真app的 用户名,比如admin4)   这几种选择
+
+        dataBean.setTradeCode("WTJS2");
+        // 金额,单位分;取值范围:1-10000000000
+
+        dataBean.setPayerId(openid);  // 凯杰 微信
+        dataBean.setWxSubAppid(smallWeChatDto.getAppid());         // 凯杰 微信
+
+        //订单信息(订单明细内容,如订单标题、订单描述等)
+        dataBean.setOrderInfo(feeName);
+        dataBean.setTradeAmt(Integer.parseInt(PayUtil.moneyToIntegerStr(payAmount)));
+        //订单支付超时时间;长度:8。单位:秒, 不填默认为300(5分钟)
+        //dataBean.setTimeoutMinutes(300);
+
+        JsApi request = new JsApi();
+        request.setOrgId(ORGID);
+        request.setOrgMercode(ORGMERCODE);
+        request.setOrgTermno(ORGTERMNO);
+        request.setSignType(BasePay.SIGN_TYPE_RSA256);
+        // 交易流水,28位定长,规则:orgId 前四位+后四位+yyyyMMddhhmmss+6位自定义 合计28位长度(唯一)
+        request.setOrgTrace(orderNum);
+
+        //request.setAppendData(appendData);
+
+        request.setData(dataBean);
+        // 使用商户私钥对data字段加签
+        String sign = BasePay.sign(dataBean, MER_RSA_PRIVATE_KEY);
+        request.setSign(sign);
+
+        String requestStr = JSONObject.toJSONString(request);
+
+        System.out.println("反反复复:" + requestStr);
+        String response = "";
+
+        response = HttpConnectUtils.sendHttpSRequest(BasePay.BASE_URL + "/standard/jsapi", requestStr, "JSON", null);
+        System.out.println("\n响应报文:" + response);
+        BasePay.checkSign(response, EASYPAY_PUBLIC_KEY);
+
+        JSONObject paramOut = JSONObject.parseObject(response);
+        if (!"000000".equals(paramOut.getString("sysRetcode"))) {
+            throw new IllegalArgumentException("支付失败" + paramOut.getString("sysRetmsg"));
+        }
+
+        JSONObject data = paramOut.getJSONObject("data");
+
+        if (!"10000".equals(paramOut.getJSONObject("data").getString("appendRetcode"))) {
+            throw new IllegalArgumentException("支付失败" + paramOut.getJSONObject("data").getString("appendRetmsg"));
+        }
+
+        //wxWcPayData
+        String wxWcPayData = data.getString("wxWcPayData");
+
+        return JSONObject.parseObject(wxWcPayData);
+    }
+
+
+    @Override
+    public PaymentOrderDto java110NotifyPayment(NotifyPaymentOrderDto notifyPaymentOrderDto) {
+
+        PaymentPoolValueDto paymentPoolValueDto = new PaymentPoolValueDto();
+        paymentPoolValueDto.setPpId(notifyPaymentOrderDto.getPaymentPoolId());
+        paymentPoolValueDto.setCommunityId(notifyPaymentOrderDto.getCommunityId());
+        List<PaymentPoolValueDto> paymentPoolValueDtos = paymentPoolValueV1InnerServiceSMOImpl.queryPaymentPoolValues(paymentPoolValueDto);
+
+
+        if (paymentPoolValueDtos == null || paymentPoolValueDtos.isEmpty()) {
+            throw new IllegalArgumentException("配置错误,未配置参数");
+        }
+        String EASYPAY_PUBLIC_KEY = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "EASYPAY_PUBLIC_KEY");
+
+        String param = notifyPaymentOrderDto.getParam();
+        System.out.println("支付结果返回值:" + param);
+
+        JSONObject paramJson = JSONObject.parseObject(param);
+
+        String sign = BasePay.calSign(paramJson, EASYPAY_PUBLIC_KEY);
+
+        if (!sign.equals(paramJson.getString("sign"))) {
+            throw new IllegalArgumentException("签名错误");
+        }
+
+        JSONObject paramOut = paramJson.getJSONObject("data");
+
+
+        PaymentOrderDto paymentOrderDto = new PaymentOrderDto();
+
+        String outTradeNo = paramOut.getString("oriOrgTrace");
+        paymentOrderDto.setOrderId(outTradeNo);
+        paymentOrderDto.setTransactionId(paramOut.getString("outTrace"));
+
+        doUpdateOnlinePay(outTradeNo, OnlinePayDto.STATE_COMPILE, "支付成功");
+
+        JSONObject resJson = new JSONObject();
+        resJson.put("return_code", "SUCCESS");
+        resJson.put("return message", "成功");
+
+        paymentOrderDto.setResponseEntity(new ResponseEntity<String>(resJson.toJSONString(), HttpStatus.OK));
+        return paymentOrderDto;
+    }
+
+    private SmallWeChatDto getSmallWechat(JSONObject paramIn) {
+
+        SmallWeChatDto smallWeChatDto = new SmallWeChatDto();
+        smallWeChatDto.setObjId(paramIn.getString("communityId"));
+        smallWeChatDto.setAppId(paramIn.getString("appId"));
+        smallWeChatDto.setPage(1);
+        smallWeChatDto.setRow(1);
+        List<SmallWeChatDto> smallWeChatDtos = smallWechatV1InnerServiceSMOImpl.querySmallWechats(smallWeChatDto);
+
+        if (smallWeChatDtos == null || smallWeChatDtos.size() < 1) {
+            smallWeChatDto = new SmallWeChatDto();
+            smallWeChatDto.setAppId(MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, "appId"));
+            smallWeChatDto.setAppSecret(MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, "appSecret"));
+            smallWeChatDto.setObjId(paramIn.getString("communityId"));
+
+            return smallWeChatDto;
+        }
+
+        return BeanConvertUtil.covertBean(smallWeChatDtos.get(0), SmallWeChatDto.class);
+    }
+
+
+    private void doUpdateOnlinePay(String orderId, String state, String message) {
+        OnlinePayPo onlinePayPo = new OnlinePayPo();
+        onlinePayPo.setMessage(message.length() > 1000 ? message.substring(0, 1000) : message);
+        onlinePayPo.setOrderId(orderId);
+        onlinePayPo.setState(state);
+        onlinePayV1InnerServiceSMOImpl.updateOnlinePay(onlinePayPo);
+    }
+
+    private void doSaveOnlinePay(SmallWeChatDto smallWeChatDto, String openId, String orderId, String feeName, double money, String state, String message) {
+        OnlinePayPo onlinePayPo = new OnlinePayPo();
+        onlinePayPo.setAppId(smallWeChatDto.getAppId());
+        onlinePayPo.setMchId(smallWeChatDto.getMchId());
+        onlinePayPo.setMessage(message.length() > 1000 ? message.substring(0, 1000) : message);
+        onlinePayPo.setOpenId(openId);
+        onlinePayPo.setOrderId(orderId);
+        onlinePayPo.setPayId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_orderId));
+        onlinePayPo.setPayName(feeName);
+        onlinePayPo.setRefundFee("0");
+        onlinePayPo.setState(state);
+        onlinePayPo.setTotalFee(money + "");
+        onlinePayPo.setTransactionId(orderId);
+        onlinePayV1InnerServiceSMOImpl.saveOnlinePay(onlinePayPo);
+    }
+
+}

File diff suppressed because it is too large
+ 1091 - 0
service-acct/src/main/java/com/java110/acct/payment/adapt/easypay/JsApi.java


File diff suppressed because it is too large
+ 235 - 0
service-acct/src/main/java/com/java110/acct/payment/adapt/easypay/TerminalInfo.java


+ 124 - 0
service-acct/src/main/java/com/java110/acct/payment/adapt/easypay/utils/Base64.java

@@ -0,0 +1,124 @@
+package com.java110.acct.payment.adapt.easypay.utils;
+
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+
+/**
+ *
+ * Base64封装类,使用java8的内置Base64
+ *
+ * @Date: 2021/10/14 20:07
+ * @Author: pandans
+ */
+public class Base64 {
+    public static final String UTF_8 = "UTF-8";
+    public static java.util.Base64.Encoder encoder;
+    public static java.util.Base64.Encoder urlEncoder;
+    public static java.util.Base64.Decoder decoder;
+    public static java.util.Base64.Decoder urlDecoder;
+
+    static {
+        encoder = java.util.Base64.getEncoder();
+        urlEncoder = java.util.Base64.getUrlEncoder();
+        decoder = java.util.Base64.getDecoder();
+        urlDecoder = java.util.Base64.getUrlDecoder();
+    }
+
+
+    public static byte[] encode(byte[] bytes) {
+        return encoder.encode(bytes);
+    }
+
+    public static String encode(String str) {
+        byte[] encode = encode(str.getBytes());
+        return new String(encode, StandardCharsets.UTF_8);
+    }
+
+    public static String encode2String(byte[] bytes) {
+        return encoder.encodeToString(bytes);
+    }
+
+    public static byte[] encode2Byte(String string) {
+        return encode(string.getBytes());
+    }
+
+    //urlEncoder
+    public static byte[] urlEncode(byte[] bytes) {
+        return urlEncoder.encode(bytes);
+    }
+
+    public static String urlEncode(String string) {
+        byte[] encode = urlEncode(string.getBytes());
+        try {
+            return new String(encode, UTF_8);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static String urlEncode2String(byte[] bytes) {
+        return urlEncoder.encodeToString(bytes);
+    }
+
+    public static byte[] urlEncode2Byte(String string) {
+        return urlEncode(string.getBytes());
+    }
+
+    //decode
+    public static byte[] decode(byte[] bytes) {
+        return decoder.decode(bytes);
+    }
+
+    public static byte[] decode2Byte(String string) {
+        return decoder.decode(string.getBytes());
+    }
+
+    public static String decode2String(byte[] bytes) {
+        try {
+            return new String(decoder.decode(bytes), UTF_8);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static String decode(String string) {
+        byte[] decode = decode(string.getBytes());
+        try {
+            return new String(decode, UTF_8);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    //urlDecode
+    public static byte[] urlDecode(byte[] bytes) {
+        return urlDecoder.decode(bytes);
+    }
+
+    public static byte[] urlDecode2Byte(String string) {
+        return urlDecode(string.getBytes());
+    }
+
+    public static String urlDecode2String(byte[] bytes) {
+        try {
+            return new String(urlDecode(bytes), UTF_8);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static String urlDecode(String string) {
+        byte[] decode = urlDecode(string.getBytes());
+        try {
+            return new String(decode, UTF_8);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}

+ 98 - 0
service-acct/src/main/java/com/java110/acct/payment/adapt/easypay/utils/BaseHttpSslSocketFactory.java

@@ -0,0 +1,98 @@
+package com.java110.acct.payment.adapt.easypay.utils;
+
+import javax.net.ssl.*;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.security.cert.X509Certificate;
+
+/**
+ *  Http ssl 处理类
+ *
+ * @date: 2021/10/14 22:03
+ * @author: pandans
+ */
+public class BaseHttpSslSocketFactory extends SSLSocketFactory {
+    public BaseHttpSslSocketFactory() {
+    }
+
+    private SSLContext getSSLContext() {
+        return this.createEasySSLContext();
+    }
+
+    @Override
+    public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException {
+        return this.getSSLContext().getSocketFactory().createSocket(arg0, arg1, arg2, arg3);
+    }
+
+    @Override
+    public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3) throws IOException {
+        return this.getSSLContext().getSocketFactory().createSocket(arg0, arg1, arg2, arg3);
+    }
+
+    @Override
+    public Socket createSocket(InetAddress arg0, int arg1) throws IOException {
+        return this.getSSLContext().getSocketFactory().createSocket(arg0, arg1);
+    }
+
+    @Override
+    public Socket createSocket(String arg0, int arg1) throws IOException {
+        return this.getSSLContext().getSocketFactory().createSocket(arg0, arg1);
+    }
+
+    @Override
+    public String[] getSupportedCipherSuites() {
+        return null;
+    }
+
+    @Override
+    public String[] getDefaultCipherSuites() {
+        return null;
+    }
+
+    @Override
+    public Socket createSocket(Socket arg0, String arg1, int arg2, boolean arg3) throws IOException {
+        return this.getSSLContext().getSocketFactory().createSocket(arg0, arg1, arg2, arg3);
+    }
+
+    private SSLContext createEasySSLContext() {
+        try {
+            SSLContext context = SSLContext.getInstance("SSL");
+            context.init(null, new TrustManager[]{MyX509TrustManager.manger}, null);
+            return context;
+        } catch (Exception var2) {
+            var2.printStackTrace();
+            return null;
+        }
+    }
+
+    public static class TrustAnyHostnameVerifier implements HostnameVerifier {
+        public TrustAnyHostnameVerifier() {
+        }
+
+        @Override
+        public boolean verify(String hostname, SSLSession session) {
+            return true;
+        }
+    }
+
+    public static class MyX509TrustManager implements X509TrustManager {
+        static MyX509TrustManager manger = new MyX509TrustManager();
+
+        public MyX509TrustManager() {
+        }
+
+        @Override
+        public X509Certificate[] getAcceptedIssuers() {
+            return null;
+        }
+
+        @Override
+        public void checkClientTrusted(X509Certificate[] chain, String authType) {
+        }
+
+        @Override
+        public void checkServerTrusted(X509Certificate[] chain, String authType) {
+        }
+    }
+}

+ 455 - 0
service-acct/src/main/java/com/java110/acct/payment/adapt/easypay/utils/HttpConnectUtils.java

@@ -0,0 +1,455 @@
+package com.java110.acct.payment.adapt.easypay.utils;
+
+
+import javax.net.ssl.*;
+import java.io.*;
+import java.net.*;
+import java.nio.charset.StandardCharsets;
+import java.security.*;
+import java.security.cert.CertificateException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * HttpUrlConnect 请求类
+ */
+public class HttpConnectUtils {
+
+    private static HttpURLConnection createConnection(
+            String url,
+            String encoding,
+            int connectionTimeout,
+            int readTimeOut,
+            String method,
+            Map param,
+            SSLSocketFactory context, String boundary
+    ) throws IOException {
+        URL u_url = new URL(url);
+        HttpURLConnection httpURLConnection = (HttpURLConnection) u_url.openConnection();
+        // 连接超时时间
+        httpURLConnection.setConnectTimeout(connectionTimeout);
+        // 读取结果超时时间
+        httpURLConnection.setReadTimeout(readTimeOut);
+        // 可读
+        httpURLConnection.setDoInput(true);
+        // 可写
+        httpURLConnection.setDoOutput(true);
+        // 取消缓存
+        httpURLConnection.setUseCaches(false);
+        if ("POST".equalsIgnoreCase(method)) {
+            httpURLConnection.setRequestProperty("Content-type",
+                    "application/x-www-form-urlencoded;charset=" + encoding);
+        } else if (method.toUpperCase() == "POST_NO_CHARSET") {
+            httpURLConnection.setRequestProperty("Content-type",
+                    "application/x-www-form-urlencoded");
+            method = "POST";
+        } else if ("ZXF".equalsIgnoreCase(method)) {
+            method = "POST";
+            httpURLConnection.setRequestProperty("Content-type",
+                    "text/plain;charset=" + encoding);
+        } else if ("JSON".equalsIgnoreCase(method)) {
+            method = "POST";
+            httpURLConnection.setRequestProperty("Content-type",
+                    "application/json;charset=" + encoding);
+        } else if ("WL".equalsIgnoreCase(method)) {
+            method = "POST";
+            httpURLConnection.setRequestProperty("Content-type", "application/xml;charset=utf-8");
+            httpURLConnection.setRequestProperty("Connection", "keep-alive");
+            httpURLConnection.setRequestProperty("MsgTp", String.valueOf(param.get("MsgTp")));
+
+            httpURLConnection.setRequestProperty("OriIssrId", String.valueOf(param.get("OriIssrId")));
+            httpURLConnection.setRequestProperty("PyeeAcctTp", "00");
+            httpURLConnection.setRequestProperty("PyerAcctTp", "04");
+            httpURLConnection.setRequestProperty("ReservedFiedld", "");
+        }else if("MULTIPART".equalsIgnoreCase(method)){
+            method = "POST";
+            httpURLConnection.addRequestProperty("Content-Type", "multipart/form-data; boundary="+ boundary);
+        } else {
+            httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+        }
+        httpURLConnection.setRequestMethod(method);
+        if ("https".equalsIgnoreCase(u_url.getProtocol())) {
+            HttpsURLConnection connection = (HttpsURLConnection) httpURLConnection;
+            if (context != null) {
+                connection.setSSLSocketFactory(context);
+            } else {
+                connection.setSSLSocketFactory(new BaseHttpSslSocketFactory());
+            }
+            //解决由于服务器证书问题导致HTTPS无法访问的情况
+            connection.setHostnameVerifier(new BaseHttpSslSocketFactory.TrustAnyHostnameVerifier());
+            return connection;
+        }
+        return httpURLConnection;
+    }
+    private static String generateBoundary() {
+        return "--------------------------" +
+                UUID.randomUUID().toString().replace("-", "");
+    }
+
+    public static int sendRequest(String url,
+                                  String encoding,
+                                  Object request,
+                                  int connectionTimeout,
+                                  int readTimeout,
+                                  String method,
+                                  StringBuilder sb_ret,
+                                  Map extraMap
+    ) throws IOException {
+        Map map = _sendRequest(encoding, request, createConnection(
+                url,
+                encoding,
+                connectionTimeout,
+                readTimeout,
+                method,
+                extraMap, null, null));
+        return _receiveResponse((Integer) map.get("i_ret"), (HttpURLConnection) map.get("connection"), sb_ret, encoding, request);
+    }
+
+    /**
+     * 支持定制的https证书
+     *
+     * @param url
+     * @param request
+     * @param method
+     * @param contextFactory
+     * @return
+     * @throws IOException
+     */
+    public static String sendHttpSRequest(String url,
+                                          Object request,
+                                          String method,
+                                          SSLSocketFactory contextFactory
+
+    ) throws IOException {
+        System.out.println(url);
+        String encoding = "UTF-8";
+        int connectionTimeout = 30000;
+        int readTimeout = 60000;
+        StringBuilder sb_ret = new StringBuilder();
+        Map map = null;
+        if("MULTIPART".equals(method)) {
+            String boundary = generateBoundary();
+            map = _sendRequestMulitiForm(boundary, encoding, (Map) request, createConnection(
+                    url,
+                    encoding,
+                    connectionTimeout,
+                    readTimeout,
+                    method,
+                    null,
+                    contextFactory, boundary
+            ));
+        }else {
+            map = _sendRequest(encoding, request, createConnection(
+                    url,
+                    encoding,
+                    connectionTimeout,
+                    readTimeout,
+                    method,
+                    null,
+                    contextFactory, null
+            ));
+        }
+        int recCode = _receiveResponse((Integer) map.get("i_ret"), (HttpURLConnection) map.get("connection"), sb_ret, encoding, request);
+        assert HttpURLConnection.HTTP_OK ==  recCode : map.get("i_ret") + "通讯异常";
+        return sb_ret.toString();
+    }
+    /**
+     * @param encoding:
+     * @param request:
+     * @param connection:
+     * @return java.util.Map<java.lang.String,java.lang.Object>
+     * @Description  推送send
+     * @date: 2021/10/14 22:12
+     * @author: pandans
+     */
+    private static Map<String, Object> _sendRequestMulitiForm(String boundary, String encoding, Map request, HttpURLConnection connection) throws IOException {
+        int i_ret = 0;
+        String dash = "--";
+        String newLine = "\r\n";
+        FileInputStream inputStream = null;
+        DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
+        Map<String, String> formMap = (Map<String, String>) request.get("form");
+
+        if(formMap != null) {
+            Set<String> formDataKeySet = formMap.keySet();
+            for(String formDataKey : formDataKeySet) {
+                // form data
+                String linHead = dash + boundary + newLine;
+                System.out.print(linHead);
+                outputStream.writeBytes(linHead);
+
+                String knowledgeRequest = "Content-Disposition: form-data; name=\"" + formDataKey + "\"" + newLine +
+                        "Content-Type: text/plain; charset=utf-8" + newLine +
+                        newLine ;// important !
+                System.out.print(knowledgeRequest);
+                outputStream.write(knowledgeRequest.getBytes(StandardCharsets.UTF_8));
+
+                String content = formMap.get(formDataKey) + newLine;
+                System.out.print(content);
+                outputStream.write(content.getBytes(StandardCharsets.UTF_8));
+            }
+            String lineEnd = dash + boundary;
+            System.out.print(lineEnd);
+            outputStream.writeBytes(lineEnd);
+        }
+        Map<String, File> fileMap = (Map<String, File>) request.get("file");
+        if(fileMap != null) {
+            Set<String> fileDataKeySet = fileMap.keySet();
+            for(String fileKey : fileDataKeySet) {
+                File file = fileMap.get(fileKey);
+                // form data
+                String linHead = newLine + dash + boundary + newLine;
+                System.out.print(linHead);
+                outputStream.writeBytes(linHead);
+                // file data
+                String fileHeader = "Content-Disposition: form-data; name=\"" + fileKey + "\"; filename=\"" + file.getName() + "\"" + newLine +
+                        "Content-Type:application/octet-stream"  + newLine +
+                        "Content-Transfer-Encoding: binary" + newLine +
+                        newLine;// important !
+                System.out.print(fileHeader);
+                outputStream.write(fileHeader.getBytes("UTF-8"));
+
+                byte[] buffer = new byte[1024];
+                int count;
+                inputStream = new FileInputStream(file);
+                while (true) {
+                    count = inputStream.read(buffer);
+                    if (count == -1) {
+                        break;
+                    }
+                    outputStream.write(buffer, 0, count);
+                }
+            }
+            System.out.print(newLine);
+            outputStream.writeBytes(newLine);// important !
+
+            String end = dash + boundary + dash;
+            System.out.print(end);
+            outputStream.writeBytes(end);
+        }else {
+            String end = dash + newLine;
+            System.out.print(end);
+            outputStream.writeBytes(end);
+        }
+
+
+
+        outputStream.flush();
+        Map<String, Object> ret = new HashMap<String, Object>(2);
+        ret.put("i_ret", i_ret);
+        ret.put("connection", connection);
+        return ret;
+    }
+    /**
+     * @param encoding:
+     * @param request:
+     * @param connection:
+     * @return java.util.Map<java.lang.String,java.lang.Object>
+     * @Description  推送send
+     * @date: 2021/10/14 22:12
+     * @author: pandans
+     */
+    private static Map<String, Object> _sendRequest(String encoding, Object request, HttpURLConnection connection) throws UnsupportedEncodingException {
+        Map<String, List<String>> headerFields = connection.getRequestProperties();
+        for(String head : headerFields.keySet()){
+            System.out.println(head + ":" + String.join(";", headerFields.get(head)));
+        }
+        System.out.println("method:" + connection.getRequestMethod());
+        int i_ret = 0;
+        PrintStream out = null;
+        String s_request = "";
+        if (request instanceof String) {
+            s_request = (String) request;
+        } else if (request instanceof Map) {
+            try {
+                s_request = getRequestParamString((Map) request, encoding);
+            } catch (UnsupportedEncodingException e) {
+                assert false : "不支持的类型:" + e.getLocalizedMessage();
+            }
+        } else {
+            assert false : "不支持的类型:" + request;
+        }
+        System.out.println("\n请求报文:" + s_request);
+        try {
+            connection.connect();
+            out = new PrintStream(connection.getOutputStream(), false, encoding);
+            out.print(s_request);
+            out.flush();
+        } catch (Exception ignore) {
+            System.out.print("通讯连接成功.返回错误,超时:" + ignore);
+            i_ret = -1;
+        } finally {
+            if (out != null) {
+                out.close();
+            }
+        }
+        Map<String, Object> ret = new HashMap<String, Object>(2);
+        ret.put("i_ret", i_ret);
+        ret.put("connection", connection);
+
+//        System.out.println("----------------请求header start-----------------");
+        Map<String, List<String>> headerRFields = connection.getHeaderFields();
+        for(String head : headerRFields.keySet()){
+//            System.out.println(head + ":" + String.join(";", headerRFields.get(head)));
+        }
+//        System.out.println("----------------请求header end-----------------");
+        return ret;
+    }
+
+    /**
+     * @param i_ret:
+     * @param connection:
+     * @param sb_ret:
+     * @param encoding:
+     * @param request:
+     * @return int
+     * @Description 处理请求
+     * @date: 2021/10/14 22:11
+     * @author: pandans
+     */
+    public static int _receiveResponse(int i_ret, HttpURLConnection connection, StringBuilder sb_ret, String encoding, Object request) {
+        if (i_ret != -1) {
+            InputStream inputStream = null;
+            try {
+                i_ret = connection.getResponseCode();
+                if (i_ret == HttpURLConnection.HTTP_OK) {
+                    inputStream = connection.getInputStream();
+                    sb_ret.append(new String(read(inputStream), encoding));
+                } else {
+                    inputStream = connection.getErrorStream();
+                    sb_ret.append(new String(read(inputStream), encoding));
+                }
+            } catch (Exception ignore) {
+                i_ret = -2;
+                System.out.print("通讯连接成功.返回错误,超时:" + ignore.getMessage());
+            } finally {
+                try {
+                    if (inputStream != null) {
+                        inputStream.close();
+                    }
+                    if (connection != null) {
+                        connection.disconnect();
+                    }
+                } catch (Throwable ignore) {
+                    System.out.print("关闭流异常:" + ignore.getMessage());
+                }
+            }
+        }
+        if (i_ret != HttpURLConnection.HTTP_OK) {
+            if (request instanceof Map) {
+                System.out.println("原始报文111:" + ((Map) request).toString());
+            } else {
+                System.out.println("原始报文:[${request}]");
+            }
+        }
+        return i_ret;
+    }
+
+    public static byte[] read(InputStream inputStream) throws IOException {
+        byte[] buf = new byte[1024];
+        int length = 0;
+        ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+        while ((length = inputStream.read(buf, 0, buf.length)) > 0) {
+            bout.write(buf, 0, length);
+        }
+        bout.flush();
+        return bout.toByteArray();
+    }
+
+    /**
+     * 将Map存储的对象,转换为key=value&key=value的字符 并且做urlencoding
+     *
+     * @param requestParam
+     * @param charset      URL.encoding
+     * @return
+     */
+    public static String getRequestParamString(Map<String, String> requestParam, String charset) throws UnsupportedEncodingException {
+        return getRequestParamString(requestParam, charset, true);
+    }
+
+    public static String getRequestParamString(Map<String, String> requestParam, String charset, boolean isEncode) throws UnsupportedEncodingException {
+        if (charset == null) {
+            charset = "UTF-8";
+        }
+        StringBuilder sb = new StringBuilder();
+
+        for (Map.Entry<String, String> entry : requestParam.entrySet()) {
+            if (entry.getValue() == null) {
+                continue;
+            }
+            if (isEncode) {
+                sb.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), charset)).append("&");
+            } else {
+                sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
+            }
+        }
+        String s_ret = sb.toString();
+        if (s_ret == null || "".equals(s_ret)) {
+            return "";
+        }
+        s_ret = s_ret.substring(0, s_ret.length() - 1);
+        return s_ret;
+    }
+
+    /**
+     * @param file
+     * @param pwd
+     * @param type PKCS12  jks
+     */
+    public static KeyStore loadKeyStore(File file, String pwd, String type) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
+        KeyStore keyStore = KeyStore.getInstance(type);
+        InputStream ksIn = new FileInputStream(file);
+        keyStore.load(ksIn, pwd.toCharArray());
+        return keyStore;
+    }
+
+    /**
+     * 初始化https环境  设置秘钥和证书
+     * 目前华势使用
+     *
+     * @param keyFilePath
+     * @param keyPW
+     * @param trustFilePath
+     * @param trustPW
+     * @return
+     */
+    public static SSLSocketFactory getSSLSocketFactory(String keyFilePath, String keyPW, String trustFilePath, String trustPW, String defaultTLS) {
+        if (defaultTLS == null) {
+            defaultTLS = "TLS";
+        }
+        try {
+            String pwd = keyPW;
+            KeyStore keyStore = loadKeyStore(
+                    new File("../cert/88888888.p12"),
+                    pwd,
+                    "PKCS12");
+            KeyStore trustStore = loadKeyStore(
+                    new File("../cert/client.truststore"),
+                    trustPW,
+                    "jks");
+            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+            tmf.init(trustStore);
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+            kmf.init(keyStore, pwd.toCharArray());
+            SecureRandom rand = new SecureRandom();
+            SSLContext sslContext = SSLContext.getInstance(defaultTLS);
+            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), rand);
+            return sslContext.getSocketFactory();
+        } catch (KeyStoreException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (CertificateException e) {
+            e.printStackTrace();
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        } catch (UnrecoverableKeyException e) {
+            e.printStackTrace();
+        } catch (KeyManagementException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+
+}

+ 154 - 0
service-acct/src/main/java/com/java110/acct/payment/adapt/easypay/utils/RsaUtil.java

@@ -0,0 +1,154 @@
+package com.java110.acct.payment.adapt.easypay.utils;
+
+
+import javax.crypto.Cipher;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+/**
+ * RSA加解密工具类
+ *
+ * @Date: 2021/10/14 20:39
+ * @Author: pandans
+ */
+public class RsaUtil {
+    private static final String ALGORITHM = "RSA";
+    /**
+     * 加解密算法/工作模式/填充方式
+     */
+    private static final String ALGORITHM_MODE_PADDING = "RSA/ECB/PKCS1Padding";
+    private static final String ALGORITHM_SHA256 = "SHA256withRSA";
+
+    /**
+     * @param content:   待加密内容
+     * @param publicKey: 加密公钥
+     * @return 加密过的内容
+     * @Description 使用公钥进行你内容假面
+     * @date: 2021/10/17 11:22
+     * @author: pandans
+     */
+    public static String encryptWithPKCS1(String content, String publicKey) {
+        if (publicKey == null || "".equals(publicKey)) {
+            //缺少Rsa密钥信息
+            return null;
+        }
+        try {
+            PublicKey pubKey = getPublicKey(publicKey);
+            Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
+
+            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
+            byte[] output = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
+
+            return Base64.encode2String(output);
+        } catch (Exception e) {
+            //签名失败
+            return null;
+        }
+    }
+
+    /**
+     * @param content:    已加密内容
+     * @param privateKey: 加密公钥
+     * @return 解密的内容
+     * @Description 使用私钥进行解密
+     * @date: 2021/10/17 11:22
+     * @author: pandans
+     */
+    public static String decryptWithPKCS1(String content, String privateKey) {
+        if (privateKey == null || "".equals(privateKey)) {
+            //缺少Rsa密钥信息
+            return null;
+        }
+        try {
+            PrivateKey priKey = getPrivateKey(privateKey);
+            Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
+
+            cipher.init(Cipher.DECRYPT_MODE, priKey);
+            byte[] output = cipher.doFinal(Base64.decode2Byte(content));
+
+            return new String(output, StandardCharsets.UTF_8);
+        } catch (Exception e) {
+            //签名失败
+            return null;
+        }
+    }
+
+    /**
+     * @param content    :
+     * @param privateKey : 易生提供的私钥
+     * @return java.lang.String
+     * @Description:
+     * @Date: 2021/10/14 20:34
+     * @Author: pandans
+     */
+    public static String signBySHA256WithRSA(String content, String privateKey) {
+        if (privateKey == null || "".equals(privateKey)) {
+            //缺少签名私钥
+            return null;
+        }
+        try {
+            PrivateKey priKey = getPrivateKey(privateKey);
+
+            Signature signature = Signature.getInstance(ALGORITHM_SHA256);
+            signature.initSign(priKey);
+            signature.update(content.getBytes(StandardCharsets.UTF_8));
+            return Base64.encode2String(signature.sign());
+        } catch (Exception e) {
+            //签名失败
+            return null;
+        }
+    }
+
+
+    /**
+     * @param content:   签名数据内容
+     * @param sign:      签名
+     * @param publicKey: 易生提供的公钥
+     * @return boolean
+     * @Description 验签
+     * @Date: 2021/10/14 21:08
+     * @Author: pandans
+     */
+    public static boolean verifyBySHA256WithRSA(String content, String sign, String publicKey) {
+        //1)	使用正則表達式把應答報文分為兩部分:JSON格式的報文(request/response)部分和簽名(signature)部分,注意為保證原文順序,不能轉為JSON對象去操作;
+        //2)	使用SHA256算法對JSON格式的報文(request/response)部分獲取消息摘要;
+        //3)	使用公鑰將簽名解碼為消息摘要;
+        //4)	比較第2,3步驟的消息摘要,如果相同,說明原文沒有變化,驗證通過;
+        if (publicKey == null || "".equals(publicKey)) {
+            //缺少签名私钥
+            return false;
+        }
+        try {
+            PublicKey pubKey = getPublicKey(publicKey);
+
+            Signature signature = Signature.getInstance(ALGORITHM_SHA256);
+            signature.initVerify(pubKey);
+            signature.update(content.getBytes(StandardCharsets.UTF_8));
+            return signature.verify(Base64.decode2Byte(sign));
+        } catch (Exception e) {
+            //验签失败
+            return false;
+        }
+    }
+
+    public static RSAPublicKey getPublicKey(String publicKey) throws Exception {
+        byte[] keyBytes = Base64.decode2Byte(publicKey);
+        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
+        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
+        return (RSAPublicKey) keyFactory.generatePublic(spec);
+    }
+
+    public static RSAPrivateKey getPrivateKey(String privateKey) throws Exception {
+        byte[] keyBytes = Base64.decode2Byte(privateKey);
+        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
+        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
+        return (RSAPrivateKey) keyFactory.generatePrivate(spec);
+    }
+}

+ 181 - 0
service-acct/src/main/java/com/java110/acct/smo/impl/QrCodeEasyPaymentAdapt.java

@@ -0,0 +1,181 @@
+package com.java110.acct.smo.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.java110.acct.payment.adapt.bbgpay.EncryptDecryptFactory;
+import com.java110.acct.payment.adapt.easypay.BasePay;
+import com.java110.acct.payment.adapt.easypay.utils.HttpConnectUtils;
+import com.java110.acct.smo.IQrCodePaymentSMO;
+import com.java110.core.client.RestTemplate;
+import com.java110.core.factory.GenerateCodeFactory;
+import com.java110.core.log.LoggerFactory;
+import com.java110.dto.paymentPoolValue.PaymentPoolValueDto;
+import com.java110.intf.acct.IPaymentPoolValueV1InnerServiceSMO;
+import com.java110.intf.store.ISmallWeChatInnerServiceSMO;
+import com.java110.utils.cache.MappingCache;
+import com.java110.utils.constant.MappingConstant;
+import com.java110.utils.constant.WechatConstant;
+import com.java110.utils.util.PayUtil;
+import com.java110.vo.ResultVo;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * 微信支付
+ */
+@Service
+public class QrCodeEasyPaymentAdapt implements IQrCodePaymentSMO {
+    private static Logger logger = LoggerFactory.getLogger(QrCodeEasyPaymentAdapt.class);
+
+    //微信支付
+    public static final String DOMAIN_WECHAT_PAY = "WECHAT_PAY";
+    // 微信服务商支付开关
+    public static final String WECHAT_SERVICE_PAY_SWITCH = "WECHAT_SERVICE_PAY_SWITCH";
+
+    //开关ON打开
+    public static final String WECHAT_SERVICE_PAY_SWITCH_ON = "ON";
+
+
+    private static final String WECHAT_SERVICE_APP_ID = "SERVICE_APP_ID";
+
+    private static final String WECHAT_SERVICE_MCH_ID = "SERVICE_MCH_ID";
+
+    private static String VERSION = "1.0";
+
+    private static String SIGN_TYPE = "RSA2";// 加密算法:SM4、RSA2
+
+    private static String gzhPayUrl = "https://mbank.bankofbbg.com/www/corepaycer/ScanCodePay";
+
+    private static String queryUrl = "https://mbank.bankofbbg.com/www/corepaycer/QueryTxnInfo";// 交易查询地址
+
+    @Autowired
+    private ISmallWeChatInnerServiceSMO smallWeChatInnerServiceSMOImpl;
+
+    @Autowired
+    private RestTemplate outRestTemplate;
+
+    @Autowired
+    private IPaymentPoolValueV1InnerServiceSMO paymentPoolValueV1InnerServiceSMOImpl;
+
+    @Override
+    public ResultVo pay(String communityId, String orderNum, double money, String authCode, String feeName, String paymentPoolId) throws Exception {
+        logger.info("【小程序支付】 统一下单开始, 订单编号=" + orderNum);
+        SortedMap<String, String> resultMap = new TreeMap<String, String>();
+        //生成支付金额,开发环境处理支付金额数到0.01、0.02、0.03元
+        double payAmount = PayUtil.getPayAmountByEnv(MappingCache.getValue(MappingConstant.ENV_DOMAIN, "HC_ENV"), money);
+        //添加或更新支付记录(参数跟进自己业务需求添加)
+
+        Map<String, String> resMap = null;
+        logger.debug("resMap=" + resMap);
+        String systemName = MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, WechatConstant.PAY_GOOD_NAME);
+
+        PaymentPoolValueDto paymentPoolValueDto = new PaymentPoolValueDto();
+        paymentPoolValueDto.setPpId(paymentPoolId);
+        List<PaymentPoolValueDto> paymentPoolValueDtos = paymentPoolValueV1InnerServiceSMOImpl.queryPaymentPoolValues(paymentPoolValueDto);
+
+        if (paymentPoolValueDtos == null || paymentPoolValueDtos.isEmpty()) {
+            throw new IllegalArgumentException("配置错误,未配置参数");
+        }
+
+        String ORGID = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "ORGID"); // 客户编号
+        String ORGMERCODE = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "ORGMERCODE");
+        String ORGTERMNO = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "ORGTERMNO");
+        String EASYPAY_PUBLIC_KEY = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "EASYPAY_PUBLIC_KEY");
+        String MER_RSA_PRIVATE_KEY = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "MER_RSA_PRIVATE_KEY");
+
+        JSONObject paramIn = new JSONObject();
+        paramIn.put("orgId", ORGID);
+        paramIn.put("orgMercode", ORGMERCODE);
+        paramIn.put("orgTermno", ORGTERMNO);
+        paramIn.put("signType", BasePay.SIGN_TYPE_RSA256);
+        paramIn.put("orgTrace", orderNum);
+
+
+        JSONObject data = new JSONObject();
+        data.put("authCode", authCode);
+        data.put("tradeAmt", Integer.parseInt(PayUtil.moneyToIntegerStr(payAmount)));
+        data.put("orderInfo", feeName);
+        paramIn.put("data", data);
+
+        // 使用商户私钥对data字段加签
+        String sign = BasePay.sign(data, MER_RSA_PRIVATE_KEY);
+        paramIn.put("sign", sign);
+
+        String requestStr = paramIn.toJSONString();
+
+        String response = HttpConnectUtils.sendHttpSRequest(BasePay.BASE_URL + "/standard/scanPay", requestStr, "JSON", null);
+        System.out.println("\n响应报文:" + response);
+        BasePay.checkSign(response, EASYPAY_PUBLIC_KEY);
+
+        JSONObject paramOut = JSONObject.parseObject(response);
+        if (!"000000".equals(paramOut.getString("sysRetcode"))) {
+            throw new IllegalArgumentException("支付失败" + paramOut.getString("sysRetmsg"));
+        }
+
+        JSONObject resData = paramOut.getJSONObject("data");
+
+        if ("00".equals(resData.getString("finRetcode"))) {
+            return new ResultVo(ResultVo.CODE_OK, "成功");
+        } else {
+            return new ResultVo(ResultVo.CODE_ERROR, "等待用户支付中");
+        }
+    }
+
+    public ResultVo checkPayFinish(String communityId, String orderNum, String paymentPoolId) {
+        Map<String, String> result = null;
+        PaymentPoolValueDto paymentPoolValueDto = new PaymentPoolValueDto();
+        paymentPoolValueDto.setPpId(paymentPoolId);
+        paymentPoolValueDto.setCommunityId(communityId);
+        List<PaymentPoolValueDto> paymentPoolValueDtos = paymentPoolValueV1InnerServiceSMOImpl.queryPaymentPoolValues(paymentPoolValueDto);
+
+
+        if (paymentPoolValueDtos == null || paymentPoolValueDtos.isEmpty()) {
+            throw new IllegalArgumentException("配置错误,未配置参数");
+        }
+        String ORGID = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "ORGID"); // 客户编号
+        String ORGMERCODE = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "ORGMERCODE");
+        String ORGTERMNO = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "ORGTERMNO");
+        String EASYPAY_PUBLIC_KEY = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "EASYPAY_PUBLIC_KEY");
+        String MER_RSA_PRIVATE_KEY = PaymentPoolValueDto.getValue(paymentPoolValueDtos, "MER_RSA_PRIVATE_KEY");
+
+        JSONObject paramIn = new JSONObject();
+        paramIn.put("orgId", ORGID);
+        paramIn.put("orgMercode", ORGMERCODE);
+        paramIn.put("orgTermno", ORGTERMNO);
+        paramIn.put("signType", BasePay.SIGN_TYPE_RSA256);
+        paramIn.put("orgTrace", GenerateCodeFactory.getGeneratorId("10"));
+        JSONObject data = new JSONObject();
+        data.put("oriOrgTrace", orderNum);
+        paramIn.put("data", data);
+        String sign = BasePay.sign(data, MER_RSA_PRIVATE_KEY);
+        paramIn.put("sign", sign);
+
+        String requestStr = paramIn.toJSONString();
+
+        String response = null;
+        try {
+            response = HttpConnectUtils.sendHttpSRequest(BasePay.BASE_URL + "/standard/tradeQuery", requestStr, "JSON", null);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        System.out.println("\n响应报文:" + response);
+        BasePay.checkSign(response, EASYPAY_PUBLIC_KEY);
+
+        JSONObject paramOut = JSONObject.parseObject(response);
+        if (!"000000".equals(paramOut.getString("sysRetcode"))) {
+            throw new IllegalArgumentException("支付失败" + paramOut.getString("sysRetmsg"));
+        }
+
+        JSONObject resData = paramOut.getJSONObject("data");
+
+        if ("00".equals(resData.getString("finRetcode"))) {
+            return new ResultVo(ResultVo.CODE_OK, "成功");
+        } else {
+            return new ResultVo(ResultVo.CODE_ERROR, "等待用户支付中");
+        }
+
+    }
+}