Reference : https://developer.android.com/google/play/billing/billing_library_overview

 

1. app 수준 build.gradle 에 dependencies 추가

 

1
2
3
4
dependencies {
   ...
implementation 'com.android.billingclient:billing:1.2'
}
cs

 

 

 

2. 소스코드

결제기능을 구현하고자 하는 화면에 아래 구문 추가.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
public class BuyPointActivity extends AppCompatActivity implements PurchasesUpdatedListener {
    Context mContext;
 
    // create new Person
    private BillingClient mBillingClient;
 
    SkuDetails skuDetails700, skuDetails2100;
    String skuID700 = "point_700", skuID2100 = "point_2100";  //제품 ID
    ...
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_buy_point);
        mContext = BuyPointActivity.this;
        ...
        mBillingClient = BillingClient.newBuilder(mContext).setListener(this).build();
        mBillingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(@BillingResponse int billingResponseCode) {
                if (billingResponseCode == BillingResponse.OK) {
                    // The billing client is ready. You can query purchases here.
                    List<String> skuList = new ArrayList<> ();
                    skuList.add(skuID700);
                    skuList.add(skuID2100);
                    SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
                    params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
                    mBillingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {
                        @Override
                        public void onSkuDetailsResponse(int responseCode, List<SkuDetails> skuDetailsList) {
                            // Process the result.
                            if (responseCode == BillingClient.BillingResponse.OK && skuDetailsList != null) {
                                for (SkuDetails skuDetails : skuDetailsList) {
                                    String sku = skuDetails.getSku();
                                    String price = skuDetails.getPrice();
 
                                    if(skuID700.equals(sku)) {
                                        skuDetails700 = skuDetails;
                                    } else if(skuID2100.equals(sku)) {
                                        skuDetails2100 = skuDetails;
                                    } 
                                }
                            }
                        }});
                }
            }
 
            @Override
            public void onBillingServiceDisconnected() {
                // Try to restart the connection on the next request to
                // Google Play by calling the startConnection() method.
            }
        });
    }
 
    /**
     * Handle a callback that purchases were updated from the Billing library
     */
    @Override
    public void onPurchasesUpdated(int responseCode, @Nullable List<Purchase> purchases) {
        if (responseCode == BillingClient.BillingResponse.OK
                && purchases != null) {
            for (Purchase purchase : purchases) {
                handlePurchase(purchase);
            }
        } else if (responseCode == BillingClient.BillingResponse.USER_CANCELED) {
            // Handle an error caused by a user cancelling the purchase flow.
        } else {
            // Handle any other error codes.
        }
    }
 
    private void doBillingFlow(SkuDetails skuDetails) {
        BillingFlowParams flowParams;
        int responseCode;
 
        // Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
        flowParams = BillingFlowParams.newBuilder().setSkuDetails(skuDetails).build();
        responseCode = mBillingClient.launchBillingFlow(BuyPointActivity.this, flowParams);
 
        /*if(responseCode == BillingClient.BillingResponse.ITEM_ALREADY_OWNED) {
            Purchase.PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.INAPP);
            onPurchasesUpdated(BillingClient.BillingResponse.OK, purchasesResult.getPurchasesList());
        }*/
    }
 
    private void handlePurchase(Purchase purchase) {
        String purchaseToken;
        purchaseToken = purchase.getPurchaseToken();
        mBillingClient.consumeAsync(purchaseToken, consumeListener);
    }
 
    ConsumeResponseListener consumeListener = new ConsumeResponseListener() {
        @Override
        public void onConsumeResponse(@BillingClient.BillingResponse int responseCode, String outToken) {
            if (responseCode == BillingClient.BillingResponse.OK) {
                // Handle the success of the consume operation.
                // For example, increase the number of coins inside the user's basket.
            }
        }
    };
 
    Button.OnClickListener mClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int id = v.getId();
 
            switch (id) {
                case R.id.btn700:
                    doBillingFlow(skuDetails700);
                    break;
 
                case R.id.btn2100:
                    doBillingFlow(skuDetails2100);
                    break;
                ...
            }
        }
    };
    ...
}
cs

 

 

 

 

doBillingFlow 안에 if(responseCode == BillingClient.BillingResponse.ITEM_ALREADY_OWNED)

코드는 처음에 테스트 구매 하다가 구매성공 후에 consume 처리를 안해서 다시 구매가 안 된 경우에 consume 시키려고 놔둔 코드 입니다. 구매 완료후 consume 를 제대로 하지 못한 경우 등에 이 코드를 쓰면 될 것 같습니다.

TrivialDrive v2 sample app 은 너무 복잡해서 잘 이해가 안 되고, anjlab 의 android-inapp-billing-v3 는 왠지 안내켜서 Google Play 결제 라이브러리 사용하여 구현해보았습니다. 인앱 결제 구현 구글 문서는 최신 내용이 아닌 듯 합니다. 업무에 참고 하시기 바랍니다.

ps.

-. 이 방법을 사용하면 Google 마켓 개발자 콘솔 설정에 있는 '서비스 및 API' 의 Base64 인코딩 RSA 공개 키 인 애플리케이션용 라이선스 키 를 입력하지 않아도 됩니다.

-. Manifest 에 <uses-permission android:name="com.android.vending.BILLING" /> 도 추가하지 않아도 됩니다. 다만 앱 등록시 인앱상품 생성을 위해 이 권한을 요구하긴 합니다.

-. 인앱 결제 테스트 및 디버깅(참고 : https://developer.android.com/google/play/billing/billing_testing?hl=ko)*인앱결제를 디버깅 모드에서도 테스트 하려면 알파 또는 베타 채널에 앱을 게시해야 하고, 게시하면 생기는 테스트 주소 https://play.google.com/apps/testing/com.android.test 와 같은 주소를 인터넷 앱등을 통해 접속한 후

테스트 참여 대상 관리 에 등록된

계정 주소를 입력해야 합니다. 이렇게 하고 나면 개발하는 앱의 디버깅 모드에서도 결제 테스트가 가능합니다. 테스트 참여 대상 관리 에 등록된 사용자만 테스트 주소(https://play.google.com/apps/testing/com.android.test)에 등록되는지는 확인해보지 못했습니다.
1. Google Play Console 접속2. 좌측 하단 '설정' 클릭3. 라이선스 테스트 추가테스트 하고자 하는 계정을 추가합니다. (구글 플레이에 설정된 계정 등)

 

 

 

 

 

 

 

+ Recent posts