Áp dụng Paypal trong rails

Lời mở

Ngày nay thương mại trực tuyến ngày càng phổ biến và giao dịch điện tử đã không còn xa lạ với hầu hết những ai dùng internet. Vậy chắc chắc sẽ có ai đó có cấu hỏi "Làm thế nào để áp dụng phương pháp giao dịch điện tử(GDĐT) vào trong rails app mà mình đã viết!". Tôi hi vọng sau bài viết sau đây sẽ giúp bạn 1 phần nào đó hiểu và áp dụng được mô hình GDĐT vào hệ thống của bạn.

Ở đây tôi sẽ tạo 1 ứng dụng sử dụng paypal để trả tiền khi đăng ký 1 khóa học qua mạng.

Bắt tay vào việc nào

Tôi sẽ không đi sâu vào bước cơ bản vào từ bước bắt đầu tạo 1 app rails, user ... mà sẽ coi như các bạn đã có rồi, và bắt đầu bằng việc tạo 1 model course-khóa học cho người dùng đăng kí và trả phí

rails g model Course name:string price:integer

Đồng thời bạn cũng sẽ phải tạo 1 model để lưu đăng kí của người dùng-registrations

rails g model Registration courses:reference user_name:string address:string eamil:string phone:string

Dĩ nhiên các thông tin phụ(name, email, phone, address) ở trên chỉ là ví dụ và các bạn có thể thay đổi tuỳ theo yêu cầu cá nhân . sau đó chạy lệnh

rake db:create
rake db:migrate

trên command line để tạo model mới trên. Sau đó bạn cần tạo 1 số dữ liệu cho model course để test bởi vì phải có khóa học nào đó thì user mới có thể đăng ký và trả tiền được chứ bạn có thể vào "rails c" trực tiếp tạo dữ liệu

rails c
> Course.create name: "learning ruby", price: 1000
> Course.create name: "learning C", price: 1000
> Course.create name: "learning java", price: 1000

Về phần view và con troller thì tôi sẽ không đi chi tiết về việc xử lý khi người dùng muốn đăng ký 1 khóa học (tương ứng với tạo 1 bản ghi registration ứng với khóa học đó), tôi tin rằng các bạn có thể xử lý viêc này không khó. Tiếp đến là phần chính của bài viết này đó là tạo liên kết của app với paypal để giúp người dùng có thể thanh toán online.

Bước 1: Bạn phải đăng ký 1 tài khoản để nhận thanh toán online trên paypal qua link sau đó bạn cần tạo tài khoản người mua(user) người bán(bạn) trong sandbox để test qua link Screenshot from 2015-06-29 13:55:24.png

Ở đây sau khi đăng ký xong, bạn cần tạo tiếp 1 tài khoản để làm người mua

Chú ý: Tất cả tài khoản trên đều là tài khoản test ở trong sandbox

Bước 2: trong controller của registration lúc tạo 1 bản ghi mới khi người dùng mua khóa học chúng ta sẽ phải chuyển tiếp link sang paypal để người dùng trả tiền qua đó

# registrations controller
  def create
    @registration = Registration.new(registration_params)
    if @registration.save
      redirect_to @registration.paypal_url(registration_path(@registration))
    else
      render :new
    end
  end

Với hàm paypal_url trong model registration sẽ tường ứng cho 1 đường dẫn của thanh toán

# model registration
def paypal_url(return_path)
    values = {
        business: "[email protected]",
        cmd: "_xclick",
        upload: 1,
        return: "#{Settings.app_host}#{return_path}",
        invoice: id,
        amount: course.price,
        item_name: course.name,
        item_number: course.id,
        quantity: '1',
        notify_url: "#{Rails.application.secrets.app_host}/hook"
    }
    "#{Settings.paypal_host}/cgi-bin/webscr?" + values.to_query
  end

Giải thích 1 chút:

  • business: email của tài khoản nhận thanh toán trên paypal do trang web bạn quản lý.
  • cmd: lệnh giao dịch, 1 sản phầm là "_xclick", nếu giao dịch 1 lúc nhiều sản phẩn thì là "_xcartart"
  • return: link đường dẫn(đoạn text "return to leanh's Test Store") sau khi người dùng thanh toán thành công, thường là 1 trang web hiển thị trạng thái thanh toán ở web người bán

