bootpay-backend 2.9.0__tar.gz → 2.10.0__tar.gz
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.
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/PKG-INFO +86 -1
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/README.md +85 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/__init__.py +28 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/__init__.py +4 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/alimtalk_webhook.py +1 -0
- bootpay_backend-2.10.0/bootpay_backend/commerce/modules/deposit.py +107 -0
- bootpay_backend-2.10.0/bootpay_backend/commerce/modules/payout.py +52 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/product.py +8 -7
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/types/__init__.py +136 -1
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/rest_client.py +1 -1
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend.egg-info/PKG-INFO +86 -1
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend.egg-info/SOURCES.txt +4 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/setup.py +1 -1
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_alimtalk.py +22 -0
- bootpay_backend-2.10.0/tests/commerce/test_deposit.py +150 -0
- bootpay_backend-2.10.0/tests/commerce/test_payout.py +179 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_wire_format.py +16 -6
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/LICENSE +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/__init__.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/bankcode.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/commerce_resource.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/alimtalk_message.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/alimtalk_official.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/alimtalk_optout.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/alimtalk_send.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/alimtalk_sender.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/alimtalk_template.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/cart.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/category.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/coupon.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/faq.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/inquiry.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/invoice.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/mall_setting.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/notice.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/order.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/order_cancel.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/order_subscription.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/order_subscription_adjustment.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/order_subscription_bill.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/order_subscription_request.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/point.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/product_qna.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/product_review.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/store.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/user.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/user_group.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/webhook.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend.egg-info/dependency_links.txt +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend.egg-info/not-zip-safe +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend.egg-info/requires.txt +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend.egg-info/top_level.txt +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/setup.cfg +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/__init__.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/__init__.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_auth_contract.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_board.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_mall_setting.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_order.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_order_subscription_charge.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_product.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_product_mall.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_store.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_token.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_user.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_user_mall.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/commerce/test_webhook.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/conftest.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/pg/__init__.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/pg/test_auth.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/pg/test_billing.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/pg/test_cash_receipt.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/pg/test_cash_receipt_wire_format.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/pg/test_legacy_compatibility.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/pg/test_payment.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/pg/test_sequential_billing_key.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/pg/test_token.py +0 -0
- {bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/tests/pg/test_wallet.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bootpay_backend
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.10.0
|
|
4
4
|
Summary: bootpay server side plugin for python
|
|
5
5
|
Home-page: https://github.com/bootpay/backend-python/tree/2-x-development
|
|
6
6
|
Author: bootpay <bootpay.co.kr@gmail.com>
|
|
@@ -69,6 +69,8 @@ Python 언어로 작성된 어플리케이션, 프레임워크 등에서 사용
|
|
|
69
69
|
- [9-2. 현금영수증 발행 취소](#9-2-현금영수증-발행-취소)
|
|
70
70
|
- [9-3. 별건 현금영수증 발행](#9-3-별건-현금영수증-발행)
|
|
71
71
|
- [9-4. 별건 현금영수증 발행 취소](#9-4-별건-현금영수증-발행-취소)
|
|
72
|
+
- [10. 뱅크알람 입금대기](#10-뱅크알람-입금대기-무통장-입금-자동-확인)
|
|
73
|
+
- [11. 입점사 지급 요청](#11-입점사-지급-요청)
|
|
72
74
|
- [Example 프로젝트](#example-프로젝트)
|
|
73
75
|
- [Documentation](#documentation)
|
|
74
76
|
- [기술문의](#기술문의)
|
|
@@ -440,6 +442,89 @@ if 'error_code' not in token:
|
|
|
440
442
|
print(response)
|
|
441
443
|
```
|
|
442
444
|
|
|
445
|
+
## 10. 뱅크알람 입금대기 (무통장 입금 자동 확인)
|
|
446
|
+
|
|
447
|
+
가맹점 서버가 아직 입금되지 않은 주문을 등록하면, 판매자 폰의 입금 알림 중 **금액 · 입금자명**이 맞는 것을
|
|
448
|
+
뱅크알람이 그 주문에 연결해 입금을 확인하고 입금 웹훅으로 알립니다.
|
|
449
|
+
전부 supervisor 전용이며, 인스턴스 role 과 무관하게 `BOOTPAY-ROLE: supervisor` 로 나갑니다.
|
|
450
|
+
|
|
451
|
+
```python
|
|
452
|
+
import os
|
|
453
|
+
|
|
454
|
+
from bootpay_backend.commerce import BootpayCommerce
|
|
455
|
+
|
|
456
|
+
commerce = BootpayCommerce(
|
|
457
|
+
client_key=os.getenv('BOOTPAY_COMMERCE_CLIENT_KEY_PROD'),
|
|
458
|
+
secret_key=os.getenv('BOOTPAY_COMMERCE_SECRET_KEY_PROD')
|
|
459
|
+
)
|
|
460
|
+
commerce.get_access_token()
|
|
461
|
+
|
|
462
|
+
# 판매자 입금 계좌 목록 — 첫 계좌가 대표 계좌(primary: true)
|
|
463
|
+
accounts = commerce.deposit.accounts()['accounts']
|
|
464
|
+
|
|
465
|
+
# 웹훅 서명 비밀값 발급 — ⚠️ 원문은 이 응답에서만 받습니다. 다시 부르면 바뀝니다
|
|
466
|
+
secret = commerce.deposit.webhook_secret()['secret']
|
|
467
|
+
|
|
468
|
+
# 입금대기 등록 — 같은 merchant_order_id 로 같은 금액·입금자명·계좌를 다시 보내면 기존 주문을 돌려줍니다
|
|
469
|
+
# (하나라도 다르면 18110 BANK_DEPOSIT_MERCHANT_ID_CONFLICT)
|
|
470
|
+
commerce.deposit.create({
|
|
471
|
+
'merchant_order_id': 'ORDER_1234',
|
|
472
|
+
'price': 15000,
|
|
473
|
+
'depositor': '홍길동', # 은행 입금 알림과 맞춰 볼 이름
|
|
474
|
+
'order_name': '티셔츠 외 1건', # 미지정시 '무통장 입금'
|
|
475
|
+
'memo': '관리자 메모',
|
|
476
|
+
'buyer_name': '홍길동', # 미지정시 입금자명
|
|
477
|
+
'buyer_email': 'buyer@example.com', # 주면 입금 안내 · 확인 메일 (무료)
|
|
478
|
+
'account_id': accounts[0]['id'], # 미지정시 대표 계좌
|
|
479
|
+
'webhook_url': 'https://example.com/hooks/deposit', # 비밀값을 먼저 발급받아야 합니다(18131)
|
|
480
|
+
# 구매자 알림톡 (유료) — buyer_phone 필수, link 는 https
|
|
481
|
+
# 'notify': {'deposit_guide': True, 'deposit_paid': True, 'link': 'https://example.com/orders/ORDER_1234'},
|
|
482
|
+
})
|
|
483
|
+
|
|
484
|
+
# 조회 · 취소 — 가맹점 주문번호 또는 부트페이 주문번호
|
|
485
|
+
commerce.deposit.detail('ORDER_1234') # status: awaiting · paid · expired · cancelled
|
|
486
|
+
commerce.deposit.cancel('ORDER_1234') # 이미 닫힌 주문은 그대로 돌려줍니다
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
`webhook_secret(idempotency_key=None)` · `cancel(id, idempotency_key=None)` 은 멱등 키 선택 인자를 받고,
|
|
490
|
+
`create(params)` 는 `params['idempotency_key']` 로 받습니다. 미지정시 호출할 때마다 새 UUID 를 사용합니다.
|
|
491
|
+
|
|
492
|
+
> 입금 웹훅은 `X-Bootpay-Signature: sha256=HMAC_SHA256(secret, "{X-Bootpay-Timestamp}.{raw_body}")` 로 서명됩니다.
|
|
493
|
+
> 이벤트 코드는 `BANK_DEPOSIT_WEBHOOK_EVENT_*` 상수(400~407)를 참고하세요.
|
|
494
|
+
|
|
495
|
+
## 11. 입점사 지급 요청
|
|
496
|
+
|
|
497
|
+
가맹점 지정 금액(`manual`) 정산 방식에서 입점사와 지급액을 정해 지급 원장에 등록합니다.
|
|
498
|
+
실제 송금은 별도 배치가 처리하며, 세 API 모두 인스턴스 role과 무관하게 `BOOTPAY-ROLE: supervisor`로 나갑니다.
|
|
499
|
+
|
|
500
|
+
```python
|
|
501
|
+
from bootpay_backend.commerce import BootpayCommerce
|
|
502
|
+
|
|
503
|
+
commerce = BootpayCommerce(client_key='CLIENT_KEY', secret_key='SECRET_KEY')
|
|
504
|
+
|
|
505
|
+
# 등록 — 같은 merchant_payout_id 재호출은 처음 생성한 항목을 돌려줍니다
|
|
506
|
+
commerce.payout.create({
|
|
507
|
+
'sub_seller_id': 'SUB_SELLER_ID',
|
|
508
|
+
'amount': 150000,
|
|
509
|
+
'merchant_payout_id': 'PAYOUT_20261112_001',
|
|
510
|
+
'order_number': 'ORDER_1234', # 선택
|
|
511
|
+
'payout_date': '2026-11-20', # 선택, YYYY-MM-DD
|
|
512
|
+
})
|
|
513
|
+
|
|
514
|
+
# merchant_payout_id 또는 지급 항목 id로 조회
|
|
515
|
+
commerce.payout.detail('PAYOUT_20261112_001')
|
|
516
|
+
|
|
517
|
+
# 목록은 전체 개수 래퍼 없는 지급 항목 배열입니다
|
|
518
|
+
commerce.payout.list({
|
|
519
|
+
'status': 'ready', 'sub_seller_id': 'SUB_SELLER_ID',
|
|
520
|
+
'from': '2026-11-01', 'to': '2026-11-30', 'page': 1, 'limit': 20,
|
|
521
|
+
})
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
`status`는 `ready` · `held` · `sending` · `requested` · `processing` · `succeeded` · `failed` ·
|
|
525
|
+
`cancelled` · `unknown` · `void` 중 하나입니다. 세 메서드 모두 명시적 `idempotency_key`를 받을 수 있고,
|
|
526
|
+
미지정하면 호출마다 새 UUID를 사용합니다.
|
|
527
|
+
|
|
443
528
|
## Example 프로젝트
|
|
444
529
|
|
|
445
530
|
[적용한 샘플 프로젝트](https://github.com/bootpay/backend-python-example)을 참조해주세요
|
|
@@ -29,6 +29,8 @@ Python 언어로 작성된 어플리케이션, 프레임워크 등에서 사용
|
|
|
29
29
|
- [9-2. 현금영수증 발행 취소](#9-2-현금영수증-발행-취소)
|
|
30
30
|
- [9-3. 별건 현금영수증 발행](#9-3-별건-현금영수증-발행)
|
|
31
31
|
- [9-4. 별건 현금영수증 발행 취소](#9-4-별건-현금영수증-발행-취소)
|
|
32
|
+
- [10. 뱅크알람 입금대기](#10-뱅크알람-입금대기-무통장-입금-자동-확인)
|
|
33
|
+
- [11. 입점사 지급 요청](#11-입점사-지급-요청)
|
|
32
34
|
- [Example 프로젝트](#example-프로젝트)
|
|
33
35
|
- [Documentation](#documentation)
|
|
34
36
|
- [기술문의](#기술문의)
|
|
@@ -400,6 +402,89 @@ if 'error_code' not in token:
|
|
|
400
402
|
print(response)
|
|
401
403
|
```
|
|
402
404
|
|
|
405
|
+
## 10. 뱅크알람 입금대기 (무통장 입금 자동 확인)
|
|
406
|
+
|
|
407
|
+
가맹점 서버가 아직 입금되지 않은 주문을 등록하면, 판매자 폰의 입금 알림 중 **금액 · 입금자명**이 맞는 것을
|
|
408
|
+
뱅크알람이 그 주문에 연결해 입금을 확인하고 입금 웹훅으로 알립니다.
|
|
409
|
+
전부 supervisor 전용이며, 인스턴스 role 과 무관하게 `BOOTPAY-ROLE: supervisor` 로 나갑니다.
|
|
410
|
+
|
|
411
|
+
```python
|
|
412
|
+
import os
|
|
413
|
+
|
|
414
|
+
from bootpay_backend.commerce import BootpayCommerce
|
|
415
|
+
|
|
416
|
+
commerce = BootpayCommerce(
|
|
417
|
+
client_key=os.getenv('BOOTPAY_COMMERCE_CLIENT_KEY_PROD'),
|
|
418
|
+
secret_key=os.getenv('BOOTPAY_COMMERCE_SECRET_KEY_PROD')
|
|
419
|
+
)
|
|
420
|
+
commerce.get_access_token()
|
|
421
|
+
|
|
422
|
+
# 판매자 입금 계좌 목록 — 첫 계좌가 대표 계좌(primary: true)
|
|
423
|
+
accounts = commerce.deposit.accounts()['accounts']
|
|
424
|
+
|
|
425
|
+
# 웹훅 서명 비밀값 발급 — ⚠️ 원문은 이 응답에서만 받습니다. 다시 부르면 바뀝니다
|
|
426
|
+
secret = commerce.deposit.webhook_secret()['secret']
|
|
427
|
+
|
|
428
|
+
# 입금대기 등록 — 같은 merchant_order_id 로 같은 금액·입금자명·계좌를 다시 보내면 기존 주문을 돌려줍니다
|
|
429
|
+
# (하나라도 다르면 18110 BANK_DEPOSIT_MERCHANT_ID_CONFLICT)
|
|
430
|
+
commerce.deposit.create({
|
|
431
|
+
'merchant_order_id': 'ORDER_1234',
|
|
432
|
+
'price': 15000,
|
|
433
|
+
'depositor': '홍길동', # 은행 입금 알림과 맞춰 볼 이름
|
|
434
|
+
'order_name': '티셔츠 외 1건', # 미지정시 '무통장 입금'
|
|
435
|
+
'memo': '관리자 메모',
|
|
436
|
+
'buyer_name': '홍길동', # 미지정시 입금자명
|
|
437
|
+
'buyer_email': 'buyer@example.com', # 주면 입금 안내 · 확인 메일 (무료)
|
|
438
|
+
'account_id': accounts[0]['id'], # 미지정시 대표 계좌
|
|
439
|
+
'webhook_url': 'https://example.com/hooks/deposit', # 비밀값을 먼저 발급받아야 합니다(18131)
|
|
440
|
+
# 구매자 알림톡 (유료) — buyer_phone 필수, link 는 https
|
|
441
|
+
# 'notify': {'deposit_guide': True, 'deposit_paid': True, 'link': 'https://example.com/orders/ORDER_1234'},
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
# 조회 · 취소 — 가맹점 주문번호 또는 부트페이 주문번호
|
|
445
|
+
commerce.deposit.detail('ORDER_1234') # status: awaiting · paid · expired · cancelled
|
|
446
|
+
commerce.deposit.cancel('ORDER_1234') # 이미 닫힌 주문은 그대로 돌려줍니다
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
`webhook_secret(idempotency_key=None)` · `cancel(id, idempotency_key=None)` 은 멱등 키 선택 인자를 받고,
|
|
450
|
+
`create(params)` 는 `params['idempotency_key']` 로 받습니다. 미지정시 호출할 때마다 새 UUID 를 사용합니다.
|
|
451
|
+
|
|
452
|
+
> 입금 웹훅은 `X-Bootpay-Signature: sha256=HMAC_SHA256(secret, "{X-Bootpay-Timestamp}.{raw_body}")` 로 서명됩니다.
|
|
453
|
+
> 이벤트 코드는 `BANK_DEPOSIT_WEBHOOK_EVENT_*` 상수(400~407)를 참고하세요.
|
|
454
|
+
|
|
455
|
+
## 11. 입점사 지급 요청
|
|
456
|
+
|
|
457
|
+
가맹점 지정 금액(`manual`) 정산 방식에서 입점사와 지급액을 정해 지급 원장에 등록합니다.
|
|
458
|
+
실제 송금은 별도 배치가 처리하며, 세 API 모두 인스턴스 role과 무관하게 `BOOTPAY-ROLE: supervisor`로 나갑니다.
|
|
459
|
+
|
|
460
|
+
```python
|
|
461
|
+
from bootpay_backend.commerce import BootpayCommerce
|
|
462
|
+
|
|
463
|
+
commerce = BootpayCommerce(client_key='CLIENT_KEY', secret_key='SECRET_KEY')
|
|
464
|
+
|
|
465
|
+
# 등록 — 같은 merchant_payout_id 재호출은 처음 생성한 항목을 돌려줍니다
|
|
466
|
+
commerce.payout.create({
|
|
467
|
+
'sub_seller_id': 'SUB_SELLER_ID',
|
|
468
|
+
'amount': 150000,
|
|
469
|
+
'merchant_payout_id': 'PAYOUT_20261112_001',
|
|
470
|
+
'order_number': 'ORDER_1234', # 선택
|
|
471
|
+
'payout_date': '2026-11-20', # 선택, YYYY-MM-DD
|
|
472
|
+
})
|
|
473
|
+
|
|
474
|
+
# merchant_payout_id 또는 지급 항목 id로 조회
|
|
475
|
+
commerce.payout.detail('PAYOUT_20261112_001')
|
|
476
|
+
|
|
477
|
+
# 목록은 전체 개수 래퍼 없는 지급 항목 배열입니다
|
|
478
|
+
commerce.payout.list({
|
|
479
|
+
'status': 'ready', 'sub_seller_id': 'SUB_SELLER_ID',
|
|
480
|
+
'from': '2026-11-01', 'to': '2026-11-30', 'page': 1, 'limit': 20,
|
|
481
|
+
})
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
`status`는 `ready` · `held` · `sending` · `requested` · `processing` · `succeeded` · `failed` ·
|
|
485
|
+
`cancelled` · `unknown` · `void` 중 하나입니다. 세 메서드 모두 명시적 `idempotency_key`를 받을 수 있고,
|
|
486
|
+
미지정하면 호출마다 새 UUID를 사용합니다.
|
|
487
|
+
|
|
403
488
|
## Example 프로젝트
|
|
404
489
|
|
|
405
490
|
[적용한 샘플 프로젝트](https://github.com/bootpay/backend-python-example)을 참조해주세요
|
|
@@ -18,6 +18,8 @@ from .modules import (
|
|
|
18
18
|
OrderSubscriptionRequestModule,
|
|
19
19
|
MallSettingModule,
|
|
20
20
|
WebhookModule,
|
|
21
|
+
DepositModule,
|
|
22
|
+
PayoutModule,
|
|
21
23
|
FaqModule,
|
|
22
24
|
NoticeModule,
|
|
23
25
|
InquiryModule,
|
|
@@ -92,6 +94,8 @@ class BootpayCommerce(BootpayCommerceResource):
|
|
|
92
94
|
self.order_subscription_request = OrderSubscriptionRequestModule(self)
|
|
93
95
|
self.mall_setting = MallSettingModule(self)
|
|
94
96
|
self.webhook = WebhookModule(self)
|
|
97
|
+
self.deposit = DepositModule(self)
|
|
98
|
+
self.payout = PayoutModule(self)
|
|
95
99
|
# 게시판 계열 (FAQ·공지사항·1:1문의·상품문의·상품평)
|
|
96
100
|
self.faq = FaqModule(self)
|
|
97
101
|
self.notice = NoticeModule(self)
|
|
@@ -238,6 +242,8 @@ __all__ = [
|
|
|
238
242
|
'OrderSubscriptionRequestModule',
|
|
239
243
|
'MallSettingModule',
|
|
240
244
|
'WebhookModule',
|
|
245
|
+
'DepositModule',
|
|
246
|
+
'PayoutModule',
|
|
241
247
|
'FaqModule',
|
|
242
248
|
'NoticeModule',
|
|
243
249
|
'InquiryModule',
|
|
@@ -347,6 +353,28 @@ __all__ = [
|
|
|
347
353
|
'MallSettingUpdateParams',
|
|
348
354
|
'CommerceMallSetting',
|
|
349
355
|
'SendTestWebhookParams',
|
|
356
|
+
# Deposit Types
|
|
357
|
+
'DepositAccount',
|
|
358
|
+
'DepositAccountsResponse',
|
|
359
|
+
'DepositWebhookSecretResponse',
|
|
360
|
+
'DepositNotifyParams',
|
|
361
|
+
'DepositCreateParams',
|
|
362
|
+
'DepositNotice',
|
|
363
|
+
'DepositNotify',
|
|
364
|
+
'CommerceDeposit',
|
|
365
|
+
'BANK_DEPOSIT_WEBHOOK_EVENT_RECEIVED',
|
|
366
|
+
'BANK_DEPOSIT_WEBHOOK_EVENT_MATCHED',
|
|
367
|
+
'BANK_DEPOSIT_WEBHOOK_EVENT_AMBIGUOUS',
|
|
368
|
+
'BANK_DEPOSIT_WEBHOOK_EVENT_UNMATCHED',
|
|
369
|
+
'BANK_DEPOSIT_WEBHOOK_EVENT_CONFIRMED_MANUALLY',
|
|
370
|
+
'BANK_DEPOSIT_WEBHOOK_EVENT_EXPIRED',
|
|
371
|
+
'BANK_DEPOSIT_WEBHOOK_EVENT_CANCELLED',
|
|
372
|
+
'BANK_DEPOSIT_WEBHOOK_EVENT_REVERTED',
|
|
373
|
+
# Payout Types
|
|
374
|
+
'PayoutStatus',
|
|
375
|
+
'PayoutCreateParams',
|
|
376
|
+
'PayoutListParams',
|
|
377
|
+
'CommercePayout',
|
|
350
378
|
# Alimtalk Types
|
|
351
379
|
'ALIMTALK_WEBHOOK_EVENT_SEND_REQUESTED',
|
|
352
380
|
'ALIMTALK_WEBHOOK_EVENT_SEND_SUCCESS',
|
{bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/__init__.py
RENAMED
|
@@ -16,6 +16,8 @@ from .cart import CartModule
|
|
|
16
16
|
from .order_subscription_request import OrderSubscriptionRequestModule
|
|
17
17
|
from .mall_setting import MallSettingModule
|
|
18
18
|
from .webhook import WebhookModule
|
|
19
|
+
from .deposit import DepositModule
|
|
20
|
+
from .payout import PayoutModule
|
|
19
21
|
from .faq import FaqModule
|
|
20
22
|
from .notice import NoticeModule
|
|
21
23
|
from .inquiry import InquiryModule
|
|
@@ -47,6 +49,8 @@ __all__ = [
|
|
|
47
49
|
'OrderSubscriptionRequestModule',
|
|
48
50
|
'MallSettingModule',
|
|
49
51
|
'WebhookModule',
|
|
52
|
+
'DepositModule',
|
|
53
|
+
'PayoutModule',
|
|
50
54
|
'FaqModule',
|
|
51
55
|
'NoticeModule',
|
|
52
56
|
'InquiryModule',
|
|
@@ -45,6 +45,7 @@ class AlimtalkWebhookModule:
|
|
|
45
45
|
300 발송 접수(기본 미구독) / 301 전달 성공 / 302 전달 실패 / 303 예약 취소 /
|
|
46
46
|
304 문자(LMS) 대체발송 전환 / 310 검수 승인 / 311 검수 반려 / 320 수신거부 등록(기본 미구독)
|
|
47
47
|
events 를 비우면 기본 구독셋(301·302·303·304·310·311)이 적용된다.
|
|
48
|
+
retry_count: 건별 재시도 횟수 (1~25, 기본 10). 범위 밖이면 11304. 생략하면 기존 값을 유지한다 (26-09-30).
|
|
48
49
|
:param params: 웹훅 설정
|
|
49
50
|
:return: 저장된 웹훅 설정
|
|
50
51
|
"""
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
from typing import TYPE_CHECKING, Optional, Dict, Any
|
|
3
|
+
from urllib.parse import quote
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from ..commerce_resource import BootpayCommerceResource
|
|
7
|
+
|
|
8
|
+
from ..types import (
|
|
9
|
+
CommerceDeposit,
|
|
10
|
+
DepositAccountsResponse,
|
|
11
|
+
DepositCreateParams,
|
|
12
|
+
DepositWebhookSecretResponse
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DepositModule:
|
|
17
|
+
"""
|
|
18
|
+
뱅크알람 입금대기 모듈 (/v1/sdk/deposits)
|
|
19
|
+
|
|
20
|
+
판매자 폰의 입금 알림 중 금액·입금자명이 맞는 것을 주문에 연결하고 입금 웹훅으로 알린다.
|
|
21
|
+
인스턴스 role 과 무관하게 모든 요청은 supervisor 전용이다.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, bootpay: 'BootpayCommerceResource'):
|
|
25
|
+
self._bootpay = bootpay
|
|
26
|
+
|
|
27
|
+
def accounts(self) -> DepositAccountsResponse:
|
|
28
|
+
"""
|
|
29
|
+
판매자 입금 계좌 목록
|
|
30
|
+
GET /v1/sdk/deposits/accounts
|
|
31
|
+
첫 계좌가 대표 계좌(primary: True)다.
|
|
32
|
+
:return: {'accounts': List[DepositAccount]}
|
|
33
|
+
"""
|
|
34
|
+
return self._bootpay.get('sdk/deposits/accounts', headers=self._supervisor_headers())
|
|
35
|
+
|
|
36
|
+
def webhook_secret(self, idempotency_key: Optional[str] = None) -> DepositWebhookSecretResponse:
|
|
37
|
+
"""
|
|
38
|
+
웹훅 서명 비밀값 발급
|
|
39
|
+
POST /v1/sdk/deposits/webhook_secret
|
|
40
|
+
⚠️ 원문은 이 응답에서만 준다. 다시 부르면 바뀐다 (기존 웹훅 작업은 이전 비밀값으로 서명된다).
|
|
41
|
+
:param idempotency_key: 미지정시 자동 생성
|
|
42
|
+
:return: {'secret': str}
|
|
43
|
+
"""
|
|
44
|
+
return self._bootpay.post(
|
|
45
|
+
'sdk/deposits/webhook_secret', {},
|
|
46
|
+
headers=self._supervisor_headers(idempotency_key)
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
def create(self, params: DepositCreateParams) -> CommerceDeposit:
|
|
50
|
+
"""
|
|
51
|
+
입금대기 등록
|
|
52
|
+
POST /v1/sdk/deposits
|
|
53
|
+
같은 merchant_order_id 재호출은 기존 주문을 반환한다 (금액·입금자명·계좌가 다르면 18110).
|
|
54
|
+
webhook_url 을 주려면 webhook_secret() 으로 비밀값을 먼저 발급받아야 한다 (18131).
|
|
55
|
+
notify 는 유료 알림톡이며, 준비가 안 됐으면 주문을 만들지 않는다 (18133).
|
|
56
|
+
:param params: merchant_order_id · price · depositor 필수, idempotency_key 선택
|
|
57
|
+
:return: CommerceDeposit
|
|
58
|
+
"""
|
|
59
|
+
payload = self._compact({k: v for k, v in params.items() if k != 'idempotency_key'})
|
|
60
|
+
if payload.get('notify') is not None:
|
|
61
|
+
payload['notify'] = self._compact(payload['notify'])
|
|
62
|
+
return self._bootpay.post(
|
|
63
|
+
'sdk/deposits', payload,
|
|
64
|
+
headers=self._supervisor_headers(params.get('idempotency_key'))
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
def detail(self, deposit_id: str) -> CommerceDeposit:
|
|
68
|
+
"""
|
|
69
|
+
입금대기 조회
|
|
70
|
+
GET /v1/sdk/deposits/{id}
|
|
71
|
+
기한이 지났으면 조회 시점에 만료(expired)로 닫힌다.
|
|
72
|
+
:param deposit_id: 가맹점 주문번호 또는 부트페이 주문번호
|
|
73
|
+
:return: CommerceDeposit
|
|
74
|
+
"""
|
|
75
|
+
if not deposit_id:
|
|
76
|
+
raise ValueError('deposit_id is required')
|
|
77
|
+
return self._bootpay.get(
|
|
78
|
+
f'sdk/deposits/{quote(deposit_id, safe="")}',
|
|
79
|
+
headers=self._supervisor_headers()
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def cancel(self, deposit_id: str, idempotency_key: Optional[str] = None) -> CommerceDeposit:
|
|
83
|
+
"""
|
|
84
|
+
입금대기 취소
|
|
85
|
+
DELETE /v1/sdk/deposits/{id}
|
|
86
|
+
기한이 지났으면 만료로 닫고, 이미 닫힌 주문은 그대로 반환한다. 입금 확인된 주문은 18108.
|
|
87
|
+
:param deposit_id: 가맹점 주문번호 또는 부트페이 주문번호
|
|
88
|
+
:param idempotency_key: 미지정시 자동 생성
|
|
89
|
+
:return: CommerceDeposit
|
|
90
|
+
"""
|
|
91
|
+
if not deposit_id:
|
|
92
|
+
raise ValueError('deposit_id is required')
|
|
93
|
+
return self._bootpay.delete(
|
|
94
|
+
f'sdk/deposits/{quote(deposit_id, safe="")}',
|
|
95
|
+
headers=self._supervisor_headers(idempotency_key)
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def _compact(self, payload: Dict[str, Any]) -> Dict[str, Any]:
|
|
99
|
+
"""None 값을 제거한다 (False 는 남긴다)."""
|
|
100
|
+
return {k: v for k, v in payload.items() if v is not None}
|
|
101
|
+
|
|
102
|
+
def _supervisor_headers(self, idempotency_key: Optional[str] = None) -> Dict[str, str]:
|
|
103
|
+
"""요청별 supervisor 헤더와 멱등키 (미지정시 매 호출마다 UUID 생성)."""
|
|
104
|
+
return {
|
|
105
|
+
'Idempotency-Key': idempotency_key or str(uuid.uuid4()),
|
|
106
|
+
'BOOTPAY-ROLE': 'supervisor'
|
|
107
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
from typing import TYPE_CHECKING, Optional, Dict, Any, List
|
|
3
|
+
from urllib.parse import quote
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from ..commerce_resource import BootpayCommerceResource
|
|
7
|
+
|
|
8
|
+
from ..types import CommercePayout, PayoutCreateParams, PayoutListParams
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PayoutModule:
|
|
12
|
+
"""입점사 지급 요청 모듈 (/v1/sdk/payouts)."""
|
|
13
|
+
|
|
14
|
+
def __init__(self, bootpay: 'BootpayCommerceResource'):
|
|
15
|
+
self._bootpay = bootpay
|
|
16
|
+
|
|
17
|
+
def create(self, params: PayoutCreateParams) -> CommercePayout:
|
|
18
|
+
"""입점사와 지급액을 지정해 지급 원장에 등록한다."""
|
|
19
|
+
payload = self._compact({k: v for k, v in params.items() if k != 'idempotency_key'})
|
|
20
|
+
return self._bootpay.post(
|
|
21
|
+
'sdk/payouts', payload,
|
|
22
|
+
headers=self._supervisor_headers(params.get('idempotency_key'))
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
def detail(self, payout_id: str, idempotency_key: Optional[str] = None) -> CommercePayout:
|
|
26
|
+
"""merchant_payout_id 또는 지급 항목 id로 한 건을 조회한다."""
|
|
27
|
+
if not payout_id:
|
|
28
|
+
raise ValueError('payout_id is required')
|
|
29
|
+
return self._bootpay.get(
|
|
30
|
+
f'sdk/payouts/{quote(payout_id, safe="")}',
|
|
31
|
+
headers=self._supervisor_headers(idempotency_key)
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def list(self, params: Optional[PayoutListParams] = None) -> List[CommercePayout]:
|
|
35
|
+
"""현재 프로젝트의 지급 항목 배열을 최근 생성 순으로 조회한다."""
|
|
36
|
+
request_params = params or {}
|
|
37
|
+
query = self._compact({k: v for k, v in request_params.items() if k != 'idempotency_key'})
|
|
38
|
+
return self._bootpay.get(
|
|
39
|
+
'sdk/payouts', params=query,
|
|
40
|
+
headers=self._supervisor_headers(request_params.get('idempotency_key'))
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def _compact(self, payload: Dict[str, Any]) -> Dict[str, Any]:
|
|
44
|
+
"""None 값을 제거한다 (0과 빈 문자열은 호출자가 보낸 값으로 유지한다)."""
|
|
45
|
+
return {k: v for k, v in payload.items() if v is not None}
|
|
46
|
+
|
|
47
|
+
def _supervisor_headers(self, idempotency_key: Optional[str] = None) -> Dict[str, str]:
|
|
48
|
+
"""요청별 supervisor 헤더와 멱등키 (미지정시 매 호출마다 UUID 생성)."""
|
|
49
|
+
return {
|
|
50
|
+
'Idempotency-Key': idempotency_key or str(uuid.uuid4()),
|
|
51
|
+
'BOOTPAY-ROLE': 'supervisor'
|
|
52
|
+
}
|
{bootpay_backend-2.9.0 → bootpay_backend-2.10.0}/bootpay_backend/commerce/modules/product.py
RENAMED
|
@@ -116,7 +116,7 @@ class ProductModule:
|
|
|
116
116
|
:return: CommerceProduct
|
|
117
117
|
"""
|
|
118
118
|
payload = self._compact(product)
|
|
119
|
-
headers = self.
|
|
119
|
+
headers = self._write_headers(idempotency_key)
|
|
120
120
|
|
|
121
121
|
if not image_paths:
|
|
122
122
|
return self._bootpay.post('products', payload, headers=headers)
|
|
@@ -173,7 +173,7 @@ class ProductModule:
|
|
|
173
173
|
return self._bootpay.put(
|
|
174
174
|
f'products/{product["product_id"]}',
|
|
175
175
|
self._compact(product),
|
|
176
|
-
headers=self.
|
|
176
|
+
headers=self._write_headers(idempotency_key)
|
|
177
177
|
)
|
|
178
178
|
|
|
179
179
|
def status(self, params: ProductStatusParams):
|
|
@@ -192,7 +192,7 @@ class ProductModule:
|
|
|
192
192
|
return self._bootpay.put(
|
|
193
193
|
f'products/{product_id}/status',
|
|
194
194
|
self._compact(params),
|
|
195
|
-
headers=self.
|
|
195
|
+
headers=self._write_headers(idempotency_key)
|
|
196
196
|
)
|
|
197
197
|
|
|
198
198
|
def delete(self, product_id: str, idempotency_key: Optional[str] = None):
|
|
@@ -205,21 +205,22 @@ class ProductModule:
|
|
|
205
205
|
"""
|
|
206
206
|
return self._bootpay.delete(
|
|
207
207
|
f'products/{product_id}',
|
|
208
|
-
headers=self.
|
|
208
|
+
headers=self._write_headers(idempotency_key)
|
|
209
209
|
)
|
|
210
210
|
|
|
211
211
|
def _compact(self, payload: Dict[str, Any]) -> Dict[str, Any]:
|
|
212
212
|
"""None 값을 제거한다."""
|
|
213
213
|
return {k: v for k, v in dict(payload or {}).items() if v is not None}
|
|
214
214
|
|
|
215
|
-
def
|
|
215
|
+
def _write_headers(self, idempotency_key: Optional[str] = None) -> Dict[str, str]:
|
|
216
216
|
"""
|
|
217
217
|
상품 쓰기(등록/수정/삭제/상태변경) 요청 헤더
|
|
218
|
-
|
|
218
|
+
서버 스코프는 user:product_create/update/delete/status 뿐이라 BOOTPAY-ROLE 은 user 로 보낸다.
|
|
219
|
+
manager 로 보내면 manager:product_* 를 찾다 401 API_ROLE_NOT_SUPPORT(-50) 로 막힌다.
|
|
219
220
|
"""
|
|
220
221
|
return {
|
|
221
222
|
'Idempotency-Key': idempotency_key or str(uuid.uuid4()),
|
|
222
|
-
'BOOTPAY-ROLE': '
|
|
223
|
+
'BOOTPAY-ROLE': 'user'
|
|
223
224
|
}
|
|
224
225
|
|
|
225
226
|
def _mall_headers(self, user_jwt: Optional[str] = None, idempotency_key: Optional[str] = None) -> Dict[str, str]:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Commerce API Types
|
|
2
|
-
from typing import TypedDict, Optional, List, Any, Dict
|
|
2
|
+
from typing import TypedDict, Optional, List, Any, Dict, Literal
|
|
3
3
|
|
|
4
4
|
# Common Types
|
|
5
5
|
class ListParams(TypedDict, total=False):
|
|
@@ -1688,6 +1688,8 @@ class AlimtalkWebhookUpdateParams(TypedDict, total=False):
|
|
|
1688
1688
|
# 목록에 없는 값은 저장 시 조용히 버려진다. 비우면 기본 구독셋(301·302·303·304·310·311).
|
|
1689
1689
|
events: List[int]
|
|
1690
1690
|
enabled: bool
|
|
1691
|
+
# 건별 재시도 횟수(1~25, 기본 10). 범위 밖이면 11304. 생략하면 기존 값을 유지한다(26-09-30)
|
|
1692
|
+
retry_count: int
|
|
1691
1693
|
|
|
1692
1694
|
|
|
1693
1695
|
class AlimtalkWebhookDeliveryListParams(TypedDict, total=False):
|
|
@@ -1695,3 +1697,136 @@ class AlimtalkWebhookDeliveryListParams(TypedDict, total=False):
|
|
|
1695
1697
|
page: int
|
|
1696
1698
|
# 서버 기본 20, 최대 100
|
|
1697
1699
|
limit: int
|
|
1700
|
+
|
|
1701
|
+
|
|
1702
|
+
# Bank Deposit Types (/v1/sdk/deposits)
|
|
1703
|
+
BANK_DEPOSIT_WEBHOOK_EVENT_RECEIVED = 400
|
|
1704
|
+
BANK_DEPOSIT_WEBHOOK_EVENT_MATCHED = 401
|
|
1705
|
+
BANK_DEPOSIT_WEBHOOK_EVENT_AMBIGUOUS = 402
|
|
1706
|
+
BANK_DEPOSIT_WEBHOOK_EVENT_UNMATCHED = 403
|
|
1707
|
+
BANK_DEPOSIT_WEBHOOK_EVENT_CONFIRMED_MANUALLY = 404
|
|
1708
|
+
BANK_DEPOSIT_WEBHOOK_EVENT_EXPIRED = 405
|
|
1709
|
+
BANK_DEPOSIT_WEBHOOK_EVENT_CANCELLED = 406
|
|
1710
|
+
BANK_DEPOSIT_WEBHOOK_EVENT_REVERTED = 407
|
|
1711
|
+
|
|
1712
|
+
|
|
1713
|
+
class DepositAccount(TypedDict, total=False):
|
|
1714
|
+
id: str
|
|
1715
|
+
bank_name: str
|
|
1716
|
+
account_no: str
|
|
1717
|
+
holder: str
|
|
1718
|
+
# 대표 계좌 여부 — 계좌 목록 응답에만 실린다
|
|
1719
|
+
primary: bool
|
|
1720
|
+
|
|
1721
|
+
|
|
1722
|
+
class DepositAccountsResponse(TypedDict, total=False):
|
|
1723
|
+
accounts: List[DepositAccount]
|
|
1724
|
+
|
|
1725
|
+
|
|
1726
|
+
class DepositWebhookSecretResponse(TypedDict, total=False):
|
|
1727
|
+
# 원문은 발급 응답에서만 받는다. 다시 발급하면 바뀐다.
|
|
1728
|
+
secret: str
|
|
1729
|
+
|
|
1730
|
+
|
|
1731
|
+
class DepositNotify(TypedDict, total=False):
|
|
1732
|
+
deposit_guide: bool
|
|
1733
|
+
deposit_paid: bool
|
|
1734
|
+
|
|
1735
|
+
|
|
1736
|
+
class DepositNotifyParams(DepositNotify, total=False):
|
|
1737
|
+
# 하나라도 True 면 buyer_phone 필수(18134), link 는 https · 500자 이하(18135)
|
|
1738
|
+
link: str
|
|
1739
|
+
|
|
1740
|
+
|
|
1741
|
+
class _DepositCreateRequired(TypedDict):
|
|
1742
|
+
merchant_order_id: str
|
|
1743
|
+
price: float
|
|
1744
|
+
depositor: str
|
|
1745
|
+
|
|
1746
|
+
|
|
1747
|
+
class DepositCreateParams(_DepositCreateRequired, total=False):
|
|
1748
|
+
order_name: str
|
|
1749
|
+
memo: str
|
|
1750
|
+
# 미지정시 입금자명
|
|
1751
|
+
buyer_name: str
|
|
1752
|
+
buyer_phone: str
|
|
1753
|
+
# 입금 안내·확인 메일 (무료). 잘못된 형식은 18136
|
|
1754
|
+
buyer_email: str
|
|
1755
|
+
# accounts() 의 id — 미지정시 대표 계좌
|
|
1756
|
+
account_id: str
|
|
1757
|
+
# 먼저 webhook_secret() 으로 서명 비밀값을 발급받아야 한다 (18131)
|
|
1758
|
+
webhook_url: str
|
|
1759
|
+
notify: DepositNotifyParams
|
|
1760
|
+
idempotency_key: str
|
|
1761
|
+
|
|
1762
|
+
|
|
1763
|
+
class DepositNotice(TypedDict, total=False):
|
|
1764
|
+
# 주문에 연결된 입금 알림 — 웹훅 본문에만 실린다
|
|
1765
|
+
key: str
|
|
1766
|
+
bank_name: str
|
|
1767
|
+
account_tail: str
|
|
1768
|
+
depositor: str
|
|
1769
|
+
amount: float
|
|
1770
|
+
received_at: Optional[str]
|
|
1771
|
+
|
|
1772
|
+
|
|
1773
|
+
class CommerceDeposit(TypedDict, total=False):
|
|
1774
|
+
merchant_order_id: str
|
|
1775
|
+
order_number: str
|
|
1776
|
+
order_name: str
|
|
1777
|
+
amount: float
|
|
1778
|
+
status: Literal['awaiting', 'paid', 'expired', 'cancelled']
|
|
1779
|
+
buyer_name: str
|
|
1780
|
+
depositor: str
|
|
1781
|
+
account: Optional[DepositAccount]
|
|
1782
|
+
deadline: Optional[str]
|
|
1783
|
+
deadline_label: Optional[str]
|
|
1784
|
+
paid_at: Optional[str]
|
|
1785
|
+
notify: Optional[DepositNotify]
|
|
1786
|
+
deposit: Optional[DepositNotice]
|
|
1787
|
+
|
|
1788
|
+
|
|
1789
|
+
# Payout Types (/v1/sdk/payouts)
|
|
1790
|
+
PayoutStatus = Literal[
|
|
1791
|
+
'ready', 'held', 'sending', 'requested', 'processing',
|
|
1792
|
+
'succeeded', 'failed', 'cancelled', 'unknown', 'void'
|
|
1793
|
+
]
|
|
1794
|
+
|
|
1795
|
+
|
|
1796
|
+
class _PayoutCreateRequired(TypedDict):
|
|
1797
|
+
sub_seller_id: str
|
|
1798
|
+
amount: int
|
|
1799
|
+
merchant_payout_id: str
|
|
1800
|
+
|
|
1801
|
+
|
|
1802
|
+
class PayoutCreateParams(_PayoutCreateRequired, total=False):
|
|
1803
|
+
order_number: str
|
|
1804
|
+
# 지급 예정일 YYYY-MM-DD (미지정시 서버 기준 오늘)
|
|
1805
|
+
payout_date: str
|
|
1806
|
+
idempotency_key: str
|
|
1807
|
+
|
|
1808
|
+
|
|
1809
|
+
PayoutListParams = TypedDict('PayoutListParams', {
|
|
1810
|
+
'status': PayoutStatus,
|
|
1811
|
+
'sub_seller_id': str,
|
|
1812
|
+
# 지급 예정일 범위 YYYY-MM-DD (포함)
|
|
1813
|
+
'from': str,
|
|
1814
|
+
'to': str,
|
|
1815
|
+
'page': int,
|
|
1816
|
+
'limit': int,
|
|
1817
|
+
'idempotency_key': str,
|
|
1818
|
+
}, total=False)
|
|
1819
|
+
|
|
1820
|
+
|
|
1821
|
+
class CommercePayout(TypedDict, total=False):
|
|
1822
|
+
id: str
|
|
1823
|
+
merchant_payout_id: str
|
|
1824
|
+
sub_seller_id: str
|
|
1825
|
+
amount: int
|
|
1826
|
+
status: PayoutStatus
|
|
1827
|
+
payout_date: str
|
|
1828
|
+
order_number: Optional[str]
|
|
1829
|
+
last_code: Optional[str]
|
|
1830
|
+
last_message: Optional[str]
|
|
1831
|
+
created_at: str
|
|
1832
|
+
updated_at: str
|
|
@@ -11,7 +11,7 @@ class BootpayBackend:
|
|
|
11
11
|
'production': 'https://api.bootpay.co.kr/v2'
|
|
12
12
|
}
|
|
13
13
|
API_VERSION = '5.1.0'
|
|
14
|
-
SDK_VERSION = '2.
|
|
14
|
+
SDK_VERSION = '2.10.0'
|
|
15
15
|
|
|
16
16
|
def __init__(self, application_id=None, private_key=None, mode='production', client_key=None, secret_key=None):
|
|
17
17
|
# application_id/private_key는 legacy 사용자를 위해 그대로 지원한다.
|