영수증 검증 오류

문의를 남기실 경우 다음 항목을 작성해 주세요.
정보가 부족한 경우 확인 및 답변이 지연될 수 있습니다.

  • 뒤끝 SDK 버전 : 5.4.5
  • 프로젝트명 : Taste of Power
  • 스테이터스 코드 :
  • 에러 코드 :
  • 에러 메시지 :

영수증 검증시 계속 오류가 발생하네요…
한명의 유저에게서 계속 영수증 검증에 문제가 발생합니다…
옛날에 한번 발생했었는데 이 후 발생하지 않아 무시했었는데,
어제 오늘 사이 한유저에게 3번이나 문제가 발생하였네요

구글 결제의 영수증 검증이 성공할 경우에 재화가 지급되도록 만들어져있습니다
문제는

  1. 뒤끝 콘솔에서 게임 캐쉬 > 영수증 검증에 최초 성공 이력이 올라옴
  2. 이후 (-)로된 실패 이력이 한번더 발생
  3. 구글 콘솔에서 본 결과 결제 정상 적용됌
  4. 재화 안들어감

어느부분이 문제인건가요 이거?

안녕하세요 개발자님,
확인된 바로는 최초 영수증 검증 성공 이후 성공된 동일한 토큰(receiptToken)으로 영수증 검증을 시도하여 검증에 실패한 것으로 확인됩니다.

첫 결제 이후 두번째, 세번째 또한 구글 결재를 시도한 이력이 있는지(구글콘솔의 주문관리) 확인해 주시고, 구글에서의 주문 내역의 구매 토큰과 뒤끝 콘솔에서의 실패 내역의 구매 토큰을 비교해 주세요.

안녕하세요 Ransiee님!
확인한 바로는 첫 시도 이후 시도된 결제가 없습니다.

또한 해당 토큰으로 다시 진행이 됐다면 최초 결제는 정상적으로 진행이 된 후에 나머지 결제문에 문제가 있어야 되는데,

최초의 결제에서 아이템 지급이 되질 않습니다.

// 코드
BackendReturnObject bro = Backend.Receipt.IsValidateGooglePurchase(args.purchasedProduct.receipt, “receiptDescription”, false);
{
if (bro.IsSuccess())
{
string newString = args.purchasedProduct.definition.id;
Param param = new Param();
param.Add(newString, “ProductName”);
SendQueue.Enqueue(Backend.GameLog.InsertLog, “buy_Sucesses_Server”, param, (callback) => { });

            // 다이아
            if (String.Equals(args.purchasedProduct.definition.id, diamond5, StringComparison.Ordinal)) { LobbyManager.MyInstance.buyDiamond(0); }
            else if (String.Equals(args.purchasedProduct.definition.id, diamond10, StringComparison.Ordinal)) { LobbyManager.MyInstance.buyDiamond(1); }
            else if (String.Equals(args.purchasedProduct.definition.id, diamond50, StringComparison.Ordinal)) { LobbyManager.MyInstance.buyDiamond(2); }
            else if (String.Equals(args.purchasedProduct.definition.id, diamond100, StringComparison.Ordinal)) { LobbyManager.MyInstance.buyDiamond(3); }

            // 크리스탈
            else if (String.Equals(args.purchasedProduct.definition.id, cristal1, StringComparison.Ordinal)) { LobbyManager.MyInstance.buycristal(0); }
            else if (String.Equals(args.purchasedProduct.definition.id, cristal2, StringComparison.Ordinal)) { LobbyManager.MyInstance.buycristal(1); }
            else if (String.Equals(args.purchasedProduct.definition.id, cristal3, StringComparison.Ordinal)) { LobbyManager.MyInstance.buycristal(2); }
            else if (String.Equals(args.purchasedProduct.definition.id, cristal4, StringComparison.Ordinal)) { LobbyManager.MyInstance.buycristal(3); }

          // 등등

            // 연금
            else if (String.Equals(args.purchasedProduct.definition.id, insurance1, StringComparison.Ordinal)) { LobbyManager.MyInstance.BuyInsurance(0); }
            else if (String.Equals(args.purchasedProduct.definition.id, insurance2, StringComparison.Ordinal)) { LobbyManager.MyInstance.BuyInsurance(1); }


        }
        else
        {
            Debug.Log(string.Format("결제실패 : '{0}'", args.purchasedProduct.definition.id));
            Debug.Log(bro.GetMessage());
        }
    }

일단 첫번째 시도에서 성공한 것은 맞습니다.
하지만 그 이후 로직인 if(bro.IsSuccess())가 동작을 하지 않은 것으로 예상됩니다.
(buy_Sucesses_Server의 로그 삽입 호출이 되지 않음)

  • 동기형식이기 때문에 1.5초 정도 멈추게 되는데 그 순간에 유저가 멈춘것으로 생각하고 나가거나, 비정상적인 행동을 해서 함수 호출이 정상적으로 이루어지지 않았을 가능성이 있습니다.
  • 유니티 IAP는 결재도중에 문제가 생기면 캐시를 저장해놓고 이후 한번 더 호출하며 해당 캐시를 이용하여 결재를 진행하기에 이후에 한번 더 결재를 했을 때 중복된 영수증을 검증했을 가능성도 있습니다.

해당 유저가 해킹 등을 진행하기보다는 단순히 유니티 IAP or 안드로이드에서의 오류일 가능성이 있으며,
bro.IsSuccess()이후에 Param 생성하고 삽입하는 부분에 에러가 발생하여 그 이후 로직이 작동하지 않았을 수 있으니 이 부분에 try catch등을 넣어 에러가 발생할 가능성이 있는지 확인하는 로직도 추가해주는 것을 추천드립니다.

네 알겠습니다! 답변 감사드립니다