【问题标题】:How to know if inapp subscriptionperiod finish or user has cancel it?如何知道应用内订阅期是否结束或用户已取消?
【发布时间】:2019-10-27 09:04:52
【问题描述】:

就这么简单,我做了一个订阅的程序,当用户订阅时,一个布尔值变为true。 当我测试我的软件时,如果我取消订阅或它自动完成,布尔值仍然返回 true。

我需要在我的代码中检查订阅是否仍然可用

由于我是 android studio 的新手,到目前为止,我已经为这个问题寻找了 2 周,但没有找到解决方案。 所有的解决方案和帖子都在用这条神奇的线讨论旧的应用内库(AIDL)

BundleownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);

但这似乎不适用于新的 Google Play 结算库。

这是我的结算活动:

;

公共类 BillingActivity 扩展 AppCompatActivity 实现 PurchasesUpdatedListener {

private static final String TAG = "BillingActivity";

private Button button;
protected SharedPreferences mSharedPreferences;
private boolean checkActivation;
private BillingClient mBillingClient;
private List<String> skuList;
private SkuDetailsParams.Builder skuParams;
private BillingFlowParams flowParams;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_billing);


    // Shred Preferences & Active user Initialize
    checkActivation = false;
    mSharedPreferences = this.getSharedPreferences("com.aterosolutions.customerspremiums", Context.MODE_PRIVATE);
    if (mSharedPreferences.getInt("activeUser", 0) == 1) { // 0 ==> InActiveUser   1 ==> ActiveUser
        //mSharedPreferences.edit().putInt("activeUser", 1).apply();
        checkActivation = true;
    } else {
        //mSharedPreferences.edit().putInt("activeUser", 0).apply();
        checkActivation = false;
    }
    Toast.makeText(this, checkActivation + "", Toast.LENGTH_SHORT).show();


    // SKU List
    skuList = new ArrayList<>();
    skuList.add("premiums_subscribe");
    skuParams = SkuDetailsParams.newBuilder();
    skuParams.setSkusList(skuList).setType(BillingClient.SkuType.SUBS);

    // Establish connection to billing client
    mBillingClient = BillingClient.newBuilder(this).enablePendingPurchases().setListener(this).build();
    mBillingClient.startConnection(new BillingClientStateListener() {
        @Override
        public void onBillingSetupFinished(BillingResult billingResult) {
            Log.i(TAG, "onBillingSetupFinished: start" + billingResult.getResponseCode());
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                Log.i(TAG, "onBillingSetupFinished: second congrat");
            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
                Log.i(TAG, "onBillingSetupFinished: you own it");
            } else {
                Log.i(TAG, "onBillingSetupFinished: not your product");
            }
        }

        @Override
        public void onBillingServiceDisconnected() {
            Toast.makeText(BillingActivity.this, "Connection Error", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "onBillingServiceDisconnected: Connection Error");

        }
    });


    queryPurchases();
    //checkPurchsedItem();

    // Button Handle
    button = findViewById(R.id.button);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mBillingClient.querySkuDetailsAsync(skuParams.build(), new SkuDetailsResponseListener() {
                @Override
                public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) {
                    flowParams = BillingFlowParams.newBuilder().setSkuDetails(skuDetailsList.get(0)).build();
                    BillingResult response = mBillingClient.launchBillingFlow(BillingActivity.this, flowParams);
                    Log.i(TAG, "onSkuDetailsResponse: " + billingResult.getResponseCode());
                    Log.i(TAG, "onSkuDetailsResponse: response OK");
                    Log.i(TAG, "onSkuDetailsResponse: my test" + response);
                    Log.i(TAG, "onSkuDetailsResponse: queryPurshase01 " + mBillingClient.queryPurchases(BillingClient.SkuType.SUBS));

                    /* (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) {
                        flowParams = BillingFlowParams.newBuilder().setSkuDetails(skuDetailsList.get(0)).build();
                        mBillingClient.launchBillingFlow(BillingActivity.this, flowParams);
                        Log.i(TAG, "onSkuDetailsResponse: response OK");

                    }else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED && skuDetailsList != null){
                        Log.i(TAG, "onSkuDetailsResponse: response already Owned");
                    }else {
                        Log.i(TAG, "onSkuDetailsResponse: response something else");
                    }*/
                }
            });
        }
    });

}


@Override
public void onPurchasesUpdated(BillingResult billingResult, @Nullable List<Purchase> purchases) {
    Log.i(TAG, "onPurchasesUpdated: start /// purchses"+ billingResult.getResponseCode() );

    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK /*&& purchases != null*/) {
        mSharedPreferences.edit().putInt("activeUser", 1).apply();
        MainScreenActivity.activeUser = true;
        for (Purchase purchase : purchases) {
            handleNewPurchase(purchase);
        }
    } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED /*&& purchases != null*/) {
        Log.i(TAG, "onPurchasesUpdated: You Already Own It");
        Toast.makeText(this, "Already Owned", Toast.LENGTH_SHORT).show();
        mSharedPreferences.edit().putInt("activeUser", 1).apply();
        MainScreenActivity.activeUser = true;

    } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED /*&& purchases != null*/) {
        Log.i(TAG, "onPurchasesUpdated: User Canceled");
        Toast.makeText(this, "User Canceled", Toast.LENGTH_SHORT).show();

    } else {
        Log.i(TAG, "onPurchasesUpdated: other error " + billingResult.getResponseCode());

    }


}

private void handleNewPurchase(Purchase purchase) {

    Log.i(TAG, "handleNewPurchase: queryPurshase00 " + mBillingClient.queryPurchases(BillingClient.SkuType.SUBS).getBillingResult());

    for (int i = 0; i < skuList.size(); i++) {
        if (purchase.getSku() == skuList.get(i)) {
            mSharedPreferences.edit().putInt("activeUser", 1).apply();
            MainScreenActivity.activeUser = true;
            Toast.makeText(this, "congrat dear", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "handleNewPurchase: product purchsed ");

            // Acknowledge the purchase if it hasn't already been acknowledged.
            if (!purchase.isAcknowledged()) {
                Log.i(TAG, "handlePurchase: ok02");
                AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
                        .setPurchaseToken(purchase.getPurchaseToken())
                        .build();

                AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = new AcknowledgePurchaseResponseListener() {
                    @Override
                    public void onAcknowledgePurchaseResponse(BillingResult billingResult) {


                    }

                };
                Log.i(TAG, "handleNewPurchase: aknowledge done");
                mBillingClient.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
            } else {
                Log.i(TAG, "handleNewPurchase: no need to aknowledge");
            }
        }
    }
}

private void queryPurchases() {
    Purchase.PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.SUBS);
    if (purchasesResult != null) {
        List<Purchase> purchaseList = purchasesResult.getPurchasesList();
        if (purchaseList == null) {
            return;
        }

        if (!purchaseList.isEmpty()){
            for (Purchase purchase : purchaseList){
                if (purchase.getSku().equals(skuList.get(0))){
                    //mSharedPreferences.edit().putInt("activeUser", 1).apply();
                    //MainScreenActivity.activeUser = true;
                }
            }
        }

    }

}

@Override
protected void onDestroy() {
    super.onDestroy();
    mBillingClient.endConnection();

}

private void checkPurchsedItem(){
    mBillingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.SUBS, new PurchaseHistoryResponseListener() {
        @Override
        public void onPurchaseHistoryResponse(BillingResult billingResult, List<PurchaseHistoryRecord> purchaseHistoryRecordList) {
            Log.i(TAG, "onPurchaseHistoryResponse: " + billingResult.getResponseCode());
        }
    });

    Purchase.PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.SUBS);
    Log.i(TAG, "checkPurchsedItem: " + purchasesResult.getBillingResult());
    try {
        Log.i(TAG, "checkPurchsedItem: " + purchasesResult.getPurchasesList().size());
    }catch (Exception e){
        e.printStackTrace();
    }
    Log.i(TAG, "checkPurchsedItem: " + purchasesResult.getResponseCode());
    Log.i(TAG, "checkPurchsedItem: " + purchasesResult.getBillingResult());
}
}

【问题讨论】:

    标签: java android


    【解决方案1】:

    在经历了很多头痛之后(就像总是使用 Google API 和服务一样),我想出了如何使用现有 API 访问 Google Play Developer API 信息(例如计费)。

    1.) 在开发者 API 控制台中创建服务帐户 (JSON) 密钥:

    2.) 下载此 service-account-private-key.json 文件(不要将其与 OAuth2.0 客户端机密文件混淆!)。

    3.) 在 Google Play 开发者控制台中,转到设置 -> 用户和权限 -> 邀请新用户,然后将下载文件中的 client_email 设置为新用户的用户电子邮件。通过此视图中的复选框(例如“查看财务数据”)分配您要授予此用户的访问权限。

    4.) 为您的项目添加适当的依赖项(版本 ...-1.23.0 对我不起作用):

    <dependency>
        <groupId>com.google.apis</groupId>
        <artifactId>google-api-services-androidpublisher</artifactId>
        <version>v2-rev50-1.22.0</version>
    </dependency>
    

    5.) 将 service-account-private-key.json 文件加载到您的应用程序中。就我而言,它是一个网络服务器:

    @Singleton
    @Startup
    public class WebserverConfiguration
    {
        private String serviceAccountPrivateKeyFilePath;
    
        /** Global instance of the HTTP transport. */
        public static HttpTransport HTTP_TRANSPORT;
    
        /** Global instance of the JSON factory. */
        public static JsonFactory JSON_FACTORY;
    
        private GoogleCredential credential;
    
        @PostConstruct
        public void init()
        {
            assignServiceAccountFileProperty();
            initGoogleCredentials();
        }
    
        public String getServiceAccountPrivateKeyFilePath()
        {
            return serviceAccountPrivateKeyFilePath;
        }
    
        public GoogleCredential getCredential()
        {
            return credential;
        }
    
        private void initGoogleCredentials()
        {
            try
            {
                newTrustedTransport();
                newJsonFactory();
    
                String serviceAccountContent = new String(Files.readAllBytes(Paths.get(getServiceAccountPrivateKeyFilePath())));
                InputStream inputStream = new ByteArrayInputStream(serviceAccountContent.getBytes());
    
                credential = GoogleCredential.fromStream(inputStream).createScoped(Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER));
    
            }
            catch (IOException | GeneralSecurityException e)
            {
                throw new InitializationException(e);
            }
        }
    
        private void newJsonFactory()
        {
            JSON_FACTORY = JacksonFactory.getDefaultInstance();
        }
    
        private void assignServiceAccountFileProperty()
        {
            serviceAccountPrivateKeyFilePath = System.getProperty("service.account.file.path");
            if (serviceAccountPrivateKeyFilePath == null)
            {
                throw new IllegalArgumentException("service.account.file.path UNKNOWN - configure it as VM startup parameter in Wildfly");
            }
        }
    
        private static void newTrustedTransport() throws GeneralSecurityException, IOException
        {
            if (HTTP_TRANSPORT == null)
            {
                HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
            }
        }
    }
    6.) Now I am able the fetch Google Play Developer API information, e.g. reviews:
    
    private void invokeGoogleApi() throws IOException
    {       
        AndroidPublisher publisher = new AndroidPublisher.Builder(WebserverConfiguration.HTTP_TRANSPORT, WebserverConfiguration.JSON_FACTORY, configuration.getCredential()).setApplicationName("The name of my app on Google Play").build();
        AndroidPublisher.Reviews reviews = publisher.reviews();
        ReviewsListResponse reviewsListResponse = reviews.list("the.packagename.of.my.app").execute();
        logger.info("review list response = " + reviewsListResponse.toPrettyString());
    }
    This worked.
    
    I cannot test it yet, but I'm sure that fetching the billing information works as well:
    
    private SubscriptionPurchase getPurchase() throws IOException
    {
        AndroidPublisher publisher = new AndroidPublisher.Builder(WebserverConfiguration.HTTP_TRANSPORT, WebserverConfiguration.JSON_FACTORY, configuration.getCredential()).setApplicationName("The name of my app on Google Play").build();
        AndroidPublisher.Purchases purchases = publisher.purchases();
    
        SubscriptionPurchase purchase = purchases.subscriptions().get("the.packagename.of.my.app", "subscriptionId", "billing token sent by the app").execute();
    
        //do something or return
        return purchase;
    }
    

    【讨论】:

    • 我设法完成了第 4 步.. 第五步我应该创建一个新类.. 并从我的计费类中调用该方法吗?
    猜你喜欢
    • 2019-10-10
    • 2014-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-06
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    相关资源
    最近更新 更多