From d0b19298e28a9b8b50c778704b77160f17e73950 Mon Sep 17 00:00:00 2001
From: jialh <1972868360@qq.com>
Date: 星期五, 17 四月 2026 18:20:38 +0800
Subject: [PATCH] 水电话费

---
 service-acct/src/main/java/com/java110/acct/payment/adapt/icbc/IcbcPaymentFactoryAdapt.java.txt |  394 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 394 insertions(+), 0 deletions(-)

diff --git a/service-acct/src/main/java/com/java110/acct/payment/adapt/icbc/IcbcPaymentFactoryAdapt.java.txt b/service-acct/src/main/java/com/java110/acct/payment/adapt/icbc/IcbcPaymentFactoryAdapt.java.txt
new file mode 100644
index 0000000..f843bb6
--- /dev/null
+++ b/service-acct/src/main/java/com/java110/acct/payment/adapt/icbc/IcbcPaymentFactoryAdapt.java.txt
@@ -0,0 +1,394 @@
+package com.java110.acct.payment.adapt.icbc;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.icbc.api.DefaultIcbcClient;
+import com.icbc.api.IcbcApiException;
+import com.icbc.api.IcbcConstants;
+import com.icbc.api.request.CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1;
+import com.icbc.api.request.CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1.CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1Biz;
+import com.icbc.api.response.CardbusinessAggregatepayB2cOnlineConsumepurchaseResponseV1;
+import com.icbc.api.utils.IcbcEncrypt;
+import com.icbc.api.utils.IcbcSignature;
+import com.icbc.api.utils.WebUtils;
+import com.java110.acct.payment.IPaymentFactoryAdapt;
+import com.java110.acct.payment.adapt.plutus.PlutusPaymentFactoryAdapt;
+import com.java110.core.context.ICmdDataFlowContext;
+import com.java110.core.factory.CommunitySettingFactory;
+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.PaymentOrderDto;
+import com.java110.dto.wechat.SmallWeChatDto;
+import com.java110.intf.store.ISmallWechatV1InnerServiceSMO;
+import com.java110.intf.user.IOwnerAppUserInnerServiceSMO;
+import com.java110.utils.cache.CommonCache;
+import com.java110.utils.cache.MappingCache;
+import com.java110.utils.cache.UrlCache;
+import com.java110.utils.constant.WechatConstant;
+import com.java110.utils.util.BeanConvertUtil;
+import com.java110.utils.util.DateUtil;
+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.util.*;
+
+/**
+ * 宸ュ晢閾惰鏀粯
+ * <p>
+ * 杩欎釜閫傞厤鍣ㄤ娇鐢ㄩ渶瑕� 瀹夎 宸ュ晢閾惰鐨� jar 瀹夎鍒癿aven
+ * 杩欓噷 浠ュ厤褰卞搷 缂栬瘧 鎵�浠ヨ繖涓狫ava 鏀瑰悕涓簍xt
+ * <p>
+ * 濡傛灉闇�瑕佸伐鍟嗛摱琛屾敮浠�
+ * 1銆佸皢 宸ュ晢閾惰鎻愪緵鐨� icbc-api-sdk-cop icbc-api-sdk-cop-io  icbc-ca 瀹夎鍒拌嚜宸辩殑绉佹湁浠撳簱 鎬庝箞瀹夎璇风櫨搴�
+ * <p>
+ * 2銆佹牴鎹綘瀹夎鐨� 鍛戒护 浼� 鏈夊涓嬬殑涓変釜jar鐨勪緷璧栧寘锛屽皢杩欎笁涓郴璇跺埌 service-acct 涓嬬殑pom.xml 鏂囦欢涓�
+ * <p>
+ * <dependency>
+ * <groupId>com.icbc</groupId>
+ * <artifactId>icbc-api-sdk-cop</artifactId>
+ * <version>v1.0</version>
+ * </dependency>
+ * <dependency>
+ * <groupId>com.icbc</groupId>
+ * <artifactId>icbc-api-sdk-cop-io</artifactId>
+ * <version>v1.0</version>
+ * </dependency>
+ * <dependency>
+ * <groupId>com.icbc</groupId>
+ * <artifactId>icbc-ca</artifactId>
+ * <version>v1.0</version>
+ * </dependency>
+ * <p>
+ * <p>
+ * 3銆佸皢 姝ょ被  鏂囦欢 鍚嶅幓鎺夋渶鍚庣殑TXT  淇敼 涓篔ava 鍚庣紑
+ * <p>
+ * 4銆佹墽琛宮vn clean install 鎵ц鎵撳寘娴嬭瘯
+ * <p>
+ * 5銆佸鏋滆浜屾寮�鍙戜紭鍖栧弬鑰� 宸ュ晢閾惰鍗忚
+ * https://open.icbc.com.cn/icbc/apip/api_detail.html?apiId=10000000000000137000&baseUrl=%2Fcardbusiness%2Faggregatepay%2Fb2c%2Fonline&resUrl=%2Fconsumepurchase&version=V1&apiName=鑱氬悎鏀粯B2C绾夸笂娑堣垂涓嬪崟&serviceId=P0067&resourceId=10000000000000009800
+ *
+ * @desc add by 鍚村鏂� 15:33
+ */
+@Service("icbcPaymentFactory")
+public class IcbcPaymentFactoryAdapt implements IPaymentFactoryAdapt {
+
+    private static final Logger logger = LoggerFactory.getLogger(PlutusPaymentFactoryAdapt.class);
+
+
+    //寰俊鏀粯
+    public static final String DOMAIN_WECHAT_PAY = "WECHAT_PAY";
+    // 寰俊鏈嶅姟鍟嗘敮浠樺紑鍏�
+    public static final String WECHAT_SERVICE_PAY_SWITCH = "WECHAT_SERVICE_PAY_SWITCH";
+
+    //寮�鍏砄N鎵撳紑
+    public static final String WECHAT_SERVICE_PAY_SWITCH_ON = "ON";
+
+
+    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";
+
+    @Autowired
+    private ISmallWechatV1InnerServiceSMO smallWechatV1InnerServiceSMOImpl;
+
+
+    @Autowired
+    private IOwnerAppUserInnerServiceSMO ownerAppUserInnerServiceSMOImpl;
+
+    @Autowired
+    private RestTemplate outRestTemplate;
+
+
+    @Override
+    public Map java110Payment(PaymentOrderDto paymentOrderDto, JSONObject reqJson, ICmdDataFlowContext context) throws Exception {
+
+        SmallWeChatDto smallWeChatDto = getSmallWechat(reqJson);
+
+
+        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/icbc/992020011134400001";
+
+        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,
+                notifyUrl
+        );
+
+
+        if (TRADE_TYPE_JSAPI.equals(tradeType)) {
+            resultMap.putAll(JSONObject.toJavaObject(resMap, Map.class));
+            //resultMap.put("sign", resultMap.get("paySign"));
+            resultMap.put("appId", resultMap.get("appid"));
+            resultMap.put("timeStamp", resultMap.get("timestamp"));
+            resultMap.put("nonceStr", resultMap.get("noncestr"));
+        } 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 notifyUrl) throws Exception {
+
+        //String systemName = MappingCache.getValue(WechatConstant.WECHAT_DOMAIN, WechatConstant.PAY_GOOD_NAME);
+        String privateKey = CommunitySettingFactory.getRemark(smallWeChatDto.getObjId(), "ICBC_PRIVATE_KEY");
+        String apiPublicKey = CommunitySettingFactory.getRemark(smallWeChatDto.getObjId(), "ICBC_PUBLIC_KEY");
+        String merId = CommunitySettingFactory.getValue(smallWeChatDto.getObjId(), "ICBC_MER_ID");
+        String merPrtclNo = CommunitySettingFactory.getValue(smallWeChatDto.getObjId(), "ICBC_MER_PRTCL_NO");
+        String deciveInfo = CommunitySettingFactory.getValue(smallWeChatDto.getObjId(), "ICBC_DECIVE_INFO");
+        String appName = CommunitySettingFactory.getValue(smallWeChatDto.getObjId(), "ICBC_APP_NAME");
+        String icbcAppId = CommunitySettingFactory.getValue(smallWeChatDto.getObjId(), "ICBC_APP_ID");
+        String appId = CommunitySettingFactory.getValue(smallWeChatDto.getObjId(), "APP_ID");
+
+        System.out.println("appId=" + appId);
+        System.out.println("privateKey=" + privateKey);
+        System.out.println("apiPublicKey=" + apiPublicKey);
+        System.out.println("merId=" + merId);
+        System.out.println("merPrtclNo=" + merPrtclNo);
+        System.out.println("deciveInfo=" + deciveInfo);
+        System.out.println("appName=" + appName);
+        System.out.println("icbcAppId=" + icbcAppId);
+
+
+        DefaultIcbcClient client = new DefaultIcbcClient(appId, IcbcConstants.SIGN_TYPE_RSA2, privateKey, apiPublicKey);
+        CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1 request = new CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1();
+        //鏍规嵁娴嬭瘯鐜鍜岀敓浜х幆澧冩浛鎹㈢浉搴攊p鍜岀鍙�
+        request.setServiceUrl("https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/consumepurchase/V1");
+        CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1Biz
+                bizContent = new CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1Biz();
+        request.setBizContent(bizContent);
+        //璇峰鐓ф帴鍙f枃妗g敤bizContent.setxxx()鏂规硶瀵逛笟鍔′笂閫佹暟鎹繘琛岃祴鍊�
+        bizContent.setMer_id(merId);
+        bizContent.setOut_trade_no(orderNum);
+        bizContent.setPay_mode("9");
+        bizContent.setAccess_type("7");
+        bizContent.setMer_prtcl_no(merPrtclNo);
+        bizContent.setOrig_date_time(DateUtil.getNow(DateUtil.DATE_FORMATE_STRING_E).replace("Z", ""));
+        bizContent.setDecive_info(deciveInfo);
+        bizContent.setBody(appName + "-璐拱鍟嗗搧");
+        bizContent.setFee_type("001");
+        bizContent.setSpbill_create_ip("192.168.1.8");
+        bizContent.setTotal_fee(PayUtil.moneyToIntegerStr(payAmount));
+        bizContent.setMer_url(notifyUrl);
+        bizContent.setShop_appid(smallWeChatDto.getAppId());
+        bizContent.setIcbc_appid(icbcAppId);
+        bizContent.setOpen_id(openid);
+        // bizContent.setMer_acct("6212880200000038618");
+        bizContent.setExpire_time("120");
+        //bizContent.setNotify_type("HS");
+         bizContent.setNotify_type("HS");
+        bizContent.setResult_type("1");
+           bizContent.setPay_limit("no_credit");
+               bizContent.setOrder_apd_inf("");
+        CardbusinessAggregatepayB2cOnlineConsumepurchaseResponseV1 response;
+
+        System.out.println("request:" + JSON.toJSONString(request));
+
+
+        response = client.execute(request, System.currentTimeMillis() + "");//msgId娑堟伅閫氳鍞竴缂栧彿锛岃姹傛瘡娆¤皟鐢ㄧ嫭绔嬬敓鎴愶紝APP绾у敮涓�
+
+        if (response.getReturnCode() == 0) {
+            // 6銆佷笟鍔℃垚鍔熷鐞嗭紝璇锋牴鎹帴鍙f枃妗g敤response.getxxx()鑾峰彇鍚屾杩斿洖鐨勪笟鍔℃暟鎹�
+            System.out.println("ReturnCode:" + response.getReturnCode());
+            System.out.println("response:" + JSON.toJSONString(response));
+            CommonCache.setValue("icbc_"+icbcAppId,smallWeChatDto.getAppId(),CommonCache.PAY_DEFAULT_EXPIRE_TIME);
+            CommonCache.setValue("icbc_community_"+icbcAppId,smallWeChatDto.getObjId(),CommonCache.PAY_DEFAULT_EXPIRE_TIME);
+            return JSONObject.parseObject(response.getWx_data_package());
+        } else {
+            // 澶辫触
+            System.out.println("ReturnMsg:" + response.getReturnMsg());
+            throw new IllegalArgumentException("鏀粯澶辫触" + response.getReturnMsg());
+        }
+    }
+
+
+    @Override
+    public PaymentOrderDto java110NotifyPayment(NotifyPaymentOrderDto notifyPaymentOrderDto) {
+        String param = notifyPaymentOrderDto.getParam();
+
+        PaymentOrderDto paymentOrderDto = new PaymentOrderDto();
+        JSONObject json = JSON.parseObject(param);
+
+        String appId = CommonCache.getAndRemoveValue("icbc_"+json.getString("app_id"));
+
+        if(StringUtil.isEmpty(appId)){
+            throw new IllegalArgumentException("鏀粯閫氱煡澶辫触");
+        }
+
+        String communityId =   CommonCache.getAndRemoveValue("icbc_community_"+json.getString("app_id"));
+
+        JSONObject paramIn = new JSONObject();
+        paramIn.put("appId", appId);
+        paramIn.put("communityId", communityId);
+        SmallWeChatDto smallWeChatDto = getSmallWechat(paramIn);
+        if (smallWeChatDto == null) {
+            throw new IllegalArgumentException("鏈厤缃叕浼楀彿鎴栬�呭皬绋嬪簭淇℃伅");
+        }
+
+        Map<String, String> params = new HashMap<String, String>();
+
+        params.put("from", json.getString("from"));
+        params.put("api", json.getString("api"));
+        params.put("app_id", json.getString("app_id"));
+        params.put("charset", json.getString("charset"));
+        params.put("format", json.getString("format"));
+        params.put("timestamp", json.getString("timestamp"));
+        params.put("biz_content", json.getString("biz_content"));
+        params.put("sign_type", json.getString("sign_type"));//鐩墠涓婅缃戝叧绛惧悕鏆傛椂浠呮敮鎸丷SA
+
+        String path ="/app/payment/notify/icbc/992020011134400001";
+        String signStr = WebUtils.buildOrderedSignStr(path, params);
+        String results = null;
+        String responseBizContent = null;
+
+
+        String apiPublicKey = CommunitySettingFactory.getRemark(smallWeChatDto.getObjId(), "ICBC_PUBLIC_KEY");
+        String theKey = CommunitySettingFactory.getValue(smallWeChatDto.getObjId(), "ICBC_KEY");
+        String privateKey = CommunitySettingFactory.getRemark(smallWeChatDto.getObjId(), "ICBC_PRIVATE_KEY");
+
+
+        boolean flag = false;
+        String content = "";
+        System.out.println("signStr="+signStr);
+        try {
+            flag = IcbcSignature.verify(signStr, json.getString("sign_type"), apiPublicKey, json.getString("charset"), json.getString("sign"));
+        } catch (IcbcApiException e) {
+            e.printStackTrace();
+        }
+        if (!flag) {
+            responseBizContent = "{\"return_code\":-12345,\"return_msg\":\"icbc sign not pass.\"}";
+        } else {
+
+            /**********biz_content瑙e瘑**********/
+            if ("AES".equals(json.getString("encrypt_type"))) {
+                try {
+                    content = IcbcEncrypt.decryptContent(json.getString("biz_content"), json.getString("encrypt_type"), theKey, json.getString("charset"));
+                } catch (IcbcApiException e) {
+                    e.printStackTrace();
+                }
+            }else{
+                content = json.getString("biz_content");
+            }
+            /**********鍚堜綔鏂�/鍒嗚 涓氬姟閫昏緫澶勭悊**********/
+            JSONObject map = JSONObject.parseObject(content);
+            logger.info("銆恑ccb鏀粯鍥炶皟銆� 鍥炶皟鏁版嵁锛� \n" + map);
+            //鏇存柊鏁版嵁
+            paymentOrderDto.setOrderId(map.getString("out_trade_no"));
+            paymentOrderDto.setTransactionId(map.getString("order_id"));
+
+            String msg_id = map.get("msg_id").toString();
+            //涓氬姟杩斿洖鍙傛暟璁剧疆
+            int return_code = 0;
+            String return_msg = "success.";
+            responseBizContent = "{\"return_code\":" + return_code + ",\"return_msg\":\"" + return_msg + "\",\"msg_id\":\"" + msg_id + "\","
+                    + "\"busi_param_rp\":\"thisisresponseparameter\"}";
+
+            /**********response_biz_content鍔犲瘑**********/
+
+            if ("AES".equals(json.getString("encrypt_type"))) {
+                try {
+                    responseBizContent = IcbcEncrypt.encryptContent(responseBizContent, json.getString("encrypt_type"), theKey, json.getString("charset"));
+                } catch (IcbcApiException e) {
+                    e.printStackTrace();
+                }
+                responseBizContent = "\"" + responseBizContent + "\"";
+            }
+        }
+
+
+        signStr = "\"response_biz_content\":" + responseBizContent + "," + "\"sign_type\":" + "\"RSA\"";
+        String sign = null;
+        try {
+            sign = IcbcSignature.sign(signStr, "RSA", privateKey, json.getString("charset"), theKey);
+        } catch (IcbcApiException e) {
+            e.printStackTrace();
+        }
+        results = "{" + signStr + ",\"sign\":\"" + sign + "\"}";
+
+        paymentOrderDto.setResponseEntity(new ResponseEntity<String>(results, 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);
+    }
+
+}

--
Gitblit v1.8.0