【SpringBoot开发】之商城项目案例(沙箱支付)

 🎉🎉欢迎来到我的CSDN主页!🎉🎉

🏅我是君易--鑨,一个在CSDN分享笔记的博主。📚📚

🌟推荐给大家我的博客专栏《SpringBoot开发之商城项目系列》。🎯🎯

🎁如果感觉还不错的话请给我关注加三连吧!🎁🎁


前言

        在上一期的商城项目分享中我们实现了订单项及订单的生成,首先在购物车中选择我们所需要结算的商品,点击结算。然后我们就会获取相关的参数传递都后端进行一系列处理,接着我们调用方法进行新增,其次就是将选中的商品从缓存中去除掉指定的商品数据即可。本期博客基于上期的博客文章,本次实现的是购买支付,请仔细阅读,干货满满。

一、什么是沙箱支付

1. 概述

        支付宝沙箱支付(Alipay Sandbox Payment)是支付宝提供的一个模拟支付环境,用于开发和测试支付宝支付功能的开发者工具。在真实的支付宝环境中进行支付开发和测试可能涉及真实资金和真实用户账户,而沙箱环境则提供了一个安全、隔离的环境,使开发者能够模拟支付过程,测试支付功能,而不会使用真实资金。

        使用支付宝沙箱支付环境,开发者可以模拟各种支付场景,包括交易创建、支付请求、支付回调等,以验证支付功能的正确性和稳定性。沙箱环境中的所有交易和数据都是虚拟的,不会产生真实的交易或资金流动。

        支付宝沙箱支付提供了开发者工具和接口,使开发者能够在模拟环境下进行支付流程的调试和测试。开发者可以在沙箱环境中创建测试账户、配置模拟的交易金额和状态,使用沙箱环境中的接口进行支付操作,并模拟支付回调接口接收支付结果。

        通过使用支付宝沙箱支付,开发者可以更安全、更有效地进行支付功能的开发和测试,避免了对真实环境的影响和风险。一旦支付功能在沙箱环境中验证通过,开发者可以将其部署到真实的支付宝生产环境中,与真实用户进行交互和支付。

2. 沙箱支付的应用场景

        沙箱支付是一个用于模拟真实支付环境的测试工具,其主要作用是在开发和测试阶段模拟支付流程,以便开发者能够验证其支付系统的正确性、稳定性和安全性。以下是沙箱支付的主要作用和一些应用场景:

沙箱支付的应用场景
应用场景说明
测试支付集成开发者可以使用沙箱支付来测试其应用与支付网关、第三方支付服务商等支付系统的集成。这有助于确保支付流程的正确性和顺畅性。
模拟不同支付状态沙箱支付通常允许开发者模拟不同的支付状态,如支付成功、支付失败、支付取消等,以确保系统能够正确地处理各种支付结果。
调试和错误排查在沙箱环境中,开发者可以更容易地调试和排查支付相关的问题,而不必担心真实支付交易对用户产生影响。
安全性测试沙箱支付环境还可以用于测试支付系统的安全性,包括对支付数据的加密、身份验证和防止欺诈的功能。
开发人员培训沙箱支付是培训新的开发人员、商户或支付系统操作员的理想环境,因为它提供了一个模拟支付流程的平台,而无需使用真实的支付账户和资金。
API 接口测试对于开发使用支付API的应用,沙箱支付提供了一个测试接口的环境,开发者可以验证其API调用的正确性。
新功能测试当支付系统添加新功能时,沙箱环境可以用于测试这些新功能,确保其与现有系统的兼容性。
合规性测试对于需要遵循一定支付行业标准和法规的应用,沙箱支付可以用于测试支付系统的合规性,确保符合相关的法规和标准。

二、配置沙箱支付

1.接入支付宝开放平台

        首先我们进入到支付宝开放平台官网进行登陆,网址:支付宝开放平台 ,

         登录成功之后,点击控制台跳转到控制台主页面,将浏览器进度条滚动到最下面,选择沙箱,最后点击沙箱选项即可,如下:

         在进入之前我们还需要进行一个操作,补全信息

         将浏览器进度条滚动到最下面,选择沙箱,最后点击沙箱选项即可

 2. 下载

        我们使用沙箱支付需要下载安装支付宝开放平台开发助手。

网址::小程序文档 - 支付宝文档中心

注意事项 :请不要安装在含有空格的目录路径下,否则会导致公私钥乱码的问题

        我们下载的版本如下所示 

         我们下载好安装包点击进行安装,根据指示进行安装,安装之后我们的桌面会生成一个图标,打开之后的页面如下

3. 配置秘钥

        打开支付宝开放平台开发助手,选择密钥方式,选择`RSA2`方式,最后点击生成密钥即可生成得到私钥和公钥。

         我们会生成对应的应用私钥和应用公钥。

4.  生成支付宝公钥

         根据支付宝开放平台开发助手生成的应用公钥,生成支付宝公钥。找到支付宝开放平台的沙箱应用一栏,选择“开发信息”接口加签方式中的自定义密钥方式,点击设置并查看按钮:

 

        将我们之前生成的应用公钥的内容复制在所选的框内 

 5. 配置沙箱账号(买家)

        我们使用沙箱支付前还需配置沙箱账号进行相应的付款支付。

网址:登录 - 支付宝

 6. 下载沙箱支付宝(手机下载)

        下载沙箱支付宝(只支持安卓),利用实现功能

网址:登录 - 支付宝

        下载安装之后,进行相应的注册或者登陆 

 

三、SpringBoot项目中集成使用

1. 导入pom依赖

        导入我们沙箱支付所需要的pom依赖,版本不同可能会影响到我们的使用

<dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-easysdk</artifactId><version>2.0.1</version>
</dependency>

2. 配置沙箱支付配置类

        我们可以参考我们的开发文档中根据自己的需要及信息进行修改

        下面是我自己修改后的配置类,配置类中需要修改以下信息

 

 AlipayConfig.java

package com.yx.yxshop.config;import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.yx.yxshop.pojo.Order;
import org.springframework.stereotype.Component;@Component
public class AlipayConfig {private Config aliconfig() {Config config = new Config();//沙箱支付宝地址config.gatewayHost = "openapi-sandbox.dl.alipaydev.com";//协议httpsconfig.protocol = "https";//应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号config.appId = "9021000133666836";//支付宝公钥config.alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr5pP6Hf4txMzWmDIjkUUK5wju2gaZwV3MdNa/zvBOImeHTNcSdXTrtNtweZ8/gXxoJJV9nJR1h9SDyBZqDx54wd2Mu3XeHuQRZuqW1Sr4uCpcbsFGgULzv4Y8AgmJZpIJUkFFUIFY3m3NdK7bHHjBqVw9T+AkiHSAvzKgAOmoLX/WHEFIEKTEGrkILvs6HtDsVSn7MWJ6WM5ndk9tZBJZDRhb2p2H0EgeVPrZ8OrqJxzWs/Tl08WYrd0yblPuLg3c7IUM6G7gXx0Y2cPc0XyjpXVhXcryASH5Pl5u7nChI9ra6xvwNshdZpXlZ9iygFsTrHW7tAgHpKwjlIxe4pM2QIDAQAB";//签名方式config.signType = "RSA2";//商户私钥(应用私钥),您的PKCS8格式RSA2私钥config.merchantPrivateKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCKk86IjtT1YR6Q00PY4OcPyd4p2L6PpYkphY2vBXoH8Umy2IJbpaERH5y+NeD06SLrCkAbSuEZ8neGR27HKX6VRlMhyFSbiSufLn4FjGrfuiLhFQ2EjtJOXN2f/aw4hpigjBEbPppt+wXTEel3ggwY8t3xqYmyuTnKLbd1R7wKTJz3iBrt02eGmcBgnkhL10oImvivbcoacCYZjbv4TvbPHYQPpyFNRGHGHFH8p4EZzmoRyZHyHCCfiUnYKvP1VESRSWWihDS1be05OIVRwFl6RORLhouDrqukRnvFnu9euE8mXsZSc1sL2fF/9uRtVY7q+s00gFYFZTseDSltcVbRAgMBAAECggEAfkEN8XKYaXtzeqVQcj7tpX/Yzi1v6LX7kn3gSS5nMOdPqwcBNXhgl5ZCmzXBX8EslBHBuFvvXFGBPjDEp+WRM3Vf9i5rj01ZFe0o2etFz9HpR0KED1qEFusa7FIU32cZlWQnjbfqwPrsIpJ2L/CnDu/u7+bz0oZZNW+TbuHNW19tPAkpS+kkSZRYOdMjqXJ8faDUUVm0ywFepOYjRgsUZhBhELC7W9Snd3ZKJt0QdtgN/OD9t3xqsrOcIoCe5V+EgYz69ntFly2xZssf9wUDr5jJz4L+ZsOolfKfiP+S9aEfq55kJxYkTseD4XmoGk6uUQMYwShi/RwBIbeFt0PJ5QKBgQD9n+ahZPXuWP4EAPiVDpG6A4HfJBTkfQ3EPIPd8/43kXuRto9VkB4XrKA90qF2+Ubg+iZTbfOZ5r9dQvODbgWA7CP8pMUV1hagIx+MrgYSkt4rZAFAZzPmDZEoPz8BrpSeGUysmii2OM6Oi/E5TOEsY9QR12AD5YdSHtt6DxaEcwKBgQCL4BCMbvZzhRh2k8tJRsoMt0d9hvK+R1AVu++dSLQEWqAYDCAVU5EGRpTMMbXH+wMNvyUCnk17vtQXJfdxdpbOlQXwHfukX5p94Tw05jI8sndbGzcmiBuB2lD+SrONIRebtqXpYqKrAvQNJN3r1VJ0nR9tU5ydGODYlNP0eqQqqwKBgHFmqKFrWgcbZWB26q8DF6d7X/tcz7amL5yZjkCUkwtXkk/Bt+8DBGGDfxaFckqXBNkdIDvXgr9CjDfv8p/GdtGBREn3hmPQGMe7TKUDPpXZc1slWOXp/yuSz1+Wf96Jp8vU9hKKzz9CwSC9c7syI9BMRos/qJ+1Zj8SqwG1c1T/AoGAXzX7zbvSYjvctQpRO+XFrvYq4ZU0MrVUHBc7OXK9pqERjIzkYd/qPb1Zl8zWkfOY1oif5rJex7bTo5YiYsd4S9JAonumSPMStFDWrKNs2sgYWpmh5saLAs7aht3ObmhyK3oeYUjUtVdjTHcl4FvqrpotRDu/xWej1Yko5ad9i9UCgYB1XGJcnclrlMlVjJvwdK/JXoBgLu+N4OLIaJQ3E5G/CSYRSFQzy1m312ogd1CeCJFL9gZzkCZE5HL5/ARpAP/5CbvcEyxN6KN+1nV9bqv9d5IqYH/CDnzVeInx3zReWSMAmpUIUX6jj+4YIfJ2Gkm4++Dei7lHJv98Gwf1xyDx5w==";return config;}public String goAlipay(Order order) {try {// 1. 设置参数(全局只需设置一次)Factory.setOptions(aliconfig());// 2. 发起API调用(subject商品标题、outTradeNo订单编号、totalAmount总金额、returnUrl异步通知地址)AlipayTradePagePayResponse response = Factory.Payment.Page().pay("商城项目收款",order.getOid().toString(),order.getTotal().toString(),//支付成功之后的异步通知(跳出到自己系统的哪个位置)"http://localhost:8080/order/payDone");return response.body;} catch (Exception e) {e.printStackTrace();throw new RuntimeException(e);}}}

3. 修改订单生成代码

