메이플스토리 SoapApi (2)
고객센터에서는 없다고 잡아떼더만 찾으니 나오더군요
먼저, soap api 를 사용하기 위해서 제공하는 xml코드를 분석하기로 하였습니다.
사진을 보면 위아래 두개가 있는거로 보입니다.
느낌상 위에가 값을 보낼 때 사용을 하는것이고,
아래가 데이터를 받아올 때 보여주는 값 인것으로 확인되니 위에것을 먼저 분석하였습니다.
POST /soap/maplestory.asmx HTTP/1.1
Host: api.maplestory.nexon.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://gnxsoap.nexon.com/soap/GetCharacterInfoByAccountID"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetCharacterInfoByAccountID xmlns="http://gnxsoap.nexon.com/soap/">
<AccountID>int</AccountID>
</GetCharacterInfoByAccountID>
</soap:Body>
</soap:Envelope>
보아하니
<?xml version="1.0" encoding="utf-8"?>
윗부분이 Header 부분이고, 아래부분이 Request 할때 보내는 값 인걸로 확인이 됩니다.
그런데 여기서 문제가 발생합니다.
다른 soap api 통신 예제를 보면 url에" ~~?wsdl" 이라는 단어가 보이게 되는데 여기서는 찾을수가 없었습니다.
한참을 고민하다가 한가지 시도를 해보게 됩니다.
Host의 api.maplestory.nexon.com
위 POST와 HTTP/1.1 사이의 /soap/maplestory.asmx
이 두가지를 묶고 ?wsdl 을 붙히기로 하였습니다.
http://api.maplestory.nexon.com/soap/maplestory.asmx?wsdl
위와같은 url이 나오게 되었습니다.
자 그럼 이제 이걸가지고 지지고 볶고 해봅시다.
SoapUI 를 설치하였습니다.
설치 후 new SoapApi 를 클릭 후 위에서 알아낸 url을 사용하였습니다.
이쯤되니 좀 황홀해집니다.
새로운 reques 를 만들고 테스트케이스로 값을 집어넣으니
이런 값을 반환해주던군요.
이 값을 이용하면 될거같습니다.
자 그럼 이제 폭풍코딩을 하기전에 nodejs 에서 SoapApi를 사용하기 위해서 easy-soap-request 를 설치해줍시다
npm i --save easy-soap-request
이제 이 모듈을 이용해 봅시다.
먼저 베이스를 잡아줍시다.
let xml =
`<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetCharacterInfoByAccountID xmlns="http://gnxsoap.nexon.com/soap/">
<AccountID> AccountID[32bit Int Data] </AccountID>
</GetCharacterInfoByAccountID>
</soap:Body>
</soap:Envelope>
`
const url = "http://api.maplestory.nexon.com/soap/maplestory.asmx?wsdl";
const sampleHeaders = {
'Content-Type':'text/xml; charset=utf-8',
'Content-Length':xml.length,
'SOAPAction':"http://gnxsoap.nexon.com/soap/GetCharacterInfoByAccountID"
};
위 코드가 베이스가되는 코드 입니다.
알아낸 url을 넣어주고,
xml에 있던 헤더를 정리하여 sampleHeaders에 넣어줍니다.
추가로 xml에 request 할때 보낼 xml을 적어줍니다.
const getUserData = async() => {
const { response } = await soapRequest({
url : url,
headers : sampleHeaders,
xml : xml,
timeout : 1000
});
const { header, body, statusCode } = response;
console.log(`header : ${header}`);
console.log(`body : ${body}`);
console.log(`statusCode : ${statusCode}`);
}
이 코드는 비동기로 처리를 해 주셔야 합니다.
비동기다보니 해당 코드에 xml-json과 콜백함수를 적용하면
const getUserData = async(callBack) => {
try{
const { response } = await soapRequest({
url : url,
headers : sampleHeaders,
xml : xml,
timeout : 1000
});
const { header, body, statusCode } = response;
console.log(`header : ${header}`);
console.log(`body : ${body}`);
console.log(`statusCode : ${statusCode}`);
var xmlToJson = convert.xml2json(body, {compact: true, spaces: 4});
callBack(xmlToJson);
} catch (error){
console.error(error);
}
}
getUserData( (userXML) => {
res.json(userXML);
});
출처 : medium.com/better-programming/how-to-perform-soap-requests-with-node-js-4a9627070eb6
이런식으로 작성이 가능합니다.
이 코드를 동작시켜보니 오류가 발생하였습니다.
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
흠... 어디서 문제가 된 것인지 한번 찾아보았더니
getUserData( (userXML) => {
res.json(userXML);
});
여기 이 콜백함수에서 res.json부분에 오류가 있었습니다.
이때부터 폭풍 구글링을 시작하였습니다.
도대체 어디서 중복이 된건가 계속 찾아다녔는데 getUserData() 밖에 보니 res.end가 있었습니다.. 이부분을 삭제하고 실행하니 오류는 나지 않았습니다.
뭐 이런 거지같은...
문제가 뭔지 찾아봤더니 json으로 변경하고 parse를 안해줫더군요
getUserData( (userXML) => {
res.json(JSON.parse(userXML));
});
이렇게 해주니 정상적으로 잘 나옵니다.
이제 여기서 제가 필요한 필드만 한번 불러와 보겠습니다.
getUserData( (userXML) => {
const jsonData = JSON.parse(userXML)['soap:Envelope']['soap:Body']['GetCharacterInfoByAccountIDResponse']['GetCharacterInfoByAccountIDResult']['diffgr:diffgram']['NewDataSet']['UserInfo'];
console.log("##############################################");
console.log(jsonData.AvatarImgURL._text);
console.log(jsonData.WorldName._text);
console.log(jsonData.CharacterName._text);
console.log(jsonData.Lev._text);
console.log(jsonData.Exp._text);
console.log(jsonData.JobDetail._text);
console.log(jsonData.TotRank._text);
console.log(jsonData.WorldRank._text);
console.log("##############################################");
res.json(jsonData);
});
이런식으로 작성을 하여 필요한 정보를 모두 불러왔습니다.
이놈의 메이플SoapApi... 중간에 특수문자때문에 고생좀 했네요
결과는 데이터 잘 가져와집니다.
저의 다른 블로그 ngyu.tistory.com에서 가져옴을 알립니다.
이전 글이 궁금하시다면?!
2020/12/08 - [공부/JavaScript] - [Node.js] 메이플스토리 api 사용하기(1) - 크롤링, SoapApi
'JavaScript > Nodejs' 카테고리의 다른 글
[NodeJS] 로그인/회원가입 구현하기 (로그인편) (4) | 2021.05.20 |
---|---|
[NodeJS] 로그인/회원가입 구현하기 ( 회원가입편 ) (3) | 2021.05.20 |
[Node.js] 콜백지옥 벗어나기 async / await (1) | 2021.02.06 |
[Node.js] 콜백지옥 벗어나기 promise (0) | 2021.02.03 |
[Node.js] 메이플스토리 api 사용하기(1) - 크롤링, SoapApi (0) | 2020.12.16 |