Claude Code 突然版本不兼容
Claude Code显示与64位版本windows不兼容打开 Claude Code,直接弹个框,提示“与 64 位版本 Windows 不兼容”。
折腾半天发现跟系统、跟兼容性都没关系,是 Claude 的启动程序自己损坏了。先去这个目录看一眼:
C:\Users\你的用户名\AppData\Roaming\npm\node_modules\@anthropic-ai\claude-code\bin
如果里面的启动程序只有 1kb,直接重装大概率没用(个人实测)。正确做法是用 winget 重新拉一个下来:
winget install Anthropic.ClaudeCode
这步需要魔法。
装完用 where claude 找到刚下载的那个可执行文件,复制粘贴覆盖掉 bin 目录里损坏的那个,重开一个命令窗口,基本就好了。(我好了)
构建插件里扫码付款自动发 licence
一个 Java 工具做成 Gradle/Maven 插件分发,想收费,就希望用户在命令行或者构建的时候直接扫码付款、licence 自动发到本机、构建接着跑,全程不用人工干预。整个链路梳理下来其实不复杂,但有几个点不注意会出问题。
整体流程是这样:用户跑构建的时候插件发现没 licence,调服务端创建一个订单(订单绑死本机指纹),服务端调微信 Native 下单拿到一个 code_url;插件把这个 code_url 在控制台打成 ASCII 二维码;用户扫码付钱;微信异步回调服务端,或者服务端主动查单兜底;服务端确认收款后凭订单里绑的指纹签发 licence、落库;插件轮询把 licence 拉下来,写盘前用内嵌公钥重新验签一遍、再比对一次本机指纹,确认无误才写进 ~/.myapp/app.lic。
几个关键点分开说。
订单绑指纹,金额服务端定
创建订单的时候,客户端把本机算的指纹一起传上去,服务端把指纹和订单绑死。金额由服务端的价格表决定,客户端传什么都改不了。这样防的是改价——客户端是用户能改的,金额判断不能放客户端。
实付金额必须等于订单金额
微信回调或者查单拿到” ...
浮点数比较踩的坑
做参数一致性检查的时候遇到个怪事:明明几个文件的相关参数是一样的,检查却报”不一致”。打印出来一看,一个是 8.0,另一个是 7.9999995。
原因是这些参数从文件头里按 float(单精度)读出来,再赋给 double 做比较。float 的有效位大概只有 7 位十进制,一个理论上等于 8 的值,存进 float 再转 double,很可能就变成 7.9999995… 这种近似值。原来的检查直接用 != 精确比较,把这种近似相等的值判成了不等。
// 原来:精确比较,float 的近似噪声会被误判if (p.timeWindow != first.timeWindow) { /* 报不一致 */ }// 改成容差比较private fun approxEqual(a: Double, b: Double): Boolean = abs(a - b) < 1e-3if (!approxEqual(p.timeWindow, first.timeWindow)) { /* 报不一致 */ }
浮点数不能直接用 == / ...
多个 JavaFX 属性怎么联动同步
场景很常见:界面上好几个图表或者控件,它们的某个属性要保持联动——比如多个子图的 X 轴范围要一致、缩放倍数要同步,一个改了其他几个跟着变。
最朴素的写法是给每个属性挂监听器,监听器里去 set 别的属性。但很快就会踩坑:set 别的属性又会触发它们的监听器,绕回来形成回环;浮点的值 set 来 set 去,精度抖动让属性在 20 和 19.9999 之间来回跳;还有属性对象被替换的时候,旧的监听器没摘干净,内存泄漏。
后来干脆写了个通用的同步器,把这些坑一次性解决。核心不长:
class PropertySyncManager<T> { var epsilon: Double = 1e-9 private val propertyMap = mutableMapOf<Property<T>, ChangeListener<T>>() private var isSyncing = false fun register(property: Property<T>) { ...
异步任务执行期间状态变了的几个坑
一个数据量比较大的画布应用,后台异步加载、重算数据,算完再渲染到 Canvas。这种结构踩了好几个坑,根子其实都出在同一件事上:异步任务跑的过程中,它依赖的外部状态已经被别的地方改了,任务回来还按旧状态干活,就出错。
下面这几个坑表现完全不一样,但捋到底都是这个原因。
整块空白后台读完数据回来,往像素缓冲区里写的时候,要按”上一段的位置”算偏移。问题出在那个”上一段”——遍历的时候有些段因为被别的段完全包含而跳过了,结果拿”上一个没跳过的段”当基准,基准就错了,偏移算成负数,写缓冲越界,抛 IndexOutOfBoundsException。这个异常在渲染流程里被 catch 住了,程序不崩,但这一块就没写进去,画面上就是一片空白,啥报错都没有。
更隐蔽的是另一个根因:待渲染的段列表是个会被原地 clear() + 重建的 ArrayList。后台线程正迭代它的时候,主线程正好在 clear + add 重建,后台读到的就是个半新半旧的列表,照样算出错误的段。
第一个修法是基准只用”真正产生了段的项”,被跳过的不当参照。第二个是段列表改成不可变快照发布:
private volatil ...
做 licence 防破解踩的几个坑
给一个 Java 工具做了套 licence,要解决两个现实问题:一份 licence 不被全公司共用、不被改系统时间无限续期。先说清楚一点,客户端 licence 本质是抬高破解成本,不是绝对防得住——私钥不泄露的前提下,能做到”普通用户懒得搞”的程度,真遇上专业逆向一样会破。
licence 本体是一张 JWT,RSA 私钥签发,客户端内嵌公钥验签。下面几个是做的时候要注意的点。
时间回拨JWT 的过期判断(exp)依赖系统时钟,所以最简单的破解就是把系统时间往回调,过期就判不出来了。
办法是本地存一个单调不降的时间记录:每次校验通过,把当前时间写进 ~/.myapp/.lastseen;下次校验前先比一下,now 比 lastseen 早超过一个容差就拒掉:
long lastSeen = Long.parseLong(readLastSeen());long now = System.currentTimeMillis();// 留 5 分钟容差吸收 NTP 微调、时区抖动return now >= lastSeen - CLOCK_ROLLBACK_TOLERANCE_ ...
Dewow:把偏到一边的秤归零
原始 A-scan 应该围绕零线上下振动,实际却经常整体偏到一边,像秤没归零。Dewow 就是先把秤拨回零。
为什么会偏波形整体偏移主要来自:
发射天线直接窜到接收天线的耦合信号;
接收机电路的直流偏置和缓慢漂移;
地面耦合条件随推车过程缓慢变化;
低频电磁干扰。
这些成分变化很慢,频率集中在零频和极低频,把真实信号的基线顶歪了。
用滑动平均估计漂移有用反射信号围绕天线中心频率快速振动,正半周和负半周大致抵消。取一个足够长的窗口做滑动平均:
快速振动部分一正一负,平均下来接近 0;
缓慢漂移在窗口里几乎是常数,平均后保留下来。
这个滑动平均就是漂移的估计,把它减掉,漂移就去掉了。
公式:
$$\hat d[n]=\frac{1}{W}\sum_{k=-W/2}^{W/2}x[n+k], \qquad \hat s[n]=x[n]-\hat d[n]$$
$x$ 是原信号,$\hat d$ 是估计漂移,$\hat s$ 是输出,$W$ 是窗长,取奇数。
写成 FIR 滤波器,所有抽头之和为 0,意味着直流增益正好是 0——这就是去 ...
微信支付接入踩的几个坑
前言微信支付的文档其实挺全,但接入的时候总有些”文档写了、你却未必留意”的坑。下面是我自己踩过或者帮人排查过的几条,不绑具体项目,只说通用经验。
平台公钥模式 vs 证书模式,怎么选微信支付回调验签现在主要有两种配置:
证书模式(RSAAutoCertificateConfig):SDK 自动下载并轮换平台证书。
平台公钥模式(RSAPublicKeyNotificationConfig):用一份固定的平台公钥验签。
证书模式省事,但在平台证书切换的那段时间,有可能 SDK 还没更新到新证书,验签就会失败。公钥模式稳定些,缺点是真到了换公钥的时候,得自己手动换文件。
我的选择是:商户号稳定、回调量不大的,用公钥模式,自己可控;商户号活跃、证书换得勤的,用证书模式,但切换那几天盯着点失败率。
回调 body 必须取原始字符串这是最容易踩的坑。微信支付回调的签名是对原始请求体算的,所以接回调时 body 得原封不动拿到,不能让框架先帮你反序列化:
@PostMapping("/notify")public ResponseEntity<String> n ...
支付状态同步-异步回调与主动查单兜底
不能只靠回调支付平台一般是异步回调通知商户:用户付完钱,平台往你的 /notify 地址 POST 一个请求,告诉你”这笔订单付了”。
但回调这东西不能全信。网络抖动、服务器重启、notify-url 改了、DNS 出问题、甚至平台那边延迟,都可能让回调丢掉或者晚到。只靠回调,迟早会遇到”用户钱都付了,你这边还不知道”这种情况。
所以支付状态同步一般做成:异步回调(推)+ 主动查单(拉),两条腿走路。
推和拉各管什么支付平台 商户服务 │ │ │ ① 用户完成支付 │ │ │ │──── POST /notify ────▶│ 推:被动接收支付结果 │ │ │◀── 返回 SUCCESS ──────│ │ │ │ │ │◀── GET /queryOrder ───│ 拉:主动查询 ...
支付回调的幂等设计
为什么回调必须幂等支付平台为了让你一定收到通知,回调是会重试的。同一笔订单支付成功,你这边可能收到一次、两次,甚至更多次 /notify。
如果每次回调都老老实实走一遍”更新订单 + 发货 + 开通权益”,轻则重复发货,重则重复扣库存、给用户重复加钱。所以回调这步必须做成幂等——同一笔通知来多少次,结果都一样。这块平时不起眼,但出了事基本都是它。
思路这三样我习惯叠在一起用,单独靠哪一个都不够稳。
状态机:PAID 是个单向终点订单状态尽量简单:
PENDING → PAID ↓EXPIRED / CANCELLED
PAID 只能从 PENDING 转过来。已经是 PAID 的订单再收到回调,直接返回成功,什么都不做——这是挡重复通知的第一步。
if (order.status == PAID) { return success; // 处理过了,直接 Ack}if (order.status != PENDING) { throw illegalState(); // 过期或已取消的订单,不再接受支付通知}
数据库唯一键 ...
