Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Totvs Rm Soap Laravel Package

mateusfbi/totvs-rm-soap

Laravel SOAP client for TOTVS RM that simplifies authentication and calling RM webservices, letting you send requests and parse responses through an expressive, framework-friendly API.

View on GitHub
Deep Wiki
Context7

Getting Started

Prerequisites. Confirm ext-soap is compiled into every environment (local, CI, container image) — it is not a Composer dependency and is the single most common install failure. You also need a reachable TOTVS RM endpoint (homologation/sandbox first), an RM username/password, and — depending on the RM version — the correct context (coligada, sistema, or similar) that scopes the call.

Install and configure.

composer require mateusfbi/totvs-rm-soap
php artisan vendor:publish --tag=totvs-rm-soap-config   # verify tag in docs if this fails

Set credentials in .env rather than in config/*.php. The package advertises env-driven configuration, so the config file is the authoritative list of keys (URL/WSDL, user, password, context, cache settings) — read it before writing any code, because the key names are the real API contract.

Where to look first. In order:

  1. docs/SERVICES.md — the catalog of the RM services/WSDLs the package expects. This is your map; confirm the endpoint you need is listed before designing anything.
  2. config/totvs-rm-soap.php — the full configuration surface (connection, auth, WebService/cache behavior).
  3. docs/TROUBLESHOOTING.md — first-line diagnostics for auth and transport errors; read it before you start debugging blind.
  4. tests/ — 57 tests with mocked SoapClient happy paths. Until you have internal docs, the tests are the most reliable usage examples.

First use case. Authenticate and execute one read-only call (a query/consulta against homologation) inside php artisan tinker, resolving the package's WebService from the container. Get a real response object printed before you write a single line of application code. If that works, the transport, credentials, and WSDL are all correct, and everything afterward is just payload shape.

In plain PHP (no Laravel). The package supports it, but you lose auto-discovery — you'll wire the service provider/bindings yourself and load config manually. Only take this path if the consuming app genuinely isn't Laravel; the Laravel binding path is significantly less work.

Implementation Patterns

Wrap the client in a domain service. Never call the package's client from a controller, job, or Blade view. Put it behind a class like RmFuncionarioRepository that takes the SOAP client in its constructor, translates application arguments into request payloads, and returns domain arrays/DTOs. This gives you one seam to mock, one place to add logging, and one place to change when a WSDL drifts.

Resolve via the container, and choose transient vs shared deliberately. The package's Provider exposes both bindings, and the distinction matters. Use transient for anything that holds request-scoped credentials or context; reserve shared for stateless, immutable configuration. In a standard FPM request lifecycle either works, but under Octane, queue workers, or long-running processes a shared client is a state-leak candidate — default to transient unless you have a measured reason not to.

Generate XML; don't concatenate it. Use the package's XML generators for request bodies. Hand-built strings are where accents get mangled, dates get formatted wrong, and empty/null values get serialized as "" where RM expects an omitted node. Because the generators are unit-tested in isolation, you can also test your payload construction without touching the network: assert the generated XML for a given input, and snapshot it.

Treat fail-fast as a boundary contract. The WebService layer fails fast rather than returning half-populated results — that's the right default, but it means you own the resilience layer. Catch the package's exceptions at your repository boundary, translate them into your domain's exceptions, and only retry the ones that are safe to retry (transport/timeout). Never blanket-retry an RM method that mutates data; a timeout on a write may mean the write succeeded.

try {
    return $this->client->execute($payload);
} catch (SoapFault $e) {
    report($e); // log raw request/response — see Tips
    throw new RmUnavailableException(previous: $e);
}

Cache reads, invalidate on writes. The package's caching is your primary throughput lever for lookups that rarely change (tables, cadastros). Design the key from the full request identity — context + method + normalized parameters — not just the method name, or you'll serve one coligada's data to another. Set TTL per service based on how stale the data is allowed to be, and explicitly bust the key when you write to the same entity. Cache the result, not the client.

Isolate environments. Register separate connections/config entries for homologation and production and select via APP_ENV. Do not conditionally swap a URL inside a service class — that's how a staging job ends up writing to production. Better: two named clients, two bindings, bound by environment config.

Test without the network. The package mocks SoapClient internally; mirror that in your own suite. Mock the SOAP client (or your repository interface, one level up) and assert on the XML your code generated and on how your code handled a fault. You should be able to run the entire suite offline — if any test needs a live RM endpoint, it isn't a unit test.

Custom headers/contexts. The package advertises extensibility for custom contexts and headers. Use that extension point for RM-specific routing (coligada, sistema) rather than forking the package. If you find yourself needing behavior the extension point can't express, that's a signal to contribute upstream — the package has tests and CI, so a PR is realistic.

Gotchas and Tips

ext-soap is invisible until it isn't. Composer will install cleanly and then fail at runtime with a class-not-found on SoapClient. Add ext-soap to your own composer.json require block and to your Dockerfile, and assert it in a health check.

Debugging is raw-XML debugging. Enable trace on the SOAP client and log __getLastRequest() / __getLastResponse() on failure — the exception message alone rarely tells you which field RM rejected. Redact credentials before logging. Keep those logs behind a debug flag so you don't ship full payloads to production log storage.

Authentication failures look like everything else. Expired/rotated RM passwords, wrong context, and WSDL mismatches often surface as the same generic SoapFault. Follow docs/TROUBLESHOOTING.md in order; the most useful single test is a minimal hardcoded call in tinker. If that fails, the problem is config, not your code.

Date and decimal formats are a silent corruption risk. TOTVS RM expects specific locale-driven formats. A date serialized one way will produce wrong records, not an error. Lock the format in the XML generator layer and cover it with a test — this is cheap insurance and the bug is very hard to spot downstream.

Caching hides upstream breakage. A stale cache makes a dead endpoint look healthy, and a warm cache makes your smoke test pass when the WSDL is already broken. Periodically exercise the uncached path; treat cache hit-rate as an observability metric, not a success metric.

WSDL drift is your dominant external risk. Nobody versions the RM contract for you. Record which RM version each integration was built against, pin the package version (^4.5.0), and re-run your smoke test after any RM upgrade on the vendor side. Budget for this review independent of package upgrades.

SOAP is synchronous — design for upstream latency. Set explicit connect/read timeouts well under your request timeout, and never put a slow RM call mid-way through a user-facing transaction if you can move it to a queue. There's no async story here; if you need throughput, batch where the RM service allows it.

Don't hold bindings across requests. In queue workers or Octane, resolve the client per job and release it. A shared client that accumulates headers or context will eventually make a call as the wrong coligada — and you'll only find out from the data.

Small package, thin ecosystem. One star, zero dependents, single maintainer. That's not disqualifying — recent 4.5.0 hardening, Pint, PHPStan, Dependabot, and a real test suite are good signals — but pin the version, read the tests rather than trusting docs alone, and be prepared to own a fork if the maintainer goes quiet. The MIT license makes that a legitimate fallback.

Mirror their quality gates. The package ships Pint + PHPStan configs. Match your PHPStan level to theirs so your own code doesn't fail where theirs passes, and treat vendor/ lint violations as noise in your IDE rather than a reason to change style rules.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource