支付寶支付的實現

工程搭建

創建youxin_pay_interface的jar工程,依賴pojo
創建youxin_pay_service的war工程,除了項目依賴,需要加入支付的依賴
在這裏插入圖片描述

<!-- 支付寶支付所需類庫包 -->
<dependency>
	<groupId>com.alipay.sdk</groupId>
	<artifactId>alipay-sdk-java</artifactId>
	<version>3.4.27.ALL</version>
</dependency>

配置sring-pay-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans.xsd 
    		http://www.springframework.org/schema/context 
    		http://www.springframework.org/schema/context/spring-context.xsd
    		http://www.springframework.org/schema/aop
    		http://www.springframework.org/schema/aop/spring-aop.xsd
    		http://www.springframework.org/schema/tx
    		http://www.springframework.org/schema/tx/spring-tx.xsd">

	<context:component-scan base-package="com.youxin"/>

	<!-- 創建AlipayClient -->
	<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="alipayPublicKey" value="${alipayPulicKey}"/>
		<constructor-arg name="format" value="${format}"/>
		<constructor-arg name="charset" value="${charset}"/>
		<constructor-arg name="signType" value="${signType}"/>
	</bean>
</beans>

配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         id="WebApp_ID" version="3.1">

  <!-- spring監聽 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- spring配置文件初始化 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:spring-*.xml</param-value>
  </context-param>

</web-app>

配置alipay.properties

serverUrl=https://openapi.alipay.com/gateway.do
appId=*******
privateKey=生成的應用私鑰
alipayPulicKey=支付寶公鑰
format=json
charset=utf-8
signType=RSA2

注意
在spring的配置文件中加載alipay.properties(我們已經設置依賴了common層導入所有properties)

向支付寶發起預支付,前端接收預支付返回信息生成付款二維碼

Map用來存儲預支付響應信息,如果發起預支付成功,將訂單號和支付總金額以及二維碼碼串返回給前端頁面
在這裏插入圖片描述
響應結果示例
在這裏插入圖片描述
service層代碼

@Autowired
private AlipayClient alipayClient;

public Map createNative(String out_trade_no, String total_fee) {
    Map<String, String> map = new HashMap<String, String>();
    // 創建預下單請求對象
    AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
    // 設置業務參數
    request.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
            + "\"total_amount\":\"" + total_fee + "\","
            + "\"subject\":\"在線支付\","
            + "\"timeout_express\":\"90m\"}");
    // 發出預下單業務請求
    try {
        AlipayTradePrecreateResponse response = alipayClient.execute(request);
        // 從相應對象讀取相應結果
        String code = response.getCode();
        System.out.println("支付寶接口響應碼:" + code);
        // 全部的響應結果
        String body = response.getBody();
        System.out.println("支付寶返回結果:" + body);

        if (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;
}

檢測支付狀態

實現思路:
通過AlipayClient實現對交易查詢接口(alipay.trade.query)的調用。阿里支付api
交易查詢接口請求關鍵參數:
在這裏插入圖片描述
響應關鍵參數
在這裏插入圖片描述
service層

public Map queryPayStatus(String out_trade_no) {
    Map<String, String> map = new HashMap<String, String>();
    AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
    // 設置業務參數
    request.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
            + "\"trade_no\":\"\"}");

    // 發出請求
    try {
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        String code = response.getCode();

        System.out.println("查詢交易狀態--返回值1:" + code);
        System.out.println("查詢交易狀態--返回值2:" + response.getBody());

        if (code.equals("10000")) {
            map.put("out_trade_no", out_trade_no);
            map.put("tradestatus", response.getTradeStatus());
        }
    } catch (AlipayApiException e) {
        e.printStackTrace();
    }
    return map;
}

controller層
先調用service層的方法去查詢支付狀態,service層會將查詢出來的結果封裝進map集合返回,controller拿到集合中交易狀態,懟它進行判斷
支付狀態的查詢如果是等待買家付款就需要一直查詢支付狀態,通過循環的方式實現

/*
查詢支付狀態
 */
public Result queryPayStatus(String out_trade_no){
    Result result = null;
    int x = 0;
    while (true) {
        Map map = new HashMap();
        try {
            map = payService.queryPayStatus(out_trade_no);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String tradestatus = (String) map.get("tradestatus");
        if (tradestatus!=null && tradestatus.equals("TRADE_CLOSED") ){
            result = new Result(false,"未付款交易超時關閉,或支付完成後全額退款");
            break;
        }
        if (tradestatus!=null && tradestatus.equals("TRADE_SUCCESS")){
            result = new Result(true,"支付成功");
            break;
        }
        if (tradestatus!=null && tradestatus.equals("TRADE_FINISHED")){
            result = new Result(false,"交易結束,不可退款");
            break;
        }
        //時間間隔三秒再去循環校驗支付狀態
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 定義一個過期時間,可以參考登錄信息的過期時間
        // 爲了測試,可以設置30秒的過期時間,即 x 約 10次,實際時可以設置和用戶登錄過期時間
        x++;
        if(x>10){
            result = new Result(false,"二維碼已失效!");
            break;
        }

    }
    return result;
}

支付日誌

(1)系統中無法查詢到支付記錄
(2)支付後訂單狀態沒有改變
實現思路:
(1)在用戶下訂單時就向支付日誌表添加一條記錄,信息包括支付總金額、訂單ID(多個)、用戶ID、下單時間等信息,支付狀態爲0(未支付)
(2)生成的支付日誌對象放入redis中,以用戶ID作爲key,這樣在生成支付二維碼時就可以從redis中提取支付日誌對象中的金額和訂單號。
(3)當用戶支付成功後,修改支付日誌的支付狀態爲1(已支付),並記錄支付寶傳遞給我們的交易流水號。根據訂單ID(多個)修改訂單的狀態爲2(已付款)。
在創建的訂單同時創建支付日誌
在這裏插入圖片描述
在這裏插入圖片描述
支付控制層從redis中獲取訂單號和總金額生成支付二維碼
在這裏插入圖片描述
在這裏插入圖片描述
監聽支付狀態的同時,如果支付成功,更新支付日誌和訂單狀態
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章