|
1 | 1 | /** |
2 | 2 | * 카카오 BMS 자유형 CAROUSEL_COMMERCE 타입 발송 예제 |
3 | 3 | * 캐러셀 커머스 형식으로, 여러 상품을 슬라이드로 보여주는 구조입니다. |
| 4 | + * 이미지 업로드 시 fileType은 'BMS_CAROUSEL_COMMERCE_LIST'를 사용해야 합니다. (2:1 비율 이미지 필수) |
4 | 5 | * head + list(상품카드들) + tail 구조입니다. |
| 6 | + * head 없이 2-6개 아이템, head 포함 시 1-5개 아이템 가능합니다. |
| 7 | + * 가격 정보(regularPrice, discountPrice, discountRate, discountFixed)는 숫자 타입입니다. |
| 8 | + * 캐러셀 커머스 버튼은 WL, AL 타입만 지원합니다. |
| 9 | + * 쿠폰 제목 형식: "N원 할인 쿠폰", "N% 할인 쿠폰", "배송비 할인 쿠폰", "OOO 무료 쿠폰", "OOO UP 쿠폰" |
5 | 10 | * targeting 타입 중 M, N의 경우는 카카오 측에서 인허가된 채널만 사용하실 수 있습니다. |
6 | 11 | * 그 외의 모든 채널은 I 타입만 사용 가능합니다. |
7 | 12 | * 발신번호, 수신번호에 반드시 -, * 등 특수문자를 제거하여 기입하시기 바랍니다. 예) 01012345678 |
8 | 13 | */ |
| 14 | +const path = require('path'); |
9 | 15 | const {SolapiMessageService} = require('solapi'); |
10 | 16 | const messageService = new SolapiMessageService( |
11 | 17 | 'ENTER_YOUR_API_KEY', |
12 | 18 | 'ENTER_YOUR_API_SECRET', |
13 | 19 | ); |
14 | 20 |
|
15 | | -// 단일 발송 예제 |
16 | | -// imageId는 미리 업로드한 이미지 ID를 사용합니다. |
17 | | -// 이미지 업로드: messageService.uploadFile(filePath, 'KAKAO').then(res => res.fileId) |
| 21 | +// CAROUSEL_COMMERCE 타입은 'BMS_CAROUSEL_COMMERCE_LIST' fileType으로 업로드해야 합니다 (2:1 비율 이미지 필수) |
18 | 22 | messageService |
19 | | - .sendOne({ |
20 | | - to: '수신번호', |
21 | | - from: '계정에서 등록한 발신번호 입력', |
22 | | - type: 'BMS_FREE', |
23 | | - kakaoOptions: { |
24 | | - pfId: '연동한 비즈니스 채널의 pfId', |
25 | | - bms: { |
26 | | - targeting: 'I', // I: 전체, M/N: 인허가 채널만 |
27 | | - chatBubbleType: 'CAROUSEL_COMMERCE', |
28 | | - carousel: { |
29 | | - // head: 캐러셀 상단 대표 이미지 및 설명 (선택) |
30 | | - head: { |
31 | | - header: '이번 주 베스트 상품', |
32 | | - content: '인기 상품을 만나보세요!', |
33 | | - imageId: '업로드한 헤드 이미지 ID', |
34 | | - linkMobile: 'https://m.example.com/best', |
35 | | - linkPc: 'https://example.com/best', // 선택 |
36 | | - }, |
37 | | - // list: 상품 카드 목록 (head 있으면 1-5개, 없으면 2-6개) |
38 | | - list: [ |
39 | | - { |
40 | | - additionalContent: '무료배송', // 부가정보 (선택) |
41 | | - imageId: '업로드한 상품 이미지 ID', |
42 | | - coupon: { |
43 | | - title: '10% 할인 쿠폰', |
44 | | - description: '신규 회원 전용', |
45 | | - linkMobile: 'https://m.example.com/coupon1', |
46 | | - }, |
47 | | - commerce: { |
48 | | - title: '상품명 1', |
49 | | - regularPrice: '30000', |
50 | | - discountPrice: '25000', |
51 | | - discountRate: '17', |
52 | | - }, |
53 | | - buttons: [ |
| 23 | + .uploadFile( |
| 24 | + path.join(__dirname, '../../images/example-2to1.jpg'), |
| 25 | + 'BMS_CAROUSEL_COMMERCE_LIST', |
| 26 | + ) |
| 27 | + .then(res => res.fileId) |
| 28 | + .then(imageId => { |
| 29 | + // 최소 구조 단건 발송 예제 (carousel.list 2개) |
| 30 | + messageService |
| 31 | + .send({ |
| 32 | + to: '수신번호', |
| 33 | + from: '계정에서 등록한 발신번호 입력', |
| 34 | + type: 'BMS_FREE', |
| 35 | + kakaoOptions: { |
| 36 | + pfId: '연동한 비즈니스 채널의 pfId', |
| 37 | + bms: { |
| 38 | + targeting: 'I', |
| 39 | + chatBubbleType: 'CAROUSEL_COMMERCE', |
| 40 | + carousel: { |
| 41 | + list: [ |
54 | 42 | { |
55 | | - linkType: 'WL', |
56 | | - name: '구매하기', |
57 | | - linkMobile: 'https://m.example.com/product1', |
| 43 | + imageId: imageId, |
| 44 | + commerce: { |
| 45 | + title: '프리미엄 블루투스 스피커', |
| 46 | + regularPrice: 129000, |
| 47 | + discountPrice: 99000, |
| 48 | + discountRate: 23, |
| 49 | + }, |
| 50 | + buttons: [ |
| 51 | + { |
| 52 | + linkType: 'WL', |
| 53 | + name: '구매하기', |
| 54 | + linkMobile: 'https://example.com', |
| 55 | + linkPc: 'https://example.com', |
| 56 | + }, |
| 57 | + ], |
58 | 58 | }, |
59 | | - ], |
60 | | - }, |
61 | | - { |
62 | | - additionalContent: '오늘 출발', |
63 | | - imageId: '업로드한 상품 이미지 ID', |
64 | | - commerce: { |
65 | | - title: '상품명 2', |
66 | | - regularPrice: '50000', |
67 | | - discountPrice: '40000', |
68 | | - discountRate: '20', |
69 | | - }, |
70 | | - buttons: [ |
71 | 59 | { |
72 | | - linkType: 'WL', |
73 | | - name: '구매하기', |
74 | | - linkMobile: 'https://m.example.com/product2', |
| 60 | + imageId: imageId, |
| 61 | + commerce: { |
| 62 | + title: '노이즈캔슬링 헤드폰', |
| 63 | + regularPrice: 249000, |
| 64 | + discountPrice: 199000, |
| 65 | + discountFixed: 50000, |
| 66 | + }, |
| 67 | + buttons: [ |
| 68 | + { |
| 69 | + linkType: 'WL', |
| 70 | + name: '구매하기', |
| 71 | + linkMobile: 'https://example.com', |
| 72 | + linkPc: 'https://example.com', |
| 73 | + }, |
| 74 | + ], |
75 | 75 | }, |
76 | 76 | ], |
77 | 77 | }, |
78 | | - { |
79 | | - imageId: '업로드한 상품 이미지 ID', |
80 | | - commerce: { |
81 | | - title: '상품명 3', |
82 | | - regularPrice: '15000', |
| 78 | + }, |
| 79 | + }, |
| 80 | + }) |
| 81 | + .then(res => console.log(res)); |
| 82 | + |
| 83 | + // 전체 필드 단건 발송 예제 (adult, additionalContent, carousel head/list 전체/tail) |
| 84 | + messageService |
| 85 | + .send({ |
| 86 | + to: '수신번호', |
| 87 | + from: '계정에서 등록한 발신번호 입력', |
| 88 | + type: 'BMS_FREE', |
| 89 | + kakaoOptions: { |
| 90 | + pfId: '연동한 비즈니스 채널의 pfId', |
| 91 | + bms: { |
| 92 | + targeting: 'I', |
| 93 | + chatBubbleType: 'CAROUSEL_COMMERCE', |
| 94 | + adult: false, |
| 95 | + additionalContent: '🔥 이번 주 한정 특가!', |
| 96 | + carousel: { |
| 97 | + head: { |
| 98 | + header: '홍길동님을 위한 추천', |
| 99 | + content: '최근 관심 상품과 비슷한 아이템을 모았어요!', |
| 100 | + imageId: imageId, |
| 101 | + linkMobile: 'https://example.com/recommend', |
83 | 102 | }, |
84 | | - buttons: [ |
| 103 | + list: [ |
| 104 | + { |
| 105 | + imageId: imageId, |
| 106 | + commerce: { |
| 107 | + title: '에어프라이어 대용량 5.5L', |
| 108 | + regularPrice: 159000, |
| 109 | + discountPrice: 119000, |
| 110 | + discountRate: 25, |
| 111 | + }, |
| 112 | + additionalContent: '⚡ 무료배송', |
| 113 | + imageLink: 'https://example.com/airfryer', |
| 114 | + buttons: [ |
| 115 | + { |
| 116 | + linkType: 'WL', |
| 117 | + name: '지금 구매', |
| 118 | + linkMobile: 'https://example.com', |
| 119 | + linkPc: 'https://example.com', |
| 120 | + }, |
| 121 | + { |
| 122 | + linkType: 'AL', |
| 123 | + name: '앱에서 보기', |
| 124 | + linkMobile: 'https://example.com', |
| 125 | + linkAndroid: 'examplescheme://path', |
| 126 | + linkIos: 'examplescheme://path', |
| 127 | + }, |
| 128 | + ], |
| 129 | + coupon: { |
| 130 | + title: '10000원 할인 쿠폰', |
| 131 | + description: '첫 구매 고객 전용 쿠폰입니다.', |
| 132 | + linkMobile: 'https://example.com/coupon', |
| 133 | + }, |
| 134 | + }, |
85 | 135 | { |
86 | | - linkType: 'WL', |
87 | | - name: '구매하기', |
88 | | - linkMobile: 'https://m.example.com/product3', |
| 136 | + imageId: imageId, |
| 137 | + commerce: { |
| 138 | + title: '스마트 로봇청소기 프로', |
| 139 | + regularPrice: 499000, |
| 140 | + discountPrice: 399000, |
| 141 | + discountFixed: 100000, |
| 142 | + }, |
| 143 | + buttons: [ |
| 144 | + { |
| 145 | + linkType: 'WL', |
| 146 | + name: '상세 보기', |
| 147 | + linkMobile: 'https://example.com', |
| 148 | + linkPc: 'https://example.com', |
| 149 | + }, |
| 150 | + ], |
89 | 151 | }, |
90 | 152 | ], |
| 153 | + tail: { |
| 154 | + linkMobile: 'https://example.com/all-products', |
| 155 | + }, |
91 | 156 | }, |
92 | | - ], |
93 | | - // tail: 캐러셀 하단에 "더보기" 링크 (선택) |
94 | | - tail: { |
95 | | - linkMobile: 'https://m.example.com/all-products', |
96 | | - linkPc: 'https://example.com/all-products', // 선택 |
97 | 157 | }, |
98 | 158 | }, |
99 | | - }, |
100 | | - }, |
101 | | - }) |
102 | | - .then(res => console.log(res)); |
| 159 | + }) |
| 160 | + .then(res => console.log(res)); |
103 | 161 |
|
104 | | -// head 없이 상품만 발송하는 예제 |
105 | | -messageService |
106 | | - .sendOne({ |
107 | | - to: '수신번호', |
108 | | - from: '계정에서 등록한 발신번호 입력', |
109 | | - type: 'BMS_FREE', |
110 | | - kakaoOptions: { |
111 | | - pfId: '연동한 비즈니스 채널의 pfId', |
112 | | - bms: { |
113 | | - targeting: 'I', |
114 | | - chatBubbleType: 'CAROUSEL_COMMERCE', |
115 | | - carousel: { |
116 | | - list: [ |
117 | | - { |
118 | | - imageId: '업로드한 상품 이미지 ID', |
119 | | - commerce: { |
120 | | - title: '한정 특가 상품 A', |
121 | | - regularPrice: '100000', |
122 | | - discountPrice: '70000', |
123 | | - discountRate: '30', |
124 | | - }, |
125 | | - buttons: [ |
126 | | - { |
127 | | - linkType: 'WL', |
128 | | - name: '바로 구매', |
129 | | - linkMobile: 'https://m.example.com/productA', |
| 162 | + // 단건 예약 발송 예제 |
| 163 | + messageService |
| 164 | + .send( |
| 165 | + { |
| 166 | + to: '수신번호', |
| 167 | + from: '계정에서 등록한 발신번호 입력', |
| 168 | + type: 'BMS_FREE', |
| 169 | + kakaoOptions: { |
| 170 | + pfId: '연동한 비즈니스 채널의 pfId', |
| 171 | + bms: { |
| 172 | + targeting: 'I', |
| 173 | + chatBubbleType: 'CAROUSEL_COMMERCE', |
| 174 | + carousel: { |
| 175 | + list: [ |
| 176 | + { |
| 177 | + imageId: imageId, |
| 178 | + commerce: { |
| 179 | + title: '겨울 롱패딩 - 그레이', |
| 180 | + regularPrice: 299000, |
| 181 | + discountPrice: 199000, |
| 182 | + discountRate: 33, |
| 183 | + }, |
| 184 | + buttons: [ |
| 185 | + { |
| 186 | + linkType: 'WL', |
| 187 | + name: '바로 구매', |
| 188 | + linkMobile: 'https://example.com/padding-gray', |
| 189 | + }, |
| 190 | + ], |
| 191 | + }, |
| 192 | + { |
| 193 | + imageId: imageId, |
| 194 | + commerce: { |
| 195 | + title: '겨울 롱패딩 - 블랙', |
| 196 | + regularPrice: 299000, |
| 197 | + discountPrice: 199000, |
| 198 | + discountRate: 33, |
| 199 | + }, |
| 200 | + buttons: [ |
| 201 | + { |
| 202 | + linkType: 'WL', |
| 203 | + name: '바로 구매', |
| 204 | + linkMobile: 'https://example.com/padding-black', |
| 205 | + }, |
| 206 | + ], |
| 207 | + }, |
| 208 | + ], |
| 209 | + tail: { |
| 210 | + linkMobile: 'https://example.com/winter-sale', |
130 | 211 | }, |
131 | | - ], |
132 | | - }, |
133 | | - { |
134 | | - imageId: '업로드한 상품 이미지 ID', |
135 | | - commerce: { |
136 | | - title: '한정 특가 상품 B', |
137 | | - regularPrice: '80000', |
138 | | - discountPrice: '60000', |
139 | | - discountRate: '25', |
140 | 212 | }, |
141 | | - buttons: [ |
142 | | - { |
143 | | - linkType: 'WL', |
144 | | - name: '바로 구매', |
145 | | - linkMobile: 'https://m.example.com/productB', |
146 | | - }, |
147 | | - ], |
148 | 213 | }, |
149 | | - ], |
150 | | - tail: { |
151 | | - linkMobile: 'https://m.example.com/sale', |
152 | 214 | }, |
153 | 215 | }, |
154 | | - }, |
155 | | - }, |
156 | | - }) |
157 | | - .then(res => console.log(res)); |
| 216 | + {scheduledDate: '2025-12-08 00:00:00'}, |
| 217 | + ) |
| 218 | + .then(res => console.log(res)); |
| 219 | + }); |
0 commit comments