Transfer Failure

I have an iOS app with Plaid/Dwolla integration. This has worked for many months but the last time I tried it was a few months ago. Every once in a while I try it to make sure it is still working. Now it fails. I was using iOS14 but now have iOS17. That is the only difference. I have two versions, the proper one uses a secure server for auth and transfers (I use Heroku), and a simpler one calls the auth and transfer API directly from the app to your servers (which I know is not allowed for real production). Both versions are failing.

Here is the log from the Heroku failure which is “certificate has expired”. I have no idea what that means.
2024-05-09T21:27:53.160222+00:00 app[web.1]: Your app is listening on port 32722

2024-05-09T21:27:53.300948+00:00 heroku[web.1]: State changed from starting to up

2024-05-09T21:42:24.107531+00:00 app[web.1]: { bearer: ‘x3RPHKfj2qwVbnFiCROfn5DXpUXw51T2QICrYIyxMbee8u1A11’,

2024-05-09T21:42:24.107771+00:00 app[web.1]: destination: ‘https://api-sandbox.dwolla.com/funding-sources/e57985ec-bd30-49e2-84a0-f14a9904ede9’,

2024-05-09T21:42:24.107772+00:00 app[web.1]: amt: ‘55’ }

2024-05-09T21:42:24.107779+00:00 app[web.1]: x3RPHKfj2qwVbnFiCROfn5DXpUXw51T2QICrYIyxMbee8u1A11 https://api-sandbox.dwolla.com/funding-sources/e57985ec-bd30-49e2-84a0-f14a9904ede9 55

2024-05-09T21:42:24.107789+00:00 app[web.1]: {“amount”:{“currency”:“USD”,“value”:“55”},“_links”:{“source”:{“href”:https://api-sandbox.dwolla.com/funding-sources/5921a0ab-854d-4a11-ba3c-6f9cf61aba83},“destination”:{“href”:https://api-sandbox.dwolla.com/funding-sources/e57985ec-bd30-49e2-84a0-f14a9904ede9}}}

2024-05-09T21:42:24.107789+00:00 app[web.1]: { hostname: ‘api-sandbox.dwolla.com’,

2024-05-09T21:42:24.107790+00:00 app[web.1]: port: 443,

2024-05-09T21:42:24.107790+00:00 app[web.1]: path: ‘/transfers’,

2024-05-09T21:42:24.107790+00:00 app[web.1]: method: ‘POST’,

2024-05-09T21:42:24.107791+00:00 app[web.1]: headers:

2024-05-09T21:42:24.107791+00:00 app[web.1]: { ‘Content-Type’: ‘application/vnd.dwolla.v1.hal+json’,

2024-05-09T21:42:24.107792+00:00 app[web.1]: Accept: ‘application/vnd.dwolla.v1.hal+json’,

2024-05-09T21:42:24.107792+00:00 app[web.1]: Authorization: ‘Bearer x3RPHKfj2qwVbnFiCROfn5DXpUXw51T2QICrYIyxMbee8u1A11’ } }

2024-05-09T21:42:24.135122+00:00 app[web.1]: { Error: certificate has expired

2024-05-09T21:42:24.135124+00:00 app[web.1]: at TLSSocket. (_tls_wrap.js:1116:38)

2024-05-09T21:42:24.135124+00:00 app[web.1]: at emitNone (events.js:106:13)

2024-05-09T21:42:24.135124+00:00 app[web.1]: at TLSSocket.emit (events.js:208:7)

2024-05-09T21:42:24.135124+00:00 app[web.1]: at TLSSocket._finishInit (_tls_wrap.js:643:8)

2024-05-09T21:42:24.135125+00:00 app[web.1]: at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:473:38) code: ‘CERT_HAS_EXPIRED’ }

2024-05-09T21:42:54.105724+00:00 heroku[router]: at=error code=H12 desc=“Request timeout” method=POST path=“/dwollaTransfer” host=square-inapp-test.herokuapp.com request_id=ad50b0bb-5b0b-4a3c-bda8-4b5e3cda050b fwd=“108.20.21.169” dyno=web.1 connect=0ms service=30036ms status=503 bytes=0 protocol=https

The direct from app to your server version throws a status code 400 when the transfer occurs. The body of data sent via the API contains the source and destination funding sources as shown in the Heroku log above. No other useful information is returned but here is the returned data.
Printing description of response:
▿ Optional

  • some : <NSHTTPURLResponse: 0x600001c9d1e0> { URL: https://api-sandbox.dwolla.com/transfers } { Status Code: 400, Headers {
    “Access-Control-Allow-Origin” = (
    “*”
    );
    “Content-Length” = (
    88
    );
    “Content-Type” = (
    “application/vnd.dwolla.v1.hal+json; profile="http://nocarrier.co.uk/profiles/vnd.error/\”"
    );
    Date = (
    “Thu, 09 May 2024 22:38:20 GMT”
    );
    Server = (
    cloudflare
    );
    “cf-cache-status” = (
    DYNAMIC
    );
    “cf-ray” = (
    “88152de0ad51905c-BOS”
    );
    “x-request-id” = (
    “8fcbd82a-4318-4ca1-962a-2dba64633655”
    );
    } }

The customerID I am using is:
c271b8e8-4263-406c-934e-a402b3b26fa3

As I say, the Plaid/Dwolla code for my app has worked in the past, the only difference that I can see is the update to iOS17.

Thanks.

Shreya, Spencer, any Developer Advocate, why no reply?

Hi @burte123 , Sorry for missing your post! Here’s the error response that I’m seeing for that particular request:

{"code":"BadRequest","message":"The request body contains bad syntax or is incomplete."}

Here’s the request body that was sent:

{
    "amount": {
        "currency": "USD",
        "value": "55"
    },
    "_links": [
        {
            "source": {
                "href": "https://api-sandbox.dwolla.com/funding-sources/5921a0ab-854d-4a11-ba3c-6f9cf61aba83"
            }
        },
        {
            "destination": {
                "href": "https://api-sandbox.dwolla.com/funding-sources/9eee4fc6-3438-4baf-aac2-c455d90e89a9"
            }
        }
    ]
}

The issue with the request body is that the _links parameter should be an object, not an array. Each link (source and destination) should be a property of the _links object, not separate objects within an array.
Here is the corrected request body:

{
    "amount": {
        "currency": "USD",
        "value": "55"
    },
    "_links": {
        "source": {
            "href": "https://api-sandbox.dwolla.com/funding-sources/5921a0ab-854d-4a11-ba3c-6f9cf61aba83"
        },
        "destination": {
            "href": "https://api-sandbox.dwolla.com/funding-sources/9eee4fc6-3438-4baf-aac2-c455d90e89a9"
        }
    }
}

Hope this information helps, please let us know if you have any follow up questions!

Thanks, that fixed the problem for the method where I send the endpoint directly from my app to your servers.

But I still get that “certificate has expired” when I send the endpoint to the Heroku server as shown above. I send other endpoints to other providers using that same Heroku program and it works fine. Do you have any idea what is going on.

hmm, based on the error message it seems like the issue is on the Heroku server that’s sending the request to the Dwolla API. Are you able to confirm if you have a valid certificate and that connections to the Dwolla API are made using TLS 1.2? Maybe your certificate is outdated or expired and needs renewed?

I’m not very knowledgeable in this area of sockets. But it seems like this is an issue on your end. It is your certificate which has expired. Maybe the Dwolla sandbox SSL certificate?

I say this because I use the same Heroku program to send to endpoints for my Bluesnap credit card processing (also in the sandbox) and those execute just fine, no socket or certificate issue. So could it be on your end?

Hi @burte123, SSL certificates are typically applied on your end, specifically on the server or infrastructure from which your application makes requests to the API. When you call an API over HTTPS (HTTP Secure), you’re establishing a secure connection from your server to the API server using SSL/TLS (Transport Layer Security) encryption.

It’s unlikely that the issue with the expired cert is on our end. I leveraged the AI chatbot on our Documentation website to help come up with some actions your can take to address this issue effectively:

  1. Confirm the expiry date of the certificate, either through your SSL certificate provider or within your Heroku dashboard.
  2. Proceed to renew the SSL certificate promptly through your provider’s renewal process.
  3. Once renewed, update the SSL certificate within your Heroku app’s configuration settings. This typically involves uploading the new certificate via the Heroku dashboard or utilizing the Heroku CLI.
  4. Perform thorough testing to ensure seamless communication between your app and the Dwolla API after updating the certificate.
  5. Implement regular monitoring practices to keep track of SSL certificate expiry dates, thus preventing potential future disruptions.

Hope this helps! Should you require further guidance or encounter any challenges during this process, feel free to reach out to your SSL certificate provider or contact Heroku support for assistance.

As I mentioned, I really don’t understand this area, and can’t understand why the endpoints work for Bluesnap but not for Dwolla.

In any case good old stackoverflow provided a work around fix. I simply added rejectUnauthorized: false, to the list of options (port, path, method) and it ran with no error. I’m not sure this is a proper permanent fix, but is fine for now.

Hi @burte123 – glad you found a workaround for the time being! This should be fine for testing in the Sandbox with dummy data. In Production, however, it does leave a security loophole as it effectively disables SSL certificate validation, meaning your application will no longer verify the authenticity of the server it’s communicating with. This makes your application vulnerable to man-in-the-middle attacks, where an attacker could intercept and manipulate the data being transmitted between your application and the API server.

To ensure the safety of your application and data, it’s crucial to address the root cause by updating or renewing your SSL certificate for a secure and trustworthy connection in the long term.