支付宝APP支付、退款、查询订单

最近在搞支付这块,总算告一段落了,来记录一下,以后找不迷路,在此也希望帮到一些同学,

其实支付宝的技术客服还挺好的,你可以找他们要示例,不像wx......就太......。

需要准备的东西如下:

appid、应用私钥、应用公钥证书、支付宝公钥证书、支付宝根证书

 

依赖

 <!-- alipay-->
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <!--<version>3.7.26.ALL</version>-->
        </dependency>

 

下面就粘下重要的代码

这里说明下,下面这些api都是以证书的方式请求的。如果你平台上是设置秘钥形式的。可以去掉证书。

APP支付

    /**
     * 支付宝APP支付
     *
     * @param aliPayParam 支付宝参数类
     * @return
     */
    @Override
    public String aliPayAPPToPay(AliPayParam aliPayParam) {
        try {
            //设置支付宝请求
            CertAlipayRequest certAlipayRequest = setUpAliPayAsk();
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            // 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay(app 支付接口)
            AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
            // 设置业务参数
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            // 商户订单号,商户自定义,需保证在商户端不重复,如:20200612000001
            String outTradeNo = String.valueOf(snowflake.nextId());
            model.setOutTradeNo(outTradeNo);
            //订单标题
            model.setSubject(aliPayParam.getSubject());
            // 销售产品码,固定值 QUICK_MSECURITY_PAY
            model.setProductCode(AliPayConfig.product_code_app);
            // 订单金额,精确到小数点后两位 **/
            model.setTotalAmount(aliPayParam.getTotalAmount().toString());
            // 订单描述
            model.setBody(aliPayParam.getBody());
            // 业务扩展参数
            //ExtendParams extendParams = new ExtendParams();
            // 系统商编号,填写服务商的PID用于获取返佣,返佣参数传值前提:传值账号需要签约返佣协议,用于isv商户。
            //extendParams.setSysServiceProviderId("2088511****07846");
            // 花呗分期参数传值前提:必须有该接口花呗收款准入条件,且需签约花呗分期
            // 指定可选期数,只支持3/6/12期,还款期数越长手续费越高
            // extendParams.setHbFqNum("3");
            // 指定花呗分期手续费承担方式,手续费可以由用户全承担(该值为0),也可以商户全承担(该值为100),但不可以共同承担,即不可取0和100外的其他值。 **/
            //extendParams.setHbFqSellerPercent("0");
            //model.setExtendParams(extendParams);

            // 将业务参数至request中
            request.setBizModel(model);
            // 异步通知地址,以http或者https开头的,商户外网可以post访问的异步地址,用于接收支付宝返回的支付结果,如果未收到该通知可参考该文档进行确认:https://opensupport.alipay.com/support/helpcenter/193/201602475759
            request.setNotifyUrl(AliPayConfig.notify_url + AliPayConfig.AliPay_APP_PAY_Callback);
            //第三方调用(服务商模式),传值app_auth_token后,会收款至授权token对应商家账号,如何获传值app_auth_token请参考文档:https://opensupport.alipay.com/support/helpcenter/79/201602494631
            //request.putOtherTextParam("app_auth_token", "传入获取到的app_auth_token值");
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            if (response.isSuccess()) {
                return response.getBody();
              
            } else {
                return response.getSubMsg();
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return e.getMessage();
        }
        
    }

不需要处理,返回一段字符给前端唤醒收银台页面就ok。

参考:https://opendocs.alipay.com/apis/api_1/alipay.trade.app.pay

 

查询支付宝订单

/**
     * 查询支付宝订单
     *
     * @param aliPayParam 支付宝参数类
     * @return
     */
    @Override
    public AlipayTradeQueryResponse queryAliPayOrder(AliPayParam aliPayParam) {
        try {
            //设置支付宝请求
            CertAlipayRequest certAlipayRequest = setUpAliPayAsk();
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            JSONObject bizContent = new JSONObject();
            if (StringUtils.isNotEmpty(aliPayParam.getOutTradeNo())) {
                bizContent.put("out_trade_no", aliPayParam.getOutTradeNo());
            }
            if (StringUtils.isNotEmpty(aliPayParam.getTradeNo())) {
                bizContent.put("trade_no", aliPayParam.getTradeNo());
            }
            request.setBizContent(bizContent.toString());
            AlipayTradeQueryResponse response = alipayClient.certificateExecute(request);
            if (response.isSuccess()) {
                System.out.println("调用成功");
                return response;
            } else {
                System.out.println("调用失败");
            }

        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        throw new CustomException("系统繁忙,请稍后重试");
    }

 

支付宝退款

 /**
     * 支付宝退款
     *
     * @param payRefund 支付宝退款参数类
     * @return
     */
    @Override
    public AlipayTradeRefundResponse aliPayRefund(AliPayRefundParam payRefund) {
        //设置支付宝请求
        CertAlipayRequest certAlipayRequest = setUpAliPayAsk();
        try {
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            // 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.refund(统一收单交易退款接口)
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            // 设置业务参数
            AlipayTradeRefundModel model = new AlipayTradeRefundModel();
            // 支付接口传入的商户订单号。如:2020061601290011200000140004
            model.setOutTradeNo(payRefund.getOutTradeNo());
            // 退款金额,退款总金额不能大于该笔订单支付最大金额 **/
            model.setRefundAmount(payRefund.getRefundAmount().toString());
            // 异步通知/查询接口返回的支付宝交易号,如:2020061622001473951448314322
            model.setTradeNo(payRefund.getTradeNo());
            //随机数  不是全额退款,部分退款必须使用该参数,同一个订单,不同的out_request_no代表部分退款
            //String outRequestNo = RandomStringUtils.randomAlphanumeric(13);
            // 如需部分退款,则此参数必传,且每次请求不能重复,如:202006230001
            model.setOutRequestNo(payRefund.getRefundNo());
            model.setRefundReason(payRefund.getRefundReason());
            request.setBizModel(model);
            //第三方调用(服务商模式),传值app_auth_token后,会收款至授权token对应商家账号,如何获传值app_auth_token请参考文档:https://opensupport.alipay.com/support/helpcenter/79/201602494631
            //request.putOtherTextParam("app_auth_token", "传入获取到的app_auth_token值");
            // 通过alipayClient调用API,获得对应的response类
            AlipayTradeRefundResponse response = alipayClient.certificateExecute(request);
            // 获取接口调用结果,如果调用失败,可根据返回错误信息到该文档寻找排查方案:https://opensupport.alipay.com/support/helpcenter/101
            return response;
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        throw new CustomException("系统繁忙,请稍后重试");
    }

参考:https://opendocs.alipay.com/apis/028pxn

 

查询支付宝退款订单

 /**
     * 查询支付宝退款订单
     *
     * @param payRefund 支付宝退款参数类
     * @return
     */
    @Override
    public AlipayTradeFastpayRefundQueryResponse aliPayRefundQuery(AliPayRefundParam payRefund) {
        try {
            //设置支付宝请求
            CertAlipayRequest certAlipayRequest = setUpAliPayAsk();
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
            com.alibaba.fastjson.JSONObject bizContent = new com.alibaba.fastjson.JSONObject();
            if (StringUtils.isNotEmpty(payRefund.getOutTradeNo())) {
                bizContent.put("outTrade_no", payRefund.getOutTradeNo());
            }
            if (StringUtils.isNotEmpty(payRefund.getTradeNo())) {
                bizContent.put("trade_no", payRefund.getTradeNo());
            }
            if (StringUtils.isNotEmpty(payRefund.getRefundNo())){
                bizContent.put("out_request_no", payRefund.getRefundNo());
            }
            request.setBizContent(bizContent.toString());
            AlipayTradeFastpayRefundQueryResponse response = alipayClient.certificateExecute(request);
            if (response.isSuccess()) {
                return response;
            } else {
                System.out.println("查订单失败");
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        throw new CustomException("系统繁忙,请稍后重试");
    }

参考:https://opendocs.alipay.com/apis/028xqc

 

封装支付宝请求

/**
     * 设置支付宝请求
     *
     * @return
     */
    public CertAlipayRequest setUpAliPayAsk() {
        // 初始化
        CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
        // 支付宝网关
        certAlipayRequest.setServerUrl(AliPayConfig.SERVER_URL);
        // 应用id
        certAlipayRequest.setAppId(AliPayConfig.APP_ID);
        // 应用私钥
        certAlipayRequest.setPrivateKey(AliPayConfig.APP_PRIVATE_KEY);
        try {
            // 应用公钥证书路径,下载后保存位置的绝对路径
            certAlipayRequest.setCertPath(String.valueOf(ResourceUtils.getFile(AliPayConfig.APPLICATION_PUBLIC_KEY_CERT)));
            // 支付宝公钥证书路径,下载后保存位置的绝对路径
            certAlipayRequest.setAlipayPublicCertPath(String.valueOf(ResourceUtils.getFile(AliPayConfig.AliPay_PUBLIC_CERT)));
            // 支付宝根证书路径,下载后保存位置的绝对路径
            certAlipayRequest.setRootCertPath(String.valueOf(ResourceUtils.getFile(AliPayConfig.ROOT_CERT_PATH)));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // 设置签名类型
        certAlipayRequest.setSignType(AliPayConfig.sign_type);
        // 设置请求格式,固定值json
        certAlipayRequest.setFormat(AliPayConfig.FORMAT);
        // 设置编码格式
        certAlipayRequest.setCharset(AliPayConfig.charset);
        return certAlipayRequest;
    }

 

回调通知(支付宝的支付回调通知与退款的回调通知是一块的)

因此我们需要根据返回的字段值做判断

 

 

 回调通知

   /**
     * 支付宝支付、退款成功回调
     *
     * @param request HttpServlet 请求
     */
    @Override
    public Integer aliPayNotify(HttpServletRequest request) {
        //获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        log.info("requestParams: {}", requestParams);
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        // 商户订单号
        //String out_trade_no = request.getParameter("out_trade_no");
        // 订单内容
        //String orderContent = request.getParameter("body");
        // 交易状态 支付成功:TRADE_SUCCESS,  交易关闭:TRADE_CLOSED, 交易完成:TRADE_FINISHED
        String tradeStatus = request.getParameter("trade_status");
        //签名验证(对支付宝返回的数据验证,确定是支付宝返回的)
        try {
            //调用SDK验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(params, AliPayConfig.AliPay_PUBLIC_KEY, AliPayConfig.charset, AliPayConfig.sign_type);
            //验证签约是否成功
            if (signVerified) {
                log.info("验签成功");
                log.info("交易状态: {}", tradeStatus);
                if (tradeStatus.equals("TRADE_SUCCESS")) {
                    System.out.println("交易状态为TRADE_SUCCESS");
                }
                //支付宝交易号
                String tradeNo = params.get("trade_no");
                log.info("tradeNo: {}", tradeNo);
                //系统订单编号
                String outTradeNo = params.get("out_trade_no");
                log.info("outTradeNo: {}", outTradeNo);

                //商户业务号 这里作为退款单号
                String outBizNo = params.get("out_biz_no");
                //退款总金额
                String refundFee = params.get("refund_fee");
                //交易退款时间
                String gmtRefund = params.get("gmt_refund");
                if (StringUtils.isNotEmpty(refundFee) && StringUtils.isNotEmpty(gmtRefund)) {
                    System.out.println("退款成功回调通知");
                  

                } else {
                    System.out.println("支付成功回调通知");
                  
                }
            } else {
                log.info("数字签名验证失败: {}", "500");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("异常状态: {} ", e.getMessage());
        }
        return Constants.SUCCESS;
    }

参考:https://opendocs.alipay.com/open/204/105301

 

如有哪里写的不好的还请多多包涵,有问题请下方留言哦

posted @ 2021-11-04 10:25  安详的苦丁茶  阅读(817)  评论(0编辑  收藏  举报