JAVA 인앱 결제 ( IOS 구매 내역 호출 )
정기 결제를 개발하며 IOS 구매 내역 확인을 해야 합니다.
구성
JAVA 8
Spring boot
Maven
https://developer.apple.com/documentation/appstoreserverapi/get_transaction_history_v1
Get Transaction History V1 | Apple Developer Documentation
Get a customer’s in-app purchase transaction history for your app, except finished consumable in-app purchases.
developer.apple.com
코드 먼저 작성 하고 설명하겠습니다.
pom.xml
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
service
Map<String, Object> headers = new HashMap<>();
headers.put("alg", "ES256");
headers.put("kid", "TTP2RC247M");
headers.put("typ", "JWT");
Date issuedAt = Date.from(Instant.now());
Date expiredAt = Date.from(Instant.now().plus(Duration.ofMinutes(10L)));
// 키파일
PrivateKey privateKey = getPrivateKey("key/AuthKey_TTP2RC247M.p8", "EC");
String jws = Jwts.builder()
.setHeader(headers)
.setIssuer("발급자키")
.setAudience("appstoreconnect-v1")
.setExpiration(expiredAt)
.setIssuedAt(issuedAt)
.claim("bid", "패키지명")
.signWith(privateKey, SignatureAlgorithm.ES256)
.compact();
Map<String, Object> returnList = new HashMap<>();
URL url = new URL(
"https://api.storekit.itunes.apple.com/inApps/v1/history/고객구매번호?productId=상품번호&sort=DESCENDING"
);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "Bearer " + jws);
conn.setRequestProperty("Content-type", "application/json");
conn.setRequestMethod("GET");
try(BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
String output;
StringBuffer sb = new StringBuffer();
while ((output = in.readLine()) != null) {
sb.append(output).append("\n");
}
if (!sb.equals("")) {
returnList = new ObjectMapper().readValue(sb.toString(), new TypeReference<Map<String, Object>>(){});
}
}
List<String> signedTransactions = new ObjectMapper().convertValue(returnList.get("signedTransactions"), new TypeReference<List<String>>() {});
for(String st : signedTransactions){
String[] check = st.split("\\.");
Base64.Decoder decoder = Base64.getDecoder();
String payload = new String(decoder.decode(check[1]));
log.info("payload :: "+payload);
}
url 은 운영, 개발(샌드박스) 이 있습니다.
저는 운영으로 진행하였습니다.
sort DESCENDING 진행 하였습니다.
JWT헤더 생성 참조
Generating JSON Web Tokens for API requests | Apple Developer Documentation
Create JSON Web Tokens signed with your private key to authorize requests for App Store Server API and External Purchase Server API.
developer.apple.com
public PrivateKey getPrivateKey(String filename, String algorithm) throws IOException {
ClassPathResource resource = new ClassPathResource(filename);
String content;
InputStream inputStream = resource.getInputStream();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream) )) {
content = reader.lines().collect(Collectors.joining("\n"));
}
try {
String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\s+", "");
KeyFactory kf = KeyFactory.getInstance(algorithm);
return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Java did not support the algorithm:" + algorithm, e);
} catch (InvalidKeySpecException e) {
throw new RuntimeException("Invalid key format");
}
}
위와 같이 하면 나오는 로그 json
{
"transactionId":"고객주문번호",
"originalTransactionId":"고객주문번호",
"webOrderLineItemId":"주문품목ID",
"bundleId":"패키지명",
"productId":"상품명",
"subscriptionGroupIdentifier":"21419068",
"purchaseDate":1714782833000,
"originalPurchaseDate":1714782834000,
"expiresDate":1717461233000,
"quantity":1,
"type":"Auto-Renewable Subscription",
"inAppOwnershipType":"PURCHASED",
"signedDate":1718589613537, // 결제 날자
"offerType":1,
"environment":"Production",
"transactionReason":"PURCHASE",
"storefront":"KOR",
"storefrontId":"매장아이디",
"price":0,
"currency":"KRW",
"offerDiscountType":"FREE_TRIAL" // 무료체험
}
inAppOwnershipType : 구매 갱신 확인
expiresDate : 만료 날짜
signedDate : 결제 날짜
위 데이터로 결제 확인 합니다.
Creating API keys to authorize API requests | Apple Developer Documentation
Create API keys you use to sign JSON Web Tokens and authorize API requests.
developer.apple.com
[Spring boot] App Store Connect API를 이용하여 앱정보 가져오기
Apple은 Appstore open API를 제공합니다. 그 중 이번에 사용해볼 API는 App Store Connect API입니다. https://developer.apple.com/documentation/appstoreconnectapi해당 API를
velog.io