back.png

  • invoice: id của bản ghi registration để hệ thống cập nhật sau khi Paypal callback
  • amount: khoản tiền cần thanh toán
  • notify_url: link mà paypal sẽ callback lại server bạn sau khi xác minh 1 giao dịch thành công (thường là địa chỉ link trang web của bạn) Lưu ý các địa chỉ nên được lưu vào trong setting
#development:
  paypal_host: https://www.sandbox.paypal.com
  app_host: http://your_app_url
#production:
  paypal_host: https://www.paypal.com
  app_host: http://your_app_url
  • tiếp theo là các thông tin bổ sung thêm cho giao dịch để người dùng xác nhận trên paypal khi giao dịch ở đây sau khi điền đủ các thông tin này thì chúng ta sẽ có được 1 đường dẫn đến paypal bao gồm các thôm tin sản phẩm giao dịch cần thiết (values.to_query) trên paypal để người dùng chuyển tiếp tới và thanh toán "#{Settings.paypal_host}/cgi-bin/webscr?" + values.to_query

link trang paypal đc gọi tới mẫu:

paying.png

Bước 3

Khởi tạo callback cho Paypal vào hệ thống thêm routes

#config/routes.rb
post "/registrations/:id" => "registrations#show"
post "/hook" => "regstrations#hook"

Tiếp theo bạn thêm hook vào controller registration để xử lý respond từ paypal

protect_from_forgery except: [:hook]
  def hook
    params.permit! # Permit all Paypal input params
    status = params[:payment_status]
    if status == "Completed"
      @registration = Registration.find params[:invoice]
      @registration.update_attributes notification_params: params, status: status, transaction_id: params[:txn_id], purchased_at: Time.now
    end
    render nothing: true
  end

Ở đây ta dựa vào giá trị status trong params paypal gửi sang để xác định giao dịch thành công chưa. Ngoài ra ta phải bỏ protect_from_forgery để tắt quá trình kiểm tra csrf khi Paypal gửi. như các bạn thấy ở trên chúng ta tốt nhất nên lưu lại các thông tin mà Paypal trả về vào CSDL để sau này khi có sự cố thì ta có thể xem lại danh sách giao dịch mà server đã nhận.

rails g migration add_params_status_transaction_id_purchased_at_to_registrations notification_params:text status:string transaction_id:string purchased_at:datetime
rake db:migrate

Okie vậy cơ bản một giao dịch đăng ký khóa học đã hoàn tất, bạn có thể bật server lên và test.

Và giờ chắc nhiều bạn sẽ có thêm 1 vấn đề, nếu khách hàng muốn thanh toán mua nhiều sản phần một lúc giống trên các trang bán hàng trực tuyến như http://www.amazon.ca/ thì phải làm như thế nào

Rất đơn giản bạn chỉ việc sửa lại hàm gọi đến paypal

#model/order
def paypal_url(return_url)
  values = {
    business: "[email protected]",
    cmd: "_xcart",
    upload: 1,
    return: "#{Settings.app_host}#{return_path}",
    invoice: id,
    notify_url: "#{Rails.application.secrets.app_host}/hook
  }

  line_items.each_with_index do |item, index|
    values.merge!({
      "amount_#{index + 1}" => item.unit_price,
      "item_name_#{index + 1}" => item.name,
      "item_number_#{index + 1}" => item.identifier,
      "quantity_#{index + 1}" => item.quantity
    })
  end
  "#{Settings.paypal_host}/cgi-bin/webscr?" + values.to_query
end

với line_intems là danh sách các item của order

Sau khi người dùng click để chuyển sang trang thanh toán sẽ có dạng dưới đây

cart.png

Một số điểm lưu ý ngoài:

  • Để kiểm tra các giao dịch trên Paypal các bạn có thể đăng nhập vào Paypal bằng tài khoản [email protected] trên qua link trong sandbox
  • lúc redirect sang trang thanh toán Paypal thường load khá là lâu nên bạn có thể add thêm 1 đoạn script jquery để ẩn nút submit và hiện thông báo đang chuyển link để người dùng ko phải có cảm giác chờ đợi quá lâu

Tham khảo:

link github tham khảo: