Activating customers via API

Hi @spencer we’re not entirely clearly on this. What would be in the charge-to href field in this case? We did not find any customer ID for the Master Account. The main payment was $1 and it should send 0.95 to seller and 0.5 to the master Dwolla account.

"_links":{
	"source":{
		"href":"THIS IS THE BUYER FUNDING SOURCE LINK"
	},
	"destination":{
		"href":"THIS IS THE SELLER'S FUNDING SOURCE LINK"
		}
	},
	"amount":{
		"currency":"USD",
		"value":0.95
	},
	"fees":{
		"_links":{
		"charge-to":{
			"href":"WHAT IS THE MASTER CUSTOMER LINK? OR HERE WILL BE SELLER FUNDING SOURCE OR SELLERS CUSTOMER LINK? OR BUYER CUSTOMER LINK/FUNDING SOURCE LINK"
		}
	},
	"amount":{
		"value":0.05,
		"currency":"USD"
		}
	},

Hi @sunlightmedia, If the Buyer (source) is being charged the fee in the transaction then it’ll be a link to the Customer resource that represents that buyer. i.e. https://api-sandbox.dwolla.com/customers/cc7c1e33-1fc7-4a2a-85ca-9058e6658668

Here’s an example:

$transfer = $transfersApi->create([
  '_links' => [
    'source' => [
      'href' => 'https://api-sandbox.dwolla.com/funding-sources/c91d6516-1855-4d36-be7c-bc78cc7c52c3',
    ],
    'destination' => [
      'href' => 'https://api-sandbox.dwolla.com/funding-sources/ae245cd4-ee55-4d20-8bad-a24642c9473f'
    ]
  ],
  'amount' => [
    'currency' => 'USD',
    'value' => '22.00'
  ],
  'fees' => [
    [
     '_links' => [
           'charge-to'=>[
              'href'=> 'https://api-sandbox.dwolla.com/customers/089cd9b4-fb5a-449e-a90e-30ffd83bbb9b'
            ]
        ],
        'amount' => [
             'value' => '2.00', // fee
              'currency' => 'USD'
           ]
    ]]
]);

@spencer Does that mean that the source href = buyer’s funding source, and destination href = seller’s funding source, and fees charged to href link will be buyer’s account link?. If so, that’s how we currently have it set up.

EG: Buyer purchased a $1 product, so $0.95 will be sent to the seller and $0.05 will be sent to the main admin.

@sunlightmedia, Yep, that’s correct!

@spencer One issue we’re having is that transactions are occurring, but the fees are not listed in the Dwolla account transaction list in the Merchant account. Only the seller transactions are visible.

@sunlightmedia, The issue might be how you’re passing in the Fees request param. It’s an array of Fee Objects which looks something like this:

{
"_links": {
    "source": {
        "href": "https://api-sandbox.dwolla.com/funding-sources/{{VCRBalanceFundingSourceId}}"
    },
    "destination": {
        "href": "https://api-sandbox.dwolla.com/funding-sources/{{CRFundingSourceId}}"
    }
},
"amount": {
    "currency": "USD",
    "value": "42.00"
},
"metadata": {
    "foo": "bar"
},
"fees": [
    {  
       "_links":{  
          "charge-to":{  
             "href":"https://api-sandbox.dwolla.com/customers/{{CRCustomerId}}"
          }
       },
       "amount":{  
          "value":"2.00",
          "currency":"USD"
       }
    }
]    

}

Can you share some of your code where you’re specifying Fees to confirm these are being passed in properly? If they aren’t we’ll ignore them and create the transaction without fees.

Hi @spencer, transaction without fees are working fine. We’ll just need to provide the admin merchant a commission of 5-10%. That’s why we’ve added fees. Below is some sample code:

include('../dwolla/vendor/autoload.php'); 
$curl = curl_init();
	curl_setopt($curl, CURLOPT_URL,DWOLLA_POST_URL_TOKEN);  
	curl_setopt($curl, CURLOPT_FAILONERROR, true);
	curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
	 
	 $postData = array(
	 	'client_id' => DWOLLA_CLIENT_ID,
	 	'client_secret' => DWOLLA_CLIENT_SECRET,
	 	'grant_type' => 'client_credentials'
	 );
	 curl_setopt($curl, CURLOPT_POST, true);
	 curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($postData));
	 curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/x-www-form-urlencoded' )); // send JSON and expect JSON
	 
	//// Timeout in seconds
	 curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 0);
	 curl_setopt($curl, CURLOPT_TIMEOUT, 60);
	//// Dont verify SSL certificate (eg. self-signed cert in testsystem)
	 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
	 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
	 $output = curl_exec($curl);
	if ($output === FALSE) {
		echo 'An error has occurred: ' . curl_error($curl) . PHP_EOL;
	}
	else {
		$output = json_decode($output) ;
		
		$token = $output->access_token;
	}
	
	DwollaSwagger\Configuration::$access_token = $token;
	DwollaSwagger\Configuration::$debug = 1;
	$apiClient = new DwollaSwagger\ApiClient(DWOLLA_API_CLIENT); 
	
	$transfersApi = new DwollaSwagger\TransfersApi($apiClient);
	$transfer = $transfersApi->create([
	  '_links' => [
	    'source' => [
	      'href' => $general_func->get_field_value(TBL_PREFIX. "user", "dwallo_funding_source", "user_id", $user_id) // Buyer funding source
	    ],
	    'destination' => [
	      'href' => $general_func->get_field_value(TBL_PREFIX. "user", "dwallo_funding_source", "user_id", $seller_id) // Seller funding source

	    ]
	  ],
	  'amount' => [
	    'currency' => 'USD',
	    'value' => '0.95'
	  ],
	  'fees' =>[
		   
		    '_links' => [
		      'charge-to' => [
		      'href' => $general_func->get_field_value(TBL_PREFIX. "user", "dwallo_account", "user_id", $user_id) // Buyer account URl

		      ]
		      ],
		    'amount' => [
		      'value' => 0.05,
		      'currency' => "USD"
		    ]
		   
		],
	  'metadata' => [
	    'paymentId' => $invoice,
	    'note' => 'payment for #'.$invoice,
	  ],
	  'clearing' => [
	    'destination' => 'next-available'
	  ],
	  'correlationId' => session_id()
	]);

 echo '<pre>'.print_r($post,true).'</pre>';  

Hi @spencer, just following up on this

@sunlightmedia, it looks like your fees array is missing an extra set of brackets.

'fees' => [
[
 '_links' => [
       'charge-to'=>[
          'href'=> 'https://api-sandbox.dwolla.com/customers/089cd9b4-fb5a-449e-a90e-30ffd83bbb9b'
        ]
    ],
    'amount' => [
         'value' => '2.00', // commission
          'currency' => 'USD'
       ]
]]

Thank you, @spencer – this is working now.

The only remaining issue we have is related to document uploads. We’ve tried to upload PDFs and JPEG files, but are receiving an error.

$target_url =  'https://api-sandbox.dwolla.com/customers/83a44d27-ddfa-4b72-8d80-d34546a46a78/documents';
  $file_name_with_full_path =  '/documents/sample.jpg' ;  
  $post = array('documentType' => 'passport','file'=>'@'.$file_name_with_full_path); 
  $ch = curl_init();
  $headers = array(
    'Content-type: multipart/form-data',
    'Authorization: Bearer '. $token,
    'Accept: application/vnd.dwolla.v1.hal+json',
); 
  curl_setopt($ch, CURLOPT_URL,$target_url);
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_POST,1);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

  $result = json_decode(curl_exec($ch));
   
 
  echo '<pre>'.print_r($result,true).'</pre>';

ERROR
stdClass Object
(
    [code] => ValidationError
    [message] => Validation error(s) present. See embedded errors list for more details.
    [_embedded] => stdClass Object
        (
            [errors] => Array
                (
                    [0] => stdClass Object
                        (
                            [code] => Invalid
                            [message] => Invalid file type.
                            [path] => /file
                            [_links] => stdClass Object
                                (
                                )

                        )

                )

        )

)

Hi @spencer, just following up on this

Hi @sunlightmedia!

The curl handle in this line of your code seems to be inconsistent with the ones above it. Perhaps try changing that to:

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

When you are specifying the path for the file you are trying to upload, using the PHP realpath() function is a good practice, as it returns the canonicalized absolute pathname.

Furthermore, @spencer recommends using Guzzle, an easy-to-use PHP HTTP client library which has a simple interface for POSTing requests. They have a very well documented manual here. There is an abundance of resources on the internet on how to upload files using Guzzle.

Please let us know if the error persists; we would be glad to help you resolve it!

1 Like

Hi @shreya, we made the suggested changes and tried using Guzzle the but the realpath function is not working. It’s returning blank.

<?php 

echo echo realpath("/documents/11_053234_sample-usa-passport.jpg");
 
?>

The above code isn’t working but the file exists: https://www.rx-post.com/documents/11_053234_sample-usa-passport.jpg

After using Guzzle, we got the following error:

Client error: `POST https://api-sandbox.dwolla.com/customers/7a2b38f2-08b2-4587-baac-094b6990ac90/documents` resulted in a `400 Bad Request` response:
{"code":"BadRequest","message":"The request body contains bad syntax or is incomplete."} 
{"code":"BadRequest","message":"The request body contains bad syntax or is incomplete."}

Below is the code we’re using:

include("vendor/autoload.php");
  $client = new \GuzzleHttp\Client();  
  $file_name_with_full_path = "/home/rxpost/public_html/documents/11_231701_sample-usa-passport.jpg"
 Try {
            $response = $client->post(
                "https://api-sandbox.dwolla.com/customers/7a2b38f2-08b2-4587-baac-094b6990ac90/documents", [
                    'headers' => [
                        'Accept'                => 'application/vnd.dwolla.v1.hal+json',
                        'Content-Type'          => 'multipart/form-data',  // <-- commented out this line
                        'Authorization'         => 'Bearer '. $token,
                    ],
                    'multipart' => [
                        [
					        'name'     => 'documentType',
					        'contents' => 'passport'
					    ],
                        [
                            'name'     => 'file',
                            'contents' => fopen($file_name_with_full_path, 'r') ,
                            'filename' => "my-passport.jpg"                        ] 
                    ],
                ] 
            );
           echo $response->getBody()->getContents();
        } catch(\Exception $e) {
            echo $e->getMessage();
            $response = $e->getResponse();
            $responseBody = $response->getBody()->getContents();

            echo $responseBody;
            exit;
        }

Hi @sunlightmedia, thank you for applying the changes, and getting back to us. It seems you can omit realpath() if you are using Guzzle.

The response is referring to a syntax error in your code. I checked the Guzzle documentation for sending form files, and found that this may have something to do with how you are POSTing the data,

According to the documentation, your POST request should look something like this,

$response = $client->request(‘POST’, ‘https://api-sandbox.dwolla.com/customers/7a2b38f2-08b2-4587-baac-094b6990ac90/documents’, […

Please let us know if the code works after referring to the official documentation.

Hi @shreya

We have removed the realpath, but the same issue happens. The error is saying that “The request body contains bad syntax or is incomplete”. We also find the same error after adding that.

Both are doing same job ($client->post or $client->request(‘POST’ ). As you we haven’t been able to find any PHP-based documentation about “document upload”, we need your help regarding this. Below is our code. We did not find any issue, but the document is not uploaded.

$file_name_with_full_path = realpath($_SERVER['DOCUMENT_ROOT'].'/documents/'.$img_path)  ;
   
  include("vendor/autoload.php");
  $client = new \GuzzleHttp\Client();  
   
 Try {
            $response = $client->request('POST',
                'https://api-sandbox.dwolla.com/customers/7a2b38f2-08b2-4587-baac-094b6990ac90/documents', [
                    'headers' => [
                        'Accept'                => 'application/vnd.dwolla.v1.hal+json',
                        'Content-Type'          => 'multipart/form-data',  // <-- commented out this line
                        'Authorization'         => 'Bearer '. $token,
                    ],
                    'multipart' => [
                        [
					        'name'     => 'documentType',
					        'contents' => 'passport'
					    ],
                        [
                            'name'     => 'file',
                            'contents' => fopen($file_name_with_full_path, 'r') ,
                            'filename' => $img_path
                        ] 
                    ] 
                ] 
            );
           echo $response->getBody()->getContents();
        } catch(\Exception $e) {
            echo $e->getMessage();
            $response = $e->getResponse();
            $responseBody = $response->getBody()->getContents();

           echo '<pre>'. print_r($responseBody,true);
            exit;
        }
        
Error : {"code":"BadRequest","message":"The request body contains bad syntax or is incomplete."}
Online Documentation

Hi @shreya,

We are also facing the same issue. We have given the correct API ( $client->request(‘POST’ ) but it returns following message.
“message”: [
“BadRequest”,
“The request body contains bad syntax or is incomplete.”
]

Can you please help us with this? As we are in urgent to implement this feature in out system. Can you help me as soon as possible. Hoping to hear from you soon.

Thanks in advance.

Hi @kordharani, can you share some of your code for what this request looks like that’s returning the 400 Invalid request. This typically indicates that the request body is not syntactically correct. (e.g. invalid parameter name, missing param, etc.)

Ya, sure.

$passed_args = array(
‘headers’ => array(
‘Content-Type’ => ‘multipart/form-data’,
‘Accept’ => ‘application/vnd.dwolla.v1.hal+json’,
‘Authorization’ => 'Bearer ’ . $access_token
),
‘form_params’ => array(
‘documentType’ => $data[‘documentType’],
‘file’ => $data[‘file’]
)
);
$response = $client->post($apiUrl,$passed_args);

$data = {
“documentType”: “passport”,
“file”: {
“file”: {
“file”: “/tmp/phplfMwsr”
}
}
}

This what I am passing in the API.

Hi @kordharani – would you be able to check what happens when you change that JSON object to

“file” : “/tmp/phplfMwsr”

If you’d like, and if you have the a request ID (the value of the x-request-id field in the response headers) for that request that fails, I could check our logs to see what we’re receiving from your app. Let me know!

Thanks for you help @spencer & @shreya. It was worked after I removed the ‘Content-Type’ => ‘multipart/form-data’ from the header and passed the correct path of the file.

$response = $client->request(‘POST’, $apiUrl, [‘headers’ => [‘Authorization’ => 'Bearer ’ . $access_token,‘Accept’ => ‘application/vnd.dwolla.v1.hal+json’], ‘multipart’ => [[‘name’=> ‘documentType’,‘contents’ => ‘license’],[‘name’=> ‘file’,‘contents’ => fopen($filePath, ‘r’)]]]);

2 Likes