BulkEnvelopesApi Docusign request data format - ruby

I am stuck when using BulkEnvelopesApi rom Docusign API for Ruby. It keep on returning me this error:
DocuSign_eSign::ApiError (Bad Request):
Edit: After #kiddorails suggestion to include debug = True, the error message is:
{ "errorCode": "UNSPECIFIED_ERROR", "message": "Value cannot be
null.\r\nParameter name: stream" }
I am using this gem: https://github.com/docusign/docusign-ruby-client
Is there anything wrong with the format of how I input the data?
Here's my code for reference.
def self.send_env()
self.auth # To initialize the #api_client
t1 = DocuSign_eSign::TemplatesApi.new(#api_client)
signer_placeholder ={"signers":[{"email":"bulk#recipient.com","name":"Bulk Recipient",
"routingOrder":1,"recipientId":"1","roleName":"Fruit",
"isBulkRecipient":"True"}]}
t1.update_recipients(account_id=ENV["ACCOUNT_ID_LIVE"], template_id=ENV["TEMPLATE_ID_LIVE"], template_recipients=signer_placeholder)
br = DocuSign_eSign::BulkRecipient.new(
{
"accessCode": '112233',
"email": 'berry#gmail.com',
"name": 'Berry',
"rowNumber":1
}
)
brr = DocuSign_eSign::BulkRecipientsRequest.new({"bulkRecipients": Array(br)})
bea = DocuSign_eSign::BulkEnvelopesApi.new(#api_client)
bea.update_recipients(account_id=ENV["ACCOUNT_ID_LIVE"], envelope_id=ENV["TEMPLATE_ID_LIVE"],
recipient_id="1",bulk_recipients_request=brr)
I am able to call other Docusign APIs using this similar data format. Only unable to work for BulkEnvelopesAPI.
I am thinking whether is there anything wrong with the source code for this BulkEnvelopesAPI function.
Thank you for reading!

With #kiddorails help, I've managed to solve it.
Here's the solution:
First, edit the source code in this format. Main idea is to change the Content-Type into 'text/csv', and input a string into the body.
def update_recipients_with_http_info(account_id, envelope_id, recipient_id, bulk_recipients_request)
if #api_client.config.debugging
#api_client.config.logger.debug "Calling API: BulkEnvelopesApi.update_recipients ..."
end
# verify the required parameter 'account_id' is set
fail ArgumentError, "Missing the required parameter 'account_id' when calling BulkEnvelopesApi.update_recipients" if account_id.nil?
# verify the required parameter 'envelope_id' is set
fail ArgumentError, "Missing the required parameter 'envelope_id' when calling BulkEnvelopesApi.update_recipients" if envelope_id.nil?
# verify the required parameter 'recipient_id' is set
fail ArgumentError, "Missing the required parameter 'recipient_id' when calling BulkEnvelopesApi.update_recipients" if recipient_id.nil?
# resource path
local_var_path = "/v2/accounts/{accountId}/envelopes/{envelopeId}/recipients/{recipientId}/bulk_recipients".sub('{format}','json').sub('{' + 'accountId' + '}', account_id.to_s).sub('{' + 'envelopeId' + '}', envelope_id.to_s).sub('{' + 'recipientId' + '}', recipient_id.to_s)
# query parameters
query_params = {}
# header parameters
header_params = {}
# HTTP header 'Accept' (if needed)
header_params['Accept'] = #api_client.select_header_accept(['application/json'])
header_params['Content-Type'] = 'text/csv'
# form parameters
form_params = {}
# http body (model)
# post_body = #api_client.object_to_http_body(bulk_recipients_request)
# puts bulk_recipients_request
# post_body = body_params
auth_names = []
data, status_code, headers = #api_client.call_api(:PUT, local_var_path,
:header_params => header_params,
:query_params => query_params,
:form_params => form_params,
:body => bulk_recipients_request,
:auth_names => auth_names,
:return_type => 'BulkRecipientsSummaryResponse')
if #api_client.config.debugging
#api_client.config.logger.debug "API called: BulkEnvelopesApi#update_recipients\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
end
return data, status_code, headers
end
end
Secondly, set bulk_recipients_request to be a string (with newlines for each row of data)
"rowNumber,email,name,Accesscode\n"+"1,berry#gmail.com,Berry,11223\n"

Related

How to include image data and boundaries in Post body?

I need to include an image in the body of a Post request using Ruby. The example uses Bing Visual Search API to find images similar to the image sent in the Post body. I'm getting a result but it's empty JSON. There is evidently something wrong with the code to set up the Post body. I'm new to the Ruby language.
There are text boundaries in the Post body that have to be included with the image data. I know the query works because I can send the same request using C# or Java and get results. I've tried base64encode the image data and simply reading the file in to the Post array.
# include libs
require 'net/https'
require 'uri'
require 'json'
require 'base64'
accessKey = "Access_Key_String"
uri = "https://api.cognitive.microsoft.com"
path = "/bing/v7.0/images/visualsearch"
batchNumber = "097ad727-862d-4720-93c4-08f7038cea7c"
fileName = "ElectricBike.jpg"
if accessKey.length != 32 then
puts "Invalid Bing Search API subscription key!"
puts "Please paste yours into the source code."
abort
end
def BuildFormDataStart(batNum, fileName)
startBoundary = "--batch_" + batNum
return startBoundary + "\r\n" + "Content-Disposition: form-data;
name=\"image\"; filename=" + "\"" + fileName + "\"" + "\r\n\r\n"
end
def BuildFormDataEnd(batNum)
return "\r\n\r\n" + "--batch_" + batNum + "--" + "\r\n"
end
# Construct the endpoint uri.
uri = URI(uri + path)
# Load the parts of the post body into an array.
post_body = []
# Add the file Data
post_body << BuildFormDataStart(batchNumber, fileName)
post_body << File.read(fileName) #Base64.encode64(File.read(fileName))
post_body << BuildFormDataEnd(batchNumber)
# Create the HTTP objects
header = {'Ocp-Apim-Subscription-Key': accessKey}
# Create the request.
request = Net::HTTP::Post.new(uri, 'knowledgeRequest' => "KnowledgeRequest")
request['Ocp-Apim-Subscription-Key'] = accessKey
request.content_type = "multipart/form-data; boundary=batch_" + batchNumber
request.body = post_body.join
# Send the request and get the response.
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
http.request(request)
end
puts "\nRelevant Headers:\n\n"
response.each_header do |key, value|
# Header names are lower-cased.
if key.start_with?("bingapis-") or key.start_with?("x-msedge-") then
puts key + ": " + value
end
end
puts "\nJSON Response:\n\n"
puts JSON::pretty_generate(JSON(response.body))
Ruby result is empty, but C# example online works:
https://learn.microsoft.com/en-us/azure/cognitive-services/bing-visual-search/quickstarts/csharp
"tags": [
{
"displayName": "",
"actions": [
{
"actionType": "MoreSizes"
},
{
"actionType": "ImageById"
}
]
}
],
"image": {
"imageInsightsToken": ""
}
In reviewing Ruby's Net::HTTP class, I found a reference that says to use Net::HTTP#post_form for multipart form data. I'd try refactoring your code to use this method to populate the form body, instead of directly setting it to a string value. It may be that your form data is not being read correctly when the post body is set directly.

Rho Mobile: Parse and create a model using JSON

I am able to parse a JSON using the following code
$httpresult = #params['body']
$jsonresult = Rho::JSON.parse($httpresult)
But I don't know how to create a model from $jsonresult.
First, using app_info you can print the result coming from the server to check if the response is valid JSON string.
Second, i think you must decode the url in order to parse it by using:
Rho::JSON.parse(Rho::RhoSupport.url_decode(#params['body']))
Once you've the data in json_result, you can put them in a pre-existing Model.
Supposing that you've already created a model with the name "Product", you can use transactions to speed up the process.
At the beginning of your module you've to require the model name:
require_source 'Product'
Then you can do this callback:
def get_callback
if #params['status'] == "ok"
json_result = Rho::JSON.parse(#params['body'])
db = ::Rho::RHO.get_src_db('Product')
db.start_transaction
Product.delete_all
begin
json_result.each do |item|
Product.create({:Brand => item["B rand"], :Name => item["Name"], :SKU => d["SKU"]})
end
db.commit
rescue Exception => e
trace_msg = e.backtrace.join("\n")
puts 'Application initialize failed: ' + e.inspect + ";Trace: #{trace_msg}"
db.rollback
end
WebView.navigate Rho::RhoConfig.start_path
else
WebView.navigate url_for :action => :show_error
end
end

Retrieving full request string using Ruby curl

I intend to send a request like the following:
c = Curl::Easy.http_post("https://example.com", json_string
) do |curl|
curl.headers['Accept'] = 'application/json'
curl.headers['Content-Type'] = 'application/json'
curl.headers['Api-Version'] = '2.2'
end
I want to log the exact http request that is being made. Is there a way to get the actual request that was made (base path, query parameters, headers and body)?
The on_debug handler has helped me before. In your example you could try:
curl.on_debug do |type, data|
puts type, data
end
You can reach the solution in differents manner:
Inside your block you can put:
curl.verbose = true # that prints a detailed output of the connection
Or outside the block:
c.url # return the url with queries
c.total_time # retrieve the total time for the prev transfer (name resolving, TCP,...)
c.header_str # return the response header
c.headers # return your call header
c.body_str # return the body of the response
Remember to call c.perform (if not yet performed) before call these methods.
Many more option can be found here: http://curb.rubyforge.org/classes/Curl/Easy.html#M000001

Ruby HTTP Post containing multiple parameters and a body

I need to post using three parameters and a body which consists of 512 bytes. I can get the body right but I can't seem to get the parameters to take:
require 'net/http'
#ip_address = Array['cueserver.dnsalias.com']
#cueserver = 0
#playback = 'p1'
def send_cuescript(data)
params = {'id' => '1', 'type' => "20",'dst' => 'RES' }
begin
url = URI.parse('http://'+ #ip_address[#cueserver] + '/set.cgi')
http = Net::HTTP.new(url.host, url.port)
response, body = http.post(url.path, params, data)
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
end
response_array = []
puts 'got this value: ' + response.to_s
response.body.each_byte { |e| response_array.push(e.to_s(16))}
end
data_array = Array.new(512, "\x80")
send_cuescript(data_array.join)
I am getting an error from the initialize_http_header. I know there must be a way to set the parameters and the body separately but I can't seem to find any reference to this.
Why do you have to send part of the params in the url and part of it in the body?
If you have to do this, try
url = URI.parse('http://'+ #ip_address[#cueserver] + '/set.cgi?' + params.to_param)
PS: to_param is from active support. You need to write your own if you are not using active support.

better ruby - possible to not repeat parts of a function?

I have a little sinatra api that I'm trying to beautify. Most of my routes are simple db operations but a few involve calling an external service before doing db operations. In all cases most of the code is the same except for how I respond to the service response. Is there any slick functional programming approach?
Here's an example of one of these routes:
get '/update_x' do
validateParams(params,:x)
xid = params[:x]
xName = getNameFromId(xid)
if xName
# Make request to proxy service
rid = generateRandomHexNumber(16) # generate requestId
params['m'] = 'set'
params['rid'] = rid
json = "{}"
begin
response = #resource["/"+"?rid=#{rid}&id=#{xid}&json=#{json}"].get
status = response.code
body = response.body
parsed_json = JSON(body)
if parsed_json['response'] and parsed_json['response']['success'] and parsed_json['response']['success']=='false'
msg = {:success => "false", :response => "unknown error"}
if parsed_json['response']['response']
msg = {:success => "false", :response => parsed_json['response']['response']}
end
content_type :json
msg.to_json
else
#### Here is stuff specific to this api call
updateDBHelper(xid,buildUpdateOptions(params))
params['ss_status'] = status
content_type :json
params.to_json
#### End specific to api call
end
rescue Exception=>e
params['ss_status'] = status
params['exception'] = e
content_type :json
params.to_json
end
else
msg = {:success => "false", :response => "Not found"}
content_type :json
msg.to_json
end
end
In general if you have a general pattern with some arbitrary code that changes every time then the simplest thing would be accepting a block with those customizations.
def make_api_request(some, params)
# do what you need to do
yield(variables, that, your_custom_code, needs)
# do some more, maybe cleanup
end
get '/some_route' do
make_api_request do |variables, that, your_custom_code, needs|
# do custom stuff here
end
end

Resources