|  |  | 
 |  |  | package com.doumee.api.business; | 
 |  |  |  | 
 |  |  | import com.alibaba.fastjson.JSON; | 
 |  |  | import com.doumee.config.wx.TransferDetailEntityNew; | 
 |  |  | import com.doumee.config.wx.WxMiniConfig; | 
 |  |  | import com.doumee.core.constants.Constants; | 
 |  |  | import com.doumee.core.constants.ResponseStatus; | 
 |  |  | import com.doumee.core.exception.BusinessException; | 
 |  |  | import com.doumee.core.model.ApiResponse; | 
 |  |  | import com.doumee.service.business.OrdersService; | 
 |  |  | import com.doumee.service.business.WithdrawalOrdersService; | 
 |  |  | import com.wechat.pay.java.core.Config; | 
 |  |  | import com.wechat.pay.java.core.RSAAutoCertificateConfig; | 
 |  |  | import com.wechat.pay.java.core.RSAPublicKeyConfig; | 
 |  |  | import com.wechat.pay.java.core.notification.NotificationConfig; | 
 |  |  | import com.wechat.pay.java.core.notification.NotificationParser; | 
 |  |  | import com.wechat.pay.java.core.notification.RequestParam; | 
 |  |  | import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction; | 
 |  |  | import com.wechat.pay.java.service.refund.model.RefundNotification; | 
 |  |  | import lombok.extern.slf4j.Slf4j; | 
 |  |  | import org.apache.commons.lang3.StringUtils; | 
 |  |  | import org.apache.shiro.SecurityUtils; | 
 |  |  | import org.apache.shiro.mgt.DefaultSecurityManager; | 
 |  |  | import org.springframework.beans.factory.annotation.Autowired; | 
 |  |  | 
 |  |  | import javax.servlet.ServletInputStream; | 
 |  |  | import javax.servlet.http.HttpServletRequest; | 
 |  |  | import java.io.BufferedReader; | 
 |  |  | import java.io.IOException; | 
 |  |  | import java.io.InputStream; | 
 |  |  | import java.io.InputStreamReader; | 
 |  |  | import java.util.HashMap; | 
 |  |  | import java.util.Map; | 
 |  |  |  | 
 |  |  | /** | 
 |  |  |  * Created by IntelliJ IDEA. | 
 |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private OrdersService ordersService; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private WithdrawalOrdersService withdrawalOrdersService; | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 【微信支付】异步通知 | 
 |  |  |      * | 
 |  |  |      * @return | 
 |  |  |      */ | 
 |  |  |     @PostMapping("/api/wxPayNotify") | 
 |  |  |     @PostMapping("/web/wxPayNotify") | 
 |  |  |     public ApiResponse wxPay_notify(HttpServletRequest request) { | 
 |  |  |         try { | 
 |  |  |             ServletInputStream inputStream = request.getInputStream(); | 
 |  |  | 
 |  |  |                     .body(body) | 
 |  |  |                     .build(); | 
 |  |  |  | 
 |  |  |             NotificationConfig config = new RSAAutoCertificateConfig.Builder() | 
 |  |  |             NotificationConfig config = /*new RSAAutoCertificateConfig.Builder() | 
 |  |  |                     .merchantId(WxMiniConfig.wxProperties.getMchId()) | 
 |  |  |                     .privateKeyFromPath(WxMiniConfig.wxProperties.getPrivateKeyPath()) | 
 |  |  |                     .merchantSerialNumber(WxMiniConfig.wxProperties.getSerialNumer()) | 
 |  |  |                     .apiV3Key(WxMiniConfig.wxProperties.getApiV3Key()) | 
 |  |  |                     .build(); */ | 
 |  |  |             new RSAPublicKeyConfig.Builder() | 
 |  |  |                     .merchantId(WxMiniConfig.wxProperties.getMchId()) | 
 |  |  |                     .privateKeyFromPath(WxMiniConfig.wxProperties.getPrivateKeyPath()) | 
 |  |  |                     .publicKeyFromPath(WxMiniConfig.wxProperties.getPubKeyPath()) | 
 |  |  |                     .publicKeyId(WxMiniConfig.wxProperties.getPayPublicKeyId()) | 
 |  |  |                     .merchantSerialNumber(WxMiniConfig.wxProperties.getSerialNumer()) | 
 |  |  |                     .apiV3Key(WxMiniConfig.wxProperties.getApiV3Key()) | 
 |  |  |                     .build(); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             NotificationParser parser = new NotificationParser(config); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             Transaction result = parser.parse(requestParam, Transaction.class); | 
 |  |  |             //自定义订单号 | 
 |  |  |             String outTradeNo = result.getOutTradeNo(); | 
 |  |  | 
 |  |  |             return ApiResponse.failed(""); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |     @PostMapping("/api/wxRefundNotify") | 
 |  |  |     @PostMapping("/web/wxRefundNotify") | 
 |  |  |     public ApiResponse wxRefundNotify(HttpServletRequest request) { | 
 |  |  |         log.error("微信退款回调结果开始===========" ); | 
 |  |  |         try { | 
 |  |  | 
 |  |  |                     .body(body) | 
 |  |  |                     .build(); | 
 |  |  |  | 
 |  |  |             NotificationConfig config = new RSAAutoCertificateConfig.Builder() | 
 |  |  |             NotificationConfig config = /*new RSAAutoCertificateConfig.Builder() | 
 |  |  |                     .merchantId(WxMiniConfig.wxProperties.getMchId()) | 
 |  |  |                     .privateKeyFromPath(WxMiniConfig.wxProperties.getPrivateKeyPath()) | 
 |  |  |                     .merchantSerialNumber(WxMiniConfig.wxProperties.getSerialNumer()) | 
 |  |  |                     .apiV3Key(WxMiniConfig.wxProperties.getApiV3Key()) | 
 |  |  |                     .build();*/ | 
 |  |  |             new RSAPublicKeyConfig.Builder() | 
 |  |  |                     .merchantId(WxMiniConfig.wxProperties.getMchId()) | 
 |  |  |                     .privateKeyFromPath(WxMiniConfig.wxProperties.getPrivateKeyPath()) | 
 |  |  |                     .publicKeyFromPath(WxMiniConfig.wxProperties.getPubKeyPath()) | 
 |  |  |                     .publicKeyId(WxMiniConfig.wxProperties.getPayPublicKeyId()) | 
 |  |  |                     .merchantSerialNumber(WxMiniConfig.wxProperties.getSerialNumer()) | 
 |  |  |                     .apiV3Key(WxMiniConfig.wxProperties.getApiV3Key()) | 
 |  |  |                     .build(); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             NotificationParser parser = new NotificationParser(config); | 
 |  |  |             RefundNotification result = parser.parse(requestParam, RefundNotification.class); | 
 |  |  | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 微信商户零线转账 - 回调通知 | 
 |  |  |      * @Context注解  把HTTP请求上下文对象注入进来,HttpServletRequest、HttpServletResponse、UriInfo 等 | 
 |  |  |      * @return | 
 |  |  |      */ | 
 |  |  |     @PostMapping(value = "/web/wechat/transferNotify") | 
 |  |  |     public ApiResponse transferNotify( HttpServletRequest request) { | 
 |  |  |         Map<String,String> errMap = new HashMap<>(); | 
 |  |  |         try { | 
 |  |  |             log.error("微信商户零线转账 - 回调通知 /wxpay/callback"); | 
 |  |  |  | 
 |  |  |             Config config = new RSAPublicKeyConfig.Builder() | 
 |  |  |                 .merchantId(WxMiniConfig.wxProperties.getSubMchId()) //微信支付的商户号 | 
 |  |  |                 .privateKeyFromPath(WxMiniConfig.wxProperties.getWechatPrivateKeyPath()) // 商户API证书私钥的存放路径 | 
 |  |  |                 .publicKeyFromPath(WxMiniConfig.wxProperties.getWechatPubKeyPath()) //微信支付公钥的存放路径 | 
 |  |  |                 .publicKeyId(WxMiniConfig.wxProperties.getWechatPayPublicKeyId()) //微信支付公钥ID | 
 |  |  |                 .merchantSerialNumber(WxMiniConfig.wxProperties.getWechatSerialNumer()) //商户API证书序列号 | 
 |  |  |                 .apiV3Key(WxMiniConfig.wxProperties.getWechatApiV3Key()) //APIv3密钥 | 
 |  |  |                 .build(); | 
 |  |  |  | 
 |  |  |             TransferDetailEntityNew entity = wxSuccessCallback(request,config); | 
 |  |  |             log.error("transfer ok.{}",entity); | 
 |  |  |             //回调成功后处理自己的业务 | 
 |  |  |             if(entity != null){ | 
 |  |  |                 if((entity.getState().equals(Constants.SUCCESS) | 
 |  |  |                         || entity.getState().equals(Constants.CANCELLED) | 
 |  |  |                         || entity.getState().equals(Constants.FAIL)) | 
 |  |  |                         && StringUtils.isNotBlank(entity.getOutBillNo())){ | 
 |  |  |                     withdrawalOrdersService.transferSuccess(entity.getOutBillNo(),entity.getState().equals(Constants.SUCCESS)?true:false); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |             return ApiResponse.success("处理成功"); | 
 |  |  |         } catch (Exception e) { | 
 |  |  |             log.error("微信商户零线转账 - 回调通知 /wxpay/callback:异常!", e); | 
 |  |  |             errMap.put("code", "FAIL"); | 
 |  |  |             errMap.put("message", "服务器内部错误"); | 
 |  |  |             return ApiResponse.failed("处理失败"); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     public TransferDetailEntityNew wxSuccessCallback(HttpServletRequest request,Config config) throws IOException { | 
 |  |  |         String requestBody = getBodyString(request, "UTF-8"); | 
 |  |  |         //证书序列号(微信平台)   验签的“微信支付平台证书”所对应的平台证书序列号 | 
 |  |  |         String wechatPaySerial = request.getHeader("Wechatpay-Serial"); | 
 |  |  |         //微信传递过来的签名   验签的签名值 | 
 |  |  |         String wechatSignature = request.getHeader("Wechatpay-Signature"); | 
 |  |  |         //验签的时间戳 | 
 |  |  |         String wechatTimestamp = request.getHeader("Wechatpay-Timestamp"); | 
 |  |  |         //验签的随机字符串 | 
 |  |  |         String wechatpayNonce = request.getHeader("Wechatpay-Nonce"); | 
 |  |  |         // 1. 构造 RequestParam | 
 |  |  |         RequestParam requestParam = new RequestParam.Builder() | 
 |  |  |                 .serialNumber(wechatPaySerial) | 
 |  |  |                 .nonce(wechatpayNonce) | 
 |  |  |                 .signature(wechatSignature) | 
 |  |  |                 .timestamp(wechatTimestamp) | 
 |  |  |                 .body(requestBody) | 
 |  |  |                 .build(); | 
 |  |  |         // 2. 构建Config RSAPublicKeyConfig | 
 |  |  | //        Config config = new RSAPublicKeyConfig.Builder() | 
 |  |  | //                        .merchantId(WxMiniConfig.wxProperties.getMchId()) //微信支付的商户号 | 
 |  |  | //                        .privateKeyFromPath(WxMiniConfig.wxProperties.getPrivateKeyPath()) // 商户API证书私钥的存放路径 | 
 |  |  | //                        .publicKeyFromPath(WxMiniConfig.wxProperties.getWechatPubKeyPath()) //微信支付公钥的存放路径 | 
 |  |  | //                        .publicKeyId(WxMiniConfig.wxProperties.getWechatPayPublicKeyId()) //微信支付公钥ID | 
 |  |  | //                        .merchantSerialNumber(WxMiniConfig.wxProperties.getSerialNumer()) //商户API证书序列号 | 
 |  |  | //                        .apiV3Key("") //APIv3密钥 | 
 |  |  | //                        .build(); | 
 |  |  |         log.info("WxPayService.wxPaySuccessCallback request : wechatPaySerial is [{}]  , wechatSignature is [{}] , wechatTimestamp is [{}] , wechatpayNonce  is [{}] , requestBody is [{}]",wechatPaySerial,wechatSignature,wechatTimestamp,wechatpayNonce,requestBody); | 
 |  |  |         // 3. 初始化 NotificationParser | 
 |  |  |         NotificationParser parser = new NotificationParser((NotificationConfig) config); | 
 |  |  |         try { | 
 |  |  |             TransferDetailEntityNew entity = parser.parse(requestParam, TransferDetailEntityNew.class); | 
 |  |  |             log.info("WxPayService.wxPaySuccessCallback responseBody: {}", entity != null ? JSON.toJSONString(entity) : null); | 
 |  |  |             return entity; | 
 |  |  |         } catch (Exception e) { | 
 |  |  |             log.error("Exception occurred while processing", e); | 
 |  |  |             throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"系统内部错误"); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 获取post请求中的Body | 
 |  |  |      * | 
 |  |  |      * @param request httpRequest | 
 |  |  |      * @return body字符串 | 
 |  |  |      */ | 
 |  |  |     public static String getBodyString(HttpServletRequest request, String charSet) throws IOException { | 
 |  |  |         StringBuilder sb = new StringBuilder(); | 
 |  |  |         InputStream inputStream = null; | 
 |  |  |         BufferedReader reader = null; | 
 |  |  |         try { | 
 |  |  |             inputStream = request.getInputStream(); | 
 |  |  |             //读取流并将流写出去,避免数据流中断; | 
 |  |  |             reader = new BufferedReader(new InputStreamReader(inputStream, charSet)); | 
 |  |  |             String line; | 
 |  |  |             while ((line = reader.readLine()) != null) { | 
 |  |  |                 sb.append(line); | 
 |  |  |             } | 
 |  |  |         } catch (IOException e) { | 
 |  |  |             log.error("获取requestBody异常", e); | 
 |  |  |         } finally { | 
 |  |  |             inputStream.close(); | 
 |  |  |             reader.close(); | 
 |  |  |         } | 
 |  |  |         return sb.toString(); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | } |