JAVA 인앱 결제 ( IOS 구매 내역 호출 )

성난호랑이 시니철 ㅣ 2024. 6. 17. 18:29

 

정기 결제를 개발하며 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헤더 생성 참조

https://developer.apple.com/documentation/appstoreserverapi/generating_json_web_tokens_for_api_requests

 

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                  : 결제 날짜

 

위 데이터로 결제 확인 합니다.

 

참조 : https://developer.apple.com/documentation/appstoreserverapi/creating_api_keys_to_authorize_api_requests

 

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

참조 : https://velog.io/@dktlsk6/Spring-boot-App-Store-Connect-API%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-%EC%95%B1%EC%A0%95%EB%B3%B4-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0

 

[Spring boot] App Store Connect API를 이용하여 앱정보 가져오기

Apple은 Appstore open API를 제공합니다. 그 중 이번에 사용해볼 API는 App Store Connect API입니다. https://developer.apple.com/documentation/appstoreconnectapi해당 API를

velog.io

 

'공부 > JAVA' 카테고리의 다른 글

솔리드원칙 객체지향(OOP) 5원칙  (0) 2024.05.24
JAVA 인앱 결제 ( 안드로이드 구글 구매 확정 호출 )  (0) 2024.04.19
JAVA 문자열 뒤집기  (0) 2024.03.04
String 기능 모음  (0) 2024.03.04
Java AES-256 양방향 암호화  (0) 2024.02.16