SpringBoot(二)整合支付寶 - 電腦網站支付和查詢賬單
一、簡介
電腦支付常用於電商和後臺管理系統的賬戶充值等場景。
電腦網站支付 文件
電腦網站支付流程圖
專案原始碼(含資料庫):碼雲Gitee
二、整合步驟
0、建立應用、配置金鑰
整合前需要先建立應用、配置金鑰、回撥地址等以及alipay-sdk-java.jar
和alipay-trade-sdk.jar
請檢視
SpringBoot(一)整合支付寶 - 準備工作 | 官網案例
1、pom 座標
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<fastjson.version>1.2.41</fastjson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mariadb依賴 start-->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
</dependency>
<!-- mariadb依賴 end-->
<!--sprignboot mybatis支援-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<!-- jsp相關 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- 用於解析jsp頁面-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<!-- 熱部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- apache的工具包 MapUtils start -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<!-- apache的工具包 end -->
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 支付寶 alipay sdk -->
<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.1.0</version>
</dependency>
<!-- wx xml相關 -->
<!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>
</dependencies>
2、application.properties
spring:
datasource:
driver-class-name: org.mariadb.jdbc.Driver
url: jdbc:mariadb://localhost:3306/alipay?allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
username: root
password: 123456
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
static-path-pattern: /**
redis:
host: 127.0.0.1
port: 6379
timeout: 10000
password: 123456
mybatis:
mapper-locations: classpath:/mybatis-mapper/*
type-aliases-package: com.example.demo.pojo
logging:
level:
org:
springframework: WARN
#列印dao上的sql語句
com:
example:
demo :
dao : DEBUG
# config: classpath:logback-admin.xml #這個註釋掉就不會在伺服器產生日誌
server:
port: 8080
devtools:
livereload:
enabled: true #是否支援livereload
port: 35729
restart:
enabled: true #是否支援熱部署
3、支付寶配置類
public class AlipayConfig {
//這裡用natapp內外網穿透
// public static final String natUrl = "http://gca8w8.natappfree.cc";
public static final String natUrl = "http://localhost:8080";
// 應用ID,您的APPID,收款賬號既是您的APPID對應支付寶賬號
public static String app_id = "";//在後臺獲取(必須配置)
// 商戶私鑰,您的PKCS8格式RSA2私鑰
public static String merchant_private_key = "";
// 支付寶公鑰,檢視地址:https://openhome.alipay.com/platform/keyManage.html 對應APPID下的支付寶公鑰。
public static String alipay_public_key = "";
// 伺服器非同步通知頁面路徑 需http://格式的完整路徑,不能加?id=123這類自定義引數,必須外網可以正常訪問
public static String notify_url = natUrl + "/alipay/alipayNotifyNotice";
// 頁面跳轉同步通知頁面路徑 需http://格式的完整路徑,不能加?id=123這類自定義引數,必須外網可以正常訪問
public static String return_url = natUrl + "/alipay/alipayReturnNotice";
// public static String return_url = "http://login.calidray.com/?#/sign";
// 簽名方式
public static String sign_type = "RSA2";
// 字元編碼格式
public static String charset = "utf-8";
// 支付寶閘道器
public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";//注意:沙箱測試環境,正式環境為:https://openapi.alipay.com/gateway.do
}
4、支付寶Controller
@Controller
@RequestMapping("/alipay")
public class AlipayController {
private static final Logger LOGGER = LoggerFactory.getLogger(AlipayController.class);
@Autowired
private ProductService productService;
@Autowired
private OrdersService ordersService;
/**
* 對應官方例子 alipay.trade.page.pay.jsp
* @Description: 前往支付寶第三方閘道器進行支付
* @Description notify_url 和 return_url 需要外網可以訪問,建議natapp 內網穿透
* @Date 2020-10-29 15:02
* @Author: StarSea99
*/
@PostMapping("goAlipay")
@ResponseBody
public String goAlipay(String orderId, HttpServletRequest request, HttpServletRequest response) throws Exception {
Orders order = ordersService.getOrderById(orderId);
Product product = productService.getProductById(order.getProductId());
//獲得初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_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 = orderId;
//付款金額,必填
String total_amount = order.getOrderAmount();
//訂單名稱,必填
String subject = product.getName();
//商品描述,可空
String body = "使用者訂購商品個數:" + order.getBuyCounts();
// 該筆訂單允許的最晚付款時間,逾期將關閉交易。取值範圍:1m~15d。m-分鐘,h-小時,d-天,1c-當天(1c-當天的情況下,無論交易何時建立,都在0點關閉)。 該引數數值不接受小數點, 如 1.5h,可轉換為 90m。
String timeout_express = "10m";
//例子去官方api找
alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
+ "\"total_amount\":\"" + total_amount + "\","
+ "\"subject\":\"" + subject + "\","
+ "\"body\":\"" + body + "\","
+ "\"timeout_express\":\"" + timeout_express + "\","
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
//請求
String result = alipayClient.pageExecute(alipayRequest).getBody();
System.out.println("==="+result);
return result;
}
/**
* @Title: 對應官方例子return_url.jsp return_url必須放在公網上 回跳頁面
* @Description: 支付寶同步通知頁面
* @Description TODO
* @Date 2020-10-29 15:02
* @Author: StarSea99
*/
@RequestMapping("alipayReturnNotice")
public String alipayReturnNotice(HttpServletRequest request, HttpServletRequest response, Map map) throws Exception {
LOGGER.info("支付成功, 進入同步通知介面...");
//獲取支付寶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 = (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] + ",";
}
//亂碼解決,這段程式碼在出現亂碼時使用
valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); //呼叫SDK驗證簽名
//——請在這裡編寫您的程式(以下程式碼僅作參考)——
if (signVerified) {
//商戶訂單號
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 total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
// 修改叮噹狀態,改為 支付成功,已付款; 同時新增支付流水 這裡放在 非同步 業務 處理
// ordersService.updateOrderStatus(out_trade_no, trade_no, total_amount);
//頁面 展示
Orders order = ordersService.getOrderById(out_trade_no);
Product product = productService.getProductById(order.getProductId());
LOGGER.info("********************** 支付成功(支付寶同步通知) **********************");
LOGGER.info("* 訂單號: {}", out_trade_no);
LOGGER.info("* 支付寶交易號: {}", trade_no);
LOGGER.info("* 實付金額: {}", total_amount);
LOGGER.info("* 購買產品: {}", product.getName());
LOGGER.info("***************************************************************");
map.put("out_trade_no", out_trade_no);
map.put("trade_no", trade_no);
map.put("total_amount", total_amount);
map.put("productName", product.getName());
} else {
LOGGER.info("支付, 驗籤失敗...");
}
//前後分離形式 直接返回頁面 記得加上註解@Response http://login.calidray.com你要返回的網址,再頁面初始化時候讓前端呼叫你其他介面,返回資訊
// String result = "<form action=\"http://login.calidray.com/?#/index/depreciation-scrap/depreciation\" method=\"get\" name=\"form1\">\n" +
// "</form>\n" +
// "<script>document.forms[0].submit();</script>";
//
// return result;
//前後不分離的形式,直接返回jsp頁面
return "alipaySuccess";
}
/* *
* 功能:支付寶伺服器非同步通知頁面 對應官方例子 notify_url.jsp notify_url必須放入公網
* 日期:2017-03-30
* 說明:
* 以下程式碼只是為了方便商戶測試而提供的樣例程式碼,商戶可以根據自己網站的需要,按照技術文件編寫,並非一定要使用該程式碼。
* 該程式碼僅供學習和研究支付寶介面使用,只是提供一個參考。
*************************頁面功能說明************************* 製作業務處理
* 建立該頁面檔案時,請留心該頁面檔案中無任何HTML程式碼及空格。
* 該頁面不能在本機電腦測試,請到伺服器上做測試。請確保外部可以訪問該頁面。
* 如果沒有收到該頁面返回的 success
* 建議該頁面只做支付成功的業務邏輯處理,退款的處理請以呼叫退款查詢介面的結果為準。
*/
/**
* @Description: 支付寶非同步 通知 製作業務處理
* @Description TODO
* @Date 2020-10-29 15:02
* @Author: StarSea99
*/
@RequestMapping(value = "/alipayNotifyNotice")
@ResponseBody
public String alipayNotifyNotice(HttpServletRequest request, HttpServletRequest response) throws Exception {
LOGGER.info("支付成功, 進入非同步通知介面...");
//獲取支付寶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 = (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] + ",";
}
//亂碼解決,這段程式碼在出現亂碼時使用
// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); //呼叫SDK驗證簽名
//——請在這裡編寫您的程式(以下程式碼僅作參考)——
/* 實際驗證過程建議商戶務必新增以下校驗:
1、需要驗證該通知資料中的out_trade_no是否為商戶系統中建立的訂單號,
2、判斷total_amount是否確實為該訂單的實際金額(即商戶訂單建立時的金額),
3、校驗通知中的seller_id(或者seller_email) 是否為out_trade_no這筆單據的對應的操作方(有的時候,一個商戶可能有多個seller_id/seller_email)
4、驗證app_id是否為該商戶本身。
*/
if (signVerified) {//驗證成功
//商戶訂單號
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");
//付款金額
String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
if (trade_status.equals("TRADE_FINISHED")) {
//判斷該筆訂單是否在商戶網站中已經做過處理
//如果沒有做過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程式
//如果有做過處理,不執行商戶的業務程式
//注意: 尚自習的訂單沒有退款功能, 這個條件判斷是進不來的, 所以此處不必寫程式碼
//退款日期超過可退款期限後(如三個月可退款),支付寶系統傳送該交易狀態通知
} else if (trade_status.equals("TRADE_SUCCESS")) {
//判斷該筆訂單是否在商戶網站中已經做過處理
//如果沒有做過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程式
//如果有做過處理,不執行商戶的業務程式
//注意:
//付款完成後,支付寶系統傳送該交易狀態通知
// 修改叮噹狀態,改為 支付成功,已付款; 同時新增支付流水
ordersService.updateOrderStatus(out_trade_no, trade_no, total_amount);
//這裡不用 查 只是為了 看日誌 查的方法應該解除安裝 同步回撥 頁面 中
Orders order = ordersService.getOrderById(out_trade_no);
Product product = productService.getProductById(order.getProductId());
LOGGER.info("********************** 支付成功(支付寶非同步通知)查詢 只是為了 看日誌 **********************");
LOGGER.info("* 訂單號: {}", out_trade_no);
LOGGER.info("* 支付寶交易號: {}", trade_no);
LOGGER.info("* 實付金額: {}", total_amount);
LOGGER.info("* 購買產品: {}", product.getName());
LOGGER.info("***************************************************************");
}
LOGGER.info("支付成功...");
} else {//驗證失敗
LOGGER.info("支付, 驗籤失敗...");
}
return "success";
}
}
5、ProductController 類
@Controller
@RequestMapping
public class ProductController {
@Autowired
private ProductService productService;
@Autowired
private OrdersService ordersService;
//獲取產品列表
@RequestMapping
public String products(Map map) {
List<Product> pList = productService.getProducts();
map.put("pList", pList);
return "index";
}
//首頁顯示,查詢全部產品
@RequestMapping("index")
public String index(Map map) {
List<Product> pList = productService.getProducts();
map.put("pList", pList);
return "index";
}
//進入購物車頁面
@RequestMapping(value = "/goConfirm")
public String goConfirm(String productId, Map map) {
Product p = productService.getProductById(productId);
map.put("p", p);
return "goConfirm";
}
//分段提交,儲存訂單
@RequestMapping(value = "/createOrder")
@ResponseBody
public LeeJSONResult createOrder(Orders order) throws Exception {
Product p = productService.getProductById(order.getProductId());
Sid sid = new Sid();
String orderId = sid.nextShort();//生成16位隨機字串
order.setId(orderId);//設定id
order.setOrderNum(orderId);//設定訂單號
order.setCreateTime(new Date());//設定建立時間
order.setOrderAmount(String.valueOf(Float.valueOf(p.getPrice()) * order.getBuyCounts()));//實際支付金額
order.setOrderStatus(OrderStatusEnum.WAIT_PAY.key);//訂單狀態
ordersService.saveOrder(order);
return LeeJSONResult.ok(orderId);
}
//分段提交,第二段
@RequestMapping(value = "/goPay")
public String goPay(String orderId, Map map) {
//根據訂單號查詢訂單
Orders order = ordersService.getOrderById(orderId);
//根據訂單號查詢產品
Product p = productService.getProductById(order.getProductId());
map.put("order", order);
map.put("p", p);
return "goPay";
}
}
6、想看完成的程式碼可以檢視 Gitee
資料庫,頁面展示以及業務層呼叫 這裡略過
專案原始碼(含資料庫):碼雲Gitee
7、專案效果圖展示
說明:此專案只是為了跑通流程,頁面不夠好可以自行尋找整合。
首頁
購物車
確認訂單
支付寶支付(使用沙箱)
支付成功回撥資訊頁
如果有收穫!!! 希望老鐵們來個三連,點贊、收藏、轉發。
創作不易,別忘點個贊,可以讓更多的人看到這篇文章,順便鼓勵我寫出更好的部落格
相關文章
- Java 支付寶支付,退款,單筆轉賬到支付寶賬戶(支付寶訂單退款)Java
- 一個PHP檔案搞定支付寶系列之電腦網站支付PHP網站
- android 整合微信支付和支付寶支付其實很簡單Android
- Laravel 整合 EasyAlipay 實現支付寶手機網站 Wap 支付Laravel網站
- java對接支付寶支付(手機網站支付)Java網站
- php 支付寶 SDK 單筆轉賬PHP
- web端網站接入支付寶支付過程Web網站
- iOS使用Stripe整合支付寶Alipay支付iOS
- 支付寶“手機網站支付”開發的相關文件和工具網站
- Python提取支付寶和微信支付二維碼Python
- java實現沙箱測試環境支付寶支付(demo)和整合微信支付和支付寶支付到springmvc+spring+mybatis環境全過程(支付寶和微信支付、附原始碼)JavaSpringMVCMyBatis原始碼
- SpringBoot 配置支付寶介面Spring Boot
- 支付寶微信合單支付
- 支付寶記賬功能怎麼用?支付寶記賬功能的使用方法
- 關於支付寶以及微信支付的整合
- 對iOS端支付寶和微信支付程式碼進行整合iOS
- PHP-Laravel支付寶支付和微信支付PHPLaravel
- Laravel實現支付寶分賬Laravel
- 支付寶支付
- iOS 模仿支付寶支付到賬推送,播報錢數iOS
- 支付寶裡如何使用網銀支付?
- 微信支付,支付寶支付
- 支付寶支付產品介面文件地址和支付寶代金券理解
- pay-spring-boot 開箱即用的Java支付模組,整合支付寶支付、微信支付SpringbootJava
- 關於微信支付,支付寶支付
- 支付寶手機網站支付開通技巧,解決簽約條件不足!網站
- Laravel 搞定支付寶和微信掃碼支付Laravel
- 支付寶實時到賬的MVC示例MVC
- XorPay 個人支付平臺【支援個人微信支付和支付寶支付介面】
- 支付寶alipay移動支付
- 支付寶、微信支付(.NET)
- vue-仿支付寶支付Vue
- Django呼叫支付寶支付介面Django
- Java接入支付寶支付教程Java
- 支付寶-API介面解析-轉賬到銀行API
- yansongda 支付寶商家轉賬給使用者
- 玩轉 iOS 開發:整合 AliPay – 支付寶iOS
- Android 接入微信支付寶支付Android