@hanzo/commerce 7.5.1 → 7.6.1
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.
- package/client.ts +462 -64
- package/components/checkout/payment-step-form/index.tsx +3 -16
- package/index.ts +25 -2
- package/package.json +9 -12
- package/.turbo/turbo-build.log +0 -5
- package/LICENSE.md +0 -21
- package/dist/billing.d.ts +0 -2
- package/dist/billing.js +0 -3
- package/dist/billing.js.map +0 -1
- package/dist/client.d.ts +0 -151
- package/dist/client.js +0 -188
- package/dist/client.js.map +0 -1
- package/dist/components/Icons.d.ts +0 -18
- package/dist/components/Icons.js +0 -19
- package/dist/components/Icons.js.map +0 -1
- package/dist/components/Icons.jsx +0 -19
- package/dist/components/Icons.jsx.map +0 -1
- package/dist/components/add-to-cart-widget.d.ts +0 -11
- package/dist/components/add-to-cart-widget.js +0 -85
- package/dist/components/add-to-cart-widget.js.map +0 -1
- package/dist/components/add-to-cart-widget.jsx +0 -99
- package/dist/components/add-to-cart-widget.jsx.map +0 -1
- package/dist/components/buy/buy-card.d.ts +0 -30
- package/dist/components/buy/buy-card.js +0 -109
- package/dist/components/buy/buy-card.js.map +0 -1
- package/dist/components/buy/buy-card.jsx +0 -123
- package/dist/components/buy/buy-card.jsx.map +0 -1
- package/dist/components/buy/carousel-buy-card.d.ts +0 -12
- package/dist/components/buy/carousel-buy-card.js +0 -94
- package/dist/components/buy/carousel-buy-card.js.map +0 -1
- package/dist/components/buy/carousel-buy-card.jsx +0 -99
- package/dist/components/buy/carousel-buy-card.jsx.map +0 -1
- package/dist/components/buy/multi-family/all-variants-carousel.d.ts +0 -4
- package/dist/components/buy/multi-family/all-variants-carousel.js +0 -115
- package/dist/components/buy/multi-family/all-variants-carousel.js.map +0 -1
- package/dist/components/buy/multi-family/all-variants-carousel.jsx +0 -147
- package/dist/components/buy/multi-family/all-variants-carousel.jsx.map +0 -1
- package/dist/components/buy/multi-family/family-carousel/index.d.ts +0 -4
- package/dist/components/buy/multi-family/family-carousel/index.js +0 -27
- package/dist/components/buy/multi-family/family-carousel/index.js.map +0 -1
- package/dist/components/buy/multi-family/family-carousel/index.jsx +0 -34
- package/dist/components/buy/multi-family/family-carousel/index.jsx.map +0 -1
- package/dist/components/buy/multi-family/family-carousel/slide.d.ts +0 -11
- package/dist/components/buy/multi-family/family-carousel/slide.js +0 -35
- package/dist/components/buy/multi-family/family-carousel/slide.js.map +0 -1
- package/dist/components/buy/multi-family/family-carousel/slide.jsx +0 -41
- package/dist/components/buy/multi-family/family-carousel/slide.jsx.map +0 -1
- package/dist/components/buy/multi-family/family-carousel/state.d.ts +0 -20
- package/dist/components/buy/multi-family/family-carousel/state.js +0 -59
- package/dist/components/buy/multi-family/family-carousel/state.js.map +0 -1
- package/dist/components/buy/multi-family/index.d.ts +0 -2
- package/dist/components/buy/multi-family/index.js +0 -3
- package/dist/components/buy/multi-family/index.js.map +0 -1
- package/dist/components/buy/single-family-selector.d.ts +0 -15
- package/dist/components/buy/single-family-selector.js +0 -28
- package/dist/components/buy/single-family-selector.js.map +0 -1
- package/dist/components/buy/single-family-selector.jsx +0 -31
- package/dist/components/buy/single-family-selector.jsx.map +0 -1
- package/dist/components/buy/title-and-byline.d.ts +0 -8
- package/dist/components/buy/title-and-byline.js +0 -7
- package/dist/components/buy/title-and-byline.js.map +0 -1
- package/dist/components/buy/title-and-byline.jsx +0 -9
- package/dist/components/buy/title-and-byline.jsx.map +0 -1
- package/dist/components/cart/cart-panel/cart-line-item.d.ts +0 -11
- package/dist/components/cart/cart-panel/cart-line-item.js +0 -25
- package/dist/components/cart/cart-panel/cart-line-item.js.map +0 -1
- package/dist/components/cart/cart-panel/cart-line-item.jsx +0 -39
- package/dist/components/cart/cart-panel/cart-line-item.jsx.map +0 -1
- package/dist/components/cart/cart-panel/index.d.ts +0 -19
- package/dist/components/cart/cart-panel/index.js +0 -65
- package/dist/components/cart/cart-panel/index.js.map +0 -1
- package/dist/components/cart/cart-panel/index.jsx +0 -79
- package/dist/components/cart/cart-panel/index.jsx.map +0 -1
- package/dist/components/cart/cart-panel/promo-code.d.ts +0 -4
- package/dist/components/cart/cart-panel/promo-code.js +0 -62
- package/dist/components/cart/cart-panel/promo-code.js.map +0 -1
- package/dist/components/cart/cart-panel/promo-code.jsx +0 -74
- package/dist/components/cart/cart-panel/promo-code.jsx.map +0 -1
- package/dist/components/cart/cart-panel/total-area.d.ts +0 -7
- package/dist/components/cart/cart-panel/total-area.js +0 -14
- package/dist/components/cart/cart-panel/total-area.js.map +0 -1
- package/dist/components/cart/cart-panel/total-area.jsx +0 -37
- package/dist/components/cart/cart-panel/total-area.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icon-row.d.ts +0 -2
- package/dist/components/checkout/payment-step-form/card-icon-row.js +0 -14
- package/dist/components/checkout/payment-step-form/card-icon-row.js.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icon-row.jsx +0 -22
- package/dist/components/checkout/payment-step-form/card-icon-row.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icons/amex.d.ts +0 -4
- package/dist/components/checkout/payment-step-form/card-icons/amex.js +0 -6
- package/dist/components/checkout/payment-step-form/card-icons/amex.js.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icons/amex.jsx +0 -12
- package/dist/components/checkout/payment-step-form/card-icons/amex.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icons/diners-club.d.ts +0 -4
- package/dist/components/checkout/payment-step-form/card-icons/diners-club.js +0 -6
- package/dist/components/checkout/payment-step-form/card-icons/diners-club.js.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icons/diners-club.jsx +0 -10
- package/dist/components/checkout/payment-step-form/card-icons/diners-club.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icons/discover.d.ts +0 -4
- package/dist/components/checkout/payment-step-form/card-icons/discover.js +0 -6
- package/dist/components/checkout/payment-step-form/card-icons/discover.js.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icons/discover.jsx +0 -12
- package/dist/components/checkout/payment-step-form/card-icons/discover.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icons/jcb.d.ts +0 -4
- package/dist/components/checkout/payment-step-form/card-icons/jcb.js +0 -6
- package/dist/components/checkout/payment-step-form/card-icons/jcb.js.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icons/jcb.jsx +0 -23
- package/dist/components/checkout/payment-step-form/card-icons/jcb.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icons/mastercard.d.ts +0 -4
- package/dist/components/checkout/payment-step-form/card-icons/mastercard.js +0 -6
- package/dist/components/checkout/payment-step-form/card-icons/mastercard.js.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icons/mastercard.jsx +0 -12
- package/dist/components/checkout/payment-step-form/card-icons/mastercard.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icons/visa.d.ts +0 -4
- package/dist/components/checkout/payment-step-form/card-icons/visa.js +0 -6
- package/dist/components/checkout/payment-step-form/card-icons/visa.js.map +0 -1
- package/dist/components/checkout/payment-step-form/card-icons/visa.jsx +0 -10
- package/dist/components/checkout/payment-step-form/card-icons/visa.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/cc-button.d.ts +0 -3
- package/dist/components/checkout/payment-step-form/cc-button.js +0 -6
- package/dist/components/checkout/payment-step-form/cc-button.js.map +0 -1
- package/dist/components/checkout/payment-step-form/cc-button.jsx +0 -9
- package/dist/components/checkout/payment-step-form/cc-button.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/contact-form.d.ts +0 -5
- package/dist/components/checkout/payment-step-form/contact-form.js +0 -6
- package/dist/components/checkout/payment-step-form/contact-form.js.map +0 -1
- package/dist/components/checkout/payment-step-form/contact-form.jsx +0 -21
- package/dist/components/checkout/payment-step-form/contact-form.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/crypto-icons/btc.d.ts +0 -4
- package/dist/components/checkout/payment-step-form/crypto-icons/btc.js +0 -6
- package/dist/components/checkout/payment-step-form/crypto-icons/btc.js.map +0 -1
- package/dist/components/checkout/payment-step-form/crypto-icons/btc.jsx +0 -8
- package/dist/components/checkout/payment-step-form/crypto-icons/btc.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/crypto-icons/eth.d.ts +0 -4
- package/dist/components/checkout/payment-step-form/crypto-icons/eth.js +0 -6
- package/dist/components/checkout/payment-step-form/crypto-icons/eth.js.map +0 -1
- package/dist/components/checkout/payment-step-form/crypto-icons/eth.jsx +0 -17
- package/dist/components/checkout/payment-step-form/crypto-icons/eth.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/crypto-icons/usdt.d.ts +0 -4
- package/dist/components/checkout/payment-step-form/crypto-icons/usdt.js +0 -6
- package/dist/components/checkout/payment-step-form/crypto-icons/usdt.js.map +0 -1
- package/dist/components/checkout/payment-step-form/crypto-icons/usdt.jsx +0 -10
- package/dist/components/checkout/payment-step-form/crypto-icons/usdt.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/index.d.ts +0 -4
- package/dist/components/checkout/payment-step-form/index.js +0 -77
- package/dist/components/checkout/payment-step-form/index.js.map +0 -1
- package/dist/components/checkout/payment-step-form/index.jsx +0 -86
- package/dist/components/checkout/payment-step-form/index.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/methods/bank-transfer.d.ts +0 -4
- package/dist/components/checkout/payment-step-form/methods/bank-transfer.js +0 -24
- package/dist/components/checkout/payment-step-form/methods/bank-transfer.js.map +0 -1
- package/dist/components/checkout/payment-step-form/methods/bank-transfer.jsx +0 -44
- package/dist/components/checkout/payment-step-form/methods/bank-transfer.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/methods/card.d.ts +0 -4
- package/dist/components/checkout/payment-step-form/methods/card.js +0 -160
- package/dist/components/checkout/payment-step-form/methods/card.js.map +0 -1
- package/dist/components/checkout/payment-step-form/methods/card.jsx +0 -182
- package/dist/components/checkout/payment-step-form/methods/card.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/methods/crypto.d.ts +0 -9
- package/dist/components/checkout/payment-step-form/methods/crypto.js +0 -137
- package/dist/components/checkout/payment-step-form/methods/crypto.js.map +0 -1
- package/dist/components/checkout/payment-step-form/methods/crypto.jsx +0 -167
- package/dist/components/checkout/payment-step-form/methods/crypto.jsx.map +0 -1
- package/dist/components/checkout/payment-step-form/methods/index.d.ts +0 -6
- package/dist/components/checkout/payment-step-form/methods/index.js +0 -21
- package/dist/components/checkout/payment-step-form/methods/index.js.map +0 -1
- package/dist/components/checkout/shipping-step-form.d.ts +0 -3
- package/dist/components/checkout/shipping-step-form.js +0 -53
- package/dist/components/checkout/shipping-step-form.js.map +0 -1
- package/dist/components/checkout/shipping-step-form.jsx +0 -106
- package/dist/components/checkout/shipping-step-form.jsx.map +0 -1
- package/dist/components/index.d.ts +0 -8
- package/dist/components/index.js +0 -9
- package/dist/components/index.js.map +0 -1
- package/dist/components/item/product-card.d.ts +0 -7
- package/dist/components/item/product-card.js +0 -9
- package/dist/components/item/product-card.js.map +0 -1
- package/dist/components/item/product-card.jsx +0 -21
- package/dist/components/item/product-card.jsx.map +0 -1
- package/dist/components/item-selector/button.d.ts +0 -4
- package/dist/components/item-selector/button.js +0 -47
- package/dist/components/item-selector/button.js.map +0 -1
- package/dist/components/item-selector/button.jsx +0 -65
- package/dist/components/item-selector/button.jsx.map +0 -1
- package/dist/components/item-selector/carousel/index.d.ts +0 -12
- package/dist/components/item-selector/carousel/index.js +0 -74
- package/dist/components/item-selector/carousel/index.js.map +0 -1
- package/dist/components/item-selector/carousel/index.jsx +0 -101
- package/dist/components/item-selector/carousel/index.jsx.map +0 -1
- package/dist/components/item-selector/carousel/slider.d.ts +0 -8
- package/dist/components/item-selector/carousel/slider.js +0 -12
- package/dist/components/item-selector/carousel/slider.js.map +0 -1
- package/dist/components/item-selector/carousel/slider.jsx +0 -11
- package/dist/components/item-selector/carousel/slider.jsx.map +0 -1
- package/dist/components/item-selector/index.d.ts +0 -2
- package/dist/components/item-selector/index.js +0 -3
- package/dist/components/item-selector/index.js.map +0 -1
- package/dist/components/item-selector/quantity-indicator.d.ts +0 -9
- package/dist/components/item-selector/quantity-indicator.js +0 -16
- package/dist/components/item-selector/quantity-indicator.js.map +0 -1
- package/dist/components/item-selector/quantity-indicator.jsx +0 -23
- package/dist/components/item-selector/quantity-indicator.jsx.map +0 -1
- package/dist/components/node-tabs/index.d.ts +0 -14
- package/dist/components/node-tabs/index.js +0 -42
- package/dist/components/node-tabs/index.js.map +0 -1
- package/dist/components/node-tabs/index.jsx +0 -48
- package/dist/components/node-tabs/index.jsx.map +0 -1
- package/dist/components/node-tabs/node-image.d.ts +0 -6
- package/dist/components/node-tabs/node-image.js +0 -13
- package/dist/components/node-tabs/node-image.js.map +0 -1
- package/dist/components/node-tabs/node-image.jsx +0 -12
- package/dist/components/node-tabs/node-image.jsx.map +0 -1
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -7
- package/dist/index.js.map +0 -1
- package/dist/service/context.d.ts +0 -8
- package/dist/service/context.js +0 -19
- package/dist/service/context.js.map +0 -1
- package/dist/service/context.jsx +0 -20
- package/dist/service/context.jsx.map +0 -1
- package/dist/service/debug.d.ts +0 -10
- package/dist/service/debug.js +0 -30
- package/dist/service/debug.js.map +0 -1
- package/dist/service/impls/standalone/actual-line-item.d.ts +0 -40
- package/dist/service/impls/standalone/actual-line-item.js +0 -84
- package/dist/service/impls/standalone/actual-line-item.js.map +0 -1
- package/dist/service/impls/standalone/get-instance.d.ts +0 -2
- package/dist/service/impls/standalone/get-instance.js +0 -39
- package/dist/service/impls/standalone/get-instance.js.map +0 -1
- package/dist/service/impls/standalone/index.d.ts +0 -67
- package/dist/service/impls/standalone/index.js +0 -416
- package/dist/service/impls/standalone/index.js.map +0 -1
- package/dist/service/impls/standalone/order/firebase.d.ts +0 -6
- package/dist/service/impls/standalone/order/firebase.js +0 -6
- package/dist/service/impls/standalone/order/firebase.js.map +0 -1
- package/dist/service/impls/standalone/order/index.d.ts +0 -30
- package/dist/service/impls/standalone/order/index.js +0 -21
- package/dist/service/impls/standalone/order/index.js.map +0 -1
- package/dist/service/impls/standalone/persistence.d.ts +0 -4
- package/dist/service/impls/standalone/persistence.js +0 -22
- package/dist/service/impls/standalone/persistence.js.map +0 -1
- package/dist/service/path-utils.d.ts +0 -7
- package/dist/service/path-utils.js +0 -16
- package/dist/service/path-utils.js.map +0 -1
- package/dist/service/sep.d.ts +0 -6
- package/dist/service/sep.js +0 -6
- package/dist/service/sep.js.map +0 -1
- package/dist/types/category-node.d.ts +0 -36
- package/dist/types/category-node.js +0 -2
- package/dist/types/category-node.js.map +0 -1
- package/dist/types/checkout.d.ts +0 -33
- package/dist/types/checkout.js +0 -2
- package/dist/types/checkout.js.map +0 -1
- package/dist/types/commerce-config.d.ts +0 -11
- package/dist/types/commerce-config.js +0 -2
- package/dist/types/commerce-config.js.map +0 -1
- package/dist/types/commerce-service.d.ts +0 -109
- package/dist/types/commerce-service.js +0 -2
- package/dist/types/commerce-service.js.map +0 -1
- package/dist/types/family.d.ts +0 -16
- package/dist/types/family.js +0 -2
- package/dist/types/family.js.map +0 -1
- package/dist/types/index.d.ts +0 -13
- package/dist/types/index.js +0 -8
- package/dist/types/index.js.map +0 -1
- package/dist/types/item-selector.d.ts +0 -72
- package/dist/types/item-selector.js +0 -2
- package/dist/types/item-selector.js.map +0 -1
- package/dist/types/line-item.d.ts +0 -14
- package/dist/types/line-item.js +0 -2
- package/dist/types/line-item.js.map +0 -1
- package/dist/types/multi-family-selector-props.d.ts +0 -16
- package/dist/types/multi-family-selector-props.js +0 -2
- package/dist/types/multi-family-selector-props.js.map +0 -1
- package/dist/types/product.d.ts +0 -15
- package/dist/types/product.js +0 -2
- package/dist/types/product.js.map +0 -1
- package/dist/types/promo.d.ts +0 -7
- package/dist/types/promo.js +0 -2
- package/dist/types/promo.js.map +0 -1
- package/dist/types/selection-ui-specifier.d.ts +0 -40
- package/dist/types/selection-ui-specifier.js +0 -2
- package/dist/types/selection-ui-specifier.js.map +0 -1
- package/dist/types/string-mutator.d.ts +0 -9
- package/dist/types/string-mutator.js +0 -2
- package/dist/types/string-mutator.js.map +0 -1
- package/dist/types/token-separators.d.ts +0 -6
- package/dist/types/token-separators.js +0 -2
- package/dist/types/token-separators.js.map +0 -1
- package/dist/util/analytics.d.ts +0 -9
- package/dist/util/analytics.js +0 -10
- package/dist/util/analytics.js.map +0 -1
- package/dist/util/countries.d.ts +0 -7
- package/dist/util/countries.js +0 -197
- package/dist/util/countries.js.map +0 -1
- package/dist/util/error.d.ts +0 -1
- package/dist/util/error.js +0 -22
- package/dist/util/error.js.map +0 -1
- package/dist/util/index.d.ts +0 -15
- package/dist/util/index.js +0 -54
- package/dist/util/index.js.map +0 -1
- package/dist/util/item-selector-options-accessor.d.ts +0 -3
- package/dist/util/item-selector-options-accessor.js +0 -27
- package/dist/util/item-selector-options-accessor.js.map +0 -1
- package/dist/util/line-item-ref.d.ts +0 -8
- package/dist/util/line-item-ref.js +0 -15
- package/dist/util/line-item-ref.js.map +0 -1
- package/dist/util/multi-family-selector-options-accessor.d.ts +0 -3
- package/dist/util/multi-family-selector-options-accessor.js +0 -11
- package/dist/util/multi-family-selector-options-accessor.js.map +0 -1
- package/dist/util/obs-string-mutator.d.ts +0 -8
- package/dist/util/obs-string-mutator.js +0 -15
- package/dist/util/obs-string-mutator.js.map +0 -1
- package/dist/util/product-media-accessor.d.ts +0 -29
- package/dist/util/product-media-accessor.js +0 -22
- package/dist/util/product-media-accessor.js.map +0 -1
- package/dist/util/promo-codes.d.ts +0 -3
- package/dist/util/promo-codes.js +0 -100
- package/dist/util/promo-codes.js.map +0 -1
- package/dist/util/selection-ui-specifiers.d.ts +0 -3
- package/dist/util/selection-ui-specifiers.js +0 -24
- package/dist/util/selection-ui-specifiers.js.map +0 -1
- package/dist/util/square-payment.d.ts +0 -7
- package/dist/util/square-payment.js +0 -37
- package/dist/util/square-payment.js.map +0 -1
- package/dist/util/use-sync-sku-param-w-current-item.d.ts +0 -2
- package/dist/util/use-sync-sku-param-w-current-item.js +0 -61
- package/dist/util/use-sync-sku-param-w-current-item.js.map +0 -1
package/client.ts
CHANGED
|
@@ -1,29 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @hanzo/commerce/client
|
|
3
3
|
*
|
|
4
|
-
* TypeScript client for the Hanzo Commerce API.
|
|
5
|
-
*
|
|
4
|
+
* Universal TypeScript client for the Hanzo Commerce API.
|
|
5
|
+
* Works in browser, Node.js, and edge runtimes — no backend required.
|
|
6
|
+
* Covers billing, subscriptions, payments, checkout, coupons,
|
|
7
|
+
* referrals, affiliates, usage, and plans.
|
|
6
8
|
*
|
|
7
9
|
* @example
|
|
8
10
|
* ```ts
|
|
9
|
-
* import { Commerce } from '@hanzo/commerce'
|
|
11
|
+
* import { Commerce } from '@hanzo/commerce/client'
|
|
10
12
|
*
|
|
11
|
-
* const commerce = new Commerce({
|
|
12
|
-
* commerceUrl: 'https://commerce.hanzo.ai',
|
|
13
|
-
* token: iamAccessToken,
|
|
14
|
-
* })
|
|
13
|
+
* const commerce = new Commerce({ baseUrl: 'https://api.hanzo.ai', token: iamToken })
|
|
15
14
|
*
|
|
16
|
-
* //
|
|
17
|
-
* const
|
|
15
|
+
* // Validate a coupon before checkout
|
|
16
|
+
* const coupon = await commerce.validateCoupon('LAUNCH50')
|
|
18
17
|
*
|
|
19
|
-
* //
|
|
20
|
-
* await commerce.
|
|
18
|
+
* // Create a checkout session
|
|
19
|
+
* const session = await commerce.createCheckoutSession({
|
|
20
|
+
* items: [{ id: 'plan_pro', quantity: 1 }],
|
|
21
|
+
* couponCode: 'LAUNCH50',
|
|
22
|
+
* referrerId: 'ref_abc123',
|
|
23
|
+
* successUrl: 'https://app.example.com/success',
|
|
24
|
+
* cancelUrl: 'https://app.example.com/cancel',
|
|
25
|
+
* })
|
|
26
|
+
* window.location.href = session.checkoutUrl
|
|
21
27
|
*
|
|
22
|
-
* //
|
|
23
|
-
* await commerce.
|
|
28
|
+
* // Tokenize a card (S2S — no external SDK required)
|
|
29
|
+
* const token = await commerce.tokenizeCard({
|
|
30
|
+
* number: '4242424242424242',
|
|
31
|
+
* expiryMonth: '12',
|
|
32
|
+
* expiryYear: '2027',
|
|
33
|
+
* cvc: '123',
|
|
34
|
+
* name: 'Jane Smith',
|
|
35
|
+
* })
|
|
24
36
|
*
|
|
25
|
-
* //
|
|
26
|
-
* await commerce.
|
|
37
|
+
* // Subscribe
|
|
38
|
+
* const sub = await commerce.subscribe({ planId: 'pro', userId: 'user_xyz' })
|
|
27
39
|
* ```
|
|
28
40
|
*/
|
|
29
41
|
|
|
@@ -32,15 +44,21 @@
|
|
|
32
44
|
// ---------------------------------------------------------------------------
|
|
33
45
|
|
|
34
46
|
export type CommerceClientConfig = {
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Commerce API base URL.
|
|
49
|
+
* Defaults to https://api.hanzo.ai
|
|
50
|
+
*/
|
|
51
|
+
baseUrl?: string
|
|
52
|
+
/** @deprecated use baseUrl */
|
|
53
|
+
commerceUrl?: string
|
|
54
|
+
/** IAM access token for authenticated requests. */
|
|
38
55
|
token?: string
|
|
56
|
+
/** Request timeout in milliseconds. Default 15 000. */
|
|
57
|
+
timeoutMs?: number
|
|
39
58
|
}
|
|
40
59
|
|
|
41
|
-
|
|
42
60
|
// ---------------------------------------------------------------------------
|
|
43
|
-
//
|
|
61
|
+
// Core types
|
|
44
62
|
// ---------------------------------------------------------------------------
|
|
45
63
|
|
|
46
64
|
export type Balance = {
|
|
@@ -69,6 +87,7 @@ export type Subscription = {
|
|
|
69
87
|
id?: string
|
|
70
88
|
planId?: string
|
|
71
89
|
userId?: string
|
|
90
|
+
customerId?: string
|
|
72
91
|
status?: 'trialing' | 'active' | 'past_due' | 'canceled' | 'unpaid' | string
|
|
73
92
|
billingType?: 'charge_automatically' | 'send_invoice'
|
|
74
93
|
periodStart?: string
|
|
@@ -77,17 +96,25 @@ export type Subscription = {
|
|
|
77
96
|
trialEnd?: string
|
|
78
97
|
quantity?: number
|
|
79
98
|
createdAt?: string
|
|
99
|
+
cancelAtPeriodEnd?: boolean
|
|
100
|
+
currentPeriodEnd?: string
|
|
80
101
|
}
|
|
81
102
|
|
|
82
103
|
export type Plan = {
|
|
104
|
+
id?: string
|
|
83
105
|
slug?: string
|
|
84
106
|
name?: string
|
|
85
107
|
description?: string
|
|
86
108
|
price?: number
|
|
109
|
+
priceMonthly?: number
|
|
110
|
+
priceAnnual?: number
|
|
87
111
|
currency?: string
|
|
88
112
|
interval?: 'monthly' | 'yearly' | string
|
|
89
113
|
intervalCount?: number
|
|
90
114
|
trialPeriodDays?: number
|
|
115
|
+
features?: string[]
|
|
116
|
+
popular?: boolean
|
|
117
|
+
contactSales?: boolean
|
|
91
118
|
metadata?: Record<string, unknown>
|
|
92
119
|
}
|
|
93
120
|
|
|
@@ -116,23 +143,202 @@ export type UsageRecord = {
|
|
|
116
143
|
completionTokens?: number
|
|
117
144
|
}
|
|
118
145
|
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
// Coupon / Discount types
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
|
|
150
|
+
export type CouponType = 'Percent' | 'Flat' | 'FreeShipping' | 'FreeItem'
|
|
151
|
+
|
|
152
|
+
export type Coupon = {
|
|
153
|
+
id?: string
|
|
154
|
+
code: string
|
|
155
|
+
type: CouponType
|
|
156
|
+
/** Amount: percentage (0-100) for Percent, cents for Flat */
|
|
157
|
+
amount: number
|
|
158
|
+
description?: string
|
|
159
|
+
limit?: number
|
|
160
|
+
used?: number
|
|
161
|
+
startDate?: string
|
|
162
|
+
endDate?: string
|
|
163
|
+
enabled?: boolean
|
|
164
|
+
/** Calculated discount in cents (returned by validateCoupon) */
|
|
165
|
+
discountCents?: number
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export type CouponValidateResult = {
|
|
169
|
+
valid: boolean
|
|
170
|
+
coupon?: Coupon
|
|
171
|
+
error?: string
|
|
172
|
+
/** Discount in cents for a given subtotal */
|
|
173
|
+
discountCents?: number
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export type Discount = {
|
|
177
|
+
id?: string
|
|
178
|
+
type: 'Percent' | 'Flat' | 'FreeShipping' | 'FreeItem' | 'Bulk'
|
|
179
|
+
amount: number
|
|
180
|
+
scope?: 'Product' | 'Variant' | 'Collection' | 'Store'
|
|
181
|
+
enabled?: boolean
|
|
182
|
+
startDate?: string
|
|
183
|
+
endDate?: string
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ---------------------------------------------------------------------------
|
|
187
|
+
// Checkout types
|
|
188
|
+
// ---------------------------------------------------------------------------
|
|
189
|
+
|
|
190
|
+
export type CheckoutItem = {
|
|
191
|
+
id: string
|
|
192
|
+
quantity?: number
|
|
193
|
+
/** Price override in cents */
|
|
194
|
+
price?: number
|
|
195
|
+
name?: string
|
|
196
|
+
description?: string
|
|
197
|
+
imageUrl?: string
|
|
198
|
+
metadata?: Record<string, unknown>
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export type CheckoutSessionRequest = {
|
|
202
|
+
items: CheckoutItem[]
|
|
203
|
+
successUrl: string
|
|
204
|
+
cancelUrl: string
|
|
205
|
+
couponCode?: string
|
|
206
|
+
referrerId?: string
|
|
207
|
+
affiliateId?: string
|
|
208
|
+
currency?: string
|
|
209
|
+
customer?: {
|
|
210
|
+
email?: string
|
|
211
|
+
name?: string
|
|
212
|
+
address?: string
|
|
213
|
+
city?: string
|
|
214
|
+
zip?: string
|
|
215
|
+
}
|
|
216
|
+
metadata?: Record<string, unknown>
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export type CheckoutSessionResponse = {
|
|
220
|
+
checkoutUrl: string
|
|
221
|
+
sessionId: string
|
|
222
|
+
/** Original total in cents before discount */
|
|
223
|
+
originalTotal?: number
|
|
224
|
+
/** Final total in cents after discount */
|
|
225
|
+
finalTotal?: number
|
|
226
|
+
discount?: {
|
|
227
|
+
code: string
|
|
228
|
+
type: CouponType
|
|
229
|
+
amount: number
|
|
230
|
+
discountCents: number
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
// Card tokenization (S2S — no provider SDK needed on the frontend)
|
|
236
|
+
// ---------------------------------------------------------------------------
|
|
237
|
+
|
|
238
|
+
export type CardTokenizeRequest = {
|
|
239
|
+
number: string
|
|
240
|
+
expiryMonth: string // "01"–"12"
|
|
241
|
+
expiryYear: string // "2025"–"2099"
|
|
242
|
+
cvc: string
|
|
243
|
+
name?: string
|
|
244
|
+
zip?: string
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export type CardTokenizeResult = {
|
|
248
|
+
token: string
|
|
249
|
+
brand: string
|
|
250
|
+
last4: string
|
|
251
|
+
expiryMonth: string
|
|
252
|
+
expiryYear: string
|
|
253
|
+
provider: string
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
257
|
+
// Payment method types
|
|
258
|
+
// ---------------------------------------------------------------------------
|
|
259
|
+
|
|
260
|
+
export type PaymentMethodType = 'card' | 'bank_account' | 'balance' | 'crypto' | 'wire'
|
|
261
|
+
|
|
262
|
+
export type PaymentMethod = {
|
|
263
|
+
id: string
|
|
264
|
+
type: PaymentMethodType
|
|
265
|
+
isDefault?: boolean
|
|
266
|
+
customerId?: string
|
|
267
|
+
card?: {
|
|
268
|
+
brand: string
|
|
269
|
+
last4: string
|
|
270
|
+
expMonth: number
|
|
271
|
+
expYear: number
|
|
272
|
+
}
|
|
273
|
+
providerRef?: string
|
|
274
|
+
providerType?: string
|
|
275
|
+
createdAt?: string
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
// Referral / Affiliate types
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
|
|
282
|
+
export type Referral = {
|
|
283
|
+
id?: string
|
|
284
|
+
userId?: string
|
|
285
|
+
referrerId?: string
|
|
286
|
+
affiliateId?: string
|
|
287
|
+
orderId?: string
|
|
288
|
+
fee?: number
|
|
289
|
+
createdAt?: string
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export type Referrer = {
|
|
293
|
+
id?: string
|
|
294
|
+
userId?: string
|
|
295
|
+
enabled?: boolean
|
|
296
|
+
code?: string
|
|
297
|
+
referrals?: Referral[]
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export type Affiliate = {
|
|
301
|
+
id?: string
|
|
302
|
+
userId?: string
|
|
303
|
+
enabled?: boolean
|
|
304
|
+
commission?: number
|
|
305
|
+
couponId?: string
|
|
306
|
+
connectUrl?: string
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// ---------------------------------------------------------------------------
|
|
310
|
+
// Credit grant
|
|
311
|
+
// ---------------------------------------------------------------------------
|
|
312
|
+
|
|
313
|
+
export type CreditGrant = {
|
|
314
|
+
id?: string
|
|
315
|
+
userId?: string
|
|
316
|
+
amount: number
|
|
317
|
+
currency: string
|
|
318
|
+
expiresAt?: string
|
|
319
|
+
tags?: string[]
|
|
320
|
+
}
|
|
321
|
+
|
|
119
322
|
// ---------------------------------------------------------------------------
|
|
120
323
|
// Client
|
|
121
324
|
// ---------------------------------------------------------------------------
|
|
122
325
|
|
|
123
|
-
const
|
|
326
|
+
const DEFAULT_BASE_URL = 'https://api.hanzo.ai'
|
|
327
|
+
const DEFAULT_TIMEOUT_MS = 15_000
|
|
124
328
|
|
|
125
329
|
export class Commerce {
|
|
126
330
|
private readonly baseUrl: string
|
|
127
331
|
private token: string | undefined
|
|
332
|
+
private readonly timeoutMs: number
|
|
128
333
|
|
|
129
|
-
constructor(config: CommerceClientConfig) {
|
|
130
|
-
this.baseUrl = config.commerceUrl.replace(/\/+$/, '')
|
|
334
|
+
constructor(config: CommerceClientConfig = {}) {
|
|
335
|
+
this.baseUrl = (config.baseUrl ?? config.commerceUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, '')
|
|
131
336
|
this.token = config.token
|
|
337
|
+
this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
132
338
|
}
|
|
133
339
|
|
|
134
340
|
/** Update the auth token (e.g. after IAM token refresh). */
|
|
135
|
-
setToken(token: string) {
|
|
341
|
+
setToken(token: string): void {
|
|
136
342
|
this.token = token
|
|
137
343
|
}
|
|
138
344
|
|
|
@@ -153,11 +359,11 @@ export class Commerce {
|
|
|
153
359
|
}
|
|
154
360
|
|
|
155
361
|
const controller = new AbortController()
|
|
156
|
-
const timer = setTimeout(() => controller.abort(),
|
|
362
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs)
|
|
157
363
|
|
|
158
364
|
const headers: Record<string, string> = { Accept: 'application/json' }
|
|
159
365
|
const authToken = opts?.token ?? this.token
|
|
160
|
-
if (authToken) headers
|
|
366
|
+
if (authToken) headers['Authorization'] = `Bearer ${authToken}`
|
|
161
367
|
if (opts?.body) headers['Content-Type'] = 'application/json'
|
|
162
368
|
|
|
163
369
|
try {
|
|
@@ -184,13 +390,13 @@ export class Commerce {
|
|
|
184
390
|
// -----------------------------------------------------------------------
|
|
185
391
|
|
|
186
392
|
async getBalance(user: string, currency = 'usd', token?: string): Promise<Balance> {
|
|
187
|
-
return this.request<Balance>('/
|
|
393
|
+
return this.request<Balance>('/v1/billing/balance', {
|
|
188
394
|
params: { user, currency }, token,
|
|
189
395
|
})
|
|
190
396
|
}
|
|
191
397
|
|
|
192
398
|
async getAllBalances(user: string, token?: string): Promise<Record<string, Balance>> {
|
|
193
|
-
return this.request<Record<string, Balance>>('/
|
|
399
|
+
return this.request<Record<string, Balance>>('/v1/billing/balance/all', {
|
|
194
400
|
params: { user }, token,
|
|
195
401
|
})
|
|
196
402
|
}
|
|
@@ -200,13 +406,13 @@ export class Commerce {
|
|
|
200
406
|
// -----------------------------------------------------------------------
|
|
201
407
|
|
|
202
408
|
async addUsageRecord(record: UsageRecord, token?: string): Promise<Transaction> {
|
|
203
|
-
return this.request<Transaction>('/
|
|
409
|
+
return this.request<Transaction>('/v1/billing/usage', {
|
|
204
410
|
method: 'POST', body: record, token,
|
|
205
411
|
})
|
|
206
412
|
}
|
|
207
413
|
|
|
208
414
|
async getUsageRecords(user: string, currency = 'usd', token?: string): Promise<Transaction[]> {
|
|
209
|
-
return this.request<Transaction[]>('/
|
|
415
|
+
return this.request<Transaction[]>('/v1/billing/usage', {
|
|
210
416
|
params: { user, currency }, token,
|
|
211
417
|
})
|
|
212
418
|
}
|
|
@@ -219,96 +425,288 @@ export class Commerce {
|
|
|
219
425
|
params: { user: string; currency?: string; amount: number; notes?: string; tags?: string[]; expiresIn?: string },
|
|
220
426
|
token?: string,
|
|
221
427
|
): Promise<Transaction> {
|
|
222
|
-
return this.request<Transaction>('/
|
|
428
|
+
return this.request<Transaction>('/v1/billing/deposit', {
|
|
223
429
|
method: 'POST', body: params, token,
|
|
224
430
|
})
|
|
225
431
|
}
|
|
226
432
|
|
|
227
433
|
async grantStarterCredit(user: string, token?: string): Promise<Transaction> {
|
|
228
|
-
return this.request<Transaction>('/
|
|
434
|
+
return this.request<Transaction>('/v1/billing/credit', {
|
|
229
435
|
method: 'POST', body: { user }, token,
|
|
230
436
|
})
|
|
231
437
|
}
|
|
232
438
|
|
|
439
|
+
// -----------------------------------------------------------------------
|
|
440
|
+
// Plans
|
|
441
|
+
// -----------------------------------------------------------------------
|
|
442
|
+
|
|
443
|
+
async getPlans(token?: string): Promise<Plan[]> {
|
|
444
|
+
return this.request<Plan[]>('/v1/billing/plans', { token })
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
async getPlan(planId: string, token?: string): Promise<Plan | null> {
|
|
448
|
+
try {
|
|
449
|
+
return await this.request<Plan>(`/v1/billing/plans/${planId}`, { token })
|
|
450
|
+
} catch { return null }
|
|
451
|
+
}
|
|
452
|
+
|
|
233
453
|
// -----------------------------------------------------------------------
|
|
234
454
|
// Subscriptions
|
|
235
455
|
// -----------------------------------------------------------------------
|
|
236
456
|
|
|
237
|
-
async subscribe(
|
|
238
|
-
|
|
457
|
+
async subscribe(
|
|
458
|
+
params: { planId: string; userId?: string; customerId?: string; paymentMethodId?: string; couponCode?: string; trialDays?: number },
|
|
459
|
+
token?: string,
|
|
460
|
+
): Promise<Subscription> {
|
|
461
|
+
return this.request<Subscription>('/v1/billing/subscriptions', {
|
|
239
462
|
method: 'POST', body: params, token,
|
|
240
463
|
})
|
|
241
464
|
}
|
|
242
465
|
|
|
243
466
|
async getSubscription(subscriptionId: string, token?: string): Promise<Subscription | null> {
|
|
244
467
|
try {
|
|
245
|
-
return await this.request<Subscription>(`/
|
|
468
|
+
return await this.request<Subscription>(`/v1/billing/subscriptions/${subscriptionId}`, { token })
|
|
246
469
|
} catch { return null }
|
|
247
470
|
}
|
|
248
471
|
|
|
472
|
+
async listSubscriptions(params?: { customerId?: string }, token?: string): Promise<Subscription[]> {
|
|
473
|
+
return this.request<Subscription[]>('/v1/billing/subscriptions', {
|
|
474
|
+
params: params as Record<string, string> | undefined, token,
|
|
475
|
+
})
|
|
476
|
+
}
|
|
477
|
+
|
|
249
478
|
async updateSubscription(subscriptionId: string, update: Partial<Subscription>, token?: string): Promise<Subscription> {
|
|
250
|
-
return this.request<Subscription>(`/
|
|
479
|
+
return this.request<Subscription>(`/v1/billing/subscriptions/${subscriptionId}`, {
|
|
251
480
|
method: 'PATCH', body: update, token,
|
|
252
481
|
})
|
|
253
482
|
}
|
|
254
483
|
|
|
255
|
-
async cancelSubscription(subscriptionId: string, token?: string): Promise<
|
|
256
|
-
|
|
257
|
-
method: '
|
|
484
|
+
async cancelSubscription(subscriptionId: string, immediately = false, token?: string): Promise<Subscription> {
|
|
485
|
+
return this.request<Subscription>(`/v1/billing/subscriptions/${subscriptionId}/cancel`, {
|
|
486
|
+
method: 'POST', body: { immediately }, token,
|
|
487
|
+
})
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
async reactivateSubscription(subscriptionId: string, token?: string): Promise<Subscription> {
|
|
491
|
+
return this.request<Subscription>(`/v1/billing/subscriptions/${subscriptionId}/reactivate`, {
|
|
492
|
+
method: 'POST', token,
|
|
258
493
|
})
|
|
259
494
|
}
|
|
260
495
|
|
|
261
496
|
// -----------------------------------------------------------------------
|
|
262
|
-
// Checkout
|
|
497
|
+
// Checkout sessions
|
|
263
498
|
// -----------------------------------------------------------------------
|
|
264
499
|
|
|
265
|
-
|
|
266
|
-
|
|
500
|
+
/**
|
|
501
|
+
* Create a hosted checkout session.
|
|
502
|
+
* Returns a URL to redirect the customer to for payment.
|
|
503
|
+
* Supports coupons, referral tracking, and multiple currencies.
|
|
504
|
+
*/
|
|
505
|
+
async createCheckoutSession(
|
|
506
|
+
params: CheckoutSessionRequest,
|
|
507
|
+
token?: string,
|
|
508
|
+
): Promise<CheckoutSessionResponse> {
|
|
509
|
+
return this.request<CheckoutSessionResponse>('/v1/checkout/sessions', {
|
|
510
|
+
method: 'POST', body: params, token,
|
|
511
|
+
})
|
|
267
512
|
}
|
|
268
513
|
|
|
269
|
-
|
|
270
|
-
|
|
514
|
+
// -----------------------------------------------------------------------
|
|
515
|
+
// Card tokenization (S2S — no external SDK required)
|
|
516
|
+
// -----------------------------------------------------------------------
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Tokenize a payment card server-side.
|
|
520
|
+
* No external SDK (Square.js, Stripe.js, etc.) is needed on the frontend.
|
|
521
|
+
* The card data is sent to the Hanzo Commerce API over HTTPS, which
|
|
522
|
+
* tokenizes via the configured payment provider (Stripe).
|
|
523
|
+
*/
|
|
524
|
+
async tokenizeCard(card: CardTokenizeRequest, token?: string): Promise<CardTokenizeResult> {
|
|
525
|
+
return this.request<CardTokenizeResult>('/v1/billing/card/tokenize', {
|
|
526
|
+
method: 'POST',
|
|
527
|
+
body: {
|
|
528
|
+
number: card.number.replace(/\s/g, ''),
|
|
529
|
+
expiry_month: card.expiryMonth,
|
|
530
|
+
expiry_year: card.expiryYear,
|
|
531
|
+
cvc: card.cvc,
|
|
532
|
+
name: card.name,
|
|
533
|
+
zip: card.zip,
|
|
534
|
+
},
|
|
535
|
+
token,
|
|
536
|
+
})
|
|
271
537
|
}
|
|
272
538
|
|
|
273
|
-
|
|
274
|
-
|
|
539
|
+
// -----------------------------------------------------------------------
|
|
540
|
+
// Payment methods
|
|
541
|
+
// -----------------------------------------------------------------------
|
|
542
|
+
|
|
543
|
+
async addPaymentMethod(
|
|
544
|
+
params: {
|
|
545
|
+
customerId: string
|
|
546
|
+
type: PaymentMethodType
|
|
547
|
+
token?: string // from tokenizeCard
|
|
548
|
+
providerRef?: string
|
|
549
|
+
providerType?: string
|
|
550
|
+
},
|
|
551
|
+
token?: string,
|
|
552
|
+
): Promise<PaymentMethod> {
|
|
553
|
+
return this.request<PaymentMethod>('/v1/billing/payment-methods', {
|
|
554
|
+
method: 'POST', body: params, token,
|
|
555
|
+
})
|
|
275
556
|
}
|
|
276
557
|
|
|
277
|
-
async
|
|
278
|
-
return this.request<
|
|
558
|
+
async listPaymentMethods(customerId: string, token?: string): Promise<PaymentMethod[]> {
|
|
559
|
+
return this.request<PaymentMethod[]>('/v1/billing/payment-methods', {
|
|
560
|
+
params: { customerId }, token,
|
|
561
|
+
})
|
|
279
562
|
}
|
|
280
563
|
|
|
564
|
+
async removePaymentMethod(paymentMethodId: string, token?: string): Promise<void> {
|
|
565
|
+
await this.request<void>(`/v1/billing/payment-methods/${paymentMethodId}`, {
|
|
566
|
+
method: 'DELETE', token,
|
|
567
|
+
})
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
async setDefaultPaymentMethod(customerId: string, paymentMethodId: string, token?: string): Promise<PaymentMethod> {
|
|
571
|
+
return this.request<PaymentMethod>(`/v1/billing/customers/${customerId}/default-payment-method`, {
|
|
572
|
+
method: 'POST', body: { paymentMethodId }, token,
|
|
573
|
+
})
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// -----------------------------------------------------------------------
|
|
577
|
+
// Coupons / Promo codes
|
|
578
|
+
// -----------------------------------------------------------------------
|
|
579
|
+
|
|
281
580
|
/**
|
|
282
|
-
*
|
|
283
|
-
*
|
|
581
|
+
* Validate a coupon code.
|
|
582
|
+
* Optionally pass a subtotalCents to get the calculated discount amount.
|
|
284
583
|
*/
|
|
285
|
-
async
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
584
|
+
async validateCoupon(code: string, subtotalCents?: number, token?: string): Promise<CouponValidateResult> {
|
|
585
|
+
try {
|
|
586
|
+
const result = await this.request<Coupon>('/v1/coupon/validate', {
|
|
587
|
+
method: 'POST',
|
|
588
|
+
body: { code: code.toUpperCase().trim(), subtotalCents },
|
|
589
|
+
token,
|
|
590
|
+
})
|
|
591
|
+
return { valid: true, coupon: result }
|
|
592
|
+
} catch (err) {
|
|
593
|
+
const msg = err instanceof CommerceApiError ? err.message : 'Invalid coupon'
|
|
594
|
+
return { valid: false, error: msg }
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Redeem a coupon for a user. Creates credit grant records.
|
|
600
|
+
*/
|
|
601
|
+
async redeemCoupon(code: string, userId: string, token?: string): Promise<CreditGrant[]> {
|
|
602
|
+
return this.request<CreditGrant[]>('/v1/coupon/redeem', {
|
|
603
|
+
method: 'POST',
|
|
604
|
+
body: { code: code.toUpperCase().trim(), userId },
|
|
605
|
+
token,
|
|
294
606
|
})
|
|
295
607
|
}
|
|
296
608
|
|
|
297
609
|
// -----------------------------------------------------------------------
|
|
298
|
-
//
|
|
610
|
+
// Referrals & Affiliates
|
|
299
611
|
// -----------------------------------------------------------------------
|
|
300
612
|
|
|
301
|
-
|
|
302
|
-
|
|
613
|
+
/**
|
|
614
|
+
* Get or create a referrer record for a user.
|
|
615
|
+
* Returns the referral code/link the user can share.
|
|
616
|
+
*/
|
|
617
|
+
async getOrCreateReferrer(userId: string, token?: string): Promise<Referrer> {
|
|
618
|
+
return this.request<Referrer>('/v1/referrer', {
|
|
619
|
+
method: 'POST', body: { userId }, token,
|
|
620
|
+
})
|
|
303
621
|
}
|
|
304
622
|
|
|
305
|
-
async
|
|
623
|
+
async getReferrals(userId: string, token?: string): Promise<Referral[]> {
|
|
624
|
+
return this.request<Referral[]>(`/v1/user/${userId}/referrals`, { token })
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
async getReferrers(userId: string, token?: string): Promise<Referrer[]> {
|
|
628
|
+
return this.request<Referrer[]>(`/v1/user/${userId}/referrers`, { token })
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Get affiliate details for a user.
|
|
633
|
+
*/
|
|
634
|
+
async getAffiliate(userId: string, token?: string): Promise<Affiliate | null> {
|
|
306
635
|
try {
|
|
307
|
-
return await this.request<
|
|
636
|
+
return await this.request<Affiliate>(`/v1/user/${userId}/affiliate`, { token })
|
|
308
637
|
} catch { return null }
|
|
309
638
|
}
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Create an affiliate account for a user.
|
|
642
|
+
* After creation, user can connect their bank via the returnedconnectUrl.
|
|
643
|
+
*/
|
|
644
|
+
async createAffiliate(userId: string, token?: string): Promise<Affiliate> {
|
|
645
|
+
return this.request<Affiliate>('/v1/affiliate', {
|
|
646
|
+
method: 'POST', body: { userId }, token,
|
|
647
|
+
})
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
async getAffiliateReferrals(affiliateId: string, token?: string): Promise<Referral[]> {
|
|
651
|
+
return this.request<Referral[]>(`/v1/affiliate/${affiliateId}/referrals`, { token })
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
async getAffiliateOrders(affiliateId: string, token?: string): Promise<unknown[]> {
|
|
655
|
+
return this.request<unknown[]>(`/v1/affiliate/${affiliateId}/orders`, { token })
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
async getAffiliateTransactions(affiliateId: string, token?: string): Promise<Transaction[]> {
|
|
659
|
+
return this.request<Transaction[]>(`/v1/affiliate/${affiliateId}/transactions`, { token })
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// -----------------------------------------------------------------------
|
|
663
|
+
// Legacy checkout (order-based)
|
|
664
|
+
// -----------------------------------------------------------------------
|
|
665
|
+
|
|
666
|
+
async authorize(orderId: string, token?: string): Promise<Payment> {
|
|
667
|
+
return this.request<Payment>(`/v1/authorize/${orderId}`, { method: 'POST', token })
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
async capture(orderId: string, token?: string): Promise<Payment> {
|
|
671
|
+
return this.request<Payment>(`/v1/capture/${orderId}`, { method: 'POST', token })
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
async charge(orderId: string, token?: string): Promise<Payment> {
|
|
675
|
+
return this.request<Payment>(`/v1/charge/${orderId}`, { method: 'POST', token })
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
async refund(paymentId: string, token?: string): Promise<Payment> {
|
|
679
|
+
return this.request<Payment>(`/v1/refund/${paymentId}`, { method: 'POST', token })
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
async billingRefund(
|
|
683
|
+
params: { user: string; amount: number; originalTransactionId: string; currency?: string; notes?: string },
|
|
684
|
+
token?: string,
|
|
685
|
+
): Promise<Transaction> {
|
|
686
|
+
return this.request<Transaction>('/v1/billing/refund', {
|
|
687
|
+
method: 'POST', body: params, token,
|
|
688
|
+
})
|
|
689
|
+
}
|
|
310
690
|
}
|
|
311
691
|
|
|
692
|
+
// ---------------------------------------------------------------------------
|
|
693
|
+
// Standalone factory helpers — import these for quick setup
|
|
694
|
+
// ---------------------------------------------------------------------------
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Create a commerce client pre-configured for api.hanzo.ai.
|
|
698
|
+
* Pass your IAM access token (read from localStorage or cookie).
|
|
699
|
+
*
|
|
700
|
+
* @example
|
|
701
|
+
* ```ts
|
|
702
|
+
* import { hanzoCommerce } from '@hanzo/commerce/client'
|
|
703
|
+
* const commerce = hanzoCommerce(localStorage.getItem('hanzo-auth-token') ?? undefined)
|
|
704
|
+
* const plans = await commerce.getPlans()
|
|
705
|
+
* ```
|
|
706
|
+
*/
|
|
707
|
+
export function hanzoCommerce(token?: string): Commerce {
|
|
708
|
+
return new Commerce({ token })
|
|
709
|
+
}
|
|
312
710
|
|
|
313
711
|
// ---------------------------------------------------------------------------
|
|
314
712
|
// Error
|