module VPaypal require File.dirname(__FILE__) + '/defaultDriver' require File.dirname(__FILE__) + '/default' class PaypalPro attr_accessor :client =begin Creates the headerhandler for each request in initialization of VPaypal object.Reads required paypal account information and certificate paths from paypal.yml.The necessary required Information includes: @ca_file: Location of Paypal Server Certificate in your server. @client_keys : Location of client.keys file that contains rsa key part of cert_key_pem.txt(digital client certificate from paypal) @client_cert: Location of client.cert file that contains the rest of the part of certificate. @paypal_username:Username for merchant account @paypal_password:Password for merchant account By default these files are searched in the current folder lib/paypal Make changes in paypal.yml as it suits you. Example:New instance can be created as vpp = VPaypal::PaypalPro.new(options) Where options = {"prefs"=>"path of v_paypal.yml"} =end def initialize(options = {"prefs"=>nil}) prefs = File.expand_path(options[:prefs] || File.dirname(__FILE__) +"/../../config/v_paypal.yml") YAML.load(File.open(prefs)).each {|pref, value| eval("@#{pref} =\"#{value}\"")}if File.exists?(prefs) client = PayPalAPIAAInterface.new client.options['protocol.http.ssl_config.verify_mode'] = OpenSSL::SSL::VERIFY_PEER client.options['protocol.http.ssl_config.ca_file'] = "#{File.expand_path(File.dirname(__FILE__))+@ca_file}" client.options['protocol.http.ssl_config.client_cert'] = "#{File.expand_path(File.dirname(__FILE__))+@client_cert}" client.options['protocol.http.ssl_config.client_key'] = "#{File.expand_path(File.dirname(__FILE__))+@client_keys}" client.headerhandler << RequesterCredentialsHandler.new(@paypal_username, @paypal_password,'') @client = client end =begin Takes two parameters request:Name of request without "Request" word appended with it. Example-For SetExpressCheckout Request request string should be "SetExpressCheckout" options:Contains all the parameters required for given Request.These parameters are passed through a multi dimensional Hash.This Hash has the same tree structure as the paypal request has. Example: res = vpp.vRequest("DoExpressCheckoutPayment",{ "Token" => token_value, "PaymentAction-PaymentActionCode" => "Sale", "PayerID" => payerID, "PaymentDetails" => {"OrderTotal"=>amount, "ShipppingTotal" =>shipping_total, "ShipToAddress-Address"=> {"Name" => name, "Street1" => street1, "StateOrProvince" => state, "CityName" => city, "Country" => country, "PostalCode" => zip } } }) One needs to remember that if variable name is different from object name in the request ,the key value must contain both name seperated by a hyphen(-).{"VariableName-ObjectName"=>value} Example: "ShipToAddress-Address"=> {"Name" => name, "Street1" => street1, "StateOrProvince" => state, "CityName" => city, "Country" => country, "PostalCode" => zip } Returns Response.Check res.ack for 'Success' Or 'Failure' .Errors can be viewed in res.errors =end def vRequest(request = nil ,options = nil) if request != "GetExpressCheckoutDetails" req = eval("#{request}Req").new type = eval("#{request}RequestType").new type.version = "2.0" details = eval("#{request}RequestDetailsType").new request = request[/^(.)(.*)?/] var_name = $1.swapcase.concat($2) type.instance_variable_set(eval(":@#{var_name}RequestDetails"),details) s = assignOptions(options,details) details = s req.instance_variable_set(eval(":@#{var_name}Request"),type) m = @client.method(var_name) res = m.call(req) else res = vGetExpressCheckoutDetails(options) end end =begin Sets all the parameters required for SetExpressCheckoutRequest.These parameters are passed through options in a multi dimensional Hash.This Hash is has the same tree structure as the paypal request has.Please follow carefully the paypal pro documentaion to create options hash for request.As this module uses the variable name and object name as given in the paypal pro documentation. Example: res = vpp.vSetExpressCheckoutRequest({"OrderTotal"=>"10.00","CancelURL"=>url_for(:action => "cancel"),"ReturnURL"=>url_for(:action => "return")}) The response contains token which can be accessed as res.token Append this token to the redirect url and redirect user to paypal screen redirect_to "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=#{res.token.to_s}" **Currently not in use =end def vSetExpressCheckoutRequest(options = nil) req = SetExpressCheckoutReq.new type = SetExpressCheckoutRequestType.new type.version = "2.0" details = SetExpressCheckoutRequestDetailsType.new type.setExpressCheckoutRequestDetails = details s = assignOptions(options,details) details = s req.setExpressCheckoutRequest = type res = @client.setExpressCheckout(req) end =begin Sets all the parameters required for GetExpressCheckoutDetails.These parameters are passed through options in a multi dimensional Hash.This Hash has the same tree structure as the paypal request has.The only value required here for this request is token Example : res = vpp.vGetExpressCheckoutDetails({"token"=>params[:token]}) The Response returned contains account insormation of user.Can be easily accessed as - firstName =res.getExpressCheckoutDetailsResponseDetails.payerInfo.payerName.firstName =end def vGetExpressCheckoutDetails(options = nil) req = GetExpressCheckoutDetailsReq.new type = GetExpressCheckoutDetailsRequestType.new type.version = "2.0" type.token=options["token"] req.getExpressCheckoutDetailsRequest = type res = @client.getExpressCheckoutDetails(req) end =begin Sets all the parameters required for DoExpressCheckoutPaymentRequest.These parameters are passed through options in a multi dimensional Hash.This Hash has the same tree structure as the paypal request has. Example: res = vpp.vDoExpressCheckoutPaymentRequest({ "Token" => token_value, "PaymentAction-PaymentActionCode" => "Sale", "PayerID" => payerID, "PaymentDetails" => {"OrderTotal"=>amount, "ShipppingTotal" =>shipping_total, "ShipToAddress-Address"=> {"Name" => name, "Street1" => street1, "StateOrProvince" => state, "CityName" => city, "Country" => country, "PostalCode" => zip } } }) One needs to remember that if variable name is different from object name in the request ,the key value must contain both name seperated by a hyphen(-).{"VariableName-ObjectName"=>value} Example: "ShipToAddress-Address"=> {"Name" => name, "Street1" => street1, "StateOrProvince" => state, "CityName" => city, "Country" => country, "PostalCode" => zip } Return Response.Check res.ack for 'Success' Or 'Failure' .Errors can be viewed in res.errors **Currently not in use =end def vDoExpressCheckoutPaymentRequest(options = nil) req = DoExpressCheckoutPaymentReq.new type = DoExpressCheckoutPaymentRequestType.new type.version = "2.0" details = DoExpressCheckoutPaymentRequestDetailsType.new type.doExpressCheckoutPaymentRequestDetails = details s = assignOptions(options,details) details = s req.doExpressCheckoutPaymentRequest = type res = @client.doExpressCheckoutPayment(req) end =begin Sets all the parameters required for DodirectPaymentRequest.These parameters are passed through options in a multi dimensional Hash.This Hash has the same tree structure as the paypal request has. One needs to remember that if variable name is different from object name in the request ,the key value must contain both name seperated by a hyphen(-).{"VariableName-ObjectName"=>value} Example: "CreditCard-CreditCardDetails" => {"CardOwner-PayerInfo" => {"PayerName-PersonName" => {"FirstName"=> fname, "LastName" => lname }, "Address" => { "Street1"=>line1 , "StateOrProvince"=>state, "CityName"=>city, "Country"=>country, "PostalCode" => zip, } , }, "CreditCardType" => type, "CreditCardNumber" =>number, "ExpMonth" =>expmonth, "ExpYear" => expyear , "CVV2" => cvm }, **Currently not in use =end def vDoDirectPaymentRequest(options = nil) req = DoDirectPaymentReq.new type = DoDirectPaymentRequestType.new type.version = "2.0" details = DoDirectPaymentRequestDetailsType.new type.doDirectPaymentRequestDetails = details s = assignOptions(options,details) details = s req.doDirectPaymentRequest = type res = @client.doDirectPayment(req) end =begin assignOptions is called by every request function in VPaypal class.It makes recursive calls to self.It takes two argument a Hash array or a string and a class object.The class object is the parent class and the hashed array contains the values of the instance variables of this object.If the instance variable itself is a class object and its value in Hash is also a Hash the function is called recursively wid the value of hash as options and class created by as parent_class. =end def assignOptions(options = nil, parent_class = nil) class_variables = parent_class.instance_variables options.each do |key,child| if key.include?("-") key = key[/^(.)(.*)-(.*)?/] else key = key[/^(.)(.*)?/] end var_name = $1.swapcase.concat($2) if $3.nil? cl_name = $1.concat($2) else cl_name = $3 end if class_variables.include?("@#{var_name}") f = false begin eval("@#{var_name} = #{cl_name}Type.new") f = true if(child.class.to_s == 'Hash') assignOptions(child,eval("@#{var_name}")) # If class is derrived from String then simply assign child value else eval("@#{var_name} = '#{child.to_s}'") end # if no class with name as key exists then assign the child value to the instance variable of parent class rescue NameError # Creating OrderTotal object if var_name.to_s == "orderTotal" ns = "urn:ebay:apis:eBLBaseComponents" otqname = XSD::QName.new(ns, "OrderTotal") otele = SOAP::SOAPElement.new(otqname, child) otele.extraattr["currencyID"] = "USD" parent_class.orderTotal = otele else parent_class.instance_variable_set(eval(":@#{var_name}") , child) end end end #assigning object to the instance variable of parent class if f parent_class.instance_variable_set(eval(":@#{var_name}") , eval("@#{var_name}")) end end parent_class end end end