支付宝芝麻免押支付集成指南及技术对接验收(Java版)

支付宝免押支付集成指南

1. 前置准备

1.1 企业支付宝账号开通产品(预授权支付、芝麻免押)

所需参数:信用服务ID、信用服务类目、商户PID

操作流程:

  1. 进入B站信用服务管理平台

  2. 配置信用服务

  3. 添加验收白名单

1.2 O站开放平台配置

所需参数:应用公钥证书、支付宝公钥证书、支付宝根证书、私钥、AppId

操作流程:

  1. 进入开放平台创建小程序
  2. 配置接口加签方式(证书模式)
  3. 设置应用网关(芝麻免押回调接口)
  4. 配置服务器域白名单(后端域名)

2. 技术验收要求

  • 需要完成两个订单:一个支付成功,一个支付失败
  • 关键参数获取:
    • 交易单号(trade_no)
    • 授权单号(auth_no)
    • 用户ID(userId2088xxx)

3. 接口清单

功能 接口名称 接口代码
资金冻结 alipay.fund.auth.order.app.freeze freeze()
发起扣款 alipay.trade.pay pay()
资金解冻 alipay.fund.auth.order.unfreeze unfreeze()
交易关闭 alipay.trade.close close()
交易退款 alipay.trade.refund refund()
授权撤销 alipay.fund.auth.operation.cancel cancel()

4. 代码实现

4.1 支付宝配置类

java 复制代码
package com.example.config;

import com.alipay.api.AlipayConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AliConfig {

    @Bean
    public AlipayConfig getConfig() {
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
        alipayConfig.setAppId("your_app_id");
        alipayConfig.setPrivateKey("your_private_key");
        alipayConfig.setFormat("json");
        alipayConfig.setCharset("UTF-8");
        alipayConfig.setSignType("RSA2");
        alipayConfig.setAppCertPath("cert/appCertPublicKey.crt");
        alipayConfig.setAlipayPublicCertPath("cert/alipayCertPublicKey_RSA2.crt");
        alipayConfig.setRootCertPath("cert/alipayRootCert.crt");
        return alipayConfig;
    }
}

4.2 支付接口

接口重要参数
扩展参数 参数值 对应场景/api
ExtraParam CREDIT_RENT_OFFLINE 信用服务类目->freeze接口
DepositProductMode DEPOSIT_ONLY 芝麻免押受理台模式
bizContent "enable_pay_channels", "balance" 关闭交易场景->pay接口
java 复制代码
package com.example.controller;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.example.config.AliConfig;
import com.example.model.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RequestMapping("/alipay")
@RestController
@Slf4j
public class AliPayController {

  @Autowired
  private AliConfig aliConfig;
  // 回调接口需要外网访问,建议本地开启内网穿透 对应本地8080端口也就是NotifyController类的接口
  private static final String ALIPAY_NOTIFY_URL = "https://60155d5f.r26.cpolar.top/notify";

  /**
   * 创建免押订单接口
   */
  @RequestMapping("/freeze")
  public String freeze() throws AlipayApiException {

    String OutOrderNo = System.currentTimeMillis() + "";
    String OutRequestNo = System.currentTimeMillis() + "";

    // 构造client
    AlipayClient alipayClient = new DefaultAlipayClient(aliConfig.getConfig());

    // 构造请求参数以调用接口
    AlipayFundAuthOrderAppFreezeRequest request = new AlipayFundAuthOrderAppFreezeRequest();
    AlipayFundAuthOrderAppFreezeModel model = new AlipayFundAuthOrderAppFreezeModel();

    // 设置订单标题
    model.setOrderTitle("租车押金");

    // 设置商户授权资金订单号
    model.setOutOrderNo(OutOrderNo);

    // 设置商户本次资金操作的请求流水号
    model.setOutRequestNo(OutRequestNo);

    // 设置需要冻结的金额
    model.setAmount("0.01");

    // 设置预授权订单相对超时时间
    model.setTimeoutExpress("2d");

    // 设置销售产品码
    model.setProductCode("PRE_AUTH_ONLINE");

    // 设置业务扩展参数 信用服务类目CREDIT_RENT_OFFLINE
    model.setExtraParam("{\"category\": \"CREDIT_RENT_OFFLINE\",\"serviceId\": \"信用服务id\"}");

    // 设置免押受理台模式
    model.setDepositProductMode("DEPOSIT_ONLY");

    request.setBizModel(model);
    request.setNotifyUrl(ALIPAY_NOTIFY_URL);
    // 发送请求
    AlipayFundAuthOrderAppFreezeResponse response = alipayClient.sdkExecute(request);
    log.info("线上资金授权冻结接口:{}", response.getBody());
    return response.getBody();
  }

  /**
   * 发起扣款接口 alipay.trade.pay
   * bizContent和BizModel不能同时使用,model未封装enable_pay_channels参数
   */
  @RequestMapping("/pay")
  public R<JSONObject> pay(@RequestBody Map<String, String> params) throws AlipayApiException {
    AlipayClient alipayClient = new DefaultAlipayClient(aliConfig.getConfig());

    // 构造请求参数以调用接口
    AlipayTradePayRequest request = new AlipayTradePayRequest();

    JSONObject bizContent = new JSONObject();
    // 商家自定义订单号
    bizContent.put("out_trade_no", params.get("outTradeNo"));
    // 创建免押订单接口freeze回调接口返回内容中的auth_no
    bizContent.put("auth_no", params.get("authNo"));
    // 指定付款方式为余额支付,关闭交易场景
    // bizContent.put("enable_pay_channels", "balance");
    bizContent.put("product_code", "PREAUTH_PAY");
    bizContent.put("total_amount", "0.01");
    bizContent.put("subject", "租车租金");
    bizContent.put("auth_confirm_mode", "COMPLETE");
    request.setBizContent(bizContent.toString());
    request.setNotifyUrl(ALIPAY_NOTIFY_URL);
    AlipayTradePayResponse response = alipayClient.certificateExecute(request);
    JSONObject jsonObject = JSONObject.parseObject(response.getBody());
    log.info("发起扣款接口参数:{}", response.getBody());
    return R.ok(jsonObject);
  }

  /**
   * 资金授权解冻接口 alipay.fund.auth.order.unfreeze
   * 以authNo为准,OutRequestNo随便填 如报错参数异常或参数缺失则是某次请求已经使用过该OutRequestNo
   */

  @RequestMapping("/unfreeze")
  public String unfreeze(@RequestBody Map<String, String> params) throws AlipayApiException {
    AlipayClient alipayClient = new DefaultAlipayClient(aliConfig.getConfig());
    // 构造请求参数以调用接口
    AlipayFundAuthOrderUnfreezeRequest request = new AlipayFundAuthOrderUnfreezeRequest();
    AlipayFundAuthOrderUnfreezeModel model = new AlipayFundAuthOrderUnfreezeModel();

    // 设置支付宝资金授权订单号
    model.setAuthNo(params.get("authNo"));

    // 设置解冻请求流水号 保证不重复
    model.setOutRequestNo(params.get("outRequestNo"));

    // 设置本次操作解冻的金额
    model.setAmount("0.01");

    // 设置商户对本次解冻操作的附言描述
    model.setRemark("2025-08期解冻0.01元");

    request.setBizModel(model);

    AlipayFundAuthOrderUnfreezeResponse response = alipayClient.certificateExecute(request);
    log.info("资金授权解冻:{}", response.getBody());

    return response.getBody();
  }

  /**
   * 统一收单交易关闭接口 alipay.trade.close
   */
  @RequestMapping("/close")
  public String close(@RequestBody Map<String, String> params) throws AlipayApiException {
    AlipayClient alipayClient = new DefaultAlipayClient(aliConfig.getConfig());

    // 构造请求参数以调用接口
    AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
    AlipayTradeCloseModel model = new AlipayTradeCloseModel();

    // 设置该交易在支付宝系统中的交易流水号
    model.setTradeNo(params.get("tradeNo"));

    request.setBizModel(model);

    AlipayTradeCloseResponse response = alipayClient.certificateExecute(request);
    log.info("交易关闭:{}", response.getBody());
    return response.getBody();
  }

  /**
   * 统一收单交易退款接口 alipay.trade.refund
   */

  @RequestMapping("/refund")
  public R<String> refund(@RequestBody Map<String, String> params) throws AlipayApiException {
    AlipayClient alipayClient = new DefaultAlipayClient(aliConfig.getConfig());

    // 构造请求参数以调用接口
    AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
    AlipayTradeRefundModel model = new AlipayTradeRefundModel();
    // 设置商家订单号
    model.setOutTradeNo(params.get("outTradeNo"));
    // 设置退款金额
    model.setRefundAmount("0.01");
    // 设置退款原因说明
    model.setRefundReason("正常退款");
    request.setBizModel(model);
    AlipayTradeRefundResponse response = alipayClient.certificateExecute(request);
    log.info("交易退款:{}", response.getBody());
    return R.ok(response.getBody());
  }

  /**
   * 资金授权撤销接口 alipay.fund.auth.operation.cancel
   * 此接口可以关闭免押订单,参数可以在芝麻免押下单成功记录获取
   */
  @RequestMapping("/cancel")
  public String cancel(@RequestBody Map<String, String> params) throws AlipayApiException {
    AlipayClient alipayClient = new DefaultAlipayClient(aliConfig.getConfig());

    // 构造请求参数以调用接口
    AlipayFundAuthOperationCancelRequest request = new AlipayFundAuthOperationCancelRequest();
    AlipayFundAuthOperationCancelModel model = new AlipayFundAuthOperationCancelModel();

    // 支付宝订单号
    model.setOperationId(params.get("operationId"));
    // 授权号
    model.setAuthNo(params.get("authNo"));
    model.setRemark("撤销授权");
    request.setBizModel(model);
    AlipayFundAuthOperationCancelResponse response = alipayClient.certificateExecute(request);
    log.info("资金授权撤销:{}", response.getBody());
    return response.getBody();
  }

}

4.3 回调接口

java 复制代码
package com.example.controller;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConfig;
import com.alipay.api.internal.util.AlipaySignature;
import com.example.config.AliConfig;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@RestController
@Slf4j
public class NotifyController {

    @Autowired
    private AliConfig aliConfig;

    /**
     * 支付宝异步通知
     */
    @RequestMapping("/notify")
    public String notify(HttpServletRequest request) throws AlipayApiException {
        Map<String, String> params = convertRequestParamsToMap(request);
        String paramsJson = JSON.toJSONString(params);
        AlipayConfig alipayConfig = aliConfig.getConfig();
        boolean signVerified = AlipaySignature.rsaCertCheckV1(params, alipayConfig.getAlipayPublicCertPath(),
                alipayConfig.getCharset(), alipayConfig.getSignType());
        if (signVerified) {
            log.info("支付宝异步通知验签成功");
            log.info("支付宝异步通知: {}", paramsJson);
            return "success";
        }
        return "failure";
    }

    private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
        Map<String, String> retMap = new HashMap<>();

        Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();

        for (Map.Entry<String, String[]> entry : entrySet) {
            String name = entry.getKey();
            String[] values = entry.getValue();
            int valLen = values.length;

            if (valLen == 1) {
                retMap.put(name, values[0]);
            } else if (valLen > 1) {
                StringBuilder sb = new StringBuilder();
                for (String val : values) {
                    sb.append(",").append(val);
                }
                retMap.put(name, sb.substring(1));
            } else {
                retMap.put(name, "");
            }
        }

        return retMap;
    }

}

4.4 日志配置

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<configuration debug="true">

    <property name="LOG-DIR" value="./logs"/>
    <property name="LOG-PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%-5level] - %m%n"/>
    <property name="APP-NAME" value="zmPayDemo"/>

    <!--控制台-->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>UTF-8</charset>
            <pattern>${LOG-PATTERN}</pattern>
        </encoder>
    </appender>

    <!--日志文件-->
    <appender name="FILE-ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--滚动策略,按照时间滚动 TimeBasedRollingPolicy-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--文件路径,定义了日志的切分方式,把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
            <FileNamePattern>${LOG-DIR}/${APP-NAME}-%d{yyyyMMdd}.log</FileNamePattern>
            <!--只保留最近30天的日志-->
            <maxHistory>30</maxHistory>
            <!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志-->
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <!--日志输出编码格式化-->
        <encoder>
            <charset>UTF-8</charset>
            <pattern>${LOG-PATTERN}</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE-ALL"/>
    </root>

</configuration>

5.前端示例

  • 小程序示例
  • index.axml
js 复制代码
<view class="container">

  <!-- 芝麻免押受理台 -->

  <view class="section">

    <view class="section-title">芝麻免押</view>

    <button class="btn" onTap="onPullPay" type="primary">拉起芝麻免押受理台</button>

  </view>

 

  <!-- 发起扣款 -->

  <view class="section">

    <view class="section-title">发起扣款</view>

    <view class="input-group">

      <view class="input-item">

        <text class="label">outTradeNo:</text>

        <input class="input" placeholder="请输入订单号" value="{{payOutTradeNo}}" onInput="onPayOutTradeNo" />

      </view>

      <view class="input-item">

        <text class="label">authNo:</text>

        <input class="input" placeholder="请输入授权号" value="{{payAuthNo}}" onInput="onPayAuthNo" />

      </view>

      <button class="btn" onTap="onPay" type="primary">发起扣款</button>

    </view>

  </view>

 

  <!-- 完结订单 -->

  <view class="section">

    <view class="section-title">完结订单</view>

    <view class="input-group">

      <view class="input-item">

        <text class="label">outTradeNo:</text>

        <input class="input" placeholder="请输入订单号" />

      </view>

      <view class="input-item">

        <text class="label">authNo:</text>

        <input class="input" placeholder="请输入授权号" />

      </view>

      <button class="btn" onTap="pay" type="primary">完结订单</button>

    </view>

  </view>

 

  <!-- 订单退款 -->

  <view class="section">

    <view class="section-title">关闭订单</view>

    <view class="input-group">

      <view class="input-item">

        <text class="label">outTradeNo:</text>

        <input class="input" placeholder="请输入订单号" value="{{closeOutTradeNo}}" onInput="onCloseOutTradeNo" />

      </view>

      <button class="btn" onTap="close" type="primary">关闭订单</button>

    </view>

  </view>

 

  <!-- 关闭订单 -->

  <view class="section">

    <view class="section-title">订单退款</view>

    <view class="input-group">

      <view class="input-item">

        <text class="label">outTradeNo:</text>

        <input class="input" placeholder="请输入订单号" value="{{refundOutTradeNo}}" onInput="onRefundOutTradeNo" />

      </view>

      <button class="btn" onTap="refund" type="primary">立即退款</button>

    </view>

  </view>

</view>
  • index.acss
css 复制代码
.container {

  padding: 20px;

  background-color: #f5f5f5;

}

  


.section {

  margin-bottom: 30px;

  background-color: #fff;

  border-radius: 10px;

  padding: 15px;

  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);

}

  


.section-title {

  font-size: 18px;

  font-weight: bold;

  margin-bottom: 15px;

  color: #333;

}

  


.input-group {

  margin-top: 10px;

}

  


.input-item {

  margin-bottom: 15px;

}

  


.label {

  display: block;

  margin-bottom: 5px;

  color: #666;

}

  


.input {

  width: 100%;

  height: 40px;

  border: 1px solid #ddd;

  border-radius: 4px;

  padding: 0 10px;

  box-sizing: border-box;

}

  


.btn {

  margin-top: 10px;

  width: 100%;

}
  • index.js
js 复制代码
Page({

  data: {

    // 发起扣款页面数据

    payOutTradeNo: '',

    payAuthNo: '',

   

    // 完结订单页面数据

    finishOutTradeNo: '',

    finishAuthNo: '',

   

    // 关闭订单页面数据

    closeOutTradeNo: '',

    closeAuthNo: '',

    url: 'https://60155d5f.r26.cpolar.top',

  


    // 订单退款

    refundOutTradeNo: '',

  },

 

  // 处理输入框变化

  onInputChange(e) {

    const { field } = e.currentTarget.dataset;

    this.setData({

      [field]: e.detail.value

    });

  },

 

  // 拉起芝麻免押受理台

  onPullPay() {

    my.request({

      url: this.data.url+'/alipay/freeze',

      method: 'POST',

      success: (res) => {

        my.tradePay({

          orderStr : res.data,

          success: (res) => {

            my.alert({

              title: '支付结果',

              content: JSON.stringify(res),

            });

          },

          fail: (e) => {

            my.alert({

              title: '支付失败',

              content: JSON.stringify(e),

            });

          }

        })

      },

      fail: (e) => {

        my.hideLoading();

        my.alert({

          title: '请求失败',

          content: JSON.stringify(e),

        });

      }

    });

  },

 

  //发起扣款 输入

  onPayOutTradeNo(e) {

    this.data.payOutTradeNo = e.detail.value;

  },

  onPayAuthNo(e) {

    this.data.payAuthNo = e.detail.value;

  },

  // 发起扣款

  onPay() {

    console.log(this.data)

    my.request({

      url: this.data.url+'/alipay/pay',

      data : {

        outTradeNo: this.data.payOutTradeNo,

        authNo: this.data.payAuthNo,

      },

      method: 'POST',

      success: (res) => {

        my.tradePay({

          success: (res2) => {

            tradeNo: res2.data.alipay_trade_pay_response.trade_no,

            my.alert({

              title: '支付结果',

              content: JSON.stringify(res),

            });

          },

          fail: (e) => {

            my.alert({

              title: '支付失败',

              content: JSON.stringify(e),

            });

          }

        })

      },

      fail: (e) => {

        my.hideLoading();

        my.alert({

          title: '请求失败',

          content: JSON.stringify(e),

        });

      }

    });

  },

  pay() {

    if (!this.data.payOutTradeNo || !this.data.payAuthNo) {

      my.alert({

        title: '参数错误',

        content: '请输入订单号和授权号',

      });

      return;

    }

   

    my.showLoading({

      title: '发起扣款中...',

    });

   

    // 实际应用中替换为您的API请求

    setTimeout(() => {

      my.hideLoading();

      my.alert({

        title: '扣款成功',

        content: `订单号:${this.data.payOutTradeNo}\n授权号:${this.data.payAuthNo}\n金额:0.01元`,

      });

     

      // 实际请求示例(请替换为您的API)

      /*

      my.request({

        url: 'https://your-domain/alipay/pay',

        method: 'POST',

        data: {

          outTradeNo: this.data.payOutTradeNo,

          authNo: this.data.payAuthNo

        },

        success: (res) => {

          my.hideLoading();

          const tradeNO = res.data.data;

          my.tradePay({

            tradeNO,

            success: (res) => {

              my.alert({

                title: '支付结果',

                content: JSON.stringify(res),

              });

            },

            fail: (e) => {

              my.alert({

                title: '支付失败',

                content: JSON.stringify(e),

              });

            }

          })

        },

        fail: (e) => {

          my.hideLoading();

          my.alert({

            title: '请求失败',

            content: JSON.stringify(e),

          });

        }

      });

      */

    }, 2000);

  },

 

  // 完结订单

  finish() {

    if (!this.data.finishOutTradeNo || !this.data.finishAuthNo) {

      my.alert({

        title: '参数错误',

        content: '请输入订单号和授权号',

      });

      return;

    }

   

    my.showLoading({

      title: '完结处理中...',

    });

   

    // 模拟完结订单请求

    setTimeout(() => {

      my.hideLoading();

      my.alert({

        title: '完结成功',

        content: `订单号:${this.data.finishOutTradeNo}\n授权号:${this.data.finishAuthNo}`,

      });

     

      // 实际请求示例(请替换为您的API)

      /*

      my.request({

        url: 'https://your-domain/alipay/finish',

        method: 'POST',

        data: {

          outTradeNo: this.data.finishOutTradeNo,

          authNo: this.data.finishAuthNo

        },

        success: (res) => {

          my.hideLoading();

          my.showToast({

            title: '订单已完结',

            icon: 'success',

          });

        },

        fail: (e) => {

          my.hideLoading();

          my.alert({

            title: '完结失败',

            content: JSON.stringify(e),

          });

        }

      });

      */

    }, 1500);

  },

 

 

  //关闭扣款 输入

  onCloseOutTradeNo(e) {

    this.data.closeOutTradeNo = e.detail.value;

  },

  // 关闭订单

  close() {

    // 模拟关闭订单请求

    my.request({

      url: this.data.url+'/alipay/close',

      method: 'POST',

      data: {

        tradeNo: this.data.closeOutTradeNo,

        authNo: this.data.closeAuthNo

      },

      success: (res) => {

        my.hideLoading();

        my.showToast({

          title: '订单已关闭',

          icon: 'success',

        });

      },

      fail: (e) => {

        my.hideLoading();

        my.alert({

          title: '关闭失败',

          content: JSON.stringify(e),

        });

      }

    });

  },

 

 

  //订单退款

  onRefundOutTradeNo(e) {

    this.data.refundOutTradeNo = e.detail.value;

  },

  // 订单退款

  refund() {

    // 模拟订单退款请求

    my.request({

      url: this.data.url+'/alipay/refund',

      method: 'POST',

      data: {

        outTradeNo: this.data.refundOutTradeNo,

      },

      success: (res) => {

        my.hideLoading();

        my.showToast({

          title: '订单已关闭',

          icon: 'success',

        });

      },

      fail: (e) => {

        my.hideLoading();

        my.alert({

          title: '关闭失败',

          content: JSON.stringify(e),

        });

      }

    });

  }

});

6.完成效果

  • 芝麻免押台
  • 下单示例
  • 支付示例
  • 退款示例

7.键注意事项

  1. 证书配置:确保证书文件路径正确,推荐使用绝对路径
  2. 回调URL:必须为公网可访问地址,本地开发可使用内网穿透
  3. 参数验证:所有接口调用前应验证输入参数有效性
  4. 错误处理:妥善处理支付宝接口返回的错误码和错误信息
  5. 幂等性:资金操作类接口需保证幂等性设计

8.常见问题解决

问题现象 可能原因 解决方案
验签失败 证书路径错误/证书内容不匹配 检查证书路径和内容
接口调用失败 参数格式错误/必填参数缺失 检查请求参数和文档
回调未收到 网络问题/应用网关配置错误 检查服务器网络和应用网关配置
资金操作异常 订单状态不满足条件 检查订单当前状态
相关推荐
肩塔didi22 分钟前
用 Pixi 管理 Python 项目:打通Conda 和 PyPI 的边界
后端·python·github
teeeeeeemo30 分钟前
Ajax、Axios、Fetch核心区别
开发语言·前端·javascript·笔记·ajax
Juchecar31 分钟前
TypeScript对 null/undefined/==/===/!=/!== 等概念的支持,以及建议用法
javascript
柏成36 分钟前
基于 pnpm + monorepo 的 Qiankun微前端解决方案(内置模块联邦)
前端·javascript·面试
dylan_QAQ37 分钟前
【附录】相对于BeanFactory ,ApplicationContext 做了哪些企业化的增强?
后端·spring
唐诗1 小时前
VMware Mac m系列安装 Windws 11,保姆级教程
前端·后端·github
Lx3521 小时前
Hadoop新手必知的10个高效操作技巧
hadoop·后端
写bug写bug1 小时前
搞懂Spring任务执行器和调度器模型
java·后端·spring
二闹1 小时前
TCP三次握手的智慧:为什么不是两次或四次?
后端·tcp/ip
熊猫片沃子2 小时前
Maven在使用过程中的核心知识点总结
java·后端·maven