Auto-renewable subscription free trial 확인

현재 react-native-iap 모듈 사용해서 자동갱신 구독 서비스 구현하고 있습니다.
1달, 6달, 12달 단위의 구독이 있고
현재는 구독아이템의 product id와 transactionDate을 기준으로 갱신일을 예상하고 있는데
(각 플랫폼 validation 확인 api로 매번 최신 transactionDate를 갱신합니다)

한달 단위로 결제하는 아이템에서 신규구독 7일 무료 설정을 한 경우
신규 구독인지나 현재 trial 버전을 사용하고 있는지 어떻게 확인할 수 있을까요?

단순히 한번만 조회하실게 아니라면, 별도의 백엔드를 통해서 관리하셔야 합니다.
AndroidiOS 각각 Server Notification 을 설정할 수 있는데요
유저로부터 구독과 관련된 이벤트가 발생하면, 서버에 post 형식으로 데이터를 보내줍니다.

이 정보에는 이벤트 타입(구독/구독취소/환불 등…) 과 구매에 대한 정보가 있구요
해당 이벤트를 받았을때, 해당 구매에 대해서 영수증을 조회하고
해당 구매 아이디를 가진 유저의 테이블을 조회하여 이벤트 타입 + 영수증 상태에 알맞게 업데이트를 해주면 됩니다.

영수증 검증 payload 를 확인하시면 무료 체험 상태와 같은 구매에 대한 모든 정보는
paymentState 혹은 is_trial_period 와 같이 양측 플랫폼에 모두 포함되어 있습니다.


질문하신 내용을 안드로이드를 예를 들어 답해 드리자면 아래와 같이 처리하시면 됩니다.

첫 구매

  1. [클라이언트] 유저가 첫 구매를 진행
  2. [클라이언트] 구매한 정보를 백엔드에 전송
  3. [서버] 수신받은 데이터로 영수증 검증
  4. [서버] 영수증 검증 결과 -> 테스트 결제 / 무료 체험 / 자동 갱신 유뮤 / 결제일 / 상품 아이디 등… 을 기반으로 유저의 상태 테이블 업데이트
  5. [서버] 구매의 상태(테스트 결제/무료체험/환불유무) 와 함께 구매 정보 저장

한달 후, 자동 갱신(Android)

  1. [구글 서버] RENEWED 이벤트를 구매 데이터와 전송
  2. [서버] 수신받은 정보를 영수증 검증
  3. [서버] 영수증 검증 결과 -> 테스트 결제 / 무료 체험 / 자동 갱신 유뮤 / 결제일 / 상품 아이디 등… 을 기반으로, 유저의 상태 테이블 업데이트 (purchaseToken 혹은 orderId 를 통해서, 해당 구매를 보유한 유저를 찾아서 업데이트 해준다.)
  4. [서버] 구매의 상태(테스트 결제/무료체험/환불유무) 와 함께 구매 정보 저장

몇가지 첨언드리자면, 안드로이드는 거의 모든 이벤트에 대해서 지원을 해주고 테스트 환경에서도 동일하게 테스트가 가능하지만
iOS의 경우 구독 갱신과 같은 이벤트는 제공하지 않아서 스케쥴러를 통해 따로 설정 해주셔야 하고
이벤트 발생 조건도 굉장히 모호하면서 중복되고, 최근에는 조금 개선 됐지만 테스트 환경과 실제 프로덕션 환경에서의 영수증 payload 가 다른 등의 문제가 있고, 두 플랫폼을 하나로 엮는다는게 매우 번거롭습니다.

하지만 만들기만 한다면, 아래와 같이 편하게 한눈에 조회가 가능합니다… :innocent:

(RevenueCat 이라는 서비스도 한번 참고해보시면 좋을 것 같습니다.)

1 Like

자세하게 설명해주셔서 정말 감사드립니다 :joy:
질문드린 부분은 is_trial_period 로 확인해서 처리했습니다.

한가지 궁금한 점이, 자동갱신시 안드로이드 자동갱신 이벤트를 구글 서버에서 보내는데,
서버에서 받을 수 있는 이벤트가 존재하는 건가요? 아니면 validation 요청을 보내 갱신된 receipt을 받는 건가요?
기존 payment 영수증으로 검증 요청을 보내면 이전 영수증일 경우 expiryTimeMillis와 사용자 취소유무를 업데이트해서 보내주던데 저는 그동안 그 정보를 가지고 갱신여부를 확인하고 있었습니다.

(iOS도 마찬가지로 validation 로직을 통해 갱신 여부를 확인하고 있습니다.)

추후 서버로 validation 로직을 이전할 계획이긴 하지만 혹시 앱에서 validation 확인을 한뒤 결과만 테이블 업데이트하는 방식으로 발생할 수 있는 보안이슈나 문제가 어떤게 있는 건지도 궁금합니다.

안드로이드 서버 알람을 수신하도록 설정하시면, 설정하신곳으로 유저의 구독 이벤트에 대해서 아래와 같이 request 가 날아옵니다.
ex) 구독중이던 유저의 정기결제가 자동 갱신됨: [구글 서버] -> SUBSCRIPTION_RENEWED -> [서비스 서버]

    // data 는 base64로 인코딩 되어있음
    // body = {
    //     message: { data }
    // };
    const { message: { data } } = request.body;
    const buffer = Buffer.from(data, "base64");
    const notification = JSON.parse(buffer.toString());
    // notification = {
    //     subscriptionNotification: {
    //         notificationType,
    //         purchaseToken,
    //         subscriptionId
    //     }
    // }

    // purchaseToken - 구매 토큰, 업그레이드 혹은 새로 구매하지 않는 한, 항상 똑같은 토큰이 전달된다.
    // subscriptionId - 구매 상품 sku ( ex: com.subscription.1000)
    // notification type - 1 ~ N (이벤트 순서대로)
    //  SUBSCRIPTION_RECOVERED = 1
    //  SUBSCRIPTION_RENEWED = 2
    //  SUBSCRIPTION_CANCELED = 3
    //  SUBSCRIPTION_PURCHASED ...
    //  SUBSCRIPTION_ON_HOLD ...
    //  SUBSCRIPTION_IN_GRACE_PERIOD
    //  SUBSCRIPTION_RESTARTED
    //  SUBSCRIPTION_PRICE_CHANGE_CONFIRMED
    //  SUBSCRIPTION_DEFERRED
    //  SUBSCRIPTION_PAUSED
    //  SUBSCRIPTION_PAUSED_SCHEDULE_CHANGED
    //  SUBSCRIPTION_REVOKED
    //  SUBSCRIPTION_EXPIRED

purchaseToken 으로 영수증 검증을 하시고, 반환된 결과를 통해 최신의 정보로 처리하시면 됩니다.


보안적인 이슈로는 Google/Apple 쪽 리소스에 접근할 수 있는 password/access token 를 앱에서 validation request 를 다이렉트로 보내면서 사용하는데, 이 부분이 탈취 혹은 노출 될 수 있습니다.
저희가 문제점을 느끼고 개발했던 주된 이유는, 수익 추적 + Purchase/Renew/Expire/Refund + 유저들의 구독 상태 모니터링 등 정확한 실시간 수집/통계가 불가능해서 였습니다.

1 Like