globalpayments / java-sdk Goto Github PK
View Code? Open in Web Editor NEWLicense: GNU General Public License v2.0
License: GNU General Public License v2.0
The execute method of Secure3dBuilder
doesn't handle most errors and instead just returns a ThreeDSecure
model with no details on what went wrong, or any indication that something did go wrong.
For example, a validation error like the following:
{
"three_dsserver_trans_id" : "...",
"error_code" : "203",
"error_component" : "S",
"error_description" : "Format of one or more Data Elements is Invalid according to the Specification",
"error_detail" : "payer.billing_address.country",
"error_message_type" : "AReq",
"message_type" : "Erro",
"message_version" : "2.1.0"
}
In this case the exception is caught in execute method and not re-thrown. Instead, a ThreeDSecure
model is returned which just contains the serverTransactionId
and nothing else so it's impossible to tell what went wrong.
My employer has been integrating Global Payments Ecom Java SDK into their 3D Secure payments solution and seems to have discovered an issue introduced with SDK version 10.2.14.
When authentication_source
is set to MOBILE_SDK
, we are seeing the following NullPointerException now happen while obtaining authentication data before card authorization:
java.lang.NullPointerException
at com.global.api.gateways.Gp3DSProvider.mapResponse(Gp3DSProvider.java:390)
at com.global.api.gateways.Gp3DSProvider.processSecure3d(Gp3DSProvider.java:81)
at com.global.api.builders.Secure3dBuilder.execute(Secure3dBuilder.java:727)
at com.global.api.builders.Secure3dBuilder.execute(Secure3dBuilder.java:686)
This happens only when authentication_source
is set to MOBILE_SDK
From our analysis, the root cause is that the Ecom Java SDK is expecting acs_rendering_type
in the authentication response which is not present. This issue also reproduces into the latest release (10.2.16).
This is blocking our ability to roll out our payment solution using Global Payments.
"browser_data": {
"javascript_enabled": true,
"screen_width": 2048,
"screen_height": 1152,
"accept_header": "application/json, text/plain, */*",
"timezone": "0",
"ip": "XXX.XXX.XXX.XXX",
"color_depth": "TWENTY_FOUR_BITS",
"java_enabled": true,
"language": "en-GB-oxendict",
"challenge_window_size": "WINDOWED_600X400",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
},
One of our customers passed the following browser_data object, with the language set to en-GB-oxendict
We got the following error immediately
{
"three_dsserver_trans_id" : "2eb7fd89-2b16-4d1b-99a6-4c69b5d7cc0d",
"error_code" : "203",
"error_component" : "S",
"error_description" : "Format of one or more Data Elements is Invalid according to the Specification",
"error_detail" : "browser_data.language",
"error_message_type" : "AReq",
"message_type" : "Erro",
"message_version" : "2.1.0"
}
Are we ok to trim this value to en-GB
instead of en-GB-oxendict
and will this cause issues during fingerprint and/or challenge phase?
The current version of the Realex Connector does not support any reporting options, even though there is some commented out code for loading a transaction details:
Are there plans on adding support for this, especially for the ReportType.OpenAuths
report type?
Hi I am trying to integrate Google Pay:
================================================================================
Endpoint:
Verb: POST
Headers: {Content-Type=[text/xml; charset=UTF-8]}
Proxy: none
Request Body: dev777094689552280692internet100000wLsaWERUR3-O8EcnJyq7RA{"signature":"MEQCIG8qveEpGY2I3N2mJl+uA5PqLUZ42KdSN01bA7lpviO6AiADnrbuk9CrjhZoULuWLfaRoYesCXMrpaPauDDMDP929A\u003d\u003d","protocolVersion":"ECv1","signedMessage":"{"encryptedMessage":"wvECjwUE0miQBBl/NqoHf4Kx+2J23Zh3AYqAYDNs5ZuxXhZFQaxtg7mjwr33G7CO42Q+kxwZYPHj65r/59vxJ8cubVL9aa/XLaZwX0WGiKFWzmQLM746DvnMImPRtb7Ox8kJJrDn6IbJ3gJ6fuyafKl5RyJm2G+tYplyrG5vBtjuJJZ/zxjkyaPEBgZ2+wWRfK7M7qQduT4xP3qQ/8V05rm4Pml4zGBcv9cVgsqd0wxUZvK4Kdr8vKGBqKFAjptM21Xt9TxbBTEpGjPOf+BR5p56O9Gn/KF5DOt0SLbu3QQNBfm0lJ6Z2E2mYpdggbIYmO8BLbj49ATPvX3tXVV7ypDQSr0aokZ0fJC5hjmLVODoe1Nqp168FbakHcowj+STrZntyDAoNwzsJKYMuOZ9qet4wJs5coQ4K6OLZKgyLR41wpWmnrcGZC0FIN7UXAPpuIZ1l8zbu8uKn0kTOfbdXsSMTl5cz6P+GbwvtyXlQmD93YCwWa5vDi3dgtSus9MRhPOHX1K5+Xbzj86DDj+L17DHjEbbhsOjyqqYC2gLqrh3yU4DUbrB5xZGDtbLUWbdr0l1k0OjO0b8QJXupWgncSZNkl4\u003d","ephemeralPublicKey":"BGjd/O+VpkFdkbHWHbyC/r0446mRCTLZWV428KxN5xFdO6YSm5TiafUX4raQTM2fnHJd6+EEQ3W0mwtrBZrspjE\u003d","tag":"t43NyG/ooI2ne8oXmAbPv0xb9x4LHxQ6NYdnC81CWaI\u003d"}"}pay-with-google58c6e2ce9810dae58c951753eda78d548cb9c29d
com.global.api.entities.exceptions.GatewayException: Unexpected Gateway Response: 108 - Using test system. Please use pre-approved test cards ONLY
com.global.api.entities.exceptions.GatewayException: Unexpected Gateway Response: 108 - Using test system. Please use pre-approved test cards ONLY
at com.global.api.gateways.RealexConnector.checkResponse(RealexConnector.java:1083)
at com.global.api.gateways.RealexConnector.mapResponse(RealexConnector.java:881)
at com.global.api.gateways.RealexConnector.processAuthorization(RealexConnector.java:389)
at com.global.api.builders.AuthorizationBuilder.execute(AuthorizationBuilder.java:869)
at com.global.api.tests.gpapi.testing.main(testing.java:44)
Process finished with exit code 0
SDK used account name(hard code):
Transaction_Processing(GpApiConnector.processAuthorization)
developer portal generated account name:
transaction_processing
So you can meet the following error result if using GP API with java-sdk:
{
"error_code": "ACTION_NOT_AUTHORIZED",
"detailed_error_code": "40003",
"detailed_error_description": "Token does not match merchant config in the request"
}
I'm trying to create a charge with 3D secure 2 data like in the docs (see Authorization):
// Create the card object
CreditCardData card = new CreditCardData();
card.setNumber("4012001038488884");
card.setExpMonth(12);
card.setExpYear(2025);
card.setCvn("123");
card.setCardHolderName("James Mason");
// Add obtained 3D Secure 2 authentication data
ThreeDSecure threeDSecureData = new ThreeDSecure();
threeDSecureData.setAuthenticationValue("ODQzNjgwNjU0ZjM3N2JmYTg0NTM=");
threeDSecureData.setDirectoryServerTransactionId("c272b04f-6e7b-43a2-bb78-90f4fb94aa25");
threeDSecureData.setEci("05");
threeDSecureData.setMessageVersion("2.1.0");
// Add the 3D Secure 2 data to the card object
card.setThreeDSecure(threeDSecureData);
Transaction response = null;
try {
response = card.charge(new BigDecimal("10.01"))
.withCurrency("USD")
.execute();
}
catch (ApiException exec) {
// TODO: add your error handling here
}
But the request builder omits all 3DS related fields except exempt_status
, and the actual body of the request is like this:
...
"authentication": {
"three_ds": [
{}
]
}
...
Problem is in the GpApiAuthorizationRequestBuilder
(from lines 289) implementation.
Is there any reason why this is implemented this way? Why other parameters are not included in the request? Is it possible to fix this issue?
For example, this field:
does not appear in the generated Javadoc.
The code is completely uncommented, and the docs on globalpayments website are incredibly incomplete, it makes using this code almost impossible. E.g., the docs on the website says that some field will be "populated by the SDK" but neither does it say what part of the SDK to use for that, nor is any part of the SDK documented properly for someone to figure it out. This is not open source. Open source includes comments that make the source usable.
I can't see that making PayPal transactions is supported by this library. This would be really helpful for developers wanting to integrate with this feature of the GP API
A bug was introduced in 6.1.74 in RealexConnector. It is still present in 6.1.82.
The "if" check for the isCustomerExists block was changed:
if(paymentData.isCustomerExists() != null) {
request.set("PAYER_EXIST", paymentData.isCustomerExists() ? "1" : "0");
}
To this:
if(paymentData.isCustomerExists()) {
request.set("PAYER_EXIST", paymentData.isCustomerExists() ? "1" : "0");
}
If isCustomerExists is false, "PAYER_EXIST" will never be set. This causes an issue as "PAYER_EXIST" is a mandatory field.
The "if" condition should be restored to the previous version where it checks for not null.
java-sdk/src/main/java/com/global/api/gateways/RealexConnector.java
Lines 440 to 442 in b7fc604
I need the hpp to do card storage (and create payer), and the current sdk is unable to do it.
"PAYER_EXIST" is a required field in the request, but the code is not able to set it to "0" .
Looking at history, this broke in v6.1.74
Passing the config values as below
GatewayConfig config = new GatewayConfig();
...
config.setSecure3dVersion(Secure3dVersion.ANY);
The response XML will always default to Secure3dVersion.ONE
It's in your documentation that we need to check for Secure3dVersion.TWO
enrolment first, then follow up with Secure3dVersion.ONE
if the first request comes back with enrolled = false
. Wouldn't it be nice to just send Secure3dVersion.ANY
and prioritise the latest specification instead of sending two requests?
link to docs: https://developer.globalpay.com/api/3d-secure-two#3ds2-version
In the log, for those failed cases, it will actuall have the return code back, but in Java code since those operation will raise ApiException, is it have way to get result code and result message back? For example using decline card to test authorized, in the xml log the response will looks like following
<response timestamp="20231207215006">
<merchantid>itsp</merchantid>
<account>internet</account>
<orderid>00000290VnoCustAccount</orderid>
<authcode></authcode>
<result>101</result>
<cvnresult>M</cvnresult>
<avspostcoderesponse>M</avspostcoderesponse>
<avsaddressresponse>M</avsaddressresponse>
<batchid></batchid>
<message>[ test system ] DECLINED</message>
<pasref>17019858063877822</pasref>
<timetaken>0</timetaken>
<authtimetaken>0</authtimetaken>
<srd>ULtb5vr8kUDqa6U3</srd>
<cardissuer>
<bank></bank>
<country></country>
<countrycode></countrycode>
<region></region>
</cardissuer>
<fraudresponse mode="ACTIVE">
<result>NOT_EXECUTED</result>
<rules/>
</fraudresponse>
<sha1hash>ee7d2507a39cfffad342d3c8afcd53de077ac390</sha1hash>
</response>
How to get that 101
and [ test system ] DECLINED
back when I using this java code
Transaction transactionResponse =
authorizedBuilder.withAmount(new BigDecimal(amount.getAmount())).withCurrency(amount.getCurrency())
.withOrderId(orderId).withTimestamp(timestamp).execute();
Attributes "type" and "sequence" are always null in the ElementTree generated, even if the value is correctly set in the Builder.
From what I can see, method "EnumUtils.getMapping" should be used in the same way it is used for generating the "initiator" element.
Looking at the file CreditResponse.java, package com.global.api.terminals.pax.responses;
(Looks like it only parsing the response objects if deviceresponseCode.equals("000000")
). What's the reason for it only map the CreditResponse
when its approved? Will it not map it if its a partially approval or declined? I mean even if its declined I guess we still need to know like the card number, entry method, etc?
Please help!
How can I do to prevent duplicate submissions when making a sale
Hi Team,
While doing testing with this SDK for connection failure scenario by removing the internet connection, I am getting NullPointerException. The stacktrace is below
"localizedMessage":"Cannot invoke \"String.length()\" because \"s\" is null","message":"Cannot invoke \"String.length()\" because \"s\" is null","name":"java.lang.NullPointerException","extendedStackTrace":[{"class":"[java.io](http://java.io/).StringReader","method":"<init>","file":"StringReader.java","line":51,"exact":false,"location":"?","version":"?"},{"class":"com.google.gson.JsonParser","method":"parseString","file":"JsonParser.java","line":51,"exact":false,"location":"gson-2.10.1.jar","version":"?"},{"class":"com.google.gson.JsonParser","method":"parse","file":"JsonParser.java","line":115,"exact":false,"location":"gson-2.10.1.jar","version":"?"},{"class":"com.global.api.utils.JsonDoc","method":"parse","file":"JsonDoc.java","line":292,"exact":false,"location":"globalpayments-sdk-11.1.24.jar","version":"?"},{"class":"com.global.api.utils.JsonDoc","method":"parse","file":"JsonDoc.java","line":289,"exact":false,"location":"globalpayments-sdk-11.1.24.jar","version":"?"},{"class":"com.global.api.entities.gpApi.GpApiTokenResponse","method":"<init>","file":"GpApiTokenResponse.java","line":107,"exact":false,"location":"globalpayments-sdk-11.1.24.jar","version":"?"},{"class":"com.global.api.gateways.GpApiConnector","method":"getAccessToken","file":"GpApiConnector.java","line":190,"exact":false,"location":"globalpayments-sdk-11.1.24.jar","version":"?"},{"class":"com.global.api.gateways.GpApiConnector","method":"signIn","file":"GpApiConnector.java","line":124,"exact":false,"location":"globalpayments-sdk-11.1.24.jar","version":"?"},{"class":"com.global.api.gateways.GpApiConnector","method":"processReport","file":"GpApiConnector.java","line":300,"exact":false,"location":"globalpayments-sdk-11.1.24.jar","version":"?"},{"class":"com.global.api.builders.ReportBuilder","method":"execute","file":"ReportBuilder.java","line":56,"exact":false,"location":"globalpayments-sdk-11.1.24.jar","version":"?"}
Expected Result:
SDK should return ApiException e.g. GatewayException/ConnectionException
Possible Solution:
For a connection failure scenario, signin() method gets GatewayException with null response. But due to the missing else
clause, the library failed to form ApiException in the below method. Resulting above NullPointerException.
GpApiConnector.generateGpApiException()
`
private void generateGpApiException(String responseCode, String responseText) throws GatewayException {
if (!StringUtils.isNullOrEmpty(responseText)) {
JsonDoc parsedResponse = JsonDoc.parse(responseText);
if (parsedResponse.has("error_code")) {
String errorCode = parsedResponse.getString("error_code");
String detailedErrorCode = parsedResponse.getString("detailed_error_code");
String detailedErrorDescription = parsedResponse.getString("detailed_error_description");
throw new GatewayException(String.format("Status Code: %s - %s", responseCode, detailedErrorDescription), errorCode,
detailedErrorCode);
}
}// Missing else clause
}
`
Requesting library maintainers to fix this.
Thanks.
When performing an OTB check and including the security code information, the JSON response includes three fields:
These three fields are detailed in the developer documentation.
However, the Transaction object returned by the RealexConnector only has methods for accessing the CVN Result and the AVS Postcode Response. There is no method for getting the AVS Address Response.
Why is this field missing when it is listed in the documentation?
This should be a common scenario but I could not find any API calls to do this on Global Payments.
Suppose we try to pay something and we then generate and HPP json by doing:
hppJson = service.charge(new BigDecimal(paymentDTO.getAmount()))
.withCurrency(paymentDTO.getCurrency())
.withHostedPaymentData(hostedPaymentData)
.withAddress(billingAddress, AddressType.Billing)
.withAddress(shippingAddress, AddressType.Shipping)
.serialize();
Then after customer gets redirected to the payment page of Global payments, he add card details and pay. If the payment was successful from global payments, it will redirect the user to our specified url. My question is if our services are unavailable when redirecting, is there a way to query that past successful transaction by using anything in that HPP Json? like order ID etc?
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.