typescript
import {
IExecuteFunctions,
INodeExecutionData,
INodeType,
INodeTypeDescription,
IHttpRequestOptions,
NodeOperationError,
} from 'n8n-workflow';
export class AligoSms implements INodeType {
description: INodeTypeDescription = {
displayName: '알리고 SMS',
name: 'aligoSms',
icon: 'file:aligoSms.svg',
group: ['communication'],
version: 1,
description: '알리고 API를 통해 SMS를 발송합니다',
defaults: { name: 'SMS 발송' },
inputs: ['main'],
outputs: ['main'],
credentials: [{ name: 'aligoApi', required: true }],
properties: [
{
displayName: '수신 번호',
name: 'receiverPhone',
type: 'string',
default: '',
required: true,
placeholder: '01098765432',
description: '수신자 전화번호 (숫자만, 다수는 쉼표로 구분)',
},
{
displayName: '메시지 내용',
name: 'message',
type: 'string',
typeOptions: { rows: 4 },
default: '',
required: true,
description: '발송할 SMS 내용 (한글 45자/영문 90자 이하)',
},
],
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const returnData: INodeExecutionData[] = [];
for (let i = 0; i < items.length; i++) {
try {
const credentials = await this.getCredentials('aligoApi');
const receiverPhone = this.getNodeParameter('receiverPhone', i) as string;
const message = this.getNodeParameter('message', i) as string;
const requestOptions: IHttpRequestOptions = {
method: 'POST',
url: 'https://apis.aligo.in/send/',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
key: credentials.apiKey as string,
user_id: credentials.userId as string,
sender: credentials.senderPhone as string,
receiver: receiverPhone,
msg: message,
testmode_yn: 'N',
}).toString(),
};
const response = await this.helpers.httpRequest(requestOptions);
const result = typeof response === 'string' ? JSON.parse(response) : response;
if (result.result_code !== '1') {
throw new NodeOperationError(
this.getNode(),
`SMS 발송 실패: ${result.message} (코드: ${result.result_code})`,
{ itemIndex: i }
);
}
returnData.push({
json: {
success: true,
msgId: result.msg_id,
receiver: receiverPhone,
message: message,
remainingCount: result.remain_count,
sentAt: new Date().toISOString(),
},
pairedItem: { item: i },
});
} catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: { success: false, error: (error as Error).message },
pairedItem: { item: i },
});
continue;
}
throw error;
}
}
return [returnData];
}
}