Support from Acquia helps fund testing for Drupal Acquia logo

Comments

TR created an issue. See original summary.

longwave’s picture

  • TR committed cce8f34 on 8.x-4.x
    Issue #2656634: Some preliminary work towards porting authorize.net.
    
arkestra’s picture

I have started to port this over for Drupal 8. Using the attached patch (for the uc_authorizenet submodule), card processing should be possible (including the CIM capture).

Will continue improvements and porting other areas.

TR’s picture

Patches need to be made relative to the Ubercart directory, so for example in your patch

diff --git a/uc_authorizenet.module b/uc_authorizenet.module
index c994b54..d6508da 100644
--- a/uc_authorizenet.module
+++ b/uc_authorizenet.module

should really be

diff --git a/payment/uc_authorizenet/uc_authorizenet.module b/payment/uc_authorizenet/uc_authorizenet.module
index c994b54..d6508da 100644
--- a/payment/uc_authorizenet/uc_authorizenet.module
+++ b/payment/uc_authorizenet/uc_authorizenet.module

etc.

sarjeet.singh’s picture

Status: Postponed » Needs review
FileSize
5.56 KB

Hi All,

I am working ubercart migration d6 to d8 and we require this module so I have fixed and it is working.

Please review attracted patch and commit it dev branch if its fine.

Thanks

sarjeet.singh’s picture

TR’s picture

Status: Needs review » Needs work

These patches are a step in the right direction, but they are far from complete.

@sarjeet.singh: Why didn't you include the changes from #4 in your patch? If they are needed then they should be included, otherwise they will be overlooked. If they are not needed then you need to explain why.

Here are my comments about the patches so far:

  1. Missing changes: This is only a partial list of some obviously missing things I noticed by skimming through the code just now:
    1. Replace the remaining variable_get() with configuration variable and remove the variable_get() shim defined in uc_authorizenet.module.
    2. Remove superglobals https://www.drupal.org/node/2150267
    3. Use string functions from the Unicode utility class, e.g. Unicode::strtoupper(), instead of the PHP equivalents which don't support unicode.
    4. Remove exit() call.
    5. Move _uc_authorizenet functions into a helper class, modify the function names appropriately.
    6. Explicitly mention which features you have tested and which you have not.
  2. Functional changes: Changes to functionality shouldn't be part of the port - that should be a separate feature request. For example, you add 'http_errors' => false, which is a change from what we had.
  3. Interdiff: When you post a new patch, also post an interdiff so we can see how your patch is different from the previous one - that way we don't have to do a complete review every time a patch is posted. See https://www.drupal.org/documentation/git/interdiff
  4. Coding standards: Do not introduce new coding standards violations. Any line of code you modify or add should conform to the current coding standards. See https://www.drupal.org/docs/develop/standards/coding-standards . Don't mix unrelated coding standards fixes into the patch for the port - those can be fixed in a separate issue - here you should only fix lines you modify or add. You can click on the green test results "PHP 5.5 & MySQL 5.5, D8.4 159 pass" next to your patch to see the coding standards analysis for your patch.

I do think that the existing uc_authorizenet code is almost working, but working and ported completely are two different things. Because I don't have an Authorize.Net account, I can't do any detailed testing of the module - that's what is needed most! It's very important to test every feature of the module, even ones that you don't currently use.

sarjeet.singh’s picture

Sure @TR, I will finish these issue and provide you new patch ASAP.

Thanks

Nathaniel’s picture

Assigned: Unassigned » Nathaniel
Status: Needs work » Needs review
Related issues: +#3025475: Authorize.net MD5 Hash Removal/Disablement
FileSize
41.79 KB
38.27 KB

Making some progress on this. Applied both patches. Attaching an interdiff with #6.

Deleted:
uc_authorizenet_uc_payment_gateway
variable_get shim

Moved to AuthorizeNet.php and renamed:
_uc_authorizenet_cim_profile_create > cimProfileCreate
_uc_authorizenet_cim_profile_create_request > cimProfileCreateRequest
_uc_authorizenet_cim_profile_charge > cimProfileCharge
_uc_authorizenet_cim_profile_charge_request > cimProfileChargeRequest
_uc_authorizenet_cim_profile_get > cimProfileGet
_uc_authorizenet_cim_payment_profile_get > cimPaymentProfileGet
uc_authorizenet_xml_api > xmlApi
_uc_authorizenet_xml_api_wrapper > xmlApiWrapper
_uc_authorizenet_array_to_xml > arrayToXml
_uc_authorize_cim_xml_billto > cimXmlBillTo
_uc_authorize_cim_xml_shipto > cimXmlShipTo
_uc_authorizenet_cim_parse_response > cimParseResponse
_uc_authorizenet_substr_between > substrBetween
_uc_authorizenet_arb_parse_response > arbParseResponse

I’ve tested the default product checkout with Authorize.net payment method on their sandbox. That works fine. I’ve tested with CIM settings “Always create a CIM profile for securely storing CC info for later use.” checked and the CIM profile was created as expected.

I worked on the code for ARB and ARB silent post URL, but I am unable to test ARB at this time since the md5 hash has been deprecated and can no longer be configured in the account settings at authorize.net. Here is a related issue to follow up on: https://www.drupal.org/project/ubercart/issues/3025475

Related article:

Note: As of 02/11/2019 we have removed the ability to configure the legacy MD5 Hash value.

https://support.authorize.net/s/article/What-is-the-MD5-Hash-Security-fe...

I'm open to working on any feedback within the next few weeks if anyone is available to review / test.

TR’s picture

Thanks @Nathaniel! It's looking a lot better, but the main thing is simply having someone like you who can test it and confirm it works.

There're still a lot of small things I see that need to be done, but I think they can be done in stages - i.e. commit the big patch then fix the little things later. The little things are things like service injection, coding standards, and documentation. If you're willing to help test these patches that would help a lot to get things finished.

The only big thing I see is that all the utility functions should be put into a separate class - NOT into the AuthorizeNet plugin. It's just way too messy to put them all into one class. But the bigger reason is that that stuff should really be refactored to use SimpleXML, and having them separated will make the refactoring easier. The existing code was initially written for Drupal 5 by people who did not know PHP very well, and when PHP was much worse at supporting OO code than it is now (still not very good, but better ...) The only good thing to say for the existing code is that it seems to work. But doing our own XML parsing and passing around undocumented arrays is really a very poor way to do things. It's not robust because the parsing doesn't, for example, escape special characters in the text strings (what if someone's name has a '<' in it? Then all the parsing would break), it doesn't handle multibyte strings, it's hard to read and understand therefore easy to hide bugs. It's also not very efficient. Using the built-in SimpleXML classes will greatly reduce our code, make the remaining code simple to read and more robust and maintainable.

I'm willing to do the XML stuff if you're not familiar with SimpleXML, as long as you will test any modifications I make.

But first, lets fix a few things from the patch in #10.

AuthorizeNetController.php:

  1. You shouldn't inject the config.factory service because it's not used anywhere.
  2. For the request_stack service, you're always accessing it with $this->requestStack->getCurrentRequest()->request->get(), which is pretty long and unnecessary. Instead of saving the service in the $requestStack variable, change the constructor to save $request_stack->getCurrentRequest()->request in a *protected* class variable named $request. Then you can use $this->request->get() everywhere else and it become much more readable.
  3. We should take this opportunity to rename the uc_auth_arb_payment hook to uc_authorizenet_arb_payment. And this hook should be documented in uc_authorizenet.api.php (it is not currently)

AuthorizeNet.php:

  1. Using the messenger service is not sufficient. I think the check on encryption setup needs to be done in validateConfigurationForm()
  2. I don't like seeing isset() used anywhere - if you need this, that means some variable isn't getting initialized properly. Configuration variables should always have default values, so I would prefer to have defaults set in defaultConfiguration() rather than testing with isset()
  3. It looks like you copied the changes @sarjeet.singh made in the \Drupal::httpClient() calls. I don't know why those changes were made, but I think they are a step backwards in terms of clarity. I would appreciate it if you restored those to the original form (using post() etc. instead of request()).
  4. Move the functions formerly known as _uc_authorizenet_ ... into a separate class. I don't care what you name it, as it will be refactored/renamed in the conversion to SimpleXML.

uc_authorizenet.module:

  1. Remove the constant definitions - they should be const variables in the AuthorizeNet.php file. What's more, since there is nothing left in uc_authorizenet.module, you can remove uc_authorizenet.module entirely. D8 does not require a module to have a .module file (only .info.yml is required).

General:

  1. Check coding standards. The easiest way to do that is post the patch so the testbot can look at it, then look at the testbot results and fix any mentioned coding standards in the lines of code you've added.
  2. Code that used to be in uc_authorizenet.module was using t(), but when you move that code into a class you should check to see if you can change this to $this->t(). Many base classes, such as ControllerBase, use the StringTranslationTrait.

I'm sure there's more, but this would be a great start. Let me know if you want me to work on the XML stuff - I can get that done over the next week if you are willing to test it.

Nathaniel’s picture

@TR thank you for the quick response and thorough review, that is refreshing. Tried to clean it up a bit. Attached a new patch.

It looks like there were some changes in guzzle that are breaking the current \Drupal::httpClient() call. Reverting it breaks the functionality, so I tweaked it a bit. Here are a few notes:

`setSslVerification()` has been removed. Use default request options instead,
like `$client->setConfig('defaults/verify', true)`.

Some other errors that came up:
TypeError: Argument 3 passed to GuzzleHttp\Client::request() must be of the type array, boolean given...
Error: Call to undefined method GuzzleHttp\Psr7\Response::send()...

Any suggestions for accessing the payment method plugin configurations? Or does this look right:

$configuration = PaymentMethod::load($order->getPaymentMethodId())->getPlugin()->getConfiguration();

Yes, if you can handle the XML that would be great! Let me know if I can help with any more testing or code changes. It might be nice to have the CIM / ARB functionality in separate files depending on how the re-writes go.

Nathaniel’s picture

Fixing some of the coding standards issues introduced in the previous patch.

TR’s picture

Thanks @Nathaniel. It will take me a day or two to get around to reviewing this in depth. My initial glance shows that you addressed all the things I mentioned (Thanks!). If all looks good after the detailed review I will probably just commit this then submit a new patch to change the helper class to SimpleXML. The only thing that I noticed so far is that you tend to private a lot, whereas in Drupal we discourage the use of private, for various reasons. IMO private should be used in OO code only if you have a really really good reason why a subclass should not touch that variable or method. If you don't have a good reason, protected should be used.

Nathaniel’s picture

Thanks for pointing that out. Changed private to protected.

albug’s picture

i need some help on ubercart module, i cant enable authorised.net under that module because it Requires: not_yet_ported (missing) i tried to look for the fix but in vain, i would appreciate if can get a fix and steps out to sort it out.