1.登陸支付寶開放平臺
進入開發者中心
點擊 研發服務
掃碼 下載沙箱版支付寶
2.設置公鑰私鑰
然後下載密鑰生成工具
生成完以後把(應用公鑰)粘貼到沙箱環境中
下載沙箱版支付寶,賬號密碼在這
沙箱環境配置完畢
3.配置服務器
要添加一個支付寶的SDK的依賴
<!--支付寶的SDK-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.3.0.ALL</version>
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
</exclusions>
</dependency>
4.創建一個pay.properties配置文件
注意要在spring配置文件中加載
改三個,用戶私鑰,阿里公鑰,AAPID
#支付寶網關地址
serverUrl=https://openapi.alipaydev.com/gateway.do
#應用編號 自己的AAPID
appId=2016091300500103
#用戶私鑰 在公鑰私鑰生成工具裏面粘貼
privateKey=用戶私鑰
#阿里公鑰 在開放平臺沙箱環境裏面查看 然後 粘貼
alipayPulicKey=阿里公鑰
#傳遞數據格式json
format=json
#編碼
charset=utf-8
#加密方式
signType=RSA2
5.在spring配置文件中配置支付寶客戶端對象的bean(記得掃描properties配置文件)
<!--配置支付寶客戶端對象-->
<bean id="payClient" class="com.alipay.api.DefaultAlipayClient">
<constructor-arg name="serverUrl" value="${serverUrl}"/>
<constructor-arg name="appId" value="${appId}"/>
<constructor-arg name="privateKey" value="${privateKey}"/>
<constructor-arg name="format" value="${format}"/>
<constructor-arg name="charset" value="${charset}"/>
<constructor-arg name="alipayPublicKey" value="${alipayPulicKey}"/>
<constructor-arg name="signType" value="${signType}"/>
</bean>
6.編寫一個預下單的代碼
具體思路可查看這個
1.寫一個接口pay_interface
參數1:訂單編號 參數2:支付金額
package com.offcn.pay.service;
import java.util.Map;
/**
* 支付寶支付接口
* @author Administrator
*
*/
public interface AliPayService {
/**
* 生成支付寶支付二維碼
* @param out_trade_no 訂單號
* @param total_fee 金額(分)
* @return
*/
public Map createNative(String out_trade_no,String total_fee);
}
2.寫實現類pay_service
傳入參數
參數1:訂單編號 參數2:支付金額
package com.offcn.pay.service.impl;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.offcn.pay.service.AliPayService;
import org.springframework.beans.factory.annotation.Autowired;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
public class AliPayServiceImpl implements AliPayService {
@Autowired
AlipayClient alipayClient;
@Override
public Map createNative(String out_trade_no, String total_fee) {
Map<String,String> map=new HashMap<String, String>();
//創建預下單請求對象
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
//轉換下單金額按照元,因爲傳進來的金額單位是 分
long total = Long.parseLong(total_fee);
BigDecimal bigTotal = BigDecimal.valueOf(total);
BigDecimal cs = BigDecimal.valueOf(100d);
BigDecimal bigYuan = bigTotal.divide(cs);
System.out.println("預下單金額:"+bigYuan.doubleValue());
request.setBizContent("{" +
" \"out_trade_no\":\""+out_trade_no+"\"," + //商家訂單號
" \"total_amount\":\""+bigYuan.doubleValue()+"\"," + //與下單金額 單位 :元
" \"subject\":\"優樂選商城商品\"," + //商家標題
" \"store_id\":\"xa_001\"," + //店鋪編號
" \"timeout_express\":\"90m\"}");//設置業務參數 預下單失效時間 90m
//3.發出預下單業務請求
try {
AlipayTradePrecreateResponse response = alipayClient.execute(request);
//4.從相應對象讀取相應結果
String code = response.getCode();
System.out.println("響應碼:"+code);
//全部的響應結果
String body = response.getBody();
System.out.println("返回結果:"+body);
if(code!=null&&code.equals("10000")){
//獲取響應訂單二維碼 並且 封裝進去
map.put("qrcode", response.getQrCode());
//訂單編號
map.put("out_trade_no", response.getOutTradeNo());
//訂單金額
map.put("total_fee",total_fee);
System.out.println("qrcode:"+response.getQrCode());
System.out.println("out_trade_no:"+response.getOutTradeNo());
System.out.println("total_fee:"+total_fee);
}else{
System.out.println("預下單接口調用失敗:"+body);
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
return map;
}
}
7.測試訪問接口
使用IdWorker工具類生成訂單編號,這裏測試金額寫死 寫成1
@RequestMapping("/createNative")
public Map createNative(){
//生成訂單編號
long out_trade_no = idWorker.nextId();
Map map=payService.createNative(out_trade_no ,1+"");
}
return map;
}
訪問接口進行測試
這個url地址就是生成二維碼的地址,掃描二維碼就可以支付了
關於二維碼生成的方法,看我的另一篇博文
鏈接: 查看地址.
如何判斷支付是否成功
思路:在生成二維碼後,就立馬訪問判斷支付是否成功的接口,並用一個死循環,不停的查詢狀態,可以設置可最大循環次數,超過次數就說明支付超時,是通過訂單編號來查詢的
8.實現類方法
public Map queryPayStatus(String out_trade_no){
System.out.println("需要查詢支付狀態的訂單編號:"+out_trade_no);
Map map=new HashMap();
//1、創建交易查詢請求對象
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
//2、設置查詢參數
request.setBizContent("{" +
" \"out_trade_no\":\""+out_trade_no+"\"," +//設置電商平臺生成訂單編號
" \"trade_no\":\"\"}");//支付寶生成交易流水號
//發出查詢
try {
AlipayTradeQueryResponse response = payClient.execute(request);
//獲取響應狀態碼
String code = response.getCode();
System.out.println("交易查詢返回結果:"+response.getBody());
if(code!=null&&code.equals("10000")){
//判斷交易狀態 交易狀態:WAIT_BUYER_PAY(交易創建,等待買家付款)、TRADE_CLOSED(未付款交易超時關閉,或支付完成後全額退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易結束,不可退款)
String tradeStatus = response.getTradeStatus();
//封裝交易狀態
map.put("tradestatus",response.getTradeStatus());
//支付寶生成交易流水號
map.put("trade_no",response.getTradeNo());
//訂單編號
map.put("out_trade_no",out_trade_no);
}else {
System.out.println("交易查詢失敗:"+code);
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
return map;
}
map裏就封裝了支付的狀態,一共就四個值 //交易狀態:WAIT_BUYER_PAY(交易創建,等待買家付款)、
TRADE_CLOSED(未付款交易超時關閉,或支付完成後全額退款)、
TRADE_SUCCESS(交易支付成功)、
TRADE_FINISHED(交易結束,不可退款)
接口
這裏採用while(true)循環,不斷地去查詢支付狀態,可以設置個最大循環次數,支付結果用Map封裝
//查詢交易狀態
@RequestMapping("/queryPayStatus")
public Result queryPayStatus(String out_trade_no){
Result result=null;
int x=0;
while (true) {
//調用實現類方法
Map map = payService.queryPayStatus(out_trade_no);
if (map == null) {
//查詢異常,不在查詢
result = new Result(false, "請求交易狀態查詢服務異常");
//跳出循環
break;
}
//判斷返回狀態
//交易狀態:WAIT_BUYER_PAY(交易創建,等待買家付款)、
// TRADE_CLOSED(未付款交易超時關閉,或支付完成後全額退款)、
// TRADE_SUCCESS(交易支付成功)、
// TRADE_FINISHED(交易結束,不可退款)
//判斷交易狀態爲 TRADE_CLOSED(未付款交易超時關閉,或支付完成後全額退款)
if (map.get("tradestatus") != null && map.get("tradestatus").equals("TRADE_CLOSED")) {
result = new Result(false, "未付款交易超時關閉,或支付完成後全額退款");
break;
}
if (map.get("tradestatus") != null && map.get("tradestatus").equals("TRADE_SUCCESS")) {
result = new Result(true, "交易支付成功");
//調用訂單服務 修改訂單狀態
orderService.uodateOrderStatus(out_trade_no,map.get("trade_no")+"");
break;
}
if (map.get("tradestatus") != null && map.get("tradestatus").equals("TRADE_FINISHED")) {
result = new Result(false, "交易結束,不可退款");
break;
}
if (map.get("tradestatus") != null && map.get("tradestatus").equals("TRADE_CLOSED")) {
result = new Result(false, "未付款交易超時關閉,或支付完成後全額退款");
break;
}
x++;
if(x>=99){
result=new Result(false,"二維碼超時");
break;
}
//爲了防止一直查詢,網關屏蔽掉,可以讓查詢線程等待3秒
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result;
}