Skip to content
This repository has been archived by the owner on Apr 14, 2023. It is now read-only.

Set source payment_type in cc hosted fields #79

Closed
wants to merge 3 commits into from

Conversation

tvdeyen
Copy link
Member

@tvdeyen tvdeyen commented May 3, 2017

The hosted fields does not set the payment_type value on credit card
sources. This leads to sources which type can’t be recognized anymore.

@tvdeyen
Copy link
Member Author

tvdeyen commented May 3, 2017

Dang. The Travis push hook gets triggered because I accidentally pushed my branch to this repo instead of my fork. I deleted the branch while the build was running. This is why I failed. But the PR hook triggered the correct build of my Fork and this passes 😅

@tvdeyen
Copy link
Member Author

tvdeyen commented May 4, 2017

Closing and reopen, to get correct Travis result

@tvdeyen tvdeyen closed this May 4, 2017
@tvdeyen tvdeyen reopened this May 4, 2017
@tvdeyen tvdeyen closed this May 4, 2017
@tvdeyen tvdeyen reopened this May 4, 2017
@tvdeyen
Copy link
Member Author

tvdeyen commented May 4, 2017

It turns out that Travis seem to have mayor caching issues. Sorry about that. Please ignore the continuous-integration/travis-ci/push result.

Copy link
Contributor

@Senjai Senjai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To my knowledge, the "card_type" and friends should be delegated to Braintree, via the delegate call there. As for determining what type of payment the source represents, the source already includes several query methods for that, are those not working in this scenario?

expect(page).to have_content("Your order has been processed successfully")
end

it "sets the payment type of source to CreditCard" do
expect(SolidusPaypalBraintree::Source.last.payment_type).to eq('CreditCard')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assertion does not belong in feature spec. Could we do this at the unit test level? We should probably also avoid using last unless we're sure the system is only creating the one record.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably also avoid using last unless we're sure the system is only creating the one record.

We know exactly that in this scenario the last source is the one we created through the controller. I had a version where I explicitly tested that we only have on source here, but this seemed overkill for me. I can add this if you want to be extra save.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feature tests should only ever test user interactions. Since there is no reliable way to ensure that the user can see that this is the case, it should not be included in a feature test. If there was a way for a user to use the site in a manner that would cause a failure, we could test that here. Otherwise this should be tested in a controller/request test.

@@ -10,7 +10,7 @@ class Engine < Rails::Engine

initializer "register_solidus_paypal_braintree_gateway", after: "spree.register.payment_methods" do |app|
app.config.spree.payment_methods << SolidusPaypalBraintree::Gateway
Spree::PermittedAttributes.source_attributes << :nonce
Spree::PermittedAttributes.source_attributes.concat [:nonce, :payment_type]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value isn't whitelisted and can be modified by users. Further if we know the payment type in advance, we should probably avoid requiring it to be set in the form.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value isn't whitelisted and can be modified by users.

I need to whitelist it, otherwise I can not pass it into the controller from the view where the value needs top be set, as we don't know the type upfront.

Further if we know the payment type in advance, we should probably avoid requiring it to be set in the form.

We don't know the type upfront. I didn't find any code that guarantees this. Maybe you can point me to?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to whitelist it, otherwise I can not pass it into the controller from the view where the value needs top be set, as we don't know the type upfront.

I meant that the value isn't whitelisted. I can insert "lol" into this field and it would save correctly. We should probably add an inclusion validation to the model to prevent this.

We don't know the type upfront. I didn't find any code that guarantees this. Maybe you can point me to?

Once we have the token, payment_method.braintree.payment_method.find(source.token).is_a?(Braintree::PaypalAccount)

As we only use this for display purposes, I no longer think that's worth doing though.

@tvdeyen
Copy link
Member Author

tvdeyen commented May 5, 2017

To my knowledge, the "card_type" and friends should be delegated to Braintree, via the delegate call there. As for determining what type of payment the source represents, the source already includes several query methods for that, are those not working in this scenario?

The payment_type is a custom database column from our side, so Braintree does not know about it.

For PayPal and ApplePay sources we set these value explicitly, but not for credit card payments. My pending spec e4e4589 shows that this is currently not working.

This is why I chose to test this integrative in stead of on the unit level. The model is polymorphic (not in the AR kind of things, but I plays multiple roles). We can't know the value upfront, so testing it on the unit level did not really made sense for me, we need to set this value while creating it through the controller. Therefore passing it along the params from the view - where we exactly know what type the source is - made the most sense for me.

Any idea how to approach this differently?

@tvdeyen
Copy link
Member Author

tvdeyen commented May 5, 2017

the source already includes several query methods for that

The query methods depend on the payment_type to be set. friendly_payment_type even blows up if no payment_type is set.

@tvdeyen
Copy link
Member Author

tvdeyen commented May 5, 2017

The "best solution" would be to actually provide three payment sources (and even gateways). Then we wouldn't even need to have these query methods at all.

I will provide a RFC for this, as I think now that we have a common interface for payment sources in Solidus 2.2 we should start to embrace it. For older stores its an easy back port we would ship with this gem.

@@ -10,7 +10,7 @@ class Engine < Rails::Engine

initializer "register_solidus_paypal_braintree_gateway", after: "spree.register.payment_methods" do |app|
app.config.spree.payment_methods << SolidusPaypalBraintree::Gateway
Spree::PermittedAttributes.source_attributes << :nonce
Spree::PermittedAttributes.source_attributes.concat [:nonce, :payment_type]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to whitelist it, otherwise I can not pass it into the controller from the view where the value needs top be set, as we don't know the type upfront.

I meant that the value isn't whitelisted. I can insert "lol" into this field and it would save correctly. We should probably add an inclusion validation to the model to prevent this.

We don't know the type upfront. I didn't find any code that guarantees this. Maybe you can point me to?

Once we have the token, payment_method.braintree.payment_method.find(source.token).is_a?(Braintree::PaypalAccount)

As we only use this for display purposes, I no longer think that's worth doing though.

expect(page).to have_content("Your order has been processed successfully")
end

it "sets the payment type of source to CreditCard" do
expect(SolidusPaypalBraintree::Source.last.payment_type).to eq('CreditCard')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feature tests should only ever test user interactions. Since there is no reliable way to ensure that the user can see that this is the case, it should not be included in a feature test. If there was a way for a user to use the site in a manner that would cause a failure, we could test that here. Otherwise this should be tested in a controller/request test.

@Senjai
Copy link
Contributor

Senjai commented May 5, 2017

RE: the query methods, yes you're correct. Missed that, I should have looked at that more closely. I'm 👍 on including on the form, would just prefer the test moved.

As for the RFC can you hold off? We've had a couple discussions on that architecture and have the beginnings of a plan in place. If you're interested we can chat about it, but I don't want to duplicate efforts here.

@tvdeyen tvdeyen force-pushed the set-payment-type branch from 8af76e2 to 3d37e78 Compare May 8, 2017 07:24
@tvdeyen
Copy link
Member Author

tvdeyen commented May 8, 2017

Build fixes waits for #84

reversible do |dir|
dir.up do
SolidusPaypalBraintree::Source.where(payment_type: nil).
update_all(payment_type: 'CreditCard')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't accurate. Is there a scenario that generated nil payment_types in the past?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. All credit card payments. PayPal and ApplePay payments have this value set via JS tailored params.

Although this isn't accurate it's the only thing we can do about, besides not doing this at all of course.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, fair point.

@@ -10,6 +10,8 @@ class Source < ApplicationRecord

belongs_to :customer, class_name: "SolidusPaypalBraintree::Customer"

validates :payment_type, presence: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validates :payment_type, inclusion: [PAYPAL, APPLE_PAY, CREDIT_CARD]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good point! 👌🏻

tvdeyen added 3 commits May 15, 2017 20:33
When submiting credit cards in checkout the payment_type is missing. We should validates it’s presence on the source model.
Our javascript takes care of setting this column in the params during checkout for PayPal and ApplePay payments,
but not for credit card payments. The easiest way is to send the value is from within the hosted fields form.
The payment_type is used to differ payment soruces. I.E. lots of query methods uses this column to decide which kind of payment this source instance is, even presentor methods uss this clumn to look up the human name in the translation files by this column.

Therefore it is necessary to validate its presence and add a not null constrained in the database.
@tvdeyen tvdeyen force-pushed the set-payment-type branch from 3d37e78 to c6f5ec7 Compare May 15, 2017 19:32
@Senjai
Copy link
Contributor

Senjai commented May 16, 2017

@tvdeyen Have some vcr issues no idea why though :/

@tvdeyen
Copy link
Member Author

tvdeyen commented May 16, 2017

@Senjai yeah. Pretty strange. Only for Solidus < 2.1. Even locally. Investigated this morning, but gave up because lack of time.

@Senjai
Copy link
Contributor

Senjai commented May 18, 2017

Closed in favor of #91 thanks thomas.

@Senjai Senjai closed this May 18, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants