Paymill integration with rails - storing ids locally

642 views Asked by At

I'm working on integrating a Rails app with the Paymill payment gateway (using the paymill-ruby gem), and was wondering if someone could give some advice to the best way to go about interacting with the API during a standard order process. I've managed to get the basics working, but there are very few resources on how to structure the full process.

I have a User model, where I want to store the paymill client id and payment id, and a Payment model, where I store details of every transaction (referencing the order id). My Payment model code is currently as follows:

class Payment < ActiveRecord::Base
  include ActiveModel::ForbiddenAttributesProtection
  attr_accessor :paymill_card_token, :email, :paymill_client_id, :paymill_payment_id

  belongs_to :order
  belongs_to :user
  validates_presence_of :order_id
  validates_presence_of :user_id

  def save_with_payment
    if valid?

      if paymill_client_id.blank?
        #if user hasn't paid before, create paymill client
        client = Paymill::Client.create email: email, description: user_id
        paymill_client_id = client.id
        # update current user with paymill client ID
        User.where("user_id = ?", user_id).update_attributes(:paymill_client_id => paymill_client_id)
      end

      if paymill_payment_id.blank?
        #if paymill_payment_id isn't present, create new payment
        payment = Paymill::Payment.create token: paymill_card_token, client: paymill_client_id
        paymill_payment_id = payment.id
        # update current user with paymill payment ID
        User.where("user_id = ?", user_id).update_attributes(:paymill_payment_id => paymill_payment_id)

      end

      transaction = Paymill::Transaction.create client: paymill_client_id, amount: "#{amount.to_s.gsub('.', '')}0", currency: 'GBP', description: "ORDER ID #{order_id}", payment: paymill_payment_id

      self.paymill_id = transaction.id
      save!
    end
  rescue Paymill::PaymillError => e
    logger.error "Paymill error while creating customer: #{e.message}"
    errors.add :base, "There was a problem with your credit card. Please try again."
    false
  end
end

I read somewhere in the documentation that the paymill payment object (a client's saved credit card details) is only valid for one year - is this correct? And if so how should this be dealt with? Is it a good idea to store this expiry date, as well as the users credit card expiry date, in my User model so I know when to ask them to enter their card info again?

2

There are 2 answers

0
Rajesh Kolappakam On BEST ANSWER

Suggested changes:

  1. Use the Payment model to store the payment_card_token and payment_id. This will allow you to support multiple cards per client, in case you need to in the future
  2. Create a PaymentTransaction model and db table. Each time the user makes a payment, store the details in a PaymentTransaction model instead of Payment model.
  3. Look into the webhooks framework. I haven't used it myself, but it might help with your questions about expired tokens, etc

Also, a general observation about your rails code

  • Instead of User.where("user_id = ?", user_id).update_attributes, just say user.update_attributes as you have already define the association.
  • Even better if you could move the if paymill_client_id block of code to the User model.
1
cbraun75 On

valid paymentobject - yes you are right the paymentobject is only valid for 364 days, but it is extended for another 364 days starting from the last transaction again. Important! The token should only be used one time till you receive the paymentobject in the successfull response of the transaction or preauth. Afterwards please use the paymentobject. We will change this behaviour that the token only can be used one time in our API Version 3.

webhooks - right now there is no webhook for an expired paymentobject, but we will implement such a token which alerts you after a card will be expiring in the next days. But will take some months. Till than you should save the expiry date. There is no problem about PCI Security to save this information.

Best, Christian