본문 바로가기
Programing/android

[android studio] 인앱결제 구현방법

by Benedictus711 2021. 9. 26.
728x90

단일 비소모성 일회성 제품 인앱결제 방법 구현.

 

1. 먼저 build.gradle 파일의 앱 수준에서 Google Play 결제 라이브러리 종속성을 추가합니다.

 

implementation 'com.android.billingclient:billing:3.0.1'

 

2. 매니페스트 파일에서 아래 권한 추가

 

<uses-permission android:name="com.android.vending.BILLING" />

 

3. Google Play 콘솔에서 제품 항목 "구매" 일회성 관리 제품 생성

 

4. 결제 화면

아래는 이리저리 자료를 찾아서 구현한 코드이다.

BillingClient billingClient;

//구매버튼 클릭시
public void purchase_noads() {
    //서비스가 이미 연결되어 있는지 확인
    if (billingClient.isReady()) {
        initiatePurchase();
    }
    //그렇지 않으면 서비스를 다시 연결
    else{
        billingClient = BillingClient.newBuilder(this).enablePendingPurchases().setListener(this).build();
        billingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(BillingResult billingResult) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    initiatePurchase();
                } else {
                    Toast.makeText(getApplicationContext(),"Error "+billingResult.getDebugMessage(),Toast.LENGTH_SHORT).show();
                }
            }
            @Override
            public void onBillingServiceDisconnected() {
            }
        });
    }
}

private void initiatePurchase() {
    List<String> skuList = new ArrayList<>();
    skuList.add(inapp_noads);
    SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
    params.setSkusList(skuList).setType(INAPP);
    billingClient.querySkuDetailsAsync(params.build(),
        new SkuDetailsResponseListener() {
            @Override
            public void onSkuDetailsResponse(BillingResult billingResult,List<SkuDetails> skuDetailsList) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    if (skuDetailsList != null && skuDetailsList.size() > 0) {
                        BillingFlowParams flowParams = BillingFlowParams.newBuilder()
                                .setSkuDetails(skuDetailsList.get(0))
                                .build();
                        billingClient.launchBillingFlow(MainActivity.this, flowParams);
                    } else {
                        // 구글 콘솔에 해당 인앱상품이 등록되지 않음.
                        Toast.makeText(getApplicationContext(),
                                    "Purchase Item not Found",Toast.LENGTH_SHORT).show();
                    }
                } else {
                    Toast.makeText(getApplicationContext()," Error "+billingResult.getDebugMessage(),                                             Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

@Override
public voidonPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> purchases) {
    //구매결과 로직을 구현
    //항목을 새로 구입한 경우
    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null) {
        handlePurchases(purchases);
    }
    //항목이 이미 구매 된 경우 변경 사항을 확인하고 반영하십시오
    else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
        Purchase.PurchasesResult queryAlreadyPurchasesResult = billingClient.queryPurchases(INAPP);
        List<Purchase> alreadyPurchases = queryAlreadyPurchasesResult.getPurchasesList();
        if(alreadyPurchases!=null){
            handlePurchases(alreadyPurchases);
        }
    }
    //구매가 취소된 경우
    else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
        //구매취소 반영
    }
    // Handle any other error msgs
    else {
        Toast.makeText(getApplicationContext(),"Error "+
                            billingResult.getDebugMessage(),Toast.LENGTH_SHORT).show();
    }
}

void handlePurchases(List<Purchase> purchases) {
    for(Purchase purchase:purchases) {
        //아이템을 구매한 경우
        if (inapp_noads.equals(purchase.getSku()) && purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
            if (!verifyValidSignature(purchase.getOriginalJson(), purchase.getSignature())) {
                // 잘못된 구매
                //사용자에게 오류 표시
                Toast.makeText(getApplicationContext(), "Error : Invalid Purchase", Toast.LENGTH_SHORT).show();
                return;
            }
            // else 구매가 유효합니다
            // 품목이 구매되고 승인되지 않은 경우
            if (!purchase.isAcknowledged()) {
                AcknowledgePurchaseParams acknowledgePurchaseParams                                                                                       =AcknowledgePurchaseParams.newBuilder()
                                    .setPurchaseToken(purchase.getPurchaseToken())
                                    .build();
                billingClient.acknowledgePurchase(acknowledgePurchaseParams, ackPurchase);
            }
            //else 항목을 구입하고 인정됨
            else {
                // 아이템 구매 시 사용자에게 권한 부여
                //구매된 상태가 아니라면 구매상태로 업데이트
                this.recreate();
            }
        }
    }
    
    else if( inapp_noads.equals(purchase.getSku()) && purchase.getPurchaseState() == Purchase.PurchaseState.PENDING)
    {
        //구매가 보류 중인 경우
    }
    //구매가 알수없는 상태
    else if(inapp_noads.equals(purchase.getSku()) && purchase.getPurchaseState() == Purchase.PurchaseState.UNSPECIFIED_STATE)
    {
        //구매는 미구매 상태로 저장
    }
}
}

AcknowledgePurchaseResponseListener ackPurchase = new AcknowledgePurchaseResponseListener() {
    @Override
    public void onAcknowledgePurchaseResponse(BillingResult billingResult) {
        if(billingResult.getResponseCode()==BillingClient.BillingResponseCode.OK){
            //구매가 확인된 경우
            // 사용자에게 구매된 상태로 처리. 해당 구매에 따른 상태처리
            MainActivity.this.recreate();
        }
    }
};

@Override
protected void onDestroy() {
    super.onDestroy();
    if(billingClient!=null){
        billingClient.endConnection();
    }
}

 

728x90

댓글