Giter Club home page Giter Club logo

checkout-sdk-java's Introduction

Checkout.com Java SDK

build-status CodeQL OWASP-Dependency-Check

build-status GitHub release Maven Central

GitHub license

Getting started

Version 6.0.0 is here!

We improved the initialization of SDK making it easier to understand the available options.
Now NAS accounts are the default instance for the SDK and ABC structure was moved to a previous prefixes.
If you have been using this SDK before, you may find the following important changes:

  • Marketplace module was moved to Accounts module, same for classes and references.
  • In most cases, IDE can help you determine from where to import, but if you’re still having issues don't hesitate to open a ticket.

Gradle

dependencies {
    implementation 'com.checkout:checkout-sdk-java:<version>'
}

Maven

<dependency>
    <groupId>com.checkout</groupId>
    <artifactId>checkout-sdk-java</artifactId>
    <version>version</version>
</dependency>

🚀 Please check in GitHub releases for all the versions available.

📖 Checkout our official documentation.

📚 Check out our official API documentation guide, where you can also find more usage examples.

How to use the SDK

This SDK can be used with two different pair of API keys provided by Checkout. However, using different API keys imply using specific API features.
Please find in the table below the types of keys that can be used within this SDK.

Account System Public Key (example) Secret Key (example)
Default pk_pkhpdtvabcf7hdgpwnbhw7r2uic sk_m73dzypy7cf3gf5d2xr4k7sxo4e
Previous pk_g650ff27-7c42-4ce1-ae90-5691a188ee7b sk_gk3517a8-3z01-45fq-b4bd-4282384b0a64

Note: sandbox keys have a sbox_ or test_ identifier, for Default and Previous accounts respectively.

If you don't have your own API keys, you can sign up for a test account here.

PLEASE NEVER SHARE OR PUBLISH YOUR CHECKOUT CREDENTIALS.

Default

Default keys client instantiation can be done as follows:

import com.checkout.CheckoutApi;

public static void main(String[] args) {
    
    final CheckoutApi checkoutApi = CheckoutSdk.builder()
            .staticKeys()
            .publicKey("public_key")  // optional, only required for operations related with tokens
            .secretKey("secret_key")
            .environment(Environment.PRODUCTION)  // required
            .environmentSubdomain("subdomain") // optional, Merchant-specific DNS name
            .executor() // optional for a custom Executor Service
            .build();
    
    final PaymentsClient client = checkoutApi.paymentsClient();
    
    final CompletableFuture<RefundResponse> refundPayment = client.refundPayment("payment_id");
}

Default OAuth

The SDK supports client credentials OAuth, when initialized as follows:

import com.checkout.CheckoutApi;

public static void main(String[] args) {

final CheckoutApi checkoutApi = CheckoutSdk.builder()
        .oAuth()
        .clientCredentials("client_id", "client_secret")
        // for a specific authorization endpoint
        //.clientCredentials(new URI("https://access.sandbox.checkout.com/connect/token"), "client_id", "client_secret")
        .scopes(OAuthScope.GATEWAY, OAuthScope.VAULT, OAuthScope.FX)
        .environment(Environment.PRODUCTION)  // required
        .environmentSubdomain("subdomain") // optional, Merchant-specific DNS name
        .executor() // optional for a custom Executor Service
        .build();

final PaymentsClient client = checkoutApi.paymentsClient();

final CompletableFuture<RefundResponse> refundPayment = client.refundPayment("payment_id");
}

Previous

If your pair of keys matches the Previous type, this is how the SDK should be used:

import com.checkout.previous.CheckoutApi;

public static void main(String[] args) {
    final CheckoutApi checkoutApi = CheckoutSdk.builder()
            .previous()
            .staticKeys()
            .publicKey("public_key")  // optional, only required for operations related with tokens
            .secretKey("secret_key")
            .environment(Environment.PRODUCTION)  // required
            .environmentSubdomain("subdomain") // optional, Merchant-specific DNS name
            .executor() // optional for a custom Executor Service
            .build();
    
    final PaymentsClient client = checkoutApi.paymentsClient();
    
    final CompletableFuture<RefundResponse> refundPayment = client.refundPayment("payment_id");
        }

Custom Environment

In case that you want to use an integrator or mock server, you can specify your own configuration as follows:

final CustomEnvironment environment = CustomEnvironment.builder()
        .checkoutApi(create("https://the.base.uri/")) // the uri for all Checkout operations
        .oAuthAuthorizationApi(create("https://the.oauth.uri/connect/token")) // the uri used for OAUTH authorization, only required for OAuth operations
        .filesApi(create("https://the.files.uri/")) // the uri used for Files operations, only required for Accounts module
        .transfersApi(create("https://the.transfers.uri/")) // the uri used for Transfer operations, only required for Transfers module
        .balancesApi(create("https://the.balances.uri/")) // the uri used for Balances operations, only required for Balances module
        .sandbox(false) // flag to determine if Sanbox or Production configured, default false
        .build();

final CheckoutApi checkoutApi = CheckoutSdk.builder()
        .staticKeys()
        .secretKey("secret_key")
        .environment(environment)  // required
        .executor(customHttpClient) // optional for a custom Executor Service
        .build();

You don't need to specify all the previous URI's, only the ones for the modules that you're going to use.

Custom HttpClient

Sometimes you need a custom thread pool, or any custom http property, so you can provide your own httpClient configuration as follows.

final HttpClientBuilder customHttpClient = HttpClientBuilder.create()
        .setProxy(HttpHost.create("https://proxy"))
        .setConnectionTimeToLive(3, TimeUnit.SECONDS);

final CheckoutApi checkoutApi = CheckoutSdk.builder()
        .staticKeys()
        .secretKey("secret_key")
        .environment(Environment.PRODUCTION)  // required
        .environmentSubdomain("subdomain") // optional, Merchant-specific DNS name
        .httpClientBuilder(customHttpClient) // optional for a custom HttpClient
        .build();

Logging

The SDK supports SLF4J as logger provider, you need to provide your configuration file through resources folder.

Exception handling

All the API responses that do not fall in the 2** status codes will cause a CheckoutApiException. The exception encapsulates the responseHeaders, httpStatusCode and a map of errorDetails, if available.

Building from source

Once you check out the code from GitHub, the project can be built using Gradle:

gradlew build

# skip tests
gradlew build -x test

The execution of integration tests require the following environment variables set in your system:

  • For default account systems (NAS): CHECKOUT_DEFAULT_PUBLIC_KEY & CHECKOUT_DEFAULT_SECRET_KEY
  • For default account systems (OAuth): CHECKOUT_DEFAULT_OAUTH_CLIENT_ID & CHECKOUT_DEFAULT_OAUTH_CLIENT_SECRET
  • For Previous account systems (ABC): CHECKOUT_PREVIOUS_PUBLIC_KEY & CHECKOUT_PREVIOUS_SECRET_KEY

Code of Conduct

Please refer to Code of Conduct

Licensing

MIT

checkout-sdk-java's People

Contributors

a-ibarra avatar alegladchteinparser avatar ariskk avatar armando-rodriguez-cko avatar armandojaleo avatar bscetbun-bc avatar cko-developer-portal[bot] avatar cloverzrg avatar diaodiaofly avatar dlabey avatar harry-peirse avatar harry-seriousstudios avatar i-srinivas avatar ioan-ghisoi avatar ioan-ghisoi-cko avatar kdrakon avatar louis-tw avatar martinseco avatar nicolas-maalouf-cko avatar nishanthvijayan avatar rsaestrela avatar sansnom avatar stephen-gilbert-cko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

checkout-sdk-java's Issues

The SDK doesn't support the dispute APIs

I need to be able to retrieve a dispute via API.

As well, I need to pull the dispute object because the dispute webhook does not provide the dispute amount.

Both strangely missing on a great product and API.

Getter For Gson Configuration in GsonSerializer

Description

We are building a Checkout.com simulator for internal load testing with Spring Boot and are setting the JSON mapper to use GSON instead of the default Jackson implementation. We are using the Checkout.com SDK for our objects. Instead of having to copy and paste the GSON configuration stored in GsonSerializer it would be ideal if GsonSerializer could be a public class with a getter for the Gson object and/or the GsonBuilder object so it could be extended.

Proposed Solution

  • Make GsonSerializer a public class

  • Add a public getter for Gson

  • Add a public getter for GsonBuilder

  • I may be able to implement this feature

Add ability to configure default response status code for ApacheHttpClientTransaport in performCall

Environment

  • Checkout SDK version: 6.0.26
  • Platform and version: Java 8
  • Operating System and version: Amazon Linux 2

Description

In the ApacheHttpClientTransport class of the Checkout SDK, in the performCall method, the default catch-all status code for the response is a bad request (400); this is thrown for a SocketTimeoutException for example. We want this status code to be customizable with the ability to provide an alternate status code, such as an internal server error (500) or gateway timeout (504).

Proposed Solution

Could you provide a way to customize this with the configuration object, with the default being the existing bad request and the ability to pass a custom status code?

  • I may be able to implement this feature

Please provide way to define own thread pool

Hi,

a suggestion. Can you please provide a possibility to define our own thread pool.

This has following advantages:

  • Thread pool independent of fork join pool, which has a fixed size and shared with the JVM. If something goes wrong elsewhere payments are not possible anymore.
  • clear naming of threads to distinguish them (especially in case where something goes wrong or is stuck)

Best regards

Previous - List payments from a payout

Environment

  • Checkout SDK version: 6.0.19
  • Platform and version: JDK 17
  • Operating System and version: Alpine 3.8

Description

Proposed Solution

Currently, the statement API allows listing payouts, but there's no way to query the payments for a specific payout through this SDK.

Workaround: Use the REST interface directly

  • I may be able to implement this feature

Need to understand the impact of new api key generation

Environment

  • Checkout SDK version: Currently we are on 2.0.10 and trying to move to 6.0.20
  • Platform and version: Java sdk
  • Operating System and version:

Description

Need to understand the impact of new api key generation

  • For our system if we move to version upgrade we need to re generate our api keys as well - (Let me know if this understanding is correct)
  • Now if we re generate the new api key what will happen to the old payment refund request will that be processed on this new api key?
  • Is there a way to do gradual change instead of big boom deployment while doing the version upgrade.

Expected behavior

  • we expect system to process the old api generated refund requests as well for backward compatibility.

Current behavior

Steps to reproduce

pendingStatus and requires Redirect Link

Hi Team,

How do we find whether the payment is in pending status and if it requires a redirection, how to get the redirect link for the payment?

In the previous SDK version 3.6.0, there would be PaymentPending object which gives the information of redirection and redirection link of the payment.

Add financial action reports API integration

Environment

  • Checkout SDK version: 6.0.19
  • Platform and version:
  • Operating System and version: Darwin Kernel Version 22.4.0

Description

The API has an endpoint to list of actions applied to the payment. This SDK doesn't have that endpoint implemented. The only workaround is to manually implement using another RestClient library.

Proposed Solution

Add another client to the reports API to support this endpoint: https://api-reference.checkout.com/#operation/getFinancialActions

  • I may be able to implement this feature

Unability to cancel request or handle connection timeout

Underlying transport implementation uses plain HttpURLConnection. This object has configurable connection and read timeouts:

connection.setConnectTimeout(connectionTimeout);
connection.setReadTimeout(readTimeout);

But this is not configurable via API so in fact we always use default connection/read timeout (unlimited). We can use CompletableFuture.get(long, TimeUnit) for getting the result with timeout but since this task cannot be cancelled in any way the request can complete fine.

We can fall into situation that we will timeout our request and tell customer back that it failed but then we will get payment_captured event. How to handle such situations? This makes this API rather not usable

webhook signature verification problem

When receiving webhook notification, we use EventResponse to receive it, but there is a problem that we want to hash it to generate HMAC. At this time, should we hash it with EventResponse.getData() and the provided key to generate HMAC or directly use EventResponse Hashing it with the supplied key to generate the HMAC?

No merchant_initiated field in PaymentRequest bean

In this doc say, you must set to true in all merchant-initiated transactions.But i can't find the field in https://github.com/checkout/checkout-sdk-java/blob/dev/src/main/java/com/checkout/payments/PaymentRequest.java,

doc:https://docs.checkout.com/quickstart/use-an-existing-card/stored-card-details

`DisputesClient` rejecting `java.time.Instant`'s in `DisputesQueryFilter`

Environment

  • Checkout SDK version: 5.4.0

Description

When using the disputes client query method, with the parameter of a DisputesQueryFilter, the client gets a rejection from the REST API when specifying the from and/or to fields (which are of type java.time.Instant).

Expected behavior

The client should accept the Instant values set for from and to and return any disputes updated within the time window.

Current behavior

For example, assuming now is from Instant.now(), the following filter will fail:

DisputesQueryFilter.builder().from(now.minusSeconds(3600)).to(now).build()

The Java exception returned is like this:

CheckoutApiException(requestId=0HMF57UGVGS7I:00000014, httpStatusCode=422, errorDetails={request_id=0HMF57UGVGS7I:00000014, error_type=request_invalid, error_codes=[paging_from_invalid_format, paging_to_invalid_format]})

Debugging the parameters built from the builder, I can see the following is being sent to the REST API:
image
Notice the precision after the seconds.

If I modify now to be now.truncatedTo(ChronoUnit.SECONDS), the parameters change to:
image
and the request succeeds.

In conclusion, it looks like the CKO REST API does not like the additional precision of the ISO8601 timestamp and thus rejecting it as a paging_from_invalid_format or paging_to_invalid_format.

Possible solution

It seems wrong for the client code to truncate the exact Instant that the implementor is creating. To me, it seems the REST API is incorrectly rejecting the timestamp because they are in fact ISO8601 compatible, albeit a little more precise.

Missing enum value authorised_signatory in EntityRoles

Environment

  • Checkout SDK version: 6.1.2 (latest)

Description

Missing enum value authorised_signatory in EntityRoles.

Steps to reproduce

Create a sub entity. Use the AccountsClient#getEntity and see that Representative#getRoles return null when the representative is an authorized signatory.

Possible solution

#404

Thanks.

PlatformType.CLASSIC pattern error

CLASSIC("^sk_([a-z]+)_(\\w{8})-(\\w{4})-(\\w{4})-(\\w{4})-(\\w{12})$", "^pk_([a-z]+)_(\\w{8})-(\\w{4})-(\\w{4})-(\\w{4})-(\\w{12})$"),

production secretKey and publicKey validate error

NoHttpResponseException not bubbled up by ApacheHttpClientTransport, returns 400 instead

Hi,

It appears that the ApacheHttpClientTransport is not properly bubbling up NoHttpResponseException and instead returning a 400. This makes it difficult to properly handle and retry requests without having to retry on all 400 errors.

Is it possible to have the ApacheHttpClientTransport either bubble up the exception or return a 5xx http code when a NoHttpResponseException is encountered?

log.error("Exception occurred during the execution of the client...", e);

org.apache.http.NoHttpResponseException: api.checkout.com:443 failed to respond
	at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:141)
	at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
	at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
	at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163)
	at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:157)
	at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)
	at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272)
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
	at com.checkout.ApacheHttpClientTransport.performCall(ApacheHttpClientTransport.java:154)
	at com.checkout.ApacheHttpClientTransport.lambda$invoke$1(ApacheHttpClientTransport.java:110)
	at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768)
	at java.base/java.lang.Thread.run(Thread.java:833)

Thanks for you help

Production secret keys don't match the regex

Environment

  • Checkout SDK version: 6.0.19
  • Platform and version:
  • Operating System and version: Darwin Kernel Version 22.4.0

Description

Using the existing 2 years old production secret keys, the regex defined at com.checkout.StaticKeysSdkCredentials.SECRET_KEY_PATTERN doesn't validate my keys.

Expected behavior

It should accept these old keys, since they are still valid when executing curl commands or with manual java rest client implementations.

Current behavior

The library throws a CheckoutArgumentException("invalid secret key");

Steps to reproduce

Create a CheckoutApi using the builder new CheckoutSdkBuilder().staticKeys().secretKey("my-private-key").environment(Environment.PRODUCTION).build();

Possible solution

Improve the regex to support these keys. Since I don't know their pattern (only my own), I cannot ensure the solution is valid for all keys.

  • I may be able to implement this bug fix

Additional information

Support for AFT in Previous API PaymentRequest

Environment

  • Checkout SDK version: 6.0.10
  • Platform and version: Any (Checkout Previous API)
  • Operating System and version: Any

Description

Based on the official Previous Documentation for AFT, the field processing.senderInformation is required for VISA transactions. However, PaymentRequest for previous API has no such field, thus Checkout SDK for Java (as of version 6.0.10) can not be used to perform AFT.

The attribute already exists as simply sender on the new API PaymentRequest.

Proposed Solution

Please add processing.senderInformation attribute to Previous API PaymentRequest.

Throwing ExecutionException instead of CheckoutApiException

Environment

  • Checkout SDK version: 6.0.2
  • Platform and version: Java 11
  • Operating System and version: Linux

Description

When executing a payment request crafted to provoke an error an ExecutionException is thrown instead of a CheckoutApiException.

Expected behavior

A CheckoutApiException should be thrown.

Current behavior

An ExecutionException is thrown.

Steps to reproduce


        final CheckoutApi checkoutApi = CheckoutSdk.builder()
                                                   .staticKeys()
                                                   .secretKey(SECRET_KEY)
                                                   .environment(Environment.SANDBOX)  // required
                                                   .build();

        final RequestCardSource source = RequestCardSource.builder()
                                                    .number("4242424242424242")
                                                    .expiryMonth(10)
                                                    .expiryYear(2027)
                                                    .cvv("987")
                                                    .stored(false)
                                                    .build();

        final PaymentIndividualSender sender = PaymentIndividualSender.builder()
                                                                .firstName("Foo")
                                                                .lastName("Bar")
                                                                .build();

        final ThreeDSRequest threeDSRequest = ThreeDSRequest.builder()
                                                      .enabled(false)
                                                      .challengeIndicator(ChallengeIndicator.NO_CHALLENGE_REQUESTED)
                                                      .build();

        final PaymentRequest request = PaymentRequest.builder()
                                               .source(source)
                                               .sender(sender)
                                               .capture(false)
                                               .reference("reference")
                                               .amount(999L)
                                               .threeDS(threeDSRequest)
                                               .successUrl("https://docs.checkout.com/success")
                                               .failureUrl("https://docs.checkout.com/failure")
                                               .build();

        try {
            PaymentResponse response = checkoutApi.paymentsClient().requestPayment(request).get();
            System.out.println(response.getSchemeId());
        } catch (CheckoutApiException e) {
            // API error
            String requestId = e.getRequestId();
            int statusCode = e.getHttpStatusCode();
            Map<String, Object> errorDetails = e.getErrorDetails();
            e.printStackTrace();
        } catch (CheckoutArgumentException e) {
            // Bad arguments
            e.printStackTrace();
        } catch (CheckoutAuthorizationException e) {
            // Invalid authorization
            e.printStackTrace();
        }
        catch (ExecutionException e){
            //Future error
            e.printStackTrace();
        }


PaymentType lost 'SUBSCRIPTION' value

Sample webhook:

{
    "id": "evt_vzpfnvvbqfmefpjlns5znj2opu",
    "type": "payment_approved",
    "created_on": "2020-12-02T10:54:57Z",
    "data": {
        "action_id": "act_4h6yqwomkzmezn7qbpbden6kvm",
        "payment_type": "SUBSCRIPTION",
        "auth_code": "739301",
        "response_code": "10000",
        "response_summary": "Approved",
        "scheme_id": "100742343895990",
        "3ds": {
            "downgraded": false,
            "enrolled": "Y",
            "signature_valid": "Y",
            "authentication_response": "Y",
            "eci": "02",
            "cavv": "hv8mUFzPzRZoCAAAAAEQBDMAAAA=",
            "xid": "MDAwMDAwMDAwMDAwMDAwMzIyNzY="
        },
        "source": {
            "id": "src_x633r7e6ox6ephctmtgrah65jm",
            "type": "card",
            "billing_address": {},
            "expiry_month": 5,
            "expiry_year": 2030,
            "name": "test name",
            "scheme": "MASTERCARD",
            "last_4": "3404",
            "fingerprint": "e3d8eed03133dc7a3be8f1b446596ae99bdcf67a4d1bd4c56285182d00e1a0eb",
            "bin": "535215",
            "card_type": "Debit",
            "card_category": "Commercial",
            "issuer": "JSB PIVDENNYI",
            "issuer_country": "UA",
            "product_id": "MDT",
            "product_type": "Commercial Debit MasterCard® Card",
            "avs_check": "S",
            "cvv_check": "Y"
        },
        "customer": {
            "id": "cus_dhfgh2pngviudjou5daemmdmx4",
            "email": "[email protected]"
        },
        "processing": {
            "acquirer_transaction_id": "3300105946",
            "retrieval_reference_number": "499966563601"
        },
        "amount": 23999,
        "metadata": {
            "userId": "143820"
        },
        "risk": {
            "flagged": false
        },
        "id": "pay_4h6yqwomkzmezn7qbpbden6kvm",
        "currency": "USD",
        "processed_on": "2020-12-02T10:54:57Z",
        "reference": "9462"
    },
    "_links": {
        "self": {
            "href": "https://api.sandbox.checkout.com/events/evt_vzpfnvvbqfmefpjlns5znj2opu"
        },
        "payment": {
            "href": "https://api.sandbox.checkout.com/payments/pay_4h6yqwomkzmezn7qbpbden6kvm"
        }
    }
}

As you see, in field payment_type value "SUBSCRIPTION",

Class com.checkout.payments.PaymentType hasn't this value.

About webhook signatures

Hello @armandojaleo @rsaestrela @ariskk @harry-peirse

Can you help me generate Cko-Signature?
The data is as follows

{
"id": "evt_az5sblvku4ge3dwpztvyizgcau",
"type": "authorization_approved",
"version": "2.0.0",
"created_on": "2019-08-24T14:15:22Z",
"data": {
"card_id": "crd_fa6psq242dcd6fdn5gifcq1491",
"transaction_id": "trx_y3oqhf46pyzuxjbcn2giaqnb44",
"transaction_type": "purchase",
"transmission_date_time": "2018-04-10T08:12:14Z",
"authorization_type": "pre_authorization",
"transaction_amount": 1000,
"transaction_currency": "GBP",
"billing_amount": 900,
"billing_currency": "EUR",
"billing_conversion_rate": 0.925643,
"ecb_conversion_rate": 0.9,
"merchant": {
"name" : "Carrefour",
"city": "Paris",
"state": "",
"country": "FRA",
"category_code": "5021"
}
}
}

Signature Key:12345678

I generated the sgnature:c506e5dd7f6c28eeef505be9057c71f6c5e858436ce1143ffc522143b3b8f869

I would like to know why the Signature I generated is different from the cko-signature webhook sent me!

Is the data sorted or otherwise processed in the background before SHA-256 is applied to the data?

Add applepay and googlepay to public enum PaymentSourceType

Add applepay and googlepay to public enum PaymentSourceType

Description

Purpose: to allow merchants only display applepay or googlepay if they wish so.
In the API reference, there is a allow_payment_methods field to allow merchants only display applepay or googlepay, but these two are not in the enum PaymentSourceType, therefore merchants are not able to have applepay or googlepay only in src/main/java/com/checkout/payments/hosted/HostedPaymentRequest.java

Proposed Solution

Add applepay and googlepay to public enum PaymentSourceType
Screenshot 2024-06-27 at 12 17 20 PM

Testing Pull Requests

Currently the test suite requires credentials to run against the Checkout.com sandbox. These have particular access in order to call all endpoints and so should be protected. They are therefore stored in secure environment variables in TravisCI.
This means that pull request builds will always fail, as to protect the variables TravisCI does not allow them to be used by pull request builds.
We need to consider the options and make a decision how to proceed... do we find another way of testing pull requests, or always merge to dev in order to run the tests?

CheckoutSettings.getProviderMode()' on a null object reference

Hello checkout team.
we are getting this error on some devices also we provide all the necessary details while initialise the sdk.

binding.checkoutCardForm.set3DSListener(m3DSecureListener)
            .setEnvironment(if (BuildConfig.DEBUG) Environment.SANDBOX else Environment.LIVE)
            .setKey(if (BuildConfig.DEBUG) BuildConfig.PAYMENT_GATEWAY_ENVIRONMENT_SANDBOX else BuildConfig.PAYMENT_GATEWAY_ENVIRONMENT_LIVE)

Fatal Exception: java.lang.NullPointerException
Attempt to invoke virtual method 'com.oppwa.mobile.connect.provider.Connect$ProviderMode com.oppwa.mobile.connect.checkout.meta.CheckoutSettings.getProviderMode()' on a null object reference.
com.oppwa.mobile.connect.checkout.dialog.BaseServiceActivity$1.onServiceConnected (Unknown Source:55)

please reply us ASAP our app is already in production mode.

GSON Serialisation of Instants throws java.time.format.DateTimeParseException

Payout Request via Java SDk:
PayoutRequest request = PayoutRequest.builder().sender(sender)
.destination(destination )
.source(source)
.reference(tx.getID())
.instruction(instruction )
.amount((long)(tx.getRedemptionAmount()*100.0d))
.currency(Currency.valueOf(tx.getCurrency()))
.billingDescriptor(PayoutBillingDescriptor.builder().purpose("Payout to Card").build())
.processingChannelId(utils.getCheckoutChannelID())
.build();

PayoutResponse response = api.paymentsClient().requestPayout(request).get();

Throws java.util.concurrent.ExecutionException: java.time.format.DateTimeParseException: Text '2022-07-21T06:23:24.5582454+00:00' could not be parsed at index 27java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:395)
java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1999)

Probable cause:
[com/checkout/GsonSerializer.java]

Instant.parse("2022-07-21T06:23:24.5582454+00:00") -- fails as it is not compatible with DateTimeFormatter.ISO_INSTANT

If this is the format the service returns the values should be serialised as such:

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSXXX");
LocalDateTime dateTime = LocalDateTime.parse("2022-07-21T06:23:24.5582454+00:00", dtf);
dateTime.atZone(ZoneId.systemDefault()).toInstant();

Although ideally the service should return a date in a format that is compatible with the calling agent (ie Java)

SDK doesn't support KNET payments

The latest version of the SDK doesn't have the provision to create KNET payment requests

Environment

Checkout SDK version: 5.9.6

Description

com.checkout.common.PaymentSourceType doesn't define source type for KNET. So it is not possible to create a source for KNET payments. The checkout API for KNET payments requires the source type to be "knet"

Expected behavior

com.checkout.common.PaymentSourceType should have an enum defined for KNET

Current behavior

PaymentSourceType doesn't define a source type for KNET payments

Possible solution

Define source type "knet" in com.checkout.common.PaymentSourceType

  • I may be able to implement this bug fix

Instrument Api missing Customer and Account Holder

The com.checkout.instruments.CreateInstrumentRequest class is missing both Customer and AccountHolder elements, and looking at CustomerRequest within the instrument package it's missing name, email and phone. Can these classes be updated?

When receiving webhook notification, links are not populated in body

Environment

  • Checkout SDK version: 3.7.0
  • Platform and version: Java 11
  • Operating System and version: AWS EC2 (Code Deploy)

Description

Receiving the webhook notification, when doing EventReponse.toString:
EventResponse(super=Resource(links={}, apiResponseInfo=null), id=evt_onvtqgdbw6curni7ihxi656il4, type=payment_refunded, version=1.0.12, createdOn=null, data={id=pay_gvw2v3jsqs5ehhqlq6bx5mqxeq, action_id=act_qklvzmfjzzrehgt3zustqcccea, reference=530999799294, amount=3000, processed_on=2022-05-17T13:57:02.8313545Z, response_code=10000, response_summary=Approved, balances={total_authorized=3000, total_voided=0, available_to_void=0, total_captured=3000, available_to_capture=0, total_refunded=3000, available_to_refund=0}, metadata={}, currency=GBP, processing={acquirer_transaction_id=732721172871362484022, acquirer_reference_number=33030362117614996567884}}, notifications=null)
or using GsonSerializer.toJson:
{"id":"evt_onvtqgdbw6curni7ihxi656il4","type":"payment_refunded","version":"1.0.12","data":{"id":"pay_gvw2v3jsqs5ehhqlq6bx5mqxeq","action_id":"act_qklvzmfjzzrehgt3zustqcccea","reference":"530999799294","amount":3000,"processed_on":"2022-05-17T13:57:02.8313545Z","response_code":"10000","response_summary":"Approved","balances":{"total_authorized":3000,"total_voided":0,"available_to_void":0,"total_captured":3000,"available_to_capture":0,"total_refunded":3000,"available_to_refund":0},"metadata":{},"currency":"GBP","processing":{"acquirer_transaction_id":"732721172871362484022","acquirer_reference_number":"33030362117614996567884"}},"_links":{}}
in both instances the links are not populated, while looking at webhook.site the links are there:
{ "id": "evt_onvtqgdbw6curni7ihxi656il4", "type": "payment_refunded", "version": "1.0.12", "created_on": "2022-05-17T13:57:05.9639092Z", "data": { "id": "pay_gvw2v3jsqs5ehhqlq6bx5mqxeq", "action_id": "act_qklvzmfjzzrehgt3zustqcccea", "reference": "530999799294", "amount": 3000, "processed_on": "2022-05-17T13:57:02.8313545Z", "response_code": "10000", "response_summary": "Approved", "balances": { "total_authorized": 3000, "total_voided": 0, "available_to_void": 0, "total_captured": 3000, "available_to_capture": 0, "total_refunded": 3000, "available_to_refund": 0 }, "metadata": {}, "currency": "GBP", "processing": { "acquirer_transaction_id": "732721172871362484022", "acquirer_reference_number": "33030362117614996567884" } }, "_links": { "self": { "href": "https://api.sandbox.checkout.com/workflows/events/evt_onvtqgdbw6curni7ihxi656il4" }, "subject": { "href": "https://api.sandbox.checkout.com/workflows/events/subject/pay_gvw2v3jsqs5ehhqlq6bx5mqxeq" } } }

Expected behavior

The links would be populated when receiving the webhook notification. This allows to match CKO-Signature key.

Current behavior

Links are not populated and we fail to match CKO-Signature as when hashing the response body our hashed value is different than the provided header.

Steps to reproduce

Controller used:

    /**
     * POST /acquirer/checkout/webhook/event : handleAcquirerEventForCheckout
     *
     * @param eventResponse EventResponse (required)
     * @param ckoSignature Cko-Signature (optional)
     * @return Event successfully invoked. (status code 200)
     *         or Internal Server Error. (status code 500)
     */
    @ApiOperation(value = "handleAcquirerEventForCheckout", nickname = "handleAcquirerEventForCheckout", notes = "", response = String.class, tags={ "acquirer-controller", })
    @ApiResponses(value = { 
        @ApiResponse(code = 200, message = "Event successfully invoked.", response = String.class),
        @ApiResponse(code = 500, message = "Internal Server Error.", response = RestError.class) })
    @RequestMapping(
        method = RequestMethod.POST,
        value = "/acquirer/checkout/webhook/event",
        produces = { "application/json" },
        consumes = { "application/json" }
    )
    default ResponseEntity<String> handleAcquirerEventForCheckout(@ApiParam(value = "EventResponse", required = true) @Valid @RequestBody com.checkout.events.EventResponse eventResponse,@ApiParam(value = "Cko-Signature") @RequestHeader(value = "Cko-Signature", required = false) String ckoSignature) {
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);

    }

and the implementation:

@Override
    public ResponseEntity<String> handleAcquirerEventForCheckout(EventResponse eventResponse, String ckOSignature) {
        log.info("handleAcquirerEventForCheckout:+ Event received from acquirer checkout, event: {}", eventResponse.toString());
        acquirerWebhookEventService.handleAcquirerEventForCheckout(eventResponse, ckOSignature);
        log.info("handleAcquirerEventForCheckout:- Event successfully invoked.");
        return ResponseEntity.ok().body("Event successfully invoked.");
    }

Possible solution

  • I may be able to implement this bug fix

Additional information

Card Type & Card Category SerializeName for Upper Case value

Card Type & Card Category SerializeName for Upper Case value

Environment

  • Checkout SDK version: 5.0.0
  • Platform and version: JDK 8
  • Operating System and version: Mac OS Monterey

Description

Respone cardType=null, cardCategory=null within com.checkout.instruments.four.create.CreateInstrumentTokenResponse

Expected behavior

Expecting to serialize value regardless upper case or lower case

Current behavior

Response null for cardType, cardCategory

Steps to reproduce

Request POST instruments API with a frames token (tok_), test card 4242 4242 4242 4242

Possible solution

Update value serialization to handle both uppercase and lowercase

  • I may be able to implement this bug fix

Additional information

{
"id": "src_zopuwjvpu4qerfas4rtbdq474u",
"type": "card",
"fingerprint": "918F0A098B1515A2860835C73550F40D0A2FAE9599F68AD969FEE893D81C51B1",
"expiry_month": 12,
"expiry_year": 2021,
"scheme": "VISA",
"last4": "4242",
"bin": "424242",
"card_type": "CREDIT",
"card_category": "CONSUMER",
"issuer": "JPMORGAN CHASE BANK NA",
"issuer_country": "US",
"product_id": "A",
"product_type": "Visa Traditional",
"customer": {
"id": "cus_z6qkm7xgqu3epa6pgj4a543lgm",
"name": "li mo",
"email": "[email protected]"
}
}

CreateInstrumentTokenResponse(super=CreateInstrumentResponse(id=src_gbpkdyguqtsenirm5ommyb2ttu), type=CARD, fingerprint=A730033CF77DE08C5BCED09FF3CE9919E4A9B5A117F2F0A2A61BCBA13E848DC8, expiryMonth=3, expiryYear=2033, scheme=VISA, last4=4242, bin=424242, cardType=null, cardCategory=null, issuer=JPMORGAN CHASE BANK NA, issuerCountry=US, productId=A, productType=Visa Traditional, customer=CustomerResponse(id=cus_vcuh4v44cu7ethfbhsagtayfla, email=[email protected], name=James))

Supporting merchant_category_code under Processing

Environment

  • Checkout SDK version: 6.2.1
  • Platform and version: Java SDK
  • Operating System and version: N/A

Description

Hello Team, Remitly (T1) have started processing transactions under 2 MCCs, and would like to have the ability to consume the MCC as part of the response. I'm aware that it is currently not listed in the API reference, and this is something that I have raised with our docs team to get it resolved. It is however listed under the 'GET Payment Details', and has the same type:
https://api-reference.checkout.com/#operation/getPaymentDetails!c=200&path=0/processing/merchant_category_code&t=response

Proposed Solution

Adding merchant_category_code under https://github.com/checkout/checkout-sdk-java/blob/master/src/main/java/com/checkout/payments/PaymentProcessing.java

Support partner_merchant_advice_code in Payment Response

Support adding processing.partner_merchant_advice_code, if available in response

Environment

  • Checkout SDK version: 6.0.19
  • Platform and version: Java SDK
  • Operating System and version: N/A

Description

An issuer can provide additional MasterCard advice code that could help merchant in further processing the payment transaction.

For example, partner_merchant_advice_code=24 could help merchant to ensure declined/rejected transaction can be retried after an hour.

https://www.checkout.com/docs/developer-resources/testing/codes/recommendation-codes

Proposed Solution

Add a field as below and update related tests
https://github.com/checkout/checkout-sdk-java/blob/master/src/main/java/com/checkout/payments/PaymentProcessing.java

@SerializedName("partner_merchant_advice_code") private String partnerMerchantAdviceCode;

  • [X ] I may be able to implement this feature

Apache core 5 support (Spring Boot 3)

Environment

  • Checkout SDK version: 6.0.19
  • Platform and version: Java SDK and Spring Boot App
  • Operating System and version: N/A

Description

We are migrating our app from spring boot 2.X to spring boot 3.X. A major change is the use of org.apache.hc.core5.http instead of org.apache.http.

In our app we are using the CheckoutSdk.builder() to instantiate a CheckoutApi Bean and we provide it a custom HttpClientBuilder which uses some custom Interceptors.

We are not able to find a way of using the new apache HttpClientBuilder with Checkout SDK. Is it possible to allow/implement the use of the new HttpClientBuilder from org.apache.hc.core5.http ?

Proposed Solution

N/A

Not able to find the new class reference while upgrading to the version from Java sdk 2.3.1 to 6.0.20

Environment

Java sdk old version - 2.3.1 currently

Description

Not able to find the new class reference while upgrading to the version from Java sdk 2.3.1 to 6.0.20

Expected behavior

Current behavior

we do imports:
import com.checkout.payments.CardSourceResponse;
import com.checkout.payments.CustomerRequest;
import com.checkout.payments.PaymentPending;
import com.checkout.payments.PaymentRequest;
import com.checkout.payments.PaymentResponse;
import com.checkout.payments.TokenSource;

Steps to reproduce

use version 2.3.1 and try to call the apis for payment

Possible solution

we need to get the new reference of classes and if the api calls needs restructuring in our side.

[Java SDK] GetPaymentResponse serialisation issue

Environment

  • Checkout SDK version: java SDK ver. 5.8.0,
  • Platform and version: OpenJDK 64-Bit Server VM Corretto-17.0.1.12.1
  • Operating System and version: OSX;

Description

Hi there,

When trying to get a payment data (GET: https://api.checkout.com/payments/pay_wp3dbqulxbimzhmgh4v6xe7msm) using SDK client ( com.checkout.payments.PaymentsClient#getPayment), I’m facing a deserialisation exception below.

Would you please advise on a possible root cause?
Thanks

Caused by: java.lang.RuntimeException: Unable to invoke no-args constructor for interface com.checkout.payments.response.destination.PaymentResponseDestination. Registering an InstanceCreator with Gson for this type may fix this problem.
	at com.google.gson.internal.ConstructorConstructor$14.construct(ConstructorConstructor.java:228)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:212)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
	at com.google.gson.Gson.fromJson(Gson.java:963)
	at com.google.gson.Gson.fromJson(Gson.java:928)
	at com.google.gson.Gson.fromJson(Gson.java:877)
	at com.checkout.GsonSerializer.fromJson(GsonSerializer.java:113)
	at com.checkout.ApiClientImpl.deserialize(ApiClientImpl.java:188)
	at com.checkout.ApiClientImpl.lambda$sendRequestAsync$4(ApiClientImpl.java:171)

Caused by: java.lang.UnsupportedOperationException: Interface can't be instantiated! Interface name: com.checkout.payments.response.destination.PaymentResponseDestination
	at com.google.gson.internal.UnsafeAllocator.assertInstantiable(UnsafeAllocator.java:117)

Expected behavior

GetPaymentResponse properly serialised from json payload.

Current behavior

GSON exception

Bring back `CheckoutSdkBuilder.uri` as a builder parameter

Environment

  • Checkout SDK version: 6.0.2

Description

CheckoutSdkBuilder no longer allows you to specify a uri for the API URI that the client should communicate with. It's now inferred by the Environment enum parameter. Although this ensures the client correctly connects to a valid checkout.com API URI, it limits integrators to use services like MockLab or anything else that can simulate API responses. In CI/CD environment, this means in many cases, integrators are forced to communicate with https://api.sandbox.checkout.com

Proposed Solution

Bring back the ability to provide a URI as an override to the one provided on com.checkout.Environment

GetPaymentResponse source type is incomplete

Environment

  • Checkout SDK version: 6.0.19
  • Platform and version:
  • Operating System and version: Darwin Kernel Version 22.4.0

Description

The payment details endpoint returns the card data, used in the payment, attached to the source field. At this version, the class returns a ResponseSource interface. For the developer, isn't clear that there are other classes who implement this interface, and using a cast to the correct class provides all fields returned by the API.

Proposed Solution

Instead of returning a ResponseSource in the GetPaymentResponse, return a CardResponseSource.

  • I may be able to implement this feature

6.0.0 Where did the recon go?

Environment

  • Checkout SDK version: 6.0.0
  • Platform and version: SANDBOX
  • Operating System and version: Windows

Description

Expected behavior

Recon method still exists in the new 6.0.0 or documentation how to migrate to the new version.

Current behavior

Recon is gone and it seems I should use the classes from .previous package

Steps to reproduce

Upgrade to 6.0.0

Possible solution

  • Deprecated method with docs explaining how to migrate
  • Add migration page

Additional information

MetadataClient not supporting SECRET key authorization

Environment

  • Checkout SDK version: 6.1.0.
  • Platform and version: not_relevant
  • Operating System and version: not_relevant

Description

MetadataClientImpl does not support secret key authorization. This is not in line with your API reference documentation https://api-reference.checkout.com/#tag/Card-metadata .

Expected behavior

MetadataClient would allow usage of secret key authorization same as e.g. PaymentsClientImpl

 public MetadataClientImpl(final ApiClient apiClient, final CheckoutConfiguration configuration) {
        super(apiClient, configuration, SdkAuthorizationType.SECRET_KEY_OR_OAUTH);
    }

Current behavior

 public MetadataClientImpl(final ApiClient apiClient, final CheckoutConfiguration configuration) {
        super(apiClient, configuration, SdkAuthorizationType.OAUTH);
    }

Steps to reproduce

Possible solution

Change of enum passed into to constructor.

  • I may be able to implement this bug fix

Additional information

We can go on low level implementation as basic POST request but we would rather stick to the sdk implementation. Or maybe you can suggest any other way to go around this.

Missing instrument information (name, expiry_monty, expiry_year, last4, bin, card_type) for response type = 'card'

Environment

  • Checkout SDK version: lastest
  • Platform and version: Four, Production
  • Operating System and version: Linux

Description

Missing instrument information (name, expiry_monty, expiry_year, last4, bin, card_type) for response type = 'card'
https://github.com/checkout/checkout-sdk-java/blob/master/src/main/java/com/checkout/instruments/four/get/GetInstrumentResponse.java

Expected behavior

Expect instrument information returned from GET instrument API

Current behavior

No card instrument information

Steps to reproduce

  • Tokenize with Frames with name
  • POST instruments
  • GET instruments

Possible solution

Additional information

Events Tests fail occasionally

I think if we don't run the tests for a while there are not events to retrieve and the 'RetrieveAllEvents' test assumes there'll be something (even if it doesn't care exactly what). Needs a little more looking into.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.