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 org.springframework.web.bind.annotation.CrossOrigin; 
 | 
import org.springframework.web.bind.annotation.PostMapping; 
 | 
import org.springframework.web.bind.annotation.RestController; 
 | 
  
 | 
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. 
 | 
 * 支付回调 
 | 
 * @Author : Rk 
 | 
 * @create 2023/2/23 13:49 
 | 
 */ 
 | 
@Slf4j 
 | 
@RestController 
 | 
@CrossOrigin 
 | 
public class PaymentCallback { 
 | 
  
 | 
    @Autowired 
 | 
    private OrdersService ordersService; 
 | 
  
 | 
    @Autowired 
 | 
    private WithdrawalOrdersService withdrawalOrdersService; 
 | 
  
 | 
    /** 
 | 
     * 【微信支付】异步通知 
 | 
     * 
 | 
     * @return 
 | 
     */ 
 | 
    @PostMapping("/web/wxPayNotify") 
 | 
    public ApiResponse wxPay_notify(HttpServletRequest request) { 
 | 
        log.error("微信支付回调结果开始===========" ); 
 | 
        try { 
 | 
            ServletInputStream inputStream = request.getInputStream(); 
 | 
            StringBuffer stringBuffer = new StringBuffer(); 
 | 
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 
 | 
            String s; 
 | 
            //读取回调请求体 
 | 
            while ((s = bufferedReader.readLine()) != null) { 
 | 
                stringBuffer.append(s); 
 | 
            } 
 | 
            String body = stringBuffer.toString(); 
 | 
            String timestamp = request.getHeader("Wechatpay-Timestamp"); 
 | 
            String nonce = request.getHeader("Wechatpay-Nonce"); 
 | 
            String signType = request.getHeader("Wechatpay-Signature-Type"); 
 | 
            String serialNo = request.getHeader("wechatpay-Serial"); 
 | 
            String signature = request.getHeader("Wechatpay-Signature"); 
 | 
            RequestParam requestParam = new RequestParam.Builder() 
 | 
                    .serialNumber(serialNo) 
 | 
                    .nonce(nonce) 
 | 
                    .signType(signType) 
 | 
                    .signature(signature) 
 | 
                    .timestamp(String.valueOf(timestamp)) 
 | 
                    .body(body) 
 | 
                    .build(); 
 | 
  
 | 
            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(); 
 | 
            //微信订单号 
 | 
            String paymentNo = result.getTransactionId(); 
 | 
            if ("SUCCESS".equals(result.getTradeState().name())) { 
 | 
                // 支付成功ge 
 | 
                switch (result.getAttach()) { 
 | 
                    //支付订单回调 
 | 
                    case "createOrder": { 
 | 
                        ordersService.payNotify(outTradeNo,paymentNo); 
 | 
                        break; 
 | 
                    } 
 | 
                } 
 | 
            } else { 
 | 
                // 支付失败 
 | 
                switch (result.getAttach()) { 
 | 
                    case "createOrder": { 
 | 
                        break; 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
            log.error("微信支付回调结果结束===========" ); 
 | 
            return ApiResponse.success("处理成功!"); 
 | 
        } catch (Exception e) { 
 | 
            e.printStackTrace(); 
 | 
            log.error("微信回调结果异常,异常原因{}", e.getLocalizedMessage()); 
 | 
            return ApiResponse.failed(""); 
 | 
        } 
 | 
    } 
 | 
    @PostMapping("/web/wxRefundNotify") 
 | 
    public ApiResponse wxRefundNotify(HttpServletRequest request) { 
 | 
        log.error("微信退款回调结果开始===========" ); 
 | 
        try { 
 | 
            DefaultSecurityManager securityManager = new DefaultSecurityManager(); 
 | 
            SecurityUtils.setSecurityManager(securityManager); 
 | 
            ServletInputStream inputStream = request.getInputStream(); 
 | 
            StringBuffer stringBuffer = new StringBuffer(); 
 | 
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 
 | 
            String s; 
 | 
            //读取回调请求体 
 | 
            while ((s = bufferedReader.readLine()) != null) { 
 | 
                stringBuffer.append(s); 
 | 
            } 
 | 
            String body = stringBuffer.toString(); 
 | 
            String timestamp = request.getHeader("Wechatpay-Timestamp"); 
 | 
            String nonce = request.getHeader("Wechatpay-Nonce"); 
 | 
            String signType = request.getHeader("Wechatpay-Signature-Type"); 
 | 
            String serialNo = request.getHeader("wechatpay-Serial"); 
 | 
            String signature = request.getHeader("Wechatpay-Signature"); 
 | 
            RequestParam requestParam = new RequestParam.Builder() 
 | 
                    .serialNumber(serialNo) 
 | 
                    .nonce(nonce) 
 | 
                    .signType(signType) 
 | 
                    .signature(signature) 
 | 
                    .timestamp(String.valueOf(timestamp)) 
 | 
                    .body(body) 
 | 
                    .build(); 
 | 
  
 | 
            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); 
 | 
//            if ("SUCCESS".equals(result.getRefundStatus().name())) { 
 | 
                // 支付成功ge 
 | 
                     ordersService.refundCallback(result); 
 | 
//            } 
 | 
            return ApiResponse.success("处理成功"); 
 | 
        } catch (Exception e) { 
 | 
            e.printStackTrace(); 
 | 
            log.error("微信回调结果异常,异常原因{}", e.getLocalizedMessage()); 
 | 
            return ApiResponse.failed(""); 
 | 
        } 
 | 
    } 
 | 
  
 | 
  
 | 
  
 | 
  
 | 
    /** 
 | 
     * 微信商户零线转账 - 回调通知 
 | 
     * @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(); 
 | 
    } 
 | 
  
 | 
} 
 |