From 9fda2131797327a80afd9a06f3769b38aec15d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=99=E6=B0=B4=E5=BF=8D?= <335298362+sensui624@users.noreply.github.com> Date: Tue, 27 Oct 2026 13:46:06 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20README=20/=20CHANGELOG=20=E6=94=B9?= =?UTF-8?q?=E7=82=BA=E7=B9=81=E9=AB=94=E4=B8=AD=E6=96=87=EF=BC=8CCLAUDE.md?= =?UTF-8?q?=20=E5=8A=A0=E5=85=A5=E8=AA=9E=E8=A8=80=E8=A6=8F=E5=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 75 +++++++++++++++--------------- CLAUDE.md | 1 + README.md | 128 +++++++++++++++++++++++++-------------------------- 3 files changed, 104 insertions(+), 100 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f0752c..5ff320d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,153 +1,156 @@ -# Changelog +# 更新紀錄(Changelog) -All notable changes to this project are documented in this file. +本檔記錄此專案所有值得注意的變更。 -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +格式參考 [Keep a Changelog](https://keepachangelog.com/zh-TW/1.1.0/),版本號遵循 [Semantic Versioning](https://semver.org/lang/zh-TW/)。 ## [Unreleased] ### Added -- `CHANGELOG.md`. -- Full `README.md`: overview, requirements, installation, configuration, usage of every API, error handling, development and release flow. -- CLAUDE.md rule: every PR must also update `README.md` and `CHANGELOG.md`. +- 新增 `CHANGELOG.md`。 +- 完整的 `README.md`:概述、環境需求、安裝、設定、每支 API 的用法、錯誤處理、開發與發版流程。 +- CLAUDE.md 規則:每個 PR 都必須同步更新 `README.md` 與 `CHANGELOG.md`;`README.md` 與 `CHANGELOG.md` 一律用繁體中文撰寫。 + +### Changed + +- `README.md`、`CHANGELOG.md` 改以繁體中文(zh-TW)撰寫。 ## [2.1.0] - 2026-10-27 ### Added -- `history_id:` option for `Client#create_orders!` and `Client#create_sales!`: attach a batch to an existing import history on the XDelivery side, so several calls merge into one history. A blank (`nil`, `""`, whitespace) value is treated as absent and surrounding whitespace is stripped. -- `Response::Orders#history_id` (the history the batch was attached to; `nil` on a failed response). -- Support for Ruby 3.3 and 3.4: `required_ruby_version >= 2.7`, explicit `ostruct` dependency and require. -- GitHub Actions test matrix (Ruby 3.1.7, 3.3.12, 3.4.11) and `publish.yml` (RubyGems Trusted Publishing). -- CLAUDE.md release rules. +- `Client#create_orders!` 與 `Client#create_sales!` 新增 `history_id:` 選項:把一批資料附加到 XDelivery 端既有的匯入紀錄,讓多次呼叫合併成同一筆紀錄。空白的值(`nil`、`""`、只有空白字元)視為未提供,前後的空白會被去除。 +- `Response::Orders#history_id`(該批資料所附加的匯入紀錄;response 失敗時為 `nil`)。 +- 支援 Ruby 3.3 與 3.4:`required_ruby_version >= 2.7`,並明確相依與 require `ostruct`。 +- GitHub Actions 測試矩陣(Ruby 3.1.7、3.3.12、3.4.11)與 `publish.yml`(RubyGems Trusted Publishing)。 +- CLAUDE.md 加入發版規則。 ### Changed -- The `rest-client` dependency now requires `>= 2.0` (needed for `RestClient::Exceptions::Timeout`). -- `Rakefile` default task is now `t`. +- `rest-client` 相依版本改為 `>= 2.0`(`RestClient::Exceptions::Timeout` 需要)。 +- `Rakefile` 的預設 task 改為 `t`。 ### Fixed -- Request timeouts (`RestClient::Exceptions::Timeout`) used to be swallowed and surfaced as a confusing `NoMethodError` (`nil.code`). They are now raised as-is. +- 請求逾時(`RestClient::Exceptions::Timeout`)以前會被吞掉,變成令人困惑的 `NoMethodError`(`nil.code`)。現在會原樣 raise。 ## [2.0.3] - 2022-08-04 ### Fixed -- Release fixes after 2.0.0 (2.0.2 was never published to RubyGems). +- 修正 2.0.0 之後的發版問題(2.0.2 從未發佈到 RubyGems)。 ## [2.0.1] - 2022-08-04 ### Fixed -- Release fixes after 2.0.0 (version bump only). +- 修正 2.0.0 之後的發版問題(只有跳版號)。 ## [2.0.0] - 2022-08-04 ### Added -- `Xdelivery.env` / `Xdelivery.env=` and `Xdelivery.production?` / `Xdelivery.test?`. In any environment other than `production` requests go to the staging API (`https://api.staging.xdelivery.io`). -- `API::Base#base_url`, `PRODUCTION_BASE_URL` and `TEST_BASE_URL`. +- 新增 `Xdelivery.env` / `Xdelivery.env=` 與 `Xdelivery.production?` / `Xdelivery.test?`。在 `production` 以外的任何環境,請求都會送到 staging API(`https://api.staging.xdelivery.io`)。 +- 新增 `API::Base#base_url`、`PRODUCTION_BASE_URL` 與 `TEST_BASE_URL`。 ### Removed -- `API::Base::BASE_URL` (replaced by the two constants above). +- 移除 `API::Base::BASE_URL`(由上述兩個常數取代)。 ## [1.0.2] - 2022-05-04 ### Added -- Error handling for HTTP error responses: `Client::NotFound` (404), `Client::InternalServerError` (500), `Client::BadGateway` (502), `Client::ServiceUnavailable` (503), `Client::GatewayTimeout` (504) and `Client::UnknownResponse` (non-JSON or unexpected status). +- HTTP 錯誤回應的處理:`Client::NotFound`(404)、`Client::InternalServerError`(500)、`Client::BadGateway`(502)、`Client::ServiceUnavailable`(503)、`Client::GatewayTimeout`(504)與 `Client::UnknownResponse`(非 JSON 或非預期的 status)。 ## [1.0.1] - 2020-04-22 ### Added -- `Xdelivery.open_timeout`, `Xdelivery.read_timeout` and `Xdelivery.configure`. +- 新增 `Xdelivery.open_timeout`、`Xdelivery.read_timeout` 與 `Xdelivery.configure`。 ## [1.0.0] - 2019-10-21 ### Added -- Shops API: `Client#get_shops!`, and the `shop_id` order / sale column. +- 商店 API:`Client#get_shops!`,以及訂單 / 銷貨的 `shop_id` 欄位。 ### Removed -- Invoice settings API (`Client#get_invoice_settings!`, `API::InvoiceSettings`) and the `invoice_setting_id` invoice column. +- 移除發票設定 API(`Client#get_invoice_settings!`、`API::InvoiceSettings`)與發票的 `invoice_setting_id` 欄位。 ## [0.2.4] - 2019-07-31 ### Added -- `Xdelivery::Callback` to verify XDelivery's callback `check_code`. +- 新增 `Xdelivery::Callback`,用來驗證 XDelivery callback 的 `check_code`。 ## [0.2.3] - 2019-07-30 ### Added -- `merchant_note` (system note) order and sale column. +- 訂單與銷貨新增 `merchant_note`(系統備註)欄位。 ## [0.2.2] - 2019-07-18 ### Added -- `company_title` invoice column. +- 發票新增 `company_title` 欄位。 ## [0.2.1] - 2019-07-17 ### Added -- `invoice_setting_id` in the sales invoice params. +- 銷貨的發票參數新增 `invoice_setting_id`。 ## [0.2.0] - 2019-07-16 ### Added -- Invoice settings API (`Client#get_invoice_settings!`) and the `invoice_setting_id` invoice column (both removed again in 1.0.0). +- 發票設定 API(`Client#get_invoice_settings!`)與發票的 `invoice_setting_id` 欄位(兩者在 1.0.0 又被移除)。 ## [0.1.6] - 2019-06-21 ### Fixed -- Fix in the sales API. +- 修正銷貨 API 的問題。 ## [0.1.5] - 2019-06-20 ### Added -- Sales API (`Client#create_sales!`). +- 銷貨 API(`Client#create_sales!`)。 ## [0.1.4] - 2019-06-13 ### Added -- Invoice items (`items` invoice column). +- 發票品項(發票的 `items` 欄位)。 ## [0.1.3] - 2019-06-12 ### Changed -- Renamed the invoice type column. +- 重新命名發票類型欄位。 ## [0.1.2] - 2019-06-12 ### Added -- Invoice support for orders. +- 訂單支援開立發票。 ## [0.1.1] - 2018-12-21 ### Added -- Product update API (`Client#update_products!`). +- 商品更新 API(`Client#update_products!`)。 ## [0.1.0] - 2018-11-16 ### Added -- Initial release. +- 首次發佈。 [Unreleased]: https://github.com/superlanding/xdelivery-ruby/compare/v2.1.0...HEAD [2.1.0]: https://github.com/superlanding/xdelivery-ruby/releases/tag/v2.1.0 diff --git a/CLAUDE.md b/CLAUDE.md index ddabc00..b2bc103 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -13,6 +13,7 @@ - **每一個 PR 都必須同步更新文件**: - 只要行為、用法、設定、相依套件或支援的 Ruby / Rails 版本有變,就要更新 `README.md`。 - 一律要在 `CHANGELOG.md` 新增一筆條目([Keep a Changelog](https://keepachangelog.com/zh-TW/1.1.0/) 格式,分類用 Added / Changed / Deprecated / Removed / Fixed / Security)。 +- **語言規則**:`README.md` 與 `CHANGELOG.md` 一律用繁體中文(zh-TW,台灣用語)撰寫;程式碼、識別字(class / 方法 / 變數名稱)、指令、檔名與路徑維持英文,不要翻譯。 - `CHANGELOG.md` 的寫法: - 沒有跳版號的 PR:寫在最上方的 `## [Unreleased]` 底下。 - 有跳版號的 PR:把條目寫在新的版本章節 `## [x.y.z] - YYYY-MM-DD`(日期為合併日),並同步更新檔尾的版本比較連結。 diff --git a/README.md b/README.md index f8879fe..1e64fde 100644 --- a/README.md +++ b/README.md @@ -3,17 +3,17 @@ [![Gem Version](https://badge.fury.io/rb/xdelivery.svg)](https://rubygems.org/gems/xdelivery) [![Tests](https://github.com/superlanding/xdelivery-ruby/actions/workflows/test.yml/badge.svg)](https://github.com/superlanding/xdelivery-ruby/actions/workflows/test.yml) -Ruby client for the **XDelivery (火箭快遞)** merchant API: push orders and sales in batches, optionally with an invoice, update product stock figures, list shops, ping the API and verify the callbacks XDelivery sends back to you. +**XDelivery(火箭快遞)** 商家 API 的 Ruby client:可批次拋送訂單與銷貨(可附發票)、更新商品庫存數據、列出商店、ping API,以及驗證 XDelivery 回呼(callback)給你的請求。 -> The gem is published on RubyGems as **`xdelivery`** (the repository and gemspec file are named `xdelivery-ruby`); the Ruby namespace is `Xdelivery`. +> 這個 gem 在 RubyGems 上的名稱是 **`xdelivery`**(repo 與 gemspec 檔名為 `xdelivery-ruby`);Ruby 的 namespace 是 `Xdelivery`。 -## Requirements +## 環境需求 -- Ruby `>= 2.7` (gemspec). CI runs on Ruby **3.1, 3.3 and 3.4** (see [`.github/workflows/test.yml`](.github/workflows/test.yml)). -- No Rails dependency. Runtime dependencies: `rest-client >= 2.0` and `ostruct`. -- A merchant number (`merchant_no`) and access key (`access_key`) issued by XDelivery. +- Ruby `>= 2.7`(gemspec)。CI 會跑 Ruby **3.1、3.3 與 3.4**(見 [`.github/workflows/test.yml`](.github/workflows/test.yml))。 +- 不依賴 Rails。Runtime 相依套件:`rest-client >= 2.0` 與 `ostruct`。 +- 由 XDelivery 核發的商家編號(`merchant_no`)與存取金鑰(`access_key`)。 -## Installation +## 安裝 ```ruby # Gemfile @@ -24,38 +24,38 @@ gem "xdelivery" bundle install ``` -Or `gem install xdelivery`, then `require "xdelivery"`. +或執行 `gem install xdelivery`,再 `require "xdelivery"`。 -## Configuration +## 設定 -All settings are optional; the defaults are shown. +所有設定都是選填的,下面列出的是預設值。 ```ruby # config/initializers/xdelivery.rb Xdelivery.configure do |config| - config.open_timeout = 5 # seconds to open the connection - config.read_timeout = 5 # seconds to wait for the response + config.open_timeout = 5 # 建立連線的等待秒數 + config.read_timeout = 5 # 等待回應的秒數 end -Xdelivery.env = :production # anything other than :production talks to the staging API +Xdelivery.env = :production # 除了 :production 之外,其他值都會連到 staging API ``` -| Environment | Base URL | +| 環境 | Base URL | |-------------|----------| -| `:production` (default) | `https://api.xdelivery.io` | -| any other value, e.g. `:test` | `https://api.staging.xdelivery.io` | +| `:production`(預設) | `https://api.xdelivery.io` | +| 其他任何值,例如 `:test` | `https://api.staging.xdelivery.io` | -## Usage +## 使用方式 -Create a client with your credentials. Every API method is a bang method on the client and returns a response object. +用你的憑證建立 client。每個 API 方法都是 client 上的 bang 方法,並回傳一個 response 物件。 ```ruby client = Xdelivery::Client.new("YOUR_MERCHANT_NO", "YOUR_ACCESS_KEY") ``` -### Create orders +### 建立訂單 -`create_orders!` yields a builder; call `add(order_params, invoice_params = {})` for each order, and the batch is sent when the block returns. +`create_orders!` 會 yield 一個 builder;每筆訂單呼叫一次 `add(order_params, invoice_params = {})`,block 結束時會把整批送出。 ```ruby response = client.create_orders! do |orders| @@ -78,37 +78,37 @@ response = client.create_orders! do |orders| callback_url: "https://example.com/xdelivery/callback", ref_id: 22345 }, - # optional invoice + # 選填:發票 { create_type: "device", device: "email", email: "buyer@example.com", items: [] } ) end -response.status? # => true when the API accepted the request -response.auth? # => false when the credentials were rejected (HTTP 401) -response.history_id # => import history id on XDelivery's side (nil on failure) +response.status? # => API 接受這次請求時為 true +response.auth? # => 憑證被拒絕(HTTP 401)時為 false +response.history_id # => XDelivery 那邊的匯入紀錄 id(失敗時為 nil) response.orders.each do |order| order.order_id - order.valid? # false when order.errors is not empty + order.valid? # order.errors 不是空的時候為 false order.errors # => [] end ``` -Allowed order keys: `order_id provider recipient mobile email store_id store_name address items warehouse_items total_order_amount cash_on_delivery order_created_at note callback_url ref_id tag merchant_note shop_id`. -Allowed invoice keys: `create_type email company_code company_title donate_code device_id device items`. -**Any other key is silently dropped** by `add`. +訂單允許的 key:`order_id provider recipient mobile email store_id store_name address items warehouse_items total_order_amount cash_on_delivery order_created_at note callback_url ref_id tag merchant_note shop_id`。 +發票允許的 key:`create_type email company_code company_title donate_code device_id device items`。 +**其他的 key 會被 `add` 默默丟掉**,不會報錯。 -#### Attach to an existing import history (`history_id`) +#### 附加到既有的匯入紀錄(`history_id`) -Pass `history_id:` to put several calls into the same import history on XDelivery's backend. A blank value (`nil`, `""`, whitespace) is ignored, and surrounding whitespace is stripped. +傳入 `history_id:`,就能讓多次呼叫歸在 XDelivery 後台的同一筆匯入紀錄。空白的值(`nil`、`""`、只有空白字元)會被忽略,前後的空白也會被去除。 ```ruby first = client.create_orders! { |orders| orders.add(order_a) } second = client.create_orders!(history_id: first.history_id) { |orders| orders.add(order_b) } ``` -### Create sales +### 建立銷貨 -Same shape as orders, for sales batches; the builder is `Xdelivery::API::Sales`, `history_id:` is supported, and the response is also a `Response::Orders`. +格式與訂單相同,用於銷貨批次;builder 是 `Xdelivery::API::Sales`,同樣支援 `history_id:`,回傳的也是 `Response::Orders`。 ```ruby response = client.create_sales! do |sales| @@ -116,9 +116,9 @@ response = client.create_sales! do |sales| end ``` -Allowed sale keys: `order_id recipient mobile email address items warehouse_items total_order_amount cash_on_delivery order_created_at note callback_url ref_id tag tracking_code merchant_note shop_id` (invoice keys as for orders). +銷貨允許的 key:`order_id recipient mobile email address items warehouse_items total_order_amount cash_on_delivery order_created_at note callback_url ref_id tag tracking_code merchant_note shop_id`(發票的 key 與訂單相同)。 -### Update products +### 更新商品 ```ruby response = client.update_products! do |products| @@ -127,9 +127,9 @@ end response.status? ``` -Allowed keys: `days_produce qty_day_average qty_week_average qty_month_average qty_owe` (others are dropped). +允許的 key:`days_produce qty_day_average qty_week_average qty_month_average qty_owe`(其他的會被丟掉)。 -### Shops and ping +### 商店與 ping ```ruby shops = client.get_shops! @@ -139,27 +139,27 @@ shops.shops.each { |shop| [shop.id, shop.title, shop.pay2go_merchant_id, shop.de client.ping!.status? ``` -### Verify a callback +### 驗證 callback -XDelivery calls the `callback_url` you gave on an order. `Xdelivery::Callback` checks the signature (`check_code`, a SHA-256 over the sorted parameters plus your merchant number and access key): +XDelivery 會呼叫你在訂單上填的 `callback_url`。`Xdelivery::Callback` 負責檢查簽章(`check_code`,是以排序後的參數加上你的商家編號與存取金鑰所算出的 SHA-256): ```ruby -# e.g. in a Rails controller (params is the callback request's params) +# 例如在 Rails controller 裡(params 是 callback 請求的 params) callback = Xdelivery::Callback.new(merchant_no, access_key, params.to_unsafe_h.symbolize_keys) if callback.valid? - callback.action # e.g. "delivered" - callback.title # e.g. "消費者取貨" + callback.action # 例如 "delivered" + callback.title # 例如 "消費者取貨" callback.desc - callback.provider # e.g. "fami" - callback.created_at # Time (Time.zone.parse when ActiveSupport's Time.zone is available) - # outside Rails, `require "time"` yourself first (the gem only calls Time.parse) + callback.provider # 例如 "fami" + callback.created_at # Time(有 ActiveSupport 的 Time.zone 時會用 Time.zone.parse) + # 在 Rails 以外的環境,請自行先 `require "time"`(這個 gem 只會呼叫 Time.parse) end ``` -### Error handling +### 錯誤處理 -The response object raises when the HTTP status is not `200` or `401`: +當 HTTP status 不是 `200` 或 `401` 時,response 物件會 raise: | HTTP status | Exception | |-------------|-----------| @@ -168,47 +168,47 @@ The response object raises when the HTTP status is not `200` or `401`: | 502 | `Xdelivery::Client::BadGateway` | | 503 | `Xdelivery::Client::ServiceUnavailable` | | 504 | `Xdelivery::Client::GatewayTimeout` | -| any other status, or a body that is not JSON | `Xdelivery::Client::UnknownResponse` | +| 其他任何 status,或 body 不是 JSON | `Xdelivery::Client::UnknownResponse` | -Network timeouts are **not** wrapped: `RestClient::Exceptions::OpenTimeout` / `ReadTimeout` are raised as-is, so rescue them yourself: +網路逾時**不會**被包裝:`RestClient::Exceptions::OpenTimeout` / `ReadTimeout` 會原樣 raise,請自行 rescue: ```ruby begin client.create_orders! { |orders| orders.add(order) } rescue Xdelivery::Client::ServiceUnavailable, RestClient::Exceptions::Timeout - # retry later + # 稍後重試 end ``` -A `401` is not an exception: check `response.auth?`. +`401` 不會 raise exception:請檢查 `response.auth?`。 -## Development +## 開發 ```bash git clone https://github.com/superlanding/xdelivery-ruby.git cd xdelivery-ruby bin/setup -bundle exec rake t # runs spec/**/*_spec.rb with Minitest + WebMock (the default rake task does too) +bundle exec rake t # 以 Minitest + WebMock 執行 spec/**/*_spec.rb(預設的 rake task 也一樣) bin/console ``` -The specs stub HTTP with WebMock; `spec/real_client_spec.rb` (calls against a real server) is commented out. +spec 以 WebMock 模擬 HTTP;`spec/real_client_spec.rb`(對真實伺服器發請求)目前被註解掉了。 -## Releasing +## 發版 -Releases are automated with RubyGems [Trusted Publishing](https://guides.rubygems.org/trusted-publishing/) (no API key in the repo): +發版透過 RubyGems [Trusted Publishing](https://guides.rubygems.org/trusted-publishing/) 自動完成(repo 內不存放 API key): -1. In your PR, bump `Xdelivery::VERSION` in `lib/xdelivery/version.rb` ([Semantic Versioning](https://semver.org/)). -2. Add a matching `## [x.y.z] - YYYY-MM-DD` section to `CHANGELOG.md`. -3. A human reviews and merges the PR into `master` (AI accounts can only open PRs). -4. [`.github/workflows/publish.yml`](.github/workflows/publish.yml) runs on `master`: when the gemspec version is not on rubygems.org yet it runs `rake release` (tags `vX.Y.Z` and publishes). A merge without a version bump publishes nothing. +1. 在你的 PR 裡修改 `lib/xdelivery/version.rb` 的 `Xdelivery::VERSION`(遵循 [Semantic Versioning](https://semver.org/lang/zh-TW/))。 +2. 在 `CHANGELOG.md` 新增對應的 `## [x.y.z] - YYYY-MM-DD` 區塊。 +3. 由真人 review 後合併進 `master`(AI 帳號只能開 PR)。 +4. [`.github/workflows/publish.yml`](.github/workflows/publish.yml) 會在 `master` 上執行:當 gemspec 的版本還沒上 rubygems.org 時,就執行 `rake release`(打 `vX.Y.Z` tag 並發佈)。沒有跳版號的合併不會發佈任何東西。 -Docs/CI-only PRs do not need a version bump. See [CLAUDE.md](CLAUDE.md): every PR must also update `README.md` (when behavior or usage changes) and add an entry to `CHANGELOG.md`. +只改文件 / CI 的 PR 不需要跳版號。請見 [CLAUDE.md](CLAUDE.md):每個 PR 也都必須更新 `README.md`(行為或用法有變時)並在 `CHANGELOG.md` 新增一筆條目。 -## Contributing +## 貢獻 -Bug reports and pull requests are welcome on GitHub at https://github.com/superlanding/xdelivery-ruby. +歡迎到 GitHub 回報問題與提交 pull request:https://github.com/superlanding/xdelivery-ruby。 -## License +## 授權 -The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). +本 gem 以 [MIT License](https://opensource.org/licenses/MIT) 條款開源。