So I’ve been trying to get Substruct to use PayPal Pro instead of Authorize.net as the payment gateway. There are a couple of options out there to do this namely
vPayPal which I didn’t have any luck with and
elTechs PayPal plugin which is the option I finally got working
The problems I had were all due to bugs in soap4r 1.5.5, the so called stable release.
So here is how you tweak soap4r to make it work… (If you want to be lazy download my patched copy)
- Skip 1.5.5 and grab the code that is sitting on the trunk and make these next two updates
- Apply patch 1629 to complexContent.rb that lives in lib/wsdl/xmlSchema/complexContent.rb
- Change wsdl/soap/classDefCreator.rb as follows
Comment out the type = nil line and uncomment the type = create_class_name line)if element.type == XSD::AnyTypeName type = nil elsif klass = element_basetype(element) type = klass.name elsif element.type type = create_class_name(element.type) else # type = nil # do we define a class for local complexType from it's name? type = create_class_name(element.name) end
- You can now go ahead and run install.rb to install the package.
- Follow the rest of the instructions from the PayPal plugin
- Success!
Big thanks to Brenden Wilson as without his post I never would have gotten this running (being a complete RubyNoobie)
The next step is getting all of this working from within Substruct.
Change the finish_order method in store_controller.rb to
def finish_order
@title = "Thanks for your order!"
@order = find_order
# If there's no order redirect to index
if @order == nil
redirect_to_index and return
end
@transaction_details = {
:firstName => @order.billing_address.first_name,
:lastName => @order.billing_address.last_name,
:ip => "127.0.0.1",
:amount => @order.total.to_s,
:itemName => @order.order_number,
:addressName => "Billing",
:street1 => @order.billing_address.address,
:street2 => "",
:cityName => @order.billing_address.city,
:postalCode => @order.billing_address.zip,
:stateOrProvince => @order.billing_address.state,
:country => "US",
:creditCardType => get_credit_card_type(@order.account.cc_number),
:creditCardNumber => @order.account.cc_number,
:cVV2 => @order.account.credit_ccv,
:expMonth => @order.account.expiration_month,
:expYear => @order.account.expiration_year
}
result = Paypal.directauth(@transaction_details)
if(result.ack == "Success")
@payment_message = "Card processed successfully: #{result.transactionID}"
# Save transaction id for later
@order.auth_transaction_id = result.transactionID
logger.info("nnORDER TRANSACTION ID - #{result.transactionID}nn")
# Set completed
@order.cleanup_successful
# Send success message
@order.deliver_receipt
clear_cart_and_order(false)
else
# Order failed - store transaction id
# @order.auth_transaction_id = result.transactionID
@order.cleanup_failed(result.ack)
# Send failed message
@order.deliver_failed
# Log errors
logger.error("nn[ERROR] FAILED ORDER n")
logger.error(result)
logger.error("nn")
# Redirect to checkout and allow them to enter info again.
error_message = "#{result.errors.longMessage}"
error_message << "Try again or contact us for further assistance."
redirect_to_checkout(error_message)
end
end
Any chance of getting the working version modularized and rolled into the base code where you cna switch between the two?
- s
How are you getting the errors from paypal? I get errors when trying to use longMessage. Can you explain that? I need to display why the card failed but cannot get the errors.
Thanks for the article by the way.
Greg: result.errors.longMessage gets you the error message (assuming there is one) can you run the paypal_test.rb script okay?
Seth: There is a slim chance :) Right now I’m adding attributes to substruct because they are more pressing with regards what I’m trying to do with it. I’m 90% of the way there with attributes and after that is done I may revisit the PayPal code.
Damian,
I’m using this in a custom project not substruct.
I’m getting different errors regarding my sandbox when i run the test script.
However, when I run the script I get undefined method `LongMessage’ for #, but I can see the LongMessage in the log files saying I need a valid credit card number.
Well you can’t just go result.longMessage, you need result.errors.longMessage.
In paypal_test.rb I’m using
if(@result.ack == “Failure”)
puts @result.errors.longMessage
end
Make sure in the default.rb that you created when you installed the PayPal plugin that you have the class ErrorType defined, and an attr_accessor for longMessage in there because the result is returned an ErrorType object. Here is mine
# {urn:ebay:apis:eBLBaseComponents}ErrorType
class ErrorType
@@schema_type = “ErrorType”
@@schema_ns = “urn:ebay:apis:eBLBaseComponents”
@@schema_element = [
["shortMessage", ["SOAP::SOAPString", XSD::QName.new("urn:ebay:apis:eBLBaseComponents", "ShortMessage")]],
["longMessage", ["SOAP::SOAPString", XSD::QName.new("urn:ebay:apis:eBLBaseComponents", "LongMessage")]],
["errorCode", ["Token", XSD::QName.new("urn:ebay:apis:eBLBaseComponents", "ErrorCode")]],
["severityCode", ["SeverityCodeType", XSD::QName.new("urn:ebay:apis:eBLBaseComponents", "SeverityCode")]],
["errorParameters", ["ErrorParameterType[]“, XSD::QName.new(“urn:ebay:apis:eBLBaseComponents”, “ErrorParameters”)]]
]
attr_accessor :shortMessage
attr_accessor :longMessage
attr_accessor :errorCode
attr_accessor :severityCode
attr_accessor :errorParameters
def initialize(shortMessage = nil, longMessage = nil, errorCode = nil, severityCode = nil, errorParameters = [])
@shortMessage = shortMessage
@longMessage = longMessage
@errorCode = errorCode
@severityCode = severityCode
@errorParameters = errorParameters
end
end
Also you’ll see the long message in the logs because it’s in the XML response coming back from PayPal but that doesn’t mean that your Soap4r install knows how to decipher it and turn it into an object for you to access.
I bet that’s the problem. I do have result.errors.longMessage in my controller, but I bet I don’t have that in my default.rb; unless of course it was there from the wsdl script. I’ll check it shortly and let you know how it works.
By the way, i’m making a modified version of acts_as_authenticated for purchase of access to a site.
I had a lot of problem with the generation of the default.rb, and until I went through the process above (using the trunk of soap4r and applying a couple of patches) it simply wouldn’t work at all.
How did you find this post Greg?
I think it was google that led me here. Not sure anymore.
Were you able to use the paypal plugin successfully with a live account? We get nothing but failures for no apparent reason. Paypal can’t even find the problem. Also, have you been able to get express checkout working with this pluign? It seems that express checkout is required to be used with this and the readme for the plugin says it’s not fully supported.
I haven’t gotten that far to be honest, but it’s not exactly encouraging to hear that. I’ll post updates when I try (probably later tonight)
Here’s my update Damian. Dump it and go with v_paypal. I set it up this morning and it worked the first time. You can get it at rubyforge. The nice thing is, they’ve already done the leg work creating the files with the wsdl, included the paypal php sdk cert and everything. All you have to do is provide, in the yml, your paypal login info for the api and it works. It also works great with the express checkout which is REQUIRED by paypal. I highly recommend this one.
The only thing I did differently was downloaded the gem, changed the file type to tar to get an extraction so I could view the readme before installing it. Documentation outside of the gem is null and void.
Dump it!! Fair enough :) All that frickin work for naught, ah well. Thanks for the heads up, I’ll give it a shot tonight.
Let me know how you make out! shoot me an email if you need anything… greg at busyashell dot com