| | |
| | | package com.doumee.api.business; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | 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) { |
| | | log.error("微信支付回调结果开始===========" ); |
| | | try { |
| | | ServletInputStream inputStream = request.getInputStream(); |
| | | StringBuffer stringBuffer = new StringBuffer(); |
| | |
| | | .body(body) |
| | | .build(); |
| | | |
| | | NotificationConfig config = new RSAAutoCertificateConfig.Builder() |
| | | NotificationConfig config = 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); |
| | | log.error("支付回调信息:{}"+ JSONObject.toJSONString(result)); |
| | | //自定义订单号 |
| | | String outTradeNo = result.getOutTradeNo(); |
| | | //微信订单号 |
| | |
| | | } else { |
| | | // 支付失败 |
| | | switch (result.getAttach()) { |
| | | case "createGoodsOrder": { |
| | | case "createOrder": { |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | log.error("微信支付回调结果结束===========" ); |
| | | return ApiResponse.success("处理成功!"); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | |
| | | 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(); |
| | | } |
| | | |
| | | } |