Set shipping address on paypal (ruby on rails) - ruby-on-rails

gem 'paypal-sdk-merchant'
#api = PayPal::SDK::Merchant::API.new
params = {:SetExpressCheckoutRequestDetails => payment_params.merge({
:ReturnURL => return_url,
:CancelURL => cancel_url,
})}
#set_express_checkout = #api.build_set_express_checkout(params)
i need send shipping address to paypal.
How to set shipping address in params?

When in doubt, take a look at the samples on the github SDK page.
I found this example:
set_express_checkout:
SetExpressCheckoutRequestDetails:
PaymentDetails:
PaymentAction: Sale
TaxTotal:
currencyID: USD
value: 0
ShippingMethod: UPSGround
ShippingTotal:
currencyID: USD
value: 3.0
PaymentDetailsItem:
Name: Item Name
Amount:
currencyID: USD
value: 5.27
Quantity: 1
ItemCategory: Physical
ShipToAddress:
Name: John Doe
Street1: "1 Main St"
CityName: San Jose
StateOrProvince: CA
Country: US
PostalCode: "95131"
Which leads me to believe the proper way to do it would be:
#api = PayPal::SDK::Merchant::API.new
params = {:SetExpressCheckoutRequestDetails => payment_params.merge({
:ReturnURL => return_url,
:CancelURL => cancel_url,
:PaymentDetails => {
:PaymentDetailsItem => {
:Name => "Item Name",
:Amount => {
:currencyId => "USD",
:value => "1.27"
}
},
:ShipToAddress => {
:Name => "John Doe",
:Street1 => "1 Main St",
:CityName => "San Jose",
:StateOrProvince => "CA",
:Country => "US",
:PostalCode => "95131"
}
}
}
)}
#set_express_checkout = #api.build_set_express_checkout(params)

Related

Ruby how to format nested hash

I have two queries I am running and iterating over both and my final hash is seen below. But, I want to have format on how the data is being stored in the hash that I'm creating or format it after I'm done creating it. But I am not sure how to achieve the desired format where the names fall under the same id as show below
desired format of example data:
[
{
id: 1,
accepted: false,
trans: 10234
names: [
{ name: "Joe", amount: "$1,698.00" },
{ name: "Smith", amount: "$674.24" },
]
},
{
id: 2,
accepted: true,
trans: 10234,
names: [
{ name: "Joe", amount: "$1,698.00" },
{ name: "Smith", amount: "$674.24" },
]
}
]
current format I have
[
{
:id => 1,
:accepted => false,
:trans => 8,
:name => "Smith",
:amount => 36.0
},
{
:id => 1,
:amount => false,
:trans => 8,
:name => "Joe",
:amount => 6.0
},
{
:id => 3,
:accepted => false,
:trans => 8,
:name => "Tom",
:amount => 34.0
},
{
:id => 3,
:accepted => false,
:trans=> 8,
:name => "Martha",
:amount => 4.0
}
],
[
{
:id => 2,
:accepted => true,
:trans => 7,
:name => "Bob",
:amount => 35.0
},
{
:id => 2,
:accepted => true,
:trans => 7,
:name => "John",
:amount => 5.0
}
]
logic for creating hash
imports = ListImports.limit(20).order(created_at: :DESC)
groups = imports.map{|import| ListImportGroup.where(list_import_id: import.id)}
pub_hash_true = []
pub_hash_false = []
hash = []
imports.map do |import|
hash << {
id: import.id,
trans: import.trans,
accepted: import.amount
}
end
hash.each do |import|
groups.flatten.each do |group|
accepted = import[:accepted]
num_transactions = import[:trans]
if accepted == false
pub_hash_false << {id: import[:id], accepted: accepted, trans: num_transactions, name: group.name, amount: group.amount}
else
pub_hash_true << {id: import[:id], accepted: accepted, trans: num_transactions, name: group.name, amount: group.amount}
end
end
end
# Note: You didn't specify what is the association between `ListImport` and `ListImportGroup`.
# However, I'm fairly sure you could be fetching this data via a JOIN query like below,
# rather than making up to 20 additional database calls to fetch the associated records.
imports = ListImports.limit(20).order(created_at: :DESC).includes(:list_import_group)
result = imports.map do |import|
{
id: import.id,
trans: import.trans,
accepted: import.amount,
names: import.list_import_groups.pluck(:name, :amount)
}
end
And if you do actually need to filter for imports where accepted is true or false, you could do something like this instead of building separate arrays manually:
accepted_imports = result.select { |import| import[:accepted] }
# and
rejected_imports = result.reject { |import| import[:accepted] }
# or even:
accepted_imports, rejected_imports = result.partition { |import| import[:accepted] }
You didn't specify the exact correspondence between the desired and current formats.
But I assume
For the entries with the same id, the values of accepted and trans are identical.
the desired amount for Joe in the current format is identical in the corresponding amount in the desired amount. (In your example, the former is 6.0 whereas the latter is "$1,698.00", which does not make sense.)
Then, the following would do the conversion. The array ahout is in the desired format.
# Let us assume "a1" is the original array in the "current format"
hout = {}
a1.flatten.map{|h|
h.slice(*(%i(id trans name amount accepted))).values
}.each{ |a|
hout[a[0]] = {id: a[0], accepted: a[4], trans: a[1], names: []} if !hout.key? a[0]
hout[a[0]][:names].push(
{name: a[2], amount: "$"+helper.number_with_precision(a[3], precision: 2, delimiter: ',')}
)
}
ahout = hout.values
You may want to sort ahout, if you like.
Note that I am assuming you are using Rails 5+. Otherwise, the method helper may not work. In that case, you can use sprintf or whatever formatting method.

Rails Rspec and Geocoder IP lookup

Geocoder DOCS explain how to fake a Geocoder lookup with Street addresses, but it doesn't seem to work with IP addresses.
This is my spec/support/geocoder.rb
Geocoder.configure(:lookup => :test)
Geocoder::Lookup::Test.add_stub(
"1.1.1.1", [
{
'latitude' => 10,
'longitude' => 10,
'address' => 'Test Address',
'state' => 'Test State',
'state_code' => 'TS',
'country' => 'Test Country',
'country_code' => 'TC'
}
]
)
Geocoder::Lookup::Test.set_default_stub(
[
{
'latitude' => 10,
'longitude' => 10,
'address' => 'Test Address',
'state' => 'Test State',
'state_code' => 'TS',
'country' => 'Test Country',
'country_code' => 'TC'
}
]
)
this is my service:
if params[:ip]
lat = Geocoder.search(params[:ip])[0].latitude
lng = Geocoder.search(params[:ip])[0].longitude
venues = venues.near([lat, lng], APP_CONFIG['geo_location_radius'], order: 'average_rating DESC')
end
And this is my service spec:
context "find featured venues by ip" do
let(:params) do
{
date: Date.today,
featured: true,
ip: '1.1.1.1',
}
end
it do
aggregate_failures do
expect(raw_venues.map { |v| v.id }.sort).to eq [venue1.id]
end
end
end
If I enter with pry in the it block and I try Geocoder.search('1.1.1.1') I get a "real" object response with a location in Australia instead of my stub, while I correctly get my stub if I enter something like Geocoder.search('Florence, Italy') ..
How can I setup stub responses to work with IP lookup?
Solution is simply:
Geocoder.configure(ip_lookup: :test)

getting error with paypal, activemerchant -- A field was longer or shorter than the server allows

I am trying to implement paypal payment gateway using activemerchet but getting error-A field was longer or shorter than the server allows
i am using credrntials of pro account. I saw other SO questions but it was not helpful
require 'rubygems'
require 'active_merchant'
ActiveMerchant::Billing::Base.mode = :test
gateway = ActiveMerchant::Billing::TrustCommerceGateway.new(
:login => 'XXX#gmail.com',
:password => 'my_password',
:signature => 'my_signature')
credit_card = ActiveMerchant::Billing::CreditCard.new(
:first_name => 'f_name',
:last_name => 'l_name',
:number => '4032034467080704',
:month => '9',
:year => '2021',
:verification_value => '123',
:brand => 'VISA'
)
AMOUNT = 1000
def purchase_options
{
ip: "127.0.0.1",
billing_address: {
name: "Flaying Cakes",
address1: "123 5th Av.",
city: "New York",
state: "NY",
country: "US",
zip: "10001"
}
}
end
if credit_card.validate.empty?
response = gateway.purchase(AMOUNT, credit_card, purchase_options)
if response.success?
puts "Successfully charged to the credit card #{credit_card.display_number}"
else
raise StandardError, response.message
end
else
puts "credit card is not valid #{credit_card.errors.full_messages.join(". ")}"
end
I changed
gateway = ActiveMerchant::Billing::TrustCommerceGateway.new
to
gateway = ActiveMerchant::Billing::PaypalGateway.new
and it worked fine.

Rabl for a nested hash of ActiveRecord collections

I have a few ActiveRecord objects like City, Country, State etc. My controller action is like (as a representative example):
def get_data
#data = {
cities: City.limit(2),
countries: Country.limit(2),
states: State.limit(2),
version: 1000
}
respond_with #data
end
I want to render a JSON like:
{
data: {
country: [{id: 1, name: 'a'}, {id: 2, name: 'b'}],
state: [{id: 1, name: 'p'}, {id: 2, name: 'q'}],
city: [{id: 1, name: 'x'}, {id: 2, name: 'y'}],
version: 1000
}
}
(Please note singular keys for collections, Please do not suggest changes to the JSON structure, as it is fixed.)
What should be the rabl template for this? I have been breaking my head on this for hours.
if i were you i will not even care to go to rabl template for this because what your are creating with this code:
#data = {
cities: City.limit(2),
countries: Country.limit(2),
states: State.limit(2),
version: 1000
}
is the final output , not the individual components.
you can just replace this with:
render :json => {
:data => {
cities: City.limit(2).map{ |c|{:id => c[:id] },
countries: Country.limit(2).map{ |c|{:id => c[:id] },
states: State.limit(2).map{ |c|{:id => c[:id] },
version: 1000
}
}
its not a best use case for rabl , but if you still want it to load via rabl this below code in the get_data.json.rabl will do just fine.
node :data do
{
:version_number => #data[:version_number],
:country => #data[:countries].map{ |c|{:id => c[:id] , :name => c[:name]} }
:state => #data[:states].map{ |s|{:id => s[:id] , :name => s[:name]} }
:city => #data[:city].map{ |c|{:id => c[:id] , :name => c[:name]} }
}
end

How do I access the data in JSON converted to hash by crack in ruby?

Here is the example from the crack documentation:
json = '{"posts":[{"title":"Foobar"}, {"title":"Another"}]}'
Crack::JSON.parse(json)
=> {"posts"=>[{"title"=>"Foobar"}, {"title"=>"Another"}]}
But how do I actually access the data in the hash?
I've tried the following:
array = Crack::JSON.parse(json)
array["posts"]
array["posts"] shows all the values, but I tried array["posts"]["title"] and it didn't work.
Here is what I am trying to parse as an example:
{"companies"=>[{"city"=>"San Mateo", "name"=>"Jigsaw", "address"=>"777 Mariners Island Blvd Ste 400", "zip"=>"94404-5059", "country"=>"USA", "companyId"=>4427170, "activeContacts"=>168, "graveyarded"=>false, "state"=>"CA"}], "totalHits"=>1}
I want to access the individual elements under companies....like city and name.
Like this?
hash = {
"companies" => [
{
"city" => "San Mateo",
"name" => "Jigsaw",
"address" => "777 Mariners Island Blvd Ste 400",
"zip" => "94404-5059",
"country" => "USA",
"companyId" => 4427170,
"activeContacts" => 168,
"graveyarded" => false,
"state" => "CA"
}
],
"totalHits" => 1
}
hash['companies'].each{ |i|
puts "city => #{i['city']}"
puts "name => #{i['name']}"
}
# >> city => San Mateo
# >> name => Jigsaw
hash['companies'][0]['city'] # => "San Mateo"
hash['companies'][0]['name'] # => "Jigsaw"
The problem is you didn't account for the array that companies points to.

Resources