 OrderController.java
package com.yx.yxshop.controller;import com.alipay.easysdk.factory.Factory;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.yitter.idgen.YitIdHelper;
import com.yx.yxshop.config.AlipayConfig;
import com.yx.yxshop.exp.BusinessException;
import com.yx.yxshop.pojo.Goods;
import com.yx.yxshop.pojo.Order;
import com.yx.yxshop.pojo.OrderItem;
import com.yx.yxshop.pojo.User;
import com.yx.yxshop.resp.JsonResponseBody;
import com.yx.yxshop.resp.JsonResponseStatus;
import com.yx.yxshop.service.IGoodsService;
import com.yx.yxshop.service.IOrderItemService;
import com.yx.yxshop.service.IOrderService;
import com.yx.yxshop.service.IRedisService;
import com.yx.yxshop.vo.CartVo;
import com.yx.yxshop.vo.OrderVo;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;/*** <p>* 订单信息表 前端控制器* </p>** @author yangxin* @since 2023-12-27*/
@RestController
@RequestMapping("/order")
public class OrderController {//    引入对应接口@Autowiredprivate IRedisService redisService;@Autowiredprivate IGoodsService goodsService;@Autowiredprivate IOrderItemService orderItemService;@Autowiredprivate IOrderService orderService;/*** 跳转订单的请求方法* @return*/@RequestMapping("/add")public JsonResponseBody<?> toOrder(User user, OrderVo orderVo){
//        获取购物车商品id字符串String ids = orderVo.getIds();
//        从缓存中获取购物车商品信息   此时只有id和数量List<CartVo> cartitems = redisService.loadCart(user, ids);//        从数据库中获取商品信息//        获取到所选中商品的Id集合List<Long> gds = cartitems.stream().map(CartVo::getGid).collect(Collectors.toList());
//      根据集合查询对应的商品信息List<Goods> goods = goodsService.listByIds(gds);
//      遍历结合赋值给对应的选项for (Goods g : goods) {
//            根据商品Id查询对应的购物车选项CartVo cartVo = cartitems.stream().filter(v -> Objects.equals(v.getGid(), g.getGid())).findFirst().get();
//            商品g的属性赋值给voBeanUtils.copyProperties(g,cartVo);}
//          使用雪花id生成订单idlong oid = YitIdHelper.nextId();//订单id
//        定义一个变量计算总价BigDecimal total = new BigDecimal("0");
//        增加订单项
//        实例化一个集合List<OrderItem> orderItems = new ArrayList<>();//用户后续插入数据
//        遍历商品信息集合for (CartVo item : cartitems) {
//            生成订单项
//            实例化一个订单项OrderItem orderItem = new OrderItem();
//              赋值属性BeanUtils.copyProperties(item,orderItem);
//            订单项的订单商品数量orderItem.setQuantity(item.getNum());orderItem.setOoid(YitIdHelper.nextId());//订单项idorderItem.setOid(oid);//订单id
//            订单对象存放到订单集合中
//              减少请求生成orderItems.add(orderItem);
//            计算总价total = total.add(item.sumprice());}
//        向数据库中批量插入数据orderItemService.saveBatch(orderItems,5);//分批插入防止数据量过多
//        增加订单
//        实例化订单对象Order order = new Order();
//        设置订单属性BeanUtils.copyProperties(orderVo,order);
//        设置订单idorder.setOid(oid);
//      设置总价order.setTotal(total);
//        设置用户idorder.setUserId(user.getId());
//        设置订单状态  默认0order.setStatus(0);
//      设置创建时间order.setCreateDate(new Date());
//      将订单插入数据库orderService.save(order);
//        删除缓存中购物车对应的商品redisService.removeCart(user,orderVo.getIds());return JsonResponseBody.success(oid);}/*** 跳转支付的请求方法* @return*/@RequestMapping("/pay")public String toOrder(User user, String oid){
//        根据订单ID查询订单Order order = orderService.getById(oid);
//        调用支付宝的支付功能String body = new AlipayConfig().goAlipay(order);//返回的是表单return body;}/*** 支付成功之后的请求方法,修改其订单状态* @return*/@RequestMapping("/payDone")public String toOrder(@RequestParam Map<String,String> ms) throws Exception {
//        验签  检验是否支付Boolean b = Factory.Payment.Common().verifyNotify(ms);if (!b){//没有支付throw new BusinessException(JsonResponseStatus.UN_KNOWN);//抛出未知异常}
//       获取订单idString oid = ms.get("out_trade_no");
//        修改订单状态orderService.update(new UpdateWrapper<Order>().set("status",1).set("pay_date",new Date()).eq("oid",oid));return "<script>\n" +"\talert(\"支付成功\");\n" +"\tlocation.href=\"/\";//跳转首页\n" +"</script>";}}

        前端代码修改主要是js的代码

 

四、演示


 

 🎉🎉本期的博客分享到此结束🎉🎉

📚📚各位老铁慢慢消化📚📚

🎯🎯下期博客博主会带来新货🎯🎯

🎁三连加关注,阅读不迷路 !🎁

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

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

相关文章

MySQL数据库索引优化实战

目录 一、前言 二、准备工作 2.1 用户表&#xff08;TB_USER) 2.2 商品表&#xff08;TB_SKU) 2.3 订单表&#xff08;TB_ORDER&#xff09; 三、实例分析 3.1 索引提升查询性能 3.2 多表查询 3.3 索引失效 四、总结 一、前言 在数据库的应用中&#xff0c;性能优化…

类加载机制之双亲委派模型、作用、源码、SPI打破双亲委派模型

双亲委派模型 双亲委派工作机制双亲委派的作用双亲委派的实现源码SPI打破双亲委派 应用程序是由三种类加载器相互配合&#xff0c;从而实现类加载&#xff0c;除此之外还可以加入自己定义的类的加载器。 类加载器之间的层次关系&#xff0c;称为双亲委派模型&#xff08;Parent…

2024最全面且有知识深度的web3开发工具、web3学习项目资源平台

在Web3技术迅速发展的时代&#xff0c;寻找一个综合且深入的Web3开发工具和学习项目资源平台变得至关重要。今天&#xff0c;我将向大家介绍一个非常有价值的网站&#xff0c;它就是https://web3x.world 。 Web3X是一个全面而深入的Web3开发者社区&#xff0c;为开发者们提供了…

【深度学习】各领域常用的损失函数汇总(2024最新版)

目录 1、L1 损失、平均绝对误差&#xff08;L1 Loss、Mean Absolute Error&#xff0c;MAE&#xff09; 2、L2 损失、均方误差&#xff08;L2 Loss、Mean Squared Error&#xff0c;MSE&#xff09; 3、交叉熵损失&#xff08;Cross-Entropy Loss&#xff09; 4、混合损失&…

webpack的深入学习与实战(持续更新)

一、何为Webpack Webpack是 一个开源的JavaScript模块打包工具&#xff0c;其最核心的功能是解决模块之间的依赖&#xff0c;把各个模块按照特定的规则和顺序组织在一起&#xff0c;最终合并为一个JS文件或多个。 二、带宽的换算 目前我们的云服务器带宽为5M 三 、bundle 体…

【算法挨揍日记】day34——647. 回文子串、5. 最长回文子串

647. 回文子串 647. 回文子串 题目描述&#xff1a; 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串&am…

202365读书笔记|《温暖和百感交集的旅程》——时间帮助着一个人的一生在几千字的篇幅里栩栩如生

202365读书笔记|《温暖和百感交集的旅程》——时间帮助着一个人的一生在几千字的篇幅里栩栩如生 我能否相信自己温暖和百感交集的旅程前言和后记 《温暖和百感交集的旅程》作者余华&#xff0c;之前读完的一本书&#xff0c;已经不太记得内容了&#xff0c;看着笔记整理的这篇书…

【进程间通信】

什么是进程通信 进程通信&#xff08; InterProcess Communication&#xff0c;IPC&#xff09;就是指进程之间的信息的传播和交换。 进程是分配系统资源的单位&#xff0c;包括内存地址空间&#xff0c;为了保证安全&#xff0c;一个进程不能直接访问另一个进程的地址空间&a…

CMake入门教程【核心篇】属性管理set_property和get_property

&#x1f608;「CSDN主页」&#xff1a;传送门 &#x1f608;「Bilibil首页」&#xff1a;传送门 &#x1f608;「本文的内容」&#xff1a;CMake入门教程 &#x1f608;「动动你的小手」&#xff1a;点赞&#x1f44d;收藏⭐️评论&#x1f4dd; 文章目录 1.概述2.设置属性 - …

FPGA设计时序约束十五、Set_Bus_Skew

目录 一、序言 二、Set Bus Skew 2.1 基本概念 2.2 设置界面 2.3 命令语法 2.4 报告分析 三、工程示例 3.1 工程代码 3.2 时序报告 四、参考资料 一、序言 在时序约束中&#xff0c;对时钟的约束除了set clock latency,set clock uncertainty,set input jitter外&…

51、全连接 - 特征的全局融合

Resnet50 中的核心算法,除了卷积、池化、bn、relu之外,在最后一层还有一个全连接。 下图是 Resnet50 网络结构结尾的部分,最后一层 Gemm(通用矩阵乘法)实现的就是全连接操作。而矩阵乘法我们之前介绍过,传送门在:矩阵乘。 卷积也好,矩阵乘法也好,其目的都是为了完成神…

JavaWeb基础(1)- Html与JavaScript(JavaScript基础语法、变量、数据类型、运算符、函数、对象、事件监听、正则表达式)

JavaWeb基础&#xff08;1&#xff09;- Html与JavaScript(JavaScript基础语法、变量、数据类型、运算符、函数、对象、事件监听、正则表达式) 文章目录 JavaWeb基础&#xff08;1&#xff09;- Html与JavaScript(JavaScript基础语法、变量、数据类型、运算符、函数、对象、事件…

2024.1.2 Redis 数据类型 Stream、Geospatial、HyperLogLog、Bitmaps、Bitfields 简介

目录 引言 Stream 类型 Geospatial 类型 HyperLogLog 类型 Bitmaps 类型 Bitfields 类型 引言 Redis 最关键&#xff08;应用广泛、频繁使用&#xff09;的五个数据类型 StringListHashSetZSet 下文介绍的数据类型一般适合在特定的场景中使用&#xff01; Stream 类型 St…

Redis命令---Hash(哈希)篇 (超全)

目录 1.Redis Hmset 命令 - 同时将多个 field-value (域-值)对设置到哈希表 key 中。简介语法可用版本: > 2.0.0返回值: 如果命令执行成功&#xff0c;返回 OK 。 示例 2.Redis Hmget 命令 - 获取所有给定字段的值简介语法可用版本: > 2.0.0返回值: 一个包含多个给定字段…

LangChain与昇腾

LangChain这个词今年已经听烂了&#xff0c;今天基于昇腾的角度总结一下&#xff1a; Why LangChain &#xff1f; 场景&#xff1a;构建一个LLM应用 在构建一个新项目时&#xff0c;可能会遇到许多API接口、数据格式和工具。要去研究每一个工具、接口很麻烦。 假设要构建一…

k8s二进制部署2

部署 Worker Node 组件 //在所有 node 节点上操作 #创建kubernetes工作目录 mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs} #上传 node.zip 到 /opt 目录中&#xff0c;解压 node.zip 压缩包&#xff0c;获得kubelet.sh、proxy.sh cd /opt/ unzip node.zip chmod x kubelet.…

3分钟了解syscall系统调用|详细易懂的流程

文章目录 syscall1.简介2.详细解释3.具体举例4.比喻解释5.作用6.优点7.总结 syscall和int 0x80有什么不同&#xff1f;1. 上下文切换效率2. 指令执行流程3. 兼容性总结 syscall 具体流程1. 用户空间准备2. 执行syscall指令3. 切换到内核态4. 内核模式下执行系统调用5. 返回用户…

Unity3D UGUI图集打包与动态使用(TexturePacker)

制作图集的好处&#xff1a; 众所周知CPU是用来处理游戏的逻辑运算的&#xff0c;而GPU是用来处理游戏中图像的。在GPU中&#xff0c;我们要绘制一个图像需要提交图片&#xff08;纹理&#xff09;到显存&#xff0c;然后再进行绘制&#xff08;在这个过程中会产生一次DrawCall…

vue3 + TS + vite 搭建中后台管理系统(完整项目)

vue3 TS vite 搭建中后台管理系统&#xff08;完整项目&#xff09; 前言1、搭建步骤及方法2、集成多种插件功能&#xff0c;实现中后台按需使用3、新手学TS如何快速进入状态、定义TS类型4、layout搭建四款常见风格6、大屏搭建效果5、vue3Ts运营管理系统总结&#xff1a; 前言…

three.js相机按照指定路线在建筑模型中漫游(支持开始,暂停)

three.js相机按照指定路线在模型中漫游&#xff08;支持开始&#xff0c;暂停&#xff09; 关键点 相机运动曲线 // 相机路线 const points [new THREE.Vector3(0, 40, 300),new THREE.Vector3(50, 40, 300),new THREE.Vector3(50, 40, 50),new THREE.Vector3(150, 40, 50),…