1
\$\begingroup\$

I have written a wrapper for Soap based 3rd party web service.

https://gist.github.com/veganista/bd940750d9e240e63b89

I'm pretty happy with it so far (I think, anyway). It's only a small sub-set of what the full API offers but will suffice for my needs at the moment.

I'm looking for some criticism from some other developers on my implementation.

Edit: I'd also like some tips on how to make this easily testable. I currently haven't written any automated tests for the class. I'd use PHP Unit for testing.

<?php

namespace KashFlow;

class KashFlow {

/**
 * Contains the username used for authenticating with KashFlow
 * 
 * @var string $username
 */
    protected $username;

/**
 * Contains the password used for authenticating with KashFlow
 *
 * @var string $password
 */
    protected $password;

/**
 * Holds a reference to the SoapClient used by the wrapper
 *
 * @var SoapClient $client
 */
    protected $client;

/**
 * Constructor method 
 *
 * @param string $username Username used for authentication
 * @param string $password Password used for authentication
 * @return KashFlow Returns it's self
 */
    public function __construct($username, $password){
        $this->client = new \SoapClient('https://securedwebapp.com/api/service.asmx?WSDL', array('trace' => 1, 'soap_version' => SOAP_1_2));

        $this->username = $username;
        $this->password = $password;

        return $this;
    }

/**
 * Makes a request to kashflow.
 * 
 * Used internally to for all requests but can also be used to make requests to kashflow
 * for methods without a wrapper.
 *
 * @param string $method The method to be called
 * @param array $arguments Any arguments that should be sent with the request
 */
    public function request($method, $arguments = array()){
        $arguments = array_merge(array('UserName' => $this->username, 'Password' => $this->password), $arguments);

        $result = $this->client->$method($arguments);

        if($result->Status == 'NO'){
            throw new \Exception($result->StatusDetail);
        }

        return $result;

    }

/**
 * This method returns all currencies that have been setup in the users account.
 * 
 * @link http://www.kashflow.com/developers/soap-api/GetCurrencies/
 *
 * @return array An array of objects of type Currencies
 */
    public function getCurrencies(){
        $result = $this->request('GetCurrencies');

        return $result->GetCurrenciesResult;
    }

/**
 * Gets the default currency for the account
 *
 * @return mixed Returns 
 */
    public function getDefaultCurrency(){
        $currencies = $this->getCurrencies();

        foreach($currencies as $currency){
            if($currency->isDefault){
                return $currency;
            }
        }

        return false;
    }

/**
 * This method returns an array of all payments method available for use as the PayMethod
 * 
 * @link http://www.kashflow.com/developers/soap-api/GetInvPayMethods/
 * @return An array of objects of type PaymentMethod
 */
    public function getInvoicePaymentMethods(){
        $result = $this->request('GetInvPayMethods');

        return $result->GetInvPayMethodsResult->PaymentMethod;
    }

/**
 * This method will create an invoice and return the new invoice number.
 *
 * InvoiceLines are automatically added to the invoice array
 *
 * @param $data array Invoice data array
 * @param $lines array InvoiceLine data array
 * @return int An integer represeting the new Invoice number
 */
    public function insertInvoice($data, $lines = array()){
        $invoiceDefault = array(
            'InvoiceDBID' => '',
            'Paid' => 0,
            'SuppressTotal' => 0,
            'ProjectID' => '',
            'NetAmount' => 0,
            'VATAmount' => 0,
            'AmountPaid' => 0,
        );

        $lineDefault = array(
            'LineID'      => 0,
            'Quantity'    => 0,
            'Description' => '',
            'Rate'        => 0,
            'ChargeType'  => 0,
            'VatAmount'   => 0,
            'VatRate'     => 0,
            'Sort'        => 0,
            'ProductID'   => 0,
            'ProjID'      => 0,
        );

        $data = array_merge($invoiceDefault, $data, array('Lines' => array()));

        foreach($lines as $line){
            $line = array_merge($lineDefault, $line);   
            $data['Lines'][] = new \SoapVar($line, 0, 'InvoiceLine', 'KashFlow');
        }

        $result = $this->request('InsertInvoice', array('Inv' => $data));

        return $result->InsertInvoiceResult;

    }

/**
 * This method allows you to add a payment to an invoice.
 * 
 * @link http://www.kashflow.com/developers/soap-api/InsertInvoicePayment/ 
 * @param $invoiceId int ID of the invoice number to enter payment for
 * @param $data array Invoice payment data array
 * @return int An integer representing the new payment number 
 */
    public function insertInvoicePayment($invoiceId, $data = array()){
        $default = array(
            'PayID' => '',
            'PayDate' => date('Y-m-d'),
            'PayNote' => '',
            'PayMethod' => '',
            'PayAccount' => '',
            'PayAmount' => 0,
        );

        $data = array_merge($default, $data, array('PayInvoice' => $invoiceId));

        $result = $this->request('InsertInvoicePayment', array('InvoicePayment' => $data));

        return $result->InsertInvoicePaymentResult;
    }

/**
 * Ths method returns a customer based on their email address
 *
 * @link http://www.kashflow.com/developers/soap-api/getcustomerbyemail/
 * @param string $email Email address of the customer
 * @return mixed Returns an object of type Customer on success of false if not found
 */
    public function getCustomerByEmail($email){

        try{
            $result = $this->request('GetCustomerByEmail', array('CustomerEmail' => $email));
            return $result->GetCustomerByEmailResult;
        }catch(\Exception $e){
            return false;
        }

    }

/**
 * This method lets you create a new Customer.
 * 
 * @link http://www.kashflow.com/developers/soap-api/InsertCustomer/
 * @param array An array containing cutomer data
 * @return int An integer containing the newly generated ID number for the customer
 */
    public function insertCustomer($data){
        $default = array(
            'CustomerID' => '',
            'Name' => '',
            'Contact' => '',
            'Telephone' => '',
            'Mobile' => '',
            'Email' => '',
            'Address1' => '',
            'Address2' => '',
            'Postcode' => '',
            'EC' => 0,
            'OutsideEC' => 0,
            'Source' => '',
            'Discount' => 0,
            'ShowDiscount' => false,
            'PaymentTerms' => '',
            'CheckBox1' => 0,
            'CheckBox2' => 0,
            'CheckBox3' => 0,
            'CheckBox4' => 0,
            'CheckBox5' => 0,
            'CheckBox6' => 0,
            'CheckBox7' => 0,
            'CheckBox8' => 0,
            'CheckBox9' => 0,
            'CheckBox10' => 0,
            'CheckBox11' => 0,
            'CheckBox12' => 0,
            'CheckBox13' => 0,
            'CheckBox14' => 0,
            'CheckBox15' => 0,
            'CheckBox16' => 0,
            'CheckBox17' => 0,
            'CheckBox18' => 0,
            'CheckBox19' => 0,
            'CheckBox20' => 0,
            'Created' => date('Y-m-d'),
            'Updated' => date('Y-m-d'),
        );

        $data = array_merge($default, $data);

        if(!isset($data['CurrencyID'])){
            $defaultCurrency = $this->getDefaultCurrency();
            $data['CurrencyID'] = $defaultCurrency->CurrencyId;
        }

        $result = $this->request('InsertCustomer', array('custr' => $data));

        return $result->InsertCustomerResult;
    }

/**
 * Gets a niceley formatted version of the last soap request
 *
 * @return string The last soap request
 */
    public function getLastRequest(){
        $request = $this->client->__getLastRequest();

        $dom = new DOMDocument();
        $dom->formatOutput = true;
        $dom->preserveWhitespace = false;
        $dom->loadXml($request);

        return '<pre>' . htmlspecialchars($dom->saveXml()) . '</pre>';
    }

}
\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

Here are some tips for your class:

For the lines like the following, I suggest applying different formatting (to make it more readable). Please see below:

$arguments = array_merge(array('UserName' => $this->username, 'Password' => $this->password), $arguments);

to this

$arguments = array_merge(
    array(
        'UserName' => $this->username, 
        'Password' => $this->password
    ), $arguments
);

You could just use Exception rather then \Exception is you define the class use in the beginning of your class like this:

use \Exception;

I really enjoyed your getLastRequest() function implementation and a trace in XML.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Yes, better readability would be an improvement there. There's nothing gained by putting it all on one line really. I think adding the use \Exception and use \SoapClient are a good idea as it gives a bit of an overview of what the class uses. \$\endgroup\$
    – veganista
    Commented Jan 18, 2014 at 11:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.