연말정산 간소화 사이트 API 사용

Ad


이 글은 2011-12-21 작성된 글입니다.

연말정산 간소화 사이트에서 다운로드 받은 PDF 파일을 검증하고 데이터를 읽어내는 API를 사용한 간단한 예제 입니다.

데이터 처리를 편하게 하기위해 객체에 XML자료를 맵핑시켜 사용하였습니다.

아래 코드가 동작하려면 연말정산 간소화 사이트에서 배포하는 API설치파일의 설치가 필요합니다.

간단한 코드들로 쓰여져 있어 설명할 부분이 많지 않습니다.

아래 예제 코드는 연말정산 간소화 사이트에서 제공하는 샘플코드를 변형한 것입니다.

주의

이 글은 2011-12-21 작성된 글입니다.

현재 문서 구조와 다를 수 있습니다.

지원하지 않는 기능이 있을 수 있고, 변경된 기능 역시 있을 수 있습니다.

Code

YesoneHelper class

using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Runtime.InteropServices;
using System.Xml.Serialization;
using System.IO;
using System.Xml;

namespace NTS_Reader_CS
{
    public class YesoneHelper
    {
        private static readonly string FILE_NAME = @"YesoneAPISetup_v1.2.exe";

        private YesoneHelper(){ }

        private static string DownloadAPI()
        {
            string strMsg = string.Empty;
            // 웹서버에서 파일을 배포하는 것으로 합니다.
            System.Diagnostics.Process.Start(@"http://localhost/" + FILE_NAME);
            strMsg = "다운로드된 파일을 설치 후 다시 진행하세요.";
            return strMsg;
        }

        public static bool Validate_연말정산_PFD(string filePath, string password, out string strMsg)
        {
            bool bResult = false;
            long result = 0L;

            strMsg = string.Empty;

            if (string.IsNullOrEmpty(filePath))
            {
                strMsg = "파일경로가 없습니다.";
                bResult = false;
            }
            else
            {
                try
                {
                    result = Yesone.YesoneUtil.asdtstpdf_setup_proxy_setting(0, 1, '1', 1, '1', '1', '1');
                    result = Yesone.YesoneUtil.asdtstpdf_verify_timestamp_with_file(password, null, filePath, 15, 0, null);
                }
                catch
                {
                    // 파일 다운로드
                    strMsg = "간소화 사이트 API 프로그램이 설치되지 않았습니다.";
                    System.Windows.Forms.DialogResult dialogResult = System.Windows.Forms.MessageBox.Show(strMsg + "rnrn파일을 다운로드 하시겠습니까?", "알림", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
                    if (dialogResult == System.Windows.Forms.DialogResult.Yes)
                    {
                        strMsg = DownloadAPI();
                    }

                    bResult = false;
                }

                bResult = ValidateFile(result, filePath, out strMsg);
            }
            return bResult;
        }

        /// <summary>
        /// 연말정산 간소화 사이트에서 다운로드 받은 PDF 파일을 로드한다.
        /// </summary>
        /// <param name="filePath">PDF파일 경로</param>
        /// <param name="password">PDF파일 비밀번호(PDF저장시 비밀번호를 설정한 경우)</param>
        /// <param name="strMsg">처리메세지</param>
        /// <returns>추출데이터</returns>
        public static Yesone.Yesone GetData_연말정산_PDF(string filePath, string password, out string strMsg)
        {
            string strTmp = string.Empty;
            return GetData_연말정산_PDF(filePath, password, out strMsg);
        }

        /// <summary>
        /// 연말정산 간소화 사이트에서 다운로드 받은 PDF 파일을 로드한다.
        /// </summary>
        /// <param name="filePath">PDF파일 경로</param>
        /// <param name="password">PDF파일 비밀번호(PDF저장시 비밀번호를 설정한 경우)</param>
        /// <param name="strMsg">처리메세지</param>
        /// <param name="strXML">추출XML</param>
        /// <returns>추출데이터</returns>
        public static Yesone.Yesone GetData_연말정산_PDF(string filePath, string password, out string strMsg, out string strXML)
        {
            long result = 0;
            Yesone.Yesone oData = new Yesone.Yesone(); // PDF 파일 데이터

            strMsg = string.Empty;
            strXML = "XML";

            if (string.IsNullOrEmpty(filePath))
            {
                strMsg = "파일경로가 없습니다.";
                return oData;
            }

            try
            {
                result = Yesone.YesoneUtil.asdtstpdf_setup_proxy_setting(0, 1, '1', 1, '1', '1', '1');
                result = Yesone.YesoneUtil.asdtstpdf_verify_timestamp_with_file(password, null, filePath, 15, 0, null);
            }
            catch
            {
                // 파일 다운로드
                strMsg = "간소화 사이트 API 프로그램이 설치되지 않았습니다.";
                System.Windows.Forms.DialogResult dialogResult = System.Windows.Forms.MessageBox.Show(strMsg + "rnrn파일을 다운로드 하시겠습니까?", "알림", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
                if (dialogResult == System.Windows.Forms.DialogResult.Yes)
                {
                    strMsg = DownloadAPI();
                }

                return oData;
            }

            if (!ValidateFile(result, filePath, out strMsg))
            {
                return oData;
            }

            strMsg = string.Empty;

            #region 파일로드

            int fileSize = Yesone.YesoneFile.NTS_GetFileSize(filePath, password, strXML, 0);

            if (fileSize == -1)
            {
                strMsg = "파일이 없거나 손상된 PDF 파일입니다.";
            }
            else if (fileSize == -2)
            {
                strMsg = "비밀번호가 틀립니다.";
            }
            else if (fileSize == 0)
            {
                strMsg = "국세청에서 발급된 전자문서가 아닙니다.";
            }
            else if (fileSize > 0)
            {
                byte[] buf = new byte[fileSize];
                fileSize = Yesone.YesoneFile.NTS_GetFileBuf(filePath, password, strXML, buf, 0);
                if (fileSize > 0)
                {
                    string strBuf = Encoding.UTF8.GetString(buf);
                    strBuf.Replace("n", "rn");
                    strXML = strBuf;
                    oData = GetData(strBuf);        // XML => object

                    strMsg = string.Empty;
                }
            }
            else
            {
                strMsg = "파일을 읽을 수 없습니다";
            }

            #endregion

            return oData;
        }

        /// <summary>
        /// XML 자료를 Object Yesone 에 맵핑한다.
        /// </summary>
        /// <param name="xml">PDF에서 추출한 XML</param>
        /// <returns>Yesone</returns>
        private static Yesone.Yesone GetData(string xml)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);

            byte[] xmlBytes = Encoding.UTF8.GetBytes(xml);
            Yesone.Yesone _yesone = new Yesone.Yesone();
            XmlSerializer serializer = new XmlSerializer(_yesone.GetType());

            StringReader reader = new StringReader(doc.OuterXml);
            _yesone = (Yesone.Yesone)serializer.Deserialize(reader);

            return _yesone;
        }

        /// <summary>
        /// 로드된 PDF 파일의 유효성 검사결과 처리
        /// </summary>
        private static bool ValidateFile(long result, string filePath, out string strMsg)
        {
            strMsg = string.Empty;
            bool bResult = false;

            switch (result)
            {
                case 2501:
                    strMsg = String.Format("파일이 변조 되지 않았습니다. [{0}]", filePath);
                    bResult = true;
                    break;
                case 2502:
                    strMsg = String.Format("TSA 증명서의 기한 마감. [{0}]", filePath);
                    break;
                case 2503:
                    strMsg = String.Format("TSA 증명서가 유효하지 않습니다. [{0}]", filePath);
                    break;
                case 2504:
                    strMsg = String.Format("TSA 증명서가 실효되었습니다. [{0}]", filePath);
                    break;
                case 2505:
                    strMsg = String.Format("CRL(인증서폐지목록)의 기한이 마감되었습니다. [{0}]", filePath);
                    break;
                case 2506:
                    strMsg = String.Format("CRL(인증서폐지목록)의 체크에 실패하였습니다. [{0}]", filePath);
                    break;
                case 2507:
                    strMsg = String.Format("CA 인증서 체크에 실패하였습니다. [{0}]", filePath);
                    break;
                case 2508:
                    strMsg = String.Format("파일이 수정(변조)되었습니다. [{0}]", filePath);
                    break;
                case 2509:
                    strMsg = String.Format("파일이 수정(변조)되었습니다. [{0}]", filePath);
                    break;
                case 1101:
                    strMsg = String.Format("파일을 열수 없습니다. [{0}]", filePath);
                    break;
                case 3453:
                    strMsg = String.Format("User Password 가 틀립니다. [{0}]", filePath);
                    break;
                case 3454:
                    strMsg = String.Format("Owner Password 가 틀립니다. [{0}]", filePath);
                    break;
                case 3200:
                    strMsg = String.Format("지정된 입력 파일에 타임 스탬프는 존재하지 않습니다. [{0}]", filePath);
                    break;
                case 1202:          // 프록시의 사용자 인증에 실패
                    strMsg = String.Format("프록시의 사용자 인증에 실패");
                    break;
                case 1203:          // 프록시의 사용자 인증을 캔슬
                    strMsg = String.Format("프록시의 사용자 인증을 취소");
                    break;
                case 4060:          // 통신 에러
                    strMsg = String.Format("통신 에러");
                    break;
                case 2530:
                default:
                    strMsg = String.Format("진본성 검증에 실패 하였습니다. error - [{0}]", result);
                    break;
            }

            return bResult;
        }

        private Yesone.YesoneFormTitle GetYesoneFormTitle(string yesoneFormCode)
        {
            Yesone.YesoneFormTitle _formTitle = Yesone.YesoneFormTitle.해당없음;
            switch (yesoneFormCode)
            {
                case "A101Y":
                case "A101M":
                    _formTitle = Yesone.YesoneFormTitle.보험료;
                    break;
                case "B101Y":
                case "B101M":
                    _formTitle = Yesone.YesoneFormTitle.의료비;
                    break;
                case "C101Y":
                case "C101M":
                    _formTitle = Yesone.YesoneFormTitle.교육비_유초중고_대학_기타;
                    break;
                case "C201Y":
                    _formTitle = Yesone.YesoneFormTitle.교육비_직업훈련비;
                    break;
                case "C301Y":
                case "C301M":
                    _formTitle = Yesone.YesoneFormTitle.교육비_교복구입비;
                    break;
                case "D101Y":
                case "D101M":
                    _formTitle = Yesone.YesoneFormTitle.개인연금저축;
                    break;
                case "E101Y":
                case "E101M":
                    _formTitle = Yesone.YesoneFormTitle.연금저축;
                    break;
                case "F101Y":
                case "F101M":
                    _formTitle = Yesone.YesoneFormTitle.퇴직연금;
                    break;
                case "G101Y":
                case "G101M":
                    _formTitle = Yesone.YesoneFormTitle.신용카드;
                    break;
                case "G201M":   // 2010
                case "G202M":   // 2011
                    _formTitle = Yesone.YesoneFormTitle.현금영수증;
                    break;
                case "G301Y":
                case "G301M":
                    _formTitle = Yesone.YesoneFormTitle.직불카드;
                    break;
                case "J101Y":
                case "J101M":
                    _formTitle = Yesone.YesoneFormTitle.주택임차차입금_원리금상환액;
                    break;
                case "J202Y":
                case "J202M":
                    _formTitle = Yesone.YesoneFormTitle.장기주택저당차입금_이자상환액;
                    break;
                case "J301Y":
                case "J301M":
                    _formTitle = Yesone.YesoneFormTitle.주택마련저축;
                    break;
                case "K101M":
                    _formTitle = Yesone.YesoneFormTitle.소기업소상공인_공제부금;
                    break;
                case "L101Y":
                case "L101M":
                    _formTitle = Yesone.YesoneFormTitle.기부금;
                    break;
                case "M101Y":
                case "M101M":
                    _formTitle = Yesone.YesoneFormTitle.장기주식형저축;
                    break;

            }
            return _formTitle;
        }

        /// <summary>
        /// 입력된 일자를 기준으로 만 나이계산
        /// </summary>
        /// <param name="regNo">주민등록번호</param>
        /// <param name="today">기준일</param>
        /// <returns>만 나이</returns>
        public static int CalcAge(string regNo, string today)
        {
            int nAge = 0;

            regNo = regNo.Replace("-", string.Empty);

            if (regNo.Length == 13)
            {
                // ***************************************************************************
                // 주민등록번호
                // 1800년대 남(9) 여(0)
                // 1900년대 남(1) 여(2)
                // 2000년대 남(3) 여(4)
                // 외국인등록번호
                // 1900년대 남(5) 여(6)
                // 2000년대 남(7) 여(8)
                // ***************************************************************************
                string sGbn = regNo.Substring(6, 1);            // 주민등록번호 7번째 문자
                string sBirthDay = regNo.Substring(0, 6);       // 생년월일
                string sBirthYear = string.Empty;               // 생일 연도
                string sBirthDate = string.Empty;               // 생일 월일
                string sTodayYear = today.Substring(0, 4);      // 오늘 연도
                string sTodayDate = today.Substring(4, 4);      // 오늘 월일
                switch (sGbn)
                {
                    case "9":
                    case "0":
                        sBirthDay = "18" + sBirthDay;
                        break;
                    case "1":
                    case "2":
                        sBirthDay = "19" + sBirthDay;
                        break;
                    case "3":
                    case "4":
                        sBirthDay = "20" + sBirthDay;
                        break;
                    case "5":
                    case "6":
                        sBirthDay = "19" + sBirthDay;
                        break;
                    case "7":
                    case "8":
                        sBirthDay = "20" + sBirthDay;
                        break;
                }

                sBirthYear = sBirthDay.Substring(0, 4);
                sBirthDate = sBirthDay.Substring(4, 4);

                nAge = int.Parse(sTodayYear) - int.Parse(sBirthYear);
                if (int.Parse(sBirthDate) > int.Parse(sTodayDate)) { nAge--; }
            }
            else
            {
                throw new Exception("형식에 맞지 않는 [주민등록번호]입니다.");
            }

            return nAge;
        }

        /// <summary>
        /// 클라이언트 시간을 기준으로 현재 만 나이 계산
        /// </summary>
        /// <param name="regNo">주민등록번호</param>
        /// <returns>만 나이</returns>
        public static int CalcAge(string regNo)
        {
            string sToday = DateTime.Today.ToShortDateString().Replace("-", string.Empty);
            return CalcAge(regNo, sToday);
        }
    }

YesoneUtil class

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
 
namespace NTS_Reader_CS.Yesone
{
    class YesoneUtil
    {
        [DllImport("tstutil_client_k.dll")]
        public static extern int asdtstpdf_setup_proxy_setting(int pram1, int pram2, char pram3, int pram4, char pram5, char pram6, char pram7);
 
        [DllImport("tstutil_client_k.dll")]
        public static extern int asdtstpdf_verify_timestamp_with_file([MarshalAs(UnmanagedType.LPStr)]string pram1, [MarshalAs(UnmanagedType.LPStr)]string pram2, [MarshalAs(UnmanagedType.LPStr)]string pram3, int pram4, int pram5, [MarshalAs(UnmanagedType.LPStr)]string pram6);
    }
}

YesoneFile class

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace NTS_Reader_CS.Yesone
{
    class YesoneFile
    {
        [DllImport("ezPDFExportFile.dll")]
        public static extern int NTS_GetFileSize([MarshalAs(UnmanagedType.LPStr)]string szIn, [MarshalAs(UnmanagedType.LPStr)]string szPassword, [MarshalAs(UnmanagedType.LPStr)]string szName, int bAnsi);

        [DllImport("ezPDFExportFile.dll")]
        public static extern int NTS_GetFileBuf([MarshalAs(UnmanagedType.LPStr)]string szIn, [MarshalAs(UnmanagedType.LPStr)]string szPassword, [MarshalAs(UnmanagedType.LPStr)]string szName, [In, Out]byte[] pcBuffer, int bAnsi);
    }
}

Yesone class

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace NTS_Reader_CS.Yesone
{
    [XmlRoot(ElementName = "yesone")]
    public class Yesone
    {
        public Yesone()
        {
            this.doc = new YesoneDoc();
            this.forms = new List<YesoneForm>();
        }

        [XmlElement(ElementName = "doc")]
        public YesoneDoc doc;
        [XmlElement(ElementName = "form")]
        public List<YesoneForm> forms;

        public bool HasDoc { get { return doc != null; } }
    }

}

YesoneDoc class

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace NTS_Reader_CS.Yesone
{
    public class YesoneDoc
    {
        /// <summary>
        /// 문서종류
        /// B:기본내역(연간)
        /// D:상세내역(월별/일별)
        /// </summary>
        [XmlElement(ElementName = "doc_type")]
        public string doc_type
        {
            set { this._doc_type = value; }
            get { return this._doc_type; }
        }
        private string _doc_type;

        /// <summary>
        /// 문서종류명
        /// </summary>
        public string doc_type_desc
        {
            get
            {
                string sNm = string.Empty;
                if (!string.IsNullOrEmpty(this._doc_type))
                {
                    switch (this._doc_type.ToUpper().Trim())
                    {
                        case "B": sNm = "B:기본내역(연간)"; break;
                        case "D": sNm = "D:상세내역(월별/일별)"; break;
                        default: break;
                    }
                }
                return sNm;
            }
        }

        [XmlElement(ElementName = "seq")]
        public string seq;
        [XmlElement(ElementName = "att_year")]
        public string att_year;
    }
}

YesoneForm class

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace NTS_Reader_CS.Yesone
{
    public class YesoneForm
    {
        public YesoneForm()
        {
            this.mans = new List<Man>();
        }

        /// <summary>
        /// 서식코드
        /// 보험료(보장성,장애인보장성)    A101Y, A101M
        /// 의료비                         B101Y, B101D
        /// 교육비(유초중고,대학,기타)     C101Y, C101M
        /// 교육비(직업훈련비)             C201Y
        /// 교육비(교복구입비)             C301Y, C301M
        /// 개인연금저축                   D101Y, D101M
        /// 연금저축                       E101Y, E101M
        /// 퇴직연금                       F101Y, F101M
        /// 신용카드                       G101Y, G101M
        /// 현금영수증                     G202M             2010년:G201M, 2011년:G202M
        /// 직불카드 등(2010년 귀속부터)   G301Y, G301M
        /// 주택임차차입금 원리금상환액    J101Y, J101M
        /// 장기주택저당차입금 이자상환액  J202Y, J202M
        /// 주택마련저축                   J301Y, J301M
        /// 소기업소상공인 공제부금        K101M
        /// 기부금                         L101Y, L101D
        /// 장기주식형저축                 M101Y, M101M
        /// </summary>
        [XmlAttribute(AttributeName = "form_cd")]
        public string form_cd
        {
            set { this._form_cd = value; }
            get { return this._form_cd; }
        }
        private string _form_cd;

        /// <summary>
        /// 서식명
        /// </summary>
        public string form_title
        {
            get
            {
                string sNm = string.Empty;
                if (!string.IsNullOrEmpty(this._form_cd))
                {
                    switch (this._form_cd.ToUpper().Trim())
                    {
                        case "A101Y":
                        case "A101M":
                            sNm = "보험료(보장성,장애인보장성)"; break;
                        case "B101Y":
                        case "B101D":
                            sNm = "의료비"; break;
                        case "C101Y":
                        case "C101M":
                            sNm = ""; break;
                        case "C201Y":
                            sNm = ""; break;
                        case "C301Y":
                        case "C301M":
                            sNm = "교육비(유초중고,대학,기타)"; break;
                        case "D101Y":
                        case "D101M":
                            sNm = "개인연금저축"; break;
                        case "E101Y":
                        case "E101M":
                            sNm = "연금저축"; break;
                        case "F101Y":
                        case "F101M":
                            sNm = "퇴직연금"; break;
                        case "G101Y":
                        case "G101M":
                            sNm = "신용카드"; break;
                        case "G201M":
                        case "G202M":
                            sNm = "현금영수증"; break;
                        case "G301Y":
                        case "G301M":
                            sNm = "직불카드 등(2010년 귀속부터)"; break;
                        case "J101Y":
                        case "J101M":
                            sNm = "주택임차차입금 원리금상환액"; break;
                        case "J202Y":
                        case "J202M":
                            sNm = "장기주택저당차입금 이자상환액"; break;
                        case "J301Y":
                        case "J301M":
                            sNm = "주택마련저축"; break;
                        case "K101M":
                            sNm = "소기업소상공인 공제부금"; break;
                        case "L101Y":
                        case "L101M":
                            sNm = "기부금"; break;
                        case "M101Y":
                        case "M101M":
                            sNm = "장기주식형저축"; break;
                        default:
                            break;
                    }
                }
                sNm = this._form_cd.ToUpper().Trim() + ":" + sNm;
                return sNm;
            }
        }

        /// <summary>
        /// 시식명
        /// </summary>
        public YesoneFormTitle form_titles
        {
            get
            {
                YesoneFormTitle _formTitle = YesoneFormTitle.해당없음;
                switch (this._form_cd.ToUpper().Trim())
                {
                    case "A101Y":
                    case "A101M":
                        _formTitle = YesoneFormTitle.보험료;
                        break;
                    case "B101Y":
                    case "B101M":
                        _formTitle = YesoneFormTitle.의료비;
                        break;
                    case "C101Y":
                    case "C101M":
                        _formTitle = YesoneFormTitle.교육비_유초중고_대학_기타;
                        break;
                    case "C201Y":
                        _formTitle = YesoneFormTitle.교육비_직업훈련비;
                        break;
                    case "C301Y":
                    case "C301M":
                        _formTitle = YesoneFormTitle.교육비_교복구입비;
                        break;
                    case "D101Y":
                    case "D101M":
                        _formTitle = YesoneFormTitle.개인연금저축;
                        break;
                    case "E101Y":
                    case "E101M":
                        _formTitle = YesoneFormTitle.연금저축;
                        break;
                    case "F101Y":
                    case "F101M":
                        _formTitle = YesoneFormTitle.퇴직연금;
                        break;
                    case "G101Y":
                    case "G101M":
                        _formTitle = YesoneFormTitle.신용카드;
                        break;
                    case "G201M":   // 2010
                    case "G202M":   // 2011
                        _formTitle = YesoneFormTitle.현금영수증;
                        break;
                    case "G301Y":
                    case "G301M":
                        _formTitle = YesoneFormTitle.직불카드;
                        break;
                    case "J101Y":
                    case "J101M":
                        _formTitle = YesoneFormTitle.주택임차차입금_원리금상환액;
                        break;
                    case "J202Y":
                    case "J202M":
                        _formTitle = YesoneFormTitle.장기주택저당차입금_이자상환액;
                        break;
                    case "J301Y":
                    case "J301M":
                        _formTitle = YesoneFormTitle.주택마련저축;
                        break;
                    case "K101M":
                        _formTitle = YesoneFormTitle.소기업소상공인_공제부금;
                        break;
                    case "L101Y":
                    case "L101M":
                        _formTitle = YesoneFormTitle.기부금;
                        break;
                    case "M101Y":
                    case "M101M":
                        _formTitle = YesoneFormTitle.장기주식형저축;
                        break;

                }
                return _formTitle;
            }
        }

        [XmlElement(ElementName = "man")]
        public List<Man> mans;

        /// <summary>
        /// 자료존재여부
        /// </summary>
        public bool HasMan
        {
            get { return (this.mans != null && this.mans.Count > 0); }
        }
    }
}

YesoneFormTitle enum

using System;
using System.Collections.Generic;
using System.Text;

namespace NTS_Reader_CS.Yesone
{
    public enum YesoneFormTitle
    {
        /*
                 보험료(보장성,장애인보장성),   A101Y, A101M
                 의료비                         B101Y, B101D
                 교육비(유초중고,대학,기타)     C101Y, C101M
                 교육비(직업훈련비)             C201Y
                 교육비(교복구입비)             C301Y, C301M
                 개인연금저축                   D101Y, D101M
                 연금저축                       E101Y, E101M
                 퇴직연금                       F101Y, F101M
                 신용카드                       G101Y, G101M
                 현금영수증                     G202M             2010년:G201M, 2011년:G202M
                 직불카드 등(2010년 귀속부터)   G301Y, G301M
                 주택임차차입금 원리금상환액    J101Y, J101M
                 장기주택저당차입금 이자상환액  J202Y, J202M
                 주택마련저축                   J301Y, J301M
                 소기업소상공인 공제부금        K101M
                 기부금                         L101Y, L101D
                 장기주식형저축                 M101Y, M101M
        */
        해당없음,
        보험료,
        의료비,
        교육비_유초중고_대학_기타,
        교육비_직업훈련비,
        교육비_교복구입비,
        개인연금저축,
        연금저축,
        퇴직연금,
        신용카드,
        현금영수증,
        직불카드,
        주택임차차입금_원리금상환액,
        장기주택저당차입금_이자상환액,
        주택마련저축,
        소기업소상공인_공제부금,
        기부금,
        장기주식형저축
    }
}

Amt class

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace NTS_Reader_CS.Yesone
{
    public class Amt
    {
        /// <summary>
        /// 월별납입금액
        /// </summary>
        [XmlText()]
        public decimal amt;

        /// <summary>
        /// 납입월
        /// 01~12
        /// </summary>
        [XmlAttribute(AttributeName = "mm")]
        public string mm;

        [XmlAttribute(AttributeName = "cnt")]
        public int cnt;

        [XmlAttribute(AttributeName = "pay")]
        public decimal pay;

        /// <summary>
        /// 확정구분코드 C:확정, E:예정, N:미수록(0)
        /// </summary>
        [XmlAttribute(AttributeName = "fix_cd")]
        public string fix_cd
        {
            set { this._fix_cd = value; }
            get { return this._fix_cd; }
        }
        private string _fix_cd;

        public string fix_cd_desc
        {
            get
            {
                string strDesc = string.Empty;
                if (!string.IsNullOrEmpty(this._fix_cd))
                {
                    switch (this._fix_cd.ToUpper().Trim())
                    {
                        case "C": strDesc = "확정"; break;
                        case "E": strDesc = "예정"; break;
                        case "N": strDesc = "미수록(0)"; break;
                        default: break;
                    }
                }
                return strDesc;
            }
        }

        [XmlAttribute(AttributeName = "date")]
        public string date;
        /// <summary>
        /// 기부일자
        /// </summary>

        [XmlAttribute(AttributeName = "dd")]
        public string dd;

        /// <summary>
        /// 납입연차
        /// </summary>
        [XmlAttribute(AttributeName = "annual")]
        public int annual;
    }
}

Data class

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace NTS_Reader_CS.Yesone
{
    public class Data
    {
        public Data()
        {
            this.amts = new List<Amt>();
            this.sums = new List<Sum>();
        }

        /// <summary>
        /// 자료코드
        /// A01:보장성, A02:장애인보장성
        /// B01:의료비 B03:의료기기 구입비용 B04:안경 또는 콘택트렌즈 구입비용 B05:보청기 또는 장애인 보장구 구입 비용 (2011년 B03,B04,B05 신규 추가)
        /// C01:유초중고(시도교육청), C03:대학교, C04:기타(개별제출)
        /// C02:직업훈련비
        /// C06:중고생 교복 구입비용
        /// D01:개인연금저축
        /// E01:연금저축
        /// F01:퇴직연금
        /// G01:신용카드
        /// G02:현금영수증
        /// G03:직불카드등
        /// J01:주택임차차입금 원리금상환액
        /// J02:장기주택저당차입금 이자상환액
        /// J03:주택마련저축
        /// K01:소기업소상공인 공제부금
        /// L01:기부금
        /// M01:장기주식형저축
        /// </summary>
        [XmlAttribute(AttributeName = "dat_cd")]
        public string dat_cd
        {
            set { this._dat_cd = value; }
            get { return this._dat_cd; }
        }
        private string _dat_cd;

        /// <summary>
        /// 자료코드값
        /// </summary>
        public string dat_cd_desc
        {
            get
            {
                string sNm = string.Empty;
                if (!string.IsNullOrEmpty(this._dat_cd))
                {
                    switch (this._dat_cd.ToUpper().Trim())
                    {
                        case "A01": sNm = "보장성"; break;
                        case "A02": sNm = "장애인보장성"; break;
                        case "B01": sNm = "의료비"; break;
                        case "B03": sNm = "의료기기 구입비용"; break;
                        case "B04": sNm = "안경 또는 콘택트렌즈 구입비용"; break;
                        case "B05": sNm = "보청기 또는 장애인 보장구 구입 비용"; break;
                        case "C01": sNm = "유초중고(시도교육청)"; break;
                        case "C03": sNm = "대학교"; break;
                        case "C04": sNm = "기타(개별제출)"; break;
                        case "C02": sNm = "직업훈련비"; break;
                        case "C06": sNm = "중고생 교복 구입비용"; break;
                        case "D01": sNm = "개인연금저축"; break;
                        case "E01": sNm = "연금저축"; break;
                        case "F01": sNm = "퇴직연금"; break;
                        case "G01": sNm = "신용카드"; break;
                        case "G02": sNm = "현금영수증"; break;
                        case "G03": sNm = "직불카드등"; break;
                        case "J01": sNm = "주택임차차입금 원리금상환액"; break;
                        case "J02": sNm = "장기주택저당차입금 이자상환액"; break;
                        case "J03": sNm = "주택마련저축"; break;
                        case "K01": sNm = "소기업소상공인 공제부금"; break;
                        case "L01": sNm = "기부금"; break;
                        case "M01": sNm = "장기주식형저축"; break;
                        default: break;
                    }
                }
                return sNm;
            }
        }

        /// <summary>
        /// 사업자번호
        /// </summary>
        [XmlAttribute(AttributeName = "busnid")]
        public string busnid;

        /// <summary>
        /// 취급기관
        /// </summary>
        [XmlAttribute(AttributeName = "trade_nm")]
        public string trade_nm;

        /// <summary>
        /// 계좌번호
        /// </summary>
        [XmlAttribute(AttributeName = "acc_no")]
        public string acc_no;

        /// <summary>
        /// 교육비구분
        /// 1:유치원
        /// 2:초등학교
        /// 3:중학교
        /// 4:고등학교
        /// 5:전문대학
        /// 6:대학교
        /// 7:대학원
        /// 8:보육시설
        /// C:원격대학
        /// D:학위취득과정
        /// E:시간제과정
        /// F:학원
        /// G:체육시설
        /// H:사회복지시설
        /// J:장애인재활교육기관
        /// </summary>
        [XmlAttribute(AttributeName = "edu_tp")]
        public string edu_tp
        {
            set { this._edu_tp = value; }
            get { return this._edu_tp; }
        }
        private string _edu_tp;

        /// <summary>
        /// 교육비구분값
        /// </summary>
        public string edu_tp_desc
        {
            get
            {
                string sNm = string.Empty;
                if (!string.IsNullOrEmpty(this._edu_tp))
                {
                    switch (this._edu_tp.ToUpper().Trim())
                    {
                        case "1": sNm = "유치원"; break;
                        case "2": sNm = "초등학교"; break;
                        case "3": sNm = "중학교"; break;
                        case "4": sNm = "고등학교"; break;
                        case "5": sNm = "전문대학"; break;
                        case "6": sNm = "대학교"; break;
                        case "7": sNm = "대학원"; break;
                        case "8": sNm = "보육시설"; break;
                        case "C": sNm = "원격대학"; break;
                        case "D": sNm = "학위취득과정"; break;
                        case "E": sNm = "시간제과정"; break;
                        case "F": sNm = "학원"; break;
                        case "G": sNm = "체육시설"; break;
                        case "H": sNm = "사회복지시설"; break;
                        case "J": sNm = "장애인재활교육기관"; break;
                        default: break;
                    }
                }
                return sNm;
            }
        }

        [XmlElement(ElementName = "goods_nm")]
        public string goods_nm;

        [XmlElement(ElementName = "insu1_resid")]
        public string insu1_resid;

        [XmlElement(ElementName = "insu1_nm")]
        public string insu1_nm;

        [XmlElement(ElementName = "insu2_resid")]
        public string insu2_resid;

        [XmlElement(ElementName = "insu2_nm")]
        public string insu2_nm;

        [XmlElement(ElementName = "sum")]
        public List<Sum> sums;

        /// <summary>
        /// 과정코드
        /// </summary>
        [XmlElement(ElementName = "course_cd")]
        public string course_cd;

        /// <summary>
        /// 과정명
        /// </summary>
        [XmlElement(ElementName = "subject_nm")]
        public string subject_nm;

        [XmlElement(ElementName = "start_dt")]
        public string start_dt;

        [XmlElement(ElementName = "end_dt")]
        public string end_dt;

        [XmlElement(ElementName = "com_cd")]
        public string com_cd;

        /// <summary>
        /// 연금구분코드
        /// 2010년귀속부터 해당
        /// 11:근로자퇴직급여보장법
        /// 12:과학기술인공제
        /// </summary>
        [XmlElement(ElementName = "pension_cd")]
        public string pension_cd
        {
            set { this._pension_cd = value; }
            get { return this._pension_cd; }
        }
        private string _pension_cd;

        /// <summary>
        /// 연금구분코드명
        /// </summary>
        public string pension_cd_desc
        {
            get
            {
                string sNm = string.Empty;
                if (!string.IsNullOrEmpty(this._pension_cd))
                {
                    switch (this._pension_cd.ToUpper().Trim())
                    {
                        case "11": sNm = "근로자퇴직급여보장법"; break;
                        case "12": sNm = "과학기술인공제"; break;
                        default: break;
                    }
                }
                return sNm;
            }
        }

        [XmlElement(ElementName = "amt")]
        public List<Amt> amts;

        [XmlElement(ElementName = "lend_dt")]
        public string lend_dt;

        /// <summary>
        /// 주택취득일
        /// </summary>
        [XmlElement(ElementName = "house_take_dt")]
        public string house_take_dt;

        /// <summary>
        /// 저당권설정일
        /// </summary>
        [XmlElement(ElementName = "mort_setup_dt")]
        public string mort_setup_dt;

        [XmlElement(ElementName = "repay_years")]
        public int repay_years;

        /// <summary>
        /// 저축구분
        /// 1:청약저축
        /// 2:주택청약종합저축
        /// 3:장기주택마련저축
        /// </summary>
        [XmlElement(ElementName = "saving_gubn")]
        public string saving_gubn
        {
            set { this._saving_gubn = value; }
            get { return this._saving_gubn; }
        }
        private string _saving_gubn;

        /// <summary>
        /// 저축구분명
        /// </summary>
        public string saving_gubn_desc
        {
            get
            {
                string sNm = string.Empty;
                if (string.IsNullOrEmpty(this._saving_gubn))
                {
                    switch (this._saving_gubn.ToUpper().Trim())
                    {
                        case "1": sNm = "청약저축"; break;
                        case "2": sNm = "주택청약종합저축"; break;
                        case "3": sNm = "장기주택마련저축"; break;
                        default: break;
                    }
                }
                return sNm;
            }
        }

        [XmlElement(ElementName = "reg_dt")]
        public string reg_dt;

        /// <summary>
        /// 납입방법 M:월납,Q:분기납
        /// </summary>
        [XmlElement(ElementName = "pay_method")]
        public string pay_method
        {
            set { this._pay_method = value; }
            get { return this._pay_method; }
        }
        private string _pay_method;
        /// <summary>
        /// 납입방법명
        /// </summary>
        public string pay_method_desc
        {
            get
            {
                string sNm = string.Empty;
                if (!string.IsNullOrEmpty(this._pay_method))
                {
                    switch (this._pay_method.ToUpper().Trim())
                    {
                        case "M": sNm = "월납"; break;
                        case "Q": sNm = "분기납"; break;
                        default: break;
                    }
                }
                return sNm;
            }
        }

        /// <summary>
        /// 기부유형
        /// 10:법정기부금
        /// 20:정치자금기부금
        /// 21:진흥기금출연
        /// 30:특례기부금(조특법 제 73조)
        /// 31:특례기부금(조특법 제 73조 11)
        /// 40:지정기부금
        /// 41:종교단체기부금
        /// 42:우리사주기부금(조특법 제 88조의 4)
        /// 50:기타기부금
        /// </summary>
        [XmlElement(ElementName = "donation_cd")]
        public string donation_cd
        {
            set { this._donation_cd = value; }
            get { return this._donation_cd; }
        }
        private string _donation_cd;

        /// <summary>
        /// 기부유형명
        /// </summary>
        public string donation_cd_desc
        {
            get
            {
                string sNm = string.Empty;
                if (!string.IsNullOrEmpty(this._donation_cd))
                {
                    switch (this._donation_cd.ToUpper().Trim())
                    {
                        case "10": sNm = "10:법정기부금"; break;
                        case "20": sNm = "20:정치자금기부금"; break;
                        case "21": sNm = "21:진흥기금출연"; break;
                        case "30": sNm = "30:특례기부금(조특법 제 73조)"; break;
                        case "31": sNm = "31:특례기부금(조특법 제 73조 11)"; break;
                        case "40": sNm = "40:지정기부금"; break;
                        case "41": sNm = "41:종교단체기부금"; break;
                        case "42": sNm = "42:우리사주기부금(조특법 제 88조의 4)"; break;
                        case "50": sNm = "50:기타기부금"; break;
                        default: break;
                    }
                }
                return sNm;
            }
        }

        public bool HasAmts
        {
            get { return (this.amts != null && this.amts.Count > 0); }
        }

        public bool HasSums
        {
            get { return (this.sums != null && this.amts.Count > 0); }
        }
    }
}

Man class

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace NTS_Reader_CS.Yesone
{
    public class Man
    {
        public Man()
        {
            this.datas = new List<Data>();
        }

        [XmlAttribute(AttributeName = "resid")]
        public string resid;
        [XmlAttribute(AttributeName = "name")]
        public string name;
        [XmlElement(ElementName = "data")]
        public List<Data> datas;

        public bool HasData
        {
            get { return (this.datas != null && this.datas.Count > 0); }
        }
    }
}

Sum class

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace NTS_Reader_CS.Yesone
{
    public class Sum
    {
        /// <summary>
        /// 연간합계액
        /// </summary>
        [XmlText()]
        public decimal sum;

        [XmlAttribute(AttributeName = "cnt")]
        public int cnt;

        [XmlAttribute(AttributeName = "pay")]
        public decimal pay;

        /// <summary>
        /// 공제액
        /// </summary>
        [XmlAttribute(AttributeName = "ddct")]
        public decimal ddct;

        /// <summary>
        /// 1년차 납입내역합계
        /// </summary>
        [XmlAttribute(AttributeName = "sum_y1")]
        public decimal sum_y1;

        /// <summary>
        /// 2년차 납입내역합계
        /// </summary>
        [XmlAttribute(AttributeName = "sum_y2")]
        public decimal sum_y2;

        /// <summary>
        /// 3년차 납입내역합계
        /// </summary>
        [XmlAttribute(AttributeName = "sum_y3")]
        public decimal sum_y3;
    }
}

Usages

아래 코드와 같이 사용합니다.

/// <summary>
/// UTF-8 버튼 클릭 이벤트 : PDF 파일 내용을 UTF-8로 변환
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnUtf8_Click(object sender, EventArgs e)
{
    try
    {
        string filePath = txtPdf.Text;
        string password = txtPass.Text;
        string sMsg = string.Empty;
        string sXML = string.Empty;

        Yesone.Yesone oData = YesoneHelper.GetData_연말정산_PDF(filePath, password, out sMsg, out sXML);

        if (string.IsNullOrEmpty(sMsg))
        {
            this.txtUtf8.Text = sXML;
            XMLDataView pForm = new XMLDataView();
            if (oData.HasDoc)
            {
                //pForm.SetDataSource(oData);
                //pForm.ShowDialog();

                this.DrawTree(oData);
            }
        }
        else
        {
            MessageBox.Show(sMsg, "알림");
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Exception");
    }
}

        private void GetData(string xml)
{
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(xml);

    byte[] xmlBytes = Encoding.UTF8.GetBytes(xml);
    Yesone.Yesone _yesone = new Yesone.Yesone();
    XmlSerializer serializer = new XmlSerializer(_yesone.GetType());

    StringReader reader = new StringReader(doc.OuterXml);
    _yesone = (Yesone.Yesone)serializer.Deserialize(reader);

    XMLDataView pForm = new XMLDataView();
    if (_yesone.HasDoc)
    {
        pForm.SetDataSource(_yesone);
        pForm.ShowDialog();
    }
}

private void DrawTree(Yesone.Yesone oData)
{
    Yesone.Yesone _yesone = oData;
    TreeNode root = new TreeNode("YESONE");
    TreeNode doc = new TreeNode("DOC");
    doc.Nodes.Add(new TreeNode("att_year : " + _yesone.doc.att_year));
    doc.Nodes.Add(new TreeNode("doc_type : " + _yesone.doc.doc_type));
    doc.Nodes.Add(new TreeNode("seq : " + _yesone.doc.seq));
    root.Nodes.Add(doc);

    this.treeView1.Nodes.Add(root);

    this.DrawTreeChildreNode<Yesone.YesoneForm>(root, _yesone.forms);
    this.treeView1.ExpandAll();
}

private void DrawTreeChildreNode<T>(TreeNode parent, List<T> data)
{
    if (data.Count == 0) return;

    int nIdx = 1;
    foreach (T item in data)
    {
        TreeNode t = new TreeNode();

        if (item is Yesone.YesoneForm)
        {
            t.Text = "Form" + nIdx.ToString();
            t.Nodes.Add(new TreeNode("form_cd : " + (item as Yesone.YesoneForm).form_cd));
            if ((item as Yesone.YesoneForm).mans.Count > 0)
            {
                this.DrawTreeChildreNode<Yesone.Man>(t, (item as Yesone.YesoneForm).mans);
            }
        }
        else if (item is NTS_Reader_CS.Yesone.Man)
        {
            t.Text = "Man" + nIdx.ToString();
            t.Nodes.Add(new TreeNode("nm : " + (item as Yesone.Man).name));
            t.Nodes.Add(new TreeNode("resid : " + (item as Yesone.Man).resid));
            if ((item as Yesone.Man).datas.Count > 0)
            {
                this.DrawTreeChildreNode<Yesone.Data>(t, (item as Yesone.Man).datas);
            }
        }
        else if (item is Yesone.Data)
        {
            t.Text = "Data" + nIdx.ToString();
            if (!string.IsNullOrEmpty((item as Yesone.Data).dat_cd))
            {
                t.Nodes.Add(new TreeNode("dat_cd : " + (item as Yesone.Data).dat_cd));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).busnid))
            {
                t.Nodes.Add(new TreeNode("busnid : " + (item as Yesone.Data).busnid));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).trade_nm))
            {
                t.Nodes.Add(new TreeNode("trade_nm : " + (item as Yesone.Data).trade_nm));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).acc_no))
            {
                t.Nodes.Add(new TreeNode("acc_no : " + (item as Yesone.Data).acc_no));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).edu_tp))
            {
                t.Nodes.Add(new TreeNode("edu_tp : " + (item as Yesone.Data).edu_tp));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).goods_nm))
            {
                t.Nodes.Add(new TreeNode("goods_nm : " + (item as Yesone.Data).goods_nm));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).insu1_resid))
            {
                t.Nodes.Add(new TreeNode("insu1_resid : " + (item as Yesone.Data).insu1_resid));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).insu1_nm))
            {
                t.Nodes.Add(new TreeNode("insu1_nm : " + (item as Yesone.Data).insu1_nm));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).insu2_resid))
            {
                t.Nodes.Add(new TreeNode("insu2_resid : " + (item as Yesone.Data).insu2_resid));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).insu2_nm))
            {
                t.Nodes.Add(new TreeNode("insu2_nm : " + (item as Yesone.Data).insu2_nm));
            }


            if (!string.IsNullOrEmpty((item as Yesone.Data).course_cd))
            {
                t.Nodes.Add(new TreeNode("course_cd : " + (item as Yesone.Data).course_cd));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).subject_nm))
            {
                t.Nodes.Add(new TreeNode("subject_nm : " + (item as Yesone.Data).subject_nm));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).start_dt))
            {
                t.Nodes.Add(new TreeNode("start_dt : " + (item as Yesone.Data).start_dt));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).end_dt))
            {
                t.Nodes.Add(new TreeNode("end_dt : " + (item as Yesone.Data).end_dt));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).com_cd))
            {
                t.Nodes.Add(new TreeNode("com_cd : " + (item as Yesone.Data).com_cd));
            }

            if (!string.IsNullOrEmpty((item as Yesone.Data).pension_cd))
            {
                t.Nodes.Add(new TreeNode("pension_cd : " + (item as Yesone.Data).pension_cd));
            }

            if ((item as Yesone.Data).sums.Count > 0)
            {
                this.DrawTreeChildreNode<Yesone.Sum>(t, (item as Yesone.Data).sums);
            }

            if ((item as Yesone.Data).amts.Count > 0)
            {
                this.DrawTreeChildreNode<Yesone.Amt>(t, (item as Yesone.Data).amts);
            }
        }
        else if (item is Yesone.Sum)
        {
            t.Text = "sum" + nIdx.ToString() + " : " + (item as Yesone.Sum).sum.ToString("n0");
            t.Nodes.Add(new TreeNode("cnt : " + (item as Yesone.Sum).cnt.ToString("n0")));
            t.Nodes.Add(new TreeNode("pay : " + (item as Yesone.Sum).pay.ToString("n0")));
        }
        else if (item is Yesone.Amt)
        {
            t.Text = "amt" + nIdx.ToString() + " : " + (item as Yesone.Amt).amt.ToString("n0");
            t.Nodes.Add(new TreeNode("mm : " + (item as Yesone.Amt).mm));
            t.Nodes.Add(new TreeNode("cnt : " + (item as Yesone.Amt).cnt.ToString("n0")));
            t.Nodes.Add(new TreeNode("pay : " + (item as Yesone.Amt).pay.ToString("n0")));
        }
        nIdx++;

        parent.Nodes.Add(t);
    }

}