天天看點

springboot 支付寶支付

實作步驟

1. 登陸支付寶開放平台

支付寶開放平台連結:https://open.alipay.com

右側直接支付寶掃碼支付就完事了。

登陸之後需要填寫入駐資訊,如果是個人開發者的話可以切換一下資訊,預設為系統服務商,可自行切換到開發者身份。如下圖所示。

springboot 支付寶支付
springboot 支付寶支付

2. 進入沙箱環境

登陸成功後,如下圖所示,頁面往下拉,找到 開發服務 > 研發服務

springboot 支付寶支付

這就是沙箱環境的入口了,接下來就是需要設定一下參數了。

3. 設定必要參數

第一個需要設定的參數為 RSA2(SHA256)密鑰(推薦)

springboot 支付寶支付

點選設定後,可以根據自己情況選擇加密方式,下面我采用的是公鑰:

springboot 支付寶支付

下載下傳安裝支付寶開放平台開放助手,點選生成秘鑰,公鑰私鑰都有用注意儲存一下:

springboot 支付寶支付

将生成的公鑰複制到支付寶視窗中:

springboot 支付寶支付

第二個需要設定的參數為 應用網關

開發環境網關連結為:https://openapi.alipaydev.com/gateway.do

springboot 支付寶支付

4. 體驗測試賬戶

沙箱環境提供了測試賬戶,包含商戶号跟買家号,但是該賬戶隻能在支付寶提供的測試APK上使用。

springboot 支付寶支付

5.搭建工程

1)引入sdk依賴

<!--支付寶SDK依賴-->
<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-sdk-java</artifactId>
    <version>3.1.0</version>
</dependency>
           

2)建立AlipayConfig配置類,集中管理支付相關配置

package com.springboot.alipaydemo.config;

import java.io.FileWriter;
import java.io.IOException;

/**
 * @author ktz 2021/1/9
 */
public class AlipayConfig {
    // 應用ID,您的APPID,收款賬号即是您APPID對應的支付寶賬号,開發時使用沙箱提供的APPID,生産環境改成自己的APPID
    public static String APP_ID = "2016101100661033";

    // 商戶(應用)私鑰(RSA2生成工具生成),您的PKCS8格式為RSA2
    public static String APP_PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCmMdQXsHvgTFeBX9YKM5lL75zIQ3OXXuyslXDFP0zKnx7/dR/Ij1/QktIiD1ZGj7stgZdNAIdM1VCLzLIvIciHmEP67COzZaf8lVYMBB+krnVUZrJSNcNVE6IdUjHfb83skSoMdmNF8GJe12gJWF5lTcbjovp4KDvptHRDr5OvlFcC2B6kbJZ1lvY0c8Y1CMHEqy2gmEM2f8ioglm0jra/9DD2leNGnJdknrQepbU+mtVmBnbSDsWwlE6NoShJEAWQGt3J2kD1iiriU0hVwxAqilLkGdHvZLbrU36ffBOnhrlAsj3FtucNox5KKuhcCmqSTEecsJaHcQarep7BBuhFAgMBAAECggEAWqnEMkgsy+fZtNI7ScVsU2ib9wQVAvbd1iiQJIqrsb2sg1+5vwe4FWiDCeGkB0pRqjmP+InZRaj5D8rTSbL8WjxOmYxIzY0fX0N4dYWqXYRurWR40zBRJxBW1/gHDQVJKUzny3SqI3VHtMV+E9sJY+pSHczDJtmMFapD4sjdoGJCUJVfYSiwnjVLDtsr4Zy0NtDy+uHLplixuFno4aYNxdZMIKkkJkxGOKAp8uiuI44daznOBYK1RJgL3oCOHoQyLS8lQslj+gI3HSZwYFjrzWJMc93itXqN7mkZ5QVOXe9UPoGHpNTk90a6kh/E/GR8iMxalHdqy4JStiwAOkINAQKBgQDg6yNWHqptoUATVrdTplCc/N9RkEY4YUDAG64Agul5SbzMzNNXRyYnoUN5raiXL/fwV+5OiIKOEv3RPAtmKCbE5HuukbJZQ/Jk+pdP/LcJnHVZhIUjeMbcpBwY6qmNzJLo00iPjeJ+8TtDDvpbILUU2uQjOhqLHq7Qy/x3PySxmQKBgQC9KTy3omZSQNltHmwAeMaJkwBRhlj78DIWO79RCMCu2vLsZAlt7ZZPpjXrFOpSJ6OElHyuVeptwOTK8r/FdSiabHxlVqPuxcUE3UTWjyusdc6skb6Q4Yb43FURZgGHQ6A40D4oh7Usnu2oTNDzrqJuiiV/ScSfEK1fOmkzNKYvjQKBgQCKTo2QK5NJjtrECZL6EU+I+capdTp4+PTELUE2d0nyl3FNzrY2+T1xKS1A6ZS+Q3UHikq0aCVAEFWcEHxB+Xa9pHKZymYNlka76YyaVyCG/Hr87Qyh32cJzrCoccSJub6tBR+dhvY8cUKr3c39s4Mmq+OV9ejUm62MH6PEAEQkIQKBgQCDZ901GE0KgOBKLGMMpNoPAh6rg6/XPNIendzW10S7c4Bj9U6TngPYSveT2lC5R64RUPGYTjjvi5uk3KOZ8TyGoix8XYa+PYcTTP8gKg9F3AT53rlKflE8GhvCXWFcbP8l2IwFrdiPKcyhKNPTJJLURYWs+jrr4TL/P12LY9y6lQKBgElazuCMKJ+soUdycSV0fdpFbMxTPH/mbilm9CILKIk82Jhv2glj6FTsSAaGaXgJ8wpULaQzHWRwizrPTsW1NVI53/7II/zP8yGnEul/VBNtUENzwPXYKzQ30MPkqj4dA1Nm7LK3tAdpHIULlUIH+czbQoW0s2hSM+3uSMSMaYw8";

    // 支付寶公鑰(支付寶生成),檢視位址:https://openhome.alipay.com/platform/keyManage.htm 對應APPID下的支付寶公鑰。
    public static String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApuwI5C81TnfLu4ql77w3FdgBCHss7GHQqpzVqwGDZkOMyKRvKGX7oWJtRYDX6I5c0n1hEtnOcG0lo5jT6tYldqRI2k7UxZLmOez2PZfA/q9wrKp2RwgiR3KSS7mS9x13IDpL5OIXADByYtjqQG3TnMGbgo4SXv0eju8qG3Vf13fwicyjs+BWfTXHFZwz8a5YyDxuCIdUL+7KYackxT2MmLmLD0FeN8fXp6iLVJmfAXuKKW95FA8X/FjbLrFtS3OtUpQcp6UBUpRhcHEIMtbTTyHsvTzAqImgsEgdaexNZgSuX/qFSNv7Q65gByThAOinfZZmQltDLy34AEh9FhAmZwIDAQAB";

    // 伺服器異步通知頁面路徑  需http://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常通路
    // 請確定url中的域名和IP是外網可以通路的,且不能填寫localhost、127.0.0.1、192.168.x.x等本地或内網IP
    public static String notify_url = "http://p3hx94.natappfree.cc/notify";

    // 頁面跳轉同步通知頁面路徑 需http://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常通路(其實就是支付成功後傳回的頁面)
    // 請確定url中的域名和IP是外網可以通路的,且不能填寫localhost、127.0.0.1、192.168.x.x等本地或内網IP
    public static String return_url = "http://p3hx94.natappfree.cc/return";
    // 如果支付寶成功通知頁面路徑無法跳轉,模拟可用跳轉位址進行測試
//    public static String return_url = "http://www.baidu.com";
//    public static String return_url = "http://127.0.0.1:8080/return";


    // 簽名方式
    public static String sign_type = "RSA2";

    // 字元編碼格式
    public static String CHARSET = "utf-8";

    // 支付寶網關,這是沙箱的網關(沙箱接口,正式上線時請改用正式支付接口)
    public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";

    // 支付寶網關
    public static String log_path = "C:\\";


    //↑↑↑↑↑↑↑↑↑↑請在這裡配置您的基本資訊↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

