天天看点

策略模式实现支付宝支付前言一、准备二、主要代码三、测试结果

策略模式实现支付宝支付

  • 前言
  • 一、准备
  • 二、主要代码
    • 1、项目结构
    • 2、支付宝支付方式枚举类
    • 3、支付常量类
    • 4、支付宝支付相关常量
    • 5、支付宝配置类
    • 6、用到的两个实体类
    • 7、调用支付宝支付的工具类
    • 8、controller
  • 三、测试结果

本文主要以 支付宝手机网站支付为例,利用策略模式开发支付宝支付,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考和学习价值,有需要的小伙伴们就来一起学习学习吧-_-

前言

策略模式

主要解决: 在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护

何时使用: 一个系统有许多许多类,而区分它们的只是他们直接的行为

如何解决: 将这些算法封装成一个一个的类,任意地替换

关键代码: 实现同一个接口

优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。

缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露

一、准备

1、到支付宝商户平台申请,获取到APPID、支付宝公钥、商户私钥

2、开发过程中所用到的依赖

<dependency>
        <groupId>com.alipay.sdk</groupId>
        <artifactId>alipay-sdk-java</artifactId>
        <version>4.22.32.ALL</version>
    </dependency>
           
<dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
       <version>3.12.0</version>
   </dependency>
           

二、主要代码

1、项目结构

策略模式实现支付宝支付前言一、准备二、主要代码三、测试结果

2、支付宝支付方式枚举类

package com.wr.common.enums;

/**
 * @Author: RainCity
 * @Date: 2022-02-18 17:34:44
 * @Desc: 支付宝支付方式枚举类
 */
public enum AliEnum {
    /** app支付 */
    APP("APP"),
    /** 手机网站支付 */
    WAP("WAP"),
    /**  电脑网站支付 */
    PAGE("PAGE"),
    /** 手机扫码支付 */
    QR_CODE("QR_CODE"),
    /** 付款码支付 */
    AUTH_CODE("AUTH_CODE");

    private final String value;

    AliEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

           

3、支付常量类

这里放一些支付会用到的常量

package com.wr.common.constant;

/**
 * @Author: RainCity
 * @Date: 2022-02-26 14:43:22
 * @Desc: 支付常量类
 */
public class PayConstants {

    /**页面服务地址*/
    public static final String SERVER_URL = "";

    /**UTF_8编码*/
    public static final String UTF_8 = "UTF-8";
    /**json格式*/
    public static final String FORMAT_JSON = "json";
    /**RSA2*/
    public static final String SIGN_RSA2 = "RSA2";

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    public static String YYYY_MM_DD_T_HH_mm_ss_TIMEZONE = "yyyy-MM-dd'T'HH:mm:ss'+08:00'";
}

           

4、支付宝支付相关常量

这里放的是仅支付宝中的相关常量,以后会写微信支付,所以和上面那个 PayConstants 分开,这样便于维护

package com.wr.common.constant;

/**
 * @Author: RainCity
 * @Date: 2022-02-28 15:16:47
 * @Desc: 支付宝支付相关常量
 */
public class AliConstants {
    /**支付宝回调地址*/
    public static final String NOTIFY_URL = "http://xxxx/api/ali/notify";
    /**网页重定向通知地址 HTTP/HTTPS开头字符串*/
    public static final String RETURN_URL = "http://xxxx/api/ali/ali_return";
    /**用户付款中途退出返回商户网站的地址*/
    public static final String QUIT_URL = "http://xxxx/api/ali/ali_quit";
    /**支付宝支付回调成功返回*/
    public static final String ALI_SUCCESS_RETURN = "success";
    /**支付宝支支付回调失败返回*/
    public static final String ALI_FAILED_RETURN = "failure";
    /**
     * 交易支付成功
     */
    public static final String TRADE_SUCCESS = "TRADE_SUCCESS";
    /**
     * 交易创建,等待买家付款
     */
    public static final String WAIT_BUYER_PAY = "WAIT_BUYER_PAY";
    /**
     * 未付款交易超时关闭,或支付完成后全额退款
     */
    public static final String TRADE_CLOSED = "TRADE_CLOSED";
    /**
     * 交易结束,不可退款
     */
    public static final String TRADE_FINISHED = "TRADE_FINISHED";
}

           

5、支付宝配置类

这里的配置也可以放到项目中的配置文件里面,这里只是写了一个demo,并没有用到配置类,懒得去搞了0.0,就写到一个类中了,根据大家需求,自行选择。。。

package com.wr.common.config;

/**
 * @Author: RainCity
 * @Date: 2022-02-26 14:46:01
 * @Desc: 支付宝配置类
 */
public class AliConfig {
    /**
     * 支付宝网关
     * https://openapi.alipaydev.com/gateway.do
     * https://openapi.alipay.com/gateway.do
     */
    public static final String GATEWAY_URL = "https://openapi.alipay.com/gateway.do";
    /**支付宝分配给开发者的应用ID*/
    public static final String APP_ID = "your appid";
    /**支付宝公钥*/
    public static final String PUBLIC_KEY = "your ali public key";
    /**支付宝商户私钥*/
    public static final String PRIVATE_KEY = "your private key";

}

           

6、用到的两个实体类

package com.wr.project.entity;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.io.Serializable;
import java.math.BigDecimal;

/**
 * @Author: RainCity
 * @Date: 2022-02-26 13:50:00
 * @Desc: 支付基类
 */
public class AliPay implements Serializable {
    private static final long serialVersionUID = 2991507710246393025L;

