InApp Purchase RESTORE_TRANSACTIONS, I am not able to figure the code out

后端 未结 3 1488
孤独总比滥情好
孤独总比滥情好 2021-01-17 15:14

I am adding a in app purchase in my coding, it\'s working well while purchase but gives error and application closes when I try to add Restore_Transaction code when applicat

相关标签:
3条回答
  • 2021-01-17 15:46

    I found the answer to my question, thanx to anddev

    You have to check for purchases not to be null

    public static void verifyPurchase(String signedData, String signature) {
        ArrayList<VerifiedPurchase> purchases = BillingSecurity.verifyPurchase(
                signedData, signature);
        if (purchases != null && !purchases.isEmpty()) {
            latestPurchase = purchases.get(0);
            confirmTransaction(new String[] { latestPurchase.notificationId });
            if (mCompletedHandler != null) {
                mCompletedHandler.sendEmptyMessage(0);
            } else {
                Log
                        .e(
                                TAG,
                                "verifyPurchase error. Handler not instantiated. Have you called setCompletedHandler()?");
            }
        }
    }
    

    and in Confirm_Notification u hav to check for

    if (notifyIds[0] != null)
    
    0 讨论(0)
  • 2021-01-17 15:51

    You can use the below code to get purchase history:

    public static ArrayList<VerifiedPurchase> verifyPurchase(String signedData,
                String signature) {
            if (signedData == null) {
                //Log.e(TAG, "data is null");
                return null;
            }
            if (Constans.DEBUG) {
                //Log.i(TAG, "signedData: " + signedData);
            }
            boolean verified = false;
            if (!TextUtils.isEmpty(signature)) {
                /**
                 * Compute your public key (that you got from the Android Market
                 * publisher site).
                 * 
                 * Instead of just storing the entire literal string here embedded
                 * in the program, construct the key at runtime from pieces or use
                 * bit manipulation (for example, XOR with some other string) to
                 * hide the actual key. The key itself is not secret information,
                 * but we don't want to make it easy for an adversary to replace the
                 * public key with one of their own and then fake messages from the
                 * server.
                 * 
                 * Generally, encryption keys / passwords should only be kept in
                 * memory long enough to perform the operation they need to perform.
                 */
                String base64EncodedPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKgldGQPL/xV9WKLmY62UVgEm7gsPI/T/nQxRKpYN17m8Sq3gO9nWD17wXew4oNaHmMAmArS7s7eFi3Z+XiyWil1iZvEOdBOdZD502BzujPoBa4Fu9eITPBO9tzBEdvNLXf8amnsRj53TA4bcxB2O6OcXrQIv3t3n5Dg5Nn+rJpoKSNUv7NEzJagG/2NhyjIysAObbvQ5SBQ5NgRtZlvhsTeQJPMLhRAoRcTK/+47VkhrxM3PppeGjoNRryn6d+RhMjs/nydvoQtP2V76UcUu4m+daDnK3PxOnwLt50hNtQhNf3VgixVrSKfHUWp240uEz9MHstjj8BWPH9BFF/TewIDAQAB";
                PublicKey key = Security.generatePublicKey(base64EncodedPublicKey);
                verified = Security.verify(key, signedData, signature);
                if (!verified) {
                    //Log.w(TAG, "signature does not match data.");
                    return null;
                }
            }
    
            JSONObject jObject;
            JSONArray jTransactionsArray = null;
            int numTransactions = 0;
            long nonce = 0L;
            try {
                jObject = new JSONObject(signedData);
    
                // The nonce might be null if the user backed out of the buy page.
                nonce = jObject.optLong("nonce");
                jTransactionsArray = jObject.optJSONArray("orders");
                if (jTransactionsArray != null) {
                    numTransactions = jTransactionsArray.length();
                }
            } catch (JSONException e) {
                return null;
            }
    
            if (!Security.isNonceKnown(nonce)) {
                //Log.w(TAG, "Nonce not found: " + nonce);
                return null;
            }
    
            ArrayList<VerifiedPurchase> purchases = new ArrayList<VerifiedPurchase>();
            try {
                for (int i = 0; i < numTransactions; i++) {
                    JSONObject jElement = jTransactionsArray.getJSONObject(i);
                    int response = jElement.getInt("purchaseState");
                    PurchaseState purchaseState = PurchaseState.valueOf(response);
                    String productId = jElement.getString("productId");
                    String packageName = jElement.getString("packageName");
                    long purchaseTime = jElement.getLong("purchaseTime");
                    String orderId = jElement.optString("orderId", "");
                    String notifyId = null;
                    if (jElement.has("notificationId")) {
                        notifyId = jElement.getString("notificationId");
                    }
                    String developerPayload = jElement.optString(
                            "developerPayload", null);
    
                    // If the purchase state is PURCHASED, then we require a
                    // verified nonce.
                    if (purchaseState == PurchaseState.PURCHASED && !verified) {
                        continue;
                    }
                    purchases.add(new VerifiedPurchase(purchaseState, notifyId,
                            productId, orderId, purchaseTime, developerPayload));
                }
            } catch (JSONException e) {
                //Log.e(TAG, "JSON exception: ", e);
                return null;
            }
            removeNonce(nonce);
            return purchases;
        }
    

    You can call this method from the below method in BillingService class:

    private void purchaseStateChanged(int startId, String signedData,
                String signature) {
            ArrayList<Security.VerifiedPurchase> purchases;
            purchases = Security.verifyPurchase(signedData, signature);
            if (purchases == null) {
                return;
            }
    
            ArrayList<String> notifyList = new ArrayList<String>();
            for (VerifiedPurchase vp : purchases) {
                if (vp.notificationId != null) {
                    notifyList.add(vp.notificationId);
                }
                ResponseHandler.purchaseResponse(this, vp.purchaseState,
                        vp.productId, vp.orderId, vp.purchaseTime,
                        vp.developerPayload);
            }
            if (!notifyList.isEmpty()) {
                String[] notifyIds = notifyList.toArray(new String[notifyList
                        .size()]);
                confirmNotifications(startId, notifyIds);
            }
        }
    
    0 讨论(0)
  • 2021-01-17 15:57

    Follow this:

        confirmTransaction(new String[] { latestPurchase.notificationId });
    

    here and do this:

    protected static void confirmTransaction(String[] notifyIds) {
            if (amIDead()) {
                return;
            }
            // there isn't a notifyid then this was the restore transaction call and this should be skipped 
            if (notifyIds[0] != null){
            Log.i(TAG, "confirmTransaction()");
            Bundle request = makeRequestBundle("CONFIRM_NOTIFICATIONS");
                 ......
                 ......
    }
    

    Works like a charm form me.. Thanks Guys...

    0 讨论(0)
提交回复
热议问题