darryncampbell / darryncampbell-cordova-plugin-intent

General purpose intent shim layer for cordova appliations on Android. Handles various techniques for sending and receiving intents.
MIT License
86 stars 134 forks source link

IONIC Native Web Intent response is incorrect in specific case #60

Open haresh333 opened 5 years ago

haresh333 commented 5 years ago

Hi @darryncampbell

(NOTE: GooglePay (earlier called Tez) is an India specific payment app launched by Google in India which uses UPI specification to facilitate in-app payment. This UPI payment provided Web Intent based mechanism to perform payment using Mobile App. BHIM, PhonePe are apps similar to GooglePay but by other vendors)

  1. I am integrating Google Pay with my IONIC v3 based mobile app on Android Device using UPI Deep linking specification (using IONIC Native Web Intent plugin. This is shim layer for the Android intent mechanism)

  2. I call below method to invoke web intent. Through chooser I choose Google Pay (Tez) app . Payment is completed successfully. this.webIntent.startActivityForResult(intentOptions ).then(intentResponse=>{},err=>{});

  3. My Problem - What I receive in intent response is below even though payment is successful. {"extras":{"resultCode":0,"requestCode":1},"flags":0}

  4. Behaviour with other apps like BHIM or PhonePe (these are applications similar to Google Pay to perform payment). If I use other app like PhonePe or BHIM instead of GooglePay, it works perfectly This kind of behaviour I have seen only with GooglePay. There are more than 25+ such applications and (I tested more that 15) all those work perfectly

Success Response scenario by BHIM/PhonePe app {"extras":{"resultCode":-1 , "response":"txnId=UPI586b8ee3d55b4405bfd30dab4b6b69bb&responseCode=00&ApprovalRefNo=null&Status=SUCCESS&txnRef=TR0001","requestCode":1},"flags":0} This response format complies with request/response guidelines provided by NPCI/UPI Payment framework which all app providers like Google Pay, Phonepe, BHIM etc are expected to follow.

After successful payment, it is supposed to return “resultCode”= -1 and provide “response” in the extras object. However the response is missing in extras

  1. I wrote a native android test program to invoke same Google Pay app. startActivityForResult(chooser, REQUEST_PAYMENT, null); if the payment is successful, it returns the response in expected manner. I can extract the response by calling Intent.getStringExtra("response"))

This probably implies the underlying Google Tez app behaves correctly.

  1. I suspect there is unique behaviour with Web Intent plugin ( IONIC native wrapper or cordova plugin version provided in maroon color below.) when response is returned by Google Pay to darryncampbell-cordova-plugin and sending that response back to my caller app o all other apps response excect GooglePay the response is correctly sent back to my caller app.

  2. Please advice o what may be wrong o what I can do to debug the IONIC native wrapper or cordova plugin or put console.log statements to deep dive. o What other information I should provide you to investigate further?

  3. My Environment Versions

      1. Mobile app – Android 6.0 and 7.0
      1. IONIC v3.20.0
      1. Web Intent a. b. "@ionic-native/web-intent": "^4.14.0",
      1. Ionic Framework
        a. ionic-angular 3.9.2
      1. System: a. Android SDK Tools : 26.1.1 b. Node : v8.11.1 c. npm : 6.0.0 d. OS : Windows 10

Thank you and warm regards

Haresh Gujarathi Business Development Partner MindNerves Technology Services Pvt Ltd Ph: +91 91724 30080

darryncampbell commented 5 years ago

Hi Haresh, thank you for the detailed problem report. I would like to help if I can and am more than open to the idea that there is some problem with how the plugin handles this scenario.

Are you able to debug the application with Android Studio? What I would do in your situation is to build the application on the command line with Ionic and then, in Android Studio, open the project under /platforms/android. You can then debug into the Java code by opening /app/java/com/darryncampbell.plugin.intent/IntentShim.java, add some break points and try to see what is going wrong. Do NOT tell Android Studio to update the version of gradle as that has given me build problems in the past as Ionic assumes a specific version.

Hope that helps narrow down the problem

haresh333 commented 5 years ago

Thanks for your quick reply. I will explore what you suggested and get back to you.

haresh333 commented 5 years ago

Hi Darryn

I debugged the web intent call. in IntentShim.java after Google Pay is loaded, the payment is completed by GooglePay below callback method gets executed. Intent processing app (OR Intermediate Cordova plugin ) calls below method BUT the Intent object received in this method is NULL even though payment is completed successfully.

While other apps intent object and result code is properly populated.

Line#579 public void onActivityResult(int requestCode, int resultCode, Intent intent) --> resultCode=0 intent=null { super.onActivityResult(requestCode, resultCode, intent); if (onActivityResultCallbackContext != null && intent != null)

darryncampbell commented 5 years ago

Is the call to startActivityForResult correct? https://github.com/darryncampbell/darryncampbell-cordova-plugin-intent/blob/master/src/android/IntentShim.java#L406 Is the intent being sent in a form that is recognised by the receiving application?

haresh333 commented 5 years ago

Hi I will double check - but same piece of code works with other applications (GooglePay peers apps like BHIM/PhonePe etc)

haresh333 commented 5 years ago

Hi

  1. the call to startActivityForResult is also correct
  2. I debugged onActivityResult of the cordova part as well - the inent object from Android Intent or Google Pay seems to be coming as null. I am trying to download Android source code and debug the Android part
  3. third opition I am thinking is to write a react native sample app to check how it behaves
darryncampbell commented 5 years ago

Debugging into the Android source would be a drastic step(!). I do have a couple of test cases for reading a contact or an image with startActivityForResult: https://github.com/darryncampbell/plugin-intent-api-exerciser/blob/master/www/js/index.js#L162, might be worth double checking those work for you..

haresh333 commented 5 years ago

Hi Darryn

I tried what you suggested. In your exerciser app, I made changes as below and called GooglePay to perform payment activity using window.plugins.intentShim. startActivityForResult(). And it worked, it returned intent with expected response, that I was not getting from Cordova/Native plugin.

So I do not understand, why would Cordova plugin behave differently from window.plugins.intentShim? Is it that it is sending intent to GooglePay differently so as for GooglePay to behave differerently?

function startActivityPickContact() { window.plugins.intentShim.startActivityForResult( { action: window.plugins.intentShim.ACTION_VIEW, url: "upi://pay?pa=haresh.gujarathi@ybl&pn=PeRuPe Services&am=1.5&tn=Note1&tr=TR0001", requestCode: 1 }, function(intent) { if (intent.extras.requestCode == 1 && intent.extras.resultCode == window.plugins.intentShim.RESULT_OK) {

haresh333 commented 5 years ago

WAIT ... Something is not quite right,

  1. I copied same above code from your excerciser app to my app (which is IONIC3 app) and it did not work with GooglePay. It returned intent as null in onActivityResult()

What is the difference?

Your exerciser app does not seem to use IONIC Native plugin for web intent. it is using "com-darryncampbell-cordova-plugin-intent": "^1.1.0",

My App is using "@ionic-native/web-intent": "^4.14.0", "com-darryncampbell-cordova-plugin-intent": "^1.1.1", "ionic-angular": "^3.9.2",

darryncampbell commented 5 years ago

I would recommend using the com-darryncampbell-cordova-plugin-intent directly. I have not had much chance to test the ionic-native/web-intent - I did submit a pull request a while back but it is not yet in the latest release. When I created the Ionic Demo for my company (https://github.com/Zebra/ZebraIonicDemo) I ran into issues with the web-intent plugin so had to use my com-darryncampbell-cordova-plugin-intent plugin directly.

haresh333 commented 5 years ago

U mean to say I should not use @ionic-native/web-intent?

Just remove from the project and try?

darryncampbell commented 5 years ago

Yes... does it work using com-darryncampbell-cordova-plugin-intent directly?

haresh333 commented 5 years ago

I did several things

  1. I removed IONIC Native Web-Intent just left your plugin in my application code. But no luck.

  2. I created new IONIC app from "ionic start" which created new IONIC 3.0 app from template. "@angular/core": "5.2.11", "com-darryncampbell-cordova-plugin-intent": "^1.1.1", "cordova-android": "7.0.0", "ionic-angular": "3.9.2",

The web intent call worked as expected.

  1. then I added web intent native to this new app. The web intent call WORKED as well. "@ionic-native/core": "~4.12.0", "@ionic-native/web-intent": "^4.15.0",

  2. So it appears to me that somewhere in IONIC/Core/Native/Android has a defect that was fixed which I do not have my ionic-native core, cordova-android, typescript etc libraries are shade older.

I will try to upgrade these in my app and see what happens.

let me know if you have any other thoughts based on above.

Regards

darryncampbell commented 5 years ago

Quite possibly something got fixed in Ionic Native 4.x but I believe 4.x is still in Beta. You can avoid using web-intent entirely and just use the plugin directly, please see https://github.com/Zebra/ZebraIonicDemo for an example of how I did that a few months back.

atsoares commented 4 years ago

Hi, I'm facing the same issue. Any news about how to solve it?

darryncampbell commented 4 years ago

Hi @atsoares , what issue are you having exactly? How are you calling the API and what response do you expect? This original issue is over a year old so probably a bit old

atsoares commented 4 years ago

Hi @darryncampbell , I'm using ionic 4, calling it like this:

(<any>window).plugins.intentShim.startActivityForResult({
        action: (<any>window).plugins.intentShim.ACTION_VIEW,
        url: checkoutUri
        },
        function(intent) {
          alert(JSON.stringify(intent));
        },
        function() {
          console.log(baseTeste);
          alert('Failed to open URL via Android Intent')}
      );

but even when the payment is done, I'm still getting the same: {"extras":{"resultCode":0,"requestCode":1},"flags":0}

I did what @haresh333 told about creating a new ionic project without install web intent, just the plugin but it doesn't work, always same response.

darryncampbell commented 4 years ago

Interesting, I wonder if it has something to do with the call to remapURI: https://github.com/darryncampbell/darryncampbell-cordova-plugin-intent/blob/master/src/android/IntentShim.java#L459 or perhaps some other way the plugin is changing the URI. If you are able, perhaps fork this repo and try removing all the URI logic so you are left with URI.parse(checkoutUri) ? I am not able to look into this at the moment I'm afraid.

atsoares commented 4 years ago

I don't think that the issue is with the URI, the checkoutUri in my code is:

var checkoutUri = "lio://payment?request="+base64+"&urlCallback=order://response";

And it works... Calls the intent with the right parameters, the payment method starts and I can pay it normally, the receipt is impressed, but when the payment is finished even If I do pay or not and the intent is finished, I get the same response:

{"extras":{"resultCode":0,"requestCode":1},"flags":0}

Followed by an alert that shows that the intent called (third app) was closed.

Checking the code given by the third app that I'm integrating with shows that I need to use it by this way after preparing the URI:

var intent = Intent(Intent.ACTION_VIEW, Uri.parse(checkoutUri))
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(intent)
darryncampbell commented 4 years ago

I didn't know whether the Cordova resourceapi.remapapi was doing anything unusual to the checkoutUri as I never tested it with lio://. Regardless, did you try specifying the flag?

(<any>window).plugins.intentShim.startActivityForResult({
        action: (<any>window).plugins.intentShim.ACTION_VIEW,
        url: checkoutUri,
        flags: 67108864  //  https://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_CLEAR_TOP
        },
        function(intent) {
          alert(JSON.stringify(intent));
        },
        function() {
          console.log(baseTeste);
          alert('Failed to open URL via Android Intent')}
      );
atsoares commented 4 years ago

I tried it but with no success. Adding the flag the intent doesn't start and I get the Failed to open URL via Android Intent alert. I'll try another approach.

atsoares commented 4 years ago

About the lio://, just to let you know I'm trying to integrate it with this device:

https://developercielo.github.io/en/manual/cielo-lio

They don't have an official integration module for hybrid frameworks like ionic if you check the website above, but there's a way to do it, following this:

In manifest.xml I need to have:

<activity android:name=".ResponseActivity">    
   <intent-filter>        
      <action android:name="android.intent.action.VIEW" /> 
      <category android:name="android.intent.category.DEFAULT" />        
      <data android:host="response" android:scheme="order" />    
   </intent-filter> 
</activity> 

Bc after creating the new Activity, the .ResponseActivity will receive the response. The Cielo Technical Partner told me that they never use onActivityResult to send the response.

Do you have any idea of how I should make the calls in your plugin for this case?

darryncampbell commented 4 years ago

This plugin does not have the capability of adding:

<data android:host="response" android:scheme="order" />  

You will probably need to fork this project and add the capability - cordova allows you to modify the manifest by specifying values in a plugin.xml. You can see where this plugin makes modifications at https://github.com/darryncampbell/darryncampbell-cordova-plugin-intent/blob/master/plugin.xml#L17 and Cordova's documentation for this capability is at https://cordova.apache.org/docs/en/latest/plugin_ref/spec.html

atsoares commented 4 years ago

Hi, I made some changes at the plugin.xml and now the app isn't crashing anymore but I guess that your plugin isn't able to bring back the response where it should be, because I'm still getting the {"extras":{"resultCode":0,"requestCode":1},"flags":0}. It should be inserted in an another activity, not in onActivityResponse. Where do you set the response in your code?

darryncampbell commented 4 years ago

Where do you set the response in your code?

The response is set here: https://github.com/darryncampbell/darryncampbell-cordova-plugin-intent/blob/master/src/android/IntentShim.java#L243

atsoares commented 4 years ago

Yeah, it's because is always returning the response as onActivityResult. And I have no idea to deal with it. I will contact the third app partner trying to find another away to get the response in the right object.

nageshvn commented 4 years ago

hi i am also getting same {"extras":{"resultCode":0,"requestCode":1},"flags":0}.

clear the problem...

nageshvn commented 4 years ago

I did several things

  1. I removed IONIC Native Web-Intent just left your plugin in my application code. But no luck.
  2. I created new IONIC app from "ionic start" which created new IONIC 3.0 app from template. "@angular/core": "5.2.11", "com-darryncampbell-cordova-plugin-intent": "^1.1.1", "cordova-android": "7.0.0", "ionic-angular": "3.9.2",

The web intent call worked as expected.

  1. then I added web intent native to this new app. The web intent call WORKED as well. "@ionic-native/core": "~4.12.0", "@ionic-native/web-intent": "^4.15.0",
  2. So it appears to me that somewhere in IONIC/Core/Native/Android has a defect that was fixed which I do not have my ionic-native core, cordova-android, typescript etc libraries are shade older.

I will try to upgrade these in my app and see what happens.

let me know if you have any other thoughts based on above.

Regards

Are u got solution ?