Á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 ...
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
Ở đây sau khi đăng ký xong, bạn cần tạo tiếp 1 tài khoản để làm người mua
- leanh@buyer.com: người dùng mua khóa học của hệ thống
- leanh@merchant.com: tài khoản để nhận các giao dịch từ buyer
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: "leanh@merchant.com", 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
- 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:
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: "leanh@merchant.com", 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
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 leanh@merchant.com 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:
- http://www.gotealeaf.com/blog/basic-paypal-checkout-processing-in-rails
- http://railscasts.com/episodes/141-paypal-basics?view=asciicast
link github tham khảo:
- https://github.com/leanh173/paypal_basics