欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java配置沙箱支付的實(shí)現(xiàn)示例

 更新時(shí)間:2025年08月24日 10:40:12   作者:hqxstudying  
箱支付是支付平臺(tái)提供的模擬支付環(huán)境,包含測(cè)試用的 APPID、密鑰、網(wǎng)關(guān)、測(cè)試賬號(hào)等資源,下面就來介紹一下如何實(shí)現(xiàn),感興趣的可以了解一下

在 Java 項(xiàng)目中集成沙箱支付(以支付寶、微信支付這兩大主流平臺(tái)為例)是支付功能開發(fā)的必經(jīng)環(huán)節(jié),用于在測(cè)試環(huán)境驗(yàn)證支付流程的正確性,避免真實(shí)資金交易風(fēng)險(xiǎn)。以下是詳細(xì)的集成步驟,包含前期準(zhǔn)備、環(huán)境搭建、核心功能實(shí)現(xiàn)及測(cè)試驗(yàn)證。

一、沙箱支付概述

沙箱支付是支付平臺(tái)(如支付寶、微信支付)提供的模擬支付環(huán)境,包含測(cè)試用的 APPID、密鑰、網(wǎng)關(guān)、測(cè)試賬號(hào)等資源,其接口邏輯與正式環(huán)境一致,但交易僅為模擬,不涉及真實(shí)資金。
核心作用:驗(yàn)證支付下單、支付跳轉(zhuǎn)、異步通知、訂單查詢等全流程的正確性。

二、支付寶沙箱支付集成步驟(詳細(xì))

2.1 前期準(zhǔn)備:獲取沙箱環(huán)境參數(shù)

  1. 注冊(cè)支付寶開放平臺(tái)賬號(hào)
    訪問 支付寶開放平臺(tái),注冊(cè)開發(fā)者賬號(hào)并完成實(shí)名認(rèn)證(個(gè)人開發(fā)者即可)。

  2. 創(chuàng)建應(yīng)用并開通沙箱

    • 進(jìn)入「控制臺(tái)」→「開發(fā)者中心」→「網(wǎng)頁 & 移動(dòng)應(yīng)用」,點(diǎn)擊「創(chuàng)建應(yīng)用」(選擇 “自研” 類型)。
    • 應(yīng)用創(chuàng)建后,在應(yīng)用詳情頁的「開發(fā)設(shè)置」中,開啟 “沙箱” 功能(沙箱環(huán)境默認(rèn)自動(dòng)生成,無需審核)。
  3. 獲取核心參數(shù)
    在「沙箱環(huán)境」頁面獲取以下參數(shù)(后續(xù)代碼中需使用):

    • APPID:沙箱應(yīng)用唯一標(biāo)識(shí)(如2021000000000000)。
    • 支付寶網(wǎng)關(guān):沙箱環(huán)境專用網(wǎng)關(guān) https://openapi.alipaydev.com/gateway.do(正式環(huán)境為https://openapi.alipay.com/gateway.do)。
    • 密鑰:需生成 RSA2 密鑰對(duì)(公鑰 + 私鑰):
      • 下載 支付寶開放平臺(tái)開發(fā)助手,生成 RSA2(2048 位)密鑰對(duì)。
      • 將生成的應(yīng)用公鑰上傳到沙箱環(huán)境的「密鑰管理」中,支付寶會(huì)自動(dòng)生成對(duì)應(yīng)的支付寶公鑰(需保存,用于驗(yàn)簽)。
      • 本地保留應(yīng)用私鑰(用于接口簽名)。
  4. 獲取沙箱測(cè)試賬號(hào)
    在沙箱環(huán)境頁面可獲取測(cè)試用的買家賬號(hào)、買家支付密碼、測(cè)試銀行卡信息(用于模擬支付)。

