SpringBoot接入支付寶教程


碼雲地址:

 https://gitee.com/zhang-zhixi/aliyun-pay

前言:

今天在一個公眾號看到了這樣一篇文章,寫的是:SpringBoot接入支付寶,看了那篇文章發現寫的比較一般,本着求知的心態,今天想着接觸下接入支付寶,然后寫個博客~

參考博客:

  springboot接入支付寶支付-新版SDK(2020/11/03)

使用到的支付寶開發網址:

  支付寶開發助手

  支付寶開放平台-沙箱環境

  MiniU研發工作台

  ngrok:內網穿透

下面需要使用到的鏈接或者秘鑰我都會用紅色標注出來

一、環境搭建

1、應用公鑰/私鑰的獲取

  進入到支付寶開發助手-->MiniU研發工作台,以前的話應該是讓下載軟件什么的獲取秘鑰,現在可以直接通過網頁進行獲取了

復制下來生成的公鑰跟私鑰,記到小本子上面~

 2、APPID、支付寶公鑰的獲取

進入到支付寶開放平台-沙箱環境,復制我們剛剛生成的公鑰,放在對應的框框中即可生成"支付寶公鑰"

復制你的APPID

 復制生成的支付寶公鑰~

記得復制下來支付寶提供的測試賬號,下面測試要用:

 

 

3、內網穿透設置

我使用的是Windows環境,這里我就下載Windows版本的ngrok,這是國外的網站有的小伙伴下載比較慢,可以使用藍奏雲下載:https://wws.lanzoui.com/izXZZsuw9wb

 下載完成之后,使用命令行進入到解壓后的目錄,復制內網穿透的鏈接:注意先別把窗口關閉了。

1、進入目錄:鼠標放到導航欄上面,輸入cmd,即可快速進入

2、啟動應用:ngrok http 端口

二、代碼整理

新建SpringBoot項目(只需添加SpringBootWeb依賴即可),項目結構如下:

pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-easysdk</artifactId>
    <version>2.1.0</version>
</dependency>

application.properties  

## 端口
server.port=8080
## 支付寶配置
# 應用ID
alipay.appId=把你的應用id填到這里
# 應用私鑰
alipay.privateKey=把你的應用私鑰填到這里
# 支付寶公鑰,注意不是生成的應用公鑰
alipay.publicKey=把你的支付寶公鑰填到這里
#支付網關配置,這一項是寫死的,正式環境是openapi.alipay.com
alipay.gateway=openapi.alipaydev.com
# 支付寶前台跳轉地址
alipay.returnUrl=生成的外網穿透鏈接/return_url.html
# 支付寶后台通知地址
alipay.notifyUrl=生成的外網穿透鏈接/api/alipay/notify_url
# 支付寶前台手機網頁支付中途取消跳轉地址
alipay.errorUrl=生成的外網穿透鏈接/error_url.html

config/AlipayConfig.java

/**
 * @author zhangzhixi
 * @version 1.0
 * @date 2021-8-19 15:02
 */
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class AlipayConfig implements ApplicationRunner {

    // 應用id
    @Value("${alipay.appId}")
    private String appId;

    // 私鑰
    @Value("${alipay.privateKey}")
    private String privateKey;

    // 公鑰
    @Value("${alipay.publicKey}")
    private String publicKey;

    // 支付寶網關
    @Value("${alipay.gateway}")
    private String gateway;

    // 支付成功后的接口回調地址,不是回調的友好頁面,不要弄混了
    @Value("${alipay.notifyUrl}")
    private String notifyUrl;

    /**
     *  項目初始化事件
     * */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        //初始化支付寶SDK
        Factory.setOptions(getOptions());
        System.out.println("**********支付寶SDK初始化完成**********");
    }

    private Config getOptions() {
        //這里省略了一些不必要的配置,可參考文檔的說明

        Config config = new Config();
        config.protocol = "https";
        config.gatewayHost = this.gateway;
        config.signType = "RSA2";

        config.appId = this.appId;

        // 為避免私鑰隨源碼泄露,推薦從文件中讀取私鑰字符串而不是寫入源碼中
        config.merchantPrivateKey = this.privateKey;

        // 注:如果采用非證書模式,則無需賦值上面的三個證書路徑,改為賦值如下的支付寶公鑰字符串即可
        config.alipayPublicKey = this.publicKey;

        // 可設置異步通知接收服務地址(可選)
        config.notifyUrl = notifyUrl;

        return config;
    }

}
View Code

controller/AlipayController.java

/**
 * @author zhangzhixi
 * @version 1.0
 * @date 2021-8-19 15:06
 */

import com.alipay.easysdk.factory.Factory;
import com.zhixi.aliyunpay.service.AlipayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

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

    private final AlipayService alipayService;

    @Autowired
    public AlipayController(AlipayService alipayService) {
        this.alipayService = alipayService;
    }

    /**
     * 支付寶電腦網頁支付
     * @param subject: 訂單名稱
     * @param total:   金額
     * @return java.lang.String
     */
    @PostMapping("/page")
    public String page(String subject, String total) {
        subject = "測試支付";
        total = "1000";

        return alipayService.page(subject, total);
    }

    /**
     * 支付寶手機網頁支付
     * @param subject: 訂單名稱
     * @param total:   金額
     * @return java.lang.String
     */
    @PostMapping("/wap")
    public String wap(String subject, String total) {
        subject = "測試支付";
        total = "1000";

        return alipayService.wap(subject, total);
    }

    /**
     * @param request: 請求
     * @return java.lang.String
     * @description: 支付寶異步回調
     * @date: 2020/11/3
     */
    @PostMapping("/notify_url")
    public String notify_url(HttpServletRequest request) throws Exception {

        if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
            System.out.println("=========支付寶異步回調========");

            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
                // System.out.println(name + " = " + request.getParameter(name));
            }

            // 支付寶驗簽
            if (Factory.Payment.Common().verifyNotify(params)) {
                // 驗簽通過
                System.out.println("交易名稱: " + params.get("subject"));
                System.out.println("交易狀態: " + params.get("trade_status"));
                System.out.println("支付寶交易憑證號: " + params.get("trade_no"));
                System.out.println("商戶訂單號: " + params.get("out_trade_no"));
                System.out.println("交易金額: " + params.get("total_amount"));
                System.out.println("買家在支付寶唯一id: " + params.get("buyer_id"));
                System.out.println("買家付款時間: " + params.get("gmt_payment"));
                System.out.println("買家付款金額: " + params.get("buyer_pay_amount"));
            }
        }

        return "success";
    }

    /**
     * @param outTradeNo:   商家訂單號
     * @param refundAmount: 退款金額(不能大於交易金額)
     * @return java.lang.String
     * @description: 支付寶退款
     * @date: 2020/11/3
     */
    @PostMapping("/refund")
    public String refund(String outTradeNo, String refundAmount) {
        return alipayService.refund(outTradeNo, refundAmount);
    }

}
View Code

service/AlipayService.java

/**
 * @author zhangzhixi
 * @version 1.0
 * @date 2021-8-19 15:04
 */
public interface AlipayService {

    /**
     * @description: 支付寶電腦網頁支付
     * @param subject: 訂單名稱
     * @param total: 金額
     * @date: 2020/11/3
     * @return java.lang.String
     */
    String page(String subject, String total);

    /**
     * @description: 支付寶手機網頁支付
     * @param subject: 訂單名稱
     * @param total: 金額
     * @date: 2020/11/3
     * @return java.lang.String
     */
    String wap(String subject, String total);

    /**
     * @description: 支付寶退款
     * @param outTradeNo: 商家訂單號
     * @param refundAmount: 退款金額(不能大於交易金額)
     * @date: 2020/11/3
     * @return java.lang.String
     */
    String refund(String outTradeNo, String refundAmount);
}
View Code

service/impl/AlipayService.java

/**
 * @author zhangzhixi
 * @version 1.0
 * @date 2021-8-19 15:04
 */

import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.payment.common.models.AlipayTradeRefundResponse;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.alipay.easysdk.payment.wap.models.AlipayTradeWapPayResponse;
import com.zhixi.aliyunpay.service.AlipayService;
import com.zhixi.aliyunpay.util.OrderUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class AlipayServiceImpl implements AlipayService {

    // 支付成功后要跳轉的頁面
    @Value("${alipay.returnUrl}")
    private String returnUrl;

    // 支付寶前台手機網頁支付中途取消跳轉地址
    @Value("${alipay.errorUrl}")
    private String errorUrl;

    @Override
    public String page(String subject, String total) {

        try {
            AlipayTradePagePayResponse response = Factory.Payment
                    // 選擇電腦網站
                    .Page()
                    // 調用支付方法(訂單名稱, 商家訂單號, 金額, 成功頁面)
                    .pay(subject, OrderUtil.getOrderNo(), total, returnUrl);

            return response.body;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public String wap(String subject, String total) {

        try {
            AlipayTradeWapPayResponse response = Factory.Payment
                    //選擇手機網站
                    .Wap()
                    // 調用支付方法(訂單名稱, 商家訂單號, 金額, 中途退出頁面, 成功頁面)
                    .pay(subject, OrderUtil.getOrderNo(), total, errorUrl, returnUrl);

            return response.body;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public String refund(String outTradeNo, String refundAmount) {
        try {
            AlipayTradeRefundResponse response = Factory.Payment
                    .Common()
                    // 調用交易退款(商家訂單號, 退款金額)
                    .refund(outTradeNo, refundAmount);

            if (response.getMsg().equals("Success")) {
                return "退款成功";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "退款失敗";
    }
}
View Code

util/OrderUtil.java

/**
 * @author zhangzhixi
 * @version 1.0
 * @date 2021-8-19 15:03
 */

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

public class OrderUtil {

    /**
     * 根據時間戳生成訂單號
     */
    public static String getOrderNo() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
        LocalDateTime localDateTime = Instant.ofEpochMilli(System.currentTimeMillis()).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
        return df.format(localDateTime);
    }
}
View Code

html頁面:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>測試支付</title>
</head>
<body>
<div>
    <h2>測試支付</h2>
    <form enctype="multipart/form-data" action="/api/alipay/page" method="post">
        <button type="submit">電腦確認支付</button>
    </form>
    <form enctype="multipart/form-data" action="/api/alipay/wap" method="post">
        <button type="submit">手機確認支付</button>
    </form>
</div>
</body>
</html>
View Code

return_url.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>支付成功</title>
</head>
<body>
<div>
    <h2>支付成功</h2>

    <a href="http://78ff7c27cdb6.ngrok.io/return_url.html">主頁</a>
    <a href="index.html">主頁</a>
</div>
</body>
</html>
View Code

error_url.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>支付失敗</title>
</head>
<body>
<div>
    <h2>支付失敗</h2>
</div>
</body>
</html>
View Code

三、測試

電腦測試訪問:

 

 

手機測試訪問:

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM