bootpay 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c451a531a23a1a127987e92afb1980687ebd31a484326da574520dc41e78da87
4
- data.tar.gz: 0d0e6b71cd59143809355360bedd0f9f43da13a6a02cf9c9d8952edbecb6c7d0
3
+ metadata.gz: d7343a0e300b71e005a0493321465245bf11217ff32318c16e21be314e242135
4
+ data.tar.gz: 174b93f4bbccfc80cafd7a080194aec18b57db7ca29462999c1e29e5e36d4b09
5
5
  SHA512:
6
- metadata.gz: 0ff9f2a74b66f0644633b605edff8e440ea29546cffba5cf7432597ea5b6ebbf8172cdc1598989b64d48c3bfd5091cbe9cec4f048965ccd032e93328faf5a4f6
7
- data.tar.gz: 9ef546f66306f41e58e8fcaffc5ac1595eab60140056a1552d8a0f7b78ecd27c6c7843803fb1015149d4b86ac98a22d3350be6e1146eccd42514cedf4a146c41
6
+ metadata.gz: aac4dd10f479d96ab72b9acb4f3ad05941ea26258a1f63e89f603a996d2b849183908b2ad9a55fb992db948ba9247effa0be2172c5881aa1a155cbefcc6e5536
7
+ data.tar.gz: dd71f98130bb7548394532df02f42a61f18466664242bdeec701e67f61232fb547abac8634dd1f48a88387d8ffa77a8b33c14d8690809af89bf71c8a809490bb
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ### 3.2.0
2
+
3
+ - 뱅크알람 입금대기 API 5종 추가 — `deposit_accounts` · `deposit_webhook_secret` · `deposit_create` ·
4
+ `deposit_detail` · `deposit_cancel` (`/v1/sdk/deposits`). 가맹점 서버가 입금 전 주문을 등록하면 판매자 폰의
5
+ 입금 알림 중 금액·입금자명이 맞는 것을 뱅크알람이 연결해 입금 웹훅으로 알린다.
6
+ 같은 `merchant_order_id` 로 금액·입금자명·계좌가 같은 재호출은 기존 주문을 돌려주고, 하나라도 다르면 `18110`.
7
+ `deposit_webhook_secret` 은 부를 때마다 비밀값이 바뀌고 원문은 그 응답에서만 온다.
8
+ `deposit_id` 는 가맹점 주문번호 또는 부트페이 주문번호이며 경로 인코딩한다. 웹훅 이벤트 상수
9
+ `BootpayStore::Concern::Deposit::BANK_DEPOSIT_WEBHOOK_EVENT_*`(400~407).
10
+ - 입점사 지급 요청 API 3종 추가 — `payout_create` · `payout_detail` · `payouts` (`/v1/sdk/payouts`).
11
+ 가맹점 지정 금액(`manual`) 정산 쇼핑몰이 입점사·지급액을 정해 지급 원장에 등록하고, 송금은 부트페이 배치가 한다.
12
+ 같은 `merchant_payout_id` 재호출은 처음 항목을 돌려준다. `payouts` 의 응답 `data` 는 항목 배열이다(전체 개수 없음).
13
+ - 위 8개는 전부 supervisor scope 라 `Bootpay-Role: supervisor` 로 보내며, `idempotency_key` 를 안 주면 UUID 를 생성한다.
14
+ nil 인자는 본문·쿼리에서 뺀다(`deposit_create` 의 `notify` 안쪽 포함, `false` 는 유지).
15
+ - `product_create` · `product_update` · `product_delete` · `product_status` 의 `Bootpay-Role` 을 `manager` → `user` 로.
16
+ 서버 스코프가 `user:product_*` 뿐이라 manager 로 보내면 401 `API_ROLE_NOT_SUPPORT(-50)` 였다.
17
+ - `alimtalk_webhook_update` 에 `retry_count` 인자 추가(선택). 웹훅 전달 실패 시 건별 재시도 횟수를
18
+ `1`~`25` 사이로 정한다(기본 `10`). 범위 밖 값을 주면 `11304` 로 거부된다. 생략하면 기존에 저장된
19
+ 값을 그대로 유지하므로 기존 호출은 변화 없이 동작한다.
20
+
1
21
  ### 3.1.0
2
22
 
3
23
  - 커머스 게시판 API 28종 SDK 메서드 추가 — FAQ · 공지사항 · 1:1 문의 · 상품문의(Q&A) · 상품평.
@@ -31,15 +31,18 @@ module BootpayStore::Concern::AlimtalkWebhook
31
31
  # 300 발송 접수(기본 미구독) / 301 전달 성공 / 302 전달 실패 / 303 예약 취소 /
32
32
  # 304 문자(LMS) 대체발송 전환 / 310 검수 승인 / 311 검수 반려 / 320 수신거부 등록(기본 미구독)
33
33
  # events 를 비우면 기본 구독셋(301·302·303·304·310·311)이 적용된다.
34
- def alimtalk_webhook_update(url: nil, events: nil, enabled: nil)
34
+ # retry_count: 건별 재시도 횟수(1~25, 기본 10). 범위 밖이면 11304. 생략하면 기존 값을 유지한다.
35
+ # @date: 26-09-30
36
+ def alimtalk_webhook_update(url: nil, events: nil, enabled: nil, retry_count: nil)
35
37
  request(
36
38
  uri: 'alimtalk/webhook',
37
39
  method: :put,
38
40
  headers: { 'Bootpay-Role' => 'user' },
39
41
  payload: {
40
- url: url,
41
- events: events,
42
- enabled: enabled
42
+ url: url,
43
+ events: events,
44
+ enabled: enabled,
45
+ retry_count: retry_count
43
46
  }.compact
44
47
  )
45
48
  end
@@ -0,0 +1,115 @@
1
+ module BootpayStore::Concern::Deposit
2
+ extend ActiveSupport::Concern
3
+
4
+ # 뱅크알람 입금대기 웹훅 이벤트 (입금 웹훅 본문의 event)
5
+ BANK_DEPOSIT_WEBHOOK_EVENT_RECEIVED = 400 # 입금 알림을 처음 저장했다 (주문 연결 전)
6
+ BANK_DEPOSIT_WEBHOOK_EVENT_MATCHED = 401 # 입금대기 주문 한 건과 연결되어 입금 확인됐다
7
+ BANK_DEPOSIT_WEBHOOK_EVENT_AMBIGUOUS = 402 # 같은 금액의 입금대기 주문이 여럿이라 판매자가 골라야 한다
8
+ BANK_DEPOSIT_WEBHOOK_EVENT_UNMATCHED = 403 # 연결할 입금대기 주문이 없다
9
+ BANK_DEPOSIT_WEBHOOK_EVENT_CONFIRMED_MANUALLY = 404 # 판매자가 관리자에서 직접 입금을 확인했다
10
+ BANK_DEPOSIT_WEBHOOK_EVENT_EXPIRED = 405 # 입금 기한이 지나 닫혔다
11
+ BANK_DEPOSIT_WEBHOOK_EVENT_CANCELLED = 406 # 입금대기 중인 주문을 취소했다
12
+ BANK_DEPOSIT_WEBHOOK_EVENT_REVERTED = 407 # 입금 확인을 되돌려 다시 입금대기로 바꿨다
13
+
14
+ included do
15
+ # 판매자 입금 계좌 목록 (GET /v1/sdk/deposits/accounts) — supervisor 전용
16
+ # @comment_by Claude
17
+ # @date: 26-11-12
18
+ # 첫 계좌가 대표 계좌(primary: true)다.
19
+ def deposit_accounts(idempotency_key: nil)
20
+ request(
21
+ uri: 'sdk/deposits/accounts',
22
+ method: :get,
23
+ headers: {
24
+ 'Idempotency-Key' => idempotency_key.presence || SecureRandom.uuid,
25
+ 'Bootpay-Role' => 'supervisor'
26
+ }
27
+ )
28
+ end
29
+
30
+ # 입금 웹훅 서명 비밀값 발급 (POST /v1/sdk/deposits/webhook_secret) — supervisor 전용
31
+ # @comment_by Claude
32
+ # @date: 26-11-12
33
+ # ⚠️ 원문은 이 응답에서만 오고, 부를 때마다 바뀐다.
34
+ # 웹훅은 X-Bootpay-Signature: sha256=HMAC_SHA256(secret, "{X-Bootpay-Timestamp}.{raw_body}") 로 서명된다.
35
+ def deposit_webhook_secret(idempotency_key: nil)
36
+ request(
37
+ uri: 'sdk/deposits/webhook_secret',
38
+ method: :post,
39
+ headers: {
40
+ 'Idempotency-Key' => idempotency_key.presence || SecureRandom.uuid,
41
+ 'Bootpay-Role' => 'supervisor'
42
+ }
43
+ )
44
+ end
45
+
46
+ # 입금대기 등록 (POST /v1/sdk/deposits) — supervisor 전용
47
+ # @comment_by Claude
48
+ # @date: 26-11-12
49
+ # 같은 merchant_order_id 로 금액·입금자명·계좌가 같은 재호출은 기존 주문을 돌려주고, 하나라도 다르면 18110.
50
+ # webhook_url 을 주려면 deposit_webhook_secret 으로 비밀값을 먼저 발급받아야 한다(18131).
51
+ # notify(구매자 알림톡, 유료): { deposit_guide:, deposit_paid:, link: } — buyer_phone 필수(18134), link 는 https(18135).
52
+ def deposit_create(merchant_order_id:, price:, depositor:, order_name: nil, memo: nil, buyer_name: nil,
53
+ buyer_phone: nil, buyer_email: nil, account_id: nil, webhook_url: nil, notify: nil,
54
+ idempotency_key: nil)
55
+ request(
56
+ uri: 'sdk/deposits',
57
+ method: :post,
58
+ headers: {
59
+ 'Idempotency-Key' => idempotency_key.presence || SecureRandom.uuid,
60
+ 'Bootpay-Role' => 'supervisor'
61
+ },
62
+ payload: {
63
+ merchant_order_id: merchant_order_id,
64
+ price: price,
65
+ depositor: depositor,
66
+ order_name: order_name,
67
+ memo: memo,
68
+ buyer_name: buyer_name,
69
+ buyer_phone: buyer_phone,
70
+ buyer_email: buyer_email,
71
+ account_id: account_id,
72
+ webhook_url: webhook_url,
73
+ notify: notify.is_a?(Hash) ? notify.compact : notify
74
+ }.compact
75
+ )
76
+ end
77
+
78
+ # 입금대기 조회 (GET /v1/sdk/deposits/:id) — supervisor 전용
79
+ # @comment_by Claude
80
+ # @date: 26-11-12
81
+ # deposit_id 는 가맹점 주문번호(merchant_order_id) 또는 부트페이 주문번호. 자유 문자열이라 경로 인코딩한다.
82
+ def deposit_detail(deposit_id:, idempotency_key: nil)
83
+ request(
84
+ uri: "sdk/deposits/#{deposit_path_segment(deposit_id)}",
85
+ method: :get,
86
+ headers: {
87
+ 'Idempotency-Key' => idempotency_key.presence || SecureRandom.uuid,
88
+ 'Bootpay-Role' => 'supervisor'
89
+ }
90
+ )
91
+ end
92
+
93
+ # 입금대기 취소 (DELETE /v1/sdk/deposits/:id) — supervisor 전용
94
+ # @comment_by Claude
95
+ # @date: 26-11-12
96
+ # 이미 닫힌 주문은 그대로 돌려준다. 입금 확인된 주문은 18108.
97
+ def deposit_cancel(deposit_id:, idempotency_key: nil)
98
+ request(
99
+ uri: "sdk/deposits/#{deposit_path_segment(deposit_id)}",
100
+ method: :delete,
101
+ headers: {
102
+ 'Idempotency-Key' => idempotency_key.presence || SecureRandom.uuid,
103
+ 'Bootpay-Role' => 'supervisor'
104
+ }
105
+ )
106
+ end
107
+
108
+ private
109
+
110
+ # 경로 세그먼트 인코딩 — 공백은 %20, / 는 %2F (다른 SDK 와 같은 결과)
111
+ def deposit_path_segment(value)
112
+ URI.encode_www_form_component(value.to_s).gsub('+', '%20')
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,69 @@
1
+ module BootpayStore::Concern::Payout
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ # 입점사 지급 요청 등록 (POST /v1/sdk/payouts) — supervisor 전용
6
+ # @comment_by Claude
7
+ # @date: 26-11-12
8
+ # 가맹점 지정 금액(manual) 정산 쇼핑몰이 입점사와 지급액을 정해 지급 원장에 등록한다. 실제 송금은 부트페이 배치가 한다.
9
+ # 같은 merchant_payout_id 재호출은 처음 만든 항목을 돌려준다(금액·입점사·지급일은 바꿀 수 없다).
10
+ # payout_date: 'YYYY-MM-DD' (미지정시 오늘). 정산 방식이 manual 이 아니면 18360, PG 미등록 입점사는 18378.
11
+ def payout_create(sub_seller_id:, amount:, merchant_payout_id:, order_number: nil, payout_date: nil,
12
+ idempotency_key: nil)
13
+ request(
14
+ uri: 'sdk/payouts',
15
+ method: :post,
16
+ headers: {
17
+ 'Idempotency-Key' => idempotency_key.presence || SecureRandom.uuid,
18
+ 'Bootpay-Role' => 'supervisor'
19
+ },
20
+ payload: {
21
+ sub_seller_id: sub_seller_id,
22
+ amount: amount,
23
+ merchant_payout_id: merchant_payout_id,
24
+ order_number: order_number,
25
+ payout_date: payout_date
26
+ }.compact
27
+ )
28
+ end
29
+
30
+ # 입점사 지급 항목 조회 (GET /v1/sdk/payouts/:id) — supervisor 전용
31
+ # @comment_by Claude
32
+ # @date: 26-11-12
33
+ # payout_id 는 merchant_payout_id 또는 지급 항목 id. 없으면 404 PAYOUT_RESULT_INVALID(18366).
34
+ def payout_detail(payout_id:, idempotency_key: nil)
35
+ request(
36
+ uri: "sdk/payouts/#{URI.encode_www_form_component(payout_id.to_s).gsub('+', '%20')}",
37
+ method: :get,
38
+ headers: {
39
+ 'Idempotency-Key' => idempotency_key.presence || SecureRandom.uuid,
40
+ 'Bootpay-Role' => 'supervisor'
41
+ }
42
+ )
43
+ end
44
+
45
+ # 입점사 지급 목록 (GET /v1/sdk/payouts) — supervisor 전용
46
+ # @comment_by Claude
47
+ # @date: 26-11-12
48
+ # 최근 생성 순. 응답 data 는 항목 배열이다(전체 개수 없음 — 받은 수가 limit 보다 적으면 마지막 페이지).
49
+ # status: ready · held · sending · requested · processing · succeeded · failed · cancelled · unknown · void
50
+ def payouts(status: nil, sub_seller_id: nil, from: nil, to: nil, page: nil, limit: nil, idempotency_key: nil)
51
+ request(
52
+ uri: 'sdk/payouts',
53
+ method: :get,
54
+ headers: {
55
+ 'Idempotency-Key' => idempotency_key.presence || SecureRandom.uuid,
56
+ 'Bootpay-Role' => 'supervisor'
57
+ },
58
+ params: {
59
+ status: status,
60
+ sub_seller_id: sub_seller_id,
61
+ from: from,
62
+ to: to,
63
+ page: page,
64
+ limit: limit
65
+ }.compact
66
+ )
67
+ end
68
+ end
69
+ end
@@ -67,6 +67,8 @@ module BootpayStore::Concern::Product
67
67
  # @date: 26-08-14
68
68
  # images 가 있으면 multipart, 없으면 JSON 으로 보낸다.
69
69
  # 컨트롤러가 읽는 필드는 _product_params 참조 — 여기 명시하지 않은 값도 attrs 로 그대로 전달된다.
70
+ # @date: 26-11-02 Bootpay-Role manager → user. 서버 스코프는 user:product_create/update/delete/status 뿐이라
71
+ # manager 로 보내면 manager:product_* 를 찾다 401 API_ROLE_NOT_SUPPORT(-50) 로 막혔다 (수정·삭제·상태변경도 같다)
70
72
  def product_create(name:, display_price: nil, desc: nil, content: nil, category_id: nil,
71
73
  type: nil, stock: nil, status_sale: nil, status_display: nil,
72
74
  use_subscription: nil, subscription_setting_id: nil,
@@ -88,7 +90,7 @@ module BootpayStore::Concern::Product
88
90
 
89
91
  headers = {
90
92
  'Idempotency-Key' => idempotency_key.presence || SecureRandom.uuid,
91
- 'Bootpay-Role' => 'manager'
93
+ 'Bootpay-Role' => 'user'
92
94
  }
93
95
 
94
96
  if images.present?
@@ -104,6 +106,7 @@ module BootpayStore::Concern::Product
104
106
  # @comment_by Claude (alfred)
105
107
  # @date: 26-08-14
106
108
  # 바뀐 값만 보내면 된다. category_id 는 키 존재 여부로 '해제 의사'를 판별하므로 주의.
109
+ # @date: 26-11-02 Bootpay-Role manager → user (product_create 주석 참고)
107
110
  def product_update(product_id:, name: nil, display_price: nil, desc: nil, content: nil,
108
111
  category_id: nil, stock: nil, status_sale: nil, status_display: nil,
109
112
  save_by: nil, idempotency_key: nil, **attrs)
@@ -112,7 +115,7 @@ module BootpayStore::Concern::Product
112
115
  method: :put,
113
116
  headers: {
114
117
  'Idempotency-Key' => idempotency_key.presence || SecureRandom.uuid,
115
- 'Bootpay-Role' => 'manager'
118
+ 'Bootpay-Role' => 'user'
116
119
  },
117
120
  payload: {
118
121
  name: name,
@@ -131,13 +134,14 @@ module BootpayStore::Concern::Product
131
134
  # 상품을 삭제한다 (DELETE /v1/products/:id)
132
135
  # @comment_by Claude (alfred)
133
136
  # @date: 26-08-14
137
+ # @date: 26-11-02 Bootpay-Role manager → user (product_create 주석 참고)
134
138
  def product_delete(product_id:, idempotency_key: nil)
135
139
  request(
136
140
  uri: "products/#{product_id}",
137
141
  method: :delete,
138
142
  headers: {
139
143
  'Idempotency-Key' => idempotency_key.presence || SecureRandom.uuid,
140
- 'Bootpay-Role' => 'manager'
144
+ 'Bootpay-Role' => 'user'
141
145
  }
142
146
  )
143
147
  end
@@ -146,6 +150,7 @@ module BootpayStore::Concern::Product
146
150
  # @comment_by Claude (alfred)
147
151
  # @date: 26-08-14
148
152
  # 컨트롤러 _status_params 기준. 재고(stock)는 여기가 아니라 product_update 로 바꾼다.
153
+ # @date: 26-11-02 Bootpay-Role manager → user (product_create 주석 참고)
149
154
  def product_status(product_id:, status_sale: nil, status_display: nil, status_frozen: nil,
150
155
  status_review: nil, use_display_period: nil, display_start_at: nil, display_end_at: nil,
151
156
  use_sale_period: nil, sale_start_at: nil, sale_end_at: nil,
@@ -155,7 +160,7 @@ module BootpayStore::Concern::Product
155
160
  method: :put,
156
161
  headers: {
157
162
  'Idempotency-Key' => idempotency_key.presence || SecureRandom.uuid,
158
- 'Bootpay-Role' => 'manager'
163
+ 'Bootpay-Role' => 'user'
159
164
  },
160
165
  payload: {
161
166
  status_sale: status_sale,
@@ -7,6 +7,7 @@ module BootpayStore
7
7
  require_relative 'concern/alimtalk_sender'
8
8
  require_relative 'concern/alimtalk_template'
9
9
  require_relative 'concern/alimtalk_webhook'
10
+ require_relative 'concern/deposit'
10
11
  require_relative 'concern/faq'
11
12
  require_relative 'concern/inquiry'
12
13
  require_relative 'concern/invoice'
@@ -15,6 +16,7 @@ module BootpayStore
15
16
  require_relative 'concern/order'
16
17
  require_relative 'concern/order_subscription'
17
18
  require_relative 'concern/payment'
19
+ require_relative 'concern/payout'
18
20
  require_relative 'concern/product'
19
21
  require_relative 'concern/product_qna'
20
22
  require_relative 'concern/product_review'
@@ -33,6 +35,7 @@ module BootpayStore
33
35
  include AlimtalkSender
34
36
  include AlimtalkTemplate
35
37
  include AlimtalkWebhook
38
+ include Deposit
36
39
  include Faq
37
40
  include Inquiry
38
41
  include Invoice
@@ -41,6 +44,7 @@ module BootpayStore
41
44
  include Order
42
45
  include OrderSubscription
43
46
  include Payment
47
+ include Payout
44
48
  include Product
45
49
  include ProductQna
46
50
  include ProductReview
data/lib/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bootpay
4
- VERSION = "3.1.0"
4
+ VERSION = "3.2.0"
5
5
 
6
6
  # 구 이름(`bootpay-backend-ruby`) 시절 gemspec·코드가 참조하던 상수.
7
7
  # 값이 갈리지 않도록 VERSION 을 그대로 가리킨다.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootpay
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gosomi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-09-30 00:00:00.000000000 Z
11
+ date: 2026-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -106,6 +106,7 @@ files:
106
106
  - lib/bootpay_store/concern/alimtalk_sender.rb
107
107
  - lib/bootpay_store/concern/alimtalk_template.rb
108
108
  - lib/bootpay_store/concern/alimtalk_webhook.rb
109
+ - lib/bootpay_store/concern/deposit.rb
109
110
  - lib/bootpay_store/concern/faq.rb
110
111
  - lib/bootpay_store/concern/inquiry.rb
111
112
  - lib/bootpay_store/concern/invoice.rb
@@ -114,6 +115,7 @@ files:
114
115
  - lib/bootpay_store/concern/order.rb
115
116
  - lib/bootpay_store/concern/order_subscription.rb
116
117
  - lib/bootpay_store/concern/payment.rb
118
+ - lib/bootpay_store/concern/payout.rb
117
119
  - lib/bootpay_store/concern/product.rb
118
120
  - lib/bootpay_store/concern/product_qna.rb
119
121
  - lib/bootpay_store/concern/product_review.rb