사전 준비하기
각 버전별 오프라인 API 사용 시 사전 준비 사항을 확인하세요.
오프라인 API v4 사용 시
온라인 API v4나 온라인 API v3, 오프라인 API v4를 호출하려면 HTTP 요청 헤더에 자격 증명 정보(credentials)를 명시해야 합니다.
가맹점 가입 후 가맹점 센터에서 채널 ID와 채널 비밀키를 얻을 수 있는데, 이를 이용해 자격 증명 정보를 생성할 수 있습니다.
샌드박스 계정을 신청해 샌드박스용 채널 ID와 채널 비밀키를 신청하여 테스트해볼 수 있습니다.
이미 가맹점으로 가입해 발급 받은 채널 ID와 채널 비밀키가 있다면, 별도의 신청없이 샌드박스 환경에 이를 바로 사용할 수 있습니다.
자격 증명 정보를 명시하는 HTTP 요청 헤더는 다음과 같습니다.
X-LINE-ChannelIdX-LINE-AuthorizationX-LINE-Authorization-Nonce
X-LINE-ChannelId 헤더에는 채널 ID 값을 입력하고 X-LINE-Authorization-Nonce 헤더에는 UUID v1나 v4 또는 타임스탬프와 같은 임시 토큰 값을 입력하세요.
X-LINE-Authorization 헤더에 입력하는 값은 채널 비밀키와 대상 메시지를 이용해 HMAC 방식으로 생성한 MAC(message authentication code)를 Base64 방식으로 인코딩한 값입니다. 호출하는 API의 HTTP 메서드에 따라 MAC 생성용 메시지는 다음과 같이 구성하세요.
| HTTP 메서드 | MAC 생성용 메시지 |
|---|---|
| GET | 채널 비밀키 + API 경로(apiPath) + 쿼리 스트링(queryString) + 임시 토큰(nonce) |
| POST | 채널 비밀키 + API 경로(apiPath) + 요청 본문 + 임시 토큰(nonce) |
다음은 HTTP 요청 헤더에 자격 정보를 추가하여 온라인 API를 호출할 수 있게 해주는 코드 예제입니다.
아래 코드 예제 중
handleBigInteger()함수는 트랜잭션 ID 값을 다룰 때 필요합니다. 트랜잭션 ID와handleBigInteger()함수에 대한 자세한 내용은 온라인 API v4나 오프라인 API v4의 트랜잭션 ID 절 설명을 참고하세요.
const crypto = require("crypto");
function signKey(clientKey, msg) {
const encoder = new TextEncoder();
return crypto
.createHmac("sha256", encoder.encode(clientKey))
.update(encoder.encode(msg))
.digest("base64");
}
async function requestLINEPayAPI({
method,
baseUrl = "https://sandbox-api-pay.line.me",
apiPath,
queryString = "",
data = null,
signal = null,
}) {
const nonce = crypto.randomUUID();
let signature = "";
// 각 방식(method)별로 MAC 생성
if (method === "GET") {
signature = signKey(
YOUR_CHANNEL_SECRET,
YOUR_CHANNEL_SECRET + apiPath + queryString + nonce
);
} else if (method === "POST") {
signature = signKey(
YOUR_CHANNEL_SECRET,
YOUR_CHANNEL_SECRET + apiPath + JSON.stringify(data) + nonce
);
}
const headers = {
"X-LINE-ChannelId": YOUR_CHANNEL_ID,
"X-LINE-Authorization": signature,
"X-LINE-Authorization-Nonce": nonce,
};
const response = await fetch(
`${baseUrl}${apiPath}${queryString !== "" ? "&" + queryString : ""}`,
{
method: method,
headers: {
"Content-Type": "application/json",
...headers,
},
body: data ? JSON.stringify(data) : null,
signal: signal,
}
);
const processedResponse = handleBigInteger(await response.text());
return processedResponse;
}
오프라인 API v2.x 사용 시
오프라인 API v2나 오프라인 API v2.4 사용 시 다음을 준비하세요.
서버 허용 목록 설정하기
오프라인 API v2나 오프라인 API v2.4를 사용하려면 가맹점 서버가 샌드박스에 접근할 수 있도록 설정해야 합니다. 가맹점 센터는 결제서버IP 관리라는 이름의 메뉴로 LINE Pay API를 호출할 수 있는 서버 허용 목록(allowlist)을 관리하고 있습니다. 다음과 같이 가맹점 서버의 IP 주소를 등록하세요.
샌드박스 가맹점이 샌드박스를 사용하여 LINE Pay API를 테스트할 때는 서버 허용 목록 설정하지 않아도 됩니다.
-
가맹점 센터에 로그인하세요.
-
왼쪽 메뉴에서 [개발자 도구 > 결제서버IP 관리]를 선택하세요.
-
결제서버IP 관리 페이지에서 다음과 같이 가맹점 서버 IP 주소와 IP 주소 마스크 값을 입력하고, 등록 버튼을 누르세요.

