Browse Source
Merge remote-tracking branch 'refs/remotes/origin/milestone-20260401-现金管理四期' into lijianlin/feature-20260401-现金管理四期
lijianlin/feature-20260401-现金管理四期
Merge remote-tracking branch 'refs/remotes/origin/milestone-20260401-现金管理四期' into lijianlin/feature-20260401-现金管理四期
lijianlin/feature-20260401-现金管理四期
13 changed files with 94 additions and 70 deletions
-
63src/main/java/com/example/demo/Util/AppleJWTGenerator.java
-
58src/main/java/com/example/demo/Util/AppleTokenGenerator.java
-
9src/main/java/com/example/demo/controller/cash/CashCollectionController.java
-
2src/main/java/com/example/demo/domain/DTO/PerformanceAdjustmentDTO.java
-
1src/main/java/com/example/demo/domain/entity/UserWalletRecord.java
-
3src/main/java/com/example/demo/mapper/cash/CashCollectionMapper.java
-
2src/main/java/com/example/demo/mapper/coin/RateMapper.java
-
3src/main/java/com/example/demo/service/cash/CashCollectionService.java
-
10src/main/java/com/example/demo/serviceImpl/cash/CashAuditServiceImpl.java
-
4src/main/java/com/example/demo/serviceImpl/cash/CashCollectionServiceImpl.java
-
3src/main/java/com/example/demo/serviceImpl/cash/CashRefundServiceImpl.java
-
3src/main/resources/cashMapper/CashCollectionMapper.xml
-
3src/main/resources/mapper/RateMapper.xml
@ -0,0 +1,63 @@ |
|||||
|
package com.example.demo.Util; |
||||
|
|
||||
|
import java.nio.file.Files; |
||||
|
import java.nio.file.Paths; |
||||
|
import java.security.KeyFactory; |
||||
|
import java.security.PrivateKey; |
||||
|
import java.security.spec.PKCS8EncodedKeySpec; |
||||
|
import java.util.Base64; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
public class AppleJWTGenerator { |
||||
|
|
||||
|
// 你提供的信息 |
||||
|
private static final String KEY_ID = "3J2S9VXU3V"; |
||||
|
private static final String ISSUER_ID = "69a6de7e-1f9a-47e3-e053-5b8c7c11a4d1"; |
||||
|
private static final String P8_FILE_PATH = "E:/Work/newgold/gold-java/src/main/java/com/example/demo/Util/AuthKey_3J2S9VXU3V.p8"; |
||||
|
|
||||
|
public static void main(String[] args) { |
||||
|
try { |
||||
|
String token = generateAppleJWT(); |
||||
|
System.out.println("在 Apifox 里直接复制这一行:"); |
||||
|
System.out.println("Bearer " + token); |
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static String generateAppleJWT() throws Exception { |
||||
|
// 读取 p8 文件 |
||||
|
String p8Content = Files.readString(Paths.get(P8_FILE_PATH)) |
||||
|
.replace("-----BEGIN PRIVATE KEY-----", "") |
||||
|
.replace("-----END PRIVATE KEY-----", "") |
||||
|
.replaceAll("\\s+", ""); |
||||
|
|
||||
|
// 解码私钥 |
||||
|
byte[] decoded = Base64.getDecoder().decode(p8Content); |
||||
|
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded); |
||||
|
KeyFactory kf = KeyFactory.getInstance("EC"); |
||||
|
PrivateKey privateKey = kf.generatePrivate(spec); |
||||
|
|
||||
|
// ========== JWT Header ========== |
||||
|
String header = "{\"alg\":\"ES256\",\"kid\":\"" + KEY_ID + "\",\"typ\":\"JWT\"}"; |
||||
|
String headerBase64 = Base64.getUrlEncoder().withoutPadding().encodeToString(header.getBytes()); |
||||
|
|
||||
|
// ========== JWT Payload ========== |
||||
|
long now = new Date().getTime() / 1000; |
||||
|
String payload = String.format( |
||||
|
"{\"iss\":\"%s\",\"iat\":%d,\"exp\":%d,\"aud\":\"appstoreconnect-v1\"}", |
||||
|
ISSUER_ID, now, now + 15 * 60 // 15分钟有效期 |
||||
|
); |
||||
|
String payloadBase64 = Base64.getUrlEncoder().withoutPadding().encodeToString(payload.getBytes()); |
||||
|
|
||||
|
// ========== ES256 签名 ========== |
||||
|
String data = headerBase64 + "." + payloadBase64; |
||||
|
java.security.Signature signature = java.security.Signature.getInstance("SHA256withECDSAinP1363Format"); |
||||
|
signature.initSign(privateKey); |
||||
|
signature.update(data.getBytes()); |
||||
|
byte[] signed = signature.sign(); |
||||
|
String signatureBase64 = Base64.getUrlEncoder().withoutPadding().encodeToString(signed); |
||||
|
|
||||
|
return data + "." + signatureBase64; |
||||
|
} |
||||
|
} |
||||
@ -1,58 +0,0 @@ |
|||||
//package com.example.demo.Util; |
|
||||
// |
|
||||
//import io.jsonwebtoken.Jwts; |
|
||||
//import io.jsonwebtoken.SignatureAlgorithm; |
|
||||
//import io.jsonwebtoken.io.Decoders; |
|
||||
//import java.nio.file.Files; |
|
||||
//import java.nio.file.Paths; |
|
||||
//import java.security.KeyFactory; |
|
||||
//import java.security.PrivateKey; |
|
||||
//import java.security.spec.PKCS8EncodedKeySpec; |
|
||||
//import java.util.Date; |
|
||||
// |
|
||||
//public class AppleTokenGenerator { |
|
||||
// |
|
||||
// // 你提供的真实信息(已全部填好) |
|
||||
// private static final String KEY_ID = "3J2S9VXU3V"; |
|
||||
// private static final String ISSUER_ID = "69a6de7e-1f9a-47e3-e053-5b8c7c11a4d1"; |
|
||||
// private static final String P8_FILE_PATH = "E:/Work/newgold/gold-java/src/main/java/com/example/demo/Util/AuthKey_3J2S9VXU3V.p8"; |
|
||||
// |
|
||||
// public static String generateToken() { |
|
||||
// try { |
|
||||
// // 读取 P8 私钥内容 |
|
||||
// String p8Content = Files.readString(Paths.get(P8_FILE_PATH)) |
|
||||
// .replace("-----BEGIN PRIVATE KEY-----", "") |
|
||||
// .replace("-----END PRIVATE KEY-----", "") |
|
||||
// .replaceAll("\\s+", ""); |
|
||||
// |
|
||||
// // 解码私钥 |
|
||||
// byte[] keyBytes = Decoders.BASE64.decode(p8Content); |
|
||||
// PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); |
|
||||
// KeyFactory keyFactory = KeyFactory.getInstance("EC"); |
|
||||
// PrivateKey privateKey = keyFactory.generatePrivate(spec); |
|
||||
// |
|
||||
// // 生成苹果官方标准 JWT(补全typ字段,完全符合文档要求) |
|
||||
// return Jwts.builder() |
|
||||
// .setHeaderParam("alg", "ES256") |
|
||||
// .setHeaderParam("kid", KEY_ID) |
|
||||
// .setHeaderParam("typ", "JWT") // 🔴 苹果官方强制要求,之前漏了! |
|
||||
// .setIssuer(ISSUER_ID) |
|
||||
// .setAudience("appstoreconnect-v1") |
|
||||
// .setIssuedAt(new Date()) |
|
||||
// .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 15)) // 15分钟有效期(≤20分钟) |
|
||||
// .signWith(privateKey, SignatureAlgorithm.ES256) |
|
||||
// .compact(); |
|
||||
// |
|
||||
// } catch (Exception e) { |
|
||||
// e.printStackTrace(); |
|
||||
// return null; |
|
||||
// } |
|
||||
// } |
|
||||
// |
|
||||
//// // 运行直接输出可用 Token |
|
||||
//// public static void main(String[] args) { |
|
||||
//// String token = generateToken(); |
|
||||
//// System.out.println("复制下面这一行直接用:"); |
|
||||
//// System.out.println("Bearer " + token); |
|
||||
//// } |
|
||||
//} |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue