Skip to content
This repository was archived by the owner on Nov 17, 2017. It is now read-only.
2 changes: 2 additions & 0 deletions lib/pagseguro.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
require "pagseguro/railtie"
require "pagseguro/notification"
require "pagseguro/order"
require "pagseguro/api_order"
require "pagseguro/api_payment"
require "pagseguro/action_controller"
require "pagseguro/helper"
require "pagseguro/utils"
96 changes: 96 additions & 0 deletions lib/pagseguro/api_order.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
module PagSeguro
class ApiOrder
# Map all billing attributes that will be added as form inputs.
BILLING_MAPPING = {
:name => "senderName",
:email => "senderEmail",
:phone_area_code => "senderAreaCode",
:phone_number => "senderPhone",
:address_zipcode => "shippingAddressPostalCode",
:address_street => "shippingAddressStreet",
:address_number => "shippingAddressNumber",
:address_complement => "shippingAddressComplement",
:address_neighbourhood => "shippingAddressDistrict",
:address_city => "shippingAddressCity",
:address_state => "shippingAddressState",
:address_country => "shippingAddressCountry",
}

# The list of products added to the order
attr_accessor :products

# The billing info that will be sent to PagSeguro.
attr_accessor :billing

# Optional: define the shipping type. Can be 1 (PAC) or 2 (Sedex)
attr_accessor :shipping_type

# Optional: extra amount on the purchase (negative for discount
attr_accessor :extra_amount

# Optional: specific redirect URL
attr_accessor :redirect_url

# Optional: order id in your system
attr_accessor :reference

# Optional: maximum number of uses of generated code, integer greater than 0
attr_accessor :max_uses

# Optional: maximum age of generated code in seconds, integer greater than 30
attr_accessor :max_age

def initialize(order_id = nil)
reset!
self.id = order_id
self.billing = {}
end

# Set the order identifier. Should be a unique
# value to identify this order on your own application
def id=(identifier)
@id = identifier
end

# Get the order identifier
def id
@id
end

# Remove all products from this order
def reset!
@products = []
end

# Add a new product to the PagSeguro order
# The allowed values are:
# - weight (Optional. If float, will be multiplied by 1000g)
# - quantity (Optional. Defaults to 1)
# - price (Required, can be float)
# - description (Required. Identifies the product)
# - id (Required. Should match the product on your database)
# - shipping_cost(Optional. Will be used if provided instead
# of calculated by Correio)
def <<(options)
options = {
:weight => nil,
:quantity => 1
}.merge(options)

# convert weight to grammes
options[:weight] = convert_unit(options[:weight], 1000)

products.push(options)
end

def add(options)
self << options
end

private
def convert_unit(number, unit)
number = (BigDecimal("#{number}") * unit).to_i unless number.nil? || number.kind_of?(Integer)
number
end
end
end
113 changes: 113 additions & 0 deletions lib/pagseguro/api_payment.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# encoding: utf-8
module PagSeguro
class ApiPayment

API_URL = "https://ws.pagseguro.uol.com.br/v2/checkout/"

# the pure response from the HTTP request
attr_accessor :response

# The complete response hash
attr_accessor :payment

# Errors hash if any
attr_accessor :errors

# Payment code attributed by PagSeguro
attr_accessor :code

# The redirect_url if successful
attr_accessor :redirect_url

# Normalize the specified hash converting all data to UTF-8.
#
def normalize(hash)
each_value(hash) do |value|
Utils.to_utf8(value)
end
end

# Denormalize the specified hash converting all data to ISO-8859-1.
#
def denormalize(hash)
each_value(hash) do |value|
Utils.to_iso8859(value)
end
end

# Send the ApiOrder information and get redirect url
def initialize(api_order)
# include the params to validate our request
request_params = {
:encoding => "UTF-8",
:email => PagSeguro.config["email"],
:token => PagSeguro.config["authenticity_token"],
:currency => "BRL"
}

api_order.products.each_with_index do |product, i|
i += 1
request_params.merge!({
"itemQuantity#{i}".to_sym => product[:quantity],
"itemId#{i}".to_sym => product[:id],
"itemDescription#{i}".to_sym => product[:description],
"itemAmount#{i}".to_sym => product[:price]
})
request_params.merge!({
"itemWeight#{i}".to_sym => product[:weight].to_i
}) if product[:weight]
end

api_order.billing.each do |name, value|
request_params.merge!({
PagSeguro::ApiOrder::BILLING_MAPPING[name.to_sym].to_sym => value
})
end

# add optional values if available
request_params.merge!({:reference => api_order.id}) if api_order.id
request_params.merge!({:shippingType => api_order.shipping_type}) if api_order.shipping_type
request_params.merge!({:extraAmount => api_order.extra_amount}) if api_order.extra_amount
request_params.merge!({:redirectURL => api_order.redirect_url}) if api_order.redirect_url
request_params.merge!({:maxUses => api_order.max_uses}) if api_order.max_uses
request_params.merge!({:maxAge => api_order.max_age}) if api_order.max_age

# do the request
uri = URI.parse(API_URL)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.ca_file = File.dirname(__FILE__) + "/cacert.pem"

request = Net::HTTP::Post.new(uri.path)
request.form_data = denormalize(request_params)
response = http.start {|r| r.request request }

# saves the response
@response = response

# saves the payment in hash format
@payment = Hash.from_xml(@response.body)

# get errors if any
@errors = @payment.try(:[], 'errors')

# saves the redirect_url
@code = @payment.try(:[], 'checkout').try(:[], 'code')
@redirect_url = @code ? "https://pagseguro.uol.com.br/v2/checkout/payment.html?code=#{@code}" : nil
end

private
def each_value(hash, &blk) # :nodoc:
hash.each do |key, value|
if value.kind_of?(Hash)
hash[key] = each_value(value, &blk)
else
hash[key] = blk.call value
end
end

hash
end
end
end
5 changes: 4 additions & 1 deletion lib/pagseguro/order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class Order
:email => "cliente_email"
}

# Optional: extra amount on the purchase (negative for discount
attr_accessor :extra_amount

# The list of products added to the order
attr_accessor :products

Expand Down Expand Up @@ -87,7 +90,7 @@ def add(options)
private
def convert_unit(number, unit)
number = (BigDecimal("#{number}") * unit).to_i unless number.nil? || number.kind_of?(Integer)
number
"%03d" % number.to_i
end
end
end
4 changes: 4 additions & 0 deletions lib/pagseguro/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@ def to_utf8(string)
def to_iso8859(string)
string.to_s.unpack("U*").pack("C*")
end

def to_payment_url(string)
string ? "https://pagseguro.uol.com.br/v2/checkout/payment.html?code=#{string}" : nil
end
end
end