Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Venmo as payment option #138

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,20 @@ With product and cart page checkout, the user is directed to the checkout confir

PayPals API does not allow for admin-side payments. Instead, backend users taking payments for customers will need to use the PayPal Virtual Terminal to take payments. [More info is available on the PayPal website.](https://www.paypal.com/merchantapps/appcenter/acceptpayments/virtualterminal?locale.x=en_US)

## Venmo
Venmo is currently available to US merchants and buyers. There are also other [prequisites](https://developer.paypal.com/docs/business/checkout/pay-with-venmo/#eligibility).

If the transaction supports Venmo then a button should appear for it on checkout, cart and product page, depending on your `Payment Method` preferences.

If you wish to disable Venmo, then set your `Payment Methods`'s `enable_venmo` preference to `false`. See more about preferences([Configuration](#configuration)) below.

[_As Venmo is only available in the US, you may want to mock your location for testing_](#mocking-your-buyer-country)

## Configuration
The easiest way to change the `Payment Method`'s preferences is through admin: `Settings > Payments > "PayPal Commerce Platform" > Edit`.

See more about preferences [here](https://guides.solidus.io/developers/preferences/add-model-preferences.html#access-your-preferences)/

## Development

### Testing the extension
Expand Down Expand Up @@ -162,6 +176,12 @@ $ bin/rails server
Use Ctrl-C to stop
```

### Mocking your buyer country
PayPal normally looks at your IP geolocation to see where you are located to determine what funding sources are available to you. For example, Venmo is currently only available to US buyers.
Because of this, you may want to pretend you are from US check that that Venmo is correctly integrated for these customers. To do this, set the payment method's preference of `force_buyer_country` to "US". See more information about preferences above.

This preference has no effect on production.

### Updating the changelog

Before and after releases the changelog should be updated to reflect the up-to-date status of
Expand Down
8 changes: 8 additions & 0 deletions app/models/solidus_paypal_commerce_platform/payment_method.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class PaymentMethod < SolidusSupport.payment_method_parent_class
preference :display_on_cart, :boolean, default: true
preference :display_on_product_page, :boolean, default: true
preference :display_credit_messaging, :boolean, default: true
preference :enable_venmo, :boolean, default: true
preference :force_buyer_country, :string

def partial_name
"paypal_commerce_platform"
Expand Down Expand Up @@ -73,6 +75,12 @@ def javascript_sdk_url(order: nil, currency: nil)
}

parameters[:shipping_preference] = 'NO_SHIPPING' if step_names.exclude? 'delivery'
parameters['enable-funding'] = 'venmo' if options[:enable_venmo]
parameters['disable-funding'] = 'venmo' unless options[:enable_venmo]

if !Rails.env.production? && options[:force_buyer_country].present?
parameters['buyer-country'] = options[:force_buyer_country]
end

"https://www.paypal.com/sdk/js?#{parameters.to_query}"
end
Expand Down
63 changes: 53 additions & 10 deletions spec/models/solidus_paypal_commerce_platform/payment_method_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,48 +77,91 @@ def Struct(data) # rubocop:disable Naming/MethodName
describe '.javascript_sdk_url' do
subject(:url) { URI(paypal_payment_method.javascript_sdk_url(order: order)) }

context 'when checkout_steps include "confirm"' do
let(:order) { instance_double(Spree::Order, checkout_steps: { "confirm" => "bar" }) }
let(:order) { build_stubbed(:order) }

context 'when checkout_steps include "confirm"' do
it 'sets autocommit' do
expect(url.query.split("&")).to include("commit=false")
end
end

context 'when checkout_steps does not include "confirm"' do
let(:order) { instance_double(Spree::Order, checkout_steps: { "foo" => "bar" }) }

it 'disables autocommit' do
allow(order).to receive(:checkout_steps).and_return([:address, :delivery, :payment])
expect(url.query.split("&")).to include("commit=true")
end
end

context 'when checkout_steps does not include "delivery"' do
let(:order) { instance_double(Spree::Order, checkout_steps: { "foo" => "bar" }) }

it 'disables autocommit' do
allow(order).to receive(:checkout_steps).and_return([:address, :confirm, :payment])
expect(url.query.split("&")).to include("shipping_preference=NO_SHIPPING")
end
end

context 'when messaging is turned on' do
let(:order) { instance_double(Spree::Order, checkout_steps: { "foo" => "bar" }) }

it 'includes messaging component' do
paypal_payment_method.preferences.update(display_credit_messaging: true)
expect(url.query.split("&")).to include("components=buttons%2Cmessages")
end
end

context 'when messaging is turned off' do
let(:order) { instance_double(Spree::Order, checkout_steps: { "foo" => "bar" }) }

it 'only includes buttons components' do
paypal_payment_method.preferences.update(display_credit_messaging: false)
expect(url.query.split("&")).not_to include("messages")
expect(url.query.split("&")).to include("components=buttons")
end
end

context 'when enable_venmo is false' do
before { paypal_payment_method.preferences.update(enable_venmo: false) }

it 'does not include "enable-funding=venmo" as a parameter' do
expect(url.query.split('&')).not_to include('enable-funding=venmo')
end

it 'includes "disable-funding=venmo" as a parameter' do
expect(url.query.split('&')).to include('disable-funding=venmo')
end
end

context 'when enable_venmo is true' do
before { paypal_payment_method.preferences.update(enable_venmo: true) }

it 'includes "enable-funding=venmo" as a parameter' do
expect(url.query.split('&')).to include('enable-funding=venmo')
end

it 'does not include "disable-funding=venmo" as a parameter' do
expect(url.query.split('&')).not_to include('disable-funding=venmo')
end
end

context 'when force_buyer_country is an empty string' do
it 'does not include the "buyer-country" parameter' do
expect(url.query.split('&')).not_to include(match 'buyer-country')
end
end

context 'when force_buyer_country is "US"' do
before { paypal_payment_method.preferences.update(force_buyer_country: 'US') }

it 'includes "buyer-country=US" as a parameter' do
expect(url.query.split('&')).to include('buyer-country=US')
end
end

context 'when force_buyer_country is "US" but the environment is production' do
before {
allow(Rails.env).to receive(:production?).and_return(true)
paypal_payment_method.preferences.update(force_buyer_country: 'US')
}

it 'includes "buyer-country=US" as a parameter' do
expect(url.query.split('&')).not_to include(match 'buyer-country')
end
end
end

private
Expand Down