worldpay / hybris Goto Github PK
View Code? Open in Web Editor NEWWorldpay SAP Hybris Addon
Worldpay SAP Hybris Addon
Hello Worldpay team, I am a backend engineer representing the Wilko project.
We've recently (Nov 16th) updated the worldpay plugin to 1905_7.0 version, and since then, we've been getting the following error:
Cannot invoke "org.springframework.http.ResponseEntity.getHeaders()" because "responseXML" is null, java.lang.NullPointerException in com.worldpay.service.http.impl.DefaultWorldpayConnector.processResponseXML(final ResponseEntity responseXML):111
It seems that, in some cases, the response from Worldpay request was getting passed as null
into the processResponseXML()
method. After some investigation, the root cause proved to be the use of the reactive API of RxJava on the following line
final Single<ResponseEntity<String>> response = sendOutboundXML(outboundPaymentService, merchantInfo, cookie);
response.subscribe(responseXML::set);
return processResponseXML(responseXML.get());
โ the Single.subscribe()
method is not blocking, and if the request takes a little bit longer than usual to return the response (for example it goes into the retry loop defined here), the responseXML.get()
bit ends up being null
, because the subscribe callback doesn't have a chance to set the response.
The logical question would be, why is this issue manifesting now more aggressively than before, since the above code hasn't been touched in the latest release? โ the answer is the newly added delay. Adding a delay between the retry attempts, increased the odds of this issue manifesting itself more often than usual.
Here is a unit test, which you can add to DefaultWorldpayConnectorTest
, to help reproduce this issue:
@Test
public void send_WhenTheResponseIsDelayedByRetries_ShouldSendThePaymentServiceTransformedInXML() throws Exception
{
final var body = "body";
final var cookie = "cookie";
final var someXML = "someXML";
final var inputStreamArgumentCaptor = ArgumentCaptor.forClass(InputStream.class);
when(responseEntityMock.getHeaders()).thenReturn(httpHeadersMock);
when(httpHeadersMock.get(HttpHeaders.SET_COOKIE)).thenReturn(List.of(cookie));
when(responseEntityMock.getBody()).thenReturn(body);
when(paymentServiceMarshallerMock.unmarshal(inputStreamArgumentCaptor.capture())).thenReturn(paymentServiceReplyMock);
when(paymentServiceMarshallerMock.marshalAsFragment(paymentServiceRequestMock)).thenReturn(someXML);
when(restTemplateMock.postForEntity(uriArgumentCaptor.capture(), httpEntityArgumentCaptor.capture(), eq(String.class)))
.thenThrow(new ResourceAccessException(""))
.thenThrow(new ResourceAccessException(""))
.thenReturn(responseEntityMock);
assertThat(testObj.send(paymentServiceRequestMock, merchantInfoMock, cookie))
.extracting(ServiceReply::getPaymentService, ServiceReply::getCookie)
.containsExactly(paymentServiceReplyMock, cookie);
final var uri = uriArgumentCaptor.getValue();
assertThat(uri.toString()).isEqualTo(ENDPOINT);
final byte[] plainCreds = ("merchantCode" + ":" + "merchantPassword").getBytes(StandardCharsets.UTF_8);
final var request = httpEntityArgumentCaptor.getValue();
assertThat(request.getHeaders()).containsAllEntriesOf(Map.of(
HttpHeaders.AUTHORIZATION, List.of("Basic " + new String(Base64.getEncoder().encode(plainCreds))),
HttpHeaders.HOST, List.of(uri.getHost()),
HttpHeaders.COOKIE, List.of(cookie)));
assertThat(request.getBody()).startsWith(XML_HEADER).contains(someXML);
assertThat(inputStreamArgumentCaptor.getValue()).hasSameContentAs(IOUtils.toInputStream(body, StandardCharsets.UTF_8));
verify(restTemplateMock, times(3)).postForEntity(eq(URI.create(ENDPOINT)), anyObject(), eq(String.class));
}
Our current hotfix for this is to do
responseXML.set(response.toBlocking().value());
instead of
response.subscribe(responseXML::set);
however it would be nice to have this fixed upstream.
Hope this feedback was helpful to you.
P.S. something like RetryTemplate might be more fitting here instead of RxJava for the retry mechanism.
@rselimi ,
Would you mind adding release notes for the last release to "master"? We'd like to upgrade to the latest and greatest version of your plugin. We'd like to understand what goes in the plugin.
Hi,
Unfortunately, I am getting a compilation error with the 2205_6 release. It was working fine until 2205_3 version and after that, I see that you changed the import for CheckoutPaymentType from
import de.hybris.platform.b2bacceleratorservices.enums.CheckoutPaymentType;
to
import de.hybris.platform.b2b.enums.CheckoutPaymentType;
in WorldpayB2BAcceleratorCheckoutFacadeDecorator class and this has a compilation error.
The definition for CheckoutPaymentType is in b2bacceleratorservices-items.xml as below:
<enumtype generate="true" code="CheckoutPaymentType" autocreate="true" dynamic="true">
<description>This enum type will be used for selecting checkout Payment Type</description>
<value code="CARD"/>
<value code="ACCOUNT"/>
</enumtype>
It seems the change happened in the 2205_4 release with this commit:
So it should be in de.hybris.platform.b2bacceleratorservices.enums. and not in de.hybris.platform.b2b.enums
Would you please fix it?
best,
Hi, as Worldpay notified they are going to change the type PAYPAL-EXPRESS to PAYPAL-SSL. I just want to ask do you have any plans to fix it in this project?
Kind regards,
Mohsen
Hello again, worldpay team, we've encountered another issue with the latest 1905_7.0 release:
When the new DefaultWorldpayOrderModificationProcessService
has been introduced, a class cast has creeped out of the if
branch on this line. This causes an unhandled ClassCastException
which crashes the OrderModificationProcessorJobPerformable
completely and orders are stuck in Pending Payment Notification
status.
Here is a unit test which you can add to DefaultWorldpayOrderModificationProcessServiceTest
to reproduce the issue:
@Test
public void processOrderModificationMessages_WhenWorldpayOrderCodeRelatesToCartWithAuthorizationTransactionType_ShouldDoNothing() throws WorldpayConfigurationException {
when(paymentTransactionModelMock.getOrder()).thenReturn(cartModelMock);
final boolean result = testObj.processOrderModificationMessages(AUTHORIZATION);
assertTrue(result);
verify(worldpayOrderNotificationHandlerMock, never()).handleNotificationBusinessProcess(AUTHORIZATION, worldpayOrderModificationMock, orderModelMock, orderNotificationMessageMock);
verify(worldpayOrderModificationMock, never()).setProcessed(Boolean.TRUE);
verify(worldpayOrderModificationMock, never()).setDefective(any(Boolean.class));
}
Thank you for your support.
Regards.
This plugin's implementation of CardPaymentService is incomplete, given that 8 out of 12 logically possible commands are absent from worldpayapi
. See https://github.com/Worldpay/hybris/tree/master/hybris/bin/y-ext/ext-worldpay/worldpayapi/src/com/worldpay/commands/impl
The commands whose implementation appear to be absent are:
The business impact as far as I can tell are:
orderModificationProcessorJobPerformable
is using worldpayOrderModificationProcessService
for the constructor-arg but it should use it's alias to allow for custom extensions, based on worldpaynotifications
to override the logic without the need of changing any of the worldpaynotifications
code.
<bean id="orderModificationProcessorJobPerformable" class="com.worldpay.cronjob.OrderModificationProcessorJobPerformable" parent="abstractJobPerformable">
<constructor-arg name="worldpayOrderModificationProcessService" ref="worldpayOrderModificationProcessService"/>
</bean>
should be changed to:
<bean id="orderModificationProcessorJobPerformable" class="com.worldpay.cronjob.OrderModificationProcessorJobPerformable" parent="abstractJobPerformable">
<constructor-arg name="worldpayOrderModificationProcessService" ref="orderModificationProcessStrategy"/>
</bean>
Hi,
I have integrated worldpay notification callback and in rare cases, I get notifications with the following values:
{ ...
"authStatus": "CANCELLED",
...
"journalType": "AUTHORISED"
...}
I was wondering what this kind of notification means exactly. Can I trust "authStatus" and be sure that the payment is canceled definitely?
There is no license attached to this extension. Which license applies? MIT? Apache Software Foundation? Or maybe it's not even open source, and there's a cost for using these extensions?
At minimum I would assume that any retailer using these extensions has to have a contract to use WorldPay and Hybris, but that doesn't speak to the licensing or commercials of these extensions? Are these extensions an add-on product that WorldPay charges to its Hybris customers?
Since this is a public github repository, what are the guidelines for contributing pull requests to this repository?
Are any contributions accepted? Or maybe none?
We know that Merchant Defined Parameters (MDP) should be possible with the World Pay API:
We know from our experience (and usage of a competing provider) that the usage of MDP is a common requirement to aid finance teams with their reporting.
Does the plugin support MDP? If not, where would it fit in the roadmap for the plugin?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.