diff --git a/Gemfile.lock b/Gemfile.lock index dd83a2c..a06e63e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -4,6 +4,7 @@ PATH beyond_api (0.24.2.pre) activesupport (~> 7.0) faraday (~> 2.10.0) + faraday-multipart faraday-retry zeitwerk @@ -42,6 +43,8 @@ GEM faraday (2.10.1) faraday-net_http (>= 2.0, < 3.2) logger + faraday-multipart (1.0.4) + multipart-post (~> 2) faraday-net_http (3.1.1) net-http faraday-retry (2.2.1) @@ -56,6 +59,7 @@ GEM logger (1.6.0) method_source (1.1.0) minitest (5.24.1) + multipart-post (2.4.1) net-http (0.4.1) uri parallel (1.26.2) diff --git a/beyond_api.gemspec b/beyond_api.gemspec index 96a9bcc..8948629 100644 --- a/beyond_api.gemspec +++ b/beyond_api.gemspec @@ -32,6 +32,7 @@ Gem::Specification.new do |spec| spec.add_dependency 'activesupport', '~> 7.0' spec.add_dependency 'faraday', '~> 2.10.0' + spec.add_dependency 'faraday-multipart' spec.add_dependency 'faraday-retry' spec.add_dependency 'zeitwerk' diff --git a/lib/beyond_api.rb b/lib/beyond_api.rb index 7c5c075..d2fd69a 100644 --- a/lib/beyond_api.rb +++ b/lib/beyond_api.rb @@ -3,6 +3,7 @@ require 'active_support/all' require 'faraday' require 'faraday/retry' +require 'faraday/multipart' require 'forwardable' require 'json' require 'zeitwerk' diff --git a/lib/beyond_api/concerns/connection.rb b/lib/beyond_api/concerns/connection.rb index fc88b2d..9109a51 100644 --- a/lib/beyond_api/concerns/connection.rb +++ b/lib/beyond_api/concerns/connection.rb @@ -32,6 +32,27 @@ def delete(path, params = {}) handle_request { agent.delete(path, parse_request(params)) } end + def upload_file(path, file_path, params = {}) + handle_request do + agent.post(path) do |request| + request.headers['Content-Type'] = Utils.file_content_type(file_path) + request.params = parse_request(params) + request.body = File.binread(file_path) + end + end + end + + def upload_files(path, body, params = {}) + handle_request do + agent.post(path) do |request| + request.headers['Content-Type'] = 'multipart/form-data' + request.options[:params_encoder] = Faraday::FlatParamsEncoder + request.params = parse_request(params) + request.body = body + end + end + end + private def parse_request(hash) @@ -59,6 +80,7 @@ def agent # Request options faraday.request :json # Encode request bodies as JSON faraday.request :retry, BeyondApi.configuration.retry_options + faraday.request :multipart, { flat_encode: true } # Response options faraday.response :json, content_type: 'application/json' faraday.response :logger, *logger_config { |logger| apply_filters(logger) } diff --git a/lib/beyond_api/services/product_management/image.rb b/lib/beyond_api/services/product_management/image.rb index 14b937d..94360a9 100644 --- a/lib/beyond_api/services/product_management/image.rb +++ b/lib/beyond_api/services/product_management/image.rb @@ -19,6 +19,44 @@ class Image < BaseService def all(id, params = {}) get("products/#{id}/images", params) end + + # Upload an image and add it to a product. The body of the request must contain the content of the image. + # The maximum image size is 7000 × 7000 px, and the maximum file size per image is 8 MB. + # + # @see https://developer.epages.com/beyond-docs/#upload_product_image + # + # @param id [String] the product UUID + # @param id [String] the image path + # @param id [String] the image file name + # + # @return [Hash] + # + # @example + # client.upload('4125b993-49fc-47c8-b9b3-76d8871e4e06', '/home/epages/file.png', 'file.png') + def upload(product_id, image_path, image_name) + upload_file("products/#{product_id}/images", image_path, file_name: image_name) + end + + # Upload up to 10 images and add them to a product. The body of the request must contain the content of the images. + # The maximum image size is 7000 × 7000px, and the maximum file size per image is 8 MB. + # + # @see https://developer.epages.com/beyond-docs/#upload_multiple_product_images + # + # @param id [String] the product UUID + # @param id [Array] an array of strings containing the path of each image + # @param id [Array] an array of strings containing the file name of each image + # + # @return [Hash] + # + # @example + # image_paths = ['/home/epages/file1.png', '/home/epages/file2.png'] + # image_names = ['file1.png', 'file2.png'] + # client.upload('4125b993-49fc-47c8-b9b3-76d8871e4e06', image_paths, image_names) + def upload_multiple(product_id, image_paths, image_names) + upload_files("products/#{product_id}/images", + { image: Utils.faraday_file_parts(image_paths) }, # body + { file_name: Utils.encode_filenames(image_names) }) # params + end end end end diff --git a/lib/beyond_api/utils.rb b/lib/beyond_api/utils.rb index 095354c..3bdf6a1 100644 --- a/lib/beyond_api/utils.rb +++ b/lib/beyond_api/utils.rb @@ -18,5 +18,15 @@ def self.file_content_type(file_path) def self.camelize_keys(hash) hash.deep_transform_keys { |key| key.to_s.camelize(:lower) } end + + def self.faraday_file_parts(file_paths) + file_paths.map do |file_path| + Faraday::FilePart.new(File.open(file_path), Utils.file_content_type(file_path)) + end + end + + def self.encode_filenames(filenames) + filenames.map { |e| URI.encode_www_form([e]) } + end end end diff --git a/spec/beyond_api/services/product_management/image_spec.rb b/spec/beyond_api/services/product_management/image_spec.rb index 0fe5897..87e2555 100644 --- a/spec/beyond_api/services/product_management/image_spec.rb +++ b/spec/beyond_api/services/product_management/image_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe BeyondApi::ProductManagement::Image, vcr: true do +RSpec.describe BeyondApi::ProductManagement::Image, vcr: { match_requests_on: [:method, :uri] } do let(:client) { described_class.new(api_url: ENV.fetch('API_URL', nil), access_token: beyond_access_token) } describe '.all' do @@ -12,4 +12,23 @@ expect(response[:page]).to be_kind_of(Hash) end end + + describe '.upload' do + it 'uploads an image' do + response = client.upload('4bf6d53d-dfb2-4468-b6f9-f6e6265bc0bc', + 'spec/files/image1.png', + 'new-image.png') + + expect(response).not_to be nil + expect(response.dig(:links, :data, :href)).to include('new-image.png') + end + + it 'uploads multiple images' do + response = client.upload_multiple('4bf6d53d-dfb2-4468-b6f9-f6e6265bc0bc', + ['spec/files/image2.png', 'spec/files/image3.png'], + ['new-image2.png', 'new-image3.png']) + expect(response).not_to be nil + expect(response.dig(:embedded, :images)).to be_kind_of(Array) + end + end end diff --git a/spec/files/image3.png b/spec/files/image3.png new file mode 100644 index 0000000..ae85c3d Binary files /dev/null and b/spec/files/image3.png differ diff --git a/spec/vcr_cassettes/BeyondApi_ProductManagement_Image/_upload/uploads_an_image.yml b/spec/vcr_cassettes/BeyondApi_ProductManagement_Image/_upload/uploads_an_image.yml new file mode 100644 index 0000000..142cb3d --- /dev/null +++ b/spec/vcr_cassettes/BeyondApi_ProductManagement_Image/_upload/uploads_an_image.yml @@ -0,0 +1,141 @@ +--- +http_interactions: +- request: + method: post + uri: https://team42-beyond-api.beyondshop.cloud/api/oauth/token?grant_type=client_credentials + body: + encoding: UTF-8 + string: "{}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - Faraday v2.10.1 + Authorization: + - Basic + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + response: + status: + code: 200 + message: OK + headers: + Date: + - Fri, 23 Aug 2024 06:24:40 GMT + Content-Type: + - application/json;charset=utf-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Cache-Control: + - no-store + Pragma: + - no-cache + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - 1; mode=block + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + X-Frame-Options: + - DENY + Server: + - epages-beyond + X-Request-Time: + - '0.123' + X-B3-Traceid: + - db6726c24244f7cfd6de9de4d765d463 + X-Hello-Human: + - Come work with us! https://developer.epages.com/devjobs/ + body: + encoding: UTF-8 + string: |- + { + "access_token" : "", + "token_type" : "bearer", + "expires_in" : 3599, + "scope" : "orde:r prat:dcur pypr:cur prod:urdc lcnt:u pymt:ur loca:urcd sctg:m shat:cdru rfpr:ur prad:rcd shpz:dcur shad:u ordr:cur shop:u shim:cd cust:urcd clpr:cr legl:ur prda:ru rtpr:rc oset:ur shpr:rcu cset:ru ordp:r catg:cdur nltg:m", + "tenantId" : 8542, + "iat" : 1724394280, + "jti" : "oFIYaozJNpVa0pp3EiLllp/To1w=" + } + recorded_at: Fri, 23 Aug 2024 06:24:40 GMT +- request: + method: post + uri: https://team42-beyond-api.beyondshop.cloud/api/products/4bf6d53d-dfb2-4468-b6f9-f6e6265bc0bc/images?fileName=new-image.png + body: + encoding: ASCII-8BIT + string: !binary |- + iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQBAMAAABykSv/AAAAG1BMVEUAAAD///8fHx+/v7/f399/f38/Pz+fn59fX1/Ew5I3AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAD1ElEQVR4nO3Zz0/bMBTAcSvQtMeZZj+ObVWhHekO244NYj+OVBqCY4s4cKTadqfTNvFnL/Z7TlI2lihKVjR9PwcaV/GLX+zYbjAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/QzQKR9dnF/mxiX+cfasXYJIfNQzQktlcDz5Za5NTLfTSrPSuTv29JBw1DNCSnp3LwZV9d3eeJiNfiNPk4scXe1wjwCIk0jRAS1aaSGzfZ38HqVx6lSyzv9+1VX8T2yQcNAvQllSH1nQoH75ZUXokH/PK+vtDTaRpgJb0hyu51lruZGTdIO/rnRw/rQywfq2JNA3Qks2xJBLZW/li4YrjF1LoJX+qUzZIDuWcpgFaEtmlJJJf0TfBN6bcugeNn8VSs2mAluw9NZLIfhgDfTfU0zCJro8qAsxONZGmAVqyONJExgf6zcC6+zjS0uZJOLOX1zk1hd7QaCKVAToVZxeURDZz/cq1YZCP7Lx5xa3tD0sBVgchkcoAndrPxrMkssiHQHrr7nPpBDEN362flQJkJ2silQE6tb4JibgjMTs1/eehsJdPn7oymL5dFvXdiZpIZYAu+REgiczykZ+1qLh60aLQJVsd4saTJlIdoENj1yhJJBsPRTuK8VBqh3TJVodErqCJVAfokL+L9xPJBnvRjl7pyfZdstUh/sb/lsiDATojF6mdiOuSrQ6RB/wRJLLyu6Paibgu2eqQ2G+odp9IlC7dR/1EovTNVodMfVa7T2RPnkOdtfJ2uEnngWd1assdYmZ+xg2zVp0A3dC1uO7060q2vHPS5Xvn02/YD9VcEP1JSXmg6O5j5wtiGMc1tyjGdchlWuoSfSp2vkXZJCdemn3e1NrzZVPWtOiSgZX6J9nnh11uGje2cCSLvG9foiu2nDQvKrg1JCq6ZFCqPzR1AnQkmojN8WRS/l3khnfxu+imqODXkFKXaP2XyWQyqhWgY3V/6sqiHpWfEu9x/NQ1IZHqdwe6qE/vr3Dxo3j5YEIiZiFvc2Lfnp6+zVkVc07YZf3WJZpIZYDOaSL7cukrueHyvjAuNXoRHub7XRISqQrQOU0kSj8a9yZY7us0uTXute4oP+1qqQfRx+36IZGqAJ3TRLKN1POzz3Y40lbZr+cz+6pG/ZBI4wBtCYmY725BuNXCwP1X4G2d+nkiTQO07/Du5ygvRNd3l/88AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj9gv2X223KqGyf0AAAAASUVORK5CYII= + headers: + Accept: + - application/json + Content-Type: + - image/png + User-Agent: + - Faraday v2.10.1 + Authorization: + - Bearer + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + response: + status: + code: 201 + message: Created + headers: + Date: + - Fri, 23 Aug 2024 06:24:40 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Location: + - https://team42-beyond-api.beyondshop.cloud/api/products/4bf6d53d-dfb2-4468-b6f9-f6e6265bc0bc/images/9d47a8ee-d2df-4227-acb1-ab1081777615 + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - 1; mode=block + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Pragma: + - no-cache + Expires: + - '0' + X-Frame-Options: + - DENY + Server: + - epages-beyond + X-Request-Time: + - '0.200' + X-B3-Traceid: + - abc4c43d5847237a86d1218306eef756 + X-Hello-Human: + - Come work with us! https://developer.epages.com/devjobs/ + body: + encoding: UTF-8 + string: |- + { + "position" : 0, + "width" : 400, + "height" : 400, + "_id" : "9d47a8ee-d2df-4227-acb1-ab1081777615", + "_links" : { + "self" : { + "href" : "https://team42-beyond-api.beyondshop.cloud/api/products/4bf6d53d-dfb2-4468-b6f9-f6e6265bc0bc/images/9d47a8ee-d2df-4227-acb1-ab1081777615" + }, + "data" : { + "href" : "https://team42-beyond-api.beyondshop.cloud/api/core-storage/images/new-image.png?hash=54386a565cf2d7f563e8dec800be24434918438d{&width,height,upscale}", + "templated" : true + }, + "image" : { + "href" : "https://team42-beyond-api.beyondshop.cloud/api/products/4bf6d53d-dfb2-4468-b6f9-f6e6265bc0bc/images/9d47a8ee-d2df-4227-acb1-ab1081777615" + } + } + } + recorded_at: Fri, 23 Aug 2024 06:24:40 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/vcr_cassettes/BeyondApi_ProductManagement_Image/_upload/uploads_multiple_images.yml b/spec/vcr_cassettes/BeyondApi_ProductManagement_Image/_upload/uploads_multiple_images.yml new file mode 100644 index 0000000..18f1794 --- /dev/null +++ b/spec/vcr_cassettes/BeyondApi_ProductManagement_Image/_upload/uploads_multiple_images.yml @@ -0,0 +1,164 @@ +--- +http_interactions: +- request: + method: post + uri: https://team42-beyond-api.beyondshop.cloud/api/oauth/token?grant_type=client_credentials + body: + encoding: UTF-8 + string: "{}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - Faraday v2.10.1 + Authorization: + - Basic + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + response: + status: + code: 200 + message: OK + headers: + Date: + - Fri, 23 Aug 2024 06:24:40 GMT + Content-Type: + - application/json;charset=utf-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Cache-Control: + - no-store + Pragma: + - no-cache + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - 1; mode=block + Strict-Transport-Security: + - max-age=31536000 ; includeSubDomains + X-Frame-Options: + - DENY + Server: + - epages-beyond + X-Request-Time: + - '0.114' + X-B3-Traceid: + - '09a5df9a5a4b44b7c177246e659cf042' + X-Hello-Human: + - Come work with us! https://developer.epages.com/devjobs/ + body: + encoding: UTF-8 + string: |- + { + "access_token" : "", + "token_type" : "bearer", + "expires_in" : 3599, + "scope" : "orde:r prat:dcur pypr:cur prod:urdc lcnt:u pymt:ur loca:urcd sctg:m shat:cdru rfpr:ur prad:rcd shpz:dcur shad:u ordr:cur shop:u shim:cd cust:urcd clpr:cr legl:ur prda:ru rtpr:rc oset:ur shpr:rcu cset:ru ordp:r catg:cdur nltg:m", + "tenantId" : 8542, + "iat" : 1724394280, + "jti" : "X4uDg1Wy4xZKXylhjIHJQWMRAx0=" + } + recorded_at: Fri, 23 Aug 2024 06:24:40 GMT +- request: + method: post + uri: https://team42-beyond-api.beyondshop.cloud/api/products/4bf6d53d-dfb2-4468-b6f9-f6e6265bc0bc/images?fileName=new-image3.png + body: + encoding: ASCII-8BIT + string: !binary |- + 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 + headers: + Accept: + - application/json + Content-Type: + - multipart/form-data; boundary=-----------RubyMultipartPost-761a9e23f99726c36082e76b34db0ba0 + User-Agent: + - Faraday v2.10.1 + Authorization: + - Bearer + Content-Length: + - '5010' + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + response: + status: + code: 201 + message: Created + headers: + Date: + - Fri, 23 Aug 2024 06:24:40 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Location: + - https://team42-beyond-api.beyondshop.cloud/api/products/4bf6d53d-dfb2-4468-b6f9-f6e6265bc0bc/images + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - 1; mode=block + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Pragma: + - no-cache + Expires: + - '0' + X-Frame-Options: + - DENY + Server: + - epages-beyond + X-Request-Time: + - '0.192' + X-B3-Traceid: + - 4e354363500d84a9d2558ccaa270f669 + X-Hello-Human: + - Come work with us! https://developer.epages.com/devjobs/ + body: + encoding: UTF-8 + string: |- + { + "_embedded" : { + "images" : [ { + "position" : 1, + "width" : 600, + "height" : 400, + "_id" : "c86a1d01-0efa-4af5-ae5e-12a9611f4cdd", + "_links" : { + "self" : { + "href" : "https://team42-beyond-api.beyondshop.cloud/api/products/4bf6d53d-dfb2-4468-b6f9-f6e6265bc0bc/images/c86a1d01-0efa-4af5-ae5e-12a9611f4cdd" + }, + "data" : { + "href" : "https://team42-beyond-api.beyondshop.cloud/api/core-storage/images/new-image2.png?hash=69edee39d8acbbb605eb5116c46c3a2eb6b2429f{&width,height,upscale}", + "templated" : true + }, + "image" : { + "href" : "https://team42-beyond-api.beyondshop.cloud/api/products/4bf6d53d-dfb2-4468-b6f9-f6e6265bc0bc/images/c86a1d01-0efa-4af5-ae5e-12a9611f4cdd" + } + } + }, { + "position" : 2, + "width" : 600, + "height" : 400, + "_id" : "3185b7d0-f27a-482f-85a7-cbbfaa82a114", + "_links" : { + "self" : { + "href" : "https://team42-beyond-api.beyondshop.cloud/api/products/4bf6d53d-dfb2-4468-b6f9-f6e6265bc0bc/images/3185b7d0-f27a-482f-85a7-cbbfaa82a114" + }, + "data" : { + "href" : "https://team42-beyond-api.beyondshop.cloud/api/core-storage/images/new-image3.png?hash=8eceffd9d90ca05a409de389a7c33669167eb423{&width,height,upscale}", + "templated" : true + }, + "image" : { + "href" : "https://team42-beyond-api.beyondshop.cloud/api/products/4bf6d53d-dfb2-4468-b6f9-f6e6265bc0bc/images/3185b7d0-f27a-482f-85a7-cbbfaa82a114" + } + } + } ] + } + } + recorded_at: Fri, 23 Aug 2024 06:24:40 GMT +recorded_with: VCR 6.2.0