자동화를 위해서 애플 앱스토어의 여러 기능을 개발할 수 있습니다.(애플에서 API일부를 제공해줘서)
그 중 앱의 IAP 리스트를 조회하는 API샘플입니다.
- 주의: API는 호출양 제한이 걸려있습니다.(링크 참고)
List All In-App Purchases for an App
- https://developer.apple.com/documentation/appstoreconnectapi/list_all_in-app_purchases_for_an_app
java 샘플 소스
- git 주소: https://github.com/oshnew/spring-boot-ver2-study/commit/b04e4293e983bf7425be17a97aaac6c80f70a26b
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import sample.apple.AppStoreConnectApi.AppStoreConnectApiJWT;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class ListInAppPurchasesForAnApp {
public static void main(String[] args) throws IOException {
final String issuer = "입력필요";
final String keyIdentifier = "입력필요";
final String privateKeyFilePath = "입력필요";
int expireAfterMinutes = 20;
AppStoreConnectApiJWT clzJWT = new AppStoreConnectApiJWT();
final String jwt = clzJWT.makeApiAuthJwt(issuer, keyIdentifier, expireAfterMinutes, privateKeyFilePath);
System.out.println("인증용 JWT: " + jwt);
OkHttpClient client = new OkHttpClient.Builder().readTimeout(4, TimeUnit.SECONDS).connectTimeout(1, TimeUnit.SECONDS).writeTimeout(5, TimeUnit.SECONDS).build();
final String id = "입력필요";
String prefixUri = String.format("https://api.appstoreconnect.apple.com/v1/apps/%s/inAppPurchasesV2", id);
HttpUrl.Builder httpBuilder = HttpUrl.get(prefixUri).newBuilder();
httpBuilder.addQueryParameter("limit", "200");
httpBuilder.addQueryParameter("filter[inAppPurchaseType]", "NON_CONSUMABLE");
final String fullUrl = httpBuilder.build().toString();
System.out.println("fullrUrl: " + fullUrl);
Request request = new Request.Builder().addHeader("Authorization", "Bearer " + jwt).url(fullUrl).build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
String rtnMsg = response.body().string();
System.out.println(String.format("성공. 응답 msg => '%s", rtnMsg));
} else {
System.out.println(String.format("응답에러(200이 아님). 응답 code:'%s'\n errMsg:'%s'", response.code(), response.body().string()));
}
}
}
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.tomcat.util.codec.binary.Base64;
import java.io.BufferedReader;
import java.io.FileReader;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class AppStoreConnectApiJWT {
public String makeApiAuthJwt(String issuer, String keyIdentifier, int expireAfterMinutes, String privateKeyFilePath) {
if (expireAfterMinutes > 20) {
throw new IllegalArgumentException(
"expireAfterMinutes는 20보다 작아야합니다. 참고: https://developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests");
}
final String strPrivateKey = readPrivateKeyBody(privateKeyFilePath);
PrivateKey privateKeyObj = convertToPrivateKeyObj(strPrivateKey);
Map<String, Object> header = new HashMap<>();
header.put("alg", SignatureAlgorithm.ES256);
header.put("kid", keyIdentifier);
header.put("typ", "JWT");
final Date now = new Date();
LocalDateTime expLdt = LocalDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault()).plusMinutes(10);
Date expiredAt = java.sql.Timestamp.valueOf(expLdt);
String jwt = Jwts.builder()
.setHeader(header)
.setIssuer(issuer)
.setAudience("appstoreconnect-v1")
.setIssuedAt(now)
.setExpiration(expiredAt)
.signWith(SignatureAlgorithm.ES256, privateKeyObj)
.compact();
return jwt;
}
private static PrivateKey convertToPrivateKeyObj(String strPrivateKey) {
try {
byte[] encodedKey = Base64.decodeBase64(strPrivateKey);
return KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
private String readPrivateKeyBody(String filePath) {
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
if (line.contains("PRIVATE KEY")) {
continue;
}
sb.append(line);
}
return sb.toString();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}