Java 支付寶手機網站支付下單 支付回調 及訂單查詢實現

首先,參考官方api:
alipay.trade.wap.pay(手機網站支付接口2.0)
官方提供DEMO下載,不過是jsp的
準備工作:平臺入駐,簽約功能,應用上線,配置祕鑰等

使用Alipay SDK:

        <!-- 支付寶支付sdk -->
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>4.9.124.ALL</version>
        </dependency>

固定參數配置類:

// 由於部分數據來自數據庫,這裏用到了我自己寫的service,不需要查詢的話也可以直接在config中寫一個固定值
import com.tb.service.ShopDeviceService;

public class AlipayConfig {

    private ShopDeviceService shopDeviceService;
    // 爲了傳遞service,只能使用new的形式創建
    public AlipayConfig(ShopDeviceService shopDeviceService) {
        this.shopDeviceService = shopDeviceService;
    }


    // 商戶appid
    public String getAppId() {
        return shopDeviceService.getDictDetailByNameAndLabel("PAY-INFO", "AlipayAppid");
    }

    // 支付寶公鑰
    public String getAliPayPublicKey() {
        return shopDeviceService.getDictDetailByNameAndLabel("KEY", "支付寶公鑰");
    }

    // 私鑰 pkcs8格式的
    public String getRSAPrivateKey() {
        return shopDeviceService.getDictDetailByNameAndLabel("KEY", "支付寶應用私鑰");
    }

    // 服務器異步通知頁面路徑 需http://或者https://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問
    public String getNotifyUrl() {
        return shopDeviceService.getDictDetailByNameAndLabel("URL", "AliPayNotify");
    }

    // 請求網關地址
    public String getUrl() {
        return "https://openapi.alipay.com/gateway.do";
    }

    // 編碼
    public String getCharset() {
        return "UTF-8";
    }

    // 返回格式
    public String getFormat() {
        return "json";
    }

    // RSA2
    public String getSignType() {
        return "RSA2";
    }

    public String getProductCode() {
        return "QUICK_WAP_WAY";
    }

    // subject
    public String getSubject() {
        return "WASHER";
    }
}

手機網站支付接口:

    // ALIPay 下單 跳轉至付款界面
    @PreAuthorize("@el.check('anonymous')")// 匿名訪問
    @PostMapping("/aliPrePay")
    public void alipayPlaceOrder(@RequestBody Map params, HttpServletResponse response) throws AlipayApiException {

		// 創建訂單並返回訂單id
        ShopOrderDTO shopOrderDTO = createOrder(params);	
		//new配置類,傳入需要的service
        AlipayConfig alipayConfig = new AlipayConfig(shopDeviceService);
        
        //支付固定寫法從這裏開始了!
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getAppId(),
                alipayConfig.getRSAPrivateKey(), alipayConfig.getFormat(), alipayConfig.getCharset(),
                alipayConfig.getAliPayPublicKey(), alipayConfig.getSignType());
        AlipayTradeWapPayRequest req = new AlipayTradeWapPayRequest();

        AlipayTradeWapPayModel model=new AlipayTradeWapPayModel();
        model.setOutTradeNo(shopOrderDTO.getId().toString());
        model.setSubject(alipayConfig.getSubject());
        String amount = String.valueOf(shopOrderDTO.getAmount().floatValue() / 100);
        model.setTotalAmount(amount);
        model.setProductCode(alipayConfig.getProductCode());
        req.setBizModel(model);
        req.setNotifyUrl(alipayConfig.getNotifyUrl());

        logger.info("發起AliPay下單請求");
        String form = alipayClient.pageExecute(req).getBody();

        response.setContentType("text/html;charset=" + alipayConfig.getCharset());
        try {
        	//直接將完整的表單html輸出到頁面
            response.getWriter().write(form);
            response.getWriter().flush();
            response.getWriter().close();
        } catch (IOException e) {
            logger.info("AliPay 界面跳轉失敗");
        }
    }

異步通知接口:

    // AliPay 支付異步通知
    @PreAuthorize("@el.check('anonymous')")
    @PostMapping("/aliPayNotify")
    public void alipayReturn(HttpServletRequest request) {
        logger.info("AliPay 支付回調:");

        Map<String,String> params = new HashMap();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //亂碼解決,這段代碼在出現亂碼時使用。如果mysign和sign不相等也可以使用這段代碼轉化 valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);
        }

        String out_trade_no = request.getParameter("out_trade_no");
        ShopOrderDTO orderDto = shopOrderService.findById(Long.valueOf(out_trade_no));

        String trade_no = request.getParameter("trade_no");
        String trade_status = request.getParameter("trade_status");
        Float amount = Float.valueOf(request.getParameter("total_amount"));

        AlipayConfig alipayConfig = new AlipayConfig(shopDeviceService);
        try {
            boolean verify_result = AlipaySignature.rsaCheckV1(params, alipayConfig.getAliPayPublicKey(), alipayConfig.getCharset(), alipayConfig.getSignType());
            if(verify_result) {	// 簽名校驗
                if (trade_status.equals("TRADE_SUCCESS") && !StringUtils.isBlank(trade_no) ) {// 支付成功
                    // 一些自己的判斷,比如金額,訂單支付狀態等等,自行修改
                    if (amount == Float.valueOf(orderDto.getAmount())/100 && orderDto.getState() == 1) {
                        onSuccess(orderDto, trade_no);
                    } else if (orderDto.getState() == 0) {
						// 日誌保存
                        shopLogService.anonymousCreate(shopLogService.getShopLog(orderDto.getStoreId(), orderDto.getDeviceId(), "訂單支付狀態有誤","訂單支付狀態爲已支付 : " + orderDto.getId()));
                    } else if (amount != Float.valueOf(orderDto.getAmount())/100){
                        shopLogService.anonymousCreate(shopLogService.getShopLog(orderDto.getStoreId(), orderDto.getDeviceId(), "AliPay支付金額有誤","金額有誤 : " + orderDto.getId()));
                    }
                } else {
                    shopLogService.anonymousCreate(shopLogService.getShopLog(orderDto.getStoreId(), orderDto.getDeviceId(), "AliPay支付失敗",orderDto.getId()+""));
                }
            } else {
                logger.info("AliPay 簽名校驗失敗");
            }
        } catch (AlipayApiException e) {
            logger.info("AliPay 簽名校驗失敗");
            e.printStackTrace();
        }
    }

訂單查詢接口:

    // AliPay 訂單查詢
    @PreAuthorize("@el.check('anonymous')")
    @GetMapping("/aliPayQuery")
    public ResponseEntity AliPayQuery(String id) {
        ShopOrderDTO orderDTO = shopOrderService.findById(Long.valueOf(id));
		
		// 這裏可以加一層判斷,如果訂單是已支付且已有支付id直接返回成功就好,不必再調支付寶查詢接口
      
        try {
            AlipayConfig alipayConfig = new AlipayConfig(shopDeviceService);
            AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getAppId(),
                    alipayConfig.getRSAPrivateKey(), alipayConfig.getFormat(), alipayConfig.getCharset(),
                    alipayConfig.getAliPayPublicKey(), alipayConfig.getSignType());
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            AlipayTradeQueryModel model = new AlipayTradeQueryModel();
            model.setOutTradeNo(id);
            request.setBizModel(model);
            logger.info("發起 AliPay 查詢請求:");
            AlipayTradeQueryResponse response = alipayClient.execute(request);
            
            Map map = JSON.parseObject(response.getBody(), Map.class);
            Map result = JSON.parseObject(map.get("alipay_trade_query_response").toString(), Map.class);

            if (result.get("code").toString().equals("10000") && result.get("trade_status").toString().equals("TRADE_SUCCESS") // 支付成功
                  && Float.valueOf(result.get("total_amount").toString()) == Float.valueOf(orderDTO.getAmount())) {	// 金額與訂單金額相等
                // TODO 支付成功後回調已經做了一些事 查詢的時候要做什麼有待思考
                ShopOrder order = new ShopOrder();
                order.setId(orderDTO.getId());
                order.setState(0);
                order.setPayId(result.get("trade_no").toString());
                shopOrderService.update(order);
            }
            return new ResponseEntity<>(result, HttpStatus.OK);
        } catch (AlipayApiException e) {
            logger.info("AliPay 查詢失敗");
            return new ResponseEntity(HttpStatus.OK);
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章