title: How to setup custom api for Magento with SOAP V2?
body: <p>I am on Magento 1.4.1.1 and I am trying to setup a custom function in the API using SOAP v2. I have it working for SOAP v1 but I need v2 so that C# can use it. For v2 the function shows up in the WSDL but alwasy returns this error: Procedure 'testFoo' not present.</p>
  
  <p>Here are my files:</p>
  
  <p><strong>/app/etc/modules/ABT_Test.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0"?&gt;
  &lt;config&gt;
      &lt;modules&gt;
          &lt;ABT_Test&gt;
              &lt;active&gt;true&lt;/active&gt;
              &lt;codePool&gt;local&lt;/codePool&gt;
          &lt;/ABT_Test&gt;
      &lt;/modules&gt;
  &lt;/config&gt;
  </code></pre>
  
  <p><strong>/app/code/local/ABT/Test/etc/config.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0"?&gt;
  &lt;config&gt;
      &lt;modules&gt;
          &lt;ABT_Test&gt;
              &lt;active&gt;true&lt;/active&gt;
              &lt;codePool&gt;local&lt;/codePool&gt;
              &lt;version&gt;1.0&lt;/version&gt;
          &lt;/ABT_Test&gt;
      &lt;/modules&gt;
      &lt;global&gt;
          &lt;models&gt;
              &lt;test&gt;
                  &lt;class&gt;ABT_Test_Model&lt;/class&gt;
              &lt;/test&gt;
          &lt;/models&gt;
      &lt;/global&gt;
  &lt;/config&gt;
  </code></pre>
  
  <p><strong>/app/code/local/ABT/Test/etc/api.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0"?&gt;
  &lt;config&gt;
      &lt;api&gt;
          &lt;resources&gt;
              &lt;test&gt;
                  &lt;model&gt;test/api&lt;/model&gt;
                  &lt;title&gt;ABT Test Api&lt;/title&gt;
                  &lt;methods&gt;
                      &lt;foo translate="title" module="test"&gt;
                          &lt;title&gt;Foo Test&lt;/title&gt;
                          &lt;method&gt;foo&lt;/method&gt;
                          &lt;acl&gt;test/foo&lt;/acl&gt;
                      &lt;/foo&gt;
                  &lt;/methods&gt;
              &lt;/test&gt;
          &lt;/resources&gt;
          &lt;v2&gt;
              &lt;resources_function_prefix&gt;
                  &lt;test&gt;test&lt;/test&gt;
              &lt;/resources_function_prefix&gt;
          &lt;/v2&gt;
      &lt;/api&gt;
  &lt;/config&gt;
  </code></pre>
  
  <p><strong>/app/code/local/ABT/Test/etc/wsdl.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
      xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/"
      name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}"&gt;
      &lt;types&gt;
          &lt;schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"&gt;
              &lt;import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/" /&gt;
          &lt;/schema&gt;
      &lt;/types&gt;
      &lt;message name="testFooRequest"&gt;
          &lt;part name="sessionId" type="xsd:string" /&gt;
      &lt;/message&gt;
      &lt;message name="testFooResponse"&gt;
          &lt;part name="result" type="typens:boolean" /&gt;
      &lt;/message&gt;
      &lt;portType name="{{var wsdl.handler}}PortType"&gt;
          &lt;operation name="testFoo"&gt;
              &lt;documentation&gt;Test Foo&lt;/documentation&gt;
              &lt;input message="typens:testFooRequest" /&gt;
              &lt;output message="typens:testFooResponse" /&gt;
          &lt;/operation&gt;
      &lt;/portType&gt;
      &lt;binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"&gt;
          &lt;soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /&gt;
          &lt;operation name="testFoo"&gt;
              &lt;soap:operation soapAction="urn:{{var wsdl.handler}}Action" /&gt;
              &lt;input&gt;
                  &lt;soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /&gt;
              &lt;/input&gt;
              &lt;output&gt;
                  &lt;soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /&gt;
              &lt;/output&gt;
          &lt;/operation&gt;
      &lt;/binding&gt;
  &lt;/definitions&gt;
  </code></pre>
  
  <p><strong>/app/code/local/ABT/Test/Model/API.php</strong></p>
  
  <pre><code>&lt;?php
  class ABT_Test_Model_Api extends Mage_Api_Model_Resource_Abstract
  {
  
      public function foo()
      {
          return true;
      }
  }
  ?&gt;
  </code></pre>
  
  <p><strong>/app/code/local/ABT/Test/Model/API/V2.php</strong></p>
  
  <pre><code>&lt;?php
  class ABT_Test_Model_Api_V2 extends ABT_Test_Model_Api
  {
  }
  ?&gt;
  </code></pre>
  
  <p>And here is the code I use to test the API:</p>
  
  <pre><code>&lt;?php
      $mageUser   = '########';
      $mageApiKey = '########';
  
      //SOAP V1
      echo "SOAP V1 &lt;br /&gt;";
      $mageUrl    = 'http://www.########.com/api/soap/?wsdl';
      $soap = new SoapClient($mageUrl, array('cache_wsdl' =&gt; 0));
  
      try {
          $sessionID = $soap-&gt;login($mageUser, $mageApiKey);
          var_dump($soap-&gt;call($sessionID, 'test.foo', array()));
      } catch (Exception $e) {
          echo 'Exception: ' . $e-&gt;getMessage() . '&lt;br /&gt;';
      }
  
      //SOAP V2
      echo "SOAP V2 &lt;br /&gt;";
      $mageUrl2    = 'http://www.########.com/api/v2_soap/?wsdl';
      $soap2 = new SoapClient($mageUrl2, array('cache_wsdl' =&gt; 0));
  
      try {
          $sessionID2 = $soap2-&gt;login($mageUser, $mageApiKey);
          var_dump($soap2-&gt;testFoo($sessionID2));
      } catch (Exception $e) {
          echo 'Exception: ' . $e-&gt;getMessage() . '&lt;br /&gt;';
      }
  ?&gt;
  </code></pre>
  
  <p>I obscured the username, password and url. The function shows up in the v2 WSDL and the php code recognizes that it is in the WSDL but I still get the error: Procedure 'testFoo' not present.</p>
  
  <p>So what am I missing?</p>
  
  <p>EDIT:
  I did what Zyava suggested and it got my example working. I then copied the folder and did an exact (case sensitive) find and replace to use a meaningful Module name and function name. I was careful to pick names that I didn't think would be reserve words. On the new module the call on the v1 WSDL works fine but the v2 gives the same "Procedure 'xxx' not present" message. I then went and renamed the method on the test from 'Foo' to 'Fooz' and I got this message: "Resource path is not callable." I find it interesting that I get a different message. This leads me to believe there is some cache/configuration/something that is causing the problem. Any ideas? </p>