Let's make the division of labor in SmashPig's Adyen code look like that of the Ingenico code.
Specifically, the class implementing PaymentProvider should be responsible for taking the normalized parameters and values, transforming them into the provider-specific parameter names (and nesting, for JSON) and value scales, and passing them off to the appropriate method on an API object. That API object should be responsible for adding any boilerplate or authentication and making the request.
Among other things, this will let us mock the API object in tests of the PaymentProvider object. Those tests shouldn't need to mock the low-level SOAP classes.