网站建设市场需求大,网站加入谷歌地图导航,国内做性视频网站有哪些,百度推广哪家做的最好第二十六章 短链服务-冗余双写架构删除和更新消费者开发实战
第1集 冗余双写架构-更新短链消费者开发实战
简介#xff1a; 短链服务-更新短链-消费者开发实战
具体步骤见代码
第2集 冗余双写架构-更新短链消费者链路测试
简介#xff1a; 冗余双写架构-更新短链消费者链…第二十六章 短链服务-冗余双写架构删除和更新消费者开发实战
第1集 冗余双写架构-更新短链消费者开发实战
简介 短链服务-更新短链-消费者开发实战
具体步骤见代码
第2集 冗余双写架构-更新短链消费者链路测试
简介 冗余双写架构-更新短链消费者链路测试
具体步骤见代码
第3集 冗余双写架构-删除短链消费者开发实战
简介 短链服务-删除短链-消费者开发实战
具体步骤见代码
第4集 冗余双写架构-删除短链消费者链路测试和越权修复
简介 冗余双写架构-删除短链消费者链路测试 对数据库操作的时候一定要防止越权 一个是直接RPC调用一个是通过MQ调用 具体步骤见代码
第5集 冗余双写架构-短链服务开发总结
简介 冗余双写架构-短链服务开发总结
短链服务器CRUD冗余双写架构 异常队列最终一致性
第二十七章 流量包商品服务需求和库表讲解
第1集 流量包商品服务-业务需求讲解
简介 流量包商品服务需求讲解 流量包需求讲解 百度短链案例 https://dwz.cn/console/price 流量包商品模型 每个套餐都是一个虚拟商品没库存限制免费版是新用户注册即可获得不同的商品每天限制的创建的条数不一样用户可以叠加使用多个流量包 业务难点 流量包购买支付(P2)流量包管理 免费流量包管理P1付费流量包管理P1 短链业务-流量包业务联动(P1)
第2集 流量包商品服务-数据库表介绍和实体类生成
简介 流量包商品服务-数据库表介绍
数据库表介绍
CREATE TABLE product (id bigint NOT NULL,title varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 商品标题,detail varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 详情,img varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 图片,level varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 产品层级FIRST青铜、SECOND黄金、THIRD钻石,old_amount decimal(16,0) DEFAULT NULL COMMENT 原价,amount decimal(16,0) DEFAULT NULL COMMENT 现价,plugin_type varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 工具类型 short_link、qrcode,day_times int DEFAULT NULL COMMENT 日次数短链类型,total_times int DEFAULT NULL COMMENT 总次数活码才有,valid_day int DEFAULT NULL COMMENT 有效天数,gmt_modified datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,gmt_create datetime DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (id)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_bin;数据库创建插入初始化数据
INSERT INTO dcloud_shop.product (id, title, detail, img, level, old_amount, amount, plugin_type, day_times, total_times, valid_day, gmt_modified, gmt_create) VALUES (1, 青铜会员-默认, 数据查看支持||日生成短链{{dayTimes}}次||限制跳转50次||默认域名, NULL, FIRST, 19, 0, SHORT_LINK, 2, NULL, 1, 2021-10-14 17:33:44, 2021-10-11 10:49:35);INSERT INTO dcloud_shop.product (id, title, detail, img, level, old_amount, amount, plugin_type, day_times, total_times, valid_day, gmt_modified, gmt_create) VALUES (2, 黄金会员-月度, 数据查看支持||日生成短链{{dayTimes}}次||限制不限制||默认域名, NULL, SECOND, 99, 1, SHORT_LINK, 5, NULL, 30, 2021-10-19 14:36:28, 2021-10-11 10:57:47);INSERT INTO dcloud_shop.product (id, title, detail, img, level, old_amount, amount, plugin_type, day_times, total_times, valid_day, gmt_modified, gmt_create) VALUES (3, 黑金会员-月度, 数据查看支持||日生成短链{{dayTimes}}次||限制不限制||自定义域名, NULL, THIRD, 199, 2, SHORT_LINK, 8, NULL, 30, 2021-10-19 14:36:30, 2021-10-11 11:01:13);MybatisPlus实体类生成
第3集 流量包商品服务-项目基本骨架创建
简介 流量包商品服务-项目基本骨架创建
配置文件增加和默认库表配置
server.port8005
spring.application.namedcloud-shop#服务注册发现
spring.cloud.nacos.discovery.server-addr120.79.150.146:8848
spring.cloud.nacos.discovery.usernamenacos
spring.cloud.nacos.discovery.passwordnacosspring.shardingsphere.datasource.namesds1
spring.shardingsphere.datasource.ds0.typecom.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.jdbc-urljdbc:mysql://120.79.150.146:3306/dcloud_shop?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue
spring.shardingsphere.datasource.ds0.driver-class-namecom.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds0.usernameroot
spring.shardingsphere.datasource.ds0.passwordclass.net168spring.shardingsphere.datasource.ds0.connectionTimeoutMilliseconds30000
spring.shardingsphere.datasource.ds0.idleTimeoutMilliseconds60000
spring.shardingsphere.datasource.ds0.maintenanceIntervalMilliseconds30000
spring.shardingsphere.datasource.ds0.maxLifetimeMilliseconds1800000
spring.shardingsphere.datasource.ds0.maxPoolSize50
spring.shardingsphere.datasource.ds0.minPoolSize50spring.shardingsphere.props.sql.showtruelogging.level.rootINFO启动类配置controller-service-manager层建立
第4集 流量包商品服务-商品列表和详情接口链路开发
简介 流量包商品服务-商品列表和详情接口链路开发
商品列表接口开发商品详情接口开发
第二十八章 流量包订单模块需求讲解和库表介绍
第1集 流量包订单模块-业务需求讲解
简介 流量包订单模块-业务需求讲解
流量包订单需求讲解 需求 支持叠加购买 效果1个流量包支持1天创建50条如果买了两个则支持1天创建100条 支持多渠道支付 支付宝、微信等开发对接微信V3最新版支付支付宝支付的参考第一个高并发项目大课V2版微信支付对接可以看 https://detail.tmall.com/item.htm?id649570556856 PC端支付宝支付可以看 https://detail.tmall.com/item.htm?id646525336722
第2集 流量包订单-数据库表介绍和实体类生成
简介 流量包订单-数据库表介绍和实体类生成
数据库表
CREATE TABLE product_order (id bigint NOT NULL,product_id bigint DEFAULT NULL COMMENT 订单类型,product_title varchar(64) DEFAULT NULL COMMENT 商品标题,product_amount decimal(16,2) DEFAULT NULL COMMENT 商品单价,product_snapshot varchar(2048) DEFAULT NULL COMMENT 商品快照,buy_num int DEFAULT NULL COMMENT 购买数量,out_trade_no varchar(64) DEFAULT NULL COMMENT 订单唯一标识,state varchar(11) DEFAULT NULL COMMENT NEW 未支付订单,PAY已经支付订单,CANCEL超时取消订单,create_time datetime DEFAULT NULL COMMENT 订单生成时间,total_amount decimal(16,2) DEFAULT NULL COMMENT 订单总金额,pay_amount decimal(16,2) DEFAULT NULL COMMENT 订单实际支付价格,pay_type varchar(64) DEFAULT NULL COMMENT 支付类型微信-银行-支付宝,nickname varchar(64) DEFAULT NULL COMMENT 账号昵称,account_no bigint DEFAULT NULL COMMENT 用户id,del int DEFAULT 0 COMMENT 0表示未删除1表示已经删除,gmt_modified datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间,gmt_create datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间,bill_type varchar(32) DEFAULT NULL COMMENT 发票类型0-不开发票1-电子发票2-纸质发票,bill_header varchar(200) DEFAULT NULL COMMENT 发票抬头,bill_content varchar(200) DEFAULT NULL COMMENT 发票内容,bill_receiver_phone varchar(32) DEFAULT NULL COMMENT 发票收票人电话,bill_receiver_email varchar(200) DEFAULT NULL COMMENT 发票收票人邮箱,PRIMARY KEY (id),UNIQUE KEY uk_query (out_trade_no,account_no) USING BTREE
) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci;数据库实体类生成
第3集 流量包订单-数据库表分库分表讲解和配置
简介 流量包订单-数据库表分库分表讲解和配置
业务需求 用户查看自己的订单列表 数据存储需求都是前期规划上线前可以调整分库分表策略和数量 未来2年短链平台累计5百万用户付费流包记录: 一个用户10条/年总就是5千万条/年两年是1亿单表不超过1千万数据需要分10张表进一步延伸进行水平分表比如 2张表、4张表、8张 表、16张表 分表数:线上分16张表本地分2张表即可 分片key account_no作为partitionKey
#----------配置默认数据库比如短链域名不分库分表--------------
spring.shardingsphere.sharding.default-data-source-nameds0
#默认id生成策略
spring.shardingsphere.sharding.default-key-generator.columnid
spring.shardingsphere.sharding.default-key-generator.typeSNOWFLAKE
spring.shardingsphere.sharding.default-key-generator.props.worker.id${workerId}# 指定product_order表的数据分布情况配置数据节点,行表达式标识符使用 ${...} 或 $-{...}但前者与 Spring 本身的文件占位符冲突所以在 Spring 环境中建议使用 $-{...}
spring.shardingsphere.sharding.tables.product_order.actual-data-nodesds0.product_order_$-{0..1}
#水平分表策略行表达式分片
spring.shardingsphere.sharding.tables.product_order.table-strategy.inline.algorithm-expressionproduct_order_$-{ account_no % 2 }
spring.shardingsphere.sharding.tables.product_order.table-strategy.inline.sharding-columnaccount_no
第4集 流量包订单-Manager层CRUD接口开发
简介 流量包订单-Manager层CRUD接口开发
开发Manager层CRUD接口
第5集 流量包订单-基础分表Manager层单元测试
简介 流量包订单-基础分表Manager层单元测试
单元测试
第二十九章 流量包商品服务-下单模块开发和订单防重提交
第1集 流量包商品服务-订单controller相关接口开发
简介 商品服务-订单controller相关接口开发
分页接口开发订单状态查询接口扫码支付-订单状态检查下单接口controller骨架 支付宝支付返回HTML微信支付返回JSON
第2集 流量包商品服务-流量包下单模块链路流程分析讲解
简介: 商品服务-订单下单模块链路流程分析讲解
不涉及到商品库存管理 防重提交重点获取最新的流量包价格订单验价 如果有优惠券或者其他抵扣验证前端显示和后台计算价格 创建订单对象保存数据库发送延迟消息-用于自动关单重点创建支付信息-对接三方支付重点回调更新订单状态重点支付成功创建流量包重点 第3集 流量包商品服务-下单接口链路骨架开发
简介: 商品服务-流量包下单接口链路骨架开发
业务流程 重防提交TODO获取最新的流量包价格订单验价 如果有优惠券或者其他抵扣验证前端显示和后台计算价格 创建订单对象保存数据库发送延迟消息-用于自动关单TODO创建支付信息-对接三方支付TODO回调更新订单状态TODO支付成功创建流量包TODO 代码开发
第4集 流量包商品服务-避免重复下单你能想到几种方式
简介:避免复下单常见解决方案 开发的项目中可能会出现下面这些情况 前端下单按钮复点击导致订单创建多次网速等原因造成页面卡顿用户重复刷新提交请求黑客或恶意用户使用postman等http工具重复恶意提交表单 问题 会导致表单重复提交造成数据重复或者错乱核心接口的请求增加消耗服务器负载严重甚至会造成服务器宕机 因此核心接口需要做防重提交你能想到几种方式 方式一前端JS控制点击次数屏蔽点击按钮无法点击 前端可以被绕过前端有限制后端也需要有限制 方式二数据库或者其他存储增加唯一索引约束 需要想出满足业务需求的唯一索引约束比如注册的手机号唯一 方式三服务端token令牌方式 下单前先获取令牌-存储redis 下单时一并把token提交并检验和删除-lua脚本分布式情况下采用Lua脚本进行操作 String script if redis.call(get,KEYS[1]) ARGV[1] then return redis.call(del,KEYS[1]) else return 0 end;方式三 是大家采用的最多的那有没更加优雅的方式呢 采用自定义注解也有多种方式
第三十章 流量包商品服务-多场景自定义注解防重提交实战
第1集 java核心知识-教你掌握自定义注解
简介:java核心知识-自定义注解
Annotation(注解) 从JDK 1.5开始, Java增加了对元数据(MetaData)的支持也就是 Annotation(注解)。注解其实就是代码里的特殊标记它用于替代配置文件常见的很多 Override、Deprecated等 什么是元注解 注解的注解比如当我们需要自定义注解时会需要一些元注解meta-annotation如**Target和Retention** java内置4种元注解 Target 表示该注解用于什么地方 ElementType.CONSTRUCTOR 用在构造器ElementType.FIELD 用于描述域-属性上ElementType.METHOD 用在方法上ElementType.TYPE 用在类或接口上ElementType.PACKAGE 用于描述包 Retention 表示在什么级别保存该注解信息 RetentionPolicy.SOURCE 保留到源码上RetentionPolicy.CLASS 保留到字节码上RetentionPolicy.RUNTIME 保留到虚拟机运行时最多可通过反射获取 Documented 将此注解包含在 javadoc 中Inherited 是否允许子类继承父类中的注解 interface 用来声明一个注解可以通过default来声明参数的默认值自定义注解时自动继承了java.lang.annotation.Annotation接口通过反射可以获取自定义注解
第2集 AOP自定义注解-接口防重提交多场景设计
简介: AOP自定义注解接口防重提交多场景设计
防重提交方式 token令牌方式ip类方法方式 利用AOP Aspect Oriented Program 面向切面编程 在不改变原有逻辑上增加额外的功能AOP思想把功能分两个部分分离系统中的各种关注点好处 减少代码侵入解耦可以统一处理横切逻辑方便添加和删除横切逻辑 业务流程 自定义注解
import java.lang.annotation.*;Documented
Target(ElementType.METHOD)
Retention(RetentionPolicy.RUNTIME)
public interface RepeatSubmit {/*** 加锁过期时间默认是5秒* return*/long lockTime() default 5;/*** 默认限制类型是方法参数* return*/Type limitType() default Type.PARAM;/*** 两种类型token 或者 param*/enum Type{ PARAM , TOKEN};
}第3集 订单防重提交-自定义注解开发实战-Token令牌方式
简介:订单防重提交-自定义注解开发实战-Token令牌方式
新增redis配置
#-------redis连接配置-------
spring.redis.client-typejedis
spring.redis.host120.79.150.146
spring.redis.passwordclass.net
spring.redis.port6379
spring.redis.jedis.pool.max-active100
spring.redis.jedis.pool.max-idle100
spring.redis.jedis.pool.min-idle100
spring.redis.jedis.pool.max-wait60000编写接口获取令牌
Autowiredprivate StringRedisTemplate redisTemplate;GetMapping(token)public JsonData getToken(){LoginUser loginUser LoginInterceptor.threadLocal.get();String token CommonUtil.getStringNumRandom(32);//order:submit:%s:%sString key String.format(RedisKey.SUBMIT_ORDER_TOKEN_KEY, loginUser.getAccountNo(),requestToken);redisTemplate.opsForValue().set(key, 1, 30, TimeUnit.MINUTES);return JsonData.buildSuccess(token);}
定义切面类-开发解析器 /*** 定义 Pointcut注解表达式* 方式一annotation当执行的方法上拥有指定的注解时生效我们采用这* 方式二execution一般用于指定方法的执行** param repeatSubmit*/Pointcut(annotation(repeatSubmit))public void pointcutNoRepeatSubmit(RepeatSubmit repeatSubmit) {}/*** 环绕通知, 围绕着方法执行* Around 可以用来在调用一个具体方法前和调用后来完成一些具体的任务。** 方式一单用 Around(execution(* net.class.controller.*.*(..)))可以* 方式二用Pointcut和Around联合注解也可以我们采用这个*** 两种方式* 方式一加锁 固定时间内不能重复提交* p* 方式二先请求获取token这边再删除token,删除成功则是第一次提交** param joinPoint* param noRepeatSubmit* return* throws Throwable*/Around(pointcutNoRepeatSubmit(noRepeatSubmit))public Object around(ProceedingJoinPoint joinPoint, RepeatSubmit noRepeatSubmit) throws Throwable {HttpServletRequest request ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();boolean res;String type noRepeatSubmit.limitType().name();if (type.equals(RepeatSubmit.Type.PARAM.name())) {//方式一方法参数 TODO} else {//方式二,令牌形式String requestToken request.getHeader(request-token);if (StringUtils.isBlank(requestToken)) {throw new BizException(BizCodeEnum.ORDER_CONFIRM_TOKEN_EQUAL_FAIL);}LoginUser loginUser LoginInterceptor.threadLocal.get();//order:submit:%s:%sString key String.format(RedisKey.SUBMIT_ORDER_TOKEN_KEY, loginUser.getAccountNo(),requestToken);/*** 提交表单的token key* 方式一不用lua脚本获取再判断之前是因为 key组成是 order:submit:accountNo, value是对应的token所以需要先获取值再判断* 方式二可以直接key是 order:submit:accountNo:token,然后直接删除成功则完成*/res stringRedisTemplate.delete(key);}if (!res) {throw new BizException(BizCodeEnum.ORDER_CONFIRM_REPEAT);}System.out.println(目标方法执行前);Object object joinPoint.proceed();System.out.println(目标方法执行后);return object;}第4集 Spring里面的AOP常见概念复习巩固
简介:Spring里面的AOP常见概念复习巩固 能否解释下AOP里面常见的概念比如 横切、通知、连接点、切入点、切面 横切关注点 对哪些方法进行拦截拦截后怎么处理这些就叫横切关注点比如 权限认证、日志、事物 通知 Advice 在特定的切入点上执行的增强处理做啥 比如你需要记录日志控制事务 提前编写好通用的模块需要的地方直接调用比如重复提交判断逻辑类型 Before前置通知 在执行目标方法之前运行 After后置通知 在目标方法运行结束之后 AfterReturning返回通知 在目标方法正常返回值后运行 AfterThrowing异常通知 在目标方法出现异常后运行 Around环绕通知 在目标方法完成前、后做增强处理 ,环绕通知是最重要的通知类型 ,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint需要手动执行 joinPoint.procced() 连接点 JointPoint 要用通知的地方业务流程在运行过程中需要插入切面的具体位置一般是方法的调用前后全部方法都可以是连接点只是概念没啥特殊 切入点 Pointcut 不能全部方法都是连接点通过特定的规则来筛选连接点, 就是Pointcut选中那几个你想要的方法在程序中主要体现为书写切入点表达式通过通配、正则表达式过滤出特定的一组 JointPoint连接点过滤出相应的 Advice 将要发生的joinpoint地方 切面 Aspect 通常是一个类里面定义 切入点通知 , 定义在什么地方 什么时间点、做什么事情通知 advice指明了时间和做的事情前置、后置等切入点 pointcut 指定在什么地方干这个事情web接口设计中web层-网关层-服务层-数据层每一层之间也是一个切面对象和对象方法和方法之间都是一个个切面 目标 target 目标类真正的业务逻辑可以在目标类不知情的条件下增加新的功能到目标类的链路上 织入 Weaving 把切面某个类应用到目标函数的过程称为织入 第5集 订单防重提交-自定义注解-Token方式效果验证
简介:订单防重提交-自定义注解开发-Token式效果验证
下单接口增加注解
RepeatSubmit(limitType RepeatSubmit.Type.TOKEN)获取令牌其他bug修复
第6集 订单防重提交-自定义注解开发实战-参数式
简介:订单防重提交-自定义注解开发实战
开发配置 //方式一方法参数long lockTime noRepeatSubmit.lockTime();String ip CommonUtil.getIpAddr(request);//获取注解MethodSignature signature (MethodSignature) joinPoint.getSignature();Method method signature.getMethod();//目标类、方法String className method.getDeclaringClass().getName();String name method.getName();String key String.format(%s#%s#%s#%s,accountNo,ip, className, name);log.info(key{}, key);// 分布式锁 TODO, 直接设置key配置过期时间也行
分布式锁几种实现 RedisLua脚本Redission 直接redis操作
使用原子命令设置和配置过期时间 setnx / setex
如: set key 1 ex 30 nxjava代码里面
redisTemplate.opsForValue().setIfAbsent(key,1,30,TimeUnit.MILLISECONDS)第7集 Redission分布式锁介绍和配置引入
简介:Redission分布式锁介绍和配置引入
Redission介绍 是一个在Redis的基础上实现的Java驻内存数据网格支持多样Redis配置支持、丰富连接方式、分布式对象、分布式集合、分布式锁、分布式服务、多种序列化方式、三方框架整合Redisson底层采用的是Netty 框架官方文档https://github.com/redisson/redisson 配置加入
聚合工程锁定版本common项目添加依赖多个服务都会用到分布式锁!--分布式锁--
dependencygroupIdorg.redisson/groupIdartifactIdredisson/artifactIdversion3.10.1/version
/dependency代码配置
Value(${spring.redis.host})private String redisHost;Value(${spring.redis.port})private String redisPort;Value(${spring.redis.password})private String redisPwd;/*** 配置分布式锁的redisson* return*/Beanpublic RedissonClient redissonClient(){Config config new Config();//单机方式config.useSingleServer().setPassword(redisPwd).setAddress(redis://redisHost:redisPort);//集群//config.useClusterServers().addNodeAddress(redis://192.31.21.1:6379,redis://192.31.21.2:6379)RedissonClient redissonClient Redisson.create(config);return redissonClient;}/*** 集群模式* 备注可以用rediss://来启用SSL连接*//*Beanpublic RedissonClient redissonClusterClient() {Config config new Config();config.useClusterServers().setScanInterval(2000) // 集群状态扫描间隔时间单位是毫秒.addNodeAddress(redis://127.0.0.1:7000).addNodeAddress(redis://127.0.0.1:7002);RedissonClient redisson Redisson.create(config);return redisson;}*/
加锁调用 // 分布式锁RLock lock redissonClient.getLock(key);// 尝试加锁最多等待2秒上锁以后5秒自动解锁 [lockTime默认为5s, 可以自定义]res lock.tryLock(2, lockTime, TimeUnit.SECONDS);
第8集 订单防重提交-自定义注解开发-参数式效果验证
简介:订单防重提交-自定义注解开发-参数式效果验证 效果验证 两种防重提交应用场景不一样也可以更多方式进行防重 个人接入微信支付V3版参数示例 公众号appid: wx5beac15ca207c40c商户平台 商户号1601644442APIv3密钥peYcTwRF581UOdaUqoPOeHzJ8FgHgsnJ证书序列号7064ADC5FE84CA2A3DDE71A692E39602DEB96E61证书文件本章本集的资料里面不可用最新的群公告获取 Config config new Config(); config.useClusterServers().setScanInterval(2000) // 集群状态扫描间隔时间单位是毫秒 .addNodeAddress(“redis://127.0.0.1:7000”) .addNodeAddress(“redis://127.0.0.1:7002”); RedissonClient redisson Redisson.create(config); return redisson; }*/
- 加锁调用java// 分布式锁RLock lock redissonClient.getLock(key);// 尝试加锁最多等待2秒上锁以后5秒自动解锁 [lockTime默认为5s, 可以自定义]res lock.tryLock(2, lockTime, TimeUnit.SECONDS);
第8集 订单防重提交-自定义注解开发-参数式效果验证
简介:订单防重提交-自定义注解开发-参数式效果验证 效果验证 两种防重提交应用场景不一样也可以更多方式进行防重 个人接入微信支付V3版参数示例 公众号appid:商户平台 商户号APIv3密钥证书序列号证书文件本章本集的资料里面不可用最新的群公告获取