Square API responds with empty JSON - square-connect

Why am I receiving an empty response from the Square server?
I can't seem to get any sort of response once I change the location to one of the test locations. I'm using the correct sandbox token. Have I unintentionally omitted necessary information or triggered some sort of bug or security mechanism? I can not imagine an empty response being appropriate in any circumstance. Sensitive strings obfuscated for obvious reasons.
PHP
$url = 'https://connect.squareup.com/v2/locations/'.$location_id.'/transactions';
$curl_handle = curl_init($url);
$request_headers = array();
$request_headers[] = 'Content-Type: application/json';
$request_headers[] = 'Accept: application/json';
$request_headers[] = 'Authorization: Bearer '.$token;
$encodedData = json_encode($jsonData);
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $encodedData);
$request_headers[] = 'Content-Length: '.strlen($encodedData);
curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($curl_handle, CURLOPT_HTTPHEADER, $request_headers);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curl_handle);
JSON used in cURL Request
{
"idempotency_key": "1",
"billing_address": {
"address_line_1": "123 Main Street",
"address_line_2": "",
"locality": "New York City",
"administrative_district_level_1": "NY",
"postal_code": "12345",
"country": "US"
},
"amount_money": {
"amount": 10,
"currency": "USD"
},
"delay_capture": false,
"buyer_email_address": "test#example.com",
"card_nonce": "122333444455555666666777777"
}
Using print_r(curl_getinfo($curl_handle)) I receive:
Array
(
[certinfo] => Array()
[connect_time] => 0.101375
[content_type] => application/json
[download_content_length] => 2
[filetime] => -1
[header_size] => 372
[http_code] => 200
[local_ip] => 66.198.240.51
[local_port] => 44428
[namelookup_time] => 0.009074
[pretransfer_time] => 0.392582
[primary_ip] => 74.122.190.85
[primary_port] => 443
[redirect_count] => 0
[redirect_time] => 0
[redirect_url] =>
[request_size] => 734
[size_download] => 2
[size_upload] => 492
[speed_download] => 3
[speed_upload] => 979
[ssl_verify_result] => 0
[starttransfer_time] => 0.502108
[total_time] => 0.502167
[upload_content_length] => 492
[url] => https://connect.squareup.com/v2/locations/__example__/transactions
)

Is there are reason why you aren't using the PHP SDK? I think that would make this a little easier for you, keeping track of all these curl options looks kind of confusing.
You are sending a GET request to the transactions endpoint asking the API to list all your transactions. For GET requests, adding a body to your requests is not a good idea since it is ignored by nearly every API out there (like ours).
The API receives your GET request and returns to you your transactions which you probably haven't created any in your testing account likely looks like:
{}
This is the expected behavior. If you are trying to create a charge and not list your transactions, send a POST request instead, or just use the SDK to make things easier on you, see Charge

Related

Sending a patch request to edit video using vimeo api not working

I am trying to send a patch request to edit a video using vimeo api using ruby. The request is successful but vimeo is not able to read my the payload(the title and description), that is, the the title and the description is not getting changed. I have used HTTParty, RestClient as well as Net::HTTP but none of it works. Below are my code that i have implemented to send a patch request,
RestClient
payload = {"description" => "Test Description", "name" => "Test Video"}
res = RestClient.patch(
vimeo_edit_url,
payload.to_s,
{ "Authorization" => auth })
NET::HTTP
options = {'description' => "Test Description", 'name' => "Test Video"}
edit_req = Net::HTTP::Patch.new(vimeo_edit_url, initheader = { "Authorization" => auth})
edit_req.data = options.to_s
edit_uri = URI(vimeo_edit_url)
edit_http = Net::HTTP.new(edit_uri.host, edit_uri.port)
edit_http.use_ssl = true
edit_http.verify_mode = OpenSSL::SSL::VERIFY_PEER
edit_response = edit_http.request(edit_req)
Usually the response will be a 200 OK with the updated video details but I get a 200 OK with video details(title and description not being changed). It is as if like vimeo is not able to read my payload.
You probably want to be passing payload, not payload.to_s.
That .to_s is turning your nicely arranged hash into a weird rubyified string, and all of the HTTP libraries you mentioned will accept a hash and handle the conversion for you.
Here's what some different representations look like in an irb session:
>> payload = {"description" => "Test Description", "name" => "Test Video"}
>> payload
=> {"description"=>"Test Description", "name"=>"Test Video"}
>> payload.to_s
=> "{"description"=>"Test Description", "name"=>"Test Video"}"
>> require 'json'
=> true
>> payload.to_json
=> "{"description":"Test Description","name":"Test Video"}"

