SpringBoot整合支付寶支付流程及ISV權限不足的解決


  具體流程可以看支付寶支付文檔,之前做過微信支付整個流程,所以大體還是比較類似的,支付寶支付更容易一些。支付寶網頁支付返回的是一個form表單,將表單承接,並點擊提交即可進入支付寶提供的web支付頁面。

  官方文檔:電腦網站支付:https://opendocs.alipay.com/open/270/105898

一、前端方面

1、通過接口請求支付寶支付 - 返回的是一個 form表單

async getAliPay() {   let _params = { orderId: this.apply.id, amount: this.apply.price, name: this.apply.examName   }   let { data } = await paymentAlipayApi(_params)   this.alipayData = data }

2、定義一個div用於承接支付寶返回的 form 表單內容

<div v-html="alipayData" id="alipay"></div>

3、給一個按鈕點擊支付

<a-button v-if="apply.status === 'apply'" type="danger" size="large" class="w100" @click="aliPay">去支付</a-button> aliPay () { document.querySelector('form[name="punchout_form"]').submit() },

二、后端方面

1、導入依賴

<!--aliPay-->
<dependency>
  <groupId>com.alipay.sdk</groupId>
  <artifactId>alipay-sdk-java</artifactId>
  <version>3.3.49.ALL</version>
</dependency>

2、controller層聲明接口及業務處理

    @ApiOperation("支付寶發起訂單") @GetMapping(value = "/aliPay", produces = "text/html; charset=utf-8") public String aliPay(@RequestParam Integer orderId, @RequestParam BigDecimal amount, @RequestParam String name) { try { return alipayService.pay(orderId, amount, name, ""); } catch (AlipayApiException e) { log.error(LogUtil.getStack(e)); return null; } }

  AlipayService

package com.opengauss.exam.common.payment; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.request.AlipayTradePagePayRequest; import org.springframework.stereotype.Service; import java.math.BigDecimal; @Service public class AlipayService { public String pay(Integer orderId, BigDecimal amount, String service, String desc) throws AlipayApiException { AlipayClient alipayClient = new DefaultAlipayClient( AlipayConfig.gateway_url, AlipayConfig.app_id, AlipayConfig.merchant_private_key, AlipayConfig.format, AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type); //設置請求參數
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); alipayRequest.setReturnUrl(AlipayConfig.return_url + orderId); alipayRequest.setNotifyUrl(AlipayConfig.notify_url); /* out_trade_no 商戶訂單號,商戶網站訂單系統中唯一訂單號,必填 total_amount 付款金額,必填 subject 訂單名稱,必填 body 商品描述,可空 */ alipayRequest.setBizContent("{\"out_trade_no\":\""+ orderId +"\","
                + "\"total_amount\":\""+ amount +"\","
                + "\"subject\":\""+ service +"\","
                + "\"body\":\""+ desc +"\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}"); //請求
        String result = alipayClient.pageExecute(alipayRequest).getBody(); int index = result.indexOf("<form"); result = "<form target=\"_blank\" " + result.substring(index + 6); return result; } }

  AlipayConfig 就是一些密鑰之類的配置,具體不一樣,這里面主要的就是記錄上面需要的配置,具體可看文檔,比如:

    // 應用ID,您的APPID,收款賬號既是您的APPID對應支付寶賬號
    public static String app_id = "***"; // 網頁支付 // 商戶私鑰,您的PKCS8格式RSA2私鑰
    public static String merchant_private_key1 = "***";
  
// 支付寶公鑰,查看地址:https://openhome.alipay.com/platform/keyManage.htm 對應APPID下的支付寶公鑰。 public static String alipay_public_key1 = "***";// 服務器異步通知頁面路徑 需http://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問 public static String notify_url = "https://***/api/alipayNotify"; // 頁面跳轉同步通知頁面路徑 需http://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問 public static String return_url = "https://***/signup"; // 簽名方式 public static String sign_type = "RSA2"; // 字符編碼格式 public static String charset = "utf-8"; // 字符串格式 public static String format = "json"; // 支付寶網關 public static String gateway_url = "https://openapi.alipay.com/gateway.do";

(1)其中 notify_url 就是支付成功之后,支付寶會給你這個接口發送通知,你可以在這里面去做一些支付成功之后的校驗和一些業務處理。

  需要注意的是這個接口需要在 SpringSecurity 里允許公開訪問。

(2)其中 return_url 就是支付成功之后會跳轉到你給的這個路由。

(3)其中支付寶公鑰,比較好獲取

(4)其中商戶私鑰,獲取方法看官方指導:接口加簽方式配置說明:https://opendocs.alipay.com/mini/introduce/01p6u8

3、異步回調接口處理

@ApiOperation("支付寶回調") @PostMapping("/alipayNotify") public Map alipayNotify(@RequestParam Map<String, String> params) { Map<String, Object> result = new HashMap<>(); result.put("success", false); try { //調用SDK驗證簽名
        boolean signVerified = AlipaySignature.rsaCheckV1( params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); /* 實際驗證過程建議商戶務必添加以下校驗: 1、需要驗證該通知數據中的out_trade_no是否為商戶系統中創建的訂單號, 2、判斷total_amount是否確實為該訂單的實際金額(即商戶訂單創建時的金額), 3、校驗通知中的seller_id(或者seller_email) 是否為out_trade_no這筆單據的對應的操作方(有的時候,一個商戶可能有多個seller_id/seller_email) 4、驗證app_id是否為該商戶本身。 */
        if (signVerified) {//驗證成功 //商戶訂單號
            String out_trade_no = params.get("out_trade_no"); //支付寶交易號
            String trade_no = params.get("trade_no"); //支付寶交易時間
            Date gmt_payment = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(params.get("gmt_payment")); //訂單金額
            BigDecimal total_amount = BigDecimal.valueOf(Double.valueOf(params.get("total_amount"))); //交易狀態
            String trade_status = params.get("trade_status") == null ? "" : params.get("trade_status"); //if (trade_status.equals("TRADE_FINISHED")) { //判斷該筆訂單是否在商戶網站中已經做過處理 //如果沒有做過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程序 //如果有做過處理,不執行商戶的業務程序 //注意: //退款日期超過可退款期限后(如三個月可退款),支付寶系統發送該交易狀態通知
            if (trade_status.equals("TRADE_SUCCESS")) { //判斷該筆訂單是否在商戶網站中已經做過處理 //如果沒有做過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程序 //如果有做過處理,不執行商戶的業務程序 //注意: //付款完成后,支付寶系統發送該交易狀態通知
                ExamApply order = examRoomService.getExamApplyById(Integer.parseInt(out_trade_no)); //訂單存在並且付款狀態未完成
                if (order != null) { if (order.getStatus().equals(ExamApplyStatus.APPLY)) { //校驗訂單金額是否等於支付金額
                        if (order.getPrice().compareTo(total_amount) == 0) { order.setTradeNo(trade_no); order.setGmtPaymentTime(gmt_payment); order.setStatus(ExamApplyStatus.PAYED); userService.paymentFinished(order); result.put("success", true); } else { log.error("Amount not equals, Order Amount: " + order.getPrice() + ", Alipay Amount: " + total_amount); } } } else { log.error("Order not found: " + params); } } else { log.error("Alipay trade fail: " + trade_status); } } else {//驗證失敗 //調試用,寫文本函數記錄程序運行情況是否正常 //String sWord = AlipaySignature.getSignCheckContentV1(params); //AlipayConfig.logResult(sWord);
            log.error("Alipay signature check fail: " + params); } } catch (Exception e) { log.error(LogUtil.getStack(e)); } return result; }

  這個異步回調通知就是支付成功之后支付寶給你設置的回調地址發送的。從里面可以拿到支付的訂單的信息,然后通過簽名校驗,如果校驗成功,就可以去做一些我們自己的業務處理。

  其中該接口需要返回上述代碼 reslult 格式的給支付寶,支付寶收到之后就不會再發生通知,如果沒收到或格式不對,就是會繼續發通知的。

  支付寶支付大體這樣,總體流程比微信支付簡單一些。

三、ISV 權限不足常見問題

  其實上面有提示解決辦法鏈接。

  其他接口提示 ISV 權限不足的原因,詳見“ISV權限不足自查方案”。

  通常都是未簽約未開通能力導致的。

  添加能力,比如:APP支付、手機網站支付、當面付、電腦網站支付。

  使用對應能力,得添加該能力,並簽約生效才可以。我剛開始電腦網站支付未簽約,導致報這個錯,簽約之后就可以了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM