diff --git a/force-app/main/default/classes/AdyenAuthorisationHelper.cls b/force-app/main/default/classes/AdyenAuthorisationHelper.cls index be05ca5..70fa873 100644 --- a/force-app/main/default/classes/AdyenAuthorisationHelper.cls +++ b/force-app/main/default/classes/AdyenAuthorisationHelper.cls @@ -1,4 +1,7 @@ public with sharing class AdyenAuthorisationHelper { + public static final String PSP_MISSING_ERROR = 'PspReference Missing'; + public static final String AMOUNT_MISSING_ERROR = 'Payment Amount Missing'; + public static final String AMOUNT_MISMATCH_ERROR = 'Authorization reversal amount of {0} does not match available to capture amount left of: {1}'; /** * Calls Adyen service to post an AUTH request to Adyen. @@ -6,7 +9,7 @@ public with sharing class AdyenAuthorisationHelper { * @return authResponse */ public static CommercePayments.GatewayResponse authorise(CommercePayments.AuthorizationRequest authRequest) { - Adyen_Adapter__mdt adyenAdapterMdt = AdyenPaymentUtility.retrieveGatewayMetadata(AdyenConstants.DEFAULT_ADAPTER_NAME); + Adyen_Adapter__mdt adyenAdapterMdt = AdyenPaymentUtility.retrieveAdapterByDeveloperName(AdyenConstants.DEFAULT_ADAPTER_NAME); AuthorisationRequest adyenAuthorisationRequest = createAuthorisationRequest(authRequest, adyenAdapterMdt); HttpResponse adyenHttpResponse = sendAuthorisationRequest(adyenAuthorisationRequest, adyenAdapterMdt); @@ -112,4 +115,49 @@ public with sharing class AdyenAuthorisationHelper { String endpoint = adyenAdapterMdt.Endpoint_Api_Version__c + adyenAdapterMdt.Authorize_Endpoint__c; return AdyenPaymentUtility.makePostRequest(endpoint, body); } + + public static CommercePayments.GatewayResponse reverseAuth(CommercePayments.AuthorizationReversalRequest authReversalRequest) { + PaymentAuthorization paymentAuth = AdyenPaymentUtility.retrievePaymentAuthorization(authReversalRequest.paymentAuthorizationId); + OrderPaymentSummary orderPaymentSummary = AdyenPaymentUtility.retrieveOrderPaymentSummary(paymentAuth.OrderPaymentSummaryId); + + String errorMessage; + if (String.isBlank(paymentAuth.GatewayRefNumber)) { + errorMessage = PSP_MISSING_ERROR; + } else if (authReversalRequest.amount == null) { + errorMessage = AMOUNT_MISSING_ERROR; + } else if (orderPaymentSummary.AvailableToCaptureAmount != authReversalRequest.amount) { + errorMessage = String.format(AMOUNT_MISMATCH_ERROR, new List{authReversalRequest.amount, orderPaymentSummary.AvailableToCaptureAmount}); + } + if (String.isNotBlank(errorMessage)) { + throw new AdyenGatewayAdapter.GatewayException(errorMessage); + } + + String pspReference = paymentAuth.GatewayRefNumber; + String merchantAccount = paymentAuth.OrderPaymentSummary.OrderSummary.SalesChannel.AdyenMerchantID__c; + Adyen_Adapter__mdt adyenAdapterMdt = AdyenPaymentUtility.chooseAdapterWithFallBack(merchantAccount); + + CancelRequest cancelRequest = new CancelRequest(); + cancelRequest.merchantAccount = adyenAdapterMdt.Merchant_Account__c; + cancelRequest.reference = paymentAuth.PaymentAuthorizationNumber; + cancelRequest.applicationInfo = AdyenPaymentUtility.getApplicationInfo(adyenAdapterMdt.System_Integrator_Name__c); + String endpoint = adyenAdapterMdt.Endpoint_Api_Version__c + adyenAdapterMdt.Cancel_Endpoint__c; + endpoint = endpoint.replace('{paymentPspReference}', pspReference); + + HttpResponse response = AdyenPaymentUtility.makePostRequest(endpoint, JSON.serialize(cancelRequest, true)); + String salesforceCompatibleBody = AdyenPaymentUtility.makeSalesforceCompatible(response.getBody()); + CancelResponse cancelResponse = (CancelResponse)JSON.deserialize(salesforceCompatibleBody, CancelResponse.class); + return processCancelResponse(cancelResponse, authReversalRequest.amount); + } + + private static CommercePayments.GatewayResponse processCancelResponse(CancelResponse cancelResponse, Double amount) { + CommercePayments.AuthorizationReversalResponse authReversalResponse = new CommercePayments.AuthorizationReversalResponse(); + authReversalResponse.setAmount(amount); + authReversalResponse.setGatewayDate(System.now()); + authReversalResponse.setGatewayReferenceDetails(cancelResponse.reference); + authReversalResponse.setGatewayResultCode(cancelResponse.status); + authReversalResponse.setGatewayReferenceNumber(cancelResponse.pspReference); + authReversalResponse.setSalesforceResultCodeInfo(AdyenConstants.SUCCESS_SALESFORCE_RESULT_CODE_INFO); + authReversalResponse.setGatewayMessage('[cancellation-received]'); + return authReversalResponse; + } } \ No newline at end of file diff --git a/force-app/main/default/classes/AdyenAuthorisationHelper.cls-meta.xml b/force-app/main/default/classes/AdyenAuthorisationHelper.cls-meta.xml index f5e18fd..651b172 100644 --- a/force-app/main/default/classes/AdyenAuthorisationHelper.cls-meta.xml +++ b/force-app/main/default/classes/AdyenAuthorisationHelper.cls-meta.xml @@ -1,5 +1,5 @@ - 60.0 + 61.0 Active diff --git a/force-app/main/default/classes/AdyenAuthorisationHelperTest.cls b/force-app/main/default/classes/AdyenAuthorisationHelperTest.cls index 90ced69..ada433e 100644 --- a/force-app/main/default/classes/AdyenAuthorisationHelperTest.cls +++ b/force-app/main/default/classes/AdyenAuthorisationHelperTest.cls @@ -3,7 +3,7 @@ private class AdyenAuthorisationHelperTest { @IsTest static void createAuthorisationRequestTest() { // given - Adyen_Adapter__mdt adyenAdapterMdt = AdyenPaymentUtility.retrieveGatewayMetadata(AdyenConstants.DEFAULT_ADAPTER_NAME); + Adyen_Adapter__mdt adyenAdapterMdt = AdyenPaymentUtility.retrieveAdapterByDeveloperName(AdyenConstants.DEFAULT_ADAPTER_NAME); AuthorisationRequest adyenAuthRequest; Double price; CommercePayments.AuthorizationRequest authRequest; @@ -95,4 +95,62 @@ private class AdyenAuthorisationHelperTest { } Test.stopTest(); } + + @IsTest(SeeAllData = true) + static void reverseAuthTest() { + // given + Account acct = TestDataFactory.createAccount(); + insert acct; + Order order = TestDataFactory.insertOrderAndRelatedRecords(acct.Id, 33.42, 0.96); + OrderPaymentSummary orderPaymentSummary = TestDataFactory.createOrderSummaryRecords(order.Id); + Double price = [SELECT AvailableToCaptureAmount FROM OrderPaymentSummary WHERE Id = :orderPaymentSummary.Id].AvailableToCaptureAmount; + TestDataFactory.insertBasicPaymentRecords(acct.Id, orderPaymentSummary.Id); + PaymentAuthorization payAuth = [SELECT Id, GatewayRefNumber FROM PaymentAuthorization WHERE OrderPaymentSummaryId = :orderPaymentSummary.Id]; + CommercePayments.AuthorizationReversalRequest authReversalRequest = new CommercePayments.AuthorizationReversalRequest(price, payAuth.Id); + Test.setMock(HttpCalloutMock.class, new TestDataFactory.CancelsMockResponse()); + // when + Test.startTest(); + CommercePayments.GatewayResponse gatewayResponse = AdyenAuthorisationHelper.reverseAuth(authReversalRequest); + Test.stopTest(); + // then + Assert.isTrue(gatewayResponse.toString().containsIgnoreCase('cancellation-received')); + } + + @IsTest(SeeAllData = true) + static void reverseAuthValidationErrorTest() { + // no PA with gateway reference + Account acct = TestDataFactory.createAccount(); + insert acct; + Order order = TestDataFactory.insertOrderAndRelatedRecords(acct.Id, 33.42, 0.96); + OrderPaymentSummary orderPaymentSummary = TestDataFactory.createOrderSummaryRecords(order.Id); + PaymentAuthorization payAuth = TestDataFactory.createPaymentAuthorization(acct.Id, null, null, orderPaymentSummary.Id, null); + insert payAuth; + CommercePayments.AuthorizationReversalRequest authReversalRequest = new CommercePayments.AuthorizationReversalRequest(Double.valueOf(1.99), payAuth.Id); + try { + AdyenAuthorisationHelper.reverseAuth(authReversalRequest); + Assert.fail(); + } catch (Exception ex) { + Assert.areEqual(ex.getMessage(), AdyenAuthorisationHelper.PSP_MISSING_ERROR); + } + // Authorization Amount is null + payAuth = TestDataFactory.createPaymentAuthorization(acct.Id, null, null, orderPaymentSummary.Id, TestDataFactory.TEST_PSP_REFERENCE); + insert payAuth; + authReversalRequest = new CommercePayments.AuthorizationReversalRequest(null, payAuth.Id); + try { + AdyenAuthorisationHelper.reverseAuth(authReversalRequest); + Assert.fail(); + } catch (Exception ex) { + Assert.areEqual(ex.getMessage(), AdyenAuthorisationHelper.AMOUNT_MISSING_ERROR); + } + // Amount mismatch + Decimal availableToCapture = [SELECT AvailableToCaptureAmount FROM OrderPaymentSummary WHERE Id = :orderPaymentSummary.Id].AvailableToCaptureAmount; + Double price = availableToCapture - 1; + authReversalRequest = new CommercePayments.AuthorizationReversalRequest(price, payAuth.Id); + try { + AdyenAuthorisationHelper.reverseAuth(authReversalRequest); + Assert.fail(); + } catch (Exception ex) { + Assert.areEqual(ex.getMessage(), String.format(AdyenAuthorisationHelper.AMOUNT_MISMATCH_ERROR, new List{price,availableToCapture})); + } + } } \ No newline at end of file diff --git a/force-app/main/default/classes/AdyenAuthorisationHelperTest.cls-meta.xml b/force-app/main/default/classes/AdyenAuthorisationHelperTest.cls-meta.xml index f5e18fd..651b172 100644 --- a/force-app/main/default/classes/AdyenAuthorisationHelperTest.cls-meta.xml +++ b/force-app/main/default/classes/AdyenAuthorisationHelperTest.cls-meta.xml @@ -1,5 +1,5 @@ - 60.0 + 61.0 Active diff --git a/force-app/main/default/classes/AdyenOMSConstants.cls b/force-app/main/default/classes/AdyenOMSConstants.cls index 0a5928f..a76d94a 100644 --- a/force-app/main/default/classes/AdyenOMSConstants.cls +++ b/force-app/main/default/classes/AdyenOMSConstants.cls @@ -16,5 +16,10 @@ public with sharing class AdyenOMSConstants { public static final String ALTERNATIVE_PAYMENT_METHOD_OBJECT = 'AlternativePaymentMethod'; public static final Set OPEN_INVOICE_METHODS = new Set{'klarna', 'afterpay', 'ratepay', 'facilypay', 'zip', 'affirm', 'atome', 'walley', 'clearpay'}; - public static final Set VALID_NOTIFICATION_TYPES = new Set{AdyenConstants.NOTIFICATION_REQUEST_TYPE_CAPTURE, AdyenConstants.NOTIFICATION_REQUEST_TYPE_REFUND, AdyenConstants.NOTIFICATION_REQUEST_TYPE_CAPTURE_FAILED, AdyenConstants.NOTIFICATION_REQUEST_TYPE_REFUND_FAILED}; + public static final Set VALID_NOTIFICATION_TYPES = new Set{ + AdyenConstants.NOTIFICATION_REQUEST_TYPE_CAPTURE, + AdyenConstants.NOTIFICATION_REQUEST_TYPE_REFUND, + AdyenConstants.NOTIFICATION_REQUEST_TYPE_CAPTURE_FAILED, + AdyenConstants.NOTIFICATION_REQUEST_TYPE_REFUND_FAILED + }; } \ No newline at end of file diff --git a/force-app/main/default/classes/AdyenOMSConstants.cls-meta.xml b/force-app/main/default/classes/AdyenOMSConstants.cls-meta.xml index f5e18fd..651b172 100644 --- a/force-app/main/default/classes/AdyenOMSConstants.cls-meta.xml +++ b/force-app/main/default/classes/AdyenOMSConstants.cls-meta.xml @@ -1,5 +1,5 @@ - 60.0 + 61.0 Active diff --git a/force-app/main/default/classes/AdyenPaymentHelper.cls b/force-app/main/default/classes/AdyenPaymentHelper.cls index 92a577a..8918208 100644 --- a/force-app/main/default/classes/AdyenPaymentHelper.cls +++ b/force-app/main/default/classes/AdyenPaymentHelper.cls @@ -14,6 +14,8 @@ public with sharing class AdyenPaymentHelper { if (paymentRequestType == CommercePayments.RequestType.Authorize) { return AdyenAuthorisationHelper.authorise((CommercePayments.AuthorizationRequest)paymentRequest); + } else if (paymentRequestType == CommercePayments.RequestType.AuthorizationReversal) { + return AdyenAuthorisationHelper.reverseAuth((CommercePayments.AuthorizationReversalRequest)paymentRequest); } else if (paymentRequestType == CommercePayments.RequestType.Capture) { return AdyenCaptureHelper.capture((CommercePayments.CaptureRequest)paymentRequest); } else if (paymentRequestType == CommercePayments.RequestType.ReferencedRefund) { diff --git a/force-app/main/default/classes/AdyenPaymentHelper.cls-meta.xml b/force-app/main/default/classes/AdyenPaymentHelper.cls-meta.xml index f5e18fd..651b172 100644 --- a/force-app/main/default/classes/AdyenPaymentHelper.cls-meta.xml +++ b/force-app/main/default/classes/AdyenPaymentHelper.cls-meta.xml @@ -1,5 +1,5 @@ - 60.0 + 61.0 Active diff --git a/force-app/main/default/classes/AdyenPaymentUtility.cls b/force-app/main/default/classes/AdyenPaymentUtility.cls index 6bce282..867076f 100644 --- a/force-app/main/default/classes/AdyenPaymentUtility.cls +++ b/force-app/main/default/classes/AdyenPaymentUtility.cls @@ -1,12 +1,14 @@ public with sharing class AdyenPaymentUtility { @TestVisible - private static final String NO_PAYMENT_FOUND_BY_ID = 'No Payment found with this id: '; + private static final String NO_PAYMENT_FOUND_BY_ID = 'No Payment found with id: '; @TestVisible - private static final String NO_PAYMENT_AUTH_FOUND_BY_ID = 'No payment authorization found with this id: '; + private static final String NO_ORDER_PAY_SUM_FOUND_BY_ID = 'No Order Payment Summary found with id: '; @TestVisible - private static final String NO_ADYEN_ADAPTER_BY_NAME = 'No Adyen adapter found with this name: '; + private static final String NO_PAYMENT_AUTH_FOUND_BY_ID = 'No payment authorization found with id: '; @TestVisible - private static final String NO_ADYEN_ADAPTER_BY_MERCHANT = 'No Adyen adapter found for this merchant account: '; + private static final String NO_ADYEN_ADAPTER_BY_NAME = 'No Adyen adapter found with name: '; + @TestVisible + private static final String NO_ADYEN_ADAPTER_BY_MERCHANT = 'No Adyen adapter found for merchant account: '; /** * Retrieve Payment Info. @@ -31,51 +33,49 @@ public with sharing class AdyenPaymentUtility { } return payments[0]; } - - - /** - * Retrieves custom meta data associated with Adyen (Endpoint info) pulls all fields. - * @param developerName name of the custom metadata type with Adyen configuration - * @return Adyen_Adapter__mdt for the passed metadata type with all fields. - */ - public static Adyen_Adapter__mdt retrieveGatewayMetadata(String developerName) { - List adyenAdapters = [ - SELECT - DeveloperName, MasterLabel, Capture_Endpoint__c, Endpoint_Api_Version__c, - System_Integrator_Name__c, Endpoint_Path__c, Merchant_Account__c, Refund_Endpoint__c, - Authorize_Endpoint__c, HMAC_Key__c - FROM Adyen_Adapter__mdt - WHERE DeveloperName = :developerName + + public static OrderPaymentSummary retrieveOrderPaymentSummary(Id orderPaySummaryId) { + List orderPaymentSummaries = [ + SELECT Id, AvailableToCaptureAmount + FROM OrderPaymentSummary + WHERE Id = :orderPaySummaryId ]; - if (adyenAdapters.isEmpty()) { - throw new AdyenGatewayAdapter.GatewayException(NO_ADYEN_ADAPTER_BY_NAME + developerName); + if (orderPaymentSummaries.isEmpty()) { + throw new AdyenGatewayAdapter.GatewayException(NO_ORDER_PAY_SUM_FOUND_BY_ID + orderPaySummaryId); } - return adyenAdapters[0]; + return orderPaymentSummaries[0]; + } + + public static Adyen_Adapter__mdt retrieveAdapterByDeveloperName(String developerName) { + return retrieveAdapter('DeveloperName', developerName, NO_ADYEN_ADAPTER_BY_NAME); } public static Adyen_Adapter__mdt retrieveAdapterByMerchantAcct(String merchantAccountName) { - List adyenAdapters = [ - SELECT - DeveloperName, MasterLabel, Capture_Endpoint__c, Endpoint_Api_Version__c, - System_Integrator_Name__c, Endpoint_Path__c, Merchant_Account__c, Refund_Endpoint__c, - Authorize_Endpoint__c, HMAC_Key__c - FROM Adyen_Adapter__mdt - WHERE Merchant_Account__c = :merchantAccountName - ]; - if (adyenAdapters.isEmpty()) { - throw new AdyenGatewayAdapter.GatewayException(NO_ADYEN_ADAPTER_BY_MERCHANT + merchantAccountName); - } - return adyenAdapters[0]; + return retrieveAdapter('Merchant_Account__c', merchantAccountName, NO_ADYEN_ADAPTER_BY_MERCHANT); } public static Adyen_Adapter__mdt chooseAdapterWithFallBack(String merchantAccountName) { if (String.isNotBlank(merchantAccountName)) { return retrieveAdapterByMerchantAcct(merchantAccountName); } else { - return retrieveGatewayMetadata(AdyenConstants.DEFAULT_ADAPTER_NAME); + return retrieveAdapter('DeveloperName', AdyenConstants.DEFAULT_ADAPTER_NAME, NO_ADYEN_ADAPTER_BY_NAME); } } + private static Adyen_Adapter__mdt retrieveAdapter(String fieldName, String fieldValue, String errorMessage) { + String query = 'SELECT DeveloperName, MasterLabel, Capture_Endpoint__c, Endpoint_Api_Version__c, ' + + 'System_Integrator_Name__c, Endpoint_Path__c, Merchant_Account__c, Refund_Endpoint__c, ' + + 'Authorize_Endpoint__c, HMAC_Key__c, Cancel_Endpoint__c ' + + 'FROM Adyen_Adapter__mdt WHERE ' + fieldName + ' = :fieldValue'; + + List adyenAdapters = Database.query(query); + + if (adyenAdapters.isEmpty()) { + throw new AdyenGatewayAdapter.GatewayException(errorMessage + fieldValue); + } + return adyenAdapters[0]; + } + public static Boolean isValidNotification(NotificationRequestItem notificationRequestItem) { return AdyenOMSConstants.VALID_NOTIFICATION_TYPES.contains(notificationRequestItem.eventCode.toUpperCase()) && isValidPspReference(notificationRequestItem.originalReference) diff --git a/force-app/main/default/classes/AdyenPaymentUtility.cls-meta.xml b/force-app/main/default/classes/AdyenPaymentUtility.cls-meta.xml index f5e18fd..651b172 100644 --- a/force-app/main/default/classes/AdyenPaymentUtility.cls-meta.xml +++ b/force-app/main/default/classes/AdyenPaymentUtility.cls-meta.xml @@ -1,5 +1,5 @@ - 60.0 + 61.0 Active diff --git a/force-app/main/default/classes/AdyenPaymentUtilityTest.cls b/force-app/main/default/classes/AdyenPaymentUtilityTest.cls index c377bb0..2bec831 100644 --- a/force-app/main/default/classes/AdyenPaymentUtilityTest.cls +++ b/force-app/main/default/classes/AdyenPaymentUtilityTest.cls @@ -6,7 +6,7 @@ private class AdyenPaymentUtilityTest { CommercePayments.CaptureRequest captureRequest; String currencyCode = 'USD'; Double price; // request comes as Double value - Adyen_Adapter__mdt adyenAdapterMdt = AdyenPaymentUtility.retrieveGatewayMetadata(AdyenConstants.DEFAULT_ADAPTER_NAME); + Adyen_Adapter__mdt adyenAdapterMdt = AdyenPaymentUtility.retrieveAdapterByDeveloperName(AdyenConstants.DEFAULT_ADAPTER_NAME); Decimal expectedPrice; CheckoutCaptureRequest modificationRequest; for (Integer i = 0; i < 10; i++) { @@ -154,6 +154,46 @@ private class AdyenPaymentUtilityTest { Assert.areNotEqual(reference1, reference2); } + @IsTest + static void retrieveAdapterByDeveloperNameTest() { + Assert.isNotNull(AdyenPaymentUtility.retrieveAdapterByDeveloperName(AdyenConstants.DEFAULT_ADAPTER_NAME)); + String notADeveloperName = '123'; + try { + AdyenPaymentUtility.retrieveAdapterByDeveloperName(notADeveloperName); + Assert.fail(); + } catch (Exception ex) { + Assert.areEqual(ex.getMessage(), AdyenPaymentUtility.NO_ADYEN_ADAPTER_BY_NAME + notADeveloperName); + } + } + + @IsTest + static void retrieveAdapterByMerchantAcctTest() { + Adyen_Adapter__mdt adyenAdapter = AdyenPaymentUtility.retrieveAdapterByDeveloperName(AdyenConstants.DEFAULT_ADAPTER_NAME); + Assert.isNotNull(AdyenPaymentUtility.retrieveAdapterByMerchantAcct(adyenAdapter.Merchant_Account__c)); + String notAMerchantAcct = '123'; + try { + AdyenPaymentUtility.retrieveAdapterByMerchantAcct(notAMerchantAcct); + Assert.fail(); + } catch (Exception ex) { + Assert.areEqual(ex.getMessage(), AdyenPaymentUtility.NO_ADYEN_ADAPTER_BY_MERCHANT + notAMerchantAcct); + } + } + + @IsTest(SeeAllData=true) + static void retrieveOrderPaymentSummaryTest() { + Account acct = TestDataFactory.createAccount(); + insert acct; + Order order = TestDataFactory.insertOrderAndRelatedRecords(acct.Id, 33.42, 0.96); + OrderPaymentSummary orderPaymentSummary = TestDataFactory.createOrderSummaryRecords(order.Id); + Assert.isNotNull(AdyenPaymentUtility.retrieveOrderPaymentSummary(orderPaymentSummary.Id)); + try { + AdyenPaymentUtility.retrieveOrderPaymentSummary(acct.Id); + Assert.fail(); + } catch (Exception ex) { + Assert.areEqual(ex.getMessage(), AdyenPaymentUtility.NO_ORDER_PAY_SUM_FOUND_BY_ID + acct.Id); + } + } + private static OrderPaymentSummary createInvoiceAndRelatedRecords(Decimal price, Decimal taxValue) { Account acct = TestDataFactory.createAccount(); insert acct; @@ -174,6 +214,4 @@ private class AdyenPaymentUtilityTest { Id creditMemoId = TestDataFactory.createCreditMemo(orderSummaryId, changeOrderId); return creditMemoId; } - - } \ No newline at end of file diff --git a/force-app/main/default/classes/AdyenPaymentUtilityTest.cls-meta.xml b/force-app/main/default/classes/AdyenPaymentUtilityTest.cls-meta.xml index f5e18fd..651b172 100644 --- a/force-app/main/default/classes/AdyenPaymentUtilityTest.cls-meta.xml +++ b/force-app/main/default/classes/AdyenPaymentUtilityTest.cls-meta.xml @@ -1,5 +1,5 @@ - 60.0 + 61.0 Active diff --git a/force-app/main/default/classes/TestDataFactory.cls b/force-app/main/default/classes/TestDataFactory.cls index bf773ee..47b3cb7 100644 --- a/force-app/main/default/classes/TestDataFactory.cls +++ b/force-app/main/default/classes/TestDataFactory.cls @@ -37,12 +37,12 @@ public class TestDataFactory { ); } - public static PaymentAuthorization createPaymentAuthorization(Id acctId, Id cardPayMetId, Id payGatId, Id orderPaySummaryId) { + public static PaymentAuthorization createPaymentAuthorization(Id acctId, Id cardPayMetId, Id payGatId, Id orderPaySummaryId, String pspReference) { return new PaymentAuthorization( AccountId = acctId, PaymentMethodId = cardPayMetId, Amount = TEST_AMOUNT, - GatewayRefNumber = TEST_PSP_REFERENCE, + GatewayRefNumber = pspReference, Status = 'Processed', ProcessingMode = 'External', PaymentGatewayId = payGatId, @@ -70,7 +70,7 @@ public class TestDataFactory { CardPaymentMethod cardPayMeth = createCardPaymentMethod(); insert cardPayMeth; - PaymentAuthorization payAuth = createPaymentAuthorization(accId, cardPayMeth.Id, null, orderPaySummaryId); + PaymentAuthorization payAuth = createPaymentAuthorization(accId, cardPayMeth.Id, null, orderPaySummaryId, TEST_PSP_REFERENCE); insert payAuth; Payment payment = createPayment(accId, cardPayMeth.Id, null, payAuth.Id, orderPaySummaryId); @@ -309,6 +309,12 @@ public class TestDataFactory { } } + public class CancelsMockResponse implements HttpCalloutMock { + public HttpResponse respond(HttpRequest req) { + return mockHttpResponse(cancelResponse(), 200); + } + } + public static HttpResponse mockHttpResponse(String body, Integer code) { HttpResponse res = new HttpResponse(); res.setHeader('Content-Type', 'text/json'); @@ -320,4 +326,8 @@ public class TestDataFactory { private static String genericErrorResponse() { return '{"status": 400, "errorCode": "702", "message": "Empty input which would have resulted in a null result.", "errorType": "validation"}'; } + + private static String cancelResponse() { + return '{"merchantAccount":"PluginDemo_Danilo_TEST","paymentPspReference":"NWQTRSVVQ8Q94875","pspReference":"M4CV9RJFPT4CZX65","reference":"PA-000000037","status":"received"}'; + } } \ No newline at end of file diff --git a/force-app/main/default/classes/TestDataFactory.cls-meta.xml b/force-app/main/default/classes/TestDataFactory.cls-meta.xml index f5e18fd..651b172 100644 --- a/force-app/main/default/classes/TestDataFactory.cls-meta.xml +++ b/force-app/main/default/classes/TestDataFactory.cls-meta.xml @@ -1,5 +1,5 @@ - 60.0 + 61.0 Active diff --git a/force-app/main/default/layouts/Adyen_Adapter__mdt-Adyen Adapter Layout.layout-meta.xml b/force-app/main/default/layouts/Adyen_Adapter__mdt-Adyen Adapter Layout.layout-meta.xml index bab4ba4..c2e45eb 100644 --- a/force-app/main/default/layouts/Adyen_Adapter__mdt-Adyen Adapter Layout.layout-meta.xml +++ b/force-app/main/default/layouts/Adyen_Adapter__mdt-Adyen Adapter Layout.layout-meta.xml @@ -49,16 +49,20 @@ Edit Endpoint_Api_Version__c - - Edit Endpoint_Path__c + + Edit Authorize_Endpoint__c + + Required + Cancel_Endpoint__c + Edit Capture_Endpoint__c @@ -75,12 +79,7 @@ true true - - - Readonly - LastModifiedById - - + Readonly @@ -105,7 +104,7 @@ false false - 00h7Q00000G96rR + 00ha5000004n2Xq 4 0 Default diff --git a/force-app/main/default/objects/Adyen_Adapter__mdt/fields/Cancel_Endpoint__c.field-meta.xml b/force-app/main/default/objects/Adyen_Adapter__mdt/fields/Cancel_Endpoint__c.field-meta.xml new file mode 100644 index 0000000..b9c1015 --- /dev/null +++ b/force-app/main/default/objects/Adyen_Adapter__mdt/fields/Cancel_Endpoint__c.field-meta.xml @@ -0,0 +1,12 @@ + + + Cancel_Endpoint__c + Endpoint used to cancel an authorized payment + false + DeveloperControlled + + 64 + false + Text + false + diff --git a/manifest/package.xml b/manifest/package.xml index c48061a..d38aef3 100644 --- a/manifest/package.xml +++ b/manifest/package.xml @@ -41,6 +41,7 @@ Payment.Adyen_Payment_Method_Variant__c PaymentAuthorization.Adyen_Payment_Method__c PaymentAuthorization.Adyen_Payment_Method_Variant__c + Adyen_Adapter__mdt.Cancel_Endpoint__c CustomField diff --git a/sfdx-project.json b/sfdx-project.json index ea3bec3..c760284 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -17,7 +17,7 @@ ], "namespace": "adyen_payment", "sfdcLoginUrl": "https://login.salesforce.com", - "sourceApiVersion": "60.0", + "sourceApiVersion": "61.0", "packageAliases": { "Adyen Salesforce Order Management": "0Ho4T000000blPMSAY", "API Library Apex Adyen@3.2.0-5": "04tRP0000000lwbYAA",