Validate and log purchase

Learn how to validate and log purchases.

The validateAndLogInAppPurchase method is part of the receipt validation flow, which enables your app to validate in-app purchase events generated by Google Play.

📘Note

The function validateAndLogInAppPurchase can be replaced by the fully automatic purchase SDK connector (a premium service). To learn how to integrate the connector, see in Github Android purchase SDK connector.

The method is currently implemented in two versions.

Implement validateAndLogInAppPurchase (BETA)

The validateAndLogInAppPurchase (currently in BETA) sends the purchase details to AppsFlyer for validation. After AppsFlyer validates the purchase with Google Play the method returns the response to a callback function.

To implement the method perform the following steps:

  1. Query the Play Store for the Purchase object of the in-app purchase event.
  2. Initialize an AFPurchaseDetails instance and set it with the purchase type, token, product ID, price, and currency details retrieved from the Purchase object.
  3. If you want to add additional details to the purchase in-app event, populate a hash map with key-value pairs.
  4. Invoke validateAndLogInAppPurchase with the following:
    • The AFPurchaseDetails object you created in step 2.
    • The hash map with the additional details you created in step 3.
    • An instance of the AppsFlyerInAppPurchaseValidationCallback to handle validation success and failure.
  5. Add your logic for handling the failure, success, or error responses returned to the callback function. See here a few response examples.

If the validation is successful, an af_purchase event is logged with the values provided to validateAndLogInAppPurchase.

📘Note

validateAndLogInAppPurchase generates an af_purchase in-app event upon successful validation. Sending this event yourself will cause duplicate event reporting.

코드 예시

AFPurchaseDetails purchaseDetails = new AFPurchaseDetails(
    AFPurchaseType.SUBSCRIPTION, //Purchase type
    "PurchaseToken", // Purchase token
    "myProductId", // Product ID
    "202.34", // Price
    "USD"); // Currency

Map<String, String> purchaseAdditionalDetails = new HashMap<>();

// Adding some key-value pairs to the map
purchaseAdditionalDetails.put("firstDetail", "something");
purchaseAdditionalDetails.put("secondDetail", "nice");
AppsFlyerLib.getInstance().validateAndLogInAppPurchase(
    purchaseDetails,
    purchaseAdditionalDetails, //optional
    new AppsFlyerInAppPurchaseValidationCallback() {
        @Override
        public void onInAppPurchaseValidationFinished(@NonNull Map<String, ?> validationFinishedResult) {
            Log.d(LOG_TAG, "Purchase validation response arrived");
            Boolean validationResult = (Boolean) validationFinishedResult.get("result");

            if (validationResult == true) {
                Log.d(LOG_TAG, "Purchase validated successfully");
                // Add here code following successful purchase validation
            } else {
                @NonNull Map<String, ?> error_data = (Map<String, ?>) validationFinishedResult.get("error_data");
                Log.d(LOG_TAG, "Purchase was not validated due to " + error_data.get("message"));
                // Add here code when validation was not successful
            }
        }

        @Override
        public void onInAppPurchaseValidationError(@NonNull Map<String, ?> validationErrorResult) {
            Log.d(LOG_TAG, "Purchase validation returned error: " + validationErrorResult.get("error_message"));
        }
    }
);

Response Examples

The callback function AppsFlyerInAppPurchaseValidationCallback receives validation responses from AppsFlyer in JSON format. Here are two examples:

One time purchase validated successfully

{
  "result": true,
	"purchase_type": "one_time_purchase",
  "product_purchase": {
    "purchasetimemillis": "1699667717458",
    "purchasestate": "0",
    "consumptionstate": "1",
    "quantity": "0",
    "regioncode": "US",
    "acknowledgementstate": "1",
    "productid": "",
    "orderid": "GPA.3345-6347-1243-65405",
    "purchasetoken": "",
    "kind": "androidpublisher#productPurchase",
    "developerpayload": "",
    "obfuscatedexternalprofileid": "",
    "purchasetype": "null",
    "obfuscatedexternalaccountid": ""
  }
}

Subscription validated successfully

{
  "result": true,
	"purchase_type": "subscription",
  "subscription_purchase": {
    "externalaccountidentifiers": {
      "obfuscatedexternalaccountid": "LD32LMR23K4E2"
    },
    "lineitems": [
      {
        "offerdetails": {
          "baseplanid": "p1w",
          "offerid": "freetrial"
        },
        "autorenewingplan": {
          "autorenewenabled": true
        },
        "productid": "s2_sub_00_00_00",
        "expirytime": "2023-10-21T09:15:16.427Z"
      }
    ],
    "regioncode": "AU",
    "acknowledgementstate": "ACKNOWLEDGEMENT_STATE_PENDING",
    "subscriptionstate": "SUBSCRIPTION_STATE_ACTIVE",
    "kind": "androidpublisher#subscriptionPurchaseV2",
    "latestorderid": "GPA.3335-6293-5584-30859",
    "starttime": "2023-10-18T09:15:45.814Z"
  }
}

validateAndLogInAppPurchase (Legacy)

validateAndLogInAppPurchase is exposed via AppsFlyerLib.

validateAndLognInAppPurchase 인수 4개를 갖습니다.

validateAndLogInAppPurchase(Context context,
                            java.lang.String publicKey,
                            java.lang.String signature,
                            java.lang.String purchaseData,
                            java.lang.String price, java.lang.String currency,
                            java.util.Map<java.lang.String,java.lang.String> additionalParameters)
  • context: 애플리케이션/액티비티 컨텍스트
  • publicKey: Google Play Console에서 얻은 라이선스 키
  • signature: data.INAPP_DATA_SIGNATURE from onActivityResult
  • purchaseData: data.INAPP_PURCHASE_DATA from onActivityResult
  • price: 구매 가격이며, 다음에서 파생되어야 합니다. skuDetails.getStringArrayList("DETAILS_LIST")
  • currency: 구매 통화이며, 다음에서 파생되어야 합니다. skuDetails.getStringArrayList("DETAILS_LIST")
  • additionalParameters - 기록할 추가 이벤트 파라미터

If the validation is successful, an af_purchase event is logged with the values provided to validateAndLogInAppPurchase.

📘

참고

validateAndLogInAppPurchase generates an af_purchase in-app event upon successful validation. Sending this event yourself will cause duplicate event reporting.

Example: Validate an in-app purchase

// Purchase object is returned by Google API in onPurchasesUpdated() callback
private void handlePurchase(Purchase purchase) {
    Log.d(LOG_TAG, "Purchase successful!");
    Map<String, String> eventValues = new HashMap<>();
    eventValues.put("some_parameter", "some_value");
    AppsFlyerLib.getInstance().validateAndLogInAppPurchase(getApplicationContext(),
                                                           PUBLIC_KEY,
                                                           purchase.getSignature(),
                                                           purchase.getOriginalJson(),
                                                           "10",
                                                           "USD",
                                                           eventValues);
}
// Purchase object is returned by Google API in onPurchasesUpdated() callback
private fun handlePurchase(Purchase purchase) {
   Log.d(LOG_TAG, "Purchase successful!")
   val eventValues = HashMap<String, String>()
   eventValues.put("some_parameter", "some_value")
   AppsFlyerLib.getInstance().validateAndLogInAppPurchase(this,
                                                          PUBLIC_KEY,
                                                          purchase.getSignature(),
                                                          purchase.getOriginalJson(),
                                                          "10",
                                                          "USD",
                                                          eventValues)
}

Handling purchase validation success/failure

Use AppsFlyerInAppPurchaseValidatorListener to subscribe to purchase validation successes/failures and registerValidatorListener to register it in your Application class.

registerValidatorListener is exposed via AppsFlyerLib. To use AppsFlyerInAppPurchaseValidatorListener, import it:

import com.appsflyer.AppsFlyerInAppPurchaseValidatorListener;
import com.appsflyer.AppsFlyerInAppPurchaseValidatorListener

AppsFlyerInAppPurchaseValidatorListener 두 개의 콜백이 있습니다.

registerValidatorListener 인수 4개를 갖습니다.

  • context: 애플리케이션 컨텍스트
  • validationListener: The AppsFlyerInAppPurchaseValidatorListener object you wish to register
AppsFlyerLib.getInstance().registerValidatorListener(this,new
   AppsFlyerInAppPurchaseValidatorListener() {
     public void onValidateInApp() {
       Log.d(TAG, "Purchase validated successfully");
     }
     public void onValidateInAppFailure(String error) {
       Log.d(TAG, "onValidateInAppFailure called: " + error);
     }
});
AppsFlyerLib.getInstance().registerValidatorListener(this, object : AppsFlyerInAppPurchaseValidatorListener {
    override fun onValidateInApp() {
       	Log.d(LOG_TAG, "Purchase validated successfully")
    }

    override fun onValidateInAppFailure(error: String) {
        Log.d(LOG_TAG, "onValidateInAppFailure called: $error")
   }
})

구매 검증을 통과하면 앱스플라이어로 인앱 구매 이벤트가 자동 전송됩니다. 아래에서 event_value 파라미터에 전송된 샘플 데이터를 참고하십시오:

{
   "some_parameter": "some_value", // from additional_event_values
   "af_currency": "USD", // from currency
   "af_content_id" :"test_id", // from purchase
   "af_revenue": "10", // from revenue
   "af_quantity": "1", // from purchase
   "af_validated": true // flag that AF verified the purchase
}