This repository has been archived by the owner on Apr 14, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 76
End to end transaction #16
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
a7fdfd1
Add start of transaction model
3c3c069
Require payment_type on a transaction
ccb4362
Add a class responsible for importing orders
c636101
Add an address model to transaction
7e5e58a
Add a transaction controller
4ff8fd2
Add email and phone to list of "required"
b386bf0
Provide html and javascript to submit transactions
94e6706
Add a simple/sane init for braintree
7ceb87e
Add a reasonable session init for apple pay
3da22d9
Correct RuboCop violations
stewart 77a1a64
Use create_gateway utility method for import test
stewart 2e8ce21
Fix up and flesh out transaction validation specs
stewart 6ddd081
Upcase country
bcbdfbc
Merge pull request #19 from solidusio/upcase_country
cbrunsdon 29c86f4
Use state_name Spree::Address property in import
stewart c25e152
Remove use of deprecated find_by_* method
stewart 848dde6
Save payment_type on the Source
257d32f
Stop recording new VCR episodes for each test run
983e818
Merge pull request #21 from solidusio/save-payment-type-to-source
stewart File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
107 changes: 106 additions & 1 deletion
107
app/assets/javascripts/spree/frontend/solidus_paypal_braintree.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,107 @@ | ||
// Placeholder manifest file. | ||
// the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/frontend/all.js' | ||
// the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/frontend/all.js' | ||
|
||
window.SolidusPaypalBraintree = { | ||
APPLE_PAY_API_VERSION: 1, | ||
|
||
initialize: function(authToken, clientReadyCallback) { | ||
braintree.client.create({ | ||
authorization: authToken | ||
}, function (clientErr, clientInstance) { | ||
if (clientErr) { | ||
console.error('Error creating client:', clientErr); | ||
return; | ||
} | ||
clientReadyCallback(clientInstance); | ||
}); | ||
}, | ||
|
||
setupApplePay: function(braintreeClient, merchantId, readyCallback) { | ||
if(window.ApplePaySession) { | ||
var promise = ApplePaySession.canMakePaymentsWithActiveCard(merchantId); | ||
promise.then(function (canMakePayments) { | ||
if (canMakePayments) { | ||
braintree.applePay.create({ | ||
client: braintreeClient | ||
}, function (applePayErr, applePayInstance) { | ||
if (applePayErr) { | ||
console.error("Error creating ApplePay:", applePayErr); | ||
return; | ||
} | ||
readyCallback(applePayInstance); | ||
}); | ||
} | ||
}); | ||
}; | ||
}, | ||
|
||
initializeApplePaySession: function(applePayInstance, storeName, paymentRequest, sessionCallback) { | ||
|
||
paymentRequest['requiredShippingContactFields'] = ['postalAddress', 'phone', 'email'] | ||
var paymentRequest = applePayInstance.createPaymentRequest(paymentRequest); | ||
|
||
var session = new ApplePaySession(SolidusPaypalBraintree.APPLE_PAY_API_VERSION, paymentRequest); | ||
session.onvalidatemerchant = function (event) { | ||
applePayInstance.performValidation({ | ||
validationURL: event.validationURL, | ||
displayName: storeName, | ||
}, function (validationErr, merchantSession) { | ||
if (validationErr) { | ||
console.error('Error validating Apple Pay:', validationErr); | ||
session.abort(); | ||
return; | ||
}; | ||
session.completeMerchantValidation(merchantSession); | ||
}); | ||
}; | ||
|
||
session.onpaymentauthorized = function (event) { | ||
applePayInstance.tokenize({ | ||
token: event.payment.token | ||
}, function (tokenizeErr, payload) { | ||
if (tokenizeErr) { | ||
console.error('Error tokenizing Apple Pay:', tokenizeErr); | ||
session.completePayment(ApplePaySession.STATUS_FAILURE); | ||
} | ||
session.completePayment(ApplePaySession.STATUS_SUCCESS); | ||
|
||
SolidusPaypalBraintree.setBraintreeApplePayContact(event.payment.shippingContact); | ||
SolidusPaypalBraintree.submitBraintreePayload(payload); | ||
}); | ||
}; | ||
|
||
sessionCallback(session); | ||
|
||
session.begin(); | ||
}, | ||
|
||
setBraintreeApplePayContact: function(appleContact) { | ||
var apple_map = { | ||
locality: 'city', | ||
countryCode: 'country_code', | ||
familyName: 'last_name', | ||
givenName: 'first_name', | ||
postalCode: 'zip', | ||
administrativeArea: 'state_code', | ||
} | ||
for (var key in apple_map) { | ||
document.querySelector("#transaction_address_attributes_" + apple_map[key]).value = appleContact[key]; | ||
} | ||
|
||
window.addressCon = appleContact; | ||
document.querySelector("#transaction_address_attributes_address_line_1").value = appleContact.addressLines[0]; | ||
|
||
if(appleContact.addressLines.length > 1) { | ||
document.querySelector("#transaction_address_attributes_address_line_2").value = appleContact.addressLines[1]; | ||
} | ||
|
||
document.querySelector("#transaction_phone").value = appleContact.phoneNumber; | ||
document.querySelector("#transaction_email").value = appleContact.emailAddress; | ||
}, | ||
|
||
submitBraintreePayload: function(payload) { | ||
document.querySelector("#transaction_nonce").value = payload.nonce; | ||
document.querySelector("#transaction_payment_type").value = payload.type; | ||
document.querySelector('#new_transaction').submit(); | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
app/controllers/solidus_paypal_braintree/transactions_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
class SolidusPaypalBraintree::TransactionsController < Spree::StoreController | ||
PERMITTED_BRAINTREE_TRANSACTION_PARAMS = [ | ||
:nonce, | ||
:payment_type, | ||
:phone, | ||
:email, | ||
address_attributes: [ | ||
:country_code, :last_name, :first_name, | ||
:city, :zip, :state_code, :address_line_1, :address_line_2 | ||
] | ||
] | ||
|
||
def create | ||
transaction = SolidusPaypalBraintree::Transaction.new transaction_params | ||
|
||
if transaction.valid? | ||
import = SolidusPaypalBraintree::TransactionImport.new(current_order, transaction) | ||
import.import! | ||
|
||
if import.order.complete? | ||
return redirect_to spree.order_path(import.order) | ||
else | ||
return redirect_to spree.checkout_state_path(import.order.state) | ||
end | ||
else | ||
render text: transaction.errors | ||
end | ||
end | ||
|
||
private | ||
|
||
def transaction_params | ||
params.require(:transaction) | ||
.permit(PERMITTED_BRAINTREE_TRANSACTION_PARAMS) | ||
.merge({ payment_method: payment_method }) | ||
end | ||
|
||
def payment_method | ||
SolidusPaypalBraintree::Gateway.find(params[:payment_method_id]) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
require 'active_model' | ||
require 'solidus_paypal_braintree/transaction_address' | ||
|
||
module SolidusPaypalBraintree | ||
class Transaction | ||
include ActiveModel::Model | ||
|
||
attr_accessor :nonce, :payment_method, :payment_type, :address, :email, :phone | ||
|
||
validates :nonce, presence: true | ||
validates :payment_method, presence: true | ||
validates :payment_type, presence: true | ||
validates :phone, presence: true | ||
validates :email, presence: true | ||
|
||
validate do | ||
unless payment_method.is_a? SolidusPaypalBraintree::Gateway | ||
errors.add(:payment_method, 'Must be braintree') | ||
end | ||
end | ||
|
||
def address_attributes=(attributes) | ||
self.address = TransactionAddress.new attributes | ||
end | ||
end | ||
end |
10 changes: 10 additions & 0 deletions
10
app/models/solidus_paypal_braintree/transaction_address.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
require 'active_model' | ||
|
||
module SolidusPaypalBraintree | ||
class TransactionAddress | ||
include ActiveModel::Model | ||
|
||
attr_accessor :country_code, :last_name, :first_name, | ||
:city, :zip, :state_code, :address_line_1, :address_line_2 | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
require 'active_model' | ||
|
||
module SolidusPaypalBraintree | ||
class TransactionImport | ||
attr_reader :transaction, :order | ||
|
||
def initialize(order, transaction) | ||
@order = order | ||
@transaction = transaction | ||
end | ||
|
||
def source | ||
SolidusPaypalBraintree::Source.new nonce: transaction.nonce, | ||
payment_type: transaction.payment_type, | ||
user: user | ||
end | ||
|
||
def user | ||
order.user | ||
end | ||
|
||
def import! | ||
order.email = user.try!(:email) || transaction.email | ||
|
||
if address | ||
order.shipping_address = order.billing_address = address | ||
# work around a bug in most solidus versions | ||
# about tax zone cachine between address changes | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a situation we can check for that we will not need to do this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't look like there is any reasonable options, its not fixed in master and its not reasonable to attempt to detect if we should be doing it. |
||
order.instance_variable_set("@tax_zone", nil) | ||
order.next | ||
end | ||
|
||
order.payments.new source: source, | ||
payment_method: transaction.payment_method, | ||
amount: order.total | ||
|
||
order.save! | ||
|
||
advance_order | ||
end | ||
|
||
def address | ||
transaction.address.try do |ta| | ||
country = Spree::Country.find_by(iso: ta.country_code.upcase) | ||
Spree::Address.new first_name: ta.first_name, | ||
last_name: ta.last_name, | ||
city: ta.city, | ||
country: country, | ||
state_name: ta.state_code, | ||
address1: ta.address_line_1, | ||
address2: ta.address_line_2, | ||
zipcode: ta.zip, | ||
phone: transaction.phone | ||
end | ||
end | ||
|
||
protected | ||
|
||
def advance_order | ||
order.next! until order.state == "confirm" | ||
end | ||
end | ||
end |
16 changes: 16 additions & 0 deletions
16
app/views/solidus_paypal_braintree/_transaction_form.html.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<%= form_for [main_app, SolidusPaypalBraintree::Transaction.new], id: 'braintree_complete_form', as: :transaction do |f| %> | ||
<%= f.hidden_field :nonce %> | ||
<%= f.hidden_field :payment_type %> | ||
<%= hidden_field_tag :payment_method_id, payment_method.id %> | ||
<%= f.hidden_field :phone %> | ||
<%= f.hidden_field :email %> | ||
|
||
<%= f.fields_for :address, SolidusPaypalBraintree::TransactionAddress.new do |fa| %> | ||
<% [:country_code, :last_name, :first_name, | ||
:city, :zip, :state_code, | ||
:address_line_1, :address_line_2].each do |address_field| %> | ||
<%= fa.hidden_field address_field %> | ||
<% end %> | ||
<% end %> | ||
|
||
<% end %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
Rails.application.routes.draw do | ||
namespace :solidus_paypal_braintree do | ||
resource :checkout, only: [:update, :edit] | ||
|
||
resource :transactions, only: [:create] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to throw a
console.error
in here so we know what happened. Similar in JS below.