-
(선택) 테스트하려는 가맹점 서버가 둘 이상이면, 우측 상단의 행추가 버튼을 눌러 행을 추가하고, 3 번 작업을 필요한 만큼 반복합니다.
오프라인 API v2.x 자격 증명 처리하기
오프라인 API v2나 오프라인 API v2.4를 사용하려면 API 호출 시 HTTP 요청 헤더에 자격 증명 정보(credentials)를 명시해야 합니다.
가맹점 가입 후 가맹점 센터에서 채널 ID와 채널 비밀키를 얻을 수 있는데, 이 값을 해당 HTTP 요청 헤더에 입력해야 합니다.
샌드박스 계정을 신청해 샌드박스용 채널 ID와 채널 비밀키를 신청하여 테스트해볼 수 있습니다.
이미 가맹점으로 가입해 발급 받은 채널 ID와 채널 비밀키가 있다면, 별도의 신청없이 샌드박스 환경에 이를 바로 사용할 수 있습니다.
자격 증명 정보를 명시하는 HTTP 요청 헤더는 다음과 같습니다.
X-LINE-ChannelIdX-LINE-ChannelSecret
오프라인 API를 호출할 때 가맹점 기기에 대한 정보를 HTTP 요청 헤더에 포함할 수도 있습니다. 이에 대한 자세한 설명은 오프라인 API v2나 오프라인 API v2.4의 API 요청 헤더를 참고하세요.
X-LINE-ChannelId 헤더에는 채널 ID 값을 입력하고 X-LINE-ChannelSecret 헤더에는 채널 비밀키를 입력하세요. 다음은 HTTP 요청 헤더에 자격 정보를 추가하여 오프라인 API를 호출할 수 있게 해주는 코드 예제입니다.
아래 코드 예제 중
handleBigInteger()함수는 트랜잭션 ID 값을 다룰 때 필요합니다. 트랜잭션 ID와handleBigInteger()함수에 대한 자세한 내용은 오프라인 API v2나 오프라인 API v2.4의 트랜잭션 ID절을 참고하세요.
const crypto = require("crypto");
async function requestLINEPayAPIv2({
method,
baseUrl = "https://sandbox-api-pay.line.me",
apiPath,
queryString = "",
data = null,
signal = null,
}) {
const headers = {
"X-LINE-ChannelId": YOUR_CHANNEL_ID,
"X-LINE-ChannelSecret": YOUR_CHANNEL_SECRET,
"X-LINE-MerchantDeviceProfileId": YOUR_DEVICE_PROFILE_ID,
"X-LINE-MerchantDeviceType": YOUR_DEVICE_TYPE,
};
const response = await fetch(
`${baseUrl}${apiPath}${queryString !== "" ? "&" + queryString : ""}`,
{
method: method,
headers: {
"Content-Type": "application/json",
...headers,
},
body: data ? JSON.stringify(data) : null,
signal: signal,
}
);
const processedResponse = handleBigInteger(await response.text());
return processedResponse;
}