Search code examples
c#.netasp.net-web-api2visual-studio-2017authorize.net

creating a web api wrapper around an existing API


Authorize.NET offers a very thorough SDK..

You can simply install it in your solution:

Install-Package AuthorizeNet

We need service(s) to wrap all the capabilities of the AuthorizeNet API.

For simplicity, let's say that the API exposes the following methods:

public bool Pay(TransactionModel trans);
public bool Decline(Guid id);
public bool Refund(Guid id);

We have easy access to these methods from our own solution controller methods. For example:

[HttpPost]
public bool PayAuthNet([FromBody] AuthnetTransModel model)
{
   TransactionModel localTransModel = CreateLocalAuthModel(model);
   var authNet = new AuthorizeNet();
   return authNet.Pay(localTransModel);
}

However, the API library is pretty vast that Authorize.NET exposes:

enter image description here

Assuming that we want to wrap these controllers, each into its own microservice (would like feedback on this approach), Is there an easier way to wrap every one of these APIs, forcing the client to go through our wrapper service, rather than allowing them to hit Authorize.NET directly?


Solution

  • This is meant as an simple explanation because it is too long for a comment.

    Will be using Pseudo code to demonstrate wrapping the AuthorizeNet

    Using the example provided in the OP

    [HttpPost]
    public bool PayAuthNet([FromBody] AuthnetTransModel model)
    {
       TransactionModel localTransModel = CreateLocalAuthModel(model);
       var authNet = new AuthorizeNet();
       return authNet.Pay(localTransModel);
    }
    

    First the naming convention. Similar to how MVC finds controller based on the naming convention like how Name/Action maps to NameController.Action

    PayAuthNet     --> AuthorizeNet.Pay
    DeclineAuthNet --> AuthorizeNet.Decline
    RefundAuthNet  --> AuthorizeNet.Refund
    

    And then using reflection the method argument type can be determined and a mapping function similar to how AutoMapper works would convert the provided model AuthnetTransModel to the expected TransactionModel argument for the function.

    Hypothetically you can use expression trees to get away from magic strings

    public class BillingConroller : ApiController {    
        [HttpPost]
        public bool PayAuthNet([FromBody] AuthnetTransModel model) {
           return authorizeNetWrapper.Execute<BillingConroller>(c => c.PayAuthNet(model));
        }    
    }
    

    Which internally would inspect the expression tree to extract the information needed to map and execute the matching wrapped API

    From expression tree:
        Method being invoked:  PayAuthNet
        Argument provider:     AuthnetTransModel 
    After applying convention:
        Found matching method: AuthorizeNet.Pay
        Expected argument:     TransactionModel
    Construct command
        Create instance of TransactionModel and copy properties from provided model
        Invoke => authNet.Pay(localTransModel)