更新時間:2022-11-10 來源:黑馬程序員 瀏覽量:
在長期的教學過程中,了解到很多同學在進行畢業(yè)設計或課程設計時會開發(fā)一些相應的商城系統(tǒng),都有在線支付的相關需求,而做為個人,想在實現(xiàn)在線支付在很多平臺是不具備相關條件的,很多平臺要求具備獨立法人資格的企業(yè)或個人商業(yè)戶才可以申請在線支付,而支付寶提供的沙箱環(huán)境,對于個人實現(xiàn)在線支付測試環(huán)境來講,是一個不錯的選擇,本文主要講解基于支付寶的沙箱環(huán)境來實現(xiàn)在線支付的功能。主要結合一個簡易的商城系統(tǒng)來講解說明在線支付的基本操作流程和相關API的應用,從而實現(xiàn)基于支付寶沙箱在線支付的基本功能。
一、案例說明
本案例基于一個簡易的商城系統(tǒng),在這個系統(tǒng)基礎上實現(xiàn)在了在線沙箱支付的基本應用。系統(tǒng)只保留了基本的商品展示和購物基本功能,其它功能接口全部刪除。系統(tǒng)基于前后端分離的開發(fā)方式,前端使用VUE開發(fā)實現(xiàn),后端使用Springboot結合Mybatis開發(fā)實現(xiàn)。
首頁商品展示

商品詳情

點擊立即付款后進入支付寶付款流程

點擊下一步:

確認付款

完成支付
看完了案例的演示,是不是有一種想試一試的沖突,感覺好簡單?OK,那么我們一起開始學習支付寶沙箱支付的旅程!
二,支付寶沙箱環(huán)境準備
2.1 支付寶沙箱介紹
沙箱環(huán)境是支付寶開放平臺為開發(fā)者提供的與生產(chǎn)環(huán)境完全隔離的聯(lián)調測試環(huán)境,開發(fā)者在沙箱環(huán)境中完成的接口調用不會對生產(chǎn)環(huán)境中的數(shù)據(jù)造成任何影響。
沙箱為開放的產(chǎn)品提供有限功能范圍的支持,可以覆蓋產(chǎn)品的絕大部分核心鏈路和對接邏輯,便于開發(fā)者快速學習/嘗試/開發(fā)/調試。
沙箱環(huán)境會自動完成或忽略一些場景的業(yè)務門檻,例如:開發(fā)者無需等待產(chǎn)品開通,即可直接在沙箱環(huán)境調用接口,使得開發(fā)集成工作可以與業(yè)務流程并行,從而提高項目整體的交付效率。
注意:
- 由于沙箱環(huán)境并非 100% 與生產(chǎn)環(huán)境一致,接口的實際響應邏輯請以生產(chǎn)環(huán)境為準,沙箱環(huán)境開發(fā)調試完成后,仍然需要在生產(chǎn)環(huán)境進行測試驗收。
- 沙箱環(huán)境擁有完全獨立的數(shù)據(jù)體系,沙箱環(huán)境下返回的數(shù)據(jù)(比如用戶 ID 等)在生產(chǎn)環(huán)境中都是不存在的,開發(fā)者不可將沙箱環(huán)境返回的數(shù)據(jù)與生產(chǎn)環(huán)境中的數(shù)據(jù)混淆。
2.2 支付寶沙箱注冊及配置
打開支付寶開發(fā)者頁面進行注冊登陸:https://opendocs.alipay.com/common/02kkv7
登陸后進入開放平臺控制臺:選擇左下解沙箱

在沙箱應用中可以查看沙箱的相關信息,其中APPID需要復制并記錄,我們在進行支付時要指定APPID。

其它的均保持默認配置即可,接口的加簽方式選擇系統(tǒng)默認密鑰即可,選用公鑰模式,點擊查看可以看到對應的公鑰和私鑰:做支付時需要用到。

支付寶網(wǎng)關地址:https://openapi.alipaydev.com/gateway.do
支付寶沙箱網(wǎng)關地址,開發(fā)者在沙箱環(huán)境調用 OpenAPI 發(fā)送 http(s) 請求的目標地址,需配置在AlipayClient中。此地址為固定的,在程序中需要配置。
選擇左邊沙賬戶:創(chuàng)建申請個人和商家對應的虛擬賬戶,并可以在線模擬充值和取現(xiàn)。

至此,我們需要準備的沙箱環(huán)境和配置己準備就緒。
三,內(nèi)網(wǎng)穿透工具準備
支付寶沙箱支付成功后,要回調本地的服務地址進行支付結果的通知,而我們的測試環(huán)境是運行在內(nèi)網(wǎng)中,所以需要借助內(nèi)網(wǎng)穿透工具來實現(xiàn)外網(wǎng)調用內(nèi)網(wǎng)的服務接口。內(nèi)網(wǎng)穿透的工具網(wǎng)上有很多免費的,我們今天使用的是NATAPP這款工具。
1、打開官網(wǎng)注冊并登陸:https://natapp.cn/login
2、登陸后選擇購買隧道:選擇免費隧道(有效期一個月)

3、指定名字,選擇Web協(xié)議,并指定本地的應用通訊的端口

4、購買成功后會生成認證令牌:復制并保存

5、下載客戶端工具:根據(jù)你電腦情況選擇合適的版本下載,這里我選用Windows64位

6、創(chuàng)建配置文件:config.ini 具體下載:https://natapp.cn/article/config_ini
放在客戶端natapp.exe同級目錄下,并將其中的authtoken換成我們剛申請的免費隧道的令牌

7、啟動客戶端:windows下,直接雙擊natapp.exe 即可。紅框內(nèi)就是我們的隧道通信地址。

注意:每次啟動客戶端都會分配一個新的隧道地址:要注意后期更換程序中配置 的地址。
8、測試:此時t2vnvc.natappfree.cc臨時域名就是代表了本地應用程序的訪問地址http://localhost:80
可以直接使用此域名來訪問應用程序下的任意一個接口,如能訪問,則環(huán)境OK。
http://t2vnvc.natappfree.cc/order/findAll 查詢所有訂單:測試成功

四,沙箱支付相關API說明
支付寶支付提供了很多種支付應用場景以及對應的API應用,打開網(wǎng)址:https://open.alipay.com/api

可以看到有對應的應用類型:選中其中某一個進入,則有相關的文檔介紹和API應用案例,所以學習和使用起來還是比較簡單。
4.1 當面付
如果我們想通過支付寶生成二維碼,讓客戶端掃描二維碼進行支付,可以選擇當面付:
https://open.alipay.com/api/detail?code=I1080300001000041016#api-detail-content

各個接口有在線文檔和在線調試的案例,可以自行查看。以其中的統(tǒng)一收單線下交易預創(chuàng)建為例說明:
package com.java.sdk.demo;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.AlipayConfig;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.FileItem;
import java.util.Base64;
import java.util.ArrayList;
import java.util.List;
public class AlipayTradePrecreate {
public static void main(String[] args) throws AlipayApiException {
String privateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCs5FX6NlZEq8t43tnAT91hcGhTPL6Iieq/e1foh3N0ME601PwtfXzFPac0Qp5qygLtyZkYFY8UiYqdXPQpvO4T4ah5Rus8IiCwGDBpyg3ha6xSWnD7QCvc/YgOJ+ei1XD6F5Y+t2X3gbTCsy1H9wTe9XLh78tcpuhib/4OEwxJfHxEi5fBzQQJBE6vo8pX7mTeeP7f1RBxAgRsswMvCQs1SX362XdD3IRWErf8dUOqV0tT5ahjhXdbFv6fUQmnt+1i00CIAlOPm7vLWslw1qJT4ubZuL0HPQLWEoD3ab0OdgaJvPdoWvnUVzBQqwZgnXHFN5nV1QQbVTe3Q3XWIWTNAgMBAAECggEBAI2JI8WBRCBVj2306cgg2XfSQOWbfdNjLHTzMaUfdemxPk2VapiG+WSzMzV6MBv2Im2tsxHfXFGQw5RNq2ibzT8jZftajmqc+auPMdr42WIn9ls4xPM6tm3kc8Q68MsB9soWEx5mnyf+3A7kBfa7BxbLUvAZkZ7Y2Lb1PcMh3tYso7FYERStxpdtUgPSkqXgZERrzrtHpFDe05CI/xjZUfmvXsTrKiIXxqvil9hYGISkMyVJjaJUXvZwmgzLtHd7I8z7sNXOw26Ie1DihCy3VzPh5pwZPQId2v2LBABdUogTwVfb7GAV6swP+OMxoffYPdW7AV+82zOYybm3GjKCTiECgYEA57ukyNybLE7h7yeDSFKdkoBnY7RmIW4NRwQNFopb5LlNt9vTm5easuEdDhPlGoNpJ5Ul/ms9pDVDnH2ZkU7IaiMPd/MxQpQ5dos5tRsjb02YwligiD3ZxDBRCNSjcqiR7+5jYb68H2c8bXLtOtZ/dsYyqZmEhH0OsV/2WKMr9bUCgYEAvv9EO9J2UEVBPkEKvhLfH7X8GZK6CROEehNG8qbDqxJ5AbFmo8lzNvbcHjJoiwEMzYU1q5VMhMVMepk1Lk5Q4VRouAMTUY3o8byQMeX7BYHlmmLaXuw8NAFFE43Mr14UGkrWesZR9u1LSw0QPNag3cyL2XxmgpWCmPAwLzQ+obkCgYEAnFukKFOR8CeZkwCaOGZmI7+4AzJp5wyWsOAu5JKexomxwuj0svtsSl5SeHk8ENOyVB7y7+P0R6QY5rJot/7sg5D8kvbouf/Bdhci7OxO0H8PH7MlPkhdc18WjlrLnkXXkojLTdygmp/RyhfNsfGhN8crz/vhynOHQm95jP0sYDECgYBGJ2zgrEVY5pc4TpurhTL/atDWc9ZxTwHx9PKyXh6wz3Ay9v5EWtI+9h2T2eAcbp5NPwifpY8dlXqp7WxjPdDncyGjtT17Tyyo3iH4sgip1TSIqJadFxhl4bGFpSfxohSwM5zkK8QfdrmZL4svTYZ48ZDMqazdeh0mH9MTA5WdwQKBgFO79TUR5fq+u0sBjYW7VLiQ5J6Tq7U0phFjFFjR/eYqkKUtE5K/BdOsSQjwY21TOkoTazyDJiVLEx5pWQueIa0ez1WPNswz7VN2su9N/jwP+G5ILrz1I+nj2PiWXVbfWZ2qd2h0qB27CF7gZ9lQgjg5dQMt4Fmd7f8uzBzrwLQW";
String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydfxVYSMISxqvitww5063ZQFVRzrcRW9a+xQ0Pozz7ve9IeK1h9p7xFwSUtTNi/ki9ZcnZ7wP0xunKrYPVXyUvRz/vSVnovkzvmcSTdqlgtzTAQTJFYL0nmzhnv4RWbcDnVbo+IIlu8g0p6wQv7V8P5EGpbh63+d3q/DYhsbxVVZN1fKjnw/y38/GuqGoiaxkcrf6h65rGO/aRGbX6gbGnRxUgBOEiFGFdkuCx9ACg4cskSme69lDbIBDpsmSbQpUKhTEA4Wv36mqrbee+hGf5sTaqDUHl0/SPgP45ab15J3BeWHB/yXbdK4Z/gPfMFMweOupg54Sm+kJOGmq73cMwIDAQAB";
AlipayConfig alipayConfig = new AlipayConfig();
alipayConfig.setServerUrl("https://openapi.alipaydev.com/gateway.do");
alipayConfig.setAppId("2021000121607425");
alipayConfig.setPrivateKey(privateKey);
alipayConfig.setFormat("json");
alipayConfig.setAlipayPublicKey(alipayPublicKey);
alipayConfig.setCharset("UTF8");
alipayConfig.setSignType("RSA2");
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setOutTradeNo("20150320010101001");
model.setTotalAmount("88.88");
model.setSubject("Iphone6 16G");
request.setBizModel(model);
AlipayTradePrecreateResponse response = alipayClient.execute(request);
//可以將此字符串返回到客戶端,使用二維碼生成工具來生成二維碼圖片即可
System.out.println("支付地址:"+response.getQrCode());
if (response.isSuccess()) {
System.out.println("調用成功");
} else {
System.out.println("調用失敗");
}
}
} 4.2 手機網(wǎng)站支付API
如果我們基于手機網(wǎng)站來實現(xiàn)在線支付,比如HTML5網(wǎng)站或小程序等,可以通過手機網(wǎng)站支付API進行實現(xiàn):
https://open.alipay.com/api/detail?code=I1080300001000041949

各個接口有在線文檔和在線調試的案例,可以自行查看。以其中的手機網(wǎng)站支付接口2.0為例說明:
package com.java.sdk.demo;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.AlipayConfig;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.FileItem;
import java.util.Base64;
import java.util.ArrayList;
import java.util.List;
public class AlipayTradeWapPay {
public static void main(String[] args) throws AlipayApiException {
String privateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCs5FX6NlZEq8t43tnAT91hcGhTPL6Iieq/e1foh3N0ME601PwtfXzFPac0Qp5qygLtyZkYFY8UiYqdXPQpvO4T4ah5Rus8IiCwGDBpyg3ha6xSWnD7QCvc/YgOJ+ei1XD6F5Y+t2X3gbTCsy1H9wTe9XLh78tcpuhib/4OEwxJfHxEi5fBzQQJBE6vo8pX7mTeeP7f1RBxAgRsswMvCQs1SX362XdD3IRWErf8dUOqV0tT5ahjhXdbFv6fUQmnt+1i00CIAlOPm7vLWslw1qJT4ubZuL0HPQLWEoD3ab0OdgaJvPdoWvnUVzBQqwZgnXHFN5nV1QQbVTe3Q3XWIWTNAgMBAAECggEBAI2JI8WBRCBVj2306cgg2XfSQOWbfdNjLHTzMaUfdemxPk2VapiG+WSzMzV6MBv2Im2tsxHfXFGQw5RNq2ibzT8jZftajmqc+auPMdr42WIn9ls4xPM6tm3kc8Q68MsB9soWEx5mnyf+3A7kBfa7BxbLUvAZkZ7Y2Lb1PcMh3tYso7FYERStxpdtUgPSkqXgZERrzrtHpFDe05CI/xjZUfmvXsTrKiIXxqvil9hYGISkMyVJjaJUXvZwmgzLtHd7I8z7sNXOw26Ie1DihCy3VzPh5pwZPQId2v2LBABdUogTwVfb7GAV6swP+OMxoffYPdW7AV+82zOYybm3GjKCTiECgYEA57ukyNybLE7h7yeDSFKdkoBnY7RmIW4NRwQNFopb5LlNt9vTm5easuEdDhPlGoNpJ5Ul/ms9pDVDnH2ZkU7IaiMPd/MxQpQ5dos5tRsjb02YwligiD3ZxDBRCNSjcqiR7+5jYb68H2c8bXLtOtZ/dsYyqZmEhH0OsV/2WKMr9bUCgYEAvv9EO9J2UEVBPkEKvhLfH7X8GZK6CROEehNG8qbDqxJ5AbFmo8lzNvbcHjJoiwEMzYU1q5VMhMVMepk1Lk5Q4VRouAMTUY3o8byQMeX7BYHlmmLaXuw8NAFFE43Mr14UGkrWesZR9u1LSw0QPNag3cyL2XxmgpWCmPAwLzQ+obkCgYEAnFukKFOR8CeZkwCaOGZmI7+4AzJp5wyWsOAu5JKexomxwuj0svtsSl5SeHk8ENOyVB7y7+P0R6QY5rJot/7sg5D8kvbouf/Bdhci7OxO0H8PH7MlPkhdc18WjlrLnkXXkojLTdygmp/RyhfNsfGhN8crz/vhynOHQm95jP0sYDECgYBGJ2zgrEVY5pc4TpurhTL/atDWc9ZxTwHx9PKyXh6wz3Ay9v5EWtI+9h2T2eAcbp5NPwifpY8dlXqp7WxjPdDncyGjtT17Tyyo3iH4sgip1TSIqJadFxhl4bGFpSfxohSwM5zkK8QfdrmZL4svTYZ48ZDMqazdeh0mH9MTA5WdwQKBgFO79TUR5fq+u0sBjYW7VLiQ5J6Tq7U0phFjFFjR/eYqkKUtE5K/BdOsSQjwY21TOkoTazyDJiVLEx5pWQueIa0ez1WPNswz7VN2su9N/jwP+G5ILrz1I+nj2PiWXVbfWZ2qd2h0qB27CF7gZ9lQgjg5dQMt4Fmd7f8uzBzrwLQW";
String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydfxVYSMISxqvitww5063ZQFVRzrcRW9a+xQ0Pozz7ve9IeK1h9p7xFwSUtTNi/ki9ZcnZ7wP0xunKrYPVXyUvRz/vSVnovkzvmcSTdqlgtzTAQTJFYL0nmzhnv4RWbcDnVbo+IIlu8g0p6wQv7V8P5EGpbh63+d3q/DYhsbxVVZN1fKjnw/y38/GuqGoiaxkcrf6h65rGO/aRGbX6gbGnRxUgBOEiFGFdkuCx9ACg4cskSme69lDbIBDpsmSbQpUKhTEA4Wv36mqrbee+hGf5sTaqDUHl0/SPgP45ab15J3BeWHB/yXbdK4Z/gPfMFMweOupg54Sm+kJOGmq73cMwIDAQAB";
AlipayConfig alipayConfig = new AlipayConfig();
alipayConfig.setServerUrl("https://openapi.alipaydev.com/gateway.do");
alipayConfig.setAppId("2021000121607425");
alipayConfig.setPrivateKey(privateKey);
alipayConfig.setFormat("json");
alipayConfig.setAlipayPublicKey(alipayPublicKey);
alipayConfig.setCharset("UTF8");
alipayConfig.setSignType("RSA2");
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo("70501111111S001111119");
model.setTotalAmount("9.00");
model.setSubject("大樂透");
//手機網(wǎng)站支付指定productCode為固定值:QUICK_WAP_WAY
model.setProductCode("QUICK_WAP_WAY");
model.setSellerId("2088102147948060");
request.setBizModel(model);
AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
//getBody()返回的就是提交支付的嵌套頁面,返回前端后自動跳轉到支付寶支付操作界面
System.out.println(response.getBody());
if (response.isSuccess()) {
System.out.println("調用成功");
} else {
System.out.println("調用失敗");
}
}
} 4.3 電腦網(wǎng)站支付API
如果我們基于PC電腦網(wǎng)站來實現(xiàn)在線支付,比如相關電商平臺等,可以通過電腦網(wǎng)站支付API進行實現(xiàn):
https://open.alipay.com/api/detail?code=I1080300001000041203#api-detail-content

各個接口有在線文檔和在線調試的案例,可以自行查看。以其中的統(tǒng)一收單下單并支付頁面接口為例說明:
package com.java.sdk.demo;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.AlipayConfig;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.FileItem;
import java.util.Base64;
import java.util.ArrayList;
import java.util.List;
public class AlipayTradePagePay {
public static void main(String[] args) throws AlipayApiException {
String privateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCs5FX6NlZEq8t43tnAT91hcGhTPL6Iieq/e1foh3N0ME601PwtfXzFPac0Qp5qygLtyZkYFY8UiYqdXPQpvO4T4ah5Rus8IiCwGDBpyg3ha6xSWnD7QCvc/YgOJ+ei1XD6F5Y+t2X3gbTCsy1H9wTe9XLh78tcpuhib/4OEwxJfHxEi5fBzQQJBE6vo8pX7mTeeP7f1RBxAgRsswMvCQs1SX362XdD3IRWErf8dUOqV0tT5ahjhXdbFv6fUQmnt+1i00CIAlOPm7vLWslw1qJT4ubZuL0HPQLWEoD3ab0OdgaJvPdoWvnUVzBQqwZgnXHFN5nV1QQbVTe3Q3XWIWTNAgMBAAECggEBAI2JI8WBRCBVj2306cgg2XfSQOWbfdNjLHTzMaUfdemxPk2VapiG+WSzMzV6MBv2Im2tsxHfXFGQw5RNq2ibzT8jZftajmqc+auPMdr42WIn9ls4xPM6tm3kc8Q68MsB9soWEx5mnyf+3A7kBfa7BxbLUvAZkZ7Y2Lb1PcMh3tYso7FYERStxpdtUgPSkqXgZERrzrtHpFDe05CI/xjZUfmvXsTrKiIXxqvil9hYGISkMyVJjaJUXvZwmgzLtHd7I8z7sNXOw26Ie1DihCy3VzPh5pwZPQId2v2LBABdUogTwVfb7GAV6swP+OMxoffYPdW7AV+82zOYybm3GjKCTiECgYEA57ukyNybLE7h7yeDSFKdkoBnY7RmIW4NRwQNFopb5LlNt9vTm5easuEdDhPlGoNpJ5Ul/ms9pDVDnH2ZkU7IaiMPd/MxQpQ5dos5tRsjb02YwligiD3ZxDBRCNSjcqiR7+5jYb68H2c8bXLtOtZ/dsYyqZmEhH0OsV/2WKMr9bUCgYEAvv9EO9J2UEVBPkEKvhLfH7X8GZK6CROEehNG8qbDqxJ5AbFmo8lzNvbcHjJoiwEMzYU1q5VMhMVMepk1Lk5Q4VRouAMTUY3o8byQMeX7BYHlmmLaXuw8NAFFE43Mr14UGkrWesZR9u1LSw0QPNag3cyL2XxmgpWCmPAwLzQ+obkCgYEAnFukKFOR8CeZkwCaOGZmI7+4AzJp5wyWsOAu5JKexomxwuj0svtsSl5SeHk8ENOyVB7y7+P0R6QY5rJot/7sg5D8kvbouf/Bdhci7OxO0H8PH7MlPkhdc18WjlrLnkXXkojLTdygmp/RyhfNsfGhN8crz/vhynOHQm95jP0sYDECgYBGJ2zgrEVY5pc4TpurhTL/atDWc9ZxTwHx9PKyXh6wz3Ay9v5EWtI+9h2T2eAcbp5NPwifpY8dlXqp7WxjPdDncyGjtT17Tyyo3iH4sgip1TSIqJadFxhl4bGFpSfxohSwM5zkK8QfdrmZL4svTYZ48ZDMqazdeh0mH9MTA5WdwQKBgFO79TUR5fq+u0sBjYW7VLiQ5J6Tq7U0phFjFFjR/eYqkKUtE5K/BdOsSQjwY21TOkoTazyDJiVLEx5pWQueIa0ez1WPNswz7VN2su9N/jwP+G5ILrz1I+nj2PiWXVbfWZ2qd2h0qB27CF7gZ9lQgjg5dQMt4Fmd7f8uzBzrwLQW";
String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydfxVYSMISxqvitww5063ZQFVRzrcRW9a+xQ0Pozz7ve9IeK1h9p7xFwSUtTNi/ki9ZcnZ7wP0xunKrYPVXyUvRz/vSVnovkzvmcSTdqlgtzTAQTJFYL0nmzhnv4RWbcDnVbo+IIlu8g0p6wQv7V8P5EGpbh63+d3q/DYhsbxVVZN1fKjnw/y38/GuqGoiaxkcrf6h65rGO/aRGbX6gbGnRxUgBOEiFGFdkuCx9ACg4cskSme69lDbIBDpsmSbQpUKhTEA4Wv36mqrbee+hGf5sTaqDUHl0/SPgP45ab15J3BeWHB/yXbdK4Z/gPfMFMweOupg54Sm+kJOGmq73cMwIDAQAB";
AlipayConfig alipayConfig = new AlipayConfig();
alipayConfig.setServerUrl("https://openapi.alipaydev.com/gateway.do");
alipayConfig.setAppId("2021000121607425");
alipayConfig.setPrivateKey(privateKey);
alipayConfig.setFormat("json");
alipayConfig.setAlipayPublicKey(alipayPublicKey);
alipayConfig.setCharset("UTF8");
alipayConfig.setSignType("RSA2");
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
model.setOutTradeNo("20150320010101001");
model.setTotalAmount("88.88");
model.setSubject("Iphone6 16G");
//電腦網(wǎng)站支付指定productCode為固定值:FAST_INSTANT_TRADE_PAY
model.setProductCode("FAST_INSTANT_TRADE_PAY");
request.setBizModel(model);
AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
//getBody()返回的就是提交支付的嵌套頁面,返回前端后自動跳轉到支付寶支付操作界面
System.out.println(response.getBody());
if (response.isSuccess()) {
System.out.println("調用成功");
} else {
System.out.println("調用失敗");
}
}
} 五,沙箱支付功能實現(xiàn)
我們今天就以電腦網(wǎng)站支付為例進行講解實現(xiàn)。
后臺開發(fā)實現(xiàn)步驟:
5.1:支付功能的實現(xiàn)
1、創(chuàng)建配置類:配置沙箱相關環(huán)境信息 把配置類中相關的信息改為自己的即可。
package com.qiu.config;
import com.qiu.util.general.PropertiesUtil;
import lombok.Data;
import org.springframework.stereotype.Component;
/**
* @author ZNZ
*/
@Data
@Component
public class AlipayConfig {
/**
* 沙箱appId
*/
public static final String APPID = "2021000121607425";
/**
* 請求網(wǎng)關 固定
*/
public static final String URL = "https://openapi.alipaydev.com/gateway.do";
/**
* 設置內(nèi)網(wǎng)穿透回調地址
*/
public static final String CALLBACK = "fcswjw.natappfree.cc";
/**
* 編碼
*/
public static final String CHARSET = "UTF-8";
/**
* 返回格式
*/
public static final String FORMAT = "json";
/**
* RSA2
*/
public static final String SIGNTYPE = "RSA2";
/**
* 異步通知地址
*/
public static final String NOTIFY_URL = "http://"+CALLBACK+"/alipay/notify";
/**
* 同步地址
*/
//使用內(nèi)網(wǎng)穿透進行回調
public static final String RETURN_URL = "http://"+CALLBACK+"/alipay/success";
/**
* 應用私鑰 pkcs8格式
*/
public static final String RSA_PRIVATE_KEY =
"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCs5FX6NlZEq8t43tnAT91hcGhTPL6Iieq/e1foh3N0ME601PwtfXzFPac0Qp5qygLtyZkYFY8UiYqdXPQpvO4T4ah5Rus8IiCwGDBpyg3ha6xSWnD7QCvc/YgOJ+ei1XD6F5Y+t2X3gbTCsy1H9wTe9XLh78tcpuhib/4OEwxJfHxEi5fBzQQJBE6vo8pX7mTeeP7f1RBxAgRsswMvCQs1SX362XdD3IRWErf8dUOqV0tT5ahjhXdbFv6fUQmnt+1i00CIAlOPm7vLWslw1qJT4ubZuL0HPQLWEoD3ab0OdgaJvPdoWvnUVzBQqwZgnXHFN5nV1QQbVTe3Q3XWIWTNAgMBAAECggEBAI2JI8WBRCBVj2306cgg2XfSQOWbfdNjLHTzMaUfdemxPk2VapiG+WSzMzV6MBv2Im2tsxHfXFGQw5RNq2ibzT8jZftajmqc+auPMdr42WIn9ls4xPM6tm3kc8Q68MsB9soWEx5mnyf+3A7kBfa7BxbLUvAZkZ7Y2Lb1PcMh3tYso7FYERStxpdtUgPSkqXgZERrzrtHpFDe05CI/xjZUfmvXsTrKiIXxqvil9hYGISkMyVJjaJUXvZwmgzLtHd7I8z7sNXOw26Ie1DihCy3VzPh5pwZPQId2v2LBABdUogTwVfb7GAV6swP+OMxoffYPdW7AV+82zOYybm3GjKCTiECgYEA57ukyNybLE7h7yeDSFKdkoBnY7RmIW4NRwQNFopb5LlNt9vTm5easuEdDhPlGoNpJ5Ul/ms9pDVDnH2ZkU7IaiMPd/MxQpQ5dos5tRsjb02YwligiD3ZxDBRCNSjcqiR7+5jYb68H2c8bXLtOtZ/dsYyqZmEhH0OsV/2WKMr9bUCgYEAvv9EO9J2UEVBPkEKvhLfH7X8GZK6CROEehNG8qbDqxJ5AbFmo8lzNvbcHjJoiwEMzYU1q5VMhMVMepk1Lk5Q4VRouAMTUY3o8byQMeX7BYHlmmLaXuw8NAFFE43Mr14UGkrWesZR9u1LSw0QPNag3cyL2XxmgpWCmPAwLzQ+obkCgYEAnFukKFOR8CeZkwCaOGZmI7+4AzJp5wyWsOAu5JKexomxwuj0svtsSl5SeHk8ENOyVB7y7+P0R6QY5rJot/7sg5D8kvbouf/Bdhci7OxO0H8PH7MlPkhdc18WjlrLnkXXkojLTdygmp/RyhfNsfGhN8crz/vhynOHQm95jP0sYDECgYBGJ2zgrEVY5pc4TpurhTL/atDWc9ZxTwHx9PKyXh6wz3Ay9v5EWtI+9h2T2eAcbp5NPwifpY8dlXqp7WxjPdDncyGjtT17Tyyo3iH4sgip1TSIqJadFxhl4bGFpSfxohSwM5zkK8QfdrmZL4svTYZ48ZDMqazdeh0mH9MTA5WdwQKBgFO79TUR5fq+u0sBjYW7VLiQ5J6Tq7U0phFjFFjR/eYqkKUtE5K/BdOsSQjwY21TOkoTazyDJiVLEx5pWQueIa0ez1WPNswz7VN2su9N/jwP+G5ILrz1I+nj2PiWXVbfWZ2qd2h0qB27CF7gZ9lQgjg5dQMt4Fmd7f8uzBzrwLQW";
/**
* 沙箱支付寶公鑰
*/
public static final String ALIPAY_PUBLIC_KEY =
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydfxVYSMISxqvitww5063ZQFVRzrcRW9a+xQ0Pozz7ve9IeK1h9p7xFwSUtTNi/ki9ZcnZ7wP0xunKrYPVXyUvRz/vSVnovkzvmcSTdqlgtzTAQTJFYL0nmzhnv4RWbcDnVbo+IIlu8g0p6wQv7V8P5EGpbh63+d3q/DYhsbxVVZN1fKjnw/y38/GuqGoiaxkcrf6h65rGO/aRGbX6gbGnRxUgBOEiFGFdkuCx9ACg4cskSme69lDbIBDpsmSbQpUKhTEA4Wv36mqrbee+hGf5sTaqDUHl0/SPgP45ab15J3BeWHB/yXbdK4Z/gPfMFMweOupg54Sm+kJOGmq73cMwIDAQAB";
private AlipayConfig() {
}
} 2、定義支付接口地址:用戶點擊立即購買后提交請求至下單接口,添加訂單成功后,發(fā)送請求到支付接口,向支付寶發(fā)送支付請求。
前端頁面代碼:在前端工程src/comments/mall/MallPurchase.vue中
createOrder(formName){
this.$refs[formName].validate((valid) => {
if (valid) {
if(this.isVip){
this.order.payPrice = this.order.discountPrice;
}
let loading = this.$loading({lock: true, text: "訂單提交中",background:"rgba(255,255,255,0.1)"});
this.$http.post('/order/add',this.$qs.stringify(this.order,{skipNulls: true})).then((rep)=>{
loading.close();
if(rep.data.code===200){
let orderNo = this.order.orderNo;
let orderName = '新新商城-'+this.productInfo.productType+'-'+this.productInfo.productName+'支付訂單';
let payPrice = this.order.payPrice;
let loading = this.$loading({lock: true, text: "正在跳轉支付頁面",background:"rgba(255,255,255,0.1)"});
this.$http.post('/alipay/create?orderNo='+orderNo+'&orderName='+orderName+'&payPrice='+payPrice).then((response)=>{
loading.close();
const div = document.createElement('div');
div.innerHTML = response.data;
document.body.appendChild(div);
document.forms[document.forms.length-1].submit();
}).catch((err)=>{loading.close();this.$msg.error(err)})
}
}).catch((err)=>{loading.close();this.$msg.error(err);})
this.orderFormVisible=false;
}else{
return false;
}
});
}后端對應的支付接口實現(xiàn):AlipayController
/**
* 創(chuàng)建支付
* @param orderNo
* @param orderName
* @param payPrice
* @return
*/
@ResponseBody
@PostMapping(value = "/create", produces = "text/html;charset=utf-8")
public String create(@RequestParam("orderNo") String orderNo,
@RequestParam("orderName") String orderName,
@RequestParam("payPrice") String payPrice) {
return alipayService.create(orderNo, orderName, payPrice);
}業(yè)務方法實現(xiàn):
/**
* 創(chuàng)建支付訂單
*
* @param orderId 訂單編號
* @param orderName 訂單名稱
* @param payPrice 支付金額
* @return 支付表單
*/
@Override
public String create(String orderId, String orderName, String payPrice) {
//創(chuàng)建支付寶支付連接客戶端
AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID,
AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT,
AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY,
AlipayConfig.SIGNTYPE);
AlipayTradeWapPayRequest payRequest = new AlipayTradeWapPayRequest();
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo(orderId);
model.setSubject(orderName);
model.setTotalAmount(payPrice);
model.setProductCode(PRODUCTCODE);
payRequest.setBizModel(model);
payRequest.setReturnUrl(AlipayConfig.RETURN_URL);
payRequest.setNotifyUrl(AlipayConfig.NOTIFY_URL);
try {
return client.pageExecute(payRequest).getBody();
} catch (AlipayApiException e) {
log.error("[支付寶] 支付失敗", e);
}
return null;
}此接口返回的字符串其實是一個FORM表單,并執(zhí)行自動提交:所以接口執(zhí)行完后自動跳轉到支付寶支付平臺頁面。
<form name="punchout_form" method="post" action="https://openapi.alipaydev.com/gateway.do?charset=UTF-8&method=alipay.trade.wap.pay&sign=bdVLwcblQMIpdDuHtLtrT6J9KK4IH0Y0FgfS4TVO61VBrG8xfKHitFafkoNAKL6CvPjEoxAhr2cSjluRirt6FpLAffrTd0iVHctBD6JBoK3oUy1j472c8onqZ9x5y896bi3zRObobc7ygJEvvR04RdwIAQPPHObkKjvNEta5qqHOW9S%2FApZSBoPqBZozkijWXhsQDlCmIpvd%2FH4LlHAcpQe67owOAujsJezrGA2cg7Exm50rUGyiAVhA3ICsqi9PVFWU4FbD3jdELHTD3%2BgP2l7%2FLzWMeEIUj9Y0vw6wU9xI%2FhPl1emZGt9iUHLce3NetowYh96kdR6vnfYSYBZhJw%3D%3D&return_url=http%3A%2F%2Ft2vnvc.natappfree.cc%2Falipay%2Fsuccess¬ify_url=http%3A%2F%2Ft2vnvc.natappfree.cc%2Falipay%2Fnotify&version=1.0&app_id=2021000121607425&sign_type=RSA2×tamp=2022-07-17+16%3A09%3A55&alipay_sdk=alipay-sdk-java-4.10.192.ALL&format=json">
<input type="hidden" name="biz_content" value="{"out_trade_no":"2271716507374","product_code":"QUICK_WAP_WAY","subject":"新新商城-生活家電-米家互聯(lián)網(wǎng)洗烘一體機Pro 20kg支付訂單","total_amount":"3299.00"}">
<input type="submit" value="立即支付" style="display:none" >
</form>
<script>document.forms[0].submit();</script>然后就進入到了我們文章開頭展示的支付流程頁面:

可以對照著沙箱的商家賬戶和買家賬戶的錢數(shù)來看看是否實現(xiàn)了買家賬戶扣款和商家賬戶收款的功能。

5.2.回調本地接口更改支付狀態(tài)
在線支付成功了,買家支付寶的賬戶的錢也已經(jīng)轉移到了商家的賬戶,可是本地應用怎么知道支付是否成功呢?我們在本地的應用中也需要根據(jù)支付成功與否來更改訂單的支付狀態(tài),這就需要我們定義回調通知接口來實現(xiàn)。
我們在AlipayConfig中已經(jīng)定義了回調的接口地址:
/** * 異步通知地址 */ public static final String NOTIFY_URL = "http://"+CALLBACK+"/alipay/notify"; ``` 那么這個接口主要實現(xiàn)的功能就是根據(jù)支付的結果來實現(xiàn)訂單狀態(tài)的更新: 在AlipayController中定義alipay/notify接口:
/**
* @param map
*/
@ResponseBody
@PostMapping(value = "/notify")
public String payNotify(@RequestParam Map<String, String> map) {
if (TRADE_SUCCESS.equals(map.get(TRADE_STATUS))) {
String payTime = map.get(TRADE_TIME);
String tradeNo = map.get(OUT_TRADE_NO);
String tradeName = map.get(TRADE_NAME);
String payAmount = map.get(TRADE_AMOUNT);
log.info("[支付成功] {交易時間:{},訂單號:{},訂單名稱:{},交易金額:{}}", payTime, tradeNo, tradeName, payAmount);
}
return "success";
}/**
* 支付回調成功
* @param map
* @param response
*/
@GetMapping(value = "/success")
public void success(@RequestParam Map<String, String> map, HttpServletResponse response) {
try {
String tradeNo = map.get(OUT_TRADE_NO);
if (tradeNo.contains(VIP)) {
openMember(response, tradeNo);
} else {
updateProductStatus(response, tradeNo);
}
} catch (IOException e) {
e.printStackTrace();
}
} /**
* 支付成功,更新商品狀態(tài)為待發(fā)貨
*
* @param response HTTP響應
* @param tradeNo 訂單編號
* @throws IOException IO異常信息
*/
private void updateProductStatus(HttpServletResponse response, String tradeNo) throws IOException {
Integer orderId = orderService.selectIdByKey(orderNo);
Order order = new Order();
order.setOrderId(orderId);
order.setOrderState("待發(fā)貨");
orderService.updateById(order);
//跳轉到我的訂單頁面
response.sendRedirect("http://localhost:8080/#/myOrder");
} 六.總結
支付寶沙箱支付給了我們一個模擬支付寶在線支付的環(huán)境來進行測試,在本地通過沙箱支付測試成功后,可以在實際應用中,將對應的賬戶修改為自己企業(yè)賬號申請的對公支付的賬戶信息即可,支付寶對整個開發(fā)提供的文檔和案例也是比較豐富的,對于我們?nèi)粘W習或做一些學校要求的簡單課設來講,這篇文章所講解的基本支付功能應該能幫到大家的。如果還需要實現(xiàn)其它的像退款等相關功能,查看文中給的API接口地址,根據(jù)官方案例進行修改即可。