首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring 整合支付寶掃碼支付完整流程實戰

     編輯:Java 相關知識

準備工作

  1. 企業支付寶賬號(PID)+ 應用(AppID)
  2. 配置密鑰:商戶私鑰(PKCS8)、商戶公鑰、支付寶公鑰
  3. 簽約「當面付」功能,開發期使用沙箱環境

依賴引入

<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-sdk-java</artifactId>
    <version>2023xxxx</version>
</dependency>

配置文件 alipay.properties(沙箱示例)

open_api_domain=https://openapi.alipaydev.com/gateway.do
pid=2088102172329883
appid=2016082000300485
private_key=MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAMKXZrFR...
public_key=MIGfMA0GCSqGSIbDQEBAQUAA4GNADCBiQKBgQDCl2axUfq572IAbPas9nBNZgkiAUXmqmp...
alipay_public_key=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIgHnOn7LLILlKETd6BFRJ0GqgS2Y3mn1wMQmyh9zEyWlz5p1zrahRahbXAfCfSqshSNfqOmAQzSHRVjCqjsAw1jyqrXaPdKBmr90DIpIxmIyKXv4GGAkPyJ/6FTFY99uhpiq0qadD/uSzQsefWo0aTvP/65zi3eof7TcZ32oWpwIDAQAB

核心 Controller:統一下單

@PostMapping("/pay/alipay")
public Map<String, String> alipay(@RequestParam String amount, @RequestParam int userId) {
    String outTradeNo = "ORDER" + System.currentTimeMillis() + (long)(Math.random()*1e7);
    AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
        .setSubject("商品付款")
        .setTotalAmount(amount)
        .setOutTradeNo(outTradeNo)
        .setStoreId("2088102172329883")
        .setTimeoutExpress("120m")
        .setNotifyUrl("https://your.domain/pay/notify");

    AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
    Map<String, String> res = new HashMap<>();
    switch (result.getTradeStatus()) {
        case SUCCESS:
            String qrCode = result.getResponse().getQrCode();
            // 保存訂單到 DB
            orderService.save(new Order(userId, outTradeNo, amount));
            res.put("status", "true");
            res.put("qrcode", qrCode);
            res.put("outtradeno", outTradeNo);
            break;
        case FAILED: case UNKNOWN: default:
            res.put("status", "false");
            res.put("msg", "系統異常,請稍後再試");
    }
    return res;
}

異步通知處理

@PostMapping("/pay/notify")
public String notify(HttpServletRequest req) {
    Map<String, String> params = getParams(req);
    if (!AlipaySignature.rsaCheckV1(params, Configs.getAlipayPublicKey(), "UTF-8")) {
        return "failed";
    }
    String outTradeNo = params.get("out_trade_no");
    Order order = orderService.findByOutTradeNo(outTradeNo);
    if (order == null || order.getAmount() != Double.parseDouble(params.get("total_amount"))) {
        return "failed";
    }
    String tradeStatus = params.get("trade_status");
    if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
        orderService.updateStatus(outTradeNo, Order.SUCCESS);
    }
    // TODO: 推送支付成功通知給前端(WebSocket/輪詢)
    return "success";
}

常見坑點

  1. 二維碼需用 ZXing 生成圖片,不可直接用瀏覽器打開支付寶返回的 QR 碼串
  2. 沙箱環境必須用沙箱版支付寶 APP 掃碼
  3. notify_url 必須可被公網訪問,內網測試用 ngrok/frp 穿透
  4. 權限不足通常是未簽約或應用未上線,開發期用沙箱應用
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved