SpringBoot實現簡易支付寶網頁支付功能

       該文章描述瞭一個基於SpringBoot程序的支付寶支付demo,由於是個人開發者而非企業,因此設計到的技術較為簡單,功能也有局限,適合初學者入門學習【我自己就是哈哈哈】

準備工作

流程簡介

電腦網站支付.png

        該圖截取於支付寶開放平臺官網,描述瞭消費者和商戶【開發者】服務器和支付寶服務間的請求流程,可以看到用戶是通過商戶的服務器進行發送支付請求,再由消費者輸入相關用戶登錄信息和支付信息【該流程商戶服務器無法幹預和監聽】,用戶和支付寶方的結果會由支付寶服務器通知回商戶服務器,商戶服務器可以編寫對應的邏輯去處理。

獲取相關支付秘鑰信息

由於是個人開發,沒有企業的營業執照,因此自己采取的是使用沙箱模型進行支付寶模擬,對應的,支付寶掃碼軟件需要是沙箱版的支付寶,沙箱支付寶下載地址:支付寶

首先登陸螞蟻金服開放平臺,登錄後進入管理中心

image-20211020210329158

image-20211020173346934

登錄後點擊該服務,進入後可以查看到屬於自己的沙箱測試賬號和一些公鑰私鑰等信息

image-20211020210258464

<!--        aliPay相關SDK-->
<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-sdk-java</artifactId>
    <version>4.17.5.ALL</version>
</dependency>
​
<!--        二維碼生成器-->
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.3.0</version>
</dependency>
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.3.0</version>
</dependency>

這些信息很重要,我們可以在配置類中去定義配置這些信息,這裡給出一個支付寶官方給出的配置類。

import java.io.FileWriter;
import java.io.IOException;
​
public class AlipayConfig {
    
//↓↓↓↓↓↓↓↓↓↓請在這裡配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
​
    // 應用ID,您的APPID,收款賬號既是您的APPID對應支付寶賬號
    public static String app_id = "你的APPID";
    
    // 商戶私鑰,您的PKCS8格式RSA2私鑰
    public static String merchant_private_key = "你的私鑰";
    
    // 支付寶公鑰,查看地址:https://openhome.alipay.com/platform/keyManage.htm 對應APPID下的支付寶公鑰。
    public static String alipay_public_key="你的應用公鑰";
    // 下面是兩個回調地址,指支付成功後用戶會跳轉到哪些頁面,不填也可以
    // 服務器異步通知頁面路徑  需http://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問
    public static String notify_url = "http://工程公網訪問地址/alipay.trade.page.pay-JAVA-UTF-8/notify_url.jsp";
    // 頁面跳轉同步通知頁面路徑 需http://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問
    public static String return_url = "http://工程公網訪問地址/alipay.trade.page.pay-JAVA-UTF-8/return_url.jsp";
​
    // 簽名方式
    public static String sign_type = "RSA2";
    
    // 字符編碼格式
    public static String charset = "UTF-8";
    
    // 沙箱支付寶網關 正式支付網關是 https://openapi.alipay.com/gateway.do 千萬不要混淆瞭
    public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
    
    // 支付寶網關
    public static String log_path = "C:\\";
​
    // json格式
    public static String format = "json";
​
​
//↑↑↑↑↑↑↑↑↑↑請在這裡配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
​
    /** 
     * 寫日志,方便測試(看網站需求,也可以改成把記錄存入數據庫)
     * @param sWord 要寫入日志裡的文本內容
     */
    public static void logResult(String sWord) {
        FileWriter writer = null;
        try {
            writer = new FileWriter(log_path + "alipay_log_" + System.currentTimeMillis()+".txt");
            writer.write(sWord);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
​

代碼編寫

支付請求鏈接

上述準備工作配置完之後,就可以編寫controller瞭,在該controller中,許多信息都雜糅在瞭一起,實際上這些步驟可能需要拆分成多個步驟才是更合理的,這裡僅僅為瞭代碼演示方便而放在一起。

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
​
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.data.domain.Pageable;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
​
/**
* @website https://el-admin.vip
* @author nijunwei
* @date 2021-10-18
**/
@Controller
@RequestMapping("/api/test")
public class TestController {
​​   
    @GetMapping("/transcation")
    public   void   doPost (HttpServletRequest httpRequest,
                            HttpServletResponse httpResponse)   throws ServletException, IOException  {
        AlipayClient alipayClient =  new DefaultAlipayClient( AlipayConfig.gatewayUrl , AlipayConfig.app_id, AlipayConfig.merchant_private_key,AlipayConfig.format , AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);  //獲得初始化的AlipayClient
        AlipayTradePagePayRequest alipayRequest =  new  AlipayTradePagePayRequest(); //創建API對應的request
​
        //商戶訂單號,商戶網站訂單系統中唯一訂單號,必填
        String out_trade_no = UUID.randomUUID().toString().substring(0,13);
        //付款金額,必填
        String total_amount = new String("88.88");
        //訂單名稱,必填
        String subject="冬天的第一杯奶茶";
        //商品描述,可空
        String body = new String("我的你的什麼?你是我的優樂美");
​
        String bizContent="{\"out_trade_no\":\""+ out_trade_no +"\","
                + "\"total_amount\":\""+ total_amount +"\","
                + "\"subject\":\""+ subject +"\","
                + "\"body\":\""+ body +"\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}";
        alipayRequest.setBizContent(bizContent);
  
​
//        alipayRequest.setBizContent(json);
        String form= "" ;
        try  {
            form = alipayClient.pageExecute(alipayRequest).getBody();  //調用SDK生成表單
        }  catch  (AlipayApiException e) {
            e.printStackTrace();
        }
        // 頁面刷新會客戶端
        httpResponse.setCharacterEncoding("UTF-8");
        httpResponse.setContentType("text/html;charset=UTF-8");
        httpResponse.getWriter().write(form); //直接將完整的表單html輸出到頁面
        httpResponse.getWriter().flush();
        httpResponse.getWriter().close();
    }
​
}

幾個比較值得註意的參數,其餘的請求體參數可以在支付寶開放平臺查詢完整的參數含義

out_tarde_no:支付單號,用於辨別是否重復確認,支付寶那邊會有一套機制防止用戶重復支付一個單號的訂單。
total_amount:支付金額,單位為元,可達到小數點後兩位,如88.88表示88元8角8分。
subject:支付時顯示訂單標題
body:商品的信息描述
product_code:此處固定為FAST_INSTANT_TRADE_PAY,對於其他代碼的含義可查看官方文檔

使用沙箱支付寶請求該鏈接後頁面如下,不同頁面是不同請求地址的,但大致流程與原理一致。

image-20211020211402658

使用沙箱支付寶進入該連接就可以瞭,例如

http://localhost:8000/api/test/transcation

二維碼生成

那麼外部該如何訪問呢?使用支付寶的掃碼功能可以很好的解決這個問題

一個生成QRCode的工具類如下

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
​
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
public class QRCodeGeneratorUtil {
    // 暫定圖片路徑
    private static final String QR_CODE_IMAGE_PATH = "D:\\eladmin\\eladmin\\QRCodePics\\test.png";
​
    private static void generateQRCodeImage(String text, int width, int height, String filePath) throws WriterException, IOException {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
​
        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height);
​
        Path path = FileSystems.getDefault().getPath(filePath);
​
        MatrixToImageWriter.writeToPath(bitMatrix, "PNG", path);
​
    }
​
    public static void main(String[] args) {
        try {
            generateQRCodeImage("http://192.168.137.1:8000/api/test/transcation", 350, 350, QR_CODE_IMAGE_PATH);
        } catch (WriterException e) {
            System.out.println("Could not generate QR Code, WriterException :: " + e.getMessage());
        } catch (IOException e) {
            System.out.println("Could not generate QR Code, IOException :: " + e.getMessage());
        }
​
    }
​
}

主方法中生成瞭一張信息為

http://192.168.137.1:8000/api/test/transcation

長寬為350的二維碼,掃描該二維嗎即可訪問其中的信息【會直接向該鏈接發生請求】

其中,請求的ip地址如果部署在公網可以訪問的服務器,那麼直接使用手機上的沙箱支付寶掃描即可。如果沒有公網的服務器【如阿裡雲】那麼可以讓手機和電腦置於同一局域網然後內網訪問,或者使用電腦自帶的熱點功能,開啟後讓手機連接。

image-20211020205440327

然後打開cmd,查看局域網內網絡配置,輸入ipconfig查看,如果是linux,則ifconfig

image-20211020205537967

可以看到是192.168.137.1這個地址,這和上面我那段代碼是一樣的,因此選取該IP地址即可在內網進行訪問,達到模擬的效果,支付寶掃碼時便可向SpringBoot程序發送請求,然後傳到支付寶端,處理請求後傳回html頁面,直接返回給客戶端。

到此這篇關於SpringBoot實現簡易支付寶網頁支付的文章就介紹到這瞭,更多相關SpringBoot支付寶網頁支付內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: