一、前言
支付寶新版SDK-PC端掃碼支付 + 手機瀏覽器H5支付「本文」
PC端掃碼支付,其實就是就是 電腦網站支付,本文基於支付寶沙箱環境,不了解的可以看一下上邊的鏈接。
PS:本文是基於支付寶新版 SDK 重寫的,用法非常簡單,之前的舊版 SDK 就別參考了~
本文環境:
- JDK1.8
- IDEA 2020.3.2
- SpringBoot 2.2.2
- alipay-easysdk 2.2.0
- 支付寶沙箱環境
二、引入依賴
源碼地址:https://github.com/niceyoo/alipay-demo
創建一個 SpringBoot 應用(有基礎的建議直接看↑源碼),在 pom 中引入如下依賴:
<!-- alipay -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-easysdk</artifactId>
<version>2.2.0</version>
</dependency>
在 application.yml 文件中添加如下配置:
## 支付寶配置
alipay:
# 應用ID
appId: 你的appid
# 應用私鑰
privateKey: 你的應用私鑰privateKey
# 支付寶公鑰,注意不是生成的應用公鑰
publicKey: 你的支付寶公鑰publicKey
#支付網關配置,這一項是寫死的,正式環境是openapi.alipay.com
gateway: openapi.alipaydev.com
# 支付寶前台跳轉地址
returnUrl: http://ngrok.sscai.club/html/success
# 支付寶后台通知地址
notifyUrl: http://ngrok.sscai.club/api/alipay/notify_url
# 支付寶前台手機網頁支付中途取消跳轉地址
errorUrl: http://ngrok.sscai.club/html/error
這些參數在哪里獲取的?
1、appId(應用ID)
https://open.alipay.com/platform/appDaily.htm?tab=info
具體見下圖所示:
2、publicKey、privateKey(支付寶公鑰、應用私鑰)
windows工具:點擊此鏈接
macos工具:點擊此鏈接
這塊參考這篇文章的第三節吧:https://www.cnblogs.com/niceyoo/p/12196095.html
3、gateway(支付網關配置)
測試環境:openapi.alipaydev.com
正式環境:openapi.alipay.com
4、returnUrl、notifyUrl、errorUrl(跳轉地址)
這三個地址在測試環境,可以使用內網映射的地址,尤其是 notifyUrl ,這個是支付寶的回調 URl,必須外網可訪問。
內網映射可以使用免費的 natapp 。
natapp鏈接:https://natapp.cn/
具體用法可自行百度。
內網映射就是將內網映射到外網,實現通過外網鏈接訪問本地的效果。 例如上方的:http://ngrok.sscai.club 指向我本地的 http://127.0.0.1:port
三、代碼部分
1、支付寶參數配置類
上面定義的參數有了,接下來就是如何使用了。新增一個配置類(AlipayConfig):
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;
/**
* @author : niceyoo
* @version : 1.0
* @title : AlipayApplication
* @description : 支付寶支付配置類
* @copyright :
* @date :
*/
@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;
}
}
PS:詳細的參數文檔:https://opendocs.alipay.com/apis/00y8k9
2、模擬訂單Controller類
/**
* @author : niceyoo
* @version : 1.0
* @title : AlipayController
* @description : 訂單支付控制層-測試代碼
* @copyright :
* @date :
*/
@RestController
@RequestMapping("/api/alipay")
public class AlipayController {
@Autowired
private AlipayService alipayService;
/**
* @description: 支付寶電腦網頁支付
* @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);
}
/**
* @description: 支付寶手機網頁支付
* @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);
}
/**
* @description: 支付寶異步回調
* @param request: 請求
* @return java.lang.String
*/
@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));
}
/** 支付寶驗簽 **/
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";
}
/**
* @description: 支付寶退款
* @param outTradeNo: 商家訂單號
* @param refundAmount: 退款金額(不能大於交易金額)
* @return java.lang.String
*/
@PostMapping("/refund")
public String refund(String outTradeNo, String refundAmount) {
return alipayService.refund(outTradeNo, refundAmount);
}
}
訂單 Controller 類主要模擬了四個方法:
- page:網站支付
- wap:手機支付
- notify_url:支付回調方法
- refund:退款調用方法
3、模擬訂單Service類
/**
* @author : niceyoo
* @version : 1.0
* @title : AlipayService
* @description :
* @copyright :
* @date : 2021/2/8 12:27
*/
@Service
public class AlipayService {
/**
* 支付成功后要跳轉的頁面
*/
@Value("${alipay.returnUrl}")
private String returnUrl;
/**
* 支付寶前台手機網頁支付中途取消跳轉地址
*/
@Value("${alipay.errorUrl}")
private String errorUrl;
/**
*
* @param subject
* @param total
* @return
*/
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;
}
/**
*
* @param subject
* @param total
* @return
*/
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;
}
/**
*
* @param outTradeNo
* @param refundAmount
* @return
*/
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 "退款失敗";
}
}
Service 主要調用支付寶支付提供的便捷方法,大家可以看一下方法中的寫法。
用到的模擬生成訂單號的工具類:
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);
}
}
4、前端截圖以及支付演示
由於使用了 thymeleaf,增加了三個前端界面:
- 首頁調用支付
- 支付成功界面
- 支付失敗界面
首頁主要就是 form 表單的提交,調用了兩個方法:網頁支付、手機網站支付
<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>
支付時需要用到沙箱賬號,即支付寶沙箱版,下載鏈接如下,一個我的下載鏈接,一個官方的,哪個下載快用哪個。
https://niceyoo.lanzous.com/i7QFulh3uri
https://sandbox.alipaydev.com/user/downloadApp.htm
4.1、點擊電腦確認支付:PC端支付截圖
4.2、點擊手機確認支付:手機端支付截圖
PS:進行支付測試,注意付款要用沙箱環境提供的支付寶APK。且環境必須手機瀏覽器環境下,非PC端操作。
支付成功后會支付寶會調回調方法:(下圖是我的代理調用截圖)
至此,從以上看來,其實不難發現支付寶支付是非常簡單的。
ok,這篇文章就到這結束了,上邊並沒有詳細介紹接口調用、參數說明等,詳細介紹請查看官方文檔:https://docs.open.alipay.com/270/105902/