2.2 環(huán)境搭建:引入依賴與配置

  1. 引入支付寶 Java SDK
    在項(xiàng)目的pom.xml(Maven)中添加依賴(最新版本可參考支付寶 SDK 文檔):

    <dependency>
        <groupId>com.alipay.sdk</groupId>
        <artifactId>alipay-sdk-java</artifactId>
        <version>4.38.0.ALL</version>
    </dependency>
    
  2. 配置沙箱參數(shù)
    application.properties(或application.yml)中配置參數(shù):

    # 支付寶沙箱配置
    alipay.app-id=你的沙箱APPID
    alipay.private-key=你的應(yīng)用私鑰(生成的私鑰,不含換行)
    alipay.public-key=支付寶公鑰(上傳應(yīng)用公鑰后生成的)
    alipay.gateway-url=https://openapi.alipaydev.com/gateway.do
    alipay.format=json
    alipay.charset=UTF-8
    alipay.sign-type=RSA2
    
  3. 創(chuàng)建配置類
    編寫 Java 配置類,初始化支付寶客戶端(AlipayClient):

    @Configuration
    public class AlipayConfig {
        @Value("${alipay.app-id}")
        private String appId;
        @Value("${alipay.private-key}")
        private String privateKey;
        @Value("${alipay.public-key}")
        private String publicKey;
        @Value("${alipay.gateway-url}")
        private String gatewayUrl;
        @Value("${alipay.format}")
        private String format;
        @Value("${alipay.charset}")
        private String charset;
        @Value("${alipay.sign-type}")
        private String signType;
    
        @Bean
        public AlipayClient alipayClient() {
            // 初始化支付寶客戶端(沙箱環(huán)境)
            return new DefaultAlipayClient(
                gatewayUrl, appId, privateKey, format, charset, publicKey, signType
            );
        }
    }
    

2.3 核心功能實(shí)現(xiàn)

(1)創(chuàng)建支付訂單(電腦網(wǎng)站支付為例)

用戶下單后,調(diào)用支付寶接口生成支付表單,前端跳轉(zhuǎn)至沙箱支付頁面。

@Service
public class AlipayService {
    @Autowired
    private AlipayClient alipayClient;

    /**
     * 創(chuàng)建支付寶支付訂單
     * @param outTradeNo 商戶訂單號(hào)(唯一)
     * @param totalAmount 訂單金額(單位:元)
     * @param subject 訂單標(biāo)題
     * @param returnUrl 支付成功后同步跳轉(zhuǎn)地址(商戶系統(tǒng)頁面)
     * @param notifyUrl 支付成功后異步通知地址(商戶系統(tǒng)接口)
     * @return 支付表單HTML(前端自動(dòng)提交跳轉(zhuǎn))
     * @throws AlipayApiException 接口調(diào)用異常
     */
    public String createPayOrder(String outTradeNo, String totalAmount, String subject, 
                                 String returnUrl, String notifyUrl) throws AlipayApiException {
        // 1. 創(chuàng)建支付請(qǐng)求對(duì)象(電腦網(wǎng)站支付用AlipayTradePagePayRequest)
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        // 設(shè)置同步回調(diào)地址(用戶支付成功后跳轉(zhuǎn))
        request.setReturnUrl(returnUrl);
        // 設(shè)置異步通知地址(支付寶主動(dòng)推送支付結(jié)果)
        request.setNotifyUrl(notifyUrl);

        // 2. 組裝請(qǐng)求參數(shù)(JSON格式)
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", outTradeNo); // 商戶訂單號(hào)(自定義,需唯一)
        bizContent.put("total_amount", totalAmount); // 訂單金額(精確到分)
        bizContent.put("subject", subject); // 訂單標(biāo)題
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY"); // 產(chǎn)品碼(固定值)
        request.setBizContent(bizContent.toString());

        // 3. 調(diào)用支付寶接口,獲取支付表單
        AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
        if (response.isSuccess()) {
            return response.getBody(); // 返回HTML表單,前端渲染后自動(dòng)提交
        } else {
            throw new RuntimeException("創(chuàng)建支付訂單失敗:" + response.getMsg());
        }
    }
}
(2)編寫控制器接口

提供給前端調(diào)用,觸發(fā)支付流程:

@RestController
@RequestMapping("/pay/alipay")
public class AlipayController {
    @Autowired
    private AlipayService alipayService;

    /**
     * 發(fā)起支付寶支付
     */
    @PostMapping("/create")
    public Result<String> createPay(@RequestBody PayDTO payDTO) {
        try {
            // 生成唯一商戶訂單號(hào)(可基于UUID或雪花算法)
            String outTradeNo = "ORDER_" + System.currentTimeMillis();
            // 調(diào)用服務(wù)生成支付表單
            String payForm = alipayService.createPayOrder(
                outTradeNo, 
                payDTO.getTotalAmount(), // 金額(如"0.01"元)
                payDTO.getSubject(), // 訂單標(biāo)題(如"測(cè)試訂單")
                "http://localhost:8080/pay/success", // 同步回調(diào)地址(前端頁面)
                "http://你的服務(wù)器公網(wǎng)地址/pay/alipay/notify" // 異步通知地址(需公網(wǎng)可訪問)
            );
            return Result.success(payForm);
        } catch (Exception e) {
            return Result.error("支付創(chuàng)建失敗:" + e.getMessage());
        }
    }
}
(3)處理異步支付通知(核心?。?/h6>

支付寶在用戶支付成功后,會(huì)主動(dòng)向notifyUrl發(fā)送 POST 請(qǐng)求(攜帶支付結(jié)果),商戶需驗(yàn)證通知合法性并更新訂單狀態(tài)。

@PostMapping("/notify")
public String handleNotify(HttpServletRequest request) {
    try {
        // 1. 獲取請(qǐng)求參數(shù)(支付寶通知的所有參數(shù))
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String key : requestParams.keySet()) {
            String[] values = requestParams.get(key);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            params.put(key, valueStr);
        }

        // 2. 驗(yàn)證簽名(關(guān)鍵!防止偽造通知)
        boolean signVerified = AlipaySignature.rsaCheckV1(
            params, 
            alipayPublicKey, // 支付寶公鑰(配置文件中獲取)
            charset, // 編碼(UTF-8)
            signType // 簽名類型(RSA2)
        );

        if (!signVerified) {
            return "fail"; // 簽名驗(yàn)證失敗,返回fail(支付寶會(huì)重試通知)
        }

        // 3. 驗(yàn)證通知參數(shù)(確保支付狀態(tài)為成功)
        String tradeStatus = params.get("trade_status");
        if (!"TRADE_SUCCESS".equals(tradeStatus)) {
            return "fail"; // 支付未成功,不處理
        }

        // 4. 處理業(yè)務(wù)邏輯(更新訂單狀態(tài)、記錄支付信息等)
        String outTradeNo = params.get("out_trade_no"); // 商戶訂單號(hào)
        String tradeNo = params.get("trade_no"); // 支付寶交易號(hào)
        String totalAmount = params.get("total_amount"); // 支付金額

        // 示例:調(diào)用訂單服務(wù)更新狀態(tài)為“已支付”
        orderService.updateOrderStatus(outTradeNo, tradeNo, totalAmount);

        // 5. 處理完成,返回"success"(支付寶收到后停止重試)
        return "success";
    } catch (Exception e) {
        // 異常時(shí)返回fail,支付寶會(huì)重試
        return "fail";
    }
}
(4)查詢支付狀態(tài)(可選)

用于主動(dòng)查詢訂單支付結(jié)果(如用戶未同步跳轉(zhuǎn)時(shí)):

public String queryPayStatus(String outTradeNo) throws AlipayApiException {
    AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
    JSONObject bizContent = new JSONObject();
    bizContent.put("out_trade_no", outTradeNo); // 商戶訂單號(hào)
    request.setBizContent(bizContent.toString());

    AlipayTradeQueryResponse response = alipayClient.execute(request);
    if (response.isSuccess()) {
        return response.getTradeStatus(); // 返回狀態(tài)(如TRADE_SUCCESS、WAIT_BUYER_PAY)
    } else {
        throw new RuntimeException("查詢支付狀態(tài)失敗:" + response.getMsg());
    }
}

2.4 測(cè)試流程

  1. 前端處理:將后端返回的payForm(HTML 表單)渲染到頁面,表單會(huì)自動(dòng)提交至支付寶沙箱支付頁面。
  2. 模擬支付
    • 使用沙箱環(huán)境提供的買家賬號(hào)登錄(非開發(fā)者賬號(hào))。
    • 輸入沙箱買家支付密碼(如111111),完成支付。
  3. 驗(yàn)證結(jié)果
    • 同步跳轉(zhuǎn):支付成功后跳轉(zhuǎn)到returnUrl(前端成功頁)。
    • 異步通知:支付寶會(huì)向notifyUrl發(fā)送通知,驗(yàn)證訂單狀態(tài)是否更新為 “已支付”。
    • 主動(dòng)查詢:調(diào)用queryPayStatus接口,確認(rèn)狀態(tài)為TRADE_SUCCESS。

三、微信支付沙箱支付集成步驟(簡(jiǎn)要)

微信支付沙箱流程與支付寶類似,但細(xì)節(jié)略有不同(如需要證書、沙箱密鑰需動(dòng)態(tài)獲?。?。

3.1 前期準(zhǔn)備

  1. 注冊(cè) 微信支付商戶平臺(tái),獲取商戶號(hào)(mch_id)。
  2. 申請(qǐng) API 證書(在商戶平臺(tái)的「賬戶中心→API 安全」中下載,包含apiclient_cert.p12等文件)。
  3. 生成 API 密鑰(32 位,用于簽名),并在商戶平臺(tái)配置。

3.2 核心差異點(diǎn)

  1. 沙箱密鑰獲取
    微信沙箱需先調(diào)用沙箱簽名接口獲取沙箱專用密鑰(sandbox_signkey),后續(xù)接口用該密鑰簽名。

    // 示例:獲取沙箱密鑰
    WXPayConfig config = new MyWXPayConfig(); // 自定義配置類(含商戶號(hào)、API密鑰等)
    WXPay wxPay = new WXPay(config);
    Map<String, String> params = new HashMap<>();
    params.put("mch_id", config.getMchID());
    params.put("nonce_str", WXPayUtil.generateNonceStr());
    params.put("sign", WXPayUtil.generateSignature(params, config.getKey()));
    Map<String, String> result = wxPay.sandboxnewKey(params);
    String sandboxSignKey = result.get("sandbox_signkey"); // 沙箱密鑰
    
  2. 接口調(diào)用
    微信支付接口(如 JSAPI 支付)需使用沙箱網(wǎng)關(guān)(https://api.mch.weixin.qq.com/sandboxnew/),并通過WXPay類(微信 SDK)調(diào)用。

    // 示例:創(chuàng)建JSAPI支付訂單
    Map<String, String> data = new HashMap<>();
    data.put("body", "測(cè)試訂單");
    data.put("out_trade_no", outTradeNo);
    data.put("total_fee", "1"); // 金額(單位:分)
    data.put("spbill_create_ip", "127.0.0.1");
    data.put("notify_url", "http://你的公網(wǎng)地址/pay/wx/notify");
    data.put("trade_type", "JSAPI");
    data.put("openid", "用戶的openid"); // 微信用戶唯一標(biāo)識(shí)
    
    WXPay wxPay = new WXPay(new SandboxWXPayConfig(sandboxSignKey)); // 使用沙箱配置
    Map<String, String> result = wxPay.unifiedOrder(data);
    
  3. 異步通知處理
    與支付寶類似,需驗(yàn)證簽名(用沙箱密鑰),并返回"<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>"確認(rèn)接收。

四、注意事項(xiàng)

  1. 簽名驗(yàn)證:必須嚴(yán)格驗(yàn)證支付平臺(tái)的通知簽名,防止惡意請(qǐng)求偽造支付結(jié)果。
  2. 回調(diào)地址:異步通知地址(notifyUrl)需公網(wǎng)可訪問(本地測(cè)試可使用 ngrok 等工具映射端口)。
  3. 冪等性處理:同一訂單可能收到多次異步通知,需確保訂單狀態(tài)更新邏輯冪等(如通過訂單號(hào)判斷是否已處理)。
  4. 沙箱與正式環(huán)境隔離:通過配置文件區(qū)分沙箱和正式環(huán)境的參數(shù)(網(wǎng)關(guān)、密鑰等),避免混淆。
  5. 異常處理:接口調(diào)用超時(shí)、網(wǎng)絡(luò)錯(cuò)誤等情況需重試,避免訂單狀態(tài)不一致。

通過以上步驟,可在 Java 項(xiàng)目中完整集成沙箱支付,驗(yàn)證支付全流程的正確性后,再切換至正式環(huán)境即可上線。

到此這篇關(guān)于java配置沙箱支付的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)java 沙箱支付內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Maven打包跳過測(cè)試的5種方式總結(jié)

    Maven打包跳過測(cè)試的5種方式總結(jié)

    使用Maven打包的時(shí)候,可能會(huì)因?yàn)閱卧獪y(cè)試打包失敗,這時(shí)候就需要跳過單元測(cè)試,下面這篇文章主要給大家介紹了關(guān)于Maven打包跳過測(cè)試的5種方式,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • Java中注解的常見用法總結(jié)

    Java中注解的常見用法總結(jié)

    注解(Annotation),也叫元數(shù)據(jù),是JDK1.5及以后版本引入的一個(gè)特性,本文主要為大家介紹了注解的常見用法,需要的小伙伴可以參考一下
    2023-07-07
  • 深入理解Java8新特性之Lambda表達(dá)式的基本語法和自定義函數(shù)式接口

    深入理解Java8新特性之Lambda表達(dá)式的基本語法和自定義函數(shù)式接口

    Lambda 表達(dá)式,也可稱為閉包,它是推動(dòng) Java 8 發(fā)布的最重要新特性。Lambda 允許把函數(shù)作為一個(gè)方法的參數(shù)(函數(shù)作為參數(shù)傳遞進(jìn)方法中)。使用 Lambda 表達(dá)式可以使代碼變的更加簡(jiǎn)潔緊湊
    2021-11-11
  • Java求余%操作引發(fā)的一連串故事

    Java求余%操作引發(fā)的一連串故事

    取模運(yùn)算與取余運(yùn)算兩個(gè)概念有重疊的部分但又不完全一致。主要的區(qū)別在于對(duì)負(fù)整數(shù)進(jìn)行除法運(yùn)算時(shí)操作不同。本文重點(diǎn)給大家介紹Java求余%操作引發(fā)的一連串故事,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • Java mongodb連接配置實(shí)踐

    Java mongodb連接配置實(shí)踐

    這篇文章主要介紹了Java mongodb連接配置實(shí)踐,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-12-12
  • java 基礎(chǔ)教程之多線程詳解及簡(jiǎn)單實(shí)例

    java 基礎(chǔ)教程之多線程詳解及簡(jiǎn)單實(shí)例

    這篇文章主要介紹了java 基礎(chǔ)教程之多線程詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,線程的基本屬性、如何創(chuàng)建線程、線程的狀態(tài)切換以及線程通信,需要的朋友可以參考下
    2017-03-03
  • 用java等語言仿360首頁拼音輸入全模糊搜索和自動(dòng)換膚

    用java等語言仿360首頁拼音輸入全模糊搜索和自動(dòng)換膚

    這篇文章主要為大家詳細(xì)介紹了仿360首頁支持拼音輸入全模糊搜索和自動(dòng)換膚的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • 使用MybatisPlus實(shí)現(xiàn)sql日志打印優(yōu)化

    使用MybatisPlus實(shí)現(xiàn)sql日志打印優(yōu)化

    本文主要介紹了使用MybatisPlus實(shí)現(xiàn)sql日志打印優(yōu)化,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-08-08
  • 菜鳥學(xué)習(xí)java設(shè)計(jì)模式之單例模式

    菜鳥學(xué)習(xí)java設(shè)計(jì)模式之單例模式

    這篇文章主要為大家詳細(xì)介紹了java設(shè)計(jì)模式之單例模式的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Spring Boot Feign服務(wù)調(diào)用之間帶token問題

    Spring Boot Feign服務(wù)調(diào)用之間帶token問題

    這篇文章主要介紹了Spring Boot Feign服務(wù)調(diào)用之間帶token的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09

最新評(píng)論