    /**
     * 寫日志,友善測試(看網站需求,也可以改成把記錄存入資料庫)
     * @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();
                }
            }
        }
    }
}
           

3)編寫控制層代碼,建立PayController類

package com.springboot.alipaydemo.controller;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.springboot.alipaydemo.config.AlipayConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
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.ResponseBody;

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

/**
 * @author ktz 2021/1/9
 */
@Slf4j
@Controller
public class PayController {
    /***
     * ktz 2021/1/11 13:45
     * 支付網站掃碼支付接口-統一下單支付接口
     * @param request
     * @param response
     * @return void
     */
    @ResponseBody
    @RequestMapping("/pay")
    public void payController(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //獲得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.APP_ID, AlipayConfig.APP_PRIVATE_KEY, "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.sign_type);

        //設定請求參數
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

        //商戶訂單号,商戶網站訂單系統中唯一訂單号,必填
        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
        //付款金額,必填
        String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");
        //訂單名稱,必填
        System.out.println(request.getParameter("subject"));

        String subject = request.getParameter("subject");
        //商品描述,可空
        String body = new String(request.getParameter("body").getBytes("ISO-8859-1"),"UTF-8");

        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                + "\"total_amount\":\""+ total_amount +"\","
                + "\"subject\":\""+ subject +"\","
                + "\"body\":\""+ body +"\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

        //若想給BizContent增加其他可選請求參數,以增加自定義逾時時間參數timeout_express來舉例說明
        //alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
        //    + "\"total_amount\":\""+ total_amount +"\","
        //    + "\"subject\":\""+ subject +"\","
        //    + "\"body\":\""+ body +"\","
        //    + "\"timeout_express\":\"10m\","
        //    + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
        //請求參數可查閱【電腦網站支付的API文檔-alipay.trade.page.pay-請求參數】章節

        //請求
        String form="";
        try {
            form = alipayClient.pageExecute(alipayRequest).getBody(); //調用SDK生成表單
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
        response.getWriter().write(form);//直接将完整的表單html輸出到頁面
        response.getWriter().flush();
        response.getWriter().close();
    }

    /***
     * ktz 2021/1/11 13:48
     * 支付寶伺服器異步通知頁面-支付成功後支付寶通知
     * @param request
     * @param out_trade_no
     * @param trade_no
     * @param trade_status
     * @return java.lang.String
     */
    @PostMapping("/notify")
    @ResponseBody
    public String alipayNotify(HttpServletRequest request, String out_trade_no, String trade_no, String trade_status) throws Exception {
        Map<String, String> params = getParamsMap(request);
        log.info("notify params: {}", JSONObject.toJSON(params));
        // 驗證簽名
        boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, "utf-8", "RSA2");
        log.info("notify signVerified: {}", signVerified);
        if (signVerified) {
            //處理你的業務邏輯,更細訂單狀态等
            return ("success");
        } else {
            log.info("驗證失敗,不去更新狀态");
            return ("fail");
        }
    }

    /***
     * ktz 2021/1/11 13:47
     * 支付寶伺服器同步通知頁面-支付成功後回跳
     * @param request
     * @param out_trade_no
     * @param trade_no
     * @param total_amount
     * @return java.lang.String
     */
    @GetMapping("/return")
    @ResponseBody
    public String alipayReturn(HttpServletRequest request, String out_trade_no,String trade_no,String total_amount) throws Exception {
        Map<String, String> params = getParamsMap(request);
        log.info("return params: {}", JSONObject.toJSON(params));

        // 驗證簽名(支付寶公鑰傳回true)
        boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY,"utf-8", "RSA2");
        log.info("return signVerified: {}", signVerified);

        if (signVerified) {
            return ("success");
        } else {
            log.info("驗證失敗,不去更新狀态");
            return ("fail");
        }
//        return "return_url";
    }

    /***
     * ktz 2021/1/11 13:51
     * 擷取請求參數
     * @param request
     * @return java.util.Map<java.lang.String,java.lang.String>
     */
    private Map<String, String> getParamsMap(HttpServletRequest request) throws Exception {
        Map<String,String> params = new HashMap<>();
        Map requestParams = request.getParameterMap();
        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] + ",";
            }
            //亂碼解決,這段代碼在出現亂碼時使用
            try {
//                valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
                params.put(name, valueStr);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return params;
    }

    @RequestMapping("/index")
    public String toTest(){
        return "index";
    }
}
           

4)其它依賴

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.33</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!--jsp支援-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <scope>provided</scope>
</dependency>
<!-- servlet 依賴包 -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
</dependency>
           

5)配置springmvc的映射路徑

# 配置springmvc映射路徑(@RestController包含的@ResponseBody不走視圖解析器,是以一般配合@Controller使用)
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
           

6)模拟訂單頁 index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<form action="/pay" method="post">
    <!--required 非空-->
    商戶訂單号:<input type="text" name="out_trade_no" required><br/>
    訂單名稱:<input type="text" name="subject" required><br/>
    交易金額:<input type="text" name="total_amount" required><br/>
    訂單描述:<input type="text" name="body"><br/>
    <input type="submit" value="下單"> <input type="reset" value="重置">
</form>
           

7)模拟異步通知頁 notify_url.jsp

<%@page import="com.alipay.api.internal.util.AlipaySignature"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.*"%>
<%@ page import="java.util.Map"%>
<%@ page import="com.springboot.alipaydemo.config.*"%>
<%
   //擷取支付寶POST過來回報資訊
   Map<String,String> params = new HashMap<String,String>();
   Map requestParams = request.getParameterMap();
   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] + ",";
      }
      //亂碼解決,這段代碼在出現亂碼時使用。如果mysign和sign不相等也可以使用這段代碼轉化
//    valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
      params.put(name, valueStr);
   }
   //擷取支付寶的通知傳回參數,可參考技術文檔中頁面跳轉同步通知參數清單(以下僅供參考)
      //商戶訂單号

      String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
      //支付寶交易号

      String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

      //交易狀态
      String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");

      //擷取支付寶的通知傳回參數,可參考技術文檔中頁面跳轉同步通知參數清單(以上僅供參考)//
      //計算得出通知驗證結果
      //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
      boolean verify_result = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2");
      
      if(verify_result){//驗證成功
         //
         //請在這裡加上商戶的業務邏輯程式代碼

         //——請根據您的業務邏輯來編寫程式(以下代碼僅作參考)——
         
         if(trade_status.equals("TRADE_FINISHED")){
            //判斷該筆訂單是否在商戶網站中已經做過處理
               //如果沒有做過處理,根據訂單号(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,并執行商戶的業務程式
               //請務必判斷請求時的total_fee、seller_id與通知時擷取的total_fee、seller_id為一緻的
               //如果有做過處理,不執行商戶的業務程式
               
            //注意:
            //如果簽約的是可退款協定,退款日期超過可退款期限後(如三個月可退款),支付寶系統發送該交易狀态通知
            //如果沒有簽約可退款協定,那麼付款完成後,支付寶系統發送該交易狀态通知。
         } else if (trade_status.equals("TRADE_SUCCESS")){
            //判斷該筆訂單是否在商戶網站中已經做過處理
               //如果沒有做過處理,根據訂單号(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,并執行商戶的業務程式
               //請務必判斷請求時的total_fee、seller_id與通知時擷取的total_fee、seller_id為一緻的
               //如果有做過處理,不執行商戶的業務程式
               
            //注意:
            //如果簽約的是可退款協定,那麼付款完成後,支付寶系統發送該交易狀态通知。
         }

         //——請根據您的業務邏輯來編寫程式(以上代碼僅作參考)——
         out.clear();
         out.println("success");    //請不要修改或删除

         //
      }else{//驗證失敗
         out.println("fail");
      }
%>
           

8)模拟同步回跳頁 return_url.jsp

<%@page import="com.alipay.api.internal.util.AlipaySignature"%>
<%
/* *
 功能:支付寶頁面跳轉同步通知頁面
 版本:3.2
 日期:2011-03-17
 說明:
 以下代碼隻是為了友善商戶測試而提供的樣例代碼,商戶可以根據自己網站的需要,按照技術文檔編寫,并非一定要使用該代碼。
 該代碼僅供學習和研究支付寶接口使用,隻是提供一個參考。

 //***********頁面功能說明***********
 該頁面可在本機電腦測試
 可放入HTML等美化頁面的代碼、商戶業務邏輯程式代碼
 TRADE_FINISHED(表示交易已經成功結束,并不能再對該交易做後續操作);
 TRADE_SUCCESS(表示交易已經成功結束,可以對該交易做後續操作,如:分潤、退款等);
 //********************************
 * */
%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.*"%>
<%@ page import="java.util.Map"%>
<%@ page import="com.springboot.alipaydemo.config.*"%>
<html>
  <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>支付寶頁面跳轉同步通知頁面</title>
  </head>
  <body>
<%
   //擷取支付寶GET過來回報資訊
   Map<String,String> params = new HashMap<String,String>();
   Map requestParams = request.getParameterMap();
   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] + ",";
      }
      //亂碼解決,這段代碼在出現亂碼時使用。如果mysign和sign不相等也可以使用這段代碼轉化
      valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
      params.put(name, valueStr);
   }
   
   //擷取支付寶的通知傳回參數,可參考技術文檔中頁面跳轉同步通知參數清單(以下僅供參考)//
   //商戶訂單号

   String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");

   //支付寶交易号

   String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

   //擷取支付寶的通知傳回參數,可參考技術文檔中頁面跳轉同步通知參數清單(以上僅供參考)//
   //計算得出通知驗證結果
   //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
   boolean verify_result = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2");
   
   if(verify_result){//驗證成功
      //
      //請在這裡加上商戶的業務邏輯程式代碼
      //該頁面可做頁面美工編輯
      out.clear();
      out.println("驗證成功<br />");
      //——請根據您的業務邏輯來編寫程式(以上代碼僅作參考)——

      //
   }else{
      //該頁面可做頁面美工編輯
      out.clear();
      out.println("驗證失敗");
   }
%>
  </body>
</html>
           

注意:異步回調和同步回跳可以在控制層模拟!

RSA生成器下載下傳位址

生成的商戶應用公鑰和私鑰需要儲存.

https://opendocs.alipay.com/open/291/105971

應用申請位置

springboot 支付寶支付

搭建後進行測試,可能遇到以下幾個問題

1.支付寶沙箱環境提示支付存在釣魚風險

springboot 支付寶支付

解決方案:

1)切換浏覽器(我用的是谷歌和火狐)

2)清除浏覽器cookie及網站資料

springboot 支付寶支付

2.網絡異常(反複重試即可)

3.訂單異常(訂單号重複)

4.回調和同步功能無法實作,出現404(内網穿透下)

natapp實作内網穿透

在對接支付寶或微信支付等支付平台時,基本都需要進行回調接口的聯調。而我們在進行本地開發時,本地的内網位址是無法被外網通路的,那麼支付平台的伺服器就無法回調我們的接口位址。是以我們需要做一個内網穿透,才能讓外網能夠通路到我們内網的接口位址。

綜上所述,内網穿透就是幹這麼一件事的,它讓外網的機器能通路到我們内網的接口位址。例如我們在本地開發好了一個網站,想要分享給朋友看,但是他不能直接通路到我們機器上的内網位址,那麼就我們需要做一個内網穿透,然後他就能通路到我們的内網位址了。簡單的說,通過内網穿透,實作外網域名通路内網資源,比如我們的服務接口。

内網映射

内網映射是一種NAT位址轉換,也就是把在内網中的IP轉換成公網IP。為了便于通路還能将變化的公網IP綁定到一個固定的域名上去,這樣外網的人就能通過這個固定域名來通路内網了。例如http://xxx.ssca.club 指向我本地的 http://127.0.0.1:port。通俗的了解,内網映射就是将内網映射到外網,實作通過外網連結進而通路本地的效果。

natapp官網

https://natapp.cn/

完整Demo

連結:https://pan.baidu.com/s/1m_DY87F4lDk3rYMk2YvpVg

提取碼:ktz1