Thêm Thư viện thanh toán Google Play vào ứng dụng của bạn cho sản phẩm Non-consumable product – Android Studio

Non-consumable product (sản phẩm không tiêu thụ) là loại sản phẩm trong ứng dụng (in-app product) mà người dùng mua một lần duy nhấtgiữ quyền sở hữu vĩnh viễn sau khi thanh toán. Sản phẩm này không bị mất đi sau khi sử dụng và có thể được khôi phục trên các thiết bị khác hoặc sau khi cài lại ứng dụng.

Liên kết tham khảo: https://developer.android.com/google/play/billing/integrate

Hôm nay, tôi sẽ giới thiệu cách tích hợp thêm Thư viện thanh toán Google Play vào ứng dụng của bạn cho các sản phẩm Non-consumable product (sản phẩm không tiêu thụ)

Các bạn thực hiện theo 3 bước sau để thêm Thư viện thanh toán Google Play:

Bước 1: Thêm Thư viện thanh toán Google Play vào tệp build.gradle của ứng dụng như minh họa:

dependencies {
def billing_version = "7.1.1"

implementation "com.android.billingclient:billing:$billing_version"
}

Bước 2: Xây dựng bố cục trong tệp “activity_main.xml”:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#00FFE6"
android:id="@+id/layout"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:text="Purchase product"
android:textStyle="bold"
android:textSize="20sp"
android:textColor="@color/black"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:textStyle="bold"
android:textColor="@color/black"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/layout"
android:text="Utilities after purchasing in-app products:"
android:gravity="center"
android:layout_marginTop="10dp"
android:textSize="17sp"
android:id="@+id/tv_1"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tv_2"
android:layout_marginTop="7dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
app:layout_constraintTop_toBottomOf="@id/tv_1"
app:layout_constraintLeft_toLeftOf="@id/tv_1"
app:layout_constraintRight_toRightOf="@id/tv_1"
android:textSize="17sp"
android:textColor="@color/black"
android:text="- Remove Ads"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/tv_2"
android:layout_margin="10dp"
android:text="Purchase"
android:backgroundTint="#FFAB00"
android:id="@+id/btn_purchase"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

Bước 3: Viết chương trình sử dụng ngôn ngữ Java trong tệp “MainActivity.java”:

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.AcknowledgePurchaseResponseListener;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingFlowParams;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.PendingPurchasesParams;
import com.android.billingclient.api.ProductDetails;
import com.android.billingclient.api.ProductDetailsResponseListener;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchasesResponseListener;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.QueryProductDetailsParams;
import com.android.billingclient.api.QueryPurchasesParams;
import com.google.android.material.snackbar.Snackbar;
import com.google.firebase.crashlytics.buildtools.reloc.com.google.common.collect.ImmutableList;

import java.util.List;

public class MainActivity extends AppCompatActivity {
private BillingClient billingClient;
private Button btn_purchase;
private String Product_ID = "example";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btn_purchase = findViewById(R.id.btn_purchase);


billingClient = BillingClient.newBuilder(this)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases(PendingPurchasesParams.newBuilder().enableOneTimeProducts().build())
.build();

btn_purchase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Purchase_product();
}
});
}
@Override
protected void onResume() {
super.onResume();
Fetching_purchases();

}

private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
// To be implemented in a later section.
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
&& purchases != null) {
for (Purchase purchase : purchases) {
handlePurchase(purchase);
}
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "Cancel purchase", Snackbar.LENGTH_LONG);
snackbar.show();
// Handle an error caused by a user cancelling the purchase flow.
} else {
// Handle any other error codes.
}
}
};
private void Fetching_purchases(){
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
billingClient.queryPurchasesAsync(
QueryPurchasesParams.newBuilder()
.setProductType(BillingClient.ProductType.INAPP)
.build(),
new PurchasesResponseListener() {
public void onQueryPurchasesResponse(BillingResult billingResult, List<Purchase> purchases) {
// check billingResult
// process returned purchase list, e.g. display the plans user owns

for (Purchase purchase : purchases) {
for(int i=0;i<purchase.getProducts().size();i++){
if (purchase.getProducts().get(i).contains(Product_ID)){
Check_product_purchase_history(purchase);
}
}
}
}
}
);
}
}
@Override
public void onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
Fetching_purchases();
}
});
}

private void Purchase_product(){
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
Show_product_available_to_buy();
}
}
@Override
public void onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
Purchase_product();
}
});
}
private void Show_product_available_to_buy(){


QueryProductDetailsParams queryProductDetailsParams =
QueryProductDetailsParams.newBuilder()
.setProductList(
ImmutableList.of(
QueryProductDetailsParams.Product.newBuilder()
.setProductId(Product_ID)
.setProductType(BillingClient.ProductType.INAPP)
.build()))
.build();

billingClient.queryProductDetailsAsync(
queryProductDetailsParams,
new ProductDetailsResponseListener() {
public void onProductDetailsResponse(BillingResult billingResult,
List<ProductDetails> productDetailsList) {
// check billingResult
// process returned productDetailsList
if (productDetailsList.size()==0){
Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "No product in the app yet", Snackbar.LENGTH_LONG);
snackbar.show();
}
else {
for(int i = 0; i<productDetailsList.size();i++){
if (productDetailsList.get(i).getProductId().equals(Product_ID)){
Launch_the_purchase_flow(productDetailsList.get(i));
break;
}
}
}

}
}
);
}

private void Launch_the_purchase_flow(ProductDetails productDetails){
// An activity reference from which the billing flow will be launched.
Activity activity = MainActivity.this;

ImmutableList productDetailsParamsList =
ImmutableList.of(
BillingFlowParams.ProductDetailsParams.newBuilder()
// retrieve a value for "productDetails" by calling queryProductDetailsAsync()
.setProductDetails(productDetails)
// to get an offer token, call ProductDetails.getSubscriptionOfferDetails()
// for a list of offers that are available to the user
.build()
);

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
.setProductDetailsParamsList(productDetailsParamsList)
.build();

// Launch the billing flow
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
}

private void handlePurchase(Purchase purchase) {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged()) {
AcknowledgePurchaseParams acknowledgePurchaseParams =
AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
billingClient.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
}
}

}
private AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = new AcknowledgePurchaseResponseListener() {
@Override
public void onAcknowledgePurchaseResponse(@NonNull BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "In-app purchase successful", Snackbar.LENGTH_LONG);
snackbar.show();
}
}
};
private void Check_product_purchase_history(Purchase purchase) {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "In-app purchase successful", Snackbar.LENGTH_LONG);
snackbar.show();
}

}
}

Vậy là bạn đã thêm thành công Thư viện thanh toán Google Play vào ứng dụng của mình!  Đây là kết quả của ứng dụng:





Comments