SSM项目集成微信支付宝第三方支付

本文介绍了一个支付控制器类,用于处理不同支付方式的订单支付流程,包括验证请求签名、调用支付平台API进行支付,并处理支付通知。同时,还涉及退款管理类,用于处理退款请求,包括验证订单信息和调用支付平台API进行退款。
摘要由CSDN通过智能技术生成
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


@Controller
public class PayController {
    private Logger logger = LoggerFactory.getLogger(PayController.class);
    @Autowired
    private PayResultValidator payResultValidator;
    @Autowired
    private PlatformPayer platformPayer;
    @Autowired
    private OrderService orderService;
    @Value("${signkey}")
    private String signkey;
    @Autowired
    private RestTemplate restTemplate;


    /**
     * payWay: 支付方式,暂时只有一个  WeiXin   ZhiFuBao
     * orderNumber:  订单的编号
     *
     * @param payWay
     * @return
     */
    @RequestMapping(value = "/mc/pay/{payWay}", method = RequestMethod.POST)
    public ResponseDto pay(@PathVariable PayWay payWay,
                                 @RequestParam String orderNumber,
                                 @RequestParam String sign, String tradeType, HttpServletRequest httpServletRequest
    ) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("orderNumber", orderNumber);
        params.put("signkey", signkey);
        if (!SignUtils.verification(params, sign)) {
            throw new RuntimeException("请求签名失败");
        }
        String clientIp = httpServletRequest.getHeader("X-Forwarded-For").split(",")[0];
        PayDto payDto = platformPayer.pay(payWay, Long.valueOf(orderNumber), tradeType, clientIp, null);
        return new ResponseDto().success(payDto);
    }

    @RequestMapping(value = "/mi/pay/notify/{payWay}")
    public void payNotify(@PathVariable PayWay payWay, HttpServletRequest request) {
        Map<String, Object> map = XmlUtils.getParameterMap(request);
//        payResultValidator.validate(map);
        String orderNumber = map.get("orderNo").toString();
        Double orderPrice = Double.valueOf(map.get("orderPrice").toString());
        orderService.handlePayResult(payWay, orderNumber, orderPrice);
    }

    @RequestMapping(value = "/mc/h5pay/{payWay}", method = RequestMethod.POST)
    public ResponseDto h5Pay(@PathVariable PayWay payWay,
                                   @RequestParam String orderNumber, @RequestParam String tradeType, HttpServletRequest request
    ) throws IOException {
        //生产环境和测试使用这个
        String clientIp = request.getHeader("X-Forwarded-For").split(",")[0];
        //本地使用这个
//        String clientIp = WebUtils.clientIp(request);
        PayDto payDto = platformPayer.pay(payWay, Long.valueOf(orderNumber), tradeType, clientIp, null);
        return new ResponseDto().success(payDto);
    }

    @RequestMapping(value = "/mc/public/number/{payWay}", method = RequestMethod.POST)
    public ResponseDto publicNumber(@PathVariable PayWay payWay,
                                          @RequestParam String orderNumber, @RequestParam String tradeType, HttpServletRequest request, HttpSession session
    ) throws IOException {
        //生产环境和测试使用这个
        String clientIp = request.getHeader("X-Forwarded-For").split(",")[0];
        //本地使用这个
//        String clientIp = WebUtils.clientIp(request);
        String openId = String.valueOf(session.getAttribute("openId"));
        PayDto payDto = platformPayer.pay(payWay, Long.valueOf(orderNumber), tradeType, clientIp, openId);
        return new ResponseDto().success(payDto);
    }


}

 

 

 

 

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.Map;

@Component
public class PlatformPayer {

    
    private static final Logger logger = LoggerFactory.getLogger(PlatformPayer.class);
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private SellerRepository sellerRepository;

    @Value("${pay.notify.url}")
    private String notifyUrl;

    @Value("${pay.create.ip}")
    private String createIp;

    @Value("${pay.url}")
    private String url;

    @Value("${h5.pay.url}")
    private String H5PayUrl;


    protected OrderService orderService = SpringUtils.getBean(OrderService.class);

    @SuppressWarnings("unchecked")
    public PayDto pay(PayWay payWay, Long orderNumber, String tradeType, String clientIp, String openId) {
        //校验传入的订单
        Order order = orderService.findByOrderNumber(orderNumber);
        if (order == null) {
            throw new Exception("未能找到订单,检查订单号");
        }
        if (!OrderStatus.WaitPay.equals(order.getStatus())) {
            throw new Exception("订单已支付");
        }

        Seller seller = sellerRepository.findOne(order.getSellerId());

        String goodsNames = orderService.findAllGoodsNames(String.valueOf(orderNumber));

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("X-Requested-With", "XMLHttpRequest");

        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        //todo 公众号支付的payKey
        params.add("payKey", seller.getPayKey());
        params.add("productName", goodsNames);
        params.add("orderIp", clientIp);
        params.add("payWayCode", payWay.getCode());
        params.add("orderNo", String.valueOf(orderNumber));
        String orderTimeStr = Utils.toDateText(new Date(), MonkeyUtils.DEFAULT_DATE_TIME_FORMAT);
        params.add("orderTime", orderTimeStr);
        params.add("orderPeriod", "60");
        params.add("orderPrice", String.valueOf(order.getShouldPay()));
        params.add("notifyUrl", notifyUrl + "/" + payWay.name() + ".htm");
        params.add("remark", "商品订单");
        if (Utils.isNotEmpty(tradeType)) {
            params.add("tradeType", tradeType);
        }
        if ("JSAPI".equals(tradeType)) {
            params.add("openId", openId);
        }
        params.add("sign", MerchantApiUtil.getSign(params.toSingleValueMap(), seller.getPaySecret()));

        logger.info("app支付,传递参数:{}", params);
        logger.info("app支付,传递参数:{}", params);

        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
        String body = "";
        if (Utils.isEmpty(tradeType)) {
            body = restTemplate.postForObject(url, requestEntity, String.class);
        } else {
            body = restTemplate.postForObject(H5PayUrl, requestEntity, String.class);
        }
        logger.info("微信支付返回:{}", body);
        logger.info("微信支付返回:{}", body);
        JSONObject data = JSON.parseObject(body);
        if (!data.getBoolean("success")) {
            throw new Exception("支付平台异常,请稍后重试");
        }

        PayDto payDto;
        if (PayWay.ZhiFuBao.equals(payWay)) {
            payDto = new PayDto(PayWay.ZhiFuBao);
            payDto.setZhiFuBaoResponse(data.getString("data"));

        } else {
            JSONObject object = JSON.parseObject(data.getString("data"));
            payDto = new PayDto(payWay);
            payDto.setWeiXinResponse((Map<String, String>) object.get("appWakeUp"));
        }

        return payDto;
    }


}

 

 

 

public enum PayWay {
    None("未知"),
    WeiXin("微信") {
        @Override
        public void sign(String key, Map<String, String> map) {
            Map<String, String> params = SignUtils.paraFilter(map);
            StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
            SignUtils.buildPayParams(buf, params, false);
            String preStr = buf.toString();
            String sign = MD5.sign(preStr, "&key=" + key, Constants.ENCODING);
            map.put("sign", sign);
        }

        @Override
        public String getCode() {
            return "WEIXIN";
        }
    },
    ZhiFuBao("支付宝") {
        @Override
        public String getCode() {
            return "ALIPAY";
        }
    },
    WeiXinH5("微信H5支付"){
        @Override
        public String getCode() {
            return "WEIXIN";
        }
    };

    private String label;

    PayWay(String label) {
        this.label = label;
    }

    public String getLabel() {
        return label;
    }


    public void sign(String key, Map<String, String> map) {
        throw new UnsupportedOperationException();
    }

    public String getCode() {
        throw new UnsupportedOperationException();
    }

 

 

 

 

 

 

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Date;


@Component
public class RefundManager {

    private Logger logger = LoggerFactory.getLogger(RefundManager.class);

    @Autowired
    private RestTemplate restTemplate;

    @Value("${refund.notify.url}")
    private String notifyUrl;

    @Value("${refund.url}")
    private String url;


    @Autowired
    private AfterSaleServerService afterSaleServerService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private SellerRepository sellerRepository;



    public void refund(Long afterSaleId, String remark) {
        AfterSaleServer afterSaleServer = afterSaleServerService.findOne(afterSaleId);
        Order order = orderService.findOne(afterSaleServer.getOrderId());
        if (order == null) {
            throw new Exception("未能找到订单,检查订单号");
        }
        if (OrderStatus.WaitPay.equals(order.getStatus())) {
            throw new Exception("订单未支付");
        }

        Seller seller = sellerRepository.findOne(order.getSellerId());

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("X-Requested-With", "XMLHttpRequest");

        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("payKey", seller.getPayKey());
        params.add("orderNo", order.getNumber());
        params.add("refundOrderNo", afterSaleServer.getNumber());
        params.add("refundRequestTime", Utils.toDateText(new Date(), MonkeyUtils.DEFAULT_DATE_TIME_FORMAT));
        params.add("refundAmount", String.valueOf(afterSaleServer.getAmountOfRefund()));
        params.add("notifyUrl", notifyUrl + "/" + order.getPayWay().name() + ".htm");
        params.add("refundReason", afterSaleServer.getProblemDes());
        params.add("remark", remark);
        params.add("sign", MerchantApiUtil.getSign(params.toSingleValueMap(), seller.getPaySecret()));

        logger.info("market info: {}", params);

        System.out.println("============================");
        System.out.println(url);
        System.out.println(JSON.toJSONString(params));

        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
        String body = restTemplate.postForObject(url, requestEntity, String.class);
        System.out.println("============================");
        System.out.println(body);


        JSONObject data = JSON.parseObject(body);
        if (!data.getBoolean("success")) {
            System.out.println(body);
            throw new Exception("支付平台异常,请稍后重试");
        }

    }

 

 

 

 

 

 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class PlatformPayResultValidator implements PayResultValidator {


    @Autowired
    private OrderService orderService;
    @Autowired
    private SellerService sellerService;

    @Override
    public void validate(Map<String, Object> params) {

        String payKey = params.get("payKey").toString();
        String orderNo = params.get("orderNo").toString();
        Order order = orderService.findByOrderNumber(Long.valueOf(orderNo));

        Seller seller = sellerService.findOne(order.getSellerId());

        if (!seller.getPayKey().equals(payKey)) {
            throw new ValidateFailException("支付key 不正确,接收到的key: " + payKey + ", 商户key: " + seller.getPayKey());
        }

        String tradeStatus = params.get("tradeStatus").toString();
        if (!"SUCCESS".equals(tradeStatus)) {
            throw new ValidateFailException("支付平台订单状态不是SUCCESS,tradeStatus:" + tradeStatus);
        }

        String sign = params.get("sign").toString();
        params.remove("sign");
        if (!MerchantApiUtil.isRightSign(params, seller.getPaySecret(), sign)) {
            throw new ValidateFailException("订单签名异常,sign:" + sign);
        }

        if (order == null) {
            throw new ValidateFailException("订单编号不对,orderNo:" + orderNo);
        }

        Double orderPrice = Double.valueOf(params.get("orderPrice").toString());
        if (!orderPrice.equals(order.getShouldPay())) {
            throw new ValidateFailException("订单价格不对,orderPrice:" + orderPrice);
        }
    }

}

 

public class ValidateFailException extends RuntimeException {

    public ValidateFailException() {
    }

    public ValidateFailException(String message) {
        super(message);
    }
}

 

 

参考文档:  http://blog.51cto.com/sihai/2131168

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值