通联支付API集成(适用于SpringBoot)

目标:

  • 学习如何使用Java与通联支付API进行交互

  • 实现一个简单的支付下单和查询订单状态的示例

所需材料:

  • 通联支付API文档

官方文档icon-default.png?t=N7T8https://aipboss.allinpay.com/know/devhelp/main.php?pid=38#mid=313

  • 通联支付加签代码SybUtil

package com.allinpay.common;import net.sf.json.JSONObject;
import org.apache.tomcat.util.codec.binary.Base64;import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;@SuppressWarnings("all")
public class SybUtil {/*** js转化为实体** @param <T>* @param jsonstr* @param cls* @return*/public static <T> T json2Obj(String jsonstr, Class<T> cls) {JSONObject jo = JSONObject.fromObject(jsonstr);T obj = (T) JSONObject.toBean(jo, cls);return obj;}/*** md5** @param b* @return*/public static String md5(byte[] b) {try {MessageDigest md = MessageDigest.getInstance("MD5");md.reset();md.update(b);byte[] hash = md.digest();StringBuffer outStrBuf = new StringBuffer(32);for (int i = 0; i < hash.length; i++) {int v = hash[i] & 0xFF;if (v < 16) {outStrBuf.append('0');}outStrBuf.append(Integer.toString(v, 16).toLowerCase());}return outStrBuf.toString();} catch (NoSuchAlgorithmException e) {e.printStackTrace();return new String(b);}}/*** 判断字符串是否为空** @param s* @return*/public static boolean isEmpty(String s) {if (s == null || "".equals(s.trim()))return true;return false;}/*** 生成随机码** @param n* @return*/public static String getValidatecode(int n) {Random random = new Random();String sRand = "";n = n == 0 ? 4 : n;// default 4for (int i = 0; i < n; i++) {String rand = String.valueOf(random.nextInt(10));sRand += rand;}return sRand;}public static boolean validSign(TreeMap<String, String> param,String appkey, String signType) throws Exception {if (param != null && !param.isEmpty()) {if (!param.containsKey("sign"))return false;String sign = param.remove("sign");if ("MD5".equals(signType)) {// 如果是md5则需要把md5的key加入到排序param.put("key", appkey);}StringBuilder sb = new StringBuilder();for (Map.Entry<String, String> entry : param.entrySet()) {if (entry.getValue() != null && entry.getValue().length() > 0) {sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");}}if (sb.length() > 0) {sb.deleteCharAt(sb.length() - 1);}if ("MD5".equals(signType)) {return sign.toLowerCase().equals(md5(sb.toString().getBytes("UTF-8")).toLowerCase());} else {return rsaVerifyPublickey(sb.toString(), sign, appkey, "UTF-8");}}return false;}public static boolean rsaVerifyPublickey(String content, String sign,String publicKey, String charset) throws Exception {try {PublicKey pubKey = getPublicKeyFromX509("RSA",Base64.decodeBase64(publicKey.getBytes()));return rsaVerifyPublickey(content, sign, pubKey, charset);} catch (Exception e) {e.printStackTrace();throw new Exception("RSAcontent = " + content + ",sign=" + sign+ ",charset = " + charset, e);}}public static boolean rsaVerifyPublickey(String content, String sign,PublicKey pubKey, String charset) throws Exception {try {java.security.Signature signature = java.security.Signature.getInstance("SHA1WithRSA");signature.initVerify(pubKey);if (charset == null || "".equals(charset)) {signature.update(content.getBytes());} else {signature.update(content.getBytes(charset));}return signature.verify(Base64.decodeBase64(sign.getBytes()));} catch (Exception e) {throw e;}}public static String unionSign(TreeMap<String, String> params,String appkey,String signType) throws Exception {// TODO Auto-generated method stubparams.remove("sign");if ("MD5".equals(signType)) {// 如果是md5则需要把md5的key加入到排序params.put("key", appkey);}StringBuilder sb = new StringBuilder();for (Map.Entry<String, String> entry : params.entrySet()) {if (entry.getValue() != null && entry.getValue().length() > 0) {sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");}}if (sb.length() > 0) {sb.deleteCharAt(sb.length() - 1);}String sign = "";if ("MD5".equals(signType)) {System.out.println(sb.toString());sign = md5(sb.toString().getBytes("UTF-8"));// 记得是md5编码的加签params.remove("key");} else {sign = rsaSign(sb.toString(), appkey, "UTF-8");}return sign;}public static String rsaSign(String content, String privateKey,String charset) throws Exception {PrivateKey priKey = getPrivateKeyFromPKCS8("RSA",Base64.decodeBase64(privateKey.getBytes()));return rsaSign(content, priKey, charset);}public static String rsaSign(String content, byte[] privateKey,String charset) throws Exception {PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", privateKey);return rsaSign(content, priKey, charset);}public static String rsaSign(String content, PrivateKey priKey,String charset) throws Exception {java.security.Signature signature = java.security.Signature.getInstance("SHA1WithRSA");signature.initSign(priKey);if (charset == null || "".equals(charset)) {signature.update(content.getBytes());} else {signature.update(content.getBytes(charset));}byte[] signed = signature.sign();return new String(Base64.encodeBase64(signed));}public static PrivateKey getPrivateKeyFromPKCS8(String algorithm,byte[] encodedKey) throws Exception {KeyFactory keyFactory = KeyFactory.getInstance(algorithm);return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));}public static PublicKey getPublicKeyFromX509(String algorithm,byte[] encodedKey) throws Exception {KeyFactory keyFactory = KeyFactory.getInstance(algorithm);return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));}
}
  • IDE(如IntelliJ IDEA或Eclipse)

  • JDK 8 或更高版本

  • 需要的maven
        <dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.43</version></dependency><!-- SybUtil文件需要用到 --><dependency><groupId>net.sf.json-lib</groupId><artifactId>json-lib</artifactId><version>2.4</version><classifier>jdk15</classifier></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.20</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
  •  辅助类
  1. 通联支付需要的请求数据格式(Allinpay.java)
package com.allinpay.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;import java.math.BigDecimal;@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Allinpay {private String cusid;private String appid;private int version;private BigDecimal trxamt;/*当指定为F02时,交易仅限分期交易。分期交易金额必须大于500元。*/// ?private String paytype;/*3  花呗分期3期6  花呗分期6期12  花呗分期12期3-cc 支付宝信用卡分期3期6-cc 支付宝信用卡分期6期12-cc 支付宝信用卡分期12期暂只支持支付宝花呗分期,支付宝信用卡分期,仅支持A01/A02*/// 可空参数private String fqnum;//订单号,商户唯一订单号private String reqsn;/*商户网站使用的编码格式,支持UTF-8、GBK跟商户网站的编码一致*///private String charset;/*必须为https协议地址,且不允许带参数页面跳转同步通知页面路径*/private String returl;// 异步通知地址// ?private String notify_url;// 商品描述,长度最大100private String body;//? 通知会原样带上, 订单备注信息private String remark;// 随机字符串,自己生成,最大32位private String randomstr;//订单有效时间,以分为单位,默认为15private String validtime;// ? 支付限制(no_credit--指定不能使用信用卡支付)private String limit_pay;// 签名类型,目前支持RSA2和RSAprivate String signtype;// 签名 32位private String sign;// 关闭订单的时候需要private String oldreqsn;}

 2. 由于本案列采用了多商家,所以暂时把配置也建成了一个类(PayConfig.java)

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class PayConfig {private String cusid;private String appid;private String privateKey;}

 3.本案列设置了多方支付方式,所以还有一个支付载荷(PayLoad.java)

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;import java.math.BigDecimal;@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class PayLoad {private String orderId;private BigDecimal amount;private String payConfigKey;private String remark;private String title;private int payType;private String returnUrl;private String notifyUrl;}
  •  H5支付下单代码

    //这个是PayService的Impl实现层private final String order = "https://syb.allinpay.com/apiweb/h5unionpay/unionorder";private final String rsaPrivateKey = "xxx";@SneakyThrows@Overridepublic String h5Pay(PayLoad payLoad) {// String payConfigKey = payLoad.getPayConfigKey();PayConfig payConfig = new PayConfig().setAppid("xxx").setCusid("xxx").setPrivateKey(rsaPrivateKey);Allinpay allinpay = new Allinpay().setSigntype("RSA").setTrxamt(new BigDecimal(2)).setReqsn(payLoad.getOrderId()).setRandomstr(SybUtil.getValidatecode(8)).setBody(payLoad.getTitle()).setRemark(payLoad.getRemark()).setCharset("UTF-8").setAppid(payConfig.getAppid()).setCusid(payConfig.getCusid()).setReturl(payLoad.getReturnUrl());allinpay.setSign(URLEncoder.encode(SybUtil.unionSign(objectToTreeMap(allinpay), payConfig.getPrivateKey() , "RSA"), StandardCharsets.UTF_8));return order + "?" + treeMapToUrlParams(objectToTreeMap(allinpay));}//Controller代码@SneakyThrows@GetMapping("pay")public String pay(HttpServletResponse response) {String paymentUrl = (String) payService.h5Pay(new PayLoad().setPayType(2).setPayConfigKey("").setReturnUrl("https://blog.csdn.net").setOrderId(IdUtil.getSnowflakeNextIdStr()).setAmount(new BigDecimal(2)).setRemark("测试支付备注").setTitle("测试H5支付"));String htmlResponse = "<!DOCTYPE html><html><head></head><body>"+ "<script>window.location.href='" + paymentUrl + "'</script>"+ "</body></html>";// 设置响应内容类型为HTMLresponse.setContentType("text/html;charset=UTF-8");return htmlResponse;}

  • 关闭订单 

    // 关闭接口private final String close = "https://vsp.allinpay.com/apiweb/tranx/close";@SneakyThrows@Overridepublic String closeOrder(PayLoad payLoad) {PayConfig payConfig = new PayConfig().setAppid("xxx").setCusid("xxxx").setPrivateKey(rsaPrivateKey);Allinpay allinpay = new Allinpay().setCusid(payConfig.getCusid()).setAppid(payConfig.getAppid()).setRandomstr(SybUtil.getValidatecode(8)).setVersion(11).setOldreqsn(payLoad.getOrderId()).setSigntype("RSA");allinpay.setSign(SybUtil.unionSign(objectToTreeMap(allinpay), rsaPrivateKey, "RSA"));return HttpUtil.post(close, BeanUtil.beanToMap(allinpay));}/*** 关闭订单* @param outTradeNo 下单的订单号,也就是你支付下单类Allinpay的reqsn* @return {@link String}***/@SneakyThrows@GetMapping("closeOrder/{outTradeNo}")public Map<String,String> closeOrder(@PathVariable Long outTradeNo) {return handleResult(payService.closeOrder(new PayLoad().setOrderId(outTradeNo.toString())));}
  •  查询订单

    // 查询接口private final String query = "https://vsp.allinpay.com/apiweb/tranx/query";@SneakyThrows@Overridepublic String query(PayLoad payLoad) {PayConfig payConfig = new PayConfig().setAppid("xxx").setCusid("xxxx").setPrivateKey(rsaPrivateKey);Allinpay allinpay = new Allinpay().setCusid(payConfig.getCusid()).setAppid(payConfig.getAppid()).setRandomstr(SybUtil.getValidatecode(8)).setVersion(11).setReqsn(payLoad.getOrderId()).setSigntype("RSA");allinpay.setSign(SybUtil.unionSign(objectToTreeMap(allinpay), rsaPrivateKey, "RSA"));return HttpUtil.post(query, BeanUtil.beanToMap(allinpay));}/*** 查询订单* @param outTradeNo 下单的订单号* @return {@link String}***/@SneakyThrows@GetMapping("query/{outTradeNo}")public Map<String, String> query(@PathVariable Long outTradeNo) {return handleResult(payService.query(new PayLoad().setOrderId(outTradeNo.toString())));}
  • 退款接口,这个是只能退当天的交易 (全额退实时返回退款结果)

    // 取消当天交易退款接口private final String cancelDayUrl = "https://vsp.allinpay.com/apiweb/tranx/cancel";@SneakyThrows@Overridepublic String cancelDay(PayLoad payLoad) {PayConfig payConfig = new PayConfig().setAppid("xxx").setCusid("xxxx").setPrivateKey(rsaPrivateKey);Allinpay allinpay = new Allinpay().setCusid(payConfig.getCusid()).setAppid(payConfig.getAppid()).setRandomstr(SybUtil.getValidatecode(8)).setVersion(11).setTrxamt(new BigDecimal(2)).setReqsn(payLoad.getOrderId()).setOldreqsn(payLoad.getOrderId()).setSigntype("RSA");allinpay.setSign(SybUtil.unionSign(objectToTreeMap(allinpay), rsaPrivateKey, "RSA"));return HttpUtil.post(cancelDayUrl, BeanUtil.beanToMap(allinpay));}/*** 退款接口,只能退今天的,全额退款,实时返回退款结果* @return {@link String}*/@SneakyThrows@GetMapping("cancelDay/{outTradeNo}")public Map<String, String> cancelDay(@PathVariable Long outTradeNo) {return handleResult(payService.cancelDay(new PayLoad().setOrderId(outTradeNo.toString())));}
  • 退款接口 ,可以退部分

    // 退款接口private final String refundUrl = "https://vsp.allinpay.com/apiweb/tranx/refund";@SneakyThrows@Overridepublic String refund(PayLoad payLoad) {PayConfig payConfig = new PayConfig().setAppid("xxx").setCusid("xxxx").setPrivateKey(rsaPrivateKey);Allinpay allinpay = new Allinpay().setCusid(payConfig.getCusid()).setAppid(payConfig.getAppid()).setRandomstr(SybUtil.getValidatecode(8)).setVersion(11).setTrxamt(new BigDecimal(2)).setReqsn(payLoad.getOrderId()).setOldreqsn(payLoad.getOrderId()).setSigntype("RSA");allinpay.setSign(SybUtil.unionSign(objectToTreeMap(allinpay), rsaPrivateKey, "RSA"));return HttpUtil.post(refundUrl, BeanUtil.beanToMap(allinpay));}// 可以和上面的接口进行整合处理/*** 退款接口,可以退部分* @return {@link String}*/@SneakyThrows@GetMapping("refund/{outTradeNo}")public Map<String, String> refund(@PathVariable Long outTradeNo) {return handleResult(payService.refund(new PayLoad().setOrderId(outTradeNo.toString())));}

提示: 可以和上面的接口进行整合处理

  • 其中签名需要用到的转map方法 

    private TreeMap<String, String> objectToTreeMap(Object obj) {TreeMap<String, String> treeMap = new TreeMap<>();Class<?> clazz = obj.getClass();while (clazz != null) {for (Field field : clazz.getDeclaredFields()) {field.setAccessible(true);try {Object fieldValue = field.get(obj);if (fieldValue != null) {treeMap.put(field.getName(), fieldValue.toString());}} catch (IllegalAccessException e) {log.error("Error accessing field " + field.getName() + ": " + e.getMessage());}}clazz = clazz.getSuperclass();}return treeMap;}
  •  其中map转路径参数方法

  private static String treeMapToUrlParams(TreeMap<String, String> treeMap) {StringBuilder sb = new StringBuilder();for (Map.Entry<String, String> entry : treeMap.entrySet()) {String key = entry.getKey();String value = entry.getValue();if (sb.length() > 0) {sb.append("&");}sb.append(key).append("=").append(value);}return sb.toString();}
  • 其中通联返回验签代码

    /*** 验签* @param result* @return {@link Map}<{@link String},{@link String}>* @throws Exception*/@SuppressWarnings({ "rawtypes", "all" })public static Map<String,String> handleResult(String result) throws Exception{Map map = SybUtil.json2Obj(result, Map.class);if(map == null){throw new Exception("返回数据错误");}if("SUCCESS".equals(map.get("retcode"))) {TreeMap tmap = new TreeMap();tmap.putAll(map);if(SybUtil.validSign(tmap,"xxxxx","RSA")){return map;}else{throw new Exception("验证签名失败");}// 验签成功,返回数据}else{throw new Exception(map.get("retmsg").toString());}}

提示:如果不考虑多商户,多支付通道,可以再方法中Allinpay类直接填参数请求,不用通过PayLoad和PayConfig类  

  • 完整代码克隆地址:

git clone https://gitee.com/byte1026/allin-pay.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/14047.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【软考中级 软件设计师】计算机网络和安全

计算机网络和安全是软件设计师&#xff08;软考中级&#xff09;考试中的重要组成部分&#xff0c;它涵盖了网络基础、网络协议、网络架构、网络安全等多个方面。以下是一些核心概念和要点&#xff0c; 计算机网络基础 OSI七层模型&#xff1a;物理层、数据链路层、网络层、传…

LLM答案抽取|xFinder:针对大型语言模型的稳健且精确的答案提取

【摘要】大型语言模型&#xff08;LLM&#xff09;的不断进步使人们越来越关注开发公平可靠的方法来评估其性能的关键问题。特别是测试集泄漏、提示格式过拟合等主观或非主观作弊现象的出现&#xff0c;给法学硕士的可靠评估带来了重大挑战。由于评估框架通常利用正则表达式 (R…

《最新出炉》系列初窥篇-Python+Playwright自动化测试-39-highlight() 方法之追踪定位

1.简介 在之前的文章中宏哥讲解和分享了&#xff0c;为了看清自动化测试的步骤&#xff0c;通过JavaScript添加高亮颜色&#xff0c;就可以清楚的看到执行步骤了。在学习和实践Playwright的过程中&#xff0c;偶然发现了使用Playwright中的highlight()方法也突出显示Web元素。…

eNSP-集线器(hub)连接局域网

一、拓扑结构搭建 二、主机配置 pc1、pc2、pc3 三、测试 Hub相当于大家共享一条线路(类似于电线搭电)&#xff0c;线路上的所有的设备都会接收同样的信息。

路由器不能端口映射什么原因?如何设置内网映射?

近期有小伙伴发来求助信息&#xff0c;他以前开游戏服务器和别人一起玩&#xff0c;那个时候端口映射还好&#xff0c;不知道哪一天开始突然不行了&#xff0c;已经是公网了&#xff0c;光猫是桥接的状态&#xff0c;连路由器都换了&#xff0c;就是不能端口映射开服务器&#…

VAE-变分自编码器(Variational Autoencoder,VAE)

变分自编码器&#xff08;Variational Autoencoder&#xff0c;VAE&#xff09;是一种生成模型&#xff0c;结合了概率图模型与神经网络技术&#xff0c;广泛应用于数据生成、表示学习和数据压缩等领域。以下是对VAE的详细解释和理解&#xff1a; 基本概念 1. 自编码器&#…

基于 Milvus Cloud + LlamaIndex 实现初级 RAG

初级 RAG 初级 RAG 的定义 初级 RAG 研究范式代表了最早的方法论,在 ChatGPT 广泛采用后不久就取得了重要地位。初级 RAG 遵循传统的流程,包括索引创建(Indexing)、检索(Retrieval)和生成(Generation),常常被描绘成一个“检索—读取”框架,其工作流包括三个关键步…

WebSocket简介

参考&#xff1a;Java NIO实现WebSocket服务器_nio websocket-CSDN博客 WebSocket API是HTML5中的一大特色&#xff0c;能够使得建立连接的双方在任意时刻相互推送消息&#xff0c;这意味着不同于HTTP&#xff0c;服务器服务器也可以主动向客户端推送消息了。 WebSocket协议是…

【PB案例学习笔记】-08 控件拖动实现

写在前面 这是PB案例学习笔记系列文章的第8篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gitee…

1941springboot VUE 服务机构评估管理系统开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot VUE服务机构评估管理系统是一套完善的完整信息管理类型系统&#xff0c;结合springboot框架和VUE完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代…

计算机-编程相关

在 Linux 中、一切都是文件、硬件设备是文件、管道是文件、网络套接字也是文件。 for https://juejin.cn/post/6844904103437582344 fork 进程的一些问题 fork 函数比较特殊、一次调用会返回两次。在父进程和子进程都会返回。 每个进程在内核中都是一个 taskstruct 结构、for…

Thingsboard规则链:Entity Type Switch节点详解

在物联网&#xff08;IoT&#xff09;领域&#xff0c;随着设备数量的爆炸式增长和数据复杂性的增加&#xff0c;高效、灵活的数据处理机制变得至关重要。作为一款先进的物联网平台&#xff0c;ThingsBoard提供了强大的规则链&#xff08;Rule Chains&#xff09;功能&#xff…

第四节 Starter 加载时机和源码理解

tips&#xff1a;每个 springBoot 的版本不同&#xff0c;代码的实现存会存在不同。 上一章&#xff0c;我们聊到 mybatis-spring-boot-starter&#xff1b; 简单分析了它的结构。 这一章我们将着重分析 Starter 的加载机制&#xff0c;并结合源码进行分析理解。 一、加载实际…

问题与解决:element ui垂直菜单展开后显示不全

比如我这个垂直菜单展开后&#xff0c;其实系统管理下面还有其他子菜单&#xff0c;但是显示不出来了。 解决方法很简单&#xff0c;只需要在菜单外面包一层el-scrollbar&#xff0c;并且将高度设置为100vh。

Laravel 11 PHP8

一直都是用laravel 7 左右的&#xff0c;现在要求将项目升级到laravel 11 和使用PHP8&#xff0c;随手记录一些小问题&#xff0c;laravel 11的包是领导给的&#xff0c;没有使用composer 安装&#xff0c;所以我也不确定和官方的是否一致 遇到这问题 可以这样 env 中默认的数…

基于若依的旅游推荐管理系统(spring boot+vue+mybatis+Ajax)

一、项目目的 随着社会的高速发展&#xff0c;人们生活水平的不断提高&#xff0c;以及工作节奏的加快&#xff0c;旅游逐渐成为一个热门的话题&#xff0c;因为其形式的多样&#xff0c;涉及的面比较广&#xff0c;成为人们放松压力&#xff0c;调节情绪的首要选择。 传统的旅…

上位机图像处理和嵌入式模块部署(mcu的按键输入)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 做技术的同学&#xff0c;大部分都会把精力放在技术本身&#xff0c;却忽视了学的东西有什么实际的用途。就拿gpio来说&#xff0c;一般我们点灯也…

正确认识IP地址和子网掩码的联系

IP地址和子网掩码是计算机网络中两个非常重要的概念&#xff0c;它们共同确定了设备在局域网中的地址以及该地址所属的子网&#xff0c;只要两者结合&#xff0c;就能确定唯一地址IP66_ip归属地在线查询_免费ip查询_ip精准定位平台。 IP地址是用于标识计算机网络中的每台设备的…

Ajax用法总结(包括原生Ajax、Jquery、Axois)

HTTP知识 HTTP&#xff08;hypertext transport protocol&#xff09;协议『超文本传输协议』&#xff0c;协议详细规定了浏览器和万维网服务器之间互相通信的规则。 请求报文 请求行: GET、POST /s?ieutf-8...&#xff08;url的一长串参数&#xff09; HTTP/1.1 请求头…

Mac安装 Intellij IDEA,亲测有效M1、M2可用

引言 最近开始学习使用spring boot写一个简单的后端项目&#xff0c;使用Intellij IDEA软件&#xff0c;Intellij IDEA为新用户提供了30天的免费试用。 方案 1.官网下载Intellij IDEA IntelliJ IDEA – the Leading Java and Kotlin IDE 或者直接网盘连接下载&#xff1a;…