Files
FruitServer/fruitshorts-module-commerce/pom.xml
T
Zhou Weidong db897d50d6 feat(commerce): Google Play 票据校验闭环(校验→建单→发权益 + 幂等/防重放)
为什么:风险清单 R-03 把支付票据校验列为上线阻塞项;/app/orders/verify 此前只有 disabled
占位,且 verifyAndDeliver 要求订单事先存在——而 IAP 没有下单接口,接了校验也走不通。

- 新增 GooglePlayStoreVerifier(校验 purchaseState/productId/orderId)+ StorePlatforms(平台归一化)
- 新增 GooglePlayPurchaseClient 端口与 HttpGooglePlayPurchaseClient:JDK HttpClient + 服务账号
  RS256 JWT 换 token,不引入 Google SDK 依赖;token 按过期缓存
- StoreVerifier 实现由 fruitshorts.commerce.store.verifier 选择,默认 disabled,无凭据时对外行为不变
- OrderService 补齐闭环:校验通过后按 (platform, storeProductId) 找商品建单、写 store_receipt 审计、
  发金币并推进到 DELIVERED;幂等键 (platform, storeTransactionId) 与唯一索引双保险
- 防重放:重复提交同用户返回既有订单且不再发币;票据已被他人使用返回 403;校验失败不写任何数据
- 凭据只走配置/环境变量(packageName + service account JSON),不入库不提交
- 契约同步 docs/api-phase1.md §1.8;金额微单位换算与回退价有单测覆盖
- 实测:mvn test 54 条全过(commerce 13 + app-api 41,M2 的 37 条未被打红);
  两个入口 package 通过;默认 disabled 端到端返回 200003 且 orders 表零行
2026-10-16 11:03:33 +08:00

45 lines
1.7 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="UTF-8"?>
<!-- Author: fruit.com.cn -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.fruitshorts</groupId>
<artifactId>fruitshorts</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>fruitshorts-module-commerce</artifactId>
<name>fruitshorts-module-commerce</name>
<description>交易域:钱包、金币、订单、权益、对账</description>
<dependencies>
<dependency>
<groupId>com.fruitshorts</groupId>
<artifactId>fruitshorts-framework</artifactId>
</dependency>
<dependency>
<groupId>com.fruitshorts</groupId>
<artifactId>fruitshorts-module-content</artifactId>
</dependency>
<dependency>
<groupId>com.fruitshorts</groupId>
<artifactId>fruitshorts-module-user</artifactId>
</dependency>
<!-- 权益判定端口定义在播放域,这里提供实现(@Primary) -->
<dependency>
<groupId>com.fruitshorts</groupId>
<artifactId>fruitshorts-module-playback</artifactId>
</dependency>
<!-- 票据校验与订单交付的单测用:JUnit5 + Mockito,test scope,不进运行态依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>