function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Shiran FernandoShiran Fernando 

Unexpected behaviour when calling Apex controller method from Lightning Controller

I'm implementing Braintree drop-in UI in a Lightning Community. For this purpose I embedded the drop-in UI in a VF page and added that to lightning component inside an iframe. Communication done using the method described here https://developer.salesforce.com/blogs/developer-relations/2017/01/lightning-visualforce-communication.html

When the payment details are submitted I call the component controller method which sends a message to VF page requesting a verified payment method. On success, VF page sends back a message with the generated 'NONCE' key. And I handle this message in lightning component using controller method;
 
requestPaymentMethod : function(component, event, helper) {
        
        var message = 'requestPaymentMethod';
        var vfOrigin = component.get("v.baseUrl");
        var vfWindow = component.find("braintreeFrame").getElement().contentWindow;
        var action = component.get("c.submitPaymentDetails");
        vfWindow.postMessage(message, vfOrigin);
        if(!window.isListenerSet) {
            window.addEventListener("message", $A.getCallback(function(event) {
                if(!vfOrigin) vfOrigin = component.get("v.baseUrl");
                if (event.origin !== vfOrigin) {
                    // Not the expected origin: Reject the message!
                    return;
                }
                var msg = event.data;
                if(msg.type==='verifiedPaymentMethod') {
                    const nonce = msg.id;
                    if(nonce) {
                        helper.submitPayment(component, nonce, action);
                    }
                }
            }), false);
            window.isListenerSet = true;
        }
    }

The helper method calls the apex controller method to charge the verified payment method
submitPayment: function(component, nonce, action){
        console.log('nonce='+nonce);
        console.log(JSON.stringify(this));
        action.setParams({ "paymentMethodId": nonce } );
        action.setCallback(this, function(response){
            var state = response.getState();
            console.log(JSON.stringify(state));
            if (state === 'SUCCESS'){
                var retVal = response.getReturnValue();
                if(retVal==='SETTLING') {
                    var message = 'clearPaymentMethods';
                    var vfOrigin = component.get("v.baseUrl");
                    var vfWindow = component.find("braintreeFrame").getElement().contentWindow;
                    vfWindow.postMessage(message, vfOrigin);
                    this.showPaymentSuccess();
                    this.navigateTo(component);
                    // $A.get('e.force:refreshView').fire();
                }
            } else if (state === 'ERROR' || state === 'INCOMPLETE'){
                let errors = response.getError();
                console.log(JSON.stringify(errors));
                // this.navigateTo(component, errors);
            }
        });
        $A.enqueueAction(action);
    }


This works fine in the first cycle. But if process a second and subsequent transactions without refreshing the browser, calling of the submitPaymentDetails action doesn't return neither a success nor an error. But I can debug that the server method has actually been executed and transaction created.

Any idea why it is behaving this particular way?

P.S. - i'm not a gun JS developer so, I might have made some obvious mistake when connecting callbacks