فهرست منبع

Merge pull request #462 from Shopify/new-abandoned-checkouts-resource

Add an abandoned checkout ActiveResource
Emmanuel Milou 6 سال پیش
والد
کامیت
9b50bd41c1

+ 7 - 0
CHANGELOG

@@ -1,3 +1,10 @@
+== Version 5.0.0
+
+* Added `ShopifyAPI::AbandonedCheckout`
+* Added support for X-Shopify-Checkout-Version header on `ShopifyAPI::Checkout`
+* Added `ShopifyAPI::ShippingRate`
+* Added support for Checkout::complete endpoint
+
 == Version 4.12.0
 
 * Added support for the GraphQL API

+ 7 - 0
README.md

@@ -10,6 +10,13 @@ The Shopify API gem allows Ruby developers to programmatically access the admin
 
 The API is implemented as JSON over HTTP using all four verbs (GET/POST/PUT/DELETE). Each resource, like Order, Product, or Collection, has its own URL and is manipulated in isolation. In other words, we’ve tried to make the API follow the REST principles as much as possible.
 
+## ⚠️ Breaking change notice for version 5.0.0 ⚠️
+The [Abandoned Checkout API](https://help.shopify.com/en/api/reference/orders/abandoned_checkouts) is now accessed through the `ShopifyAPI::AbandonedCheckout` resource. If you were previously accessing the Abandoned Checkout API through the `ShopifyAPI::Checkout` resource, you will need to update your code after upgrading from version 4.x.x or earlier.
+
+Going forward, the `ShopifyAPI::Checkout` resource is used to access the [Checkout API](https://help.shopify.com/en/api/reference/sales_channels/checkout), which can be used to create new checkouts.
+
+For more details, [please see this issue](https://github.com/Shopify/shopify_api/issues/471).
+
 ## Usage
 
 ### Requirements

+ 7 - 0
lib/shopify_api/resources/abandoned_checkout.rb

@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module ShopifyAPI
+  class AbandonedCheckout < Base
+    self.element_name = "checkout"
+  end
+end

+ 24 - 1
lib/shopify_api/resources/checkout.rb

@@ -1,4 +1,27 @@
+# frozen_string_literal: true
+
 module ShopifyAPI
   class Checkout < Base
+    self.primary_key = :token
+    headers['X-Shopify-Checkout-Version'] = '2016-09-06'
+
+    def complete
+      post(:complete)
+    end
+
+    def ready?
+      return false unless persisted?
+
+      reload
+      [200, 201].include?(ShopifyAPI::Base.connection.response.code.to_i)
+    end
+
+    def payments
+      Payment.find(:all, params: { checkout_id: id })
+    end
+
+    def shipping_rates
+      ShippingRate.find(:all, params: { checkout_id: id })
+    end
   end
-end
+end

+ 7 - 0
lib/shopify_api/resources/payment.rb

@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module ShopifyAPI
+  class Payment < Base
+    self.prefix = '/admin/checkouts/:checkout_id/'
+  end
+end

+ 7 - 0
lib/shopify_api/resources/shipping_rate.rb

@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module ShopifyAPI
+  class ShippingRate < Base
+    self.prefix = '/admin/checkouts/:checkout_id/'
+  end
+end

+ 1 - 1
lib/shopify_api/version.rb

@@ -1,3 +1,3 @@
 module ShopifyAPI
-  VERSION = "4.13.0"
+  VERSION = "5.0.0"
 end

+ 29 - 0
test/abandoned_checkouts_test.rb

@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+require 'test_helper'
+
+class AbandonedCheckoutsTest < Test::Unit::TestCase
+  def setup
+    super
+
+    @expected_checkouts = JSON.parse(load_fixture('abandoned_checkouts'))['checkouts']
+    @expected_checkout_id = JSON.parse(load_fixture('abandoned_checkout'))['checkout']['id']
+  end
+
+  test ":create creates a checkout" do
+    fake 'checkouts', method: :post, status: 201, body: load_fixture('abandoned_checkout')
+
+    checkout = ShopifyAPI::AbandonedCheckout.create
+
+    assert_equal @expected_checkout_id, checkout.id
+    assert_equal true, checkout.attributes.include?(:abandoned_checkout_url)
+  end
+
+  test "get all checkouts indexed by token" do
+    fake 'checkouts', method: :get, status: 200, body: load_fixture('abandoned_checkouts')
+
+    checkouts = ShopifyAPI::AbandonedCheckout.all
+
+    assert_equal @expected_checkout_id, checkouts.first.id
+    assert_equal @expected_checkouts.size, checkouts.size
+  end
+end

+ 67 - 4
test/checkouts_test.rb

@@ -1,9 +1,72 @@
+# frozen_string_literal: true
 require 'test_helper'
 
 class CheckoutsTest < Test::Unit::TestCase
-  test "get all should get all orders" do
-    fake 'checkouts', :method => :get, :status => 200, :body => load_fixture('checkouts')
-    checkout = ShopifyAPI::Checkout.all
-    assert_equal 450789469, checkout.first.id
+  def setup
+    super
+
+    @expected_checkouts = JSON.parse(load_fixture('checkouts'))['checkouts']
+    @expected_checkout_id = JSON.parse(load_fixture('checkout'))['checkout']['token']
+  end
+
+  test ":create creates a checkout" do
+    fake 'checkouts', method: :post, status: 201, body: load_fixture('checkout')
+
+    checkout = ShopifyAPI::Checkout.create
+
+    assert_equal @expected_checkout_id, checkout.id
+  end
+
+  test "get all checkouts indexed by token" do
+    fake 'checkouts', method: :get, status: 200, body: load_fixture('checkouts')
+
+    checkouts = ShopifyAPI::Checkout.all
+
+    assert_equal @expected_checkout_id, checkouts.first.id
+    assert_equal @expected_checkouts.size, checkouts.size
+  end
+
+  test ":complete completes a checkout" do
+    fake "checkouts/#{@expected_checkout_id}", method: :get, status: 200, body: load_fixture('checkout')
+
+    checkout = ShopifyAPI::Checkout.find(@expected_checkout_id)
+
+    fake "checkouts/#{@expected_checkout_id}/complete", method: :post, status: 200, body: load_fixture('checkouts')
+
+    checkout.complete
+  end
+
+  test ":ready? returns true when status is 201" do
+    fake "checkouts/#{@expected_checkout_id}", method: :get, status: 201, body: load_fixture('checkout')
+    checkout = ShopifyAPI::Checkout.find(@expected_checkout_id)
+
+    assert_predicate checkout, :ready?
+  end
+
+  test ":ready? returns false when status is 202" do
+    fake "checkouts/#{@expected_checkout_id}", method: :get, status: 202, body: load_fixture('checkout')
+    checkout = ShopifyAPI::Checkout.find(@expected_checkout_id)
+
+    refute_predicate checkout, :ready?
+  end
+
+  test ":payments returns payments for a checkout" do
+    fake "checkouts/#{@expected_checkout_id}", method: :get, status: 200, body: load_fixture('checkout')
+    checkout = ShopifyAPI::Checkout.find(@expected_checkout_id)
+
+    fake "checkouts/#{@expected_checkout_id}/payments", method: :get, status: 202, body: load_fixture('payments')
+
+    assert_equal 10.00, checkout.payments.first.amount
+  end
+
+  test ":shipping_rates returns shipping rates for a checkout" do
+    fake "checkouts/#{@expected_checkout_id}", method: :get, status: 200, body: load_fixture('checkout')
+    checkout = ShopifyAPI::Checkout.find(@expected_checkout_id)
+
+    fake("checkouts/#{@expected_checkout_id}/shipping_rates",
+      method: :get,
+      status: 202,
+      body: load_fixture('shipping_rates'))
+    assert_equal "canada_post-INT.TP.BOGUS-4.00", checkout.shipping_rates.first.id
   end
 end

+ 3 - 2
test/detailed_log_subscriber_test.rb

@@ -8,6 +8,7 @@ class LogSubscriberTest < Test::Unit::TestCase
     super
     @page = { :page => { :id => 1, :title => 'Shopify API' } }.to_json
     @ua_header = "\"User-Agent\"=>\"ShopifyAPI/#{ShopifyAPI::VERSION} ActiveResource/#{ActiveResource::VERSION::STRING} Ruby/#{RUBY_VERSION}\""
+    @ver_header = "\"X-Shopify-Checkout-Version\"=>\"2016-09-06\""
 
     ShopifyAPI::Base.clear_session
     ShopifyAPI::Base.site = "https://this-is-my-test-shop.myshopify.com/admin"
@@ -28,7 +29,7 @@ class LogSubscriberTest < Test::Unit::TestCase
     assert_equal 4, @logger.logged(:info).size
     assert_equal "GET https://this-is-my-test-shop.myshopify.com:443/admin/pages/1.json", @logger.logged(:info)[0]
     assert_match /\-\-\> 200/, @logger.logged(:info)[1]
-    assert_equal "Headers: {\"Accept\"=>\"application/json\", #{@ua_header}}", @logger.logged(:info)[2]
+    assert_equal "Headers: {\"Accept\"=>\"application/json\", #{@ua_header}, #{@ver_header}}", @logger.logged(:info)[2]
     assert_match /Response:\n\{\"page\"\:\{((\"id\"\:1)|(\"title\"\:\"Shopify API\")),((\"id\"\:1)|(\"title\"\:\"Shopify API\"))\}\}/,  @logger.logged(:info)[3]
 
   end
@@ -43,7 +44,7 @@ class LogSubscriberTest < Test::Unit::TestCase
     assert_equal 4, @logger.logged(:info).size
     assert_equal "GET https://this-is-my-test-shop.myshopify.com:443/admin/pages/2.json", @logger.logged(:info)[0]
     assert_match /\-\-\> 404/, @logger.logged(:info)[1]
-    assert_equal "Headers: {\"Accept\"=>\"application/json\", #{@ua_header}}", @logger.logged(:info)[2]
+    assert_equal "Headers: {\"Accept\"=>\"application/json\", #{@ua_header}, #{@ver_header}}", @logger.logged(:info)[2]
     assert_equal "Response:", @logger.logged(:info)[3]
   end
 end

+ 184 - 0
test/fixtures/abandoned_checkout.json

@@ -0,0 +1,184 @@
+{
+  "checkout": {
+    "buyer_accepts_marketing": false,
+    "cart_token": "68778783ad298f1c80c3bafcddeea02f",
+    "closed_at": null,
+    "completed_at": null,
+    "created_at": "2012-10-12T07:05:27-04:00",
+    "currency": "USD",
+    "email": "bob.norman@hostmail.com",
+    "gateway": null,
+    "id": 450789469,
+    "landing_site": null,
+    "note": null,
+    "referring_site": null,
+    "shipping_lines": [
+      {
+        "title": "Free Shipping",
+        "price": "0.00",
+        "code": "Free Shipping",
+        "source": "shopify"
+      }
+    ],
+    "source": null,
+    "source_identifier": null,
+    "source_name": "web",
+    "source_url": null,
+    "subtotal_price": "398.00",
+    "taxes_included": false,
+    "token": "2a1ace52255252df566af0faaedfbfa7",
+    "total_discounts": "0.00",
+    "total_line_items_price": "398.00",
+    "total_price": "409.94",
+    "total_tax": "11.94",
+    "total_weight": 400,
+    "updated_at": "2012-10-12T07:05:27-04:00",
+    "line_items": [
+      {
+        "applied_discounts": [
+
+        ],
+        "compare_at_price": null,
+        "fulfillment_service": "manual",
+        "gift_card": false,
+        "grams": 200,
+        "id": 49148385,
+        "line_price": "199.00",
+        "price": "199.00",
+        "product_id": 632910392,
+        "properties": null,
+        "quantity": 1,
+        "requires_shipping": true,
+        "sku": "IPOD2008RED",
+        "tax_lines": [
+
+        ],
+        "taxable": true,
+        "title": "IPod Nano - 8GB",
+        "variant_id": 49148385,
+        "variant_title": "Red",
+        "vendor": "Apple"
+      },
+      {
+        "applied_discounts": [
+
+        ],
+        "compare_at_price": null,
+        "fulfillment_service": "manual",
+        "gift_card": false,
+        "grams": 200,
+        "id": 808950810,
+        "line_price": "199.00",
+        "price": "199.00",
+        "product_id": 632910392,
+        "properties": null,
+        "quantity": 1,
+        "requires_shipping": true,
+        "sku": "IPOD2008PINK",
+        "tax_lines": [
+
+        ],
+        "taxable": true,
+        "title": "IPod Nano - 8GB",
+        "variant_id": 808950810,
+        "variant_title": "Pink",
+        "vendor": "Apple"
+      }
+    ],
+    "name": "#450789469",
+    "note_attributes": [
+      {
+        "name": "custom engraving",
+        "value": "Happy Birthday"
+      },
+      {
+        "name": "colour",
+        "value": "green"
+      }
+    ],
+    "discount_codes": [
+      {
+        "code": "TENOFF",
+        "amount": "10.00"
+      }
+    ],
+    "abandoned_checkout_url": "https://checkout.local/orders/690933842/2a1ace52255252df566af0faaedfbfa7?recovered=1",
+    "tax_lines": [
+      {
+        "price": "11.94",
+        "rate": 0.06,
+        "title": "State Tax"
+      }
+    ],
+    "billing_address": {
+      "address1": "Chestnut Street 92",
+      "address2": "",
+      "city": "Louisville",
+      "company": null,
+      "country": "United States",
+      "first_name": "Bob",
+      "last_name": "Norman",
+      "latitude": "45.41634",
+      "longitude": "-75.6868",
+      "phone": "555-625-1199",
+      "province": "Kentucky",
+      "zip": "40202",
+      "name": "Bob Norman",
+      "country_code": "US",
+      "province_code": "KY"
+    },
+    "shipping_address": {
+      "address1": "Chestnut Street 92",
+      "address2": "",
+      "city": "Louisville",
+      "company": null,
+      "country": "United States",
+      "first_name": "Bob",
+      "last_name": "Norman",
+      "latitude": "45.41634",
+      "longitude": "-75.6868",
+      "phone": "555-625-1199",
+      "province": "Kentucky",
+      "zip": "40202",
+      "name": "Bob Norman",
+      "country_code": "US",
+      "province_code": "KY"
+    },
+    "customer": {
+      "accepts_marketing": false,
+      "created_at": "2014-03-07T16:12:37-05:00",
+      "email": "bob.norman@hostmail.com",
+      "first_name": "Bob",
+      "id": 207119551,
+      "last_name": "Norman",
+      "last_order_id": null,
+      "multipass_identifier": null,
+      "note": null,
+      "orders_count": 0,
+      "state": "disabled",
+      "total_spent": "0.00",
+      "updated_at": "2014-03-07T16:12:37-05:00",
+      "verified_email": true,
+      "tags": "",
+      "last_order_name": null,
+      "default_address": {
+        "address1": "Chestnut Street 92",
+        "address2": "",
+        "city": "Louisville",
+        "company": null,
+        "country": "United States",
+        "first_name": null,
+        "id": 207119551,
+        "last_name": null,
+        "phone": "555-625-1199",
+        "province": "Kentucky",
+        "zip": "40202",
+        "name": null,
+        "province_code": "KY",
+        "country_code": "US",
+        "country_name": "United States",
+        "default": true
+      }
+    }
+  }
+}

+ 186 - 0
test/fixtures/abandoned_checkouts.json

@@ -0,0 +1,186 @@
+{
+  "checkouts": [
+    {
+      "buyer_accepts_marketing": false,
+      "cart_token": "68778783ad298f1c80c3bafcddeea02f",
+      "closed_at": null,
+      "completed_at": null,
+      "created_at": "2012-10-12T07:05:27-04:00",
+      "currency": "USD",
+      "email": "bob.norman@hostmail.com",
+      "gateway": null,
+      "id": 450789469,
+      "landing_site": null,
+      "note": null,
+      "referring_site": null,
+      "shipping_lines": [
+        {
+          "title": "Free Shipping",
+          "price": "0.00",
+          "code": "Free Shipping",
+          "source": "shopify"
+        }
+      ],
+      "source": null,
+      "source_identifier": null,
+      "source_name": "web",
+      "source_url": null,
+      "subtotal_price": "398.00",
+      "taxes_included": false,
+      "token": "2a1ace52255252df566af0faaedfbfa7",
+      "total_discounts": "0.00",
+      "total_line_items_price": "398.00",
+      "total_price": "409.94",
+      "total_tax": "11.94",
+      "total_weight": 400,
+      "updated_at": "2012-10-12T07:05:27-04:00",
+      "line_items": [
+        {
+          "applied_discounts": [
+
+          ],
+          "compare_at_price": null,
+          "fulfillment_service": "manual",
+          "gift_card": false,
+          "grams": 200,
+          "id": 49148385,
+          "line_price": "199.00",
+          "price": "199.00",
+          "product_id": 632910392,
+          "properties": null,
+          "quantity": 1,
+          "requires_shipping": true,
+          "sku": "IPOD2008RED",
+          "tax_lines": [
+
+          ],
+          "taxable": true,
+          "title": "IPod Nano - 8GB",
+          "variant_id": 49148385,
+          "variant_title": "Red",
+          "vendor": "Apple"
+        },
+        {
+          "applied_discounts": [
+
+          ],
+          "compare_at_price": null,
+          "fulfillment_service": "manual",
+          "gift_card": false,
+          "grams": 200,
+          "id": 808950810,
+          "line_price": "199.00",
+          "price": "199.00",
+          "product_id": 632910392,
+          "properties": null,
+          "quantity": 1,
+          "requires_shipping": true,
+          "sku": "IPOD2008PINK",
+          "tax_lines": [
+
+          ],
+          "taxable": true,
+          "title": "IPod Nano - 8GB",
+          "variant_id": 808950810,
+          "variant_title": "Pink",
+          "vendor": "Apple"
+        }
+      ],
+      "name": "#450789469",
+      "note_attributes": [
+        {
+          "name": "custom engraving",
+          "value": "Happy Birthday"
+        },
+        {
+          "name": "colour",
+          "value": "green"
+        }
+      ],
+      "discount_codes": [
+        {
+          "code": "TENOFF",
+          "amount": "10.00"
+        }
+      ],
+      "abandoned_checkout_url": "https://checkout.local/orders/690933842/2a1ace52255252df566af0faaedfbfa7?recovered=1",
+      "tax_lines": [
+        {
+          "price": "11.94",
+          "rate": 0.06,
+          "title": "State Tax"
+        }
+      ],
+      "billing_address": {
+        "address1": "Chestnut Street 92",
+        "address2": "",
+        "city": "Louisville",
+        "company": null,
+        "country": "United States",
+        "first_name": "Bob",
+        "last_name": "Norman",
+        "latitude": "45.41634",
+        "longitude": "-75.6868",
+        "phone": "555-625-1199",
+        "province": "Kentucky",
+        "zip": "40202",
+        "name": "Bob Norman",
+        "country_code": "US",
+        "province_code": "KY"
+      },
+      "shipping_address": {
+        "address1": "Chestnut Street 92",
+        "address2": "",
+        "city": "Louisville",
+        "company": null,
+        "country": "United States",
+        "first_name": "Bob",
+        "last_name": "Norman",
+        "latitude": "45.41634",
+        "longitude": "-75.6868",
+        "phone": "555-625-1199",
+        "province": "Kentucky",
+        "zip": "40202",
+        "name": "Bob Norman",
+        "country_code": "US",
+        "province_code": "KY"
+      },
+      "customer": {
+        "accepts_marketing": false,
+        "created_at": "2014-03-07T16:12:37-05:00",
+        "email": "bob.norman@hostmail.com",
+        "first_name": "Bob",
+        "id": 207119551,
+        "last_name": "Norman",
+        "last_order_id": null,
+        "multipass_identifier": null,
+        "note": null,
+        "orders_count": 0,
+        "state": "disabled",
+        "total_spent": "0.00",
+        "updated_at": "2014-03-07T16:12:37-05:00",
+        "verified_email": true,
+        "tags": "",
+        "last_order_name": null,
+        "default_address": {
+          "address1": "Chestnut Street 92",
+          "address2": "",
+          "city": "Louisville",
+          "company": null,
+          "country": "United States",
+          "first_name": null,
+          "id": 207119551,
+          "last_name": null,
+          "phone": "555-625-1199",
+          "province": "Kentucky",
+          "zip": "40202",
+          "name": null,
+          "province_code": "KY",
+          "country_code": "US",
+          "country_name": "United States",
+          "default": true
+        }
+      }
+    }
+  ]
+}

+ 160 - 0
test/fixtures/checkout.json

@@ -0,0 +1,160 @@
+{
+  "checkout": {
+    "applied_discount": "0.00",
+    "clone_url": "",
+    "completed_at": null,
+    "created_at": "2012-10-12T07:05:27-04:00",
+    "credit_card": null,
+    "currency": "USD",
+    "presentment_currency": "USD",
+    "email": "bob.norman@hostmail.com",
+    "note": null,
+    "shipping_line": [
+      {
+        "title": "Free Shipping",
+        "price": "0.00",
+        "code": "Free Shipping",
+        "source": "shopify"
+      }
+    ],
+    "shipping_rates": [
+      {
+        "id": "canada_post-INT.TP.BOGUS-4.00",
+        "price": "4.00",
+        "title": "Small Packet International Air Bogus"
+      },
+      {
+        "id": "canada_post-INT.TP.BOGUS-8.00",
+        "price": "8.00",
+        "title": "Medium Packet International Air Bogus"
+      }
+    ],
+    "source_identifier": null,
+    "source_name": "web",
+    "source_url": null,
+    "subtotal_price": "398.00",
+    "shipping_policy_url": null,
+    "taxes_included": false,
+    "token": "2a1ace52255252df566af0faaedfbfa7",
+    "total_line_items_price": "398.00",
+    "total_price": "409.94",
+    "total_tax": "11.94",
+    "updated_at": "2012-10-12T07:05:27-04:00",
+    "line_items": [
+      {
+        "applied_discounts": [
+
+        ],
+        "compare_at_price": null,
+        "fulfillment_service": "manual",
+        "gift_card": false,
+        "grams": 200,
+        "id": 49148385,
+        "line_price": "199.00",
+        "price": "199.00",
+        "product_id": 632910392,
+        "properties": null,
+        "quantity": 1,
+        "requires_shipping": true,
+        "sku": "IPOD2008RED",
+        "tax_lines": [
+
+        ],
+        "taxable": true,
+        "title": "IPod Nano - 8GB",
+        "variant_id": 49148385,
+        "variant_title": "Red",
+        "vendor": "Apple"
+      },
+      {
+        "applied_discounts": [
+
+        ],
+        "compare_at_price": null,
+        "fulfillment_service": "manual",
+        "gift_card": false,
+        "grams": 200,
+        "id": 808950810,
+        "line_price": "199.00",
+        "price": "199.00",
+        "product_id": 632910392,
+        "properties": null,
+        "quantity": 1,
+        "requires_shipping": true,
+        "sku": "IPOD2008PINK",
+        "tax_lines": [
+
+        ],
+        "taxable": true,
+        "title": "IPod Nano - 8GB",
+        "variant_id": 808950810,
+        "variant_title": "Pink",
+        "vendor": "Apple"
+      }
+    ],
+    "name": "#450789469",
+    "note_attributes": [
+      {
+        "name": "custom engraving",
+        "value": "Happy Birthday"
+      },
+      {
+        "name": "colour",
+        "value": "green"
+      }
+    ],
+    "discount_code": [
+      {
+        "code": "TENOFF",
+        "amount": "10.00"
+      }
+    ],
+    "tax_lines": [
+      {
+        "price": "11.94",
+        "rate": 0.06,
+        "title": "State Tax"
+      }
+    ],
+    "billing_address": {
+      "address1": "Chestnut Street 92",
+      "address2": "",
+      "city": "Louisville",
+      "company": null,
+      "country": "United States",
+      "first_name": "Bob",
+      "last_name": "Norman",
+      "latitude": "45.41634",
+      "longitude": "-75.6868",
+      "phone": "555-625-1199",
+      "province": "Kentucky",
+      "zip": "40202",
+      "name": "Bob Norman",
+      "country_code": "US",
+      "province_code": "KY"
+    },
+    "shipping_address": {
+      "address1": "Chestnut Street 92",
+      "address2": "",
+      "city": "Louisville",
+      "company": null,
+      "country": "United States",
+      "first_name": "Bob",
+      "last_name": "Norman",
+      "latitude": "45.41634",
+      "longitude": "-75.6868",
+      "phone": "555-625-1199",
+      "province": "Kentucky",
+      "zip": "40202",
+      "name": "Bob Norman",
+      "country_code": "US",
+      "province_code": "KY"
+    },
+    "customer_id": null,
+    "customer_locale": "en-CA",
+    "device_id": "12",
+    "order": null,
+    "order_id": null,
+    "order_status_url": ""
+  }
+}

+ 25 - 49
test/fixtures/checkouts.json

@@ -1,19 +1,16 @@
 {
   "checkouts": [
     {
-      "buyer_accepts_marketing": false,
-      "cart_token": "68778783ad298f1c80c3bafcddeea02f",
-      "closed_at": null,
+      "applied_discount": "0.00",
+      "clone_url": "",
       "completed_at": null,
       "created_at": "2012-10-12T07:05:27-04:00",
+      "credit_card": null,
       "currency": "USD",
+      "presentment_currency": "USD",
       "email": "bob.norman@hostmail.com",
-      "gateway": null,
-      "id": 450789469,
-      "landing_site": null,
       "note": null,
-      "referring_site": null,
-      "shipping_lines": [
+      "shipping_line": [
         {
           "title": "Free Shipping",
           "price": "0.00",
@@ -21,18 +18,28 @@
           "source": "shopify"
         }
       ],
-      "source": null,
+      "shipping_rates": [
+        {
+          "id": "canada_post-INT.TP.BOGUS-4.00",
+          "price": "4.00",
+          "title": "Small Packet International Air Bogus"
+        },
+        {
+          "id": "canada_post-INT.TP.BOGUS-8.00",
+          "price": "8.00",
+          "title": "Medium Packet International Air Bogus"
+        }
+      ],
       "source_identifier": null,
       "source_name": "web",
       "source_url": null,
       "subtotal_price": "398.00",
+      "shipping_policy_url": null,
       "taxes_included": false,
       "token": "2a1ace52255252df566af0faaedfbfa7",
-      "total_discounts": "0.00",
       "total_line_items_price": "398.00",
       "total_price": "409.94",
       "total_tax": "11.94",
-      "total_weight": 400,
       "updated_at": "2012-10-12T07:05:27-04:00",
       "line_items": [
         {
@@ -97,13 +104,12 @@
           "value": "green"
         }
       ],
-      "discount_codes": [
+      "discount_code": [
         {
           "code": "TENOFF",
           "amount": "10.00"
         }
       ],
-      "abandoned_checkout_url": "https://checkout.local/orders/690933842/2a1ace52255252df566af0faaedfbfa7?recovered=1",
       "tax_lines": [
         {
           "price": "11.94",
@@ -145,42 +151,12 @@
         "country_code": "US",
         "province_code": "KY"
       },
-      "customer": {
-        "accepts_marketing": false,
-        "created_at": "2014-03-07T16:12:37-05:00",
-        "email": "bob.norman@hostmail.com",
-        "first_name": "Bob",
-        "id": 207119551,
-        "last_name": "Norman",
-        "last_order_id": null,
-        "multipass_identifier": null,
-        "note": null,
-        "orders_count": 0,
-        "state": "disabled",
-        "total_spent": "0.00",
-        "updated_at": "2014-03-07T16:12:37-05:00",
-        "verified_email": true,
-        "tags": "",
-        "last_order_name": null,
-        "default_address": {
-          "address1": "Chestnut Street 92",
-          "address2": "",
-          "city": "Louisville",
-          "company": null,
-          "country": "United States",
-          "first_name": null,
-          "id": 207119551,
-          "last_name": null,
-          "phone": "555-625-1199",
-          "province": "Kentucky",
-          "zip": "40202",
-          "name": null,
-          "province_code": "KY",
-          "country_code": "US",
-          "country_name": "United States",
-          "default": true
-        }
-      }
+      "customer_id": null,
+      "customer_locale": "en-CA",
+      "device_id": "12",
+      "order": null,
+      "order_id": null,
+      "order_status_url": ""
     }
   ]
 }

+ 7 - 0
test/fixtures/payment.json

@@ -0,0 +1,7 @@
+{
+  "payment" : {
+    "amount": 10.00,
+    "session_id": "east-44a400ef20b36e38f10b882cb7260796",
+    "unique_token": "my-client-generated-idempotency-token"
+  }
+}

+ 9 - 0
test/fixtures/payments.json

@@ -0,0 +1,9 @@
+{
+  "payments" : [
+    {
+      "amount": 10.00,
+      "session_id": "east-44a400ef20b36e38f10b882cb7260796",
+      "unique_token": "my-client-generated-idempotency-token"
+    }
+  ]
+}

+ 12 - 0
test/fixtures/shipping_rates.json

@@ -0,0 +1,12 @@
+[
+  {
+    "id": "canada_post-INT.TP.BOGUS-4.00",
+    "price": "4.00",
+    "title": "Small Packet International Air Bogus"
+  },
+  {
+    "id": "canada_post-INT.TP.BOGUS-8.00",
+    "price": "8.00",
+    "title": "Medium Packet International Air Bogus"
+  }
+]

+ 19 - 0
test/payment_test.rb

@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+require 'test_helper'
+
+class PaymentTest < Test::Unit::TestCase
+  def setup
+    super
+
+    @checkout_id = JSON.parse(load_fixture('checkout'))['checkout']['token']
+    @expected_payment = JSON.parse(load_fixture('payment'))['payment']
+  end
+
+  test ":create creates a new payment" do
+    fake "checkouts/#{@checkout_id}/payments", method: :post, status: 201, body: load_fixture('payment')
+
+    new_payment = ShopifyAPI::Payment.create(checkout_id: @checkout_id)
+
+    assert_equal @expected_payment['unique_token'], new_payment.attributes['unique_token']
+  end
+end

+ 17 - 0
test/shipping_rate_test.rb

@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'test_helper'
+
+class ShippingRateTest < Test::Unit::TestCase
+  test ":get lists all shipping rates for a given checkout" do
+    fake 'checkouts', method: :get, status: 200, body: load_fixture('checkouts')
+    checkouts = ShopifyAPI::Checkout.all
+
+    fake "checkouts/#{checkouts.first.id}/shipping_rates",
+      method: :get, status: 200, body: load_fixture('checkouts')
+    shipping_rates = ShopifyAPI::ShippingRate.find(:all, params: { checkout_id: checkouts.first.id })
+
+    assert_equal 2, shipping_rates.first.shipping_rates.length
+    assert_equal 'canada_post-INT.TP.BOGUS-4.00', shipping_rates.first.shipping_rates.first.id
+  end
+end