Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add mle #179

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
8d42402
adding MLE parameters in merchantConfig
gaubansa Jan 31, 2025
d8f3a4a
adding MLE Utility
gaubansa Jan 31, 2025
46ddb40
adding mle req body encryption in payment api
gaubansa Jan 31, 2025
f3f5068
adding mle encryption logic in api.mustache
gaubansa Jan 31, 2025
30bbb86
adding mle encryption logic call to api classes
gaubansa Jan 31, 2025
be1177a
adding checkIsMLEForAPI implementation
gaubansa Jan 31, 2025
8e4b7b8
correcting comment
gaubansa Jan 31, 2025
0d335d6
Merge branch 'master' into feature/add-mle-encrypt
mahmishr Feb 13, 2025
73542f3
"python SDK MLE implementation"
mahmishr Feb 20, 2025
e1a7030
"loggers"
mahmishr Feb 20, 2025
c457290
Update MLEUtility.php
mahmishr Feb 20, 2025
e116bae
Merge branch 'feature/add-MLE' into feature/mle-readme
mahmishr Feb 20, 2025
1b4be6e
Merge branch 'feature/add-mle-encrypt' into feature/mle-readme
mahmishr Feb 20, 2025
7dd409b
"readme updated"
mahmishr Feb 20, 2025
57be300
"map type"
mahmishr Feb 20, 2025
6461b26
Merge branch 'master' into feature/add-MLE
gaubansa Feb 20, 2025
5573b7f
"MLE exception fix"
mahmishr Feb 20, 2025
9dedd0e
"caching update"
mahmishr Feb 25, 2025
bb2d7ed
"refactoring"
mahmishr Feb 25, 2025
b1efb70
"refactoring"
mahmishr Feb 25, 2025
282cbe0
"comments resolved"
mahmishr Mar 7, 2025
0070f33
"refactoring"
mahmishr Mar 7, 2025
0fe600e
"error handling refactored"
mahmishr Mar 7, 2025
5902861
"updated api.mustache"
mahmishr Mar 7, 2025
dd6292e
"generating apis based on mustache"
mahmishr Mar 7, 2025
07c86d2
Update MLE.md
mahmishr Mar 10, 2025
67caeb3
"null request body check"
mahmishr Mar 10, 2025
8e6fc13
Merge pull request #177 from CyberSource/feature/mle-encrypt-readme
gaubansa Mar 11, 2025
d697ea6
Merge pull request #176 from CyberSource/feature/add-mle-encrypt
gaubansa Mar 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions MLE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
[![Generic badge](https://img.shields.io/badge/MLE-NEW-GREEN.svg)](https://shields.io/)

# Message Level Encryption (MLE) Feature

This feature provides an implementation of Message Level Encryption (MLE) for APIs provided by CyberSource, integrated within our SDK. This feature ensures secure communication by encrypting messages at the application level before they are sent over the network.

## Configuration

### Global MLE Configuration

In the `merchantConfig` object, set the `useMLEGlobally` variable to enable or disable MLE for all supported APIs for the Rest SDK.

- **Variable**: `useMLEGlobally`
- **Type**: `boolean`
- **Default**: `false`
- **Description**: Enables MLE globally for all APIs when set to `true`. If set to `true`, it will enable MLE for all API calls that support MLE by CyberSource, unless overridden by `mapToControlMLEonAPI`.

### API-level MLE Control

Optionally, you can control the MLE feature at the API level using the `mapToControlMLEonAPI` variable in the `merchantConfig` object.

- **Variable**: `mapToControlMLEonAPI`
- **Type**: `map = [string, boolean]`
- **Description**: Overrides the global MLE setting for specific APIs. The key is the function name of the API in the SDK, and the value is a boolean indicating whether MLE should be enabled (`true`) or disabled (`false`) for that specific API call.

### MLE Key Alias

Another optional parameter for MLE is `mleKeyAlias`, which specifies the key alias used to retrieve the MLE certificate from the JWT P12 file.

- **Variable**: `mleKeyAlias`
- **Type**: `string`
- **Default**: `CyberSource_SJC_US`
- **Description**: By default, CyberSource uses the `CyberSource_SJC_US` public certificate to encrypt the payload. However, users can override this default value by setting their own key alias.

## Notes
- If `useMLEGlobally` is set to true, it will enable MLE for all API calls that support MLE by CyberSource, unless overridden by mapToControlMLEonAPI.
- If `mapToControlMLEonAPI` is not provided or does not contain a specific API function name, the global useMLEGlobally setting will be applied.
- The `mleKeyAlias` parameter is optional and defaults to CyberSource_SJC_US if not specified by the user. Users can override this default value by setting their own key alias.

## Example Configuration

```php
// Enable MLE globally for all supported APIs
$merchantConfig->setUseMLEGlobally(true);
```

Or

```php
// Enable MLE globally for all supported APIs
$merchantConfig->setUseMLEGlobally(true);

// Optionally, control MLE at the API level
$merchantConfig->setMapToControlMLEonAPI([
'apiFunctionName1' => false, // Disable MLE for this specific API
'apiFunctionName2' => true // Enable MLE for this specific API
]);

// Optionally, set a custom MLE key alias
$merchantConfig->setMleKeyAlias('Custom_Key_Alias');
```

Or

```php
// Disable MLE globally for all supported APIs
$merchantConfig->setUseMLEGlobally(false);

// Optionally, enable MLE for some APIs
$merchantConfig->setMapToControlMLEonAPI([
'apiFunctionName1' => true, // Enable MLE for this specific API
'apiFunctionName2' => true // Enable MLE for this specific API
]);

// Optionally, set a custom MLE key alias
$merchantConfig->setMleKeyAlias('Custom_Key_Alias');
```

In the above examples:
- MLE is enabled/disabled globally (`useMLEGlobally` is true/false).
- `apiFunctionName1` will have MLE disabled/enabled based on value provided.
- `apiFunctionName2` will have MLE enabled.
- `mleKeyAlias` is set to `Custom_Key_Alias`, overriding the default value.

Please refer given link for sample codes with MLE:
https://github.com/CyberSource/cybersource-rest-samples-php/tree/master/Samples/MLEFeature

## Additional Information

### API Support
- MLE is initially designed to support a few APIs.
- It can be extended to support more APIs in the future based on requirements and updates.
### Authentication Type
- MLE is only supported with `JWT (JSON Web Token)` authentication type within the SDK.
### Using the SDK
To use the MLE feature in the SDK, configure the `merchantConfig` object as shown above and pass it to the SDK initialization.

## Contact
For any issues or further assistance, please open an issue on the GitHub repository or contact our support team.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ More information about this new logging framework can be found in this file : [L

## Features

### Message Level Encryption (MLE) Feature
[![Generic badge](https://img.shields.io/badge/MLE-NEW-GREEN.svg)](https://shields.io/)

This feature provides an implementation of Message Level Encryption (MLE) for APIs provided by CyberSource, integrated within our SDK. This feature ensures secure communication by encrypting messages at the application level before they are sent over the network.

More information about this new MLE feature can be found in this file : [MLE.md](MLE.md)

### MetaKey Support

A Meta Key is a single key that can be used by one, some, or all merchants (or accounts, if created by a Portfolio user) in the portfolio.
Expand Down
14 changes: 14 additions & 0 deletions generator/cybersource-php-template/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ use \{{invokerPackage}}\ApiException;
use \{{invokerPackage}}\Configuration;
use \{{invokerPackage}}\ObjectSerializer;
use \{{invokerPackage}}\Logging\LogFactory as LogFactory;
use \{{invokerPackage}}\Authentication\Util\MLEUtility;
use \Exception;

/**
* {{classname}} Class Doc Comment
Expand Down Expand Up @@ -233,6 +235,18 @@ use \{{invokerPackage}}\Logging\LogFactory as LogFactory;
} elseif (count($formParams) > 0) {
$httpBody = $formParams; // for HTTP post (form)
}

//MLE check and mle encryption for req body
$isMLESupportedByCybsForApi = {{#vendorExtensions.x-devcenter-metaData.isMLEsupported}}true;{{/vendorExtensions.x-devcenter-metaData.isMLEsupported}}{{^vendorExtensions.x-devcenter-metaData.isMLEsupported}}false;{{/vendorExtensions.x-devcenter-metaData.isMLEsupported}}
if (MLEUtility::checkIsMLEForAPI($this->apiClient->merchantConfig, $isMLESupportedByCybsForApi, "{{operationId}},{{operationId}}WithHttpInfo")) {
try {
$httpBody = MLEUtility::encryptRequestPayload($this->apiClient->merchantConfig, $httpBody);
} catch (Exception $e) {
self::$logger->error("Failed to encrypt request body: $e");
throw new ApiException("Failed to encrypt request body : " . $e->getMessage());
}
}

{{#authMethods}}
{{#isApiKey}}
// this endpoint requires API key authentication
Expand Down
50 changes: 50 additions & 0 deletions lib/Api/BatchesApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
use \CyberSource\Configuration;
use \CyberSource\ObjectSerializer;
use \CyberSource\Logging\LogFactory as LogFactory;
use \CyberSource\Authentication\Util\MLEUtility;
use \Exception;

/**
* BatchesApi Class Doc Comment
Expand Down Expand Up @@ -157,6 +159,18 @@ public function getBatchReportWithHttpInfo($batchId)
} elseif (count($formParams) > 0) {
$httpBody = $formParams; // for HTTP post (form)
}

//MLE check and mle encryption for req body
$isMLESupportedByCybsForApi = false;
if (MLEUtility::checkIsMLEForAPI($this->apiClient->merchantConfig, $isMLESupportedByCybsForApi, "getBatchReport,getBatchReportWithHttpInfo")) {
try {
$httpBody = MLEUtility::encryptRequestPayload($this->apiClient->merchantConfig, $httpBody);
} catch (Exception $e) {
self::$logger->error("Failed to encrypt request body: $e");
throw new ApiException("Failed to encrypt request body : " . $e->getMessage());
}
}


// Logging
self::$logger->debug("Resource : GET $resourcePath");
Expand Down Expand Up @@ -267,6 +281,18 @@ public function getBatchStatusWithHttpInfo($batchId)
} elseif (count($formParams) > 0) {
$httpBody = $formParams; // for HTTP post (form)
}

//MLE check and mle encryption for req body
$isMLESupportedByCybsForApi = false;
if (MLEUtility::checkIsMLEForAPI($this->apiClient->merchantConfig, $isMLESupportedByCybsForApi, "getBatchStatus,getBatchStatusWithHttpInfo")) {
try {
$httpBody = MLEUtility::encryptRequestPayload($this->apiClient->merchantConfig, $httpBody);
} catch (Exception $e) {
self::$logger->error("Failed to encrypt request body: $e");
throw new ApiException("Failed to encrypt request body : " . $e->getMessage());
}
}


// Logging
self::$logger->debug("Resource : GET $resourcePath");
Expand Down Expand Up @@ -386,6 +412,18 @@ public function getBatchesListWithHttpInfo($offset = '0', $limit = '20', $fromDa
} elseif (count($formParams) > 0) {
$httpBody = $formParams; // for HTTP post (form)
}

//MLE check and mle encryption for req body
$isMLESupportedByCybsForApi = false;
if (MLEUtility::checkIsMLEForAPI($this->apiClient->merchantConfig, $isMLESupportedByCybsForApi, "getBatchesList,getBatchesListWithHttpInfo")) {
try {
$httpBody = MLEUtility::encryptRequestPayload($this->apiClient->merchantConfig, $httpBody);
} catch (Exception $e) {
self::$logger->error("Failed to encrypt request body: $e");
throw new ApiException("Failed to encrypt request body : " . $e->getMessage());
}
}


// Logging
self::$logger->debug("Resource : GET $resourcePath");
Expand Down Expand Up @@ -503,6 +541,18 @@ public function postBatchWithHttpInfo($body)
} elseif (count($formParams) > 0) {
$httpBody = $formParams; // for HTTP post (form)
}

//MLE check and mle encryption for req body
$isMLESupportedByCybsForApi = false;
if (MLEUtility::checkIsMLEForAPI($this->apiClient->merchantConfig, $isMLESupportedByCybsForApi, "postBatch,postBatchWithHttpInfo")) {
try {
$httpBody = MLEUtility::encryptRequestPayload($this->apiClient->merchantConfig, $httpBody);
} catch (Exception $e) {
self::$logger->error("Failed to encrypt request body: $e");
throw new ApiException("Failed to encrypt request body : " . $e->getMessage());
}
}


// Logging
self::$logger->debug("Resource : POST $resourcePath");
Expand Down
38 changes: 38 additions & 0 deletions lib/Api/BillingAgreementsApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
use \CyberSource\Configuration;
use \CyberSource\ObjectSerializer;
use \CyberSource\Logging\LogFactory as LogFactory;
use \CyberSource\Authentication\Util\MLEUtility;
use \Exception;

/**
* BillingAgreementsApi Class Doc Comment
Expand Down Expand Up @@ -171,6 +173,18 @@ public function billingAgreementsDeRegistrationWithHttpInfo($modifyBillingAgreem
} elseif (count($formParams) > 0) {
$httpBody = $formParams; // for HTTP post (form)
}

//MLE check and mle encryption for req body
$isMLESupportedByCybsForApi = true;
if (MLEUtility::checkIsMLEForAPI($this->apiClient->merchantConfig, $isMLESupportedByCybsForApi, "billingAgreementsDeRegistration,billingAgreementsDeRegistrationWithHttpInfo")) {
try {
$httpBody = MLEUtility::encryptRequestPayload($this->apiClient->merchantConfig, $httpBody);
} catch (Exception $e) {
self::$logger->error("Failed to encrypt request body: $e");
throw new ApiException("Failed to encrypt request body : " . $e->getMessage());
}
}


// Logging
self::$logger->debug("Resource : PATCH $resourcePath");
Expand Down Expand Up @@ -299,6 +313,18 @@ public function billingAgreementsIntimationWithHttpInfo($intimateBillingAgreemen
} elseif (count($formParams) > 0) {
$httpBody = $formParams; // for HTTP post (form)
}

//MLE check and mle encryption for req body
$isMLESupportedByCybsForApi = true;
if (MLEUtility::checkIsMLEForAPI($this->apiClient->merchantConfig, $isMLESupportedByCybsForApi, "billingAgreementsIntimation,billingAgreementsIntimationWithHttpInfo")) {
try {
$httpBody = MLEUtility::encryptRequestPayload($this->apiClient->merchantConfig, $httpBody);
} catch (Exception $e) {
self::$logger->error("Failed to encrypt request body: $e");
throw new ApiException("Failed to encrypt request body : " . $e->getMessage());
}
}


// Logging
self::$logger->debug("Resource : POST $resourcePath");
Expand Down Expand Up @@ -412,6 +438,18 @@ public function billingAgreementsRegistrationWithHttpInfo($createBillingAgreemen
} elseif (count($formParams) > 0) {
$httpBody = $formParams; // for HTTP post (form)
}

//MLE check and mle encryption for req body
$isMLESupportedByCybsForApi = true;
if (MLEUtility::checkIsMLEForAPI($this->apiClient->merchantConfig, $isMLESupportedByCybsForApi, "billingAgreementsRegistration,billingAgreementsRegistrationWithHttpInfo")) {
try {
$httpBody = MLEUtility::encryptRequestPayload($this->apiClient->merchantConfig, $httpBody);
} catch (Exception $e) {
self::$logger->error("Failed to encrypt request body: $e");
throw new ApiException("Failed to encrypt request body : " . $e->getMessage());
}
}


// Logging
self::$logger->debug("Resource : POST $resourcePath");
Expand Down
14 changes: 14 additions & 0 deletions lib/Api/BinLookupApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
use \CyberSource\Configuration;
use \CyberSource\ObjectSerializer;
use \CyberSource\Logging\LogFactory as LogFactory;
use \CyberSource\Authentication\Util\MLEUtility;
use \Exception;

/**
* BinLookupApi Class Doc Comment
Expand Down Expand Up @@ -158,6 +160,18 @@ public function getAccountInfoWithHttpInfo($createBinLookupRequest)
} elseif (count($formParams) > 0) {
$httpBody = $formParams; // for HTTP post (form)
}

//MLE check and mle encryption for req body
$isMLESupportedByCybsForApi = false;
if (MLEUtility::checkIsMLEForAPI($this->apiClient->merchantConfig, $isMLESupportedByCybsForApi, "getAccountInfo,getAccountInfoWithHttpInfo")) {
try {
$httpBody = MLEUtility::encryptRequestPayload($this->apiClient->merchantConfig, $httpBody);
} catch (Exception $e) {
self::$logger->error("Failed to encrypt request body: $e");
throw new ApiException("Failed to encrypt request body : " . $e->getMessage());
}
}


// Logging
self::$logger->debug("Resource : POST $resourcePath");
Expand Down
14 changes: 14 additions & 0 deletions lib/Api/CaptureApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
use \CyberSource\Configuration;
use \CyberSource\ObjectSerializer;
use \CyberSource\Logging\LogFactory as LogFactory;
use \CyberSource\Authentication\Util\MLEUtility;
use \Exception;

/**
* CaptureApi Class Doc Comment
Expand Down Expand Up @@ -171,6 +173,18 @@ public function capturePaymentWithHttpInfo($capturePaymentRequest, $id)
} elseif (count($formParams) > 0) {
$httpBody = $formParams; // for HTTP post (form)
}

//MLE check and mle encryption for req body
$isMLESupportedByCybsForApi = true;
if (MLEUtility::checkIsMLEForAPI($this->apiClient->merchantConfig, $isMLESupportedByCybsForApi, "capturePayment,capturePaymentWithHttpInfo")) {
try {
$httpBody = MLEUtility::encryptRequestPayload($this->apiClient->merchantConfig, $httpBody);
} catch (Exception $e) {
self::$logger->error("Failed to encrypt request body: $e");
throw new ApiException("Failed to encrypt request body : " . $e->getMessage());
}
}


// Logging
self::$logger->debug("Resource : POST $resourcePath");
Expand Down
14 changes: 14 additions & 0 deletions lib/Api/ChargebackDetailsApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
use \CyberSource\Configuration;
use \CyberSource\ObjectSerializer;
use \CyberSource\Logging\LogFactory as LogFactory;
use \CyberSource\Authentication\Util\MLEUtility;
use \Exception;

/**
* ChargebackDetailsApi Class Doc Comment
Expand Down Expand Up @@ -170,6 +172,18 @@ public function getChargebackDetailsWithHttpInfo($startTime, $endTime, $organiza
} elseif (count($formParams) > 0) {
$httpBody = $formParams; // for HTTP post (form)
}

//MLE check and mle encryption for req body
$isMLESupportedByCybsForApi = false;
if (MLEUtility::checkIsMLEForAPI($this->apiClient->merchantConfig, $isMLESupportedByCybsForApi, "getChargebackDetails,getChargebackDetailsWithHttpInfo")) {
try {
$httpBody = MLEUtility::encryptRequestPayload($this->apiClient->merchantConfig, $httpBody);
} catch (Exception $e) {
self::$logger->error("Failed to encrypt request body: $e");
throw new ApiException("Failed to encrypt request body : " . $e->getMessage());
}
}


// Logging
self::$logger->debug("Resource : GET $resourcePath");
Expand Down
Loading