영수증 검증 관련 문의드립니다.

  • 뒤끝 SDK 버전 : 5.15.0
  • 프로젝트명 : MagicCommander
  • 스테이터스 코드 : public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
  • 에러 코드 : 없음
  • 에러 메시지 : 없음

안녕하세요. 우선 뒤끝서버 덕분에 서버 걱정 없이 개발할 수 있어서 감사합니다.
다름이 아니라,
영수증 검증 관련해서 게임을 껐다 켤 때마다
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
이 매서드가 호출되고 있는데
로그를 확인해보니
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
이 매서드 호출된 이후에 자동으로 호출되고 있는 것 같아서요.

실제 기능상으로는 아무런 문제는 없지만,
뒤끝 콘솔 ‘영수증 검증’ 탭에 실패한 기록이 계속 작성되어 보는데 불편함이 있습니다.
모든 구매항목들이 뜨는 건 아니고 이전에 구매한 적이 있는 항목만 뜨는 것 같습니다.

혹시 해결방법이 없을까 싶어서 문의드립니다.

아래는 제가 작성한 코드입니다.

public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
        {
            Debug.Log("유니티 IAP 초기화 성공");
            storeController = controller;
            storeExtensionProvider = extensions;
        }

        public void OnInitializeFailed(InitializationFailureReason error)
        {
            Debug.LogError($"유니티 IAP 초기화 실패 {error}");
        }

        public void OnInitializeFailed(InitializationFailureReason error, string message)
        {
            Debug.LogError($"유니티 IAP 초기화 실패: {error}, 메시지: {message}");
        }

        //영수증 검증
        public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
        {
            Debug.Log("영수증 검증 시작");
            string receiptJson = args.purchasedProduct.receipt;
            // 일반영수증 검증 (금액을 콘솔에서 표시하고자 할 경우)
            decimal iapPrice = args.purchasedProduct.metadata.localizedPrice;
            string iapCurrency = args.purchasedProduct.metadata.isoCurrencyCode;
            BackendReturnObject validation = Backend.Receipt.IsValidateGooglePurchase(receiptJson, "receiptDescription", iapPrice, iapCurrency);

            if (validation.IsSuccess())
            {
                string productId = args.purchasedProduct.definition.id;

                // 공통 처리
                MasterAudio.PlaySound("Buy");
                ClearMission();

                // 제품별 처리
                if (productId == ProductGem5000 || productId == ProductGem12000)
                {
                    int gemAmount = productId == ProductGem5000 ? 5000 : 12000;
                    GameManager.Instance.GainGem(gemAmount);
                    MainUIManager.Instance.rewardPopup.SetActive(true);
                    MainUIManager.Instance.rewardPopup.GetComponent<RewardPopup>().SetReward(2, gemAmount);
                }
                else if (productId == ProductPremiumPack)
                {
                    HandlePremiumPurchase();
                }
                else if (productId == ProductDailyPass)
                {
                    HandleDailyPassPurchase();
                }
                else if (productId == SkinSkeleton || productId == SkinSnow || productId == SkinTerra || productId == SkinWater || productId == SkinWitch)
                {
                    string skinName = "";
                    if(productId == SkinSkeleton){
                        skinName = "Skeleton";
                    }
                    else if(productId == SkinSnow){
                        skinName = "Snow";
                    }
                    else if(productId == SkinTerra){
                        skinName = "Terra";
                    }
                    else if(productId == SkinWater){
                        skinName = "Water";
                    }
                    else if(productId == SkinWitch){
                        skinName = "Witch";
                    }
                    HandleSkinPurchase(skinName);
                }
                else if (productId == ProductStarterPack)
                {
                    HandleStarterPackPurchase();
                }
                else
                {
                    Debug.Log($"인식되지 않은 제품: '{productId}'");
                    return PurchaseProcessingResult.Pending;
                }
            }
            else
            {
                Debug.Log($"일반 영수증 검증 실패. 인식되지 않은 제품: '{args.purchasedProduct.definition.id}'");
                return PurchaseProcessingResult.Pending;
            }

            return PurchaseProcessingResult.Complete;
        }

안녕하세요, 개발자님.

게임 실행 시마다 Unity IAP가 초기화하면서 자동으로 ProcessPurchase가 호출되는 것은 정상 구매 처리가 되지 않은 상품이 있기 때문입니다.
상품 구매 시에 오류가 발생하여 Complete처리되지 않고 앱이 종료되거나 Pending된 상품이 있을 경우에 발생합니다.
ProcessPurchase가 호출되면 필요한 처리를 하신 후(ex:구매 복구로직 등) 마지막에 IStoreController의 ConfirmPendingPurchase 함수를 호출해 주시면 됩니다.

감사합니다.

답변감사합니다. 아무래도 지난 번에 구글 계정 확인 때문에 결제가 안 되던 때에 구매 요청을 하셨던 분인가보네요. 일단 코드 상으로 막아두긴 했는데, 다른 분들도 동일 증상이 생기면 적용해보겠습니다! 감사합니다^^

좋아요 1