Google Play支付后端必看:service account.json获取与对接指南
做Google Play支付的时候最让后端同学头疼的往往不是写代码而是搞到那把能进Google Play Developer API的钥匙。标题里说的service account.json就是这个钥匙。很多团队在客户端把谷歌支付集成了订单也生成了结果后端要验签、查订单状态的时候发现没有service account.jsonGoogle Play Developer API根本调不通整个支付链路卡死在最后一步。这篇文章我完整拆一遍这个文件的获取方式、它在整个支付链路里的作用以及后端拿到文件后怎么去对接Play Developer API按我的步骤走一遍基本不会踩坑。这个项目面向的是正在做或者准备做Google Play支付的后端工程师、Android开发尤其适合那种客户端已经能弹出谷歌支付框但后端校验这块一直没落地的团队。核心就解决一件事怎么从零开始把服务账号文件拿到手并让后端用它完成购买凭证的校验。1. 这个项目到底在解决什么问题先把这个问题的位置放清楚。Google Play支付的对接分两段客户端一段后端一段。客户端用Play Billing Library拉起支付用户付完钱之后Google会返回一个purchaseToken客户端再把这个token传给自己的后端。后端拿着这个token去Google的服务器问一句这个token对应的订单是不是真实存在的、是不是已经付了钱、这个商品是不是该给用户发货。问题就在这。Google的服务器凭什么信任你它不认你的用户也不认你的App包名它认的是一个服务账号。服务账号的身份凭证就是service account.json。这个文件本质上是Google Cloud体系里的一种机器人账号的私钥里面有client_email和private_key后端就是拿这两个字段去换一个短期的access token再拿这个token去调Google Play Developer API。很多团队会在这里走弯路常见的有两种。一种是以为客户端拿到purchaseToken之后直接丢给Google校验就行结果发现C端那套OAuth根本不适合服务器场景另一种是图省事在Google Cloud Console里开了个API Key就拿去用短期能通但权限边界和审计能力都不如服务账号生产环境迟早要返工。1.1 Google Play支付的完整链路我习惯把整条链路画成五个环节这样出了问题能快速定位是哪一段的锅。第一步用户在Android应用里点购买应用通过Play Billing Library向Google Play发起购买请求。第二步Google Play弹出支付界面用户完成付款。第三步Google Play把购买结果回调给客户端客户端拿到一个叫做purchaseToken的字符串以及orderId、productId等订单信息。第四步客户端把purchaseToken发给自己的后端。第五步后端拿着这个token配合自己的service account.json调用Google Play Developer API查询这笔购买的真实状态确认无误后给用户发放权益。注意这里的关键点客户端拿到的purchaseToken就是后端验证的凭证它是一次性的、跟具体订单绑定的Google的接口会告诉你这个token对应的商品、购买时间、订单状态如果客户端和后端的订单信息对不上比如token是伪造的或者是从别的App里拷贝来的接口直接会返回404。1.2 为什么是service account.json而不是一把API KeyGoogle Cloud Console里创建凭据的时候会给你两个选项API Key和服务账号。API Key的用法是把它拼在URL后面方便是真方便但你想想这个Key只要能调通接口它就是个万能钥匙一旦泄露到客户端或Git仓库别人就能拿你的Key去刷Google的接口而且你没法在Google Cloud Console里按哪个App在用来精细控制。service account.json就不一样了。它是一对公钥私钥你拿私钥签发一个JWTGoogle那边用公钥验你的身份然后给你颁发一个短期的access token。这个过程中私钥全程不出现在网络请求里安全性高一个量级。而且服务账号可以挂角色权限比如只给androidpublisher的访问权限不给其他云资源的权限最小权限原则在支付这种场景里非常重要。所以生产环境我强烈建议直接用服务账号。标题里问的是service account.json获取方式其实答案已经隐含了你要创建的是服务账号并且把密钥以JSON格式下载下来不是创建API Key。2. service account.json获取全流程获取这个文件的完整路径是Google Cloud Console创建服务账号 Google Play Console授权两个控制台的操作串起来才算闭环。我见过有人只做了前半段下载了JSON文件兴冲冲地拿给后端去调接口结果一直403问下来发现Play Console那边压根没给这个服务账号分配App权限花了几小时才排查出来。2.1 前置条件两个控制台都要有权限开始操作之前你先确认两件东西。第一你得能登录Google Cloud Console并且对项目有管理员权限因为创建服务账号这个动作需要一定的IAM权限。第二你得能登录Google Play Console并且对该应用拥有管理订单和财务数据或者至少能管理用户权限的角色因为要把服务账号关联到App上没有管理员角色没法操作。如果你这两样都没有先去让团队里的Owner给你开权限别硬着头皮用自己的个人账号去试着搞后面会卡在授权环节而且用个人账号创建的凭据团队其他人没法维护。还有个细节容易被忽略Google Cloud的项目ID需要记住后面你在代码里如果要用project_id做参数或者排查问题的时候跟Google Cloud项目的区别对照没有项目ID会一脸懵。2.2 在Google Cloud Console创建服务账号并下载JSON在Cloud Console里左上角先选好项目如果你还没有项目新建一个叫google-pay-service之类的项目就行。然后进到IAM和管理-服务账号点创建服务账号。给服务账号起个名字比如play-billing-service描述里写清楚用途避免过几个月看到一堆服务账号分不清谁是谁。创建完成之后列表里会出现这一行点进去切到密钥页签点添加密钥-创建新密钥格式选JSON这时候浏览器会触发一个下载下载下来的那个文件就是service account.json。这个文件下载的时候要立刻转移到安全的地方。整个列表里你会看到有json和p12两种格式p12现在已经比较少用了统一选json就行。下载机会只有这一次如果你把文件弄丢了没法找回只能重新再生成一把新的密钥。生成之后我建议顺手把服务账号的类型记一下后面在代码里你要用到的是client_email和private_key这两个字段也是你判断这个文件是不是服务账号文件的关键依据。2.3 在Play Console把服务账号授权给应用这一步是整个流程里最容易被跳过的一环。拿到JSON不等于能用你在Cloud Console创建的服务账号默认跟Google Play没有任何关系得去Play Console里告诉它这个服务账号属于我们这个应用。打开Google Play Console进入你要对接的那个应用。左侧菜单找到设置或API权限新版界面叫API access或者用户和权限区域不同时期入口名称有差异找到关联服务账号的入口。谷歌会列出一串服务账号邮箱地址选中你在Cloud Console刚创建的那个client_email就行。关联后还需要给这个服务账号分配具体的角色。如果只是做支付验证给它财务数据相关的查看权限就够了别图省事直接给整包的管理权限。这一步做完服务账号才算是有了操作Google Play Developer API的资格。有些团队会用GCP的项目级授权来代替Play Console的关联操作但我不推荐那么干因为Play Console的授权是跟着具体应用走的你以后如果有多个App每个App单独关联权限边界更清晰。2.4 JSON文件里每个字段是干什么的后端拿到这个文件之后团队里其他人可能对这个文件一头雾水我顺手把关键字段解释一遍方便你写在项目文档里。典型的service account.json长这样{ type: service_account, project_id: my-google-pay-project, private_key_id: a1b2c3d4e5f6..., private_key: -----BEGIN PRIVATE KEY-----\nMIIEvQ...\n-----END PRIVATE KEY-----\n, client_email: play-billing-servicemy-google-pay-project.iam.gserviceaccount.com, client_id: 123456789012345678901, auth_uri: https://accounts.google.com/o/oauth2/auth, token_uri: https://oauth2.googleapis.com/token, auth_provider_x509_cert_url: https://www.googleapis.com/oauth2/v1/certs, client_x509_cert_url: https://www.googleapis.com/robot/v1/metadata/x509/play-billing-service%40my-google-pay-project.iam.gserviceaccount.com }type固定是service_account说明这是服务账号类型。project_id是Cloud项目的ID不是项目名称。private_key是核心中的核心就是你的私钥它决定了你能不能用这个服务账号去签发JWT这个字段千万不能泄露尤其是不要提交到Git仓库里。client_email是服务账号的用户名你在Play Console里关联账号用的就是它后端在代码里也主要靠它来标识身份。token_uri是换取access token时要请求的地址几乎是固定的但你还是应该以文件里的为准。注意这个JSON文件是敏感信息。我的习惯是把它加进.gitignore然后放到服务器的环境变量或者用密钥管理服务来存比如KMS之类的东西而不是直接放在代码目录里。也别为了省事把它发给客户端客户端永远不需要这个文件。3. 后端拿service account.json做什么文件拿到手后端的工作其实就三件事读取JSON文件、用私钥换access token、带着token去调Google Play Developer API。好消息是Google官方对主流的语言都提供了客户端库不需要自己手写JWT签名流程但理解底层原理对排查问题很有帮助。3.1 OAuth2认证流程从JSON到access token整个认证过程叫Service Account Authorization属于OAuth2里的客户端凭证模式只不过凭证不是简单的secret而是一个用私钥签名的JWT。流程大概是这样的后端读取JSON里的client_email和private_key构造一个JWTJWT的payload里需要包含iss签发者填client_email、scope请求的权限范围这里填https://www.googleapis.com/auth/androidpublisher、aud要发给谁填token_uri、iat签发时间、exp过期时间通常是一小时。然后拿private_key对这个JWT做RSA签名再把签名好的JWT以grant_typeurn:ietf:params:oauth:grant-type:jwt-bearer的形式POST到token_uri。Google收到请求后会验签验签通过就返回一个access_token这个token默认有效期3600秒也就是一小时。你拿着这个access_token去请求https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}就能查到订单了。如果不用官方库手动实现一遍上述流程踩坑点不少比如RSA签名算法的选择要用RS256、JWT头部的alg字段、时间戳的格式要Unix秒级。所以能用库就用库省心。3.2 用Python快速实现校验逻辑给后端一个Reference实现Python版本大概长这样from google.oauth2 import service_account from googleapiclient.discovery import build SERVICE_ACCOUNT_FILE service_account.json PACKAGE_NAME com.example.myapp SCOPES [https://www.googleapis.com/auth/androidpublisher] credentials service_account.Credentials.from_service_account_file( SERVICE_ACCOUNT_FILE, scopesSCOPES ) service build(androidpublisher, v3, credentialscredentials) def verify_purchase(product_id, purchase_token): try: result service.purchases().products().get( packageNamePACKAGE_NAME, productIdproduct_id, tokenpurchase_token ).execute() purchase_state result.get(purchaseState, -1) if purchase_state 0: return {valid: True, order_info: result} else: return {valid: False, reason: fpurchaseState{purchase_state}} except Exception as e: return {valid: False, error: str(e)}purchaseState字段是关键。0代表已购买1代表已取消2代表待处理。你发货的逻辑只有收到0才执行。另外还有consumptionState如果你做的是可消耗商品比如游戏币、钻石那还得管消耗状态。Java/Kotlin后端的实现也很常见用google-api-client库GoogleCredentials credentials ServiceAccountCredentials.fromStream( new FileInputStream(service_account.json)) .createScoped(Collections.singleton(https://www.googleapis.com/auth/androidpublisher)); AndroidPublisher publisher new AndroidPublisher.Builder( GoogleNetHttpTransport.newTrustedTransport(), GsonFactory.getDefaultInstance(), credentials) .setApplicationName(My App) .build(); Publisher.Purchases.Products.Get request publisher.purchases() .products() .get(packageName, productId, token); ProductPurchase purchase request.execute();官方库的好处是它内部自己处理了access_token的缓存、刷新不会每次请求都去重新走一遍OAuth流程性能上很重要。如果你自己手动搞别忘了对access_token做复用别每秒钟都重新签JWT不然Google的限流先把你拦了。3.3 产品与订阅的接口差异上面那个接口是查询一次性商品的如果你做的是订阅接口路径要换成purchases.subscriptions.get。订阅的返回体多了一些字段比如expiryTimeMillis到期时间、autoRenewing是否自动续费、cancelReason取消原因等。订阅这块有个容易踩的坑用户续费之后expiryTimeMillis会往后延你的后端不能只在上次到期时间前验证一次就完事得在拿到新token或者定期轮询时重新查询。客户端每次恢复购买也要把最新的token传给你你用新token去查才能拿到最新的订阅状态。另外一个很重要的字段orderId。客户端传到后端的orderId和Google接口返回的orderId格式可能不完全一致。Google接口的订单号有时带..后缀客户端那个可能不带所以后端如果拿订单号做去重建议以Google接口返回的为准别直接拿客户端传的字符串去数据库比对。4. 常见报错与排查实录对接过程中报错是难免的我把实际工作中高概率遇到的报错和排查思路整理一下方便你对着现象找原因。4.1 403 Permission Denied这个报错出现的频率最高。字面意思是权限被拒绝了但实际原因分好几种。第一种Play Console里没有关联服务账号。你拿着一个新建好的服务账号去调接口Play Console那边对这个服务账号一无所知当然要拒绝。去Play Console把client_email关联到应用上就好。第二种服务账号关联了但权限角色不对。比如你只给了查看财务报告的权限但代码里去调订单查询接口权限不足照样403。在Play Console的用户和权限里把服务账号的权限调整为能访问订单数据。第三种项目选错了。Google Cloud Console里有多个项目你创建服务账号的project_id跟你接口里的packageName不匹配或者你代码里初始化凭据时用的跟实际下载的不是同一个项目下的文件都会出现权限问题。排查的时候先确认client_email属于哪个项目packageName属于哪个应用这两个的归属关系要对上。4.2 401 Unauthorized401意味着认证本身出了问题Google根本不认你的身份或token。常见原因是access_token传错了位置。Google Play Developer API的HTTP请求要求把access_token放在Authorization: Bearer token头里有些同学把它拼到query参数或者拿成API Key去用就会401。还有一种是系统时钟不准。JWT里有iat和exp字段如果你的服务器时间跟真实时间偏差太大Google验签时会判定JWT过期或未生效直接拒绝。这个坑我踩过一次查了半天最后发现是服务器时间慢了几分钟用NTP同步一下就好了。最后一个原因要重点注意你拿到的JSON文件里的private_key是不是包含换行的完整私钥。有时候从KMS或者配置中心读出来的时候\n被转义成普通的n字符串签名出来的JWT就不对Google验签必失败。看到401且日志里没有更具体的提示时先检查私钥字符串的格式。4.3 400参数错误如果你的请求能到Google的接口且参数有问题Google会返回400或404。常见的情况是purchaseToken不合法比如客户端传过来的是拼接的或截断的。这时候你可以去Play Console的订单管理里找对应的真实token对比一下。还有可能是productId对不上比如客户端用的商品ID带了下划线或者大小写不一致跟你在Play Console里配置的商品ID不是同一个接口查不到自然就报错。404还有另一个原因这个token对应的订单确实存在但是它是另外一款应用生成的。Google的接口是packageName productId token三个参数联合校验的任何一个对不上都查不到这也刚好是Google防伪造的设计点。5. 一些踩坑后的经验最后说几点我在多个项目里沉淀下来的习惯。第一service account.json的保管流程一定要在团队里定死。私钥不止一个人用建议由一个人负责下载放到配置中心和密钥管理平台其他人通过环境变量或者配置中心读取不要用微信传来传去。这个文件一旦泄露别人可以拿你的服务账号去查询你名下所有用户的购买状态那不只是隐私问题是实打实的生产事故。第二不要把客户端传上来的purchaseToken直接存进数据库就完事。后端一定要在发货前实时调用Google接口验证不要在客户端支付时验证一次就信任一整天。因为用户可能发起退款、取消订阅你发货的那一刻才知道订单的真实状态。我见过有项目偷懒用户付完款后把订单状态缓存了7天结果有用户利用这个窗口收货后又退款最后对账对出一堆坏账。第三后端最好做一层缓存。access_token的有效期是3600秒频繁换token虽然不报错但Google有调用限额。你的服务如果是高并发的第一次拿到token后缓存到内存里比如用一个(expire_time - 60秒)提前量来刷新能避免很多无谓的请求。第四订阅场景一定要做定时任务对账。用户订阅了之后他的订阅状态理论上会一直变化比如到期不续费、退款、换绑。建议你每天跑一次全量订阅检查拿store到的最新订阅状态跟本地数据库做比对发现异常时自动降级用户权益。这个逻辑不复杂但能救你于水火省去和处理客诉的同事吵架的麻烦。第五日志里不要打印完整的purchaseToken和orderId。这些信息虽然不像私钥那么敏感但涉及用户交易数据万一日志被人扒了对用户没什么好处。真要打印截取前几位和最后几位做个脱敏就够了。这个流程走到这里你的后端应该已经能用service account.json完成整个Google Play支付校验了。下次再碰到Android端说我这边已经唤起支付了你就可以自信地把这串验收清单甩过去token先发我packageName对不对productId对不对我这边用service account去查一次Google就清楚了。

相关新闻

TCP四次挥手与TIME_WAIT:从原理到线上排查实战

TCP四次挥手与TIME_WAIT:从原理到线上排查实战

排查过几次“Address already in use”之后,你就会对TCP四次挥手和TIME_WAIT产生一种又爱又恨的情绪。网上讲三次握手、四次挥手的文章一抓一大把,但大部分都停留在“画箭头、念状态”的层面;一旦你真正面对一个Java客户端重连时报地址已在使…

2026/10/2 18:26:15 阅读更多 →
本科生降AI率实战:9个工具与避坑指南

本科生降AI率实战:9个工具与避坑指南

先说句实在话:本科生现在提“降AI率”,多数是被检测报告逼出来的。我见过一个学弟,论文写得四平八稳,结果AIGC检测直接标红62%,导师看完让他拿回去“亲手重写”。他来找我的时候,第一句话就是“有没有工具能…

2026/10/2 18:26:15 阅读更多 →
指静脉图像预处理全流程:边界去除、静脉提取与去毛刺实战

指静脉图像预处理全流程:边界去除、静脉提取与去毛刺实战

简介:面向图像处理与生物识别初学者的MATLAB源码包,以手指静脉识别为应用场景,集中解决图像边界去除、静脉提取、毛刺消除等预处理难题。包内共1个m文件,体积仅2KB,是一份可直接运行的核心脚本,适合快速理解…

2026/10/2 18:26:14 阅读更多 →

最新新闻

SpringBoot多数据源实战:dynamic-datasource集成与避坑指南

SpringBoot多数据源实战:dynamic-datasource集成与避坑指南

做后端开发的兄弟,大概率都遇到过这样的场景:项目刚上线时一套MySQL库跑得挺欢,后来订单量大了,老板说要把报表拆出来,于是又多了一个只读库;再往后,用户服务单独拆了一套库,数据分析…

2026/10/3 20:48:49 阅读更多 →
北大凸优化编程作业全解析:从自动微分到ADMM的代码链

北大凸优化编程作业全解析:从自动微分到ADMM的代码链

简介:北京大学信息科学技术学院智能科学与技术系“凸分析与优化方法”课程编程作业集合,面向正在学习凸优化、自动微分和神经网络训练的学生,用于实践并比较多种经典优化算法。资源共63个文件,以23个Python脚本和32张结果图为主&a…

2026/10/3 20:48:49 阅读更多 →
龙勃透镜电磁聚焦原理与Matlab仿真实现:雷达增益提升的工程解读

龙勃透镜电磁聚焦原理与Matlab仿真实现:雷达增益提升的工程解读

雷达信号中的“光学魔术”:用Matlab模拟龙勃透镜的聚焦放大效应做雷达信号处理这些年,我一直对天线和传播路径上的“另类”器件很感兴趣。龙勃透镜这名字听着像光学里的东西,但它在雷达领域的作用其实非常硬核——把一个球形的介质透镜放在天…

2026/10/3 20:47:48 阅读更多 →
Go语言实现三数之和:排序+双指针去重技巧全解析

Go语言实现三数之和:排序+双指针去重技巧全解析

这道题我刷了好几遍,每次在面试前都会把它翻出来重新写一遍。不是说它难,而是它在 LeetCode Hot 100 里的地位很特别——你几乎不可能在真正的面试里碰到一模一样的三数之和,但面试官完全可能换一个壳,考你排序加双指针这个组合套…

2026/10/3 20:47:48 阅读更多 →
Redis服务器部署与生产级排障实战:从安装到缓存治理

Redis服务器部署与生产级排障实战:从安装到缓存治理

服务器之 Redis:从零搭建到生产级排障的完整实战笔记 Redis 在服务器端的重要性,根本不需要我再多吹。只要你的系统扛过一定的并发,Redis 基本就是那根绕不开的“救命稻草”。它是高性能键值存储服务器,能做缓存、分布式锁、消息队…

2026/10/3 20:47:48 阅读更多 →
人机协同实战指南:从分工逻辑到落地流程

人机协同实战指南:从分工逻辑到落地流程

做AI项目这几年,我越来越觉得,真正决定项目上限的往往不是模型本身的参数量,而是我们和AI协作的方式。人机协同不是一句贴在PPT里的口号,它直接决定了你是被AI替代,还是用AI放大自己的能力。这篇内容算是“AI全景”系列…

2026/10/3 20:47:48 阅读更多 →

日新闻

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南 【免费下载链接】ex-skill 前任 skill 项目地址: https://gitcode.com/gh_mirrors/exsk/ex-skill 前任.skill 是一个运行在 Claude Code 上的开源 Skill:导入微信、iMessage、短信、…

2026/10/3 0:00:27 阅读更多 →
45个经典Linux面试题:从命令到网络排障的完整考点解析

45个经典Linux面试题:从命令到网络排障的完整考点解析

刚开始带应届生的时候,我最头疼的就是他们拿着一摞Linux面试题背得滚瓜烂熟,一上机全露馅。后来自己从被面的人变成面别人的人,才慢慢摸清楚:Linux面试题考的根本不是答案本身,而是你面对一个不确定的系统问题时&#…

2026/10/3 0:01:28 阅读更多 →
SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

简介:本资源是一份面向SAP ABAP开发人员、生产计划专员及ERP实施顾问的实操型操作指南,聚焦SAP生产预留核心业务场景,系统解决物料预留创建、查询、校验与批量处理等高频问题。文档以结构化方式覆盖预留背景原理、OMC2编码规则、工厂级参数配…

2026/10/3 0:01:28 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/3 9:14:33 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/3 9:47:50 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/3 9:42:31 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:35 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →