인앱 결제 테스트 : android.test.purchased 이미 소유


122

현재 향후 앱에 대한 인앱 결제를 테스트하고 있으며 테스트 항목 "android.test.purchased"를 처음으로 성공적으로 "구매"한 후 다시 구매하려고 할 때마다 응답 코드 7을받습니다. 이미이 항목을 소유하고 있음을 의미합니다.

12-15 23 : 02 : 14.149 : E / IabHelper (19829) : 인앱 결제 오류 : 항목을 구매할 수 없음, 오류 응답 : 7 : 항목이 이미 소유 됨

내가 이해 한 바에 따르면이 구매는 항상 가능해야합니다. 개발자가 자신의 앱을 테스트 할 수 있도록?

그렇지 않은 경우 상태를 소유하지 않음으로 "재설정"하려면 어떻게해야합니까? Google 인앱 결제 샘플의 util 패키지를 사용하고 있습니다.


1
내 모집은 바이스 구절입니다 .. 이미 소유 한 메시지가 필요하지만 구매를 허용 할 때마다
— Sandeep P

답변:


109

이 코드를 스레드에 추가하여 소비 요청을 시작하십시오.

int response = mService.consumePurchase(3, getPackageName(), purchaseToken);

여기에서 구매 테스트를 위해 purchaseToken은

purchaseToken = "inapp:" + getPackageName() + ":android.test.purchased";

과

if (response == 0)

그러면 소비가 성공합니다.

또한 mService를 공개하는 것을 잊지 마십시오.

IabHelper.Java

다음과 같이 액세스 할 수 있습니다.

int response = mHelper.mService.consumePurchase(3, getPackageName(), purchaseToken);

2
이것이 작동하는 전설, @psykhi가 실제로 당신에게 포인트를 주었어야했습니다. 나는 그것을 소비하려고했지만 구매 토큰을 알아낼 수 없었다. 감사합니다
— Blundell

1
감사합니다! @prasharonnet
— Y2i

1
이것은 엄청난 시간 절약입니다. 완전한. 감사.
— PrivusGuru 2011

13
mService 란 무엇입니까? mHelper? 하지만 ConsumerPurchase ()를 찾을 수 없습니다
— Bagusflyer 2014-08-18

1
mService는 인앱 구매를 위해 시작된 구매 서비스와 결합 된 IInAppBillingService.aidl 인터페이스의 객체입니다.
— Aashutosh Sharma

92

특별한 소비 코드를 작성할 필요가 없습니다. Google Play Store 데이터를 지우려면 adb 명령을 사용하십시오.

adb shell pm clear com.android.vending

1
고마워요 내가 앱을 지워야하는 트릭을 했으므로 전체 답변을 사용할 수 있습니다. 이것은 나에게 올바른 접근 방식입니다.
— sivi

이것은 많은 사람들에게 올바른 접근 방식입니다. 앱에 코드를 추가하고 재배포하는 데 더 많은 시간이 소요됩니다 (의도 한 말장난).
— Michael Labbé 2015 년

9
이는 테스트 기기에 적합한 솔루션이지만주의하세요. Google Play 스토어 앱의 모든 설정을 재설정합니다. 그래서 나는 내 개인 장치에서 그것을하지 않을 것입니다.
— racs

7
아니! 이것은 나쁜 생각입니다. 다른 제품과 다른 앱의 인앱 구매를 잃었습니다. 좋은 것은 인앱 구매를 테스트하려면 제품을 소비해야한다는 것입니다. 시나리오는 구매 용과 구매 용으로 두 가지를 생성하는 것입니다. 안건.
— Rahul Mandaliya

2
@RahulMandaliya 앱은 이미 구매 한 항목을 파악하기 위해 getPurchases () API를 사용하여 캐시 지우기에 대해 탄력적이어야합니다.
— mttmllns

66

android.test.purchased 항목은 일반 ID처럼 작동합니다. 다시 구매하려면 코드의 어딘가에서 소비해야합니다. Google 문서는이 문제에 대해 오해의 소지가 있으며 테스트 목적으로 끝없이 구입할 수있는 또 다른 정적 ID를 추가해야한다고 생각합니다.


인벤토리 호출을 사용하여 Purchase 객체를 가져온 다음 소비합니다. 일단 머리를 돌리면 꽤 쉽습니다.
— slott

3
@mttmlins의 아래 답변을 보거나 vvse.com/blog/blog/2016/08/26/을 읽으십시오 …
— IgorGanapolsky

완전히 사실이 아닙니다. 사용하지 않은 테스트 아이템이 있지만 billingClient.queryPurchases()그 미사용 아이템을 반환하지 않는 경우가 있습니다 . 그래서 지금은 얻을 수 없어서 아이템을 소비 할 수 없습니다.purchaseToken 그것을
— Jemshit Iskenderov

28

인앱 버전 3 :

IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {

    public void onQueryInventoryFinished(IabResult result, Inventory inventory) {

        .....................

        if (inventory.hasPurchase(SKU_CONTENT)) {

            mHelper.consumeAsync(inventory.getPurchase(SKU_CONTENT), null);
        }
    }
};

사진은 천 단어의 가치가 있으므로, 완전한 작동하는 베어 본 코드 조각은 천 'Add this code to a thread. . . '.
— Androidcoder dec.

11

버전 3-가장 빠른 해결 방법 : Google Play 스토어의 캐시를 지우면 "android.test.purchased"를 다시 사용할 수 있습니다.


시스템에 설치된 다른 앱에도 영향을주지 않습니까?
— IgorGanapolsky

1
@IgorGanapolsky, 아니. 시뮬레이션 된 구매 만 영향을받습니다. "실제"구매는 Google 서버에 저장되며 수정되지 않습니다.
— Denis

1
Google Play에서 앱 데이터를 지 웠지만 작동하지 않습니다. 테스트 구매 세부 정보가 여전히 존재합니다.
— Srikar Reddy

2
"설정 / 응용 프로그램 관리자 /"를 통해 @Richard를 사용하거나 메뉴에서 Google Play 스토어 아이콘을 화면 상단의 "정보"버튼으로 드래그합니다. 마지막으로 "캐시 지우기"버튼을 클릭하십시오.
— Denis

1
저에게 가장 좋은 대답입니다. 모든 다른 사람은 좋다, 그러나 이것은 확실히 해결하는 가장 빠른 방법입니다
— 이그나시오 로다

10

나는 adb 쉘을 사용했습니다.

adb shell pm clear com.android.vending

9

이것이 우리가 아이템을 소비하는 방법입니다

 consume.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    String purchaseToken = "inapp:" + getPackageName() + ":android.test.purchased";
                    try {
                        Log.d("","Running");
                        int response = mService.consumePurchase(3, getPackageName(), purchaseToken);
                        if(response==0)
                        {
                            Log.d("Consumed","Consumed");
                        }else {
                            Log.d("","No"+response);
                        }
                    }catch (RemoteException e)
                    {
                        Log.d("Errorr",""+e);
                    }

                }
            });
            t.start();
        }
    });

나를 위해 일했습니다- android.test.purchase문제를 일으키는 어떤 시점에서 사용했습니다 . 인앱 결제의 인벤토리 작업은 오류를 던지고 완료되지 않았습니다. 이것을 일회성으로 실행하면 실제 SKU를 다시 사용하고 이전처럼 계속할 수 있습니다. 감사합니다
— Jon

1
훌륭한 대답입니다. 정적 응답과 함께 작동 = 인앱 결제가 활성화 된 APK가 Google Play에 업로드되기 전.
— infero

감사! 나를 위해 일했습니다.
— AndroidMechanic-Viral Patel 2015 년

6

내 생각에 프로그램이 항목을 소비하도록 설계되지 않은 경우 외부 공급 업체의 메모리를 지우기 위해 코드를 조정할 필요가 없습니다. 이렇게하면 코드가 더 취약 해지고 소프트웨어에 속하지 않는 코드를 추가하고 제거하는 데 많은 시간을 소비해야하므로 이와 같은 솔루션을 구현하는 것은 나쁜 설계입니다.

android.test.purchased를 지우는 데 도움이 된 최고의 솔루션은

adb uninstall com.yourapp.name

그리고

adb shell pm clear com.android.vending

