Getting Substruct to use the PayPal API

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)

  1. Skip 1.5.5 and grab the code that is sitting on the trunk and make these next two updates
  2. Apply patch 1629 to complexContent.rb that lives in lib/wsdl/xmlSchema/complexContent.rb
  3. 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
  4. You can now go ahead and run install.rb to install the package.
  5. Follow the rest of the instructions from the PayPal plugin
  6. 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
Comments
  • Seth July 13, 2006 at 5:42 pm

    Any chance of getting the working version modularized and rolled into the base code where you cna switch between the two?

    - s

  • Greg July 13, 2006 at 8:06 pm

    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.

  • Damian July 13, 2006 at 11:03 pm

    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.

  • Greg July 14, 2006 at 2:46 am

    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.

  • Damian July 14, 2006 at 7:12 am

    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

  • Damian July 14, 2006 at 7:14 am

    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.

  • Greg July 14, 2006 at 9:12 am

    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.

  • Damian July 14, 2006 at 11:41 am

    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.

  • Damian July 14, 2006 at 11:41 am

    How did you find this post Greg?

  • Greg July 17, 2006 at 2:43 am

    I think it was google that led me here. Not sure anymore.

  • Greg July 20, 2006 at 3:47 am

    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.

  • Damian July 20, 2006 at 9:14 am

    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)

  • Greg July 20, 2006 at 12:01 pm

    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.

  • Damian July 20, 2006 at 4:18 pm

    Dump it!! Fair enough :) All that frickin work for naught, ah well. Thanks for the heads up, I’ll give it a shot tonight.

  • Greg July 20, 2006 at 4:19 pm

    Let me know how you make out! shoot me an email if you need anything… greg at busyashell dot com

  • Post a comment

    Threaded commenting powered by Spectacu.la code.