简体   繁体   English

如何实现 Rails POST API 根据正文请求向外部 API 发送数据

[英]How to implement Rails POST API to send data to external API based on body request

I have been trying to integrate an API on a rails app.我一直在尝试在 rails 应用程序上集成 API。

It is structured in such a way that I have to write my own POST API to communicate back and forth with it.它的结构使得我必须编写自己的 POST API 来与它来回通信。

For example: POST dividebuy/api/getorderdetails例如: POST dividebuy/api/getorderdetails

Example Request:示例请求:

{
  "orderId":"6667",
  "retailerStoreCode":"default",
  "storeAuthentication":"5LIH1TaW8ewd",
  "storeToken":"3aa7Sgt76sz7"
}

Example Response:示例响应:

{
        "order_detail": {
        "store_order_id": "64",
        "store_order_increment_id": "145006485",
        "store_token": ENV['DIVIDEBUY_TOKEN'],
        "store_authentication": ENV['DIVIDEBUY_AUTHENTICATION'],
        "logo_url": "https://moduleinstalledmagento1.dbuytest.info/media/dividebuy/",
        "grand_total": 318.4,
        "subtotal": 265.33,
        "subtotalInclVat": 318.4,
        "discount": 0,
        "discountApplied": "beoforeVat",
        "shipping": 0,
        "shippingInclVat": 0,
        "shipping_label": "Free Shipping - Free",
        "shipping_method": "freeshipping_freeshipping",
        "is_default_shipping": 0,
        "is_default_billing": 0,
        "vat": 53.07
      },
      "product_details": [
        {
          "name": "Some product name",
          "sku": "SKU",
          "qty": "1.0000",
          "price": "249.1700",
          "priceInclVat": "299.0000",
          "rowTotal": "249.1700",
          "rowTotalInclVat": "299.0000",
          "discount": "0.0000",
          "short_description": "Some Product",
          "product_type": "simple",
          "product_weight": "35.5000",
          "product_visibility": "4",
          "DivVat": "20",
          "image_url": "some url.jpg"
        }
      ],
      "shipping_address": {
          "first_name": "name",
          "last_name": "name",
          "email": "retailer@dividebuy.co.uk",
          "street": [
              "Address 1",
              "Adress 2"
          ],
          "postcode": "DE4 3ED",
          "region": "County",
          "city": "town"
      },
      "billing_address": {
          "first_name": "name",
          "last_name": "name",
          "email": "retailer@dividebuy.co.uk",
          "street": [
              "Address 1", "Adress 2"
          ],
          "postcode": "ST15 8YR",
          "region": "County",
          "city": "town"
      }
    }

so the controller I have is structured like this:所以我拥有的 controller 的结构如下:

class Dividebuy::Api::GetorderdetailsController < ApplicationController
  protect_from_forgery with: :null_session
  skip_before_action :verify_authenticity_token, only: :create

  # GET /product
  def index
    product = Spree::Product.all
    render json: product, status: 200
  end

  # POST /product
  def create

    data = {
        "order_detail": {
        "store_order_id": "64",
        "store_order_increment_id": "145006485",
        "store_token": ENV['DIVIDEBUY_TOKEN'],
        "store_authentication": ENV['DIVIDEBUY_AUTHENTICATION'],
        "logo_url": "https://moduleinstalledmagento1.dbuytest.info/media/dividebuy/",
        "grand_total": 318.4,
        "subtotal": 265.33,
        "subtotalInclVat": 318.4,
        "discount": 0,
        "discountApplied": "beoforeVat",
        "shipping": 0,
        "shippingInclVat": 0,
        "shipping_label": "Free Shipping - Free",
        "shipping_method": "freeshipping_freeshipping",
        "is_default_shipping": 0,
        "is_default_billing": 0,
        "vat": 53.07
      },
      "product_details": [
        {
          "name": "Some product name",
          "sku": "SKU",
          "qty": "1.0000",
          "price": "249.1700",
          "priceInclVat": "299.0000",
          "rowTotal": "249.1700",
          "rowTotalInclVat": "299.0000",
          "discount": "0.0000",
          "short_description": "Some Product",
          "product_type": "simple",
          "product_weight": "35.5000",
          "product_visibility": "4",
          "DivVat": "20",
          "image_url": "some url.jpg"
        }
      ],
      "shipping_address": {
          "first_name": "name",
          "last_name": "name",
          "email": "retailer@dividebuy.co.uk",
          "street": [
              "Address 1",
              "Adress 2"
          ],
          "postcode": "DE4 3ED",
          "region": "County",
          "city": "town"
      },
      "billing_address": {
          "first_name": "name",
          "last_name": "name",
          "email": "retailer@dividebuy.co.uk",
          "street": [
              "Address 1", "Adress 2"
          ],
          "postcode": "ST15 8YR",
          "region": "County",
          "city": "town"
      }
    }

    user = User.where(email: 'test@example.com')

    if user.valid_password?(params[:password])
      render json:  data, status: :created
    else
      render json: { error: "error:" }, status: 400
    end
  end

end

Here is what I have on my routes for this API:这是我在此 API 的路线上的内容:

  namespace :dividebuy, defaults: { format: 'json' } do
    namespace :api do
      resources :getorderdetails, only: [:index, :create]
    end
  end

My question is basically from the examples given in the documentation of the request & response as shown above, what is the best way to integrate with this API communication on my rails app?我的问题基本上来自如上所示的请求响应文档中给出的示例,在我的 rails 应用程序上与此 API 通信集成的最佳方法是什么? I just hardcoded some data and passed it as a response, probably there is a better way to do that.我只是硬编码了一些数据并将其作为响应传递,可能有更好的方法来做到这一点。

More clarity, to test I use postman: localhost:3000/dividebuy/api/getorderdetails更清晰,为了测试我使用 postman: localhost:3000/dividebuy/api/getorderdetails

Any help or guidance will be much appreciated.任何帮助或指导将不胜感激。

Since I just did something similar myself, I can tell you my approach, which follows my guiding principle of "fat model skinny controller".由于我自己也做了类似的事情,所以我可以告诉你我的方法,它遵循我的“胖 model 瘦控制器”的指导原则。

All the api-related structures that you show in the GetOrderDetailsController should be moved into a service class.您在GetOrderDetailsController中显示的所有与 api 相关的结构都应移动到服务 class 中。 Since I see the word Spree in your question, I'll call it SpreeService .由于我在您的问题中看到 Spree 这个词,我将其称为SpreeService So the first step at refactoring is to change your GetOrderDetailsController :所以重构的第一步是改变你的GetOrderDetailsController

# app/models/dividebuy/api/get_order_details.rb

def create
  spree = SpreeService.new(params)

  response = spree.create_order

  if response.errors
    # render the error page
  else
    # render the success page, with order number etc
  end
end

This gives the general idea, specifics depend on your app.这给出了总体思路,具体取决于您的应用程序。 In the SpreeService class, you can further decompose the request into smaller methods.SpreeService class 中,您可以进一步将请求分解为更小的方法。 As you app develops, you will find more and more functionality to delegate to the SpreeService class.随着应用程序的开发,您会发现越来越多的功能可以委托给SpreeService class。

# app/domain_models/spree_service.rb
require 'net/http'

class SpreeService
  BaseUrl = "api.spree.com"

  def initialize(params)
    # capture the params of interest
  end

  def create_order
    response = Net::HTTP.request(...)
  end

private
  def create_order_query
    # define the hash of all the date to make new order
  end
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM