프로그래밍/ 안드로이드어플만들기

인앱결제 결제 자동 취소 이슈 해결

kugancity 2023. 12. 22. 20:44
반응형

 

 

 

문제

 

빌링 라이브러리 업데이트 이후 이용자들의 구매가 자동으로 취소가 되고 있는 현상이 발생하였다. 자동으로 취소가 되는 것으로 보니 구매 후 처리가 제대로 되고 있지 않는것 같다. 

 

참고) 구글 플레이 스토어의 정책에 따라, 모든 구매는 구매 후 일정 시간 내에 acknowledge(구독 상품의 경우) 또는 consume(일회성 상품의 경우) 처리가 되어야 합니다. 만약 이 처리가 제대로 이루어지지 않으면, 구글 플레이 스토어는 구매를 자동으로 취소하고 환불할 수 있습니다. 

 

 

 

 

 

 

원인

 

Since v5.0.0 BillingFlowParams.Builder has setProductDetailsParamsList() method which indicates there can be multiple products included within one purchase, so to be consistent with this Purchase has the getProducts() method which returns a list.

 

Google Play Billing Library v5.0.0부터 BillingFlowParams.Builder에 setProductDetailsParamsList() 메소드가 추가되어 한 번의 결제 흐름에서 여러 상품을 포함할 수 있게 되었습니다. 이 변경으로 인해 Purchase 객체의 getProducts() 메소드는 구매된 상품들의 목록을 반환하는 List<String> 형태로 변경되었습니다.

 

 

이러한 업데이트는 단일 구매 내에서 여러 상품을 처리할 수 있도록 하는 등 더 유연한 결제 옵션을 제공하기 위함입니다. 그러나 이 변경은 기존 코드에 영향을 미치며, 특히 getProducts().toString()의 결과가 이전과 다르게 나타나게 만들 수 있습니다.

 

 

 

해결

 

onPurchasesUpdate 함수에서 product id를 문자열 비교해서 acknowledge(구독 상품의 경우) 또는 consume(일회성 상품의 경우) 처리를 하는 부분이 있는데  getProducts() 메소드가 List<String> 타입을 반환하도록 변경되면서 toString() 메소드를 사용하면 리스트의 내용을 문자열로 변환합니다. 이 경우 리스트에 하나의 요소만 있더라도 결과는 "[element]" 형식으로 반환됩니다.

 

이 부분에서 조건문에 들어가지 못해서 결재 이후 처리가 제대로 되지 못해서 3일 후에 자동 취소가 된 것이다. 

 

 

public void onPurchasesUpdated(BillingResult billingResult, @Nullable List<Purchase> purchases) {


    // 결제에 성공한 경우.
    if( billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null )
    {

        Log.d( TAG, "결제에 성공했으며, 아래에 구매한 상품들이 나열될 것 입니다." );

        for( Purchase purchase : purchases )
        {
            Log.d( TAG, "결제에 대해 응답 받은 데이터 :"+ purchase.getOriginalJson() );

            String productid = purchase.getProducts().toString();
            if(productid.equals("consume")) {
                ConsumeParams consumeParams =
                        ConsumeParams.newBuilder()
                                .setPurchaseToken(purchase.getPurchaseToken())
                                .build();
                //
                mBillingClient.consumeAsync(consumeParams, mConsumResListner);
            }
            else if(productid.equals("sub")) {

                if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
                    if (!purchase.isAcknowledged()) {
                        AcknowledgePurchaseParams acknowledgePurchaseParams =
                                AcknowledgePurchaseParams.newBuilder()
                                        .setPurchaseToken(purchase.getPurchaseToken())
                                        .build();
                        mBillingClient.acknowledgePurchase(acknowledgePurchaseParams, mSubscribeListner);
                    }
                } else if (purchase.getPurchaseState() == Purchase.PurchaseState.PENDING){
                    //거래 중지 등등 ... 결제관련 문제가 발생했을때
                    Log.d(TAG, "acknowledgePurchase: PENDING");
                } else {
                    //그외 알 수 없는 에러들...
                    Log.d(TAG, "acknowledgePurchase: UNSPECIFIED_STATE");
                }

            }
        }
    }
    // 사용자가 결제를 취소한 경우.
    else if( billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED )
    {
        Log.d( TAG, "사용자에 의해 결제가 취소 되었습니다." );

    }
    // 그 외에 다른 결제 실패 이유.
    else
    {
        Log.d( TAG, "결제가 취소 되었습니다. 종료코드 : " + billingResult.getResponseCode() );
    }
}

 

 

해결 방법은 간단하다. 그냥 productid.equals("removead")를 productid.contains("removead")로 변경하였더니 정상적으로 처리가 되었다. 

 

 

 

참고 : https://stackoverflow.com/questions/72963984/billingclient-purchase-getproducts-returns-multiple-identifiers

 

 

 

 

 

728x90
반응형