SpringBoot 集成支付宝的各种应用场景

时间:2021-03-06 01:06:34

SpringBoot 集成支付宝的各种应用场景

Spring Boot是一个非常流行的Java框架,它提供了一种快速、简便的方式来开发基于Java的Web应用程序。支付宝是中国最大的第三方支付平台,它提供了丰富的API,支持多种支付方式。在本篇博客中,我将介绍如何使用Spring Boot集成支付宝支付,包括以下几个场景:

  • 手机网站支付
  • 电脑网站支付
  • 移动支付
  • 扫码支付
  • APP支付

在开始之前,您需要先在 支付宝开放平台 注册一个支付宝账号,并且完成开发者认证,获取到支付宝开放平台的APPID、商户私钥、支付宝公钥等信息。

一. 手机网站支付

手机网站支付是指在手机浏览器中完成支付的一种方式。下面是集成步骤:

1.引入支付宝SDK依赖

在pom.xml文件中添加以下依赖:

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

2.配置支付宝信息

在SpringBoot的配置文件(application.yml或application.properties)中,添加支付宝的配置参数,例如:

alipay:
  alipayPublicKey: ALIPAY_PUBLIC_KEY
  appId: YOUR_APP_ID
  gateway: https://openapi.alipay.com/gateway.do
  appPrivateKey: YOUR_PRIVATE_KEY

alipay.alipayPublicKey=ALIPAY_PUBLIC_KEY
alipay.appId=YOUR_APP_ID
alipay.gateway=https://openapi.alipay.com/gateway.do
alipay.appPrivateKey=YOUR_PRIVATE_KEY

3.编写支付请求接口

@RestController
public class PayController {

    @Value("${alipay.appId}")
    private String appId;

    @Value("${alipay.gateway}")
    private String gateway;

    @Value("${alipay.appPrivateKey}")
    private String appPrivateKey;

    @Value("${alipay.alipayPublicKey}")
    private String alipayPublicKey;

    @RequestMapping("/pay")
    public String pay(HttpServletRequest request) throws AlipayApiException {
        // 实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient(gateway, appId, appPrivateKey, "json", "utf-8", alipayPublicKey, "RSA2");
        // 实例化请求对象
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
        // 设置回调地址
        alipayRequest.setReturnUrl(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/return_url");
        alipayRequest.setNotifyUrl(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/notify_url");
        // 设置订单信息
        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setOutTradeNo("20150320010101001");
        model.setSubject("Iphone6 16G");
        model.setTotalAmount("0.01");
        model.setBody("Iphone6 16G");
        model.setTimeoutExpress("30m");
        model.setProductCode("QUICK_WAP_WAY");
        alipayRequest.setBizModel(model);
        // 调用SDK生成表单
        String form = alipayClient.pageExecute(alipayRequest).getBody();
        return form;
    }

    @RequestMapping("/return_url")
    public String returnUrl(HttpServletRequest request) throws AlipayApiException {
        // 获取支付宝GET过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = iter.next();
            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] + ",";
            }
            // 解码
            params.put(name, URLDecoder.decode(valueStr, "UTF-8"));
        }
        // 验证签名
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8", "RSA2");
        if (signVerified) {
            return "success";
        } else {
            return "fail";
        }
    }

    @RequestMapping("/notify_url")
    public String notifyUrl(HttpServletRequest request) throws AlipayApiException {
        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = iter.next();
            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] + ",";
            }
            // 解码
            params.put(name, URLDecoder.decode(valueStr, "UTF-8"));
        }
        // 验证签名
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8", "RSA2");
        if (signVerified) {
            // 商户订单号
            String outTradeNo = params.get("out_trade_no");
            // 支付宝交易号
            String tradeNo = params.get("trade_no");
            // 交易状态
            String tradeStatus = params.get("trade_status");
            if (tradeStatus.equals("TRADE_SUCCESS")) {
                // TODO: 处理业务逻辑
                return "success";
            }
        }
        return "fail";
    }
}

二. 电脑网站支付

电脑网站支付是指在电脑浏览器中完成支付的一种方式。下面是集成步骤:

1.引入支付宝SDK依赖

在pom.xml文件中添加以下依赖:

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

2.配置支付宝信息

在SpringBoot的配置文件(application.yml或application.properties)中,添加支付宝的配置参数,例如:

alipay:
  alipayPublicKey: ALIPAY_PUBLIC_KEY
  appId: YOUR_APP_ID
  gateway: https://openapi.alipay.com/gateway.do
  appPrivateKey: YOUR_PRIVATE_KEY

alipay.alipayPublicKey=ALIPAY_PUBLIC_KEY
alipay.appId=YOUR_APP_ID
alipay.gateway=https://openapi.alipay.com/gateway.do
alipay.appPrivateKey=YOUR_PRIVATE_KEY

3.编写支付请求接口

@RestController
public class PayController {

    @Value("${alipay.appId}")
    private String appId;

    @Value("${alipay.gateway}")
    private String gateway;

    @Value("${alipay.appPrivateKey}")
    private String appPrivateKey;

    @Value("${alipay.alipayPublicKey}")
    private String alipayPublicKey;

    @RequestMapping("/pay")
    public String pay(HttpServletRequest request) throws AlipayApiException {
        // 实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient(gateway, appId, appPrivateKey, "json", "utf-8", alipayPublicKey, "RSA2");
        // 实例化请求
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        // 设置异步通知地址
        alipayRequest.setNotifyUrl("http://localhost:8080/notify_url");
        // 设置同步通知地址
        alipayRequest.setReturnUrl("http://localhost:8080/return_url");
        // 设置订单号
        String outTradeNo = "20220326112000001";
        // 设置订单总金额
        String totalAmount = "100.00";
        // 设置订单标题
        String subject = "测试电脑网站支付";
        // 组装请求参数
        AlipayTradePagePayModel model = new AlipayTradePagePayModel();
        model.setOutTradeNo(outTradeNo);
        model.setTotalAmount(totalAmount);
        model.setSubject(subject);
        model.setBody("测试电脑网站支付");
        model.setProductCode("FAST_INSTANT_TRADE_PAY");
        alipayRequest.setBizModel(model);
        // 请求支付宝进行支付
        String form = alipayClient.pageExecute(alipayRequest).getBody();
        return form;
    }

    @RequestMapping("/return_url")
    public String returnUrl(HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException {
        // 获取支付宝GET过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = iter.next();
            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] + ",";
            }
            // 解码
            params.put(name, URLDecoder.decode(valueStr, "UTF-8"));
        }
        // 验证签名
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8", "RSA2");
        if (signVerified) {
            // 获取订单号
            String outTradeNo = params.get("out_trade_no");
            // 获取支付宝交易号
            String tradeNo = params.get("trade_no");
            // 获取交易状态
            String tradeStatus = params.get("trade_status");
            if (tradeStatus.equals("TRADE_SUCCESS")) {
                // TODO: 处理业务逻辑
                return "success";
            }
        }
        return "fail";
    }

    @RequestMapping("/notify_url")
    public String notifyUrl(HttpServletRequest request) throws AlipayApiException {
        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = iter.next();
            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] + ",";
            }
            // 解码
            params.put(name, URLDecoder.decode(valueStr, "UTF-8"));
        }
        // 验证签名
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8", "RSA2");
        if (signVerified) {
            // 获取订单号
            String outTradeNo = params.get("out_trade_no");
            // 获取支付宝交易号
            String tradeNo = params.get("trade_no");
            // 获取交易状态
            String tradeStatus = params.get("trade_status");
            if (tradeStatus.equals("TRADE_SUCCESS")) {
                // TODO: 处理业务逻辑
                return "success";
            }
        }
        return "fail";
    }
}

在上面的代码中,我们首先定义了一个AlipayClient对象,用来创建支付宝请求对象和发送请求。然后,我们定义了一个方法,用于生成电脑网站支付的表单,该方法接收订单号、订单总金额和订单标题等参数,并返回生成的表单字符串。在该方法中,我们首先创建了一个AlipayTradePagePayRequest对象,设置了异步通知地址和同步通知地址等参数,然后使用AlipayTradePagePayModel对象组装了请求参数,最后使用alipayClient.pageExecute()方法发起支付宝支付请求,并将返回的表单字符串返回给调用方。

returnUrl方法中,我们首先获取支付宝返回的参数,并验证签名是否正确。如果签名验证通过,我们再从返回参数中获取订单号、支付宝交易号和交易状态等信息,根据交易状态进行业务逻辑处理。如果交易状态为TRADE_SUCCESS,表示交易成功,我们可以在这里处理相关业务逻辑,例如更新订单状态等操作。

notifyUrl方法中,与returnUrl方法类似,我们也是首先获取支付宝返回的参数,并验证签名是否正确。如果签名验证通过,我们再从返回参数中获取订单号、支付宝交易号和交易状态等信息,根据交易状态进行业务逻辑处理。与returnUrl方法不同的是,该方法是异步通知接口,支付宝服务器会向该接口发送POST请求,通知支付结果,我们需要在该方法中及时处理通知,并返回success字符串表示已成功接收到通知。

三. 移动支付

除了电脑网站支付,支付宝还提供了移动支付的功能,让用户可以在手机端完成支付。

1.注册支付宝开发者账号并创建应用

在使用支付宝移动支付之前,我们需要注册一个支付宝开发者账号,并在开发者中心创建一个应用。具体步骤如下:

1.1. 打开支付宝开发者中心网址: https://openhome.alipay.com/platform/appManage.htm

1.2. 登录支付宝开发者账号,如果还没有账号,可以先注册一个。

1.3. 点击“创建应用”按钮,进入创建应用页面。

1.4. 填写应用名称和应用类型,选择移动应用,并提交创建。

1.5. 创建成功后,会自动生成AppID、私钥等信息。我们需要将这些信息保存下来,后面会用到。

2.引入支付宝SDK依赖

在项目的pom.xml文件中添加支付宝SDK依赖,具体代码如下:

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

3.配置支付宝参数

在SpringBoot的配置文件(application.yml或application.properties)中,添加支付宝的配置参数,例如:

ali:
  pay:
    app-id: YOUR_APP_ID
    notify-url: http://www.example.com/notify
    private-key: YOUR_PRIVATE_KEY
    public-key: ALIPAY_PUBLIC_KEY

ali.pay.app-id=YOUR_APP_ID
ali.pay.private-key=YOUR_PRIVATE_KEY
ali.pay.public-key=ALIPAY_PUBLIC_KEY
ali.pay.notify-url=http://www.example.com/notify

其中,ali.pay.app-id是在支付宝开发者中心创建应用时生成的AppID;ali.pay.private-key是我们自己生成的私钥,需要在支付宝开发者中心上传,同时也需要保存在本地;ali.pay.public-key是支付宝公钥,也需要在支付宝开发者中心获取;ali.pay.notify-url是支付成功后,支付宝服务器将支付结果通知给商户服务器的回调接口地址。

4.编写支付接口

在SpringBoot中,我们可以使用@Controller和@ResponseBody注解来定义一个接口,用于处理支付请求。具体代码如下:

@Controller
public class PayController {

    @Autowired
    private AliPayConfig aliPayConfig;

    @PostMapping("/pay")
    @ResponseBody
    public String pay(@RequestParam("outTradeNo") String outTradeNo,
                      @RequestParam("totalAmount") String totalAmount,
                      @RequestParam("subject") String subject) throws AlipayApiException {
        // 创建 AlipayClient 对象,用于调用支付宝接口
        AlipayClient alipayClient = new DefaultAlipayClient(
                aliPayConfig.getServerUrl(),
                aliPayConfig.getAppId(),
                aliPayConfig.getPrivateKey(),
                "json",
                "utf-8",
                aliPayConfig.getPublicKey(),
                "RSA2");
        // 创建 AlipayTradeAppPayRequest 对象,用于设置支付参数
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        // 设置异步回调地址
        request.setNotifyUrl(aliPayConfig.getNotifyUrl());
	    // 设置订单信息
	    AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
	    model.setOutTradeNo(outTradeNo);
	    model.setTotalAmount(totalAmount);
	    model.setSubject(subject);
	    model.setProductCode("QUICK_MSECURITY_PAY");
	    request.setBizModel(model);
	    // 调用支付接口,获取支付参数
	    AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
	    // 返回客户端支付参数
	    return response.getBody();
	}
}

在代码中,我们通过AlipayClientAlipayTradeAppPayRequest对象来设置支付参数,然后调用支付宝的接口获取支付参数。最后将支付参数返回给客户端,客户端就可以使用支付宝SDK调起支付宝APP进行支付了。

5. 处理支付结果回调

当客户端支付成功后,支付宝服务器会将支付结果通知给商户服务器的回调接口地址,我们需要编写一个接口来处理支付结果回调。具体代码如下:

@Controller
public class NotifyController {

    @PostMapping("/notify")
    @ResponseBody
    public String notify(HttpServletRequest request) throws AlipayApiException {
        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<>();
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String paramName = parameterNames.nextElement();
            String paramValue = request.getParameter(paramName);
            params.put(paramName, paramValue);
        }
        // 验证签名
        boolean signVerified = AlipaySignature.rsaCheckV1(params,
                aliPayConfig.getPublicKey(),
                "utf-8",
                "RSA2");
        if (signVerified) {
            // 处理支付结果
            String tradeStatus = params.get("trade_status");
            String outTradeNo = params.get("out_trade_no");
            String tradeNo = params.get("trade_no");
            String totalAmount = params.get("total_amount");
            // TODO: 处理支付结果
            return "success";
        } else {
            return "failure";
        }
    }
}

在代码中,我们首先获取支付宝POST过来的反馈信息,然后通过AlipaySignature.rsaCheckV1()方法验证签名,确保支付结果是合法的。最后,我们可以根据支付结果进行相应的业务处理,例如更新订单状态、发送邮件通知等。

6.发起支付请求

客户端在发起支付请求时,需要调用我们编写的支付接口,并将支付参数传递给支付宝SDK。具体代码如下:

public class PayActivity extends AppCompatActivity {

    private static final String TAG = "PayActivity";

    private static final String SERVER_URL = "http://www.example.com/pay";

    private static final int SDK_PAY_FLAG = 1;

    private Button mBtnPay;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pay);
        mBtnPay = findViewById(R.id.btn_pay);
        mBtnPay.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                pay();
            }
        });
    }

    private void pay() {
        String outTradeNo = UUID.randomUUID().toString();
        String totalAmount = "0.01";
        String subject = "测试商品";
        OkHttpClient client = new OkHttpClient();
        RequestBody requestBody = new FormBody.Builder()
                .add("out_trade_no", outTradeNo)
                .add("total_amount", totalAmount)
                .add("subject", subject)
                .build();
        Request request = new Request.Builder()
                .url(SERVER_URL)
                .post(requestBody)
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e(TAG, "请求支付接口失败", e);
                showToast("请求支付接口失败");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    // 获取支付参数成功,打印日志,并将支付参数传递给支付宝SDK
                    String body = response.body().string();
                    Log.d(TAG, "获取支付参数成功: " + body);
                    PayTask task = new PayTask(PayActivity.this);
                    Map<String, String> result = task.payV2(body, true);
                    // 将支付结果通过 Handler 对象传递回主线程
                    Message msg = new Message();
                    msg.what = SDK_PAY_FLAG;
                    msg.obj = result;
                    mHandler.sendMessage(msg);
                } else {
                    // 获取支付参数失败,打印日志,并提示用户
                    Log.e(TAG, "获取支付参数失败: " + response.code());
                    showToast("获取支付参数失败");
                }
            }
        });
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case SDK_PAY_FLAG:
                    Map<String, String> result = (Map<String, String>) msg.obj;
                    String resultStatus = result.get("resultStatus");
                    if (TextUtils.equals(resultStatus, "9000")) {
                        showToast("支付成功");
                    } else if (TextUtils.equals(resultStatus, "6001")) {
                        showToast("支付取消");
                    } else {
                        showToast("支付失败");
                    }
                    break;
            }
        }
    };

    private void showToast(String message) {
        runOnUiThread(() -> Toast.makeText(PayActivity.this, message, Toast.LENGTH_SHORT).show());
    }
}

在代码中,我们首先调用我们编写的支付接口获取支付参数,然后将支付参数传递给支付宝SDK,让SDK调起支付宝APP进行支付。支付结果会通过SDK_PAY_FLAG标志和Handler对象返回到主线程,我们可以在Handler对象中根据支付结果进行相应的提示。

至此,我们已经成功集成了支付宝移动支付。在实际开发中,还需要考虑异常处理、订单状态同步、订单查询等问题。

四. 扫码支付

除了电脑网站支付和移动支付,支付宝还提供了扫码支付的功能,让用户可以在商户店铺扫描二维码完成支付。

1.注册支付宝开发者账号

首先,我们需要注册一个支付宝开发者账号。在注册完成后,我们需要进入开发者中心,在“应用管理”中创建一个新的应用,选择“PC网站支付”作为接口类型。

在创建完应用后,我们需要获取一些必要的配置信息,包括应用ID、商户私钥、支付宝公钥、异步通知地址、同步跳转地址等。这些配置信息将在后面的代码中使用。

2.引入支付宝SDK依赖

在我们的Spring Boot项目中,我们需要引入支付宝SDK。支付宝SDK提供了一系列用于调用支付宝接口的Java类和方法。我们可以使用Maven或Gradle来管理我们的项目依赖。下面是一个Maven的依赖配置示例:

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

3.配置支付宝信息

在我们的Spring Boot项目中,我们需要在配置文件中添加支付宝信息。下面是一个示例配置文件:

# 支付宝网关
alipay.gatewayUrl=https://openapi.alipay.com/gateway.do
# 应用ID
alipay.appId=xxxxxxxxxxxx
# 商户私钥
alipay.privateKey=xxxxxxxxxxxx
# 支付宝公钥
alipay.alipayPublicKey=xxxxxxxxxxxx
# 异步通知地址
alipay.notifyUrl=http://localhost:8080/notify
# 同步跳转地址
alipay.returnUrl=http://localhost:8080/return

alipay:
  alipayPublicKey: xxxxxxxxxxxx
  appId: xxxxxxxxxxxx
  gatewayUrl: https://openapi.alipay.com/gateway.do
  notifyUrl: http://localhost:8080/notify
  privateKey: xxxxxxxxxxxx
  returnUrl: http://localhost:8080/return

4.实现支付接口

在我们的Spring Boot项目中,我们需要实现一个支付接口,用于生成支付二维码并返回给前端。下面是一个示例代码:

@RestController
public class AlipayController {

    @Resource
    private AlipayConfig alipayConfig;

    /**
     * 支付宝扫码支付
     */
    @GetMapping("/scan/pay")
    public String scanPay(String orderNo, String amount, String subject) throws AlipayApiException {
        // 创建AlipayClient对象
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getServerUrl(), alipayConfig.getAppId(), alipayConfig.getPrivateKey(), "json", "UTF-8", alipayConfig.getAlipayPublicKey(), "RSA2");
        // 创建AlipayTradePrecreateRequest对象
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        // 设置异步通知地址
        request.setNotifyUrl("异步通知地址");
        // 设置订单信息
        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        model.setOutTradeNo(orderNo);
        model.setTotalAmount(amount);
        model.setSubject(subject);
        request.setBizModel(model);
        // 发起支付请求
        AlipayTradePrecreateResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            // 返回二维码链接给前端
            return response.getQrCode();
        } else {
            // 处理支付失败的情况
            throw new AlipayApiException(response.getMsg());
        }
    }

    /**
     * 处理支付结果
     */
    @PostMapping("/notify")
    public String notify(HttpServletRequest request) throws AlipayApiException {
        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            StringBuilder valueStr = new StringBuilder();
            for (int i = 0; i < values.length; i++) {
                valueStr.append((i == values.length - 1) ? values[i] : values[i] + ",");
            }
            params.put(name, valueStr.toString());
        }
        // 验证签名
        boolean verifyResult = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), "UTF-8", "RSA2");
        if (verifyResult) {
            // 处理支付成功的情况
            String orderNo = params.get("out_trade_no");
            String tradeNo = params.get("trade_no");
            String amount = params.get("total_amount");
            // TODO: 处理订单状态
            return "success";
        } else {
            // 处理验签失败的情况
            return "failure";
        }
    }
}

在上面的代码中,我们定义了一个AlipayController,其中包含了两个接口:scanPaynotify

scanPay接口中,我们首先创建了一个AlipayClient对象,然后创建了一个AlipayTradePrecreateRequest对象,并设置了异步通知地址和订单信息。最后,我们通过AlipayClient对象的execute方法发送支付请求,获取二维码链接,并将其返回给前端。

notify接口中,我们首先从request中获取支付结果参数,并使用AlipaySignature.rsaCheckV1方法验证签名。如果验签成功,则处理支付成功的情况,否则处理验签失败的情况。在处理支付成功的情况时,我们可以根据订单号、交易号和金额等参数来更新订单状态。

5. 测试支付接口

最后,我们可以使用Postman等工具来测试我们的支付接口。在测试时,我们需要传入订单号、订单金额和订单标题等参数,然后可以获取到支付宝生成的二维码,并使用支付宝App或支付宝扫码枪扫描二维码来完成支付。

至此,我们已经完成了在Spring Boot中集成支付宝扫码支付的过程。如果您在实际使用中遇到了问题,可以查看支付宝SDK文档或咨询支付宝开发者支持。

五. APP支付

除了移动支付和扫码支付,支付宝还提供了APP支付的功能,让开发者可以在APP中集成支付宝支付。

1.引入支付宝SDK依赖

在pom.xml文件中添加以下依赖:

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

2.配置支付宝信息

在application.properties文件中添加支付宝相关配置信息,包括应用ID、私钥、公钥等:

# 支付宝配置信息
alipay.app-id=应用ID
alipay.private-key=应用私钥
alipay.public-key=支付宝公钥
alipay.server-url=https://openapi.alipay.com/gateway.do

alipay:
  app-id: 应用ID
  private-key: 应用私钥
  public-key: 支付宝公钥
  server-url: https://openapi.alipay.com/gateway.do

其中,应用ID可以在支付宝开放平台中创建应用后获得,私钥和公钥需要在创建应用时生成。

3.创建支付接口

在Spring Boot应用程序中创建一个控制器类,命名为AlipayController,用于处理支付相关的请求:

@RestController
@RequestMapping("/alipay")
public class AlipayController {

    @Autowired
    private AlipayConfig alipayConfig;

    /**
     * 处理支付请求
     */
    @PostMapping("/app-pay")
    public String appPay(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException, IOException {
        // 实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getServerUrl(),
                alipayConfig.getAppId(),
                alipayConfig.getPrivateKey(),
                "json",
                "UTF-8",
                alipayConfig.getAlipayPublicKey(),
                "RSA2");
        // 实例化请求对象
        AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest();
        // 设置异步通知地址
        alipayRequest.setNotifyUrl("http://localhost:8080/alipay/notify");
        // 设置订单信息
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setOutTradeNo("订单号");
        model.setSubject("订单标题");
        model.setBody("订单描述");
        model.setTotalAmount("订单金额");
        alipayRequest.setBizModel(model);
        // 请求支付宝生成支付结果
        String form = alipayClient.sdkExecute(alipayRequest).getBody();
        // 将支付结果返回给客户端
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write(form);
        response.getWriter().flush();
        response.getWriter().close();
        return null;
    }

    /**
     * 处理支付结果
     */
    @PostMapping("/notify")
    public String notify(HttpServletRequest request) throws AlipayApiException {
        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            StringBuilder valueStr = new StringBuilder();
            for (int i = 0; i < values.length; i++) {
                valueStr.append((i == values.length - 1) ? values[i] : values[i] + ",");
            }
            params.put(name, valueStr.toString());
        }
        // 验证签名
        boolean verifyResult = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), "UTF-8", "RSA2");
        if (verifyResult) {
            // 处理支付结果
            String tradeStatus = params.get("trade_status");
            if ("TRADE_SUCCESS".equals(tradeStatus)) {
                String outTradeNo = params.get("out_trade_no");
                String tradeNo = params.get("trade_no");
                // TODO: 处理支付结果
            }
            return "success";
        } else {
            return "failure";
        }
    }
}

在支付请求处理方法appPay()中,我们创建了一个AlipayTradeAppPayRequest对象,设置了异步通知地址、订单信息等参数,然后通过AlipayClient对象调用sdkExecute()方法向支付宝发起支付请求,并将支付结果以HTML形式返回给客户端。

在支付结果处理方法notify()中,我们获取支付宝POST过来的反馈信息,使用AlipaySignature类的rsaCheckV1()方法验证签名,然后根据支付结果处理业务逻辑,最后返回一个success字符串表示处理成功,或者返回failure字符串表示处理失败。

4.调用支付接口

在客户端调用支付接口时,需要向服务端发送支付请求,并获取服务端返回的支付结果。具体代码如下:

public class AlipayClient {
    
    private static final String APP_PAY_URL = "http://localhost:8080/alipay/app-pay";

    /**
     * 调用支付接口
     */
    public String pay() {
        OkHttpClient client = new OkHttpClient();
        RequestBody formBody = new FormBody.Builder()
                .build();
        Request request = new Request.Builder()
                .url(APP_PAY_URL)
                .post(formBody)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            return response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

在客户端的AlipayClient类中,我们通过OkHttpClient对象向服务端发送一个POST请求,获取服务端返回的支付结果,最后将支付结果返回给调用方。

以上就是集成支付宝APP支付的基本步骤。需要注意的是,在使用支付宝SDK进行支付开发时,需要遵守支付宝的相关规定和安全要求,确保支付过程的安全和正确性。在实际开发中,还需要根据业务需求进行相关的调整和优化。例如,可以根据不同的支付场景选择不同的支付方式,或者对支付结果进行定时查询和处理等等。总之,只有不断地实践和优化,才能在实际项目中使用支付宝SDK进行高效、安全、稳定的支付开发。

总结

在本篇博客中,我们介绍了在SpringBoot项目中集成支付宝支付的五种场景;需要注意保护支付宝API密钥和支付宝公钥等敏感信息,确保支付过程的安全性。

在实际的开发过程中,我们可以根据具体的业务场景和需求,进行支付宝支付功能的扩展和定制化开发。同时,我们也需要考虑支付宝支付过程中的异常情况和处理方法,例如订单重复支付、支付超时、支付金额不正确等问题。

希望这篇博客能够帮助您掌握SpringBoot集成支付宝支付的方法,并能够在实际项目中得到应用。如果您有任何问题或建议,欢迎在评论区留言,谢谢!