현금을 지우고 앱 설정을 탐색하거나 코드를 변경할 필요가 없었습니다. Windows 시스템의 경로 변수에 adb를 추가해야했습니다. 그래서 예, 어쨌든 필요할 것 같은 adb를 사용해야합니다.

C : \ ... \ android-sdk \ platform-tools를 추가하기 만하면됩니다. 환경 변수의 Windows 경로에서 Mac과 Linux OS에서도 매우 간단하다고 생각합니다. 누군가가 앱 결제에서 Android를 구현하는 데 며칠을 덜 소비하는 데 도움이되기를 바랍니다.


uninstallandroid.test.purchased sku 를 지우는 데는 필요하지 않습니다 .
— IgorGanapolsky

4

가장 큰 문제는 android.test.purchased아이템 을 소비해야한다는 것 입니다. 그러나이 항목은 쿼리 인벤토리에서 사용할 수 없으므로 정상적인 흐름을 사용하여 소비 할 수 없습니다.

따라서 IabHelper클래스 에서 IabHelper를 사용하는 경우 IabHelper에서 IInAppBillingService액세스 할 수 있도록 mService를 일시적 으로 public 으로 변경할 수 있습니다 .

그런 다음 수업에서 이렇게 소비 할 수 있습니다.

int response = mHelper.mService.consumePurchase(3, getPackageName(), "inapp:"+getPackageName()+":android.test.purchased");

성공하면 응답은 0이됩니다.

도움이 되었기를 바랍니다.


Tangent : 관리되는 항목에 대해 환불을 처리 할 수 ​​있나요 (테스트 계정 사용-대시 보드에 표시되지 않음)?
— 에드 리

당신은 호출 할 수 있습니다 consumeAsync()에 android.test.purchased . 그것에는 문제가 없습니다.
— IgorGanapolsky

간단한 테스트의 경우 IabHelper를 사용하는 경우 가능한 가장 좋은 방법입니다. 나를 도와 주었다.
— Rúben 2017 년

2

테스트 목적으로 gp 구매 흐름을 초기화하는 메서드를 호출하기 전에 구입 한 모든 제품을 지우는 코드를 삽입하는 것이 좋습니다. 한 번에 하나의 항목 만 테스트 할 때 특히 편안합니다. 예 :

PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.INAPP);
    for (Purchase sourcePurchase : purchasesResult.getPurchasesList()) {
        if(sourcePurchase != null){

            ConsumeResponseListener listener = new ConsumeResponseListener() {
                @Override
                public void onConsumeResponse(String outToken, @BillingResponse int responseCode) {

                    System.out.println("all consumed");
                }
            };
            mBillingClient.consumeAsync(sourcePurchase.getPurchaseToken(), listener);
        }else{
            System.out.println("null");
        }
    }

// and then initiate whole process with clear "shoping basket"

BillingFlowParams.Builder builder = new BillingFlowParams.Builder()
        .setSku(itemName).setType(BillingClient.SkuType.INAPP);

2

Google Play 콘솔로 이동하여 주문 관리 탭을 엽니 다. 여기에서 테스트 구매를 환불 / 취소 할 수 있습니다.


1

테스트 환경에있는 경우

1) android.test.purchased의 경우, 안드로이드 기기 (인벤토리 소모)를 다시 시작하여 위조 결제를 초기화 할 수 있습니다.

2) InApp util에는 Security.java라는 파일이 있습니다. 임시로 다음과 같이 만듭니다. 테스트 결제 (가짜)는 보안 예외로 인해 항상 거짓을 반환하기 때문에.

public static boolean verifyPurchase(String base64PublicKey,
                                     String signedData, String signature) {
    return true; }

그런 다음 OnIabPurchaseFinishedListener에서 fechInvForconsumeItem ()을 호출하십시오.

IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
            = new IabHelper.OnIabPurchaseFinishedListener() {
        public void onIabPurchaseFinished(IabResult result,
                                          Purchase purchase)
        {
            if (result.isFailure()) {
                // Handle error
                Log.e("123","Failure");

                return;
            }
            else if (purchase.getSku().equals(ITEM_SKU)) {
                Log.e("123","PURCAsed");
                fechInvForconsumeItem(); // Restart device if not consume

            }

        }
    };

fechInvForconsumeItem ()은

    public void fechInvForconsumeItem() {
    mHelper.queryInventoryAsync(mReceivedInventoryListener);
}
IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener
        = new IabHelper.QueryInventoryFinishedListener() {
    public void onQueryInventoryFinished(IabResult result,
                                         Inventory inventory) {


        if (result.isFailure()) {
            // Handle failure
            Log.e("11","Failure");



        } else {
            Log.e("11","suc");
            mHelper.consumeAsync(inventory.getPurchase(ITEM_SKU),
                    mConsumeFinishedListener);
        }


    }
};

소비 리스너 (현재)

    IabHelper.OnConsumeFinishedListener mConsumeFinishedListener =
        new IabHelper.OnConsumeFinishedListener() {
            public void onConsumeFinished(Purchase purchase,
                                          IabResult result) {

                if (result.isSuccess()) {
                } else {
                    // handle error
                    Log.e("11","sucConsume");
                }
            }
        };

0
IabHelper.QueryInventoryFinishedListener 
       mQueryFinishedListener = new IabHelper.QueryInventoryFinishedListener() {
       public void onQueryInventoryFinished(IabResult result, Inventory inventory)   
       {
          if (result.isFailure()) {
             return;
           }          
          try {

                if(inventory.hasPurchase("product_sku_id"))
                {   
                     isItemEnable= true;
                     mHelper.consumeAsync(inventory.getPurchase("product_sku_id"),null);            
                }
                else
                {
                       isItemEnable = false;
                }           

            } catch (Exception e) {
                e.printStackTrace();
            }
       }

    };

-1

제 경우에는 Google이 해당 항목에 대한 구매를 기록하지 않는 것 같습니다. 대신 Google Play 서비스의 로컬 사본이 구매를 캐시합니다. 이렇게하면 동일한 장치에서 두 번째 요청이있을 때 android.test.purchased already owned나타납니다. 그러나 다른 장치를 사용하거나 장치를 재설정하면 캐시가 지워지고 구매를 반복 할 수 있습니다.


-1

제 경우에는 앱 캐시를 지우면됩니다. 캐시를 지운 후 다시 구매 흐름을 시작할 수있었습니다.

내 장치 (4.4.2)에서 "설정-> 응용 프로그램 관리자"로 이동했습니다. 다음으로 "다운로드 됨"탭에서 앱을 선택한 다음 "캐시 지우기"를 선택했습니다.


-2

이것은 소모품과 비 소모품의 차이입니다. 비 소모성 품목 (여기서 다루는 것처럼 보이는 것)은 지속적으로 상태를 추적하는 반면, 소모품은 여러 번 구매할 수 있습니다. 다시 테스트하려면 Play 관리 콘솔로 이동하여 판매를 취소 / 환불해야합니다.


1
그러나 문제는 이러한 "가짜"품목에 대한 "권한"이 없으며 실제 구매가 아니기 때문에 판매 상태를 어디에서 변경할 수 있는지 알 수 없습니다. 구글 문서는 (가) android.test.purchased에 대해 말한다 : 이 제품 ID로 인앱 결제 요청을 할 때, 구글 플레이 응답 비록 당신이 성공적으로 항목을 구입. 그래서 나는 꽤 혼란 스러워요 : /
— psykhi

아직 정적 응답 테스트를하고 있습니까? 그렇다면 어떤 정적 응답이 전송되는지 변경하기 만하면됩니다. 취소 가능한 주문으로 실제 구매를 수행하는 "자신의 제품 ID를 사용하여 인앱 구매 테스트"를 수행하는 것처럼 들립니다.
— addaon dec

나는 여전히 정적 ID로 붙어 있습니다. 내가 원하는 것은 android.test.purchased ID로 인앱 구매를 테스트 할 수있는 것입니다. Google 문서에서 이해 한 내용에서 항상 작동해야 할 때 처음으로 작동했습니다. 명확하지 않으면 죄송합니다!
— psykhi

내 오해, 죄송합니다. 그 경우 ... 모르겠어요. 매번 성공을 거두어야하는데, 당신이보고있는 사건을 본 적이 없습니다. 죄송합니다.
— addaon dec

숙면을 취한 후 문제를 다시 살펴볼 것입니다 :) 도와 주셔서 감사합니다!
— psykhi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.