    /** 支付方式 */
    private String payType;
    /** 支付回调地址 */
    private String notifyUrl;
    /**网页重定向通知 HTTP/HTTPS开头字符串*/
    private String returnUrl;
    /** 订单编号 */
    private String outTradeNo;
    /** 金额 */
    private BigDecimal totalAmount;
    /** 订单标题 */
    private String subject;
    /** 公共回传参数 */
    private String backParams;
    /**
     * 交易绝对时间
     * 支付宝格式:yyyy-MM-dd HH:mm:ss
     * 微信格式:YYYY-MM-DDTHH:mm:ss+TIMEZONE
     */
    private String timeExpire;
    /** 用户付款中途退出返回商户网站的地址 */
    private String quitUrl;
    /**
     * 支付授权码
     * 当面付场景传买家的付款码(25~30开头的长度为16~24位的数字,实际字符串长度以开发者获取的付款码长度为准)
     * 或者刷脸标识串(fp开头的35位字符串)
     */
    private String authCode;

    /** 此处省略setter、getter、toString方法,切勿忘记,不建议使用Lombok*/
    /** 此处省略setter、getter、toString方法,切勿忘记,不建议使用Lombok*/
    /** 此处省略setter、getter、toString方法,切勿忘记,不建议使用Lombok*/
    
}

           
package com.wr.project.entity.dto;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.io.Serializable;
import java.math.BigDecimal;

/**
 * @Author: RainCity
 * @Date: 2022-02-26 17:20:34
 * @Desc: 接收前端传过来的参数
 */
public class PayDTO implements Serializable {
    private static final long serialVersionUID = -7610591285294877627L;

    /** 支付方式 */
    private String payType;
    /** 金额 */
    private BigDecimal totalAmount;

    /** 此处省略setter、getter、toString方法,切勿忘记,不建议使用Lombok*/
    /** 此处省略setter、getter、toString方法,切勿忘记,不建议使用Lombok*/
    /** 此处省略setter、getter、toString方法,切勿忘记,不建议使用Lombok*/
}

           

7、调用支付宝支付的工具类

package com.wr.common.util;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.wr.common.config.AliConfig;
import com.wr.common.constant.PayConstants;
import com.wr.project.entity.AliPay;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: RainCity
 * @Date: 2022-02-26 13:42:18
 * @Desc: 支付宝支付工具类
 */
public class AliPayUtils {
    private static final Logger log = LoggerFactory.getLogger(AliPayUtils.class);

    /**销售产品码,商家和支付宝签约的产品码(APP)*/
    private static final String PRODUCT_CODE_APP = "QUICK_MSECURITY_PAY";
    /**销售产品码,商家和支付宝签约的产品码(WAP)*/
    private static final String PRODUCT_CODE_WAP = "QUICK_WAP_WAY";
    /**销售产品码,商家和支付宝签约的产品码(PAGE)*/
    private static final String PRODUCT_CODE_PAGE = "FAST_INSTANT_TRADE_PAY";
    /**销售产品码,商家和支付宝签约的产品码(当面付快捷版)*/
    private static final String PRODUCT_CODE_OFFLINE = "OFFLINE_PAYMENT";
    /**销售产品码,商家和支付宝签约的产品码(默认当面付)*/
    private static final String PRODUCT_CODE_FACE_TO_FACE = "FACE_TO_FACE_PAYMENT";

    /**
     * 请求参数封装
     * @param aliPay
     *  outTradeNo 订单号
     *  totalAmount 总金额(单位分)
     *  payTitle 订单标题
     *  timeExpire 过期时间
     *  backParams 公共回传参数
     * @param productCode 销售产品码
     * @return bizContent
     */
    private static JSONObject packageBizContent(AliPay aliPay, String productCode){
        JSONObject bizContent = new JSONObject();
        //商户网站唯一订单号
        bizContent.put("out_trade_no", aliPay.getOutTradeNo());
        //订单总金额,单位为元,精确到小数点后两位
        BigDecimal amount = aliPay.getTotalAmount().setScale(2, RoundingMode.HALF_UP);
        bizContent.put("total_amount", amount.toString());
        //订单标题
        bizContent.put("subject", aliPay.getSubject());
        //销售产品码,商家和支付宝签约的产品码
        bizContent.put("product_code", productCode);
        //绝对超时时间,格式为yyyy-MM-dd HH:mm:ss
        if(StringUtils.isNotEmpty(aliPay.getTimeExpire())){
            bizContent.put("time_expire", aliPay.getTimeExpire());
        }
        // 公用回传参数,按需传入
        if(StringUtils.isNotEmpty(aliPay.getBackParams())){
            bizContent.put("passback_params", aliPay.getBackParams());
        }

        return bizContent;
    }

    /**
     * 支付宝APP支付
     * @param aliPay 支付参数
     * @return 支付结果 https://opendocs.alipay.com/apis/028xq9
     * @throws AlipayApiException
     */
    public static AlipayTradeAppPayResponse tradeAppPay(AliPay aliPay) throws AlipayApiException {
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(
                AliConfig.GATEWAY_URL, AliConfig.APP_ID, AliConfig.PRIVATE_KEY, PayConstants.FORMAT_JSON,
                PayConstants.UTF_8, AliConfig.PUBLIC_KEY, PayConstants.SIGN_RSA2);

        //创建API对应的request类
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //设置回调地址
        request.setNotifyUrl(aliPay.getNotifyUrl());

        JSONObject bizContent = packageBizContent(aliPay, PRODUCT_CODE_APP);

        request.setBizContent(bizContent.toString());

        AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
        log.info("TradeAppPayResponse:{}",response);
        return  response;
    }

    /**
     * 支付宝手机网站支付
     * @param aliPay 支付参数
     * @return 支付结果 https://opendocs.alipay.com/apis/api_1/alipay.trade.wap.pay
     * @throws AlipayApiException
     */
    public static AlipayTradeWapPayResponse tradeWapPay(AliPay aliPay) throws AlipayApiException {
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(
                AliConfig.GATEWAY_URL, AliConfig.APP_ID, AliConfig.PRIVATE_KEY, PayConstants.FORMAT_JSON,
                PayConstants.UTF_8, AliConfig.PUBLIC_KEY, PayConstants.SIGN_RSA2);

        //创建API对应的request类
        AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
        //设置回调地址
        request.setNotifyUrl(aliPay.getNotifyUrl());
        //网页重定向通知 HTTP/HTTPS开头字符串
        request.setReturnUrl(aliPay.getReturnUrl());

        JSONObject bizContent = packageBizContent(aliPay, PRODUCT_CODE_WAP);
        //用户付款中途退出返回商户网站的地址
        bizContent.put("quit_url", aliPay.getQuitUrl());

        request.setBizContent(bizContent.toString());

        AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
        log.info("TradeWapPayResponse:{}",response);
        return  response;
    }

    /**
     * 支付宝电脑网站支付
     * @param aliPay 支付参数
     * @return 支付结果 https://opendocs.alipay.com/apis/api_1/alipay.trade.page.pay?scene=22
     * @throws AlipayApiException
     */
    public static AlipayTradePagePayResponse tradePagePay(AliPay aliPay) throws AlipayApiException {
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(
                AliConfig.GATEWAY_URL, AliConfig.APP_ID, AliConfig.PRIVATE_KEY, PayConstants.FORMAT_JSON,
                PayConstants.UTF_8, AliConfig.PUBLIC_KEY, PayConstants.SIGN_RSA2);

        //创建API对应的request类
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        //设置回调地址
        request.setNotifyUrl(aliPay.getNotifyUrl());
        //网页重定向通知 HTTP/HTTPS开头字符串
        request.setReturnUrl(aliPay.getReturnUrl());

        JSONObject bizContent = packageBizContent(aliPay, PRODUCT_CODE_PAGE);
        //PC扫码支付的方式
        //前置模式 0:订单码-简约前置模式,对应 iframe 宽度不能小于600px,高度不能小于300px;
        //        1:订单码-前置模式,对应iframe 宽度不能小于 300px,高度不能小于600px;
        //        3:订单码-迷你前置模式,对应 iframe 宽度不能小于 75px,高度不能小于75px;
        //        4:订单码-可定义宽度的嵌入式二维码,商户可根据需要设定二维码的大小
        //跳转模式 2:订单码-跳转模式
        bizContent.put("qr_pay_mode", "2");
        //商户自定义二维码宽度。qr_pay_mode=4时该参数有效
        //bizContent.put("qrcode_width", 100);

        request.setBizContent(bizContent.toString());

        AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
        log.info("TradePagePayResponse:{}",response);
        return  response;
    }

    /**
     * 支付宝手机扫码支付
     * @param aliPay 支付参数
     * @return 支付结果 https://opendocs.alipay.com/apis/api_1/alipay.trade.precreate?scene=19
     * @throws AlipayApiException
     */
    public static AlipayTradePrecreateResponse tradeQrCodePay(AliPay aliPay) throws AlipayApiException {
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(
                AliConfig.GATEWAY_URL, AliConfig.APP_ID, AliConfig.PRIVATE_KEY, PayConstants.FORMAT_JSON,
                PayConstants.UTF_8, AliConfig.PUBLIC_KEY, PayConstants.SIGN_RSA2);

        //创建API对应的request类
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        //设置回调地址
        request.setNotifyUrl(aliPay.getNotifyUrl());

        JSONObject bizContent = packageBizContent(aliPay, PRODUCT_CODE_FACE_TO_FACE);

        request.setBizContent(bizContent.toString());

        AlipayTradePrecreateResponse response = alipayClient.execute(request);
        log.info("TradePreCreateResponse:{}",response);
        return  response;
    }

    /**
     * 支付宝付款码支付
     * @param aliPay 支付参数
     * @return 支付结果 https://opendocs.alipay.com/apis/api_1/alipay.trade.pay?scene=32
     * @throws AlipayApiException
     */
    public static AlipayTradePayResponse tradeAuthCodePay(AliPay aliPay) throws AlipayApiException {
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(
                AliConfig.GATEWAY_URL, AliConfig.APP_ID, AliConfig.PRIVATE_KEY, PayConstants.FORMAT_JSON,
                PayConstants.UTF_8, AliConfig.PUBLIC_KEY, PayConstants.SIGN_RSA2);

        //创建API对应的request类
        AlipayTradePayRequest request = new AlipayTradePayRequest();
        //设置回调地址
        request.setNotifyUrl(aliPay.getNotifyUrl());

        JSONObject bizContent = packageBizContent(aliPay, PRODUCT_CODE_FACE_TO_FACE);
        //支付场景 bar_code:当面付条码支付场景;
        //        security_code:当面付刷脸支付场景,对应的auth_code为fp开头的刷脸标识串;
        bizContent.put("scene", "bar_code");
        //支付授权码 当面付场景传买家的付款码
        bizContent.put("auth_code", aliPay.getAuthCode());

        request.setBizContent(bizContent.toString());

        AlipayTradePayResponse response = alipayClient.execute(request);
        log.info("TradePayResponse:{}",response);
        return  response;
    }

    /**
     * 交易查询
     * @param outTradeNo 商户网站唯一订单号
     * @return 查询结果
     * @throws AlipayApiException
     */
    public static AlipayTradeQueryResponse tradeQuery(String outTradeNo) throws AlipayApiException {
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(
                AliConfig.GATEWAY_URL, AliConfig.APP_ID, AliConfig.PRIVATE_KEY, PayConstants.FORMAT_JSON,
                PayConstants.UTF_8, AliConfig.PUBLIC_KEY, PayConstants.SIGN_RSA2);

        //创建API对应的request类
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();

        JSONObject bizContent = new JSONObject();
        //商户网站唯一订单号
        bizContent.put("out_trade_no", outTradeNo);

        request.setBizContent(bizContent.toString());
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        log.info("TradeQueryResponse:{}",response);
        return response;
    }

    /**
     * 交易撤销
     * @param outTradeNo 户网站唯一订单号
     * @return retryFlag=是否需要重试(Y/N)
     *         action=本次撤销触发的交易动作,接口调用成功且交易存在时返回
     *              可能的返回值:
     *              close:交易未支付,触发关闭交易动作,无退款;
     *              refund:交易已支付,触发交易退款动作;
     *              未返回:未查询到交易,或接口调用失败;
     * @throws AlipayApiException
     */
    public static AlipayTradeCancelResponse tradeCancel(String outTradeNo) throws AlipayApiException {
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(
                AliConfig.GATEWAY_URL, AliConfig.APP_ID, AliConfig.PRIVATE_KEY, PayConstants.FORMAT_JSON,
                PayConstants.UTF_8, AliConfig.PUBLIC_KEY, PayConstants.SIGN_RSA2);

        //创建API对应的request类
        AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();

        JSONObject bizContent = new JSONObject();
        //商户网站唯一订单号
        bizContent.put("out_trade_no", outTradeNo);
        request.setBizContent(bizContent.toString());

        AlipayTradeCancelResponse response = alipayClient.execute(request);
        log.info("TradeCancelResponse:{}",response);
        return response;
    }

    /**
     * 用于交易创建后,用户在一定时间内未进行支付,可调用该接口直接将未付款的交易进行关闭
     * @param outTradeNo 商户网站唯一订单号
     * @return 状态码
     * @throws AlipayApiException
     */
    public static AlipayTradeCloseResponse tradeClose(String outTradeNo) throws AlipayApiException {
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(
                AliConfig.GATEWAY_URL, AliConfig.APP_ID, AliConfig.PRIVATE_KEY, PayConstants.FORMAT_JSON,
                PayConstants.UTF_8, AliConfig.PUBLIC_KEY, PayConstants.SIGN_RSA2);

        //创建API对应的request类
        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();

        JSONObject bizContent = new JSONObject();
        //商户网站唯一订单号
        bizContent.put("out_trade_no", outTradeNo);
        request.setBizContent(bizContent.toString());
        AlipayTradeCloseResponse response = alipayClient.execute(request);
        log.info("TradeCloseResponse:{}",response);
        return response;
    }

    /**
     * 设置过期时间
     * @param minute
     * @return
     */
    public static String aliTimeExpire(int minute){
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MINUTE,minute);
        SimpleDateFormat sdf = new SimpleDateFormat(PayConstants.YYYY_MM_DD_HH_MM_SS);
        return sdf.format(cal.getTime());
    }

    /**
     * 获取支付宝POST过来的反馈信息
     * @param request
     * @return
     */
    public static Map<String,String> getPostParams(HttpServletRequest request){
        Map<String,String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = 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);
        }
        return params;
    }
}

           

8、controller

package com.wr.project.web;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.wr.common.AjaxResult;
import com.wr.common.config.AliConfig;
import com.wr.common.constant.AliConstants;
import com.wr.common.constant.PayConstants;
import com.wr.common.util.AliPayUtils;
import com.wr.project.entity.dto.PayDTO;
import com.wr.project.service.AliPayService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * @Author: RainCity
 * @Date: 2022-02-18 13:04:52
 * @Desc: 
 */
@RestController
@RequestMapping("/api/ali")
public class AliController {
    private static final Logger log = LoggerFactory.getLogger(AliController.class);

    @Autowired
    private List<AliPayService> aliPayServices;

    @PostMapping("/pay")
    public AjaxResult pay(PayDTO payDTO) {
        log.info("********** 支付宝支付==> *************");
        AliPayService aliPayService = aliPayServices.stream()
                .filter(service -> service.support(payDTO.getPayType()))
                .findAny()
                .orElseThrow(() -> new RuntimeException("支付模式:"+payDTO.getPayType()+"不支持"));
        return aliPayService.execute(payDTO);
    }

    @PostMapping("/notify")
    public String notify(HttpServletRequest request) {
        log.info("********** 支付宝支付回调执行 *************");
        //获取支付宝POST过来反馈信息
        Map<String,String> params = AliPayUtils.getPostParams(request);
        log.info("params:{}",params);
        String backParams = params.get("passback_params");
        log.info("backParams:{}",backParams);
        try {
            //切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。
            boolean flag = AlipaySignature.rsaCheckV1(params, AliConfig.PUBLIC_KEY,PayConstants.UTF_8, PayConstants.SIGN_RSA2);
            if(!flag){
                log.error("支付宝回调签名认证失败");
                return AliConstants.ALI_FAILED_RETURN;
            }
            String tradeStatus= params.get("trade_status");
            log.info("支付宝回调签名认证成功,tradeStatus={}",tradeStatus);
            if(!AliConstants.TRADE_SUCCESS.equals(tradeStatus)){
                return AliConstants.ALI_FAILED_RETURN;
            }
            //自己的业务逻辑......

            return AliConstants.ALI_SUCCESS_RETURN;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            log.error("支付宝回调失败,code:{},msg:{}",e.getErrCode(),e.getErrMsg());
            return AliConstants.ALI_FAILED_RETURN;
        }
    }

    @GetMapping("/ali_return")
    public void aliSuccess(HttpServletResponse response) throws IOException {
        log.info("********** 支付宝进入成功页面 *************");
        //进入页面的地址
        response.sendRedirect(PayConstants.SERVER_URL + "/ali_success");
    }

    @GetMapping("/ali_quit")
    public void aliCancel(HttpServletResponse response) throws IOException {
        log.info("********** 支付宝进入取消页面 *************");
        response.sendRedirect(PayConstants.SERVER_URL + "/ali_cancel");
    }

  
}

           

9、业务处理service

一个service多个Impl,impl包中对应枚举类 AliEnum

策略模式实现支付宝支付前言一、准备二、主要代码三、测试结果
package com.wr.project.service;

import com.wr.common.AjaxResult;
import com.wr.project.entity.dto.PayDTO;

/**
 * @Author: RainCity
 * @Date: 2022-02-26 16:36:20
 * @Desc: 支付宝支付业务层
 */
public interface AliPayService {

    /**
     * 判断是否支持此支付方式
     * @param payType
     * @return
     */
    boolean support(String payType);

    /**
     * 要执行的动作
     * @param payDTO
     * @return
     */
    AjaxResult execute(PayDTO payDTO);

}

           

以手机网站(WAP)为例

package com.wr.project.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.wr.common.AjaxResult;
import com.wr.common.constant.AliConstants;
import com.wr.common.enums.AliEnum;
import com.wr.common.util.AliPayUtils;
import com.wr.project.entity.AliPay;
import com.wr.project.entity.dto.PayDTO;
import com.wr.project.service.AliPayService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * @Author: RainCity
 * @Date: 2022-02-26 16:52:59
 * @Desc: 支付宝WAP支付业务逻辑处理层
 */
@Service
public class AliWapPayServiceImpl implements AliPayService {
    private static final Logger log = LoggerFactory.getLogger(AliWapPayServiceImpl.class);

    @Override
    public boolean support(String payType) {

        return AliEnum.WAP.getValue().equals(payType);
    }

    @Override
    public AjaxResult execute(PayDTO payDTO) {
        AliPay aliPay = new AliPay();
        aliPay.setPayType(payDTO.getPayType());
        aliPay.setNotifyUrl(AliConstants.NOTIFY_URL);
        aliPay.setReturnUrl(AliConstants.RETURN_URL);
        aliPay.setQuitUrl(AliConstants.QUIT_URL);
        aliPay.setOutTradeNo(String.valueOf(System.currentTimeMillis()));
        aliPay.setTotalAmount(payDTO.getTotalAmount());
        aliPay.setSubject("支付测试");
        //过期时间,设置为5分钟后
        aliPay.setTimeExpire(AliPayUtils.aliTimeExpire(5));
        //回传参数
        // 注:长度为512,超过了就换其他的方式吧,如redis
        //language=JSON
        String testStr = "{\"payType\": \""+payDTO.getPayType()+"\",\"userName\": \"测试一下\",\"userPhone\": \"15266668888\"}";
        aliPay.setBackParams(testStr);
        try {
            AlipayTradeWapPayResponse response = AliPayUtils.tradeWapPay(aliPay);
            if(response.isSuccess()){
                log.info("支付调用成功");
                //支付调用成功,将支付宝返回的form表单返给前端
                JSONObject data = new JSONObject();
                data.put("outTradeNo",response.getOutTradeNo());
                data.put("formResult",response.getBody());
                return AjaxResult.success(data);
            }
            log.error("支付调用失败,{},{}",response.getMsg(),response.getSubMsg());
            return AjaxResult.error("支付调用失败!");
        } catch (AlipayApiException e) {
            log.error("支付调用失败,{},{}",e.getErrCode(),e.getErrMsg());
            return AjaxResult.error("支付调用失败!");
        }
    }

}
           

注:代码中AjaxResult类只是一个用于数据返回的类,这里就不贴出来了 ):

三、测试结果

没有写前端页面,所以就用Api工具测了一下,可以看到已经可以调起支付了,后续放到服务器上测一下回调就结束了,嘻嘻~~~

策略模式实现支付宝支付前言一、准备二、主要代码三、测试结果

- -THE END- -

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持!!!