Solved

ICCHostedPaymentFormResponseParser

  • 13 October 2023
  • 30 replies
  • 398 views

Badge

Working on creating a Custom cc plug-in . However i cannot get the ICCHostedPaymentFormResponseParser to work . 

Does anyone have any ideas of how i can go about this?

icon

Best answer by Evgeny Afanasiev 19 October 2023, 15:44

View original

30 replies

Userlevel 3
Badge

Hi @Merch ,


The click on the Pay/Save on the Hosted Payment Form should invoke the following callback from within Hosted Payment Form:

window.parent.px_callback.paymentCallback('action=transactResponse&response=somestring

The somestring value will be delivered as an input in the Parse() method. Where you can take the whole response and and extract the TransactionId from it.


Here is a demo implementation of CC Plug-in: https://github.com/weihnachtswichtel/AcumaticaDemoHostedFormIntegration

Userlevel 3
Badge

Great, then you only need to add the file to the customization project like documented here:

https://help.acumatica.com/(W(5))/Help?ScreenId=ShowWiki&pageid=01a694bb-8e42-436c-89ad-2c42c040089a then export it from your dev instance and import and publish it on production instance.

Please note that even you are absolutely sure in your customization, it is recommended to have a staging environment, for testing at least the deployment process.

Userlevel 3
Badge

Hi @Merch,

Yes, you’d need to pass the full url of the PaymentConnector.html to the HostedForm service, so it will render its own hosted form, and place the PaymentConnector in the nested IFrame. The communication between the processing center and hosted form will be performed directly, but when it will happened, nested iframe with PaymentConnector, will pass the result of the response to Acumatica. Obviously the full url to the connector should be generated dynamically, and since HttpContext.Current might not be available in some scenarios or depending on version, try to use build in helper method for it and check the GitHub link in first reply.

 

In case you are using build-in PaymentConnector.html you do not need to add it again. If you are build your own form, based on JS scripts, after you have if on the Dev instance, you can just add it as Files item in the customization project.

Userlevel 3
Badge

Hi @Merch,

It looks like that the issue you’re describing is related to Same-origin policy for example when you’re trying to access an iframe with different origin using JavaScript. This is not really Acumatica specific, and most probably related to the code nested in the frame loaded in the PaymentConnector. There are two common scenarios we see in implementation of hosted form - it is either really a web page hosted by the gateway and when called it is loaded in the iframe. Or it is some js. libraries that allows you to build form on side in PCI-compliant way. Which is your case? Since there is not much information provided in the post, I would suggest to debug hosted form using browser developer tools, to find where exactly the issue is happening and act accordingly.

Userlevel 3
Badge

Hi @Merch,

Another idea.

Many gateways having some of the services and APIs behind the Geo Block, etc for security reasons. In the case of hosted form, the API request will be done from the browser of your machine (not from the place where the server is hosted). The server response for the blocked location might not contain “Access-Control-Allow-Origin” header. And that will look like a CORS issue, but root cause is elsewhere.
Below is an actual example of getting a CORS issue when vaulting card via Hosted Form that was caused be geo blocking:

So if you are not based in the area where the gateway usually operates (US?), try to use VPN tunnels, or RDP machine somewhere closer to that region. As a proof of concept, try to access the url location that fails just in the browser to see if you have any response. If the physical location is not an issue, please share some screenshots of browser console.

Userlevel 3
Badge

Hi @Merch,

The error message you’ve posted stating that the issue is in accessing a cross-origin frame, so it should be related to Same-Origin Policy. In your example test1 is not a subdomain but a path, so test.com and test.com/test1 are same-origin as only path part is different, but host is the same.


My scientific guess, that the issue might be in the protocol. When you’re retrieving the url of the current Acumatica instance for a callback based on the scenario it might take http instead of https. If this is the case in GetDataForPaymentForm method, when getting PaymentConnector url for a callback, ensure that it is https using string.Replace().

 

Userlevel 3
Badge

@Merch ,

I think something is not right in the approach.

If the hosted form is really hosted in the processing center side, than IFrame should direct to this form. i.e. Url property of the HostedFormData object returned by GetDataForPaymentForm() method should be populated by the hosted form service, not the local frame. The url to the local frame passed to the processing center as a parameter for callback.

If you’re building the hosted form your own using js libs, then you can use in the Url the local custom frame that you’ve build.

It looks somehow mixed in your case. Also as mentioned before -iframePost.contentWindow.postMessage('action=transactResponse&response would not work.
When hosted form is open Acuamica is just waiting for the px_callback.paymentCallback() method to be called. It is hardcoded and compiled in PX.Web.dll, so nothing can be done about it.

Please note that in the native PaymentConnector this method in not called directly. Instead the listener is added and window.parent.parent.px_callback.paymentCallback(somedata) is called on message received.
This part is missing

Userlevel 3
Badge

Hi Merch,
 

Glad that it worked for you!

As for the HostedForm to vault the Cards, you would need to implement ICCHostedFormProcessor interface. Very similar way as ICCHostedPaymentFormProcessor, just simplier, as you do not need to pass amount, currency, etc.

The getting card token (aka payment profile id) process is different, as Acumatica interfaces initially build for Auth.Net, that not returning card token by response. So the way it works, after the callback received, hosted form is closed and the implementation of the GetAllPaymentProfies method in ICCProfileProcessor called. There you can retrieve all the card for the specific customer  with the card that just has been vaulted. Then the payment profile is created base on that.

If your processing center returns the token by response, then there is a trick to return in the GetAllPaymentProfies just one CreditCardData, based on response.

For this you need to to capture the response from the hosted form yourself. This is an example:
https://github.com/weihnachtswichtel/AcumaticaDemoHostedFormIntegration/blob/master/CLCustomerPaymentMethodMaintExt.cs

Then you can get this value in plug-in like that:
https://github.com/weihnachtswichtel/AcumaticaDemoHostedFormIntegration/blob/master/CLProfileProcessor.cs#L48

parse the token out of it, form CreditCardData object and return it as an only item in the list.
 

@Merch, since the initial matter (ICCHostedPaymentFormResponseParser) is clarified, I would suggest to close this topic as answered. Please mark as an answer the post that helped you most.
And if you have any other questions regarding ICCPlugin please raise another topic. This way, for other people who would have similar questions it will be easier to find right answers here.

Thank you

Userlevel 3
Badge

Hi @Merch,

First about http/https:
I am still referring to your statement:

The interesting part about this is that the error displays as two domains as the same domain with a different subdomain.

for example test.com and test.com/test1

Since the origin issue is thrown when the host and origin are test.com in both cases, what could be an issue is either the protocol or port or both.
Not to be unfounded below is an example, when there is external http call from within the https frame:

because http://localhost and https://localhost are different origins. If this is fixed, and call is made using https, the request is working:


If to make a call from the frame to the another domain and call the paymentCallback function directly, CORS will arise:

So in my case above the issue would be CORSMissingAllowOrigin.
I did not see such issues in the case when the payment form is hosted at the gateway, as usually js-scripts loaded in the frame that enabling the secure communication.

If you are using a custom payment conntector, it might not be really needed in your case. Please use the build-in Frames/PaymentConnector.html (or review and reuse it’s code). Its contains the logic that passes the data from Iframe to parent.

If suggestions above not resolving the matter, please share the screenshots of the error from the browser developer tools - console and networking tabs, when the issue is raised.

Badge

When i submit the form i get : The 001982 payment has no active pre-authorized or captured transactions. To process the 001982 payment, open the Payments and Applications (AR302000) form.

 

when i post do window.postMessage nothings happens when i post to parent I get a CORS error..

Badge


I thought i should just include the url for the iframe which hosts the payment and then send back the response through the iframe form. Is this not the method to use? what would you suggest?

   

Badge

after i submit the form the page submits reloads and the i did a parent.postMessage or parent.window.px_callback().. i think i am missing a step here  

Badge

Also my form submit the page and then on the submitted page (same url) i try to post but i am not even seeing that portion on my browser debug tools .. 

Badge

Thank you for this , so just to understand - what am i returning in the hosted form a vaulted card not tied to a customer ?

Badge

I created an iframe from within the payment processor hosted window the iframe source is ***.acumatica.com/Frames/PaymentConnector.html. i then did iframe.contentWindow.PostMessage(action=transactResponse&response=somestring , ‘*’) . I got a simillar result in my dev tools to what you posted but the transaction is still not feeding through (the window for the hosted paymnet form is also not closing unless i X it out)

Userlevel 3
Badge

@Merch,

In case your processing center returns the card token on response and you managed to pass it to GetAllPaymentProfies method. The card created will be linked to the customerProfileId. If the current Acumatica customer does not have a saved customerProfileId, it should will be created first in your ICCProfileProcessor.CreateCustomerProfile implementation.

If processing center does not return the card token, you can retrieve all the card for specific customer -  customerProfileId is a parameter of GetAllPaymentProfies method.

Please see in the official documentation, what methods should be implemented:
https://help.acumatica.com/(W(1))/Help?ScreenId=ShowWiki&pageid=53da199c-4dbc-44a7-8f73-93292f723b81

Badge

@Evgeny Afanasiev 

 

Thank you very much for this !

After implementing this solution I am still getting Uncaught DOMException: Blocked a frame with origin "****.com" from accessing a cross-origin frame. The iframe calls to this origin with a subdomain appended.

Badge

I created A frame how to i publish it to production ? ( i was able to publish to local)

Badge

right but how do i add the file on the dev instance ? Also when i was trying to use build in methods to get the url , it was telling me that it wasnt available on this instance?

Userlevel 3
Badge

Hi @Merch,

For the development purposes in most cases you would require a locally installed instance of Acumatica, as implementing a code customization you would need a direct access to the file system. In order to have a file that has to be distributed, you just need to place it physically on on the local site where you would like it to be and add this as FILE item in the customization project.
If you do not have a local instance for development, it better to set one. Here is a quick guide: https://www.acumatica.com/blog/quick-start-acumatica-developer-guide/

Badge

I have a local ORG and i added the Frame , my question is going from there how do i get it into production?

Badge

But since my local environment is not connected to production , i am not seeing my file when i try to add it to production. I have a sandbox but it is on the same tenant so not sure how helpful it actually is.

Badge

@Evgeny Afanasiev 

It is hosted on the payment gateway . If it is the not the Same-Origin Policy then how do you think I should resolve in that case?

The interesting part about this is that the error displays as two domains as the same domain with a different subdomain.

 

for example test.com and test.com/test1

Badge

okay but at this point i am not seeing any errors- no cors or failed to load resource or anything like that! everything seems to be working but the SynchornizePayment graph is still not triggered. How can I send you screenshots because i do not want to submit them on  a public forum?

Userlevel 3
Badge

@Merch,

SynchornizePayment will be triggered after the payment callback is invoked from hosted form. By callback I mean window.parent.px_callback.paymentCallback() method. As for sharing, you can copy/paste pictures in PMs. Or use any service that allow sharing files by link.

Reply


About Acumatica ERP system
Acumatica Cloud ERP provides the best business management solution for transforming your company to thrive in the new digital economy. Built on a future-proof platform with open architecture for rapid integrations, scalability, and ease of use, Acumatica delivers unparalleled value to small and midmarket organizations. Connected Business. Delivered.
© 2008 — 2024  Acumatica, Inc. All rights reserved