支付寶支付功能的實現(沙箱測試)

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

理解思路圖

在這裏插入圖片描述

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