当前位置: 首页 > news >正文

实现多租户JAVA支付(微信拉起支付):一个简单而强大的解决方案

简介:

本篇文章为多租户场景

在当今数字经济时代,许多企业都面临着处理多租户支付的挑战。多租户系统是指一种架构,其中单个实例的软件服务多个租户,每个租户的数据通常被隔离,以确保安全性和数据隐私。而在这种环境下,实现支付功能需要特别注意数据隔离、安全性和可扩展性等方面的考量。

本文将探讨如何利用JAVA编程语言实现多租户支付系统。我们将介绍一种简单而强大的解决方案,该方案能够轻松处理多租户环境下的支付需求,并且具有良好的可扩展性和安全性。

首先,我们将深入了解多租户系统的特点以及为何需要专门的支付解决方案。然后,我们将讨论设计和实施多租户支付系统的关键考虑因素,包括数据隔离、安全认证、支付通道管理等。接着,我们将介绍一些常用的JAVA支付库和框架,以及它们在多租户环境下的应用实践。

通过本文的阅读,读者将了解到如何利用JAVA技术栈构建一个稳健、高效的多租户支付系统,并且能够灵活地适应不同规模和需求的业务场景。同时,我们还将分享一些实用的技巧和最佳实践,帮助读者在实践中避免常见的问题和挑战。

无论您是正在构建多租户支付系统的开发者,还是对多租户系统和支付技术感兴趣的技术爱好者,本文都将为您提供有价值的见解和指导,助您在支付领域取得更大的成功。

pom依赖

微信支付pom​​​​​​​

代码部分:

判断是否存在该支付类型(根据service Bean名称)

String BASE_NAME = "PayStrategy";/*** 获取支付凭证*/static Map<String, Object> ObtainCertificate(String orderSerial, PaymentBody paymentBody, PaymentConfigProperties paymentConfigProperties, HttpServletResponse response) {// 支付类型与付款方式String paymentType = paymentBody.getPaymentType();String appName = paymentConfigProperties.getAppName();String beanName = appName + BASE_NAME;if (!SpringUtils.containsBean(beanName)) {throw new ResultException("支付类型不正确!");}IPayStrategy instance = SpringUtils.getBean(beanName);instance.validate(paymentBody);return instance.ObtainCertificate(paymentType, orderSerial, paymentBody, paymentConfigProperties, response);}

service

注⚠️:多支付渠道情境下需要配置路由Bean名称

@Service("wechatV3" + IPayStrategy.BASE_NAME)

传入paymentType(支付渠道)

PaymentBody中 为订单信息 以及租户信息和应用信息

    @Overridepublic Map<String, Object> ObtainCertificate(String paymentType, String orderSerial, PaymentBody paymentBody, PaymentConfigProperties paymentConfigProperties, HttpServletResponse response) {switch (paymentType) {case Const.APP:return wxPay(paymentBody, paymentConfigProperties,WXPayConstants.V3_APP_API,Const.APP);case Const.JSAPI:return wxPay(paymentBody, paymentConfigProperties,WXPayConstants.V3_JSAPI_API,Const.JSAPI);default:log.error("不支持的支付类型:{}", paymentType);throw new ResultException("不支持的支付类型");}}

impl

public Map<String, Object> wxPay(PaymentBody paymentBody, PaymentConfigProperties paymentConfigProperties,String api,String type) {Map<String,Object> map =new HashMap<>();//支付总金额BigDecimal totalPrice = BigDecimal.ZERO;totalPrice = totalPrice.add(BigDecimal.valueOf(paymentBody.getActualPrice()).divide(BigDecimal.valueOf(100)));//转换金额保留两位小数点Integer money=new BigDecimal(String.valueOf(totalPrice)).movePointRight(2).intValue();try {//验证证书CloseableHttpClient httpClient = wxPayV3Util.checkSign(paymentConfigProperties);//app下单HttpPost httpPost = new HttpPost(api);httpPost.addHeader("Accept", "application/json");httpPost.addHeader("Content-type", "application/json; charset=utf-8");ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectMapper objectMapper = new ObjectMapper();ObjectNode rootNode = objectMapper.createObjectNode();rootNode.put("mchid", paymentConfigProperties.getMchId()).put("appid", paymentConfigProperties.getAppId()).put("description",paymentBody.getDescription()).put("notify_url", paymentConfigProperties.getNotifyUrl())//回调.put("out_trade_no", paymentBody.getOrderNo());// 如果为JSAPI支付if (type.equals(Const.JSAPI)){if (StringUtils.isBlank(paymentBody.getOpenId())){throw new IllegalStateException("openId不能为空");}rootNode.putObject("payer").put("openid", paymentBody.getOpenId());}rootNode.putObject("amount").put("total",paymentBody.getActualPrice());objectMapper.writeValue(bos, rootNode);httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));//完成签名并执行请求CloseableHttpResponse response = httpClient.execute(httpPost);//获取返回状态int statusCode = response.getStatusLine().getStatusCode();log.info("JSAPI成功->{}->{}",statusCode,response);if (statusCode == 200) { //处理成功String result = EntityUtils.toString(response.getEntity(), "UTF-8");JSONObject object = JSONObject.parseObject(result);//获取预付单String prepayId = object.getString("prepay_id");//生成签名Long timestamp = System.currentTimeMillis() / 1000;//随机字符串 这个是微信支付maven自带的 也可以用其它的//这个是v2支付依赖自带的工具包 可以去掉了//String nonceStr = WXPayUtil.generateNonceStr();//该方法org.apache.commons.lang3.RandomStringUtils依赖自带随机生成字符串 RandomStringUtils.randomAlphanumeric(32) 代表生成32位String nonceStr = RandomStringUtils.randomAlphanumeric(32);//生成带签名支付信息String paySign = wxPayV3Util.appPaySign(String.valueOf(timestamp), nonceStr, prepayId, paymentConfigProperties);Map<String, String> param = new HashMap<>();map.put("apply", paymentBody.getApply());param.put("appid", paymentConfigProperties.getAppId());param.put("partnerid", paymentConfigProperties.getMchId());param.put("prepayid", prepayId);param.put("package", "Sign=WXPay");param.put("noncestr", nonceStr);param.put("timestamp", String.valueOf(timestamp));param.put("sign", paySign);map.put("code",200);map.put("message", "下单成功");map.put("data", param);return map;}else {map.put("code", statusCode);map.put("message", "下单失败");map.put("data", EntityUtils.toString(response.getEntity(), "UTF-8")); // 提取响应体信息return map;}} catch (Exception e) {log.error("微信预支付id获取失败{}->{}",e.getMessage(),e);e.printStackTrace();}return map;}

获取预支付id

注⚠️:JSAPI拉起支付时 需要传入 用户的openid

获取方式在我的另一个文章   获取openid

WxPayV3Util

import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;@Component
public class WxPayV3Util {/*** 证书验证* 自动更新的签名验证器*/public  CloseableHttpClient checkSign(PaymentConfigProperties paymentConfigProperties) throws IOException {//验签CloseableHttpClient httpClient = null;PrivateKey merchantPrivateKey = getPrivateKey(paymentConfigProperties);httpClient = WechatPayHttpClientBuilder.create().withMerchant(paymentConfigProperties.getMchId(), paymentConfigProperties.getMchSerialNo(), merchantPrivateKey).withValidator(new WechatPay2Validator(getVerifier(paymentConfigProperties))).build();return httpClient;}/*** 保存微信平台证书*/private  final ConcurrentHashMap<String, AutoUpdateCertificatesVerifier> verifierMap = new ConcurrentHashMap<>();/*** 功能描述:获取平台证书,自动更新* 注意:这个方法内置了平台证书的获取和返回值解密*/public AutoUpdateCertificatesVerifier getVerifier(PaymentConfigProperties properties) {String mchSerialNo = properties.getMchSerialNo();AutoUpdateCertificatesVerifier verifier = null;if (verifierMap.isEmpty() || !verifierMap.containsKey(mchSerialNo)) {verifierMap.clear();try {//传入证书PrivateKey privateKey = getPrivateKey(properties);//刷新PrivateKeySigner signer = new PrivateKeySigner(mchSerialNo, privateKey);WechatPay2Credentials credentials = new WechatPay2Credentials(properties.getMchId(), signer);verifier = new AutoUpdateCertificatesVerifier(credentials, properties.getApiV3Key().getBytes("utf-8"));verifierMap.put(verifier.getValidCertificate().getSerialNumber()+"", verifier);} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IOException e) {throw new RuntimeException(e);}} else {verifier = verifierMap.get(mchSerialNo);}return verifier;}/*** app生成带签名支付信息** @param timestamp 时间戳* @param nonceStr  随机数* @param prepayId  预付单* @return 支付信息* @throws Exception*/public  String appPaySign(String timestamp, String nonceStr, String prepayId,PaymentConfigProperties paymentConfigProperties) throws Exception {//上传私钥PrivateKey privateKey = getPrivateKey(paymentConfigProperties);String signatureStr = Stream.of(paymentConfigProperties.getAppId(), timestamp, nonceStr, prepayId).collect(Collectors.joining("\n", "", "\n"));Signature sign = Signature.getInstance("SHA256withRSA");sign.initSign(privateKey);sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(sign.sign());}/*** 小程序及其它支付生成带签名支付信息** @param timestamp 时间戳* @param nonceStr  随机数* @param prepayId  预付单* @return 支付信息* @throws Exception*/public  String jsApiPaySign(String timestamp, String nonceStr, String prepayId,PaymentConfigProperties paymentConfigProperties) throws Exception {//上传私钥PrivateKey privateKey = getPrivateKey(paymentConfigProperties);String signatureStr = Stream.of(paymentConfigProperties.getAppId(), timestamp, nonceStr, "prepay_id="+prepayId).collect(Collectors.joining("\n", "", "\n"));Signature sign = Signature.getInstance("SHA256withRSA");sign.initSign(privateKey);sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(sign.sign());}/*** 获取私钥。* String filename 私钥文件路径  (required)* @return 私钥对象*/public  PrivateKey getPrivateKey(PaymentConfigProperties properties) throws IOException {String content = new String(Files.readAllBytes(Paths.get(properties.getPrivateKeyPath())), "utf-8");try {String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");KeyFactory kf = KeyFactory.getInstance("RSA");return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));} catch (NoSuchAlgorithmException e) {throw new RuntimeException("当前Java环境不支持RSA", e);} catch (InvalidKeySpecException e) {throw new RuntimeException("无效的密钥格式");}}}

PaymentConfigProperties


import lombok.Data;
import lombok.ToString;/*** 支付配置*/
@Data
@ToString
public class PaymentConfigProperties {/*** 是否启用*/private Boolean enabled;/*** 应用配置名称(alipay,wechat,yinsheng)*/private String appName;/*** 支持的付款类型*/private String paymentType;/*** 微信公众号或者小程序等的appid*/private String appId;/*** 微信支付商户号*/private String mchId;/*** 公钥*/private String publicKey;/*** 微信支付商户密钥,支付宝私钥*/private String privateKey;private String privateKeyPath;/*** 服务商模式下的子商户公众账号ID* 如果是普通模式,请不要配置这两个参数,最好从配置文件中移除相关项*/private String subAppId;/*** 服务商模式下的子商户号* 如果是普通模式,请不要配置这两个参数,最好从配置文件中移除相关项*/private String subMchId;/*** 微信:p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)* 支付宝:应用公钥证书文件本地路径。*/private String keyPath;/*** 支付成功回调地址*/private String notifyUrl;/*** 支付成功返回地址*/private String returnUrl;/*** 退款成功回调地址*/private String refundUrl;//-----------支付宝-----------/*** 支付宝证书*/private String appCertPath;/*** 支付宝证书*/private String aliPayCertPath;/*** 支付宝证书*/private String aliPayRootCertPath;/****/private String domain;/*** 支付宝服务地址*/private String serverUrl;/***  图标*/private String icon;/*** 平台证书序列号*/private String mchSerialNo;/*** API V3密钥  "c3Gmjlc5A7fds7uJNUsReVEbs37BlmWL";*/private String apiV3Key;/*** 银盛私钥*/private String ysPrivateCerPath;/*** 银盛公钥*/private String ysPublicCerPath;/*** 银盛环境*/private String ysEnv;/*** 银盛私钥密码*/private String ysPrivateCerPwd;/*** 银盛发起方*/private String srcMerchantNo;/*** 银盛收款方*/private String payeeMerchantNo;/*** 银盛支付回调地址*/private String ysNotifyUrl;/*** 银盛支付回调地址*/private String ysRefundUrl;/*** v2 微信 商户key*/private String mchKey;/** 拉卡拉 银联商户号 */private String lklMerchantNo;/** 拉卡拉 订单有效期 */private int lklOrderEffMinutes = 15;/** 拉卡拉 订单支付成功后商户接收订单通知的地址 */private String lklOrderCreateNotifyUrl;}

PayProperties

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;import java.util.Map;/*** payment 配置属性*/
@Data
@Component
@ConfigurationProperties(prefix = "payment")
public class PayProperties {/*** 支付租户*/private Map<String, Map<String, PaymentConfigProperties>> tenement;}

Const

public class Const {public static final String NATIVE = "NATIVE";//原生扫码支付public static final String APP = "APP";//APP支付public static final String JSAPI = "JSAPI";//公众号支付/小程序支付public static final String M_WEB = "MWEB";//H5支付public static final String MICRO_PAY = "MICROPAY";//刷卡支付public static final String PC = "PC";//PC支付public static final String WAP = "WAP";//网页支付
}

到这里 就可以正常的获取到微信的预支付id了

相关文章:

实现多租户JAVA支付(微信拉起支付):一个简单而强大的解决方案

简介&#xff1a; 本篇文章为多租户场景 在当今数字经济时代&#xff0c;许多企业都面临着处理多租户支付的挑战。多租户系统是指一种架构&#xff0c;其中单个实例的软件服务多个租户&#xff0c;每个租户的数据通常被隔离&#xff0c;以确保安全性和数据隐私。而在这种环境…...

万字长文:FineBI面试题及参考答案详解

1:FineBI的基本概念是什么? FineBI是帆软软件有限公司推出的一款商业智能产品。它的核心功能是通过分析企业已有的信息化数据,帮助企业发现并解决存在的问题,预测模拟企业将来的发展,并协助企业及时调整策略做出更好的决策,增强企业的可持续竞争性。 2:描述FineBI的使…...

Python爬虫:为什么你爬取不到网页数据

目录 前言 一、网络请求被拒绝 二、数据是通过JavaScript加载的 三、需要进行登录 四、网站反爬虫策略 五、网站结构变更 总结 前言 作为一名开发者&#xff0c;使用Python编写爬虫程序是一项常见的任务。爬虫程序的目的是收集互联网上的数据&#xff0c;并将其保存或使…...

NLP在搜索召回领域中的应用场景

自然语言处理&#xff08;NLP&#xff09;在搜索召回领域中的应用场景非常广泛&#xff0c;它通过理解和分析人类语言&#xff0c;提高了信息检索的准确性和效率。以下是一些具体的应用场景&#xff1a; 1. 搜索引擎优化 NLP技术可以用于优化搜索引擎的查询处理&#xff0c;通…...

2. Django配置信息

第2章 Django配置信息 Django的配置文件settings.py用于配置整个网站的环境和功能, 核心配置必须有项目路径, 密钥配置, 域名访问权限, App列表, 中间件, 资源文件, 模板配置, 数据库的连接方式.* 项目运行时, 如果修改代码, 项目会自动检测发现改动后会重新运行, 除非报错否…...

【Web】纯萌新的BUUCTF刷题日记Day1

目录 [RoarCTF 2019]Easy Java [网鼎杯 2018]Fakebook [CISCN2019 华北赛区 Day2 Web1]Hack World [BJDCTF2020]The mystery of ip [网鼎杯 2020 朱雀组]phpweb [BSidesCF 2020]Had a bad day [BJDCTF2020]ZJCTF&#xff0c;不过如此 [BUUCTF 2018]Online Tool [GXYCTF…...

【51单片机入门记录】RTC(实时时钟)-DS1302概述

目录 一、基于三线通信的RTC-DS1302 &#xff08;1&#xff09;简介 &#xff08;2&#xff09;特性 &#xff08;3&#xff09;引脚介绍 &#xff08;4&#xff09;控制字的格式 &#xff08;5.0&#xff09;日历时钟寄存器介绍 &#xff08;5.1&#xff09;日历时钟寄存…...

Lua热更新(AssetBundle)

AssetBundle 新版本导入ab包报错,则删除其中的Tests文件夹。 给资源分组 打包设置:平台、路径、重复打包清空文件夹、复制到streaming文件夹 建议勾选 建议使用LZ4压缩方式 用来观察文件中的包大小,不常用 参数总结: 这六个只做了解,重要的是上面的...

互联网人才现状分析

作者&#xff1a;哈哥撩编程&#xff08;视频号、抖音、公众号同名&#xff09; 新星计划全栈领域优秀创作者博客专家全国博客之星第四名超级个体COC上海社区主理人特约讲师谷歌亚马逊演讲嘉宾科技博主极星会首批签约作者 &#x1f3c6; 推荐专栏&#xff1a; &#x1f3c5;…...

高级IO——多路转接

高级IO——五种IO模型 首先我们之前在基础IO部分就学过IO的过程分等待过程和读写过程&#xff01; 比如我们的scanf除了从键盘缓冲区读取数据所花的时间&#xff0c;主要的时间花费放在了等你输入的过程&#xff01; 所以我们如果想提高我们的IO效率&#xff0c;我们除了要缩…...

TypeScript常用知识点整理

介绍 TypeScript 是 JavaScript 的一个超集&#xff0c;添加了静态类型支持和更多现代编程特性&#xff0c;提高了代码的可靠性和可维护性。最终会被编译成标准的 JavaScript 代码运行。 使用npm install -g typescript进行全局安装 将编写好的ts代码进行运行&#xff0c;第…...

【Unity实战100例】Unity入门小地图位置同步(第一第三人称)

unity小地图制作包括第一人称控制器和第三人称控制器 目录 一.选择合适自身的人称控制器 二.小地图制作...

蓝桥杯简单模板

目录 最大公约数 两个数的最大公约数 多个数的最大公约数 最小公倍数 两个数的最小公倍数 多个数的最小公倍数 素数 ​编辑 位数分离 正写 ​编辑 反写 闰年 最大公约数 两个数的最大公约数 之前看见的是辗转相除法&#xff0c;例如现在让算一个49&#xff0c;21…...

单例模式(饿汉模型,懒汉模型)

在着里我们先了解什么是单例模式。 就是某个类在进程中只能有单个实例&#xff0c;这里的单例模式需要一定的编程技巧&#xff0c;做出限制&#xff0c;一旦程序写的有问题&#xff0c;创建了多个实例&#xff0c;编程就会报错。 如果我们学会了单例模式&#xff0c;这种模式…...

torchvision中的数据集使用

torchvision中的数据集使用 使用和下载CIFAR10数据集 输出测试集中的第一个元素&#xff08;输出img信息和target&#xff09; 查看分类classes 打断点–>右键Debug–>找到classes 代码 import torchvisiontrain_set torchvision.datasets.CIFAR10(root"./data…...

linux 迁移home目录以及修改conda中pip的目录,修改pip安装路径

1&#xff09;sudo rsync -av /home/lrf /data/home/lrf 将/home目录下的文件进行复制&#xff08;假设机械硬盘挂载在/data目录下&#xff09;** 2&#xff09;usermod -d /data/home/lrf -m lrf 修改用户$HOME变量** 3&#xff09;vi /etc/passwd 查看对应用户的$HOME变量是…...

解析大语言模型训练三阶段

大语言模型的训练过程一般包括3个阶段&#xff1a;预训练&#xff08;Pre-training&#xff09;、SFT&#xff08;有监督的微调&#xff0c;Supervised-Finetuning&#xff09;以及RLHF&#xff08;基于人类反馈的强化学习&#xff0c;Reinforcement Learning from Human Feedb…...

知识图谱的最新进展与未来趋势

知识图谱的最新进展与未来趋势 一、引言 在过去的几年中&#xff0c;知识图谱已经从一个前沿的研究概念发展成为现代信息技术不可或缺的一部分。作为结构化知识的存储和表示形式&#xff0c;知识图谱通过组织信息和数据提供了深刻的洞见&#xff0c;它已被广泛应用于搜索引擎优…...

Facebook直播延迟过高是为什么?

在进行Facebook直播 时&#xff0c;高延迟可能会成为一个显著的问题&#xff0c;影响观众的观看体验和互动效果。以下是一些导致Facebook直播延迟过高的可能原因&#xff1a; 1、网络连接问题 网络连接不稳定或带宽不足可能是导致Facebook直播延迟的主要原因之一。如果您的网络…...

CentOS 7.9 额外安装一个Python3.x版本详细教程

Centos7默认的python版本是2.7&#xff0c;根据需要我们额外安装一个Python3.x版本。 1、安装基础环境 yum update -yyum -y groupinstall "Development tools"yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel psmisc …...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景

Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知&#xff0c;帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量&#xff0c;能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度&#xff0c;还为机器人、医疗设备和制造业的智…...