diff --git a/src/main/java/com/sqx/modules/pay/controller/app/ApiWeiXinPayController.java b/src/main/java/com/sqx/modules/pay/controller/app/ApiWeiXinPayController.java index 4c7324a..0f0e234 100644 --- a/src/main/java/com/sqx/modules/pay/controller/app/ApiWeiXinPayController.java +++ b/src/main/java/com/sqx/modules/pay/controller/app/ApiWeiXinPayController.java @@ -1,5 +1,6 @@ package com.sqx.modules.pay.controller.app; +import com.alibaba.fastjson.JSONObject; import com.sqx.common.utils.Result; import com.sqx.modules.app.annotation.Login; import com.sqx.modules.orders.entity.Orders; @@ -17,6 +18,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.util.List; +import java.util.Map; /** * @author fang @@ -143,18 +145,21 @@ public class ApiWeiXinPayController { @PostMapping("/notifyJsApi") @ApiOperation("微信回调") - public void notifyJsApi(HttpServletRequest req, HttpServletResponse resp) { + public void notifyJsApi(@RequestParam Map params, HttpServletResponse resp) { PrintWriter out = null; try { - String result = wxService.icbcPayBack(req,3); + log.info("icbc支付回调参数: {}", JSONObject.toJSONString(params)); + String result = wxService.icbcPayBack(params,3); resp.setContentType("application/json; charset=utf-8"); out = resp.getWriter(); out.write(result); } catch (Exception e) { log.error("【工商银行】微信支付回调处理失败,请检查原因!!!,{}", e.getMessage()); } finally { - out.flush(); - out.close(); + if(out != null){ + out.flush(); + out.close(); + } } // String resXml = ""; // try { @@ -192,10 +197,11 @@ public class ApiWeiXinPayController { @PostMapping("/notifyJsApiShop") @ApiOperation("微信回调") - public void notifyJsApiShop(HttpServletRequest req, HttpServletResponse resp) { + public void notifyJsApiShop(@RequestParam Map params, HttpServletResponse resp) { PrintWriter out = null; try { - String result = wxService.icbcPayBack(req,4); + log.info("icbc支付回调参数: {}", JSONObject.toJSONString(params)); + String result = wxService.icbcPayBack(params,4); resp.setContentType("application/json; charset=utf-8"); out = resp.getWriter(); out.write(result); diff --git a/src/main/java/com/sqx/modules/pay/service/WxService.java b/src/main/java/com/sqx/modules/pay/service/WxService.java index 5d8f217..099dd93 100644 --- a/src/main/java/com/sqx/modules/pay/service/WxService.java +++ b/src/main/java/com/sqx/modules/pay/service/WxService.java @@ -3,9 +3,11 @@ package com.sqx.modules.pay.service; import com.sqx.common.utils.Result; import com.sqx.modules.orders.entity.Orders; import com.sqx.modules.task.entity.HelpOrder; +import org.springframework.web.bind.annotation.RequestBody; import javax.servlet.http.HttpServletRequest; import java.util.List; +import java.util.Map; /** @@ -26,7 +28,7 @@ public interface WxService { String payBack(String resXml,Integer type); - String icbcPayBack(HttpServletRequest request, Integer type) throws Exception; + String icbcPayBack(@RequestBody Map params, Integer type) throws Exception; boolean refund(String ordersNo); diff --git a/src/main/java/com/sqx/modules/pay/service/impl/WxServiceImpl.java b/src/main/java/com/sqx/modules/pay/service/impl/WxServiceImpl.java index 1a55fa8..7085d5f 100644 --- a/src/main/java/com/sqx/modules/pay/service/impl/WxServiceImpl.java +++ b/src/main/java/com/sqx/modules/pay/service/impl/WxServiceImpl.java @@ -12,7 +12,9 @@ import com.github.wxpay.sdk.WXPayUtil; import com.icbc.api.DefaultIcbcClient; import com.icbc.api.IcbcApiException; import com.icbc.api.IcbcConstants; +import com.icbc.api.UiIcbcClient; import com.icbc.api.request.CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1; +import com.icbc.api.request.CardbusinessAggregatepayB2cOnlineUiConsumepurchaseshowpayRequestV1; import com.icbc.api.response.CardbusinessAggregatepayB2cOnlineConsumepurchaseResponseV1; import com.icbc.api.utils.IcbcSignature; import com.icbc.api.utils.WebUtils; @@ -60,6 +62,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.RequestBody; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; @@ -663,16 +666,19 @@ public class WxServiceImpl implements WxService { return xmlBack; } - private static final String ICBC_MCH_ID = "150537540002";//商户编号 - private static final String ICBC_MER_PRTCL_NO = "150537540002";//收单产品协议编号 +// private static final String ICBC_MCH_ID = "150537540002";//商户编号 + private static final String ICBC_MCH_ID = "150537540003";//商户编号 +// private static final String ICBC_MER_PRTCL_NO = "150537540004";//收单产品协议编号 + private static final String ICBC_MER_PRTCL_NO = "150537540003";//收单产品协议编号 private static final String ICBC_APPID = "11000000000000051225"; private static final String MY_PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCx24qZDrnPwAOwFJDmBcdEn+gkPj3tIfDi9nptHobqIPIwwZwtsQ20FxzYTG4QCcuFw4iDGb/VL4oxY4cjkWKjlAkVe6eyFdffiA2+toXK/Nu/U/UkcknHxeNE8CGyf/iV+yEwEiiWZ7zjNvXPGcWG+6IZkk4H9iOKwh2xbk3sd50em95meIxgKDOsaKoJ3VvCJs4ajNt8ly+V6B/at7qMF20XoQG7Qtmm1FCv05QVEH3JIYLg7N4TllYEAxKrTz4Wr4/qiiQ/dVRl6pxkDodJ/8UraFfYbsuOizeGZpAaj8lgkljwD9k32ov1X3GSNbG8EZTMJ7mSH5VWGI+w1Eh7AgMBAAECggEAZQwoOEFHjCK5daaZlDYgOnrnNwAtyrYH18rVT32ShR5muxCknMkE0hZ3iuQRfAc0nDC1NFbCyGoUB29WbfzBn9IRPyVb5y/Fz/fKZ1nntaXna1JV6nkMNfXV42rSmklegEeHWXpXmOwjQqwNB7bKpJ/+Pq0CrD9JfiI/IHlcyEVShNTR3SCxpye8Vkca1/HOBcI/aRLJ0t/xkKBXfkJOpUo7QLvEwhqZN0m/Z+AE84TNNscKNDiNmWDCfntFFzuFIbjYXUrkZwWNDU+LCYtOZ6/WXLrFpp2UoeVdJACBxAHqmaNSZltgavH3swDkMswSwj/gt7lK4k/U8rpp3uw3sQKBgQDW5ddgyyXoADRLyvNiqjRNBayaekdgUZwjs3mMQ9tkAuk+hWCGPNHAM+iIkSmjP5x3ajBrLKAPpN1/iJ0aloi9CAICXCoD4B/lfANc6njZxeIWKEZjV4hUYfXsGp57EHGlgDlAKk727IxfsHJeW7gq9KX5aao1qHyT8Yo8FhyzjwKBgQDT4BQ2o4rBCF0okJDJXgF9WexI3LD+N02Tfd9Yuz8zWaM5wgPw2EDPnwp7jrlA6IcCgn/xlAWCZAHzvD/CIg33BH0bqB9LDkJHHNwmCscczw55jwa2RXJfQFDSZ2lFggAB/01ByyU0ex1Px/Q+p2ykueYbWmQV8xst7ZL03Yu2VQKBgF1417fYZQKGpDibbEXsNpeR8kO3EDjLBplYxXPHSDQ2N/Hj3dpFtg5eBbTxPyUs1Af0/l5/qJdlZJrGd19LPurKAuW35OaOpBETYfsWWb6Pngl5NzSarEfX3Dn4UhrBSk1senp4bKRmu6AbhYOZbX/xrgfQeCKiyJ0pILGGBLHtAoGBAJiHXIXpPl6w8r/dMx6EOnZPYjciCZk5nvNrTnrGcj05brSJ4+RjCmVtjVJd8Se1PlykLg9wDHdOH8mj4BKWCY+m/5oFcmHKJhSjxijs4WLv/O+t85sMa8X+uzB9md+cMv09GhUfde1OJE/nFwJz7Va5LdrLO/pBRXPO8FivlYDxAoGBAKnjcXz3rDyXIQZSG7f81P7FudPeHbX4aywI9yWHzXjcHADVwniEBLxR0oE35Wu0gAcmnGB7aJxNqBgIBrc4VU8yJA896gKaneq20JCVKBcfB6EuHJwK31MF/YCA4JnHhuqaJ91JMnOWHkn/6DJlxbvIc+VDtW7czkvhgFS73JDN"; //应用私钥 private static final String APIGW_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMpjaWjngB4E3ATh+G1DVAmQnIpiPEFAEDqRfNGAVvvH35yDetqewKi0l7OEceTMN1C6NPym3zStvSoQayjYV+eIcZERkx31KhtFu9clZKgRTyPjdKMIth/wBtPKjL/5+PYalLdomM4ONthrPgnkN4x4R0+D4+EBpXo8gNiAFsNwIDAQAB"; private static final String DECIVE_INFO = "qHYmicPTZyKO452IV4A2stOozmLj2aYu"; + private static final String ICBC_URL = "https://gw.open.icbc.com.cn/" ; //https://gw-sandbox.open.icbc.com.cn https://gw.open.icbc.com.cn + private Result icbcPay(Double moneys, Integer classify, Long userId, String outTradeNo, HttpServletRequest httpRequest, Integer shop) throws Exception{ UserEntity userEntity = userService.queryByUserId(userId); - String url = "https://gw.open.icbc.com.cn/" ; //https://gw-sandbox.open.icbc.com.cn https://gw.open.icbc.com.cn String action = "api/cardbusiness/aggregatepay/b2c/online/consumepurchase/V1"; // UiIcbcClient client = new UiIcbcClient(APP_ID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY, IcbcConstants.CHARSET_UTF8); @@ -680,7 +686,7 @@ public class WxServiceImpl implements WxService { DefaultIcbcClient client = new DefaultIcbcClient(ICBC_APPID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY, APIGW_PUBLIC_KEY); CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1 request = new CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1(); - request.setServiceUrl(url + action); + request.setServiceUrl(ICBC_URL + action); CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1.CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1Biz bizContent = new CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1.CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1Biz(); request.setBizContent(bizContent); @@ -732,6 +738,7 @@ public class WxServiceImpl implements WxService { CardbusinessAggregatepayB2cOnlineConsumepurchaseResponseV1 response; try { + log.info("----调用icbc支付:{}", JSONObject.toJSONString(request)); response = client.execute(request); log.info("----调用icbc支付回调:{}", JSONObject.toJSONString(response)); if (response.getReturnCode() == 0) { @@ -771,11 +778,11 @@ public class WxServiceImpl implements WxService { } @Override - public String icbcPayBack(HttpServletRequest request, Integer type) throws Exception { - log.info("工商支付回调:"); + public String icbcPayBack(@RequestBody Map reqParams, Integer type) throws Exception { //接收参数 - JSONObject bizContent = JSON.parseObject(request.getParameter("biz_content")); + JSONObject bizContent = JSONObject.parseObject(String.valueOf(reqParams.get("biz_content"))); String msgId = bizContent.getString("msg_id"); + log.info("icbc 支付回调业务参数: {}", bizContent); //应答参数 JSONObject responseBizContent = new JSONObject(); @@ -787,10 +794,10 @@ public class WxServiceImpl implements WxService { String transactionId = bizContent.getString("third_trade_no"); String appid = type == 3 ? commonInfoService.findOne(45).getValue() : commonInfoService.findOne(239).getValue(); - String notifyUrl = (type == 3 ? "/sqx_fast/app/wxPay/notifyJsApiShop" : "/sqx_fast/app/wxPay/notifyJsApi"); + String notifyUrl = (type == 3 ? "/sqx_fast/app/wxPay/notifyJsApi" : "/sqx_fast/app/wxPay/notifyJsApiShop"); //返回码 String returnCode = bizContent.getString("return_code"); - if (this.icbcCheckSign(request, notifyUrl)) { + if (this.icbcCheckSign(reqParams, notifyUrl)) { if ("0".equals(returnCode)) { // log.error("微信支付订单号" + notifyMap.get("transaction_id")); // String transactionId = notifyMap.get("transaction_id"); @@ -964,6 +971,7 @@ public class WxServiceImpl implements WxService { responseBizContent.put("return_code", 0); responseBizContent.put("return_msg", "success"); }else { + log.info("icbc支付回调签名错误"); responseBizContent.put("return_code", -1); responseBizContent.put("return_msg", "icbc sign not pass."); } @@ -979,23 +987,78 @@ public class WxServiceImpl implements WxService { return resp.toJSONString(); } - private boolean icbcCheckSign(HttpServletRequest request, String path) { + private Result icbcPayUI(Double moneys, Integer classify, Long userId, String outTradeNo, HttpServletRequest httpRequest, Integer shop) throws Exception{ + UserEntity userEntity = userService.queryByUserId(userId); + //回调 + String notifyUrl = commonInfoService.findOne(19).getValue() + (shop != null ? "/sqx_fast/app/wxPay/notifyJsApiShop" : "/sqx_fast/app/wxPay/notifyJsApi"); + //微信商户号mchId + String mchId = commonInfoService.findOne(76).getValue(); + //openid + String openId = shop != null ? userEntity.getShopOpenId() : userEntity.getOpenId(); + //商户appid + String mchAppid = shop != null ? commonInfoService.findOne(239).getValue() : commonInfoService.findOne(45).getValue(); + //后台服务名称 + String name = commonInfoService.findOne(12).getValue(); + //订单金额 + String money = String.valueOf(AmountCalUtils.mul(moneys, 100).intValue()); + + UiIcbcClient client = new UiIcbcClient(ICBC_APPID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY, IcbcConstants.CHARSET_UTF8); + CardbusinessAggregatepayB2cOnlineUiConsumepurchaseshowpayRequestV1 request = new CardbusinessAggregatepayB2cOnlineUiConsumepurchaseshowpayRequestV1(); + //根据测试环境和生产环境替换相应ip和端口 + request.setServiceUrl(ICBC_URL + "ui/cardbusiness/aggregatepay/b2c/online/ui/consumepurchaseshowpay/V1"); + CardbusinessAggregatepayB2cOnlineUiConsumepurchaseshowpayRequestV1.CardbusinessAggregatepayB2cOnlineUiConsumepurchaseshowpayRequestV1Biz bizContent = new CardbusinessAggregatepayB2cOnlineUiConsumepurchaseshowpayRequestV1.CardbusinessAggregatepayB2cOnlineUiConsumepurchaseshowpayRequestV1Biz(); + request.setBizContent(bizContent); +// bizContent.setAttach(""); + bizContent.setBody(name); //微信商品描述 + bizContent.setIcbc_appid(ICBC_APPID); + bizContent.setMer_id(ICBC_MCH_ID); + bizContent.setMer_prtcl_no(ICBC_MER_PRTCL_NO); +// bizContent.setMer_acct(""); +// bizContent.setNotify_type(""); + bizContent.setNotify_url(notifyUrl); + bizContent.setOpenId(openId); + bizContent.setOrder_amt(money); + bizContent.setOut_trade_no(outTradeNo); +// bizContent.setPay_limit(""); +// bizContent.setResult_type(""); +// bizContent.setReturn_url(""); + bizContent.setSaledepname(name); // 门店名称 +// bizContent.setSubject(""); + bizContent.setShop_appid(mchAppid); +// bizContent.setOrder_apd_inf(""); +// bizContent.setDetail(name); +// bizContent.setCust_name("xxx"); +// bizContent.setCust_cert_type("x"); +// bizContent.setCust_cert_no("xxxx"); +// bizContent.setGoods_tag("xxx"); + bizContent.setStart_datetime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")); + bizContent.setExpireTime("120"); + String result = ""; + try { + result = client.buildPostForm(request); + } catch (IcbcApiException e) { + return Result.error("获取订单失败" + e.getMessage()); + } + return Result.success().put("data", result); + } + + private boolean icbcCheckSign(Map reqParams, String path) { Map params = new HashMap<>(); - String sign = request.getParameter("sign"); - params.put("from", request.getParameter("from")); - params.put("api", request.getParameter("api")); - params.put("app_id", request.getParameter("app_id")); - params.put("charset", request.getParameter("charset")); - params.put("format", request.getParameter("format")); - params.put("timestamp", request.getParameter("timestamp")); - params.put("biz_content", request.getParameter("biz_content")); + String sign = reqParams.get("sign"); + params.put("from", reqParams.get("from")); + params.put("api", reqParams.get("api")); + params.put("app_id", reqParams.get("app_id")); + params.put("charset", reqParams.get("charset")); + params.put("format", reqParams.get("format")); + params.put("timestamp", reqParams.get("timestamp")); + params.put("biz_content", reqParams.get("biz_content")); //目前上行网关签名暂时仅支持RSA - params.put("sign_type", request.getParameter("sign_type")); + params.put("sign_type", reqParams.get("sign_type")); String signStr= WebUtils.buildOrderedSignStr(path, params); try { //注意:此次用的是RSA,和下单时不一样 - return IcbcSignature.verify(signStr, IcbcConstants.SIGN_TYPE_RSA, APIGW_PUBLIC_KEY, request.getParameter("charset"), sign); + return IcbcSignature.verify(signStr, IcbcConstants.SIGN_TYPE_RSA, APIGW_PUBLIC_KEY, reqParams.get("charset"), sign); } catch (IcbcApiException e) { return false; } @@ -1138,13 +1201,30 @@ public class WxServiceImpl implements WxService { } - public static void main(String[] args) { - String timestamp = DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss"); - String rawToken = "100000002" + "2ry7EXwNHE3zOtUpEUqj1BdkFGuIna67TmKExNxG" + "1740728660"; - String hashedToken = DigestUtil.sha256Hex(rawToken); - String encodedToken = cn.hutool.core.codec.Base64.encode(hashedToken); - System.out.println(System.currentTimeMillis()/1000); - System.out.println(hashedToken); - System.out.println(encodedToken); + public static void main(String[] args) throws IcbcApiException { + String notifyUrl = (true ? "/sqx_fast/app/wxPay/notifyJsApi" : "/sqx_fast/app/wxPay/notifyJsApiShop"); + + String jsonStr = "{\"api\":\"/api/cardbusiness/aggregatepay/b2c/online/consumepurchase/V1\",\"app_id\":\"11000000000000051225\",\"biz_content\":\"{\\\"access_type\\\":\\\"9\\\",\\\"attach\\\":\\\"\\\",\\\"bank_disc_amt\\\":\\\"0\\\",\\\"card_flag\\\":\\\"\\\",\\\"card_kind\\\":\\\"\\\",\\\"card_no\\\":\\\"\\\",\\\"coupon_amt\\\":\\\"0\\\",\\\"cust_id\\\":\\\"\\\",\\\"decr_flag\\\":\\\"\\\",\\\"ecoupon_amt\\\":\\\"0\\\",\\\"mer_disc_amt\\\":\\\"0\\\",\\\"mer_id\\\":\\\"150537540003\\\",\\\"msg_id\\\":\\\"050200155087883006188152791\\\",\\\"open_id\\\":\\\"ow8NuxGas0u7FrZkg-DWi-F1ABwM\\\",\\\"order_id\\\":\\\"150537540003000522503280002157\\\",\\\"out_trade_no\\\":\\\"1000001823360698\\\",\\\"pay_time\\\":\\\"20250328150403\\\",\\\"pay_type\\\":\\\"9\\\",\\\"payment_amt\\\":\\\"10\\\",\\\"point_amt\\\":\\\"0\\\",\\\"return_code\\\":\\\"0\\\",\\\"return_msg\\\":\\\"交易成功\\\",\\\"third_party_coupon_amt\\\":\\\"0\\\",\\\"third_party_discount_amt\\\":\\\"0\\\",\\\"third_trade_no\\\":\\\"4200002667202503283423055973\\\",\\\"total_amt\\\":\\\"10\\\",\\\"total_disc_amt\\\":\\\"0\\\"}\",\"charset\":\"UTF-8\",\"format\":\"json\",\"from\":\"icbc-api\",\"sign\":\"H1wXn/2399BQr3FOpbqdGkNCpiSbi3njGdXsWV5x8nGEzMR+CTuO8ynB+KbsVivmeHX3UERZe0Z1mAtwibIZsJ1S7Li3Hl+XwdjHbBDi7Nkpj/ZHN0iEY7NK4X+b87ZuA2edXjr5Fo2btj7yjPNwr9c5C0C7madncHRziWidjFg=\",\"sign_type\":\"RSA\",\"timestamp\":\"2025-03-28 15:05:56\"}"; + JSONObject reqParams = JSONObject.parseObject(jsonStr); +// System.out.println(jsonObject.getJSONObject("biz_content")); + Map params = new HashMap<>(); + String sign = reqParams.getString("sign"); + params.put("from", reqParams.getString("from")); + params.put("api", reqParams.getString("api")); + params.put("app_id", reqParams.getString("app_id")); + params.put("charset", reqParams.getString("charset")); + params.put("format", reqParams.getString("format")); + params.put("timestamp", reqParams.getString("timestamp")); + params.put("biz_content", reqParams.getString("biz_content")); +// //目前上行网关签名暂时仅支持RSA + params.put("sign_type", reqParams.getString("sign_type")); + + System.out.println(params); +// + String signStr= WebUtils.buildOrderedSignStr(notifyUrl, params); + System.out.println(signStr); + Boolean flag = IcbcSignature.verify(signStr, IcbcConstants.SIGN_TYPE_RSA, APIGW_PUBLIC_KEY, reqParams.getString("charset"), sign); + System.out.println(flag); + } } \ No newline at end of file