Best way of calculating stripe taxamo price including tax

Hi I'm curious of how to best calculate the price including VAT for a product pre checkout. Currently the only way I found is creating a order containing the item and then fetching the tax and price from the order. This however creates a lot of redundant orders and seems sub optimal. Is there a way to do this calculation without creating an order?
def get_price
location = current_user.location
location_data = APP_CONFIG['country_list'][location]
currency = location_data['currency']
country_code = location_data['code']
product_id = APP_CONFIG['stripe_reconstruction_ids'][currency]
product = Stripe::Product.retrieve(product_id)
product_sku = product['skus']['data'][0]['id']
ip = request.remote_ip
order = Stripe::Order.create(
:currency => currency,
:customer => current_user.stripe_id,
:items => [
{
:type => 'sku',
:parent => product_sku,
:quantity => 1,
:currency => currency
}
],
:email => current_user.email,
:metadata => {
:buyer_ip => ip,
:billing_country_code => country_code,
:product_type => 'e-service'
}
)
render :json => order, :status => 200 and return
rescue => error
logger.error error.message
render :json => { message: "Could not fetch the correct price." }, :status => 500 and return
end
UPDATE
After talking to the stripe support my proposal seems to be the best way to do this at the moment. I suggested to them that it would be nice if developers could set a flag on the order that it was just for pricing information to avoid creating an order that would not later be used for a payment. They said they would deliver this suggestion to their developers. Perhaps we will have a better way to do this in the future.
You can use Taxamo's API Calculate tax endpoint (Ruby client lib is available).
Note that if setting buyer_ip private token must be used, otherwise field is ignored.
Example curl call:
curl -X 'POST' -H "Content-Type: application/json" -d \
'{
"transaction": {
"currency_code": "EUR",
"transaction_lines": [
{
"custom_id": "line1",
"product_type": "e-service",
"amount": 100
}
],
"billing_country_code": "SOME_COUNTRY_CODE",
"buyer_ip": "SOME_IP"
},
"private_token": "YOUR_PRIVATE_TOKEN"
}' \
https://api.taxamo.com/api/v1/tax/calculate | python -m json.tool

Saving Point to a Google Fitness API (fitness.body.write)

Im trying to save a Point with float value into fitness.body.
Getting value is not a problem, while saving a new point causes 403. No permission to modify data for this source.
Im using DataSetId derived:com.google.weight:com.google.android.gms:merge_weight to find point and read value, and raw:com.google.weight:com.google.android.apps.fitness:user_input to insert data.
.
Here is a workflow using Ruby and google-api-ruby-client:
require 'google/api_client'
require 'google/api_client/client_secrets'
require 'google/api_client/auth/installed_app'
require 'pry'
# Initialize the client.
client = Google::APIClient.new(
:application_name => 'Example Ruby application',
:application_version => '1.0.0'
)
fitness = client.discovered_api('fitness')
# Load client secrets from your client_secrets.json.
client_secrets = Google::APIClient::ClientSecrets.load
flow = Google::APIClient::InstalledAppFlow.new(
:client_id => client_secrets.client_id,
:client_secret => client_secrets.client_secret,
:scope => ['https://www.googleapis.com/auth/fitness.body.write',
'https://www.googleapis.com/auth/fitness.activity.write',
'https://www.googleapis.com/auth/fitness.location.write']
)
client.authorization = flow.authorize
Forming my new data Point:
dataSourceId = 'raw:com.google.weight:com.google.android.apps.fitness:user_input'
startTime = (Time.now-1).to_i # 1 Second ago
endTime = (Time.now).to_i
metadata = {
dataSourceId: dataSourceId,
maxEndTimeNs: "#{startTime}000000000", # Faking nanoseconds with tailing zeros
minStartTimeNs: "#{endTime}000000000",
point: [
{
endTimeNanos: "#{endTime}000000000",
startTimeNanos: "#{startTime}000000000",
value: [
{ fpVal: 80 }
]
}
]
}
Attempting to save the point:
result = client.execute(
:api_method => fitness.users.data_sources.datasets.patch,
:body_object => metadata,
:parameters => {
'userId' => "me",
'dataSourceId' => dataSourceId,
'datasetId' => "#{Time.now.to_i-1}000000000-#{(Time.now).to_i}000000000"
}
)
And as I indicated previously im getting 403. No permission to modify data for this source
#<Google::APIClient::Schema::Fitness::V1::Dataset:0x3fe78c258f60 DATA:{"error"=>{"er
rors"=>[{"domain"=>"global", "reason"=>"forbidden", "message"=>"No permission to modif
y data for this source."}], "code"=>403, "message"=>"No permission to modify data for
this source."}}>
I believe, I selected all required permissions in the scope. I tried submitting the point to both accessible datasetid's for fitness.body.
Please let me know if im doing anything wrong here.
Thank you!
I encountered the same situation, turns out you can NOT insert data points directly into the datasource "raw:com.google.weight:com.google.android.apps.fitness:user_input". From the name, one might guess out this datasource is reserved. So the workaround is to add your own datasource, note should with dataType.name="com.google.weight", like this:
{
"dataStreamName": "xxxx.body.weight",
"dataType": {
"field": [
{
"name": "weight",
"format": "floatPoint"
}
],
"name": "com.google.weight"
},
"dataQualityStandard": [],
"application": {
"version": "1",
"name": "Foo Example App",
"detailsUrl": "http://example.com"
},
"device": {
"model": "xxxmodel",
"version": "1",
"type": "scale",
"uid": "xxx#yyy",
"manufacturer": "xxxxManufacturer"
},
"type": "derived"
}
then after the successful creation, you can use this datasource(datastream id) to insert your own data points, and then the inserted data points will also be included in the datasource "derived:com.google.weight:com.google.android.gms:merge_weight" when you do the querying with suffix "dataPointChanges".
Try adding an Authorization header:
result = client.execute(
:api_method => fitness.users.data_sources.datasets.patch,
:headers => {'Authorization' => 'Bearer YOUR_AUTH_TOKEN'},
:body_object => metadata,
:parameters => {
'userId' => "me",
'dataSourceId' => dataSourceId,
'datasetId' => "#{Time.now.to_i-1}000000000-#{(Time.now).to_i}000000000"
}
)

The merge tags in mandrill don't work in codeigniter

I use Mandrill plugin for Codeigniter.
I created HTML template through Mandrill account, named fess1 with merge tag FNAME, after I published it.
Example:
...
<p>
<span>Hi *|FNAME|*,<br></span>
</p>
....
Now I try to send mail from codeigniter like:
private function sendMailMandrill($owner_name,$business_name,$owner_email){
$message = array('dest_mail' => $owner_email);
$message['to'] = array(array('email' => 'mim#wefi.com'));
$mergeVars[] = array(
'rcpt' => array(array('email' => 'mim#wefi.com')),
'vars' => array(
array(
'name' => 'FNAME',
'content' => 'Fessy'
)
)
);
$message['merge'] = true;
$template_name = 'fess1';
$template_content = array( // I don't know what I need to provide here, left it empty
array(
'name' => 'example name',
'content' => 'example content'
)
);
$message['merge_vars'] = $mergeVars;
return $this->mandrill->messages_send_template($template_name, $template_content, $message);
}
The result:
I get the mail, based on fess1 template, but with the tag *|FNAME|*.
Sounds like Mandrill didn't recognize the merge tag.
I used mandrill->messages_send_template but since my template stored into Mandrill account I have no clue what I need to provide for $template_content.
So I wrote dummy info there.
Did I miss something?
Thank you,
[EDIT]
From logs this is what I send:
{
"template_name": "fess1",
"template_content": [
{
"name": "example name",
"content": "example content"
}
],
"message": {
"owner_name": "עידו",
"business_name": "פלאפל מוסקו",
"dest_mail": "maxim#wifi.com",
"to": [
{
"email": "maxim#wifi.com"
}
],
"merge": "true",
"merge_vars": [
{
"rcpt": [
{
"email": "maxim#wifi.com"
}
],
"vars": [
{
"name": "FNAME",
"content": "Fessy"
}
]
}
]
},
"key": "xxxxxxxxxxxxxxxx"
}
You can provide blank information for the template_content parameter. That parameter allows you to use mc:edit regions in your template. It is a required parameter, but a blank array will suffice if all of the content is in your template in Mandrill.
As for whether the merge_vars were recognized, the first thing we recommend is inspecting the API Logs for your account (Settings > API Logs) since that will show you the JSON that Mandrill received. You can then compare that to the expected JSON format from the Mandrill API docs: https://mandrillapp.com/api/docs/messages.JSON.html#method=send-template
It looks like your arrays may not be nested as expected. Once you view the JSON that's being generated as compared with the expected format, you can also view the PHP documentation for the Mandrill PHP client. It may not be identical to the CodeIgniter plugin, but should give you an idea of how the merge_vars parameter would be structured in PHP: https://mandrillapp.com/api/docs/messages.php.html
In mergeVars you created array instead key:value. Change it to:
'rcpt' => 'mim#wefi.com',

Why do I get a 401 error when using Ruby to execute a Google Fusion Tables API command?

I'm using the Ruby gem 'google-api-client', and I make sure to add in all my credentials, but for some reason, I keep getting a 401 error from Google.
Here's my code:
['google/api_client','json'].each{|g| require g}
client_secrets = File.open('client_secrets.json','r').read # My client secrets are stored in this .JSON file
client_secrets_hsh = JSON.parse(client_secrets)
client = Google::APIClient.new
client.authorization.client_id = client_secrets_hsh['installed']['client_id']
client.authorization.client_secret = client_secrets_hsh['installed']['client_secret']
client.authorization.redirect_uri = client_secrets_hsh['installed']['redirect_uris'][0]
client.authorization.access_token = 'MY_ACCESS_TOKEN'
client.authorization.username = 'MY_USER_NAME#gmail.com'
client.authorization.password = 'MY_GOOGLE_ACCOUNT_PASSWORD'
client.authorization.scope = 'https://www.googleapis.com/auth/fusiontables'
request_body = ''
headers = []
headers << ['Content-Type','application/json']
api = client.discovered_api('fusiontables','v1')
result = client.execute(
:api_method => api.to_h['fusiontables.table.list'],
:parameters => {'maxResults' => 1000},
:merged_body => request_body,
:headers => headers
)
puts result.response.body
And here's the response I get back from the puts results.response.body line:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "authError",
"message": "Invalid Credentials",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Invalid Credentials"
}
}
Username and password should not be supplied. Try dropping those to start. You only need the access token in order to make API calls. Which, incidentally, I'm not sure where you got that from. Usually you'd need to make a call to fetch_access_token! somewhere. It's normally not something you set via an accessor. There are advanced cases where you would – but you're probably not one of them.

Resources