简体   繁体   中英

Why does this Objective-C code trigger False Purchase Tracking

The point of this code is to track Purchases using a service called MobileAppTracking, some of which are correctly tracked. But the service is showing that this code is sending a bunch of extra purchase calls, for which there is no record in itunes connect. Much of the following is just boilerplate code from the typical IOS storekit. specifically, this code is from InAppPurchaseManager, an IOS plugin for IOS purchases.

Here is the plugin I'm using: https://github.com/phonegap/phonegap-plugins/tree/master/iPhone/InAppPurchaseManager

And here is my modified code:

// SKPaymentTransactionObserver methods
// called when the transaction status is updated
//
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    NSString *state, *error, *transactionIdentifier, *transactionReceipt, *productId;
    NSInteger errorCode;
    SKPayment *thePayment;

    for (SKPaymentTransaction *transaction in transactions)
    {
        error = state = transactionIdentifier = transactionReceipt = productId = @"";
        errorCode = 0;

        BOOL shouldTrackEvent = false;  //  maybe this should just be for successful purchases.

        switch (transaction.transactionState)
        {
            case SKPaymentTransactionStatePurchasing:
                continue;

            case SKPaymentTransactionStatePurchased:
                state = @"PaymentTransactionStatePurchased";
                transactionIdentifier = transaction.transactionIdentifier;
                transactionReceipt = [[transaction transactionReceipt] base64EncodedString];
                productId = transaction.payment.productIdentifier;
                //thePayment = transaction.payment;

                //NSLog(@"localCurr=", thePayment.currency );
                //NSLog(@"localCurr=", thePayment.localizedTitle );
                shouldTrackEvent = true;
                break;

            case SKPaymentTransactionStateFailed:
                state = @"PaymentTransactionStateFailed";
                error = transaction.error.localizedDescription;
                errorCode = transaction.error.code;
                NSLog(@"error %d %@", errorCode, error);

                break;

            case SKPaymentTransactionStateRestored:
                state = @"PaymentTransactionStateRestored";
                transactionIdentifier = transaction.originalTransaction.transactionIdentifier;
                transactionReceipt = [[transaction transactionReceipt] base64EncodedString];
                productId = transaction.originalTransaction.payment.productIdentifier;
                break;

            default:
                NSLog(@"Invalid state");
                continue;
        }
        NSLog(@"state: %@", state);
        NSArray *callbackArgs = [NSArray arrayWithObjects:
                                 NILABLE(state),
                                 [NSNumber numberWithInt:errorCode],
                                 NILABLE(error),
                                 NILABLE(transactionIdentifier),
                                 NILABLE(productId),
                                 NILABLE(transactionReceipt),
                                 nil];
        NSString *js = [NSString stringWithFormat:@"plugins.inAppPurchaseManager.updatedTransactionCallback.apply(plugins.inAppPurchaseManager, %@)", [callbackArgs JSONSerialize]];
        NSLog(@"js: %@", js);
        [self writeJavascript: js];
        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];


        //  The Rest is all tracking code. P
        // default tracking event name
        NSString *eventName = @"purchase";


        // self.products is the dictionary (NString, SKProduct) to be created by the user
        NSDictionary *dictProducts = true; //(NSDictionary *)savedValidProducts;

        // get the product associated with this transaction
        //SKProduct *product = (SKProduct *)([dictProducts objectForKey:transaction.payment.productIdentifier]);
        // assign the currency code extracted from the transaction
        NSString *currencyCode = @"";// [product.priceLocale objectForKey:NSLocaleCurrencyCode];

        //  transaction.payment.productIdentifier

            //  The problem with not retrieving the real price is, what if they purchase in another country??
            float unitPrice = 0; //[product.price floatValue];

            NSString *title;
            title = @"Tester";

            NSLog(@"productIdentifier: %@", transaction.payment.productIdentifier);

            if( [transaction.payment.productIdentifier isEqualToString:@"2_REFILLS"] ) {
                title = @"2 Energy Refills";
                unitPrice = 1.99;
            }

            if( [transaction.payment.productIdentifier isEqualToString:@"6_REFILLS"] ) {
                title = @"6 Energy Refills";
                unitPrice = 4.99;
            }

            if( [transaction.payment.productIdentifier isEqualToString:@"15_REFILLS"] ) {
                title = @"15 Energy Refills";
                unitPrice = 9.99;
            }

            // extract transaction product quantity
            int quantity = 1; //transaction.payment.quantity; // extract unit price of the product

            // assign revenue generated from the current product
            float revenue = unitPrice * quantity;

            // create MAT tracking event item
            NSDictionary *dictItem = @{ @"item" : title,   // product.localizedTitle,
                                        @"unit_price" : [NSString stringWithFormat:@"%f", unitPrice],
                                        @"quantity" : [NSString stringWithFormat:@"%i", quantity],
                                        @"revenue" : [NSString stringWithFormat:@"%f", revenue]
                                        };

            NSArray *arrEventItems = @[ dictItem ];

            if(shouldTrackEvent) {

                NSLog(@"Event Item = %@", arrEventItems);

                // track the purchase transaction event
                // Total event revenue = sum of even item revenues in arrEventItems + extraRevenue
                float extraRevenue = 0; // default to zero
                [[MobileAppTracker sharedManager] trackActionForEventIdOrName:eventName
                                                                    eventIsId:NO
                                                                   eventItems:arrEventItems
                                                                  referenceId:transaction.transactionIdentifier
                                                                revenueAmount:extraRevenue
                                                                 currencyCode:currencyCode
                                                             transactionState:transaction.transactionState];
                NSLog(@"Transaction event tracked: %@", eventName);
            }
    }
}

One possibility is that you are being hacked. Your update of the tracking information, and acceptance of the purchase, is done even if the purchase is invalid. There are standard tools available for bypassing payment and getting IAP items for free if a server is not used for signature checking. Unfortunately, the only way I know of checking this requires the use of your own server for purchase verification.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM