最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot?支付渠道實(shí)現(xiàn)統(tǒng)一的支付服務(wù)示例

 更新時間:2026年03月13日 09:55:00   作者:Java程序員?擁抱ai  
本文提出了一種基于工廠模式和策略模式的多渠道支付封裝方案,該設(shè)計(jì)采用策略模式實(shí)現(xiàn)各支付渠道(微信、支付寶、銀聯(lián))的統(tǒng)一接口,通過工廠模式動態(tài)創(chuàng)建支付策略,感興趣的可以了解一下

設(shè)計(jì)思路

使用工廠和策略模式設(shè)計(jì)一個可擴(kuò)展的多渠道支付封裝方案,支持微信、支付寶、銀聯(lián)等支付渠道。

  • 策略模式:每個支付渠道實(shí)現(xiàn)統(tǒng)一的支付接口;
  • 工廠模式:根據(jù)支付類型創(chuàng)建對應(yīng)的支付策略;
  • 配置化管理:支付參數(shù)通過配置文件管理;
  • 統(tǒng)一響應(yīng):標(biāo)準(zhǔn)化支付返回結(jié)果。

設(shè)計(jì)優(yōu)勢:

  • 開閉原則:新增支付渠道只需實(shí)現(xiàn)PayStrategy接口,無需修改現(xiàn)有代碼;
  • 統(tǒng)一入口:通過PayService提供統(tǒng)一的支付入口
  • 配置化:支付參數(shù)通過配置文件管理,便于不同環(huán)境部署
  • 異常處理:統(tǒng)一的異常處理機(jī)制
  • 易于擴(kuò)展:支持添加新的支付渠道和支付方式
  • 維護(hù)性:代碼結(jié)構(gòu)清晰,易于維護(hù)和測試

實(shí)現(xiàn)代碼

主要包含:支付相關(guān)枚舉、支付請求和響應(yīng)對象、支付策略接口、支付策略實(shí)現(xiàn)、支付策略工廠、統(tǒng)一支付服務(wù)。

依賴 pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
 
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
 
<dependency>
    <groupId>com.github.wechatpay-apiv3</groupId>
    <artifactId>wechatpay-java</artifactId>
    <version>0.2.17</version>
</dependency>
 
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

支付相關(guān)枚舉定義

支付渠道 PayChannel.java

@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum PayChannel {
 
    WECHAT_PAY("wechat", "微信支付"),
    ALI_PAY("alipay", "支付寶"),
    UNION_PAY("union", "銀聯(lián)支付");
 
    private String code;
 
    private String name;
 
    public static PayChannel getByCode(String code) {
        for (PayChannel item : values()) {
            if (item.getCode().equals(code)) {
                return item;
            }
        }
        return null;
    }
 
}
 
支付狀態(tài) PayStatus.java
 
```java
@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum PayStatus {
 
    WAITING(0, "待支付"),
 
    SUCCESS(1, "成功"),
 
    FAILED(2, "失敗"),
 
    CANCELED(3, "已取消"),
 
    REFUND(4, "已退款");
 
    private Integer code;
 
    private String desc;
 
    public static PayStatus getByCode(String code) {
        for (PayStatus item : values()) {
            if (item.getCode().equals(code)) {
                return item;
            }
        }
        return null;
    }
 
}

交易類型 TradeType.java,根據(jù)支付渠道篩選可用的交易類型

@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum TradeType {
 
    APP("app", "APP支付"),
    JSAPI("jsapi", "公眾號/小程序支付"),
    NATIVE("native", "掃碼支付"),
    H5("h5", "H5支付");
 
    private String code;
 
    private String desc;
 
    public static TradeType getByCode(String code) {
        for (TradeType item : values()) {
            if (item.getCode().equals(code)) {
                return item;
            }
        }
        return null;
    }
 
}

交易方式 TradeMethod.java

@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum TradeMethod {
 
    PAY("pay", "支付"),
    REFUND("refund", "退款");
 
    private String code;
 
    private String desc;
 
    public static TradeMethod getByCode(String code) {
        for (TradeMethod item : values()) {
            if (item.getCode().equals(code)) {
                return item;
            }
        }
        return null;
    }
 
}

常量 Constants.java

public class Constants {
 
    /**
     * 操作狀態(tài)
     */
    public final static Integer OPERATE_SUCCESS_STATE = 200;
    public final static String OPERATE_SUCCESS_MSG = "success";
 
    public final static Integer OPERATE_ERROR_STATE = 500;
    public final static String OPERATE_ERROR_MSG = "error";
 
}

支付請求和響應(yīng)對象

公共請求參數(shù) BaseRequest.java

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class BaseRequest implements Serializable {
 
    /**
     * appid
     */
    private String appId;
 
    /**
     * 商戶號
     */
    private String mchId;
 
    /**
     * 商戶證書序列號
     */
    private String serialNo;
 
    /**
     * 商戶API私鑰
     */
    private String privateKey;
 
    /**
     * 商戶API公鑰
     */
    private String publicKey;
 
    /**
     * 商戶APIV3密鑰
     */
    private String apiV3Key;
 
}

關(guān)閉訂單響應(yīng)參數(shù) CloseResponse.java

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CloseResponse implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    /**
     * 是否成功
     */
    private Boolean success;
 
    /**
     * 訂單號
     */
    private String orderNo;
 
    /**
     * 錯誤碼
     */
    private String errorCode;
 
    /**
     * 錯誤信息
     */
    private String errorMsg;
 
    public static CloseResponse success(String orderNo) {
        CloseResponse response = new CloseResponse();
        response.setSuccess(true);
        response.setOrderNo(orderNo);
        return response;
    }
 
    public static CloseResponse failure(String errorCode, String errorMsg) {
        CloseResponse response = new CloseResponse();
        response.setSuccess(false);
        response.setErrorCode(errorCode);
        response.setErrorMsg(errorMsg);
        return response;
    }
}

回調(diào)處理請求 NotifyRequest.java

@Data
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public class NotifyRequest extends BaseRequest implements Serializable {
 
    private static final long serialVersionUID=1L;
 
    /**
     * 支付渠道
     */
    private PayChannel payChannel;
 
    /**
     * 交易方式
     */
    private TradeMethod method;
 
    /**
     * 請求體
     */
    private HttpServletRequest servletRequest;
 
}

回調(diào)處理響應(yīng) NotifyResponse.java

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class NotifyResponse implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    /**
     * 是否成功
     */
    private Boolean success;
 
    /**
     * 交易訂單號
     */
    private String orderNo;
 
    /**
     * 三方交易訂單號
     */
    private String transactionId;
 
    /**
     * 退款單號
     */
    private String refundNo;
 
    /**
     * 退款三方訂單號
     */
    private String refundId;
 
    /**
     * 狀態(tài)
     */
    private PayStatus status;
 
    /**
     * 時間
     */
    private LocalDateTime time;
 
    /**
     * 錯誤碼
     */
    private String errorCode;
 
    /**
     * 錯誤信息
     */
    private String errorMsg;
 
    public static NotifyResponse failure(String errorCode, String errorMsg) {
        return NotifyResponse.builder().success(false).errorCode(errorCode).errorMsg(errorMsg).build();
    }
 
}

統(tǒng)一支付請求 PayRequest.java

@Data
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public class PayRequest extends BaseRequest implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    /**
     * 支付渠道
     */
    private PayChannel payChannel;
 
    /**
     * 交易類型
     */
    private TradeType tradeType;
 
    /**
     * 訂單號
     */
    private String orderNo;
 
    /**
     * 訂單金額(單位:分)
     */
    private BigDecimal amount;
 
    /**
     * 訂單描述
     */
    private String description;
 
    /**
     * 用戶IP
     */
    private String clientIp;
 
    /**
     * 過期時間
     */
    private LocalDateTime expireTime;
 
    /**
     * 附加數(shù)據(jù)
     */
    private String attach;
 
    /**
     * 通知地址
     */
    private String notifyUrl;
 
    /**
     * 用戶標(biāo)識
     */
    private String openId;
 
    /**
     * 場景類型:Wap、iOS、Android
     */
    private String h5Type;
 
}

統(tǒng)一支付響應(yīng) PayResponse.java

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PayResponse implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    /**
     * 是否成功
     */
    private Boolean success;
 
    /**
     * 錯誤碼
     */
    private String errorCode;
 
    /**
     * 錯誤信息
     */
    private String errorMsg;
 
    /**
     * 支付所需參數(shù)(前端調(diào)起支付所需)
     */
    private Map<String, Object> payParams;
 
    /**
     * 預(yù)支付交易會話標(biāo)識
     */
    private String prepayId;
 
    /**
     * 支付跳轉(zhuǎn)URL
     */
    private String payUrl;
 
    /**
     * 二維碼鏈接
     */
    private String codeUrl;
 
    public static PayResponse failure(String errorCode, String errorMsg) {
        PayResponse response = new PayResponse();
        response.setSuccess(false);
        response.setErrorCode(errorCode);
        response.setErrorMsg(errorMsg);
        return response;
    }
 
}

查詢響應(yīng) QueryResponse.java

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class QueryResponse implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    /**
     * 是否成功
     */
    private Boolean success;
 
    /**
     * 訂單號
     */
    private String orderNo;
 
    /**
     * 三方交易訂單號
     */
    private String transactionId;
 
    /**
     * 狀態(tài)
     */
    private PayStatus payStatus;
 
    /**
     * 支付時間
     */
    private LocalDateTime payTime;
 
    /**
     * 錯誤碼
     */
    private String errorCode;
 
    /**
     * 錯誤信息
     */
    private String errorMsg;
 
    public static QueryResponse failure(String errorCode, String errorMsg) {
        QueryResponse response = new QueryResponse();
        response.setSuccess(false);
        response.setErrorCode(errorCode);
        response.setErrorMsg(errorMsg);
        return response;
    }
}

退款請求 RefundRequest.java

@Data
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public class RefundRequest extends BaseRequest implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    /**
     * 交易訂單號
     */
    private String orderNo;
 
    /**
     * 退款單號
     */
    private String refundNo;
 
    /**
     * 交易金額
     */
    private BigDecimal payAmount;
 
    /**
     * 退款金額
     */
    private BigDecimal refundAmount;
 
    /**
     * 退款原因
     */
    private String refundReason;
 
    /**
     * 退款回調(diào)地址
     */
    private String notifyUrl;
 
}

退款響應(yīng) RefundResponse.java

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RefundResponse implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    /**
     * 是否成功
     */
    private Boolean success;
 
    /**
     * 交易訂單號
     */
    private String orderNo;
 
    /**
     * 退款單號
     */
    private String refundNo;
 
    /**
     * 退款三方訂單號
     */
    private String refundId;
 
    /**
     * 狀態(tài)
     */
    private PayStatus refundStatus;
 
    /**
     * 退款時間
     */
    private LocalDateTime refundTime;
 
    /**
     * 錯誤碼
     */
    private String errorCode;
 
    /**
     * 錯誤信息
     */
    private String errorMsg;
 
    public static RefundResponse failure(String errorCode, String errorMsg) {
        return RefundResponse.builder().success(false).errorCode(errorCode).errorMsg(errorMsg).build();
    }
 
}

支付策略接口 PayStrategy.java

public interface PayStrategy {
 
    /**
     * 獲取支付渠道
     */
    PayChannel getPayChannel();
 
    /**
     * 統(tǒng)一支付
     */
    PayResponse pay(PayRequest request);
 
    /**
     * 查詢訂單
     */
    QueryResponse queryOrder(PayRequest request);
 
    /**
     * 關(guān)閉訂單
     */
    CloseResponse close(PayRequest request);
 
    /**
     * 退款
     */
    RefundResponse refund(RefundRequest request);
 
    /**
     * 退款查詢
     */
    RefundResponse queryRefund(RefundRequest request);
 
    /**
     * 處理回調(diào)
     */
    NotifyResponse handleNotify(NotifyRequest request);
 
}

支付策略實(shí)現(xiàn) AbstractPayStrategy.java

抽象支付策略

@Slf4j
public abstract class AbstractPayStrategy implements PayStrategy {
 
    @Override
    public PayResponse pay(PayRequest request) {
        try {
            log.info("開始支付,渠道:{},訂單號:{}", getPayChannel().getName(), request.getOrderNo());
            return doPay(request);
        } catch (Exception e) {
            log.error("支付異常,渠道:{},訂單號:{}", getPayChannel().getName(), request.getOrderNo(), e);
            return PayResponse.failure(Constants.OPERATE_ERROR_MSG, "支付處理異常:" + e.getMessage());
        }
    }
 
    @Override
    public QueryResponse queryOrder(PayRequest request) {
        try {
            log.info("查詢訂單,渠道:{},訂單號:{}", getPayChannel().getName(), request.getOrderNo());
            return doQueryOrder(request);
        } catch (Exception e) {
            log.error("查詢訂單異常,渠道:{},訂單號:{}", getPayChannel().getName(), request.getOrderNo(), e);
            return QueryResponse.failure(Constants.OPERATE_ERROR_MSG, "查詢訂單異常:" + e.getMessage());
        }
    }
 
    @Override
    public CloseResponse close(PayRequest request) {
        try {
            log.info("關(guān)閉訂單,渠道:{},訂單號:{}", getPayChannel().getName(), request.getOrderNo());
            return doClose(request);
        } catch (Exception e) {
            log.error("關(guān)閉訂單異常,渠道:{},訂單號:{}", getPayChannel().getName(), request.getOrderNo(), e);
            return CloseResponse.failure(Constants.OPERATE_ERROR_MSG, "關(guān)閉訂單異常:" + e.getMessage());
        }
    }
 
    @Override
    public RefundResponse refund(RefundRequest request) {
        try {
            log.info("開始退款,渠道:{},退款單號:{}", getPayChannel().getName(), request.getRefundNo());
            return doRefund(request);
        } catch (Exception e) {
            log.error("退款異常,渠道:{},退款單號:{}", getPayChannel().getName(), request.getRefundNo(), e);
            return RefundResponse.failure(Constants.OPERATE_ERROR_MSG, "退款處理異常:" + e.getMessage());
        }
    }
 
    @Override
    public RefundResponse queryRefund(RefundRequest request) {
        try {
            log.info("開始退款查詢,渠道:{},退款單號:{}", getPayChannel().getName(), request.getRefundNo());
            return doQueryRefund(request);
        } catch (Exception e) {
            log.error("退款查詢異常,渠道:{},退款單號:{}", getPayChannel().getName(), request.getRefundNo(), e);
            return RefundResponse.failure(Constants.OPERATE_ERROR_MSG, "退款查詢處理異常:" + e.getMessage());
        }
    }
 
    protected abstract PayResponse doPay(PayRequest request);
 
    protected abstract QueryResponse doQueryOrder(PayRequest request);
 
    protected abstract CloseResponse doClose(PayRequest request);
 
    protected abstract RefundResponse doRefund(RefundRequest request);
 
    protected abstract RefundResponse doQueryRefund(RefundRequest request);
 
}

各渠道實(shí)現(xiàn)

主要以微信支付為列,實(shí)現(xiàn)支付、退款、查詢、關(guān)閉訂單、支付退款回調(diào)等功能。

微信支付實(shí)現(xiàn) WechatPayStrategy.java

import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.app.AppServiceExtension;
import com.wechat.pay.java.service.payments.app.model.CloseOrderRequest;
import com.wechat.pay.java.service.payments.app.model.QueryOrderByOutTradeNoRequest;
import com.wechat.pay.java.service.payments.h5.H5Service;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.*;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
 
@Slf4j
@Component
public class WechatPayStrategy extends AbstractPayStrategy {
 
    @Override
    protected PayResponse doPay(PayRequest request) {
        try {
            // 初始化商戶配置
            Config config = new RSAAutoCertificateConfig.Builder()
                    .merchantId(request.getMchId())
                    .privateKey(request.getPrivateKey())
                    .merchantSerialNumber(request.getSerialNo())
                    .apiV3Key(request.getApiV3Key())
                    .build();
 
            switch (request.getTradeType()) {
                case TradeType.APP:
                    com.wechat.pay.java.service.payments.app.model.PrepayRequest appRrq = new com.wechat.pay.java.service.payments.app.model.PrepayRequest();
                    appRrq.setAppid(request.getAppId());
                    appRrq.setMchid(request.getMchId());
                    appRrq.setOutTradeNo(request.getOrderNo());
                    appRrq.setDescription(request.getDescription());
                    appRrq.setAttach(request.getAttach());
                    appRrq.setNotifyUrl(request.getNotifyUrl());
                    com.wechat.pay.java.service.payments.app.model.Amount appAmount = new com.wechat.pay.java.service.payments.app.model.Amount();
                    appAmount.setCurrency("CNY");
                    appAmount.setTotal(request.getAmount().multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_UP).intValue());
                    appRrq.setAmount(appAmount);
                    if (Objects.nonNull(request.getExpireTime())) {
                        appRrq.setTimeExpire(request.getExpireTime().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
                    }
 
                    log.info("APP支付,請求參數(shù):{}", appRrq);
                    com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse appRes = new AppServiceExtension.Builder().config(config).build().prepayWithRequestPayment(appRrq);
                    log.info("APP支付,返回參數(shù):{}", appRes);
 
                    if (Objects.nonNull(appRes)) {
                        Map<String, Object> appParams = new HashMap<>();
                        appParams.put("appid", appRes.getAppid());
                        appParams.put("partnerid", appRes.getPartnerId());
                        appParams.put("prepayid", appRes.getPrepayId());
                        appParams.put("package", appRes.getPackageVal());
                        appParams.put("noncestr", appRes.getNonceStr());
                        appParams.put("timestamp", appRes.getTimestamp());
                        appParams.put("sign", appRes.getSign());
                        return PayResponse.builder().success(true).payParams(appParams).prepayId(appRes.getPrepayId()).build();
                    }
                    return PayResponse.failure(Constants.OPERATE_ERROR_MSG, Constants.OPERATE_ERROR_MSG);
                case TradeType.JSAPI:
                    com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest jsapiReq = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest();
                    jsapiReq.setAppid(request.getAppId());
                    jsapiReq.setMchid(request.getMchId());
                    jsapiReq.setOutTradeNo(request.getOrderNo());
                    jsapiReq.setDescription(request.getDescription());
                    jsapiReq.setAttach(request.getAttach());
                    jsapiReq.setNotifyUrl(request.getNotifyUrl());
                    com.wechat.pay.java.service.payments.jsapi.model.Amount jsapiAmount = new com.wechat.pay.java.service.payments.jsapi.model.Amount();
                    jsapiAmount.setCurrency("CNY");
                    jsapiAmount.setTotal(request.getAmount().multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_UP).intValue());
                    jsapiReq.setAmount(jsapiAmount);
                    com.wechat.pay.java.service.payments.jsapi.model.Payer jsapiPayer = new com.wechat.pay.java.service.payments.jsapi.model.Payer();
                    jsapiPayer.setOpenid(request.getOpenId());
                    jsapiReq.setPayer(jsapiPayer);
                    if (Objects.nonNull(request.getExpireTime())) {
                        jsapiReq.setTimeExpire(request.getExpireTime().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
                    }
 
                    log.info("JSAPI支付,請求參數(shù):{}", jsapiReq);
                    com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse jsapiRes = new JsapiServiceExtension.Builder().config(config).build().prepayWithRequestPayment(jsapiReq);
                    log.info("JSAPI支付,返回參數(shù):{}", jsapiRes);
 
                    if (Objects.nonNull(jsapiRes)) {
                        Map<String, Object> jsapiParams = new HashMap<>();
                        jsapiParams.put("appId", jsapiRes.getAppId());
                        jsapiParams.put("paySign", jsapiRes.getPaySign());
                        jsapiParams.put("signType", jsapiRes.getSignType());
                        jsapiParams.put("package", jsapiRes.getPackageVal());
                        jsapiParams.put("nonceStr", jsapiRes.getNonceStr());
                        jsapiParams.put("timeStamp", jsapiRes.getTimeStamp());
                        return PayResponse.builder().success(true).payParams(jsapiParams).build();
                    }
                    return PayResponse.failure(Constants.OPERATE_ERROR_MSG, Constants.OPERATE_ERROR_MSG);
                case TradeType.NATIVE:
                    com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest nativeReq = new com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest();
                    nativeReq.setAppid(request.getAppId());
                    nativeReq.setMchid(request.getMchId());
                    nativeReq.setOutTradeNo(request.getOrderNo());
                    nativeReq.setDescription(request.getDescription());
                    nativeReq.setAttach(request.getAttach());
                    nativeReq.setNotifyUrl(request.getNotifyUrl());
                    com.wechat.pay.java.service.payments.nativepay.model.Amount nativeAmount = new com.wechat.pay.java.service.payments.nativepay.model.Amount();
                    nativeAmount.setCurrency("CNY");
                    nativeAmount.setTotal(request.getAmount().multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_UP).intValue());
                    nativeReq.setAmount(nativeAmount);
                    if (Objects.nonNull(request.getExpireTime())) {
                        nativeReq.setTimeExpire(request.getExpireTime().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
                    }
 
                    log.info("NATIVE支付,請求參數(shù):{}", nativeReq);
                    com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse nativeRes = new NativePayService.Builder().config(config).build().prepay(nativeReq);
                    log.info("NATIVE支付,返回參數(shù):{}", nativeRes);
 
                    if (Objects.nonNull(nativeRes)) {
                        return PayResponse.builder().success(true).codeUrl(nativeRes.getCodeUrl()).build();
                    }
                case TradeType.H5:
                    com.wechat.pay.java.service.payments.h5.model.PrepayRequest h5Req = new com.wechat.pay.java.service.payments.h5.model.PrepayRequest();
                    h5Req.setAppid(request.getAppId());
                    h5Req.setMchid(request.getMchId());
                    h5Req.setOutTradeNo(request.getOrderNo());
                    h5Req.setDescription(request.getDescription());
                    h5Req.setAttach(request.getAttach());
                    h5Req.setNotifyUrl(request.getNotifyUrl());
 
                    com.wechat.pay.java.service.payments.h5.model.Amount h5Amount = new com.wechat.pay.java.service.payments.h5.model.Amount();
                    h5Amount.setCurrency("CNY");
                    h5Amount.setTotal(request.getAmount().multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_UP).intValue());
                    h5Req.setAmount(h5Amount);
 
                    com.wechat.pay.java.service.payments.h5.model.SceneInfo h5Scene = new com.wechat.pay.java.service.payments.h5.model.SceneInfo();
                    h5Scene.setPayerClientIp(request.getClientIp());
                    com.wechat.pay.java.service.payments.h5.model.H5Info h5Info = new com.wechat.pay.java.service.payments.h5.model.H5Info();
                    h5Info.setType(request.getH5Type());
                    h5Scene.setH5Info(h5Info);
                    h5Req.setSceneInfo(h5Scene);
                    if (Objects.nonNull(request.getExpireTime())) {
                        h5Req.setTimeExpire(request.getExpireTime().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
                    }
 
                    log.info("H5支付,請求參數(shù):{}", h5Req);
                    com.wechat.pay.java.service.payments.h5.model.PrepayResponse h5Re s= new H5Service.Builder().config(config).build().prepay(h5Req);
                    log.info("H5支付,返回參數(shù):{}", h5Res);
 
                    if (Objects.nonNull(h5Res)) {
                        return PayResponse.builder().success(true).codeUrl(h5Res.getH5Url()).build();
                    }
                default:
                    return PayResponse.failure(Constants.OPERATE_ERROR_MSG, "不支持的微信交易類型");
            }
        } catch (Exception e) {
            log.error("微信支付失敗: {}", e);
            return PayResponse.failure(Constants.OPERATE_ERROR_MSG, e.getMessage());
        }
    }
 
    @Override
    protected QueryResponse doQueryOrder(PayRequest request) {
        try {
            QueryOrderByOutTradeNoRequest req = new QueryOrderByOutTradeNoRequest();
            req.setMchid(request.getMchId());
            req.setOutTradeNo(request.getOrderNo());
 
            log.info("訂單開始,請求參數(shù):{}", req);
            Transaction res = new AppServiceExtension.Builder().config(
                    new RSAAutoCertificateConfig.Builder()
                            .merchantId(request.getMchId())
                            .privateKey(request.getPrivateKey())
                            .merchantSerialNumber(request.getSerialNo())
                            .apiV3Key(request.getApiV3Key())
                            .build()
            ).build().queryOrderByOutTradeNo(req);
            log.info("訂單結(jié)束,返回參數(shù):{}", res);
 
            if (Objects.nonNull(res)) {
                PayStatus payStatus = PayStatus.WAITING;
                LocalDateTime payTime = null;
                if (Transaction.TradeStateEnum.SUCCESS == res.getTradeState()) {
                    // 成功
                    payTime = LocalDateTime.parse(res.getSuccessTime());
                    payStatus = PayStatus.SUCCESS;
                } else if (Transaction.TradeStateEnum.NOTPAY == res.getTradeState() || Transaction.TradeStateEnum.USERPAYING == res.getTradeState()) {
                    // 未支付、支付中
                    payStatus = PayStatus.WAITING;
                } else if (Transaction.TradeStateEnum.CLOSED == res.getTradeState() || Transaction.TradeStateEnum.REVOKED == res.getTradeState()) {
                    // 已關(guān)閉、已撤銷
                    payStatus = PayStatus.CANCELED;
                } else if (Transaction.TradeStateEnum.PAYERROR == res.getTradeState()) {
                    // 失敗
                    payStatus = PayStatus.FAILED;
                }
 
                return QueryResponse.builder()
                        .success(true)
                        .orderNo(res.getOutTradeNo())
                        .transactionId(res.getTransactionId())
                        .payStatus(payStatus)
                        .payTime(payTime)
                        .build();
            }
            return QueryResponse.failure(Constants.OPERATE_ERROR_MSG, "訂單查詢失敗");
        } catch (Exception e) {
            log.error("微信支付查詢失敗: {}", e);
            return QueryResponse.failure(Constants.OPERATE_ERROR_MSG, e.getMessage());
        }
    }
 
    @Override
    protected CloseResponse doClose(PayRequest request) {
        try {
            CloseOrderRequest req = new CloseOrderRequest();
            req.setMchid(request.getMchId());
            req.setOutTradeNo(request.getOrderNo());
 
            log.info("關(guān)閉訂單開始,請求參數(shù):{}", req);
            new AppServiceExtension.Builder().config(
                    new RSAAutoCertificateConfig.Builder()
                            .merchantId(request.getMchId())
                            .privateKey(request.getPrivateKey())
                            .merchantSerialNumber(request.getSerialNo())
                            .apiV3Key(request.getApiV3Key())
                            .build()
            ).build().closeOrder(req);
            log.info("關(guān)閉訂單結(jié)束");
 
            return CloseResponse.success(request.getOrderNo());
        } catch (Exception e) {
            log.error("微信關(guān)閉訂單失敗: {}", e);
            return CloseResponse.failure(Constants.OPERATE_ERROR_MSG, e.getMessage());
        }
    }
 
    @Override
    protected RefundResponse doRefund(RefundRequest request) {
        try {
            CreateRequest req = new CreateRequest();
            req.setOutTradeNo(request.getOrderNo());
            AmountReq amountReq = new AmountReq();
            amountReq.setTotal(request.getPayAmount().multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_UP).longValue());
            amountReq.setRefund(request.getRefundAmount().multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_UP).longValue());
            amountReq.setCurrency("CNY");
            req.setAmount(amountReq);
            req.setOutRefundNo(request.getRefundNo());
            req.setReason(request.getRefundReason());
            req.setNotifyUrl(request.getNotifyUrl());
 
            log.info("退款開始,請求參數(shù):{}", req);
            Refund res = new RefundService.Builder().config(
                    new RSAAutoCertificateConfig.Builder()
                            .merchantId(request.getMchId())
                            .privateKey(request.getPrivateKey())
                            .merchantSerialNumber(request.getSerialNo())
                            .apiV3Key(request.getApiV3Key())
                            .build()
            ).build().create(req);
            log.info("退款結(jié)束,返回參數(shù):{}", res);
 
            if (Objects.nonNull(res)) {
                return RefundResponse.builder().success(true).refundNo(res.getOutRefundNo()).build();
            }
            return RefundResponse.failure(Constants.OPERATE_ERROR_MSG, "退款失敗");
        } catch (Exception e) {
            log.error("微信退款失敗: {}", e);
            return RefundResponse.failure(Constants.OPERATE_ERROR_MSG, e.getMessage());
        }
    }
 
    @Override
    protected RefundResponse doQueryRefund(RefundRequest request) {
        try {
            QueryByOutRefundNoRequest req = new QueryByOutRefundNoRequest();
            req.setOutRefundNo(request.getRefundNo());
 
            log.info("退款查詢開始,請求參數(shù):{}", req);
            Refund res = new RefundService.Builder().config(
                    new RSAAutoCertificateConfig.Builder()
                            .merchantId(request.getMchId())
                            .privateKey(request.getPrivateKey())
                            .merchantSerialNumber(request.getSerialNo())
                            .apiV3Key(request.getApiV3Key())
                            .build()
            ).build().queryByOutRefundNo(req);
            log.info("退款查詢結(jié)束,返回參數(shù):{}", res);
 
            if (Objects.nonNull(res)) {
                PayStatus payStatus = PayStatus.WAITING;
                BigDecimal amount = null;
                LocalDateTime refundTime = null;
                if (Status.SUCCESS == res.getStatus()) {
                    // 成功
                    refundTime = LocalDateTime.parse(res.getSuccessTime());
                    payStatus = PayStatus.SUCCESS;
                } else if (Status.PROCESSING == res.getStatus()) {
                    // 處理中
                    payStatus = PayStatus.WAITING;
                } else if (Status.CLOSED == res.getStatus()) {
                    // 已關(guān)閉
                    payStatus = PayStatus.CANCELED;
                } else if (Status.ABNORMAL == res.getStatus()) {
                    // 失敗
                    payStatus = PayStatus.FAILED;
                }
 
                return RefundResponse.builder()
                        .success(true)
                        .orderNo(res.getOutTradeNo())
                        .refundNo(res.getOutRefundNo())
                        .refundId(res.getRefundId())
                        .refundStatus(payStatus)
                        .refundTime(refundTime)
                        .build();
            }
            return RefundResponse.failure(Constants.OPERATE_ERROR_MSG, "退款查詢失敗");
        } catch (Exception e) {
            log.error("微信退款查詢失敗: {}", e);
            return RefundResponse.failure(Constants.OPERATE_ERROR_MSG, e.getMessage());
        }
    }
 
    @Override
    public NotifyResponse handleNotify(NotifyRequest request) {
        try {
            log.info("微信回調(diào)處理開始...");
            HttpServletRequest servletRequest = request.getServletRequest();
            // 讀取請求體的信息
            ServletInputStream inputStream = servletRequest.getInputStream();
            StringBuffer stringBuffer = new StringBuffer();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String s;
            while ((s = bufferedReader.readLine()) != null) {
                stringBuffer.append(s);
            }
            log.info("微信回調(diào)處理,請求體參數(shù):{}", stringBuffer);
 
            // 初始化 NotificationParser
            NotificationParser parser = new NotificationParser(
                    new RSAAutoCertificateConfig.Builder()
                            .merchantId(request.getMchId())
                            .privateKey(request.getPrivateKey())
                            .merchantSerialNumber(request.getSerialNo())
                            .apiV3Key(request.getApiV3Key())
                            .build()
            );
            RequestParam requestParam = new RequestParam.Builder()
                    .serialNumber(servletRequest.getHeader("Wechatpay-Serial"))
                    .nonce(servletRequest.getHeader("Wechatpay-Nonce"))
                    .signature(servletRequest.getHeader("Wechatpay-Signature"))
                    .timestamp(servletRequest.getHeader("Wechatpay-Timestamp"))
                    .signType(servletRequest.getHeader("Wechatpay-Signature-Type"))
                    .body(stringBuffer.toString())
                    .build();
 
            log.info("微信回調(diào)處理,RequestParam:{}", requestParam);
 
            switch (request.getMethod()) {
                case TradeMethod.PAY:
                    Transaction transaction = parser.parse(requestParam, Transaction.class);
                    log.info("微信支付回調(diào)返回參數(shù):{}", transaction);
                    NotifyResponse payResponse = NotifyResponse.builder().success(true).orderNo(transaction.getOutTradeNo()).build();
                    if (Transaction.TradeStateEnum.SUCCESS == transaction.getTradeState()) {
                        // SUCCESS:支付成功
                        payResponse.setTransactionId(transaction.getTransactionId());
                        payResponse.setTime(LocalDateTime.parse(transaction.getSuccessTime()));
                        payResponse.setStatus(PayStatus.SUCCESS);
                    } else if (Transaction.TradeStateEnum.CLOSED == transaction.getTradeState() || Transaction.TradeStateEnum.REVOKED == transaction.getTradeState() || Transaction.TradeStateEnum.PAYERROR == transaction.getTradeState()) {
                        // CLOSED:已關(guān)閉、REVOKED:已撤銷、PAYERROR:支付失敗
                        payResponse.setStatus(PayStatus.FAILED);
                    } else {
                        // REFUND:轉(zhuǎn)入退款、NOTPAY:未支付、USERPAYING:用戶支付中
                        log.info("支付中的暫不處理:{}", transaction);
                    }
 
                    log.info("微信支付回調(diào)結(jié)束:{}", payResponse);
                    return payResponse;
                case TradeMethod.REFUND:
                    RefundNotification refund = parser.parse(requestParam, RefundNotification.class);
                    log.info("微信退款回調(diào)返回參數(shù):{}", refund);
                    NotifyResponse refundResponse = NotifyResponse.builder().success(true).refundNo(refund.getOutRefundNo()).build();
                    if (Status.SUCCESS == refund.getRefundStatus()) {
                        // SUCCESS:退款成功
                        refundResponse.setRefundId(refund.getRefundId());
                        refundResponse.setOrderNo(refund.getOutTradeNo());
                        refundResponse.setTransactionId(refund.getTransactionId());
                        refundResponse.setTime(LocalDateTime.parse(refund.getSuccessTime()));
                        refundResponse.setStatus(PayStatus.SUCCESS);
                    } else {
                        // ABNORMAL:退款異常、CLOSED:退款關(guān)閉
                        refundResponse.setRefundId(refund.getRefundId());
                        refundResponse.setOrderNo(refund.getOutTradeNo());
                        refundResponse.setTransactionId(refund.getTransactionId());
                        refundResponse.setTime(LocalDateTime.parse(refund.getCreateTime()));
                        refundResponse.setStatus(PayStatus.FAILED);
                    }
 
                    log.info("微信退款回調(diào)結(jié)束:{}", refundResponse);
                    return refundResponse;
                default:
                    return NotifyResponse.failure(Constants.OPERATE_ERROR_MSG, "不支持的回調(diào)方式");
            }
        } catch (Exception e) {
            log.error("微信回調(diào)處理失敗: {}", e);
            return NotifyResponse.failure(Constants.OPERATE_ERROR_MSG, e.getMessage());
        }
    }
 
    @Override
    public PayChannel getPayChannel() {
        return PayChannel.WECHAT_PAY;
    }
 
}

支付寶支付實(shí)現(xiàn) AlipayStrategy.java

@Slf4j
@Component
public class AlipayStrategy extends AbstractPayStrategy {
 
    @Override
    protected PayResponse doPay(PayRequest request) {
        try {
            // TODO 業(yè)務(wù)實(shí)現(xiàn)
            return null;
        } catch (Exception e) {
            throw new RuntimeException("支付寶支付失敗", e);
        }
    }
 
    @Override
    protected QueryResponse doQueryOrder(PayRequest request) {
        return null;
    }
 
    @Override
    protected CloseResponse doClose(PayRequest request) {
        return null;
    }
 
    @Override
    protected RefundResponse doRefund(RefundRequest request) {
        return null;
    }
 
    @Override
    protected RefundResponse doQueryRefund(RefundRequest request) {
        return null;
    }
 
    @Override
    public PayChannel getPayChannel() {
        return PayChannel.ALI_PAY;
    }
 
    @Override
    public NotifyResponse handleNotify(NotifyRequest request) {
        return null;
    }
 
}

銀聯(lián)支付實(shí)現(xiàn) UnionPayStrategy.java

@Slf4j
@Component
public class UnionPayStrategy extends AbstractPayStrategy {
 
    @Override
    protected PayResponse doPay(PayRequest request) {
        try {
            // TODO 業(yè)務(wù)實(shí)現(xiàn)
            return null;
        } catch (Exception e) {
            throw new RuntimeException("銀聯(lián)支付失敗", e);
        }
    }
 
    @Override
    protected QueryResponse doQueryOrder(PayRequest request) {
        return null;
    }
 
    @Override
    protected CloseResponse doClose(PayRequest request) {
        return null;
    }
 
    @Override
    protected RefundResponse doRefund(RefundRequest request) {
        return null;
    }
 
    @Override
    protected RefundResponse doQueryRefund(RefundRequest request) {
        return null;
    }
 
    @Override
    public PayChannel getPayChannel() {
        return PayChannel.UNION_PAY;
    }
 
    @Override
    public NotifyResponse handleNotify(NotifyRequest request) {
        return null;
    }
 
}

支付策略工廠 PayStrategyFactory.java

@Component
public class PayStrategyFactory {
 
    private final Map<PayChannel, PayStrategy> strategyMap = new ConcurrentHashMap<>();
 
    public PayStrategyFactory(List<PayStrategy> strategies) {
        for (PayStrategy strategy : strategies) {
            strategyMap.put(strategy.getPayChannel(), strategy);
        }
    }
 
    public PayStrategy getStrategy(PayChannel payChannel) {
        PayStrategy strategy = strategyMap.get(payChannel);
        if (strategy == null) {
            throw new RuntimeException("不支持的支付渠道:" + payChannel.getName());
        }
        return strategy;
    }
 
    public PayStrategy getStrategy(String channelCode) {
        PayChannel payChannel = PayChannel.getByCode(channelCode);
        if (payChannel == null) {
            throw new RuntimeException("不支持的支付渠道代碼:" + channelCode);
        }
        return getStrategy(payChannel);
    }
 
}

統(tǒng)一支付服務(wù) PayService.java

@Slf4j
@Service
public class PayService {
 
    @Autowired
    private PayStrategyFactory payStrategyFactory;
 
    /**
     * @Description: 支付
     * @Date: 2025/11/21
     * @Param: [request]
     **/
    public PayResponse pay(PayRequest request) {
        PayStrategy strategy = payStrategyFactory.getStrategy(request.getPayChannel());
        return strategy.pay(request);
    }
 
    /**
     * @Description: 查詢訂單
     * @Date: 2025/11/21
     * @Param: [request]
     **/
    public QueryResponse queryOrder(PayRequest request) {
        PayStrategy strategy = payStrategyFactory.getStrategy(request.getPayChannel());
        return strategy.queryOrder(request);
    }
 
    /**
     * @Description: 關(guān)閉訂單
     * @Date: 2025/11/21
     * @Param: [request]
     **/
    public CloseResponse close(PayRequest request) {
        PayStrategy strategy = payStrategyFactory.getStrategy(request.getPayChannel());
        return strategy.close(request);
    }
 
    /**
     * @Description: 退款
     * @Date: 2025/11/21
     * @Param: [payChannel, request]
     **/
    public RefundResponse refund(PayChannel payChannel, RefundRequest request) {
        PayStrategy strategy = payStrategyFactory.getStrategy(payChannel);
        return strategy.refund(request);
    }
 
    /**
     * @Description: 退款查詢
     * @Date: 2025/11/21
     * @Param: [payChannel, request]
     **/
    public RefundResponse queryRefund(PayChannel payChannel, RefundRequest request) {
        PayStrategy strategy = payStrategyFactory.getStrategy(payChannel);
        return strategy.queryRefund(request);
    }
 
    /**
     * @Description: 處理回調(diào)
     * @Date: 2025/11/21
     * @Param: [request]
     **/
    public NotifyResponse handleNotify(NotifyRequest request) {
        PayStrategy strategy = payStrategyFactory.getStrategy(request.getPayChannel());
        return strategy.handleNotify(request);
    }
 
}

使用示例

@Service
public class OrderService {
 
    @Autowired
    private PayService payService;
 
    public void createOrderAndPay() {
        // 創(chuàng)建支付請求
        PayRequest request = new PayRequest();
 
        // 公共參數(shù)
        request.setAppId("wxd678efxxxxxxxxxxxxxxxxx");
        request.setMchId("123xxxxxxxx");
        request.setSerialNo("1DDE55AD98Exxxxxxxxxx");
        request.setPrivateKey("XXXXXXXXXXXXXXXXXXXXXXXXX");
        request.setPublicKey("XXXXXXXXXXXXXXXXXXXXXXXXXX");
        request.setApiV3Key("XXXXXXXXXXXXXXXXXXXXXX");
 
        // 訂單參數(shù)
        request.setPayChannel(PayChannel.WECHAT_PAY);
        request.setTradeType(TradeType.APP);
        request.setOrderNo("ORDER_" + System.currentTimeMillis());
        request.setAmount(100); // 1元
        request.setDescription("測試商品");
        request.setClientIp("127.0.0.1");
 
        // 發(fā)起支付
        PayResponse response = payService.pay(request);
 
        if (response.isSuccess()) {
            // 支付創(chuàng)建成功,返回支付參數(shù)給前端
            System.out.println("支付參數(shù):" + response.getPayParams());
        } else {
            // 處理支付失敗
            System.out.println("支付失?。? + response.getErrorMsg());
        }
    }
}

到此這篇關(guān)于SpringBoot 支付渠道實(shí)現(xiàn)統(tǒng)一的支付服務(wù)的文章就介紹到這了,更多相關(guān)SpringBoot 支付渠道統(tǒng)一支付內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 簡易JDBC框架實(shí)現(xiàn)過程詳解

    簡易JDBC框架實(shí)現(xiàn)過程詳解

    這篇文章主要介紹了簡易JDBC框架實(shí)現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • mybatis-plus 處理大數(shù)據(jù)插入太慢的解決

    mybatis-plus 處理大數(shù)據(jù)插入太慢的解決

    這篇文章主要介紹了mybatis-plus 處理大數(shù)據(jù)插入太慢的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 使用SpringBoot和JPA實(shí)現(xiàn)批量處理新增、修改

    使用SpringBoot和JPA實(shí)現(xiàn)批量處理新增、修改

    最近項(xiàng)目需要在JPA中使用ID進(jìn)行批量更新,所以下面這篇文章主要給大家介紹了關(guān)于使用SpringBoot和JPA實(shí)現(xiàn)批量處理新增、修改的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • 淺析JDK12的五大重要新特性(推薦)

    淺析JDK12的五大重要新特性(推薦)

    這篇文章主要介紹了JDK12的五大重要新特性,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05
  • 輕松掌握J(rèn)ava備忘錄模式

    輕松掌握J(rèn)ava備忘錄模式

    這篇文章主要幫助大家輕松掌握J(rèn)ava備忘錄模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • 解決springboot application.properties server.port配置問題

    解決springboot application.properties server.port配置問題

    這篇文章主要介紹了解決springboot application.properties server.port配置問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 扒一扒 Java 中的枚舉類型

    扒一扒 Java 中的枚舉類型

    這篇文章主要給大家介紹了Java中枚舉類型的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • 使用Java自定義注解實(shí)現(xiàn)一個簡單的令牌桶限流器

    使用Java自定義注解實(shí)現(xiàn)一個簡單的令牌桶限流器

    限流是在分布式系統(tǒng)中常用的一種策略,它可以有效地控制系統(tǒng)的訪問流量,保證系統(tǒng)的穩(wěn)定性和可靠性,在本文中,我將介紹如何使用Java自定義注解來實(shí)現(xiàn)一個簡單的令牌桶限流器,需要的朋友可以參考下
    2023-10-10
  • 零基礎(chǔ)學(xué)Java:Java開發(fā)工具 Eclipse 安裝過程創(chuàng)建第一個Java項(xiàng)目及Eclipse的一些基礎(chǔ)使用技巧

    零基礎(chǔ)學(xué)Java:Java開發(fā)工具 Eclipse 安裝過程創(chuàng)建第一個Java項(xiàng)目及Eclipse的一些基礎(chǔ)使用技巧

    這篇文章主要介紹了零基礎(chǔ)學(xué)Java:Java開發(fā)工具 Eclipse 安裝過程創(chuàng)建第一個Java項(xiàng)目及Eclipse的一些基礎(chǔ)使用技巧,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • Spring中的事務(wù)管理實(shí)例詳解

    Spring中的事務(wù)管理實(shí)例詳解

    這篇文章主要介紹了Spring中的事務(wù)管理,以實(shí)例形式詳細(xì)分析了事務(wù)的概念與特性以及事物管理的具體用法,需要的朋友可以參考下
    2014-11-11

最新評論

芜湖县| 治县。| 铜鼓县| 达州市| 涟源市| 大同县| 甘德县| 上蔡县| 郎溪县| 泽州县| 象州县| 蓬溪县| 磴口县| 玉溪市| 昌图县| 新乡市| 葵青区| 濉溪县| 博白县| 苗栗县| 临沭县| 突泉县| 子洲县| 交城县| 英超| 五寨县| 洛扎县| 陇川县| 南岸区| 博罗县| 日照市| 河东区| 武穴市| 辽宁省| 阳西县| 集安市| 册亨县| 项城市| 葫芦岛市| 新营市| 电白县|