diff --git a/.gitignore b/.gitignore index 63ee138..02a4df0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ # Adding .DS_Store for mac .DS_Store +/bin diff --git a/src/main/java/Data/ConfigurationWithMLE.java b/src/main/java/Data/ConfigurationWithMLE.java index 88dfc8a..d1a5a7c 100644 --- a/src/main/java/Data/ConfigurationWithMLE.java +++ b/src/main/java/Data/ConfigurationWithMLE.java @@ -16,9 +16,16 @@ public static Properties getMerchantDetailsWithMLE1() { props.setProperty("runEnvironment", "apitest.cybersource.com"); props.setProperty("requestJsonPath", "src/main/resources/request.json"); - //Set MLE Settings in Merchant Configuration - props.setProperty("useMLEGlobally", "true"); //globally MLE will be enabled for all MLE supported APIs - props.setProperty("mleKeyAlias", "CyberSource_SJC_US"); //this is optional parameter, not required to set the parameter if custom value is not required for MLE key alias. Default value is "CyberSource_SJC_US". + //Set Request MLE Settings in Merchant Configuration [Refer MLE.md on cybersource-rest-client-java github repo] + props.setProperty("enableRequestMLEForOptionalApisGlobally", "true"); //Enables request MLE globally for all APIs that have optional MLE support //same as older deprecated variable "useMLEGlobally" //APIs that has MLE Request mandatory is default has MLE support in SDK without any configuration but support with JWT auth type. + props.setProperty("requestMleKeyAlias", "CyberSource_SJC_US"); //this is optional parameter, not required to set the parameter if custom value is not required for MLE key alias. Default value is "CyberSource_SJC_US". //same as older deprecated variable "mleKeyAlias" + + //Set Response MLE Settings in Merchant Configuration [Refer MLE.md on cybersource-rest-client-java github repo] + props.setProperty("enableResponseMleGlobally", "false"); //Enables/Disable response MLE globally for all APIs that support MLE responses + props.setProperty("responseMlePrivateKeyFilePath", ""); //Path to the Response MLE private key file. Supported formats: .p12, .pfx, .pem, .key, .p8. Recommendation use encrypted private Key (password protection) for MLE response. + props.setProperty("responseMlePrivateKeyFilePassword", ""); //Password for the private key file (required for .p12/.pfx files or encrypted private keys). + props.setProperty("responseMleKID", ""); //This parameter is optional when responseMlePrivateKeyFilePath points to a CyberSource-generated P12 file. If not provided, the SDK will automatically fetch the Key ID from the P12 file. If provided, the SDK will use the user-provided value instead of the auto-fetched value. + //Required when using PEM format files (.pem, .key, .p8) or when providing responseMlePrivateKey object directly. // MetaKey Parameters props.setProperty("portfolioID", ""); @@ -71,54 +78,29 @@ public static Properties getMerchantDetailsWithMLE2() { props.setProperty("merchantID", "testrest"); props.setProperty("runEnvironment", "apitest.cybersource.com"); - props.setProperty("requestJsonPath", "src/main/resources/request.json"); - //Set MLE Settings in Merchant Configuration - Map mleMap = new HashMap<>(); - mleMap.put("createPayment", false); //only createPayment function will have MLE=false i.e. (/pts/v2/payments POST API) out of all MLE supported APIs - mleMap.put("capturePayment", true); //capturePayment function will have MLE=true i.e. (/pts/v2/payments/{id}/captures POST API), if it not in list of MLE supportedAPIs else it will already have MLE=true by global MLE parameter. + //Set Request MLE Settings in Merchant Configuration [Refer MLE.md on cybersource-rest-client-java github repo] + Map mleMap = new HashMap<>(); + mleMap.put("createPayment", "false"); //only createPayment function will have MLE=false i.e. (/pts/v2/payments POST API) out of all MLE supported APIs + mleMap.put("capturePayment", "true"); //capturePayment function will have MLE=true i.e. (/pts/v2/payments/{id}/captures POST API), if it not in list of MLE supportedAPIs else it will already have MLE=true by global MLE parameter. - props.setProperty("useMLEGlobally", "true"); //globally MLE will be enabled for all MLE supported APIs + props.setProperty("enableRequestMLEForOptionalApisGlobally", "true"); //Enables request MLE globally for all APIs that have optional MLE support //same as older deprecated variable "useMLEGlobally" props.put("mapToControlMLEonAPI", mleMap); //disable or enable the MLE for APIs which is in the list of mleMAP - props.setProperty("mleKeyAlias", "CyberSource_SJC_US"); //this is optional parameter, not required to set the parameter if custom value is not required for MLE key alias. Default value is "CyberSource_SJC_US". + props.setProperty("requestMleKeyAlias", "CyberSource_SJC_US"); //this is optional parameter, not required to set the parameter if custom value is not required for MLE key alias. Default value is "CyberSource_SJC_US". //same as older deprecated variable "mleKeyAlias" + + //Set Response MLE Settings in Merchant Configuration [Refer MLE.md on cybersource-rest-client-java github repo] + props.setProperty("enableResponseMleGlobally", "false"); //Enables/Disable response MLE globally for all APIs that support MLE responses + props.setProperty("responseMlePrivateKeyFilePath", ""); //Path to the Response MLE private key file. Supported formats: .p12, .pfx, .pem, .key, .p8. Recommendation use encrypted private Key (password protection) for MLE response. + props.setProperty("responseMlePrivateKeyFilePassword", ""); //Password for the private key file (required for .p12/.pfx files or encrypted private keys). + props.setProperty("responseMleKID", ""); //This parameter is optional when responseMlePrivateKeyFilePath points to a CyberSource-generated P12 file. If not provided, the SDK will automatically fetch the Key ID from the P12 file. If provided, the SDK will use the user-provided value instead of the auto-fetched value. + //Required when using PEM format files (.pem, .key, .p8) or when providing responseMlePrivateKey object directly. - // MetaKey Parameters - props.setProperty("portfolioID", ""); - props.setProperty("useMetaKey", "false"); - // JWT Parameters props.setProperty("keyAlias", "testrest"); props.setProperty("keyPass", "testrest"); props.setProperty("keyFileName", "testrest"); // P12 key path. Enter the folder path where the .p12 file is located. props.setProperty("keysDirectory", "src/main/resources"); - - // Logging to be enabled or not. - props.setProperty("enableLog", "true"); - // Log directory Path - props.setProperty("logDirectory", "log"); - props.setProperty("logFilename", "cybs"); - - // Log file size in KB - props.setProperty("logMaximumSize", "5M"); - - // OAuth related properties. - props.setProperty("enableClientCert", "false"); - props.setProperty("clientCertDirectory", "src/main/resources"); - props.setProperty("clientCertFile", ""); - props.setProperty("clientCertPassword", ""); - props.setProperty("clientId", ""); - props.setProperty("clientSecret", ""); - -// // HTTP Parameters -// props.setProperty("merchantKeyId", "08c94330-f618-42a3-b09d-e1e43be5efda"); -// props.setProperty("merchantsecretKey", "yBJxy6LjM2TmcPGu+GaJrHtkke25fPpUX+UY6/L/1tE="); - - /* - PEM Key file path for decoding JWE Response Enter the folder path where the .pem file is located. - It is optional property, require adding only during JWE decryption. - */ -// props.setProperty("jwePEMFileDirectory", "src/main/resources/NetworkTokenCert.pem"); return props; @@ -133,20 +115,23 @@ public static Properties getMerchantDetailsWithMLE3() { props.setProperty("merchantID", "testrest"); props.setProperty("runEnvironment", "apitest.cybersource.com"); - props.setProperty("requestJsonPath", "src/main/resources/request.json"); - //Set MLE Settings in Merchant Configuration - Map mleMap = new HashMap<>(); - mleMap.put("createPayment", true); //only createPayment function will have MLE=true i.e. (/pts/v2/payments POST API) - mleMap.put("capturePayment", true); //only capturePayment function will have MLE=true i.e. (/pts/v2/payments/{id}/captures POST API) + //Set Request MLE Settings in Merchant Configuration [Refer MLE.md on cybersource-rest-client-java github repo] + Map mleMap = new HashMap<>(); + mleMap.put("createPayment", "true"); //only createPayment function will have MLE=true i.e. (/pts/v2/payments POST API) + mleMap.put("capturePayment", "true"); //only capturePayment function will have MLE=true i.e. (/pts/v2/payments/{id}/captures POST API) - props.setProperty("useMLEGlobally", "false"); //globally MLE will be disabled for all the APIs in SDK + props.setProperty("enableRequestMLEForOptionalApisGlobally", "false"); //Disabled request MLE globally for all APIs that have optional MLE support //same as older deprecated variable "useMLEGlobally" props.put("mapToControlMLEonAPI", mleMap); //disable or enable the MLE for APIs which is in the list of mleMAP - props.setProperty("mleKeyAlias", "CyberSource_SJC_US"); //this is optional parameter, not required to set the parameter if custom value is not required for MLE key alias. Default value is "CyberSource_SJC_US". + props.setProperty("requestMleKeyAlias", "CyberSource_SJC_US"); //this is optional parameter, not required to set the parameter if custom value is not required for MLE key alias. Default value is "CyberSource_SJC_US". //same as older deprecated variable "mleKeyAlias" + + //Set Response MLE Settings in Merchant Configuration [Refer MLE.md on cybersource-rest-client-java github repo] + props.setProperty("enableResponseMleGlobally", "false"); //Enables/Disable response MLE globally for all APIs that support MLE responses + props.setProperty("responseMlePrivateKeyFilePath", ""); //Path to the Response MLE private key file. Supported formats: .p12, .pfx, .pem, .key, .p8. Recommendation use encrypted private Key (password protection) for MLE response. + props.setProperty("responseMlePrivateKeyFilePassword", ""); //Password for the private key file (required for .p12/.pfx files or encrypted private keys). + props.setProperty("responseMleKID", ""); //This parameter is optional when responseMlePrivateKeyFilePath points to a CyberSource-generated P12 file. If not provided, the SDK will automatically fetch the Key ID from the P12 file. If provided, the SDK will use the user-provided value instead of the auto-fetched value. + //Required when using PEM format files (.pem, .key, .p8) or when providing responseMlePrivateKey object directly. - // MetaKey Parameters - props.setProperty("portfolioID", ""); - props.setProperty("useMetaKey", "false"); // JWT Parameters props.setProperty("keyAlias", "testrest"); @@ -155,35 +140,88 @@ public static Properties getMerchantDetailsWithMLE3() { // P12 key path. Enter the folder path where the .p12 file is located. props.setProperty("keysDirectory", "src/main/resources"); - // Logging to be enabled or not. - props.setProperty("enableLog", "true"); - // Log directory Path - props.setProperty("logDirectory", "log"); - props.setProperty("logFilename", "cybs"); - - // Log file size in KB - props.setProperty("logMaximumSize", "5M"); - - // OAuth related properties. - props.setProperty("enableClientCert", "false"); - props.setProperty("clientCertDirectory", "src/main/resources"); - props.setProperty("clientCertFile", ""); - props.setProperty("clientCertPassword", ""); - props.setProperty("clientId", ""); - props.setProperty("clientSecret", ""); - -// // HTTP Parameters -// props.setProperty("merchantKeyId", "08c94330-f618-42a3-b09d-e1e43be5efda"); -// props.setProperty("merchantsecretKey", "yBJxy6LjM2TmcPGu+GaJrHtkke25fPpUX+UY6/L/1tE="); - - /* - PEM Key file path for decoding JWE Response Enter the folder path where the .pem file is located. - It is optional property, require adding only during JWE decryption. - */ -// props.setProperty("jwePEMFileDirectory", "src/main/resources/NetworkTokenCert.pem"); + return props; + + } + + public static Properties getMerchantDetailsWithRequestAndResponseMLE1() { + + Properties props = new Properties(); + + // MLE only support with JWT = jwt auth type only + props.setProperty("authenticationType", "JWT"); + + props.setProperty("merchantID", "agentic_mid_091225001"); + props.setProperty("runEnvironment", "apitest.cybersource.com"); + + //Set Request MLE Settings in Merchant Configuration [Refer MLE.md on cybersource-rest-client-java github repo] + props.setProperty("enableRequestMLEForOptionalApisGlobally", "true"); //Enables request MLE globally for all APIs that have optional MLE support //same as older deprecated variable "useMLEGlobally" //APIs that has MLE Request mandatory is default has MLE support in SDK without any configuration but support with JWT auth type. + + //Set Response MLE Settings in Merchant Configuration [Refer MLE.md on cybersource-rest-client-java github repo] + props.setProperty("enableResponseMleGlobally", "true"); //Enables response MLE globally for all APIs that support MLE responses + props.setProperty("responseMlePrivateKeyFilePath", "src/main/resources/agentic_mid_091225001_mle.p12"); //Path to the Response MLE private key file. Supported formats: .p12, .pfx, .pem, .key, .p8. Recommendation use encrypted private Key (password protection) for MLE response. + props.setProperty("responseMlePrivateKeyFilePassword", "Changeit@123"); //Password for the private key file (required for .p12/.pfx files or encrypted private keys). + props.setProperty("responseMleKID", "1757970970891045729358"); //Optional since p12 is Cybs Generated. + //This parameter is optional when responseMlePrivateKeyFilePath points to a CyberSource-generated P12 file. If not provided, the SDK will automatically fetch the Key ID from the P12 file. If provided, the SDK will use the user-provided value instead of the auto-fetched value. + //Required when using PEM format files (.pem, .key, .p8) or when providing responseMlePrivateKey object directly. + + + // JWT Parameters + props.setProperty("keyAlias", "agentic_mid_091225001"); + props.setProperty("keyPass", "Changeit@123"); + props.setProperty("keyFileName", "agentic_mid_091225001"); + // P12 key path. Enter the folder path where the .p12 file is located. + props.setProperty("keysDirectory", "src/main/resources"); + + return props; } + +public static Properties getMerchantDetailsWithRequestAndResponseMLE2() { + + Properties props = new Properties(); + + // MLE only support with JWT = jwt auth type only + props.setProperty("authenticationType", "JWT"); + + props.setProperty("merchantID", "agentic_mid_091225001"); + props.setProperty("runEnvironment", "apitest.cybersource.com"); + + //Set Request MLE Settings in Merchant Configuration [Refer MLE.md on cybersource-rest-client-java github repo] + props.setProperty("enableRequestMLEForOptionalApisGlobally", "false"); //Disable request MLE globally for all APIs that have optional MLE support //same as older deprecated variable "useMLEGlobally" //APIs that has MLE Request mandatory is default has MLE support in SDK without any configuration but support with JWT auth type. + + //Set Response MLE Settings in Merchant Configuration [Refer MLE.md on cybersource-rest-client-java github repo] + props.setProperty("enableResponseMleGlobally", "false"); //Disable response MLE globally for all APIs that support MLE responses + + //Set Request & Response MLE Settings in Merchant Configuration through MAP for API control level [Refer MLE.md on cybersource-rest-client-java github repo] + Map mleMap = new HashMap<>(); + mleMap.put("createPayment", "true::false"); //only createPayment function will have Request MLE=true and Response MLE = false i.e. (/pts/v2/payments POST API) + mleMap.put("enrollCard", "true::true"); //only enrollCard function will have Request MLE=true & Response MLE =true i.e. (/acp/v1/tokens POST API) + + props.put("mapToControlMLEonAPI", mleMap); //disable or enable the MLE for APIs which is in the list of mleMAP + + //since one of the API has Response MLE true, so below fields are required for Response MLE + props.setProperty("responseMlePrivateKeyFilePath", "src/main/resources/agentic_mid_091225001_mle.p12"); //Path to the Response MLE private key file. Supported formats: .p12, .pfx, .pem, .key, .p8. Recommendation use encrypted private Key (password protection) for MLE response. + props.setProperty("responseMlePrivateKeyFilePassword", "Changeit@123"); //Password for the private key file (required for .p12/.pfx files or encrypted private keys). + props.setProperty("responseMleKID", "1757970970891045729358"); //Optional since p12 is Cybs Generated. + //This parameter is optional when responseMlePrivateKeyFilePath points to a CyberSource-generated P12 file. If not provided, the SDK will automatically fetch the Key ID from the P12 file. If provided, the SDK will use the user-provided value instead of the auto-fetched value. + //Required when using PEM format files (.pem, .key, .p8) or when providing responseMlePrivateKey object directly. + + + // JWT Parameters + props.setProperty("keyAlias", "agentic_mid_091225001"); + props.setProperty("keyPass", "Changeit@123"); + props.setProperty("keyFileName", "agentic_mid_091225001"); + // P12 key path. Enter the folder path where the .p12 file is located. + props.setProperty("keysDirectory", "src/main/resources"); + + + + return props; + + } + } \ No newline at end of file diff --git a/src/main/java/samples/MLEFeature/AcpApiExampleWithRequestAndResponseMLE.java b/src/main/java/samples/MLEFeature/AcpApiExampleWithRequestAndResponseMLE.java new file mode 100644 index 0000000..c9025ea --- /dev/null +++ b/src/main/java/samples/MLEFeature/AcpApiExampleWithRequestAndResponseMLE.java @@ -0,0 +1,99 @@ +package samples.MLEFeature; + +import java.lang.invoke.MethodHandles; +import java.util.Properties; + +import com.cybersource.authsdk.core.MerchantConfig; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import Api.EnrollmentApi; +import Data.ConfigurationWithMLE; +import Invokers.ApiClient; +import Invokers.ApiException; +import Model.AgenticCardEnrollmentRequest; +import Model.AgenticCardEnrollmentResponse200; + +public class AcpApiExampleWithRequestAndResponseMLE { + private static String responseCode = null; + private static String status = null; + private static Properties merchantProp; + public static boolean userCapture = false; + + public static void WriteLogAudit(int status) { + String filename = MethodHandles.lookup().lookupClass().getSimpleName(); + System.out.println("[Sample Code Testing] [" + filename + "] " + status); + } + + public static void main(String args[]) throws Exception { + run(); + } + + public static AgenticCardEnrollmentResponse200 run() throws JsonMappingException, JsonProcessingException { + + String request = "{\"clientCorrelationId\":\"3e1b7943-6567-4965-a32b-5aa93d057d35\",\"deviceInformation\":{\"userAgent\":\"SampleUserAgent\",\"applicationName\":\"MyMagicApp\",\"fingerprintSessionId\":\"finSessionId\",\"country\":\"US\",\"deviceData\":{\"type\":\"Mobile\",\"manufacturer\":\"Apple\",\"brand\":\"Apple\",\"model\":\"iPhone16ProMax\"},\"ipAddress\":\"192.168.0.100\",\"clientDeviceId\":\"000b2767814e4416999f4ee2b099491d2087\"},\"buyerInformation\":{\"merchantCustomerId\":\"3e1b7943-6567-4965-a32b-5aa93d057d35\",\"personalIdentification\":[{\"type\":\"Theidentificationtype\",\"id\":\"1\",\"issuedBy\":\"Thegovernmentagencythatissuedthedriver'slicenseorpassport\"}],\"language\":\"en\"},\"billTo\":{\"firstName\":\"John\",\"lastName\":\"Doe\",\"fullName\":\"JohnMichaelDoe\",\"email\":\"john.doe@example.com\",\"countryCallingCode\":\"1\",\"phoneNumber\":\"5551234567\",\"numberIsVoiceOnly\":false,\"country\":\"US\"},\"consumerIdentity\":{\"identityType\":\"EMAIL_ADDRESS\",\"identityValue\":\"john.doe@example.com\",\"identityProvider\":\"PARTNER\",\"identityProviderUrl\":\"https://identity.partner.com\"},\"paymentInformation\":{\"customer\":{\"id\":\"\"},\"paymentInstrument\":{\"id\":\"\"},\"instrumentIdentifier\":{\"id\":\"4044EB915C613A82E063AF598E0AE6EF\"}},\"enrollmentReferenceData\":{\"enrollmentReferenceType\":\"TOKEN_REFERENCE_ID\",\"enrollmentReferenceProvider\":\"VTS\"},\"assuranceData\":[{\"verificationType\":\"DEVICE\",\"verificationEntity\":\"10\",\"verificationEvents\":[\"01\"],\"verificationMethod\":\"02\",\"verificationResults\":\"01\",\"verificationTimestamp\":\"1735690745\",\"authenticationContext\":{\"action\":\"AUTHENTICATE\"},\"authenticatedIdentities\":{\"data\":\"authenticatedData\",\"provider\":\"VISA_PAYMENT_PASSKEY\",\"id\":\"f48ac10b-58cc-4372-a567-0e02b2c3d489\"},\"additionalData\":\"\"}],\"consentData\":[{\"id\":\"550e8400-e29b-41d4-a716-446655440000\",\"type\":\"PERSONALIZATION\",\"source\":\"CLIENT\",\"acceptedTime\":\"1719169800\",\"effectiveUntil\":\"1750705800\"}]}"; + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + AgenticCardEnrollmentRequest requestObj = objectMapper.readValue(request, AgenticCardEnrollmentRequest.class); + + AgenticCardEnrollmentResponse200 result = null; + + + //Case1: Simple way to configure the request and response MLE in SDK. + try { + merchantProp = ConfigurationWithMLE.getMerchantDetailsWithRequestAndResponseMLE1(); + ApiClient apiClient = new ApiClient(); + MerchantConfig merchantConfig = new MerchantConfig(merchantProp); + apiClient.merchantConfig = merchantConfig; + + EnrollmentApi apiInstance = new EnrollmentApi(apiClient); + result = apiInstance.enrollCard(requestObj); + + responseCode = apiClient.responseCode; + status = apiClient.status; + System.out.println("ResponseCode :" + responseCode); + System.out.println("ResponseMessage :" + status); + System.out.println(result); + WriteLogAudit(Integer.parseInt(responseCode)); + + } catch (ApiException e) { + e.printStackTrace(); + WriteLogAudit(e.getCode()); + } catch (Exception e) { + e.printStackTrace(); + } + + + + + + //Case2: Control Request and Response MLE through map on API level + try { + merchantProp = ConfigurationWithMLE.getMerchantDetailsWithRequestAndResponseMLE2(); + ApiClient apiClient = new ApiClient(); + MerchantConfig merchantConfig = new MerchantConfig(merchantProp); + apiClient.merchantConfig = merchantConfig; + + EnrollmentApi apiInstance = new EnrollmentApi(apiClient); + result = apiInstance.enrollCard(requestObj); + + responseCode = apiClient.responseCode; + status = apiClient.status; + System.out.println("ResponseCode :" + responseCode); + System.out.println("ResponseMessage :" + status); + System.out.println(result); + WriteLogAudit(Integer.parseInt(responseCode)); + + } catch (ApiException e) { + e.printStackTrace(); + WriteLogAudit(e.getCode()); + } catch (Exception e) { + e.printStackTrace(); + } + + + return result; + } +} diff --git a/src/main/resources/agentic_mid_091225001.p12 b/src/main/resources/agentic_mid_091225001.p12 new file mode 100644 index 0000000..818ee46 Binary files /dev/null and b/src/main/resources/agentic_mid_091225001.p12 differ diff --git a/src/main/resources/agentic_mid_091225001_mle.p12 b/src/main/resources/agentic_mid_091225001_mle.p12 new file mode 100644 index 0000000..8bdb84e Binary files /dev/null and b/src/main/resources/agentic_mid_091225001_mle.p12 differ