Rails Braintree couldn't update
I'm implementing Braintree Subscription Payment into my rails app. I've encounter some issue when trying to update subscription information in my database. When I make a payment, it's successfully created and saved into Braintree. The transaction was also created and saved into my database. The only problem is it couldn't update the payment information such as braintree_id, braintree_subscription_id etc in the User.
Below is my Subscriptions Controller:
class SubscriptionsController < ApplicationController
before_action :logged_in_user, only: [:new, :create]
def new
@plans = Braintree::Plan.all
end
def create
if current_user.braintree_id?
customer = Braintree::Customer.find(current_user.braintree_id)
else
result = Braintree::Customer.create(
email: current_user.company_email,
payment_method_nonce: params[:payment_method_nonce]
)
customer = result.customer
current_user.update(braintree_id: customer.id)
end
result = Braintree::Subscription.create(
payment_method_token: customer.payment_methods.find{ |pm| pm.default? }.token,
plan_id: params[:plan_id],
)
result.subscription.transactions.each do |transaction|
current_user.transactions.create(braintree_transaction_id: transaction.id,
plan_name: params[:plan_name],
price: transaction.amount.to_f,
start_date: transaction.subscription_details.billing_period_start_date,
end_date: transaction.subscription_details.billing_period_end_date,
subscription_id: result.subscription.id,
)
end
current_user.update(braintree_subscription_id: result.subscription.id, next_billing_date: result.subscription.next_billing_date,
billing_period_start_date: result.subscription.billing_period_start_date,
billing_period_end_date: result.subscription.billing_period_end_date,
status: result.subscription.status,
next_billing_period_amount: result.subscription.next_billing_period_amount,
paid_through_date: result.subscription.paid_through_date,
plan_id: params[:plan_id],
plan_name: params[:plan_name])
redirect_to @current_user, notice: "You have been subscribed"
end
end
I've tried to manually update the information in the console, and everything works well. Below are the output that when making a new payment, it rollback and couldn't update the User. While the Transaction was created and saved into database.
Started POST "/subscription.213" for 61.6.143.87 at 2017-12-14 07:57:55 +0000
Processing by SubscriptionsController#create as
Parameters: {"utf8"=>"✓", "authenticity_token"=>"FHwbQSfiinjfskBG3Iec8C0gKuGIeOQDmBnjJu4fpEQwsrmsewHYvgAFIpKVguehm+TZAjHrfd8Ya6CWYPX1Rw==", "plan_id"=>"monthly", "plan_name"=>"monthly", "payment_method_nonce"=>"0986895d-aab4-01b3-5829-778101fa0ebb"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 213]]
I, [2017-12-14T07:57:56.724260 #10346] INFO -- : [Braintree] [14/Dec/2017 07:57:56 UTC] POST /merchants/wt92v8tk2hn8j7kg/customers 201
(0.1ms) begin transaction
User Exists (0.3ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."company_email") = LOWER('test-11@railstutorial.org') AND "users"."id" != 213) LIMIT 1
(0.1ms) rollback transaction
I, [2017-12-14T07:57:57.747920 #10346] INFO -- : [Braintree] [14/Dec/2017 07:57:57 UTC] POST /merchants/wt92v8tk2hn8j7kg/subscriptions 201
(0.0ms) begin transaction
SQL (0.3ms) INSERT INTO "transactions" ("braintree_transaction_id", "plan_name", "price", "start_date", "end_date", "subscription_id", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) [["braintree_transaction_id", "38273ws4"], ["plan_name", "monthly"], ["price", 9.0], ["start_date", "2017-12-14"], ["end_date", "2018-01-13"], ["subscription_id", "7882v6"], ["user_id", 213], ["created_at", "2017-12-14 07:57:57.780968"], ["updated_at", "2017-12-14 07:57:57.780968"]]
(8.8ms) commit transaction
(0.1ms) begin transaction
User Exists (0.3ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."company_email") = LOWER('test-11@railstutorial.org') AND "users"."id" != 213) LIMIT 1
(0.1ms) rollback transaction
Redirected to https://kiplr-ternggio.c9users.io/users/213
Completed 302 Found in 2257ms (ActiveRecord: 10.4ms)
This thing works perfectly in my other app which using Devise. I didn't use Devise in this app and I'm not sure what really cause this issue. It really appreciated if somebody point me some direction.
Hi Lee,
You probably have a validation on the user model or transaction model that's not being satisfied. Can you post any validations you have on your user and transaction model?
You can also use the byebug gem and place byebug
right before the transaction that fails. Then try another subscription and this time when byebug is triggered, try creating the transaction there manually and see what error is raised.
Below is the User
model:
validates :company_name, presence: true, length: {maximum: 50}
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :company_email, presence: true, length: {maximum: 255}, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
validates :company_contact, presence: true, length: {maximum: 15}
validates :term, presence: true
has_secure_password
validates :password, presence: true, length: { minimum: 6 }
validates_confirmation_of :password
Below is my db/seed
User.create!(company_name: "Example User",
company_email: "example@railstutorial.org",
company_contact: "011999484",
password: "foobar",
password_confirmation: "foobar",
term: true,
activated: true,
activated_at: Time.zone.now)
99.times do |n|
company_name = "Example user"
company_email = "example-#{n+1}@railstutorial.org"
company_contact = "0119999494"
password = "password"
User.create!(company_name: company_name,
company_email: company_email,
company_contact: company_contact,
password: password,
password_confirmation: password,
term: true,
activated: true,
activated_at: Time.zone.now)
end
When I run rake db:seed
, everything works well, and I can login using the password as "password", but when run user.valid?
, it gives false
and the errors messages show {:password=>["can't be blank", "is too short (minimum is 6 characters)"]}
What are you using to authenticate your users in this app if you're not using Devise? The error shown is clearly that it's expecting a password, and your validations on your user model also state you need password info when saving/updating a user.
I think you need to restructure your models some... your user
model really needs to be focused on just the users information needed to login. Everything else needs to be in their own model that is associated with the user
model.
So instead of putting a users company in the user model, create a company
model and then depending on your needs, either do a has_one
or has_many
association between the user
and company
.
You also need a subscription
model that will take care of keeping track of a users subscription. You may also consider a payment_source
model that will keep track of the braintree_id
.
Ideally, for what you're wanting to accomplish, you shouldn't need to save anything to the user
model when you're creating a transaction.