① 배운 것
IapUtils().iapStatusChangedCallback = (status) {
switch (status) {
case PurchaseStatus.error:
showSnackBar(strFailPurchase, context);
setState(() => showCircularProgress = false);
break;
case PurchaseStatus.purchased:
setState(() => showCircularProgress = false);
break;
case PurchaseStatus.restored:
setState(() => showCircularProgress = false);
break;
case PurchaseStatus.pending:
setState(() => showCircularProgress = true);
break;
case PurchaseStatus.canceled:
setState(() => showCircularProgress = false);
break;
}
};
//ios의 구매상태
다이어로그가 뜸(pending)
다이어로그 닫음(canceled)
구매 완료됨(purchased)
구매 에러(error)
//구매요청 코드
InAppPurchase.instance.buyConsumable(purchaseParam: purchaseParam);
//안드로이드의 구매상태
다이어로그 뜸(아무상태 x)
다이어로그 닫음(canceld)
일반구매 시작됨(아무상태 x)
일반구매 완료됨(purchased)
일반구매 에러(error)
느린구매 시작됨(pending)
느린구매 완료됨(purchased)
느린구매 에러(error)
구매요청을 빠르게 여러번(사용자가 구매버튼-구매다이어로그에 있는 구매버튼 말고 개발자가 만든 구매버튼-을 여러번 클릭함)클릭하면 기본적으로 구매다이어로그가 보였다가 사라졌다가 다시 구매다이어로그가 보였다 사라졌다 이런식으로 작동한다. 물론! 안드로이드같은경우 구매 다이어로그가 뜨는것은 아직 아무 상태도 아니기때문에 다이어로그가 떳다 없어졌다 하더라도 로직에 버그를 발생할 수 있는건아니다. 하지만 문제는, 너무 버튼을 빠르게 누르게되면 다이어로그가 꺼졋다 다시 나와야하는데 그러지 못하고 다이어로그가 연속으로 중첩되어 보이는 경우가 생기는것이다. 그러면 한 다이어로그에서 구매요청을 완료해서 그 다이어로그가 사라져도 중첩되어있던 다이어로그가 또 보인다.
이런경우를 방지하기 위해, 나는 ios와 동일하게 다이어로그가 뜨면 바로 상태를 pending 상태인것으로 인지하여 IapUtils().iapStatusChangedCallback을 호출했다. purchaseStream에서 리슨받는 상태flag값을 바꾼게 아니라 임의로 내가 만든 상태값을 변경하고 콜백을 호출한 것이기에 원래인앱결제로직에 걸려있는 상태에는 영향을 끼치지 않아서 문제되지 않는다고 판단했다.
그리고 안드로이드, ios 둘다 구매가 완료되어서 purchaseStrem에서 purchsed 상태를 리슨받아도 바로 purchased 콜백을 호출하지않았다. 왜냐하면 이 상태에서 서버검증을 마치고 응답을 받아야 진짜 구매가 완료되기 때문이다. 그래서 purchaseStrem에서 purchased 상태를 리슨 받으면 서버검증 api를 호출하고 서버 검증이 끝나면 내가 만든 flag를 purchased로 바꾸고 purchased 콜백을 호출했다.
이때, api 호출 시 에러가 난다해도 purchaseStrem에서 상태 변화는 없다. 그래서 만약 api 호출 시 에러가 난다면 내가 임의로 만든 상태를 error로 변경하고 error 콜백을 호출해야 정상적으로 구매로직이 종료가 되고 circurlatorProgressBar가 사라지면서 다음 구매요청을 할 수 있다.
아무튼 그렇게해서 안드로이드도 구매요청을하여 다이어로그가 뜨면 바로 pending콜백을 호출하여 circurlarProgress가 뜨고 취소,에러,성공 할때까지 다음 구매요청을 할 수 없게 만들었다.
내가 구현하고 있는 상품은 구독상품이 아니라 일회성 구매 상품인데, 구매요청을 하면 이미 보유하고 있는 아이템 입니다라는 팝업이 뜨면서 구매가 진행이 안되었다.
구글 플레이스토어랑 앱의 캐시와 데이터를 지워봤지만 여전히 똑같은 에러가 발생했다.
이 블로그를 참고하면 구매 후 소비를 임의로 해줘야한다고 한다. 이게 아마 플러터 코드에서는 이 부분인것 같은데 나는 이미 이 코드가 있었다.
if (purchaseDetails.pendingCompletePurchase) {
await InAppPurchase.instance
.completePurchase(purchaseDetails);
}
여기서부터는 추측인데 이 문제가 일어나 이유는 저 비동기 코드가 완료되기 전에 다른 구매를 요청하면 일어나는것 같다.
일단 저 문제는 플레이스토어 콘솔에서 주문관리 - 환불 에 들어가서 해당 구매를 환불하면된다.
그리고 저 문제를 근본적으로 해결하지는 못하고 그냥 하나의 구매를 저 비동기 코드가 끝난 후 서버검증까지 완료된 후 다음 구매요청을 할 수 있게 해결함으로써 저 문제가 애초에 일어날 수 없게 대응했다.
② 회고 (restropective)
③ 개선을 위한 방법