Back to All

Custom Money Out Integration for ACH

(edited)

Use Cases

  1. User enables new ACH money out option
    1. Cloudspark: New CloudSpark page with a form that does the work?
    2. Disco: Impersonate into CS, create a link into the web office page, or create a custom Disco page.
  2. User updates ACH money out option
    1. User fills out the same page as in use case 1. Data is replaced.
  3. User wants to know where their payment is
    1. User sees data on the page (as in use case 1)

Solution

Software Structure

Cambridge application needs to be developed in a NuGet package owned, maintained, and deployed by Cambridge. The Client Extension will reference this package during installation.

The solution must be developed in the DirectScale Client Extension.

Cloudspark elements will need to be added through the Admin tool. The outcome of the project will be clear documentation surrounding the setup and management of admin elements.

Task 1 - Build Disco API to Set Cambridge Data on Disco

Custom API build in Disco

  • Set the associate to the Cambridge account
  • Set the unique Beneficiary ID on that account

Task 2 - Allow User to Enable and Manage ACH Money-out Option

Option 1

Preferred: Create a form that validates the fields and calls custom API (Task 1) to set that associate to Cambridge and adds their beneficiary ID to the database. This form would be owned, hosted, and controlled by Cambridge. (Cambridge not ready for this option right now)

  • DS enables SSO on the links to the page.
  • Cambridge develops DS SSO link
  • Dev team adds a custom page in Web Office that iFrames Cambridge page.
  • Call Custom API

Option 2

Create a custom page in the web office that validates the IBan and does the bank search calling out to Cambridge and calls an API in disco (Task 1) to set the Unique Beneficiary ID for that user.

Task 3 - Implement the Money-out Interaction with Cambridge

Custom Money Out Merchant

Create a custom class inside that inherits from AccountCommissionMerchant and complete the different methods

PayCommissions - This is the location that will tell Cambridge how much money each associate has earned and will return the status of those payments.

ProvisionAccount - could inform the associate to go to the custom page and create their account

public class CustomHyperWalletMoneyOutMerchant : AccountCommissionMerchant {

 private const string ACCOUNT_NUMBER_KEY = "ActNum";
       public CustomHyperWalletMoneyOutMerchant()
           : base( new MerchantInfo(5555, "CustomHyperWallet", "USD")
                 , new List<CommissionMerchantCustomField>
                 {
                     new CommissionMerchantCustomField
                     {
                         DisplayText = "Account Number",
                         Key = ACCOUNT_NUMBER_KEY,
                         IsRequired = true
                     }
                 })
       {
       }
       public override CommissionPaymentResults PayCommissions(int batchId, List<CommissionPayment> payments)
       {
           var results = new List<CommissionPaymentResult>();
           foreach (var payment in payments)
           {
               // Be careful here!
               // We process the whole batch at once, so you have to provide the error handling so the statuses are correctly saved.
               // If half of the payments succeeded, but then an exception were thrown, disco would not receive the CommissionPaymentResults
               // and would be unaware that any of the payments went out. Try - catch handling is necessary
               try
               {
                   if (payment.MerchantCustomFields.TryGetValue(ACCOUNT_NUMBER_KEY, out string accountNumber))
                   {
                       // call out to merchant to process payment
                       results.Add(new CommissionPaymentResult()
                       {
                           PaymentUniqueId = payment.PaymentUniqueId, // This one is important that you manually set this equal to the payment you just processed
                           TransactionNumber = payment.PaymentUniqueId,
                           Status = CommissionPaymentStatus.Paid,
                           DatePaid = DateTime.Now,
                           CheckNumber = 100,
                       });
                   }
                   else
                   {
                       results.Add(new CommissionPaymentResult()
                       {
                           PaymentUniqueId = payment.PaymentUniqueId, // This one is important that you manually set this equal to the payment you just processed
                           Status = CommissionPaymentStatus.Failed,
                           ErrorMessage = "Account not initialized"
                       });
                   }
               }
               catch (Exception e)
               {
                   results.Add(new CommissionPaymentResult()
                   {
                       PaymentUniqueId = payment.PaymentUniqueId, // This one is important that you manually set this equal to the payment you just processed
                       Status = CommissionPaymentStatus.Failed,
                       ErrorMessage = $"Exception ocurred while paying {payment.AssociateId} : {e.Message}"
                   }) ;
               }
           }
           return new CommissionPaymentResults
           {
               Results = results
           };
       }
       public override CommissionMerchantAccountFields ProvisionAccount(int associateID)
       {
           // Create an account for this associate, and any other custom values you need in PayCommissions
           return new CommissionMerchantAccountFields
           {
               CustomValues = new Dictionary<string, string>
               {
                   { ACCOUNT_NUMBER_KEY, "Response account number" }
               }
           };
       }
   }
}

Read more: Setting Up a Money Out Payment Provider

Task 4 - Credentials

We discussed the Partner Key (DirectScale) being stored in the Nu Get package since it will not change. The client key and (another one) will need to be either passed in the constructor from the registration in the Client DLL OR stored in a DB table and retrieved. This may include CRUD for management of the creds.