protected virtual void OnSuccessfulResponse(BulkResponse response, HttpResponseMessage httpResponse)
 {
     using (var content = httpResponse.Content.ReadAsStream())
     {
         response.Rows = Serializer.Deserialize<BulkResponse.Row[]>(content);
     }
 }
Beispiel #2
0
 protected virtual void OnSuccessfulBulkResponseContentMaterializer(HttpResponseMessage response, BulkResponse result)
 {
     using (var content = response.Content.ReadAsStream())
         ResponseMaterializer.PopulateBulkResponse(result, content);
 }
Beispiel #3
0
        protected void Page_Load(object sender, EventArgs e)
        {
            /*
             * 최대 100건의 현금영수증 발행을 한번의 요청으로 접수합니다.
             * - https://docs.popbill.com/cashbill/dotnet/api#BulkSubmit
             */

            // 팝빌회원 사업자번호, '-' 제외 10자리
            String testCorpNum = "1234567890";

            // 제출아이디, 대량 발행 접수를 구별하는 식별키
            // └ 최대 36자리 영문, 숫자, '-' 조합으로 구성
            String submitID = "20220525-BULK";

            // 현금영수증 객체정보 목록
            List <Cashbill> cashbillList = new List <Cashbill>();

            for (int i = 0; i < 100; i++)
            {
                // 현금영수증 객체 생성
                Cashbill cashbill = new Cashbill();

                // 문서번호, 최대 24자리, 영문, 숫자 '-', '_'를 조합하여 사업자별로 중복되지 않도록 구성
                cashbill.mgtKey = submitID + "-" + i;

                //// [취소거래시 필수] 원본 현금영수증 국세청승인번호
                //cashbill.orgConfirmNum = "";

                //// [취소거래시 필수] 원본 현금영수증 거래일자
                //cashbill.orgTradeDate = "";

                // 문서형태, { 승인거래, 취소거래 } 중 기재
                cashbill.tradeType = "승인거래";

                // 거래구분, { 소득공제용, 지출증빙용 } 중 기재
                cashbill.tradeUsage = "소득공제용";

                // 거래유형, {일반, 도서공연, 대중교통} 중 기재
                // - 미입력시 기본값 "일반" 처리
                cashbill.tradeOpt = "일반";

                // 과세형태, { 과세, 비과세 } 중 기재
                cashbill.taxationType = "과세";

                // 거래금액 ( 공급가액 + 세액 + 봉사료 )
                cashbill.totalAmount = "11000";

                // 공급가액
                cashbill.supplyCost = "10000";

                // 부가세
                cashbill.tax = "1000";

                // 봉사료
                cashbill.serviceFee = "0";

                // 가맹점 사업자번호
                cashbill.franchiseCorpNum = testCorpNum;

                // 가맹점 종사업장 식별번호
                cashbill.franchiseTaxRegID = "";

                // 가맹점 상호
                cashbill.franchiseCorpName = "가맹점 상호";

                // 가맹점 대표자 성명
                cashbill.franchiseCEOName = "가맹점 대표자 성명";

                // 가맹점 주소
                cashbill.franchiseAddr = "가맹점 주소";

                // 가맹점 전화번호
                cashbill.franchiseTEL = "";

                // 식별번호, 거래구분에 따라 작성
                // └ 소득공제용 - 주민등록/휴대폰/카드번호(현금영수증 카드)/자진발급용 번호(010-000-1234) 기재가능
                // └ 지출증빙용 - 사업자번호/주민등록/휴대폰/카드번호(현금영수증 카드) 기재가능
                // └ 주민등록번호 13자리, 휴대폰번호 10~11자리, 카드번호 13~19자리, 사업자번호 10자리 입력 가능
                cashbill.identityNum = "0100001234";

                // 주문자명
                cashbill.customerName = "주문자명";

                // 주문상품명
                cashbill.itemName = "주문상품명";

                // 주문번호
                cashbill.orderNumber = "주문번호";

                // 주문자 이메일
                // 팝빌 개발환경에서 테스트하는 경우에도 안내 메일이 전송되므로,
                // 실제 거래처의 메일주소가 기재되지 않도록 주의
                cashbill.email = "";

                // 주문자 휴대폰
                // - {smssendYN} 의 값이 true 인 경우 아래 휴대폰번호로 안내 문자 전송
                cashbill.hp = "";

                // 주문자 팩스번호
                cashbill.fax = "";

                // 발행시 알림문자 전송여부
                cashbill.smssendYN = false;

                cashbillList.Add(cashbill);
            }

            try
            {
                BulkResponse response = Global.cashbillService.BulkSubmit(testCorpNum, submitID, cashbillList);

                code      = response.code.ToString();
                message   = response.message;
                receiptID = response.receiptID;
            }
            catch (PopbillException ex)
            {
                code    = ex.code.ToString();
                message = ex.Message;
            }
        }
 public virtual async void Materialize(BulkResponse response, HttpResponseMessage httpResponse)
 {
     using (var content = await httpResponse.Content.ReadAsStreamAsync().ForAwait())
         response.Rows = Serializer.Deserialize<BulkResponse.Row[]>(content);
 }
Beispiel #5
0
 public virtual async Task MaterializeAsync(BulkResponse response, HttpResponseMessage httpResponse)
 {
     using (var content = await httpResponse.Content.ReadAsStreamAsync().ForAwait())
         response.Rows = Serializer.Deserialize <BulkResponse.Row[]>(content);
 }
        public BulkResponse ProcessZip(string filePath, bool download, string fileName, string operationType, string fileURL, bool checkFailed)
        {
            StreamReader  streamReader             = null;
            string        fileType                 = "";
            List <string> fieldAPINames            = new List <string>();
            Dictionary <string, object> EventsData = new Dictionary <string, object>();
            string ModuleAPIName;

            try
            {
                if (operationType.Equals(APIConstants.READ))
                {
                    if (download && fileName == null)
                    {
                        FileAPIResponse fileResponse = BulkReadAPIHandler.GetInstance(this.bulkReadRecordIns).DownloadBulkReadResult();
                        if (!fileResponse.HttpStatusCode.Equals(APIConstants.ResponseCode.OK))
                        {
                            throw new ZCRMException("Zip file not downloaded");
                        }
                        else
                        {
                            if (!this.WriteStreamtoZipFile(fileResponse, filePath + "/"))
                            {
                                throw new ZCRMException("Error while writing file in the file path specified: " + filePath + "/");
                            }
                            if (!this.Unzip(filePath + "/" + fileResponse.GetFileName(), filePath + "/"))
                            {
                                throw new ZCRMException("Error occurred while unzipping the file: " + filePath + "/" + fileResponse.GetFileName());
                            }
                            streamReader = new StreamReader(File.OpenRead(filePath + "/" + this.fileName));
                        }
                        fileResponse = null;
                    }
                    ModuleAPIName = this.bulkReadRecordIns.ModuleAPIName;
                }
                else
                {
                    if (download && fileName == null && fileURL != null)
                    {
                        FileAPIResponse fileResponse = BulkWriteAPIHandler.GetInstance(this.bulkWriteRecordIns).DownloadBulkWriteResult(fileURL);
                        if (!fileResponse.HttpStatusCode.Equals(APIConstants.ResponseCode.OK))
                        {
                            throw new ZCRMException("Zip file not downloaded");
                        }
                        else
                        {
                            if (!this.WriteStreamtoZipFile(fileResponse, filePath + "/"))
                            {
                                throw new ZCRMException("Error while writing file in the file path specified: " + filePath + "/");
                            }

                            if (!this.Unzip(filePath + "/" + fileResponse.GetFileName(), filePath + "/"))
                            {
                                throw new ZCRMException("Error occurred while unzipping the file: " + filePath + "/" + fileResponse.GetFileName());
                            }
                            streamReader = new StreamReader(File.OpenRead(filePath + "/" + this.fileName));
                        }
                        fileResponse = null;
                    }
                    ModuleAPIName = this.bulkWriteRecordIns.ModuleAPIName;
                }
                if (streamReader == null && fileName != null)
                {
                    if (!Unzip(filePath + "/" + fileName, filePath + "/"))
                    {
                        throw new ZCRMException("Error occurred while unzipping the file: " + filePath + "/" + fileName);
                    }
                    streamReader = new StreamReader(File.OpenRead(filePath + "/" + this.fileName));
                }
                try
                {
                    if (this.fileName.Contains(".ics"))
                    {
                        fileType = "ics";
                        long cur_pos = 0;
                        int  length  = 0;
                        while (!streamReader.EndOfStream)
                        {
                            string line = streamReader.ReadLine();
                            cur_pos = cur_pos + line.Length;
                            var value = line.Split(new[] { ':' }, 2);
                            if (!EventsData.ContainsKey(value[0]))
                            {
                                EventsData[value[0]] = value[1];
                            }
                            else
                            {
                                break;
                            }
                            length = value.Length;
                        }
                        streamReader.BaseStream.Seek(cur_pos, SeekOrigin.Begin);
                        streamReader.DiscardBufferedData();
                    }
                    else
                    {
                        string header = streamReader.ReadLine();
                        if (header != null)
                        {
                            fieldAPINames = this.ParseCsvRow(header);
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new ZCRMException(APIConstants.SDK_ERROR, ex);
                }
            }
            catch (ZCRMException e)
            {
                ZCRMLogger.LogError(e);
                throw new ZCRMException(APIConstants.SDK_ERROR, e);
            }
            this.fileName = null;
            BulkResponse bulkResponse = new BulkResponse(ModuleAPIName, streamReader, checkFailed, fileType);

            bulkResponse.FieldAPINames = fieldAPINames;
            bulkResponse.APIHandlerIns = this;
            if (fileType.Equals("ics"))
            {
                EventsData["EventsData"] = bulkResponse;
                EventsData["END"]        = (string)EventsData["BEGIN"];
                bulkResponse.Data        = EventsData;
            }
            return(bulkResponse);
        }
    private async Task <BulkAllResponse> HandleBulkRequestAsync(IList <T> buffer, long page, int backOffRetries, BulkResponse response)
    {
        var clientException = response.ApiCall.OriginalException as TransportException;
        var failureReason   = clientException?.FailureReason;
        var reason          = failureReason?.GetStringValue() ?? nameof(PipelineFailure.BadRequest);

        switch (failureReason)
        {
        case PipelineFailure.MaxRetriesReached:
            if (response.ApiCall.AuditTrail.Last().Event == AuditEvent.FailedOverAllNodes)
            {
                throw ThrowOnBadBulk(response, $"{nameof(BulkAll)} halted after attempted bulk failed over all the active nodes");
            }

            ThrowOnExhaustedRetries();
            return(await RetryDocumentsAsync(page, ++backOffRetries, buffer).ConfigureAwait(false));

        case PipelineFailure.CouldNotStartSniffOnStartup:
        case PipelineFailure.BadAuthentication:
        case PipelineFailure.NoNodesAttempted:
        case PipelineFailure.SniffFailure:
        case PipelineFailure.Unexpected:
            throw ThrowOnBadBulk(response, $"{nameof(BulkAll)} halted after {nameof(PipelineFailure)}.{reason} from _bulk");

        case PipelineFailure.BadResponse:
        case PipelineFailure.PingFailure:
        case PipelineFailure.MaxTimeoutReached:
        case PipelineFailure.BadRequest:
        default:
            ThrowOnExhaustedRetries();
            return(await RetryDocumentsAsync(page, ++backOffRetries, buffer).ConfigureAwait(false));
        }

        void ThrowOnExhaustedRetries()
        {
            if (backOffRetries < _backOffRetries)
            {
                return;
            }

            throw ThrowOnBadBulk(response,
                                 $"{nameof(BulkAll)} halted after {nameof(PipelineFailure)}.{reason} from _bulk and exhausting retries ({backOffRetries})");
        }
    }
    private void HandleDroppedDocuments(List <Tuple <BulkResponseItemBase, T> > droppedDocuments, BulkResponse response)
    {
        if (droppedDocuments.Count <= 0)
        {
            return;
        }

        foreach (var dropped in droppedDocuments)
        {
            _droppedDocumentCallBack(dropped.Item1, dropped.Item2);
        }

        if (!_partitionedBulkRequest.ContinueAfterDroppedDocuments)
        {
            throw ThrowOnBadBulk(response, $"{nameof(BulkAll)} halted after receiving failures that can not be retried from _bulk");
        }
    }
        public async override Task RunExampleAsync()
        {
            Console.WriteLine("-------------------------------");
            Console.WriteLine("Sending scheduled fully featured textual message...");

            SMSResponse smsResponse = await SendScheduledMessageAsync();

            String             bulkId          = smsResponse.BulkId;
            SMSResponseDetails sentMessageInfo = smsResponse.Messages[0];

            Console.WriteLine("Sending scheduled fully featured textual message complete.");

            Console.WriteLine("-------------------------------");
            Console.WriteLine("Scheduled SMS");
            Console.WriteLine("Message ID: " + sentMessageInfo.MessageId);
            Console.WriteLine("Bulk ID: " + bulkId);
            Console.WriteLine("Receiver: " + sentMessageInfo.To);
            Console.WriteLine("Message status: " + sentMessageInfo.Status.Name);
            Console.WriteLine("-------------------------------");

            System.Threading.Thread.Sleep(1000);

            BulkResponse bulkResponse = await GetBulkAsync(bulkId);

            Console.WriteLine("Fetched scheduling date.");
            Console.WriteLine("Bulk ID: " + bulkResponse.BulkId);
            Console.WriteLine("SendAt: " + bulkResponse.SendAt);
            Console.WriteLine("-------------------------------");

            RescheduleMessageAsync(bulkId);
            Console.WriteLine("Rescheduling message.");
            Console.WriteLine("-------------------------------");

            System.Threading.Thread.Sleep(1000);

            bulkResponse = await GetBulkAsync(bulkId);

            Console.WriteLine("Fetched scheduling date after rescheduling.");
            Console.WriteLine("Bulk ID: " + bulkResponse.BulkId);
            Console.WriteLine("SendAt: " + bulkResponse.SendAt);
            Console.WriteLine("-------------------------------");

            System.Threading.Thread.Sleep(1000);

            BulkStatusResponse statusResponse = await GetBulkStatusAsync(bulkId);

            Console.WriteLine("Fetched bulk status.");
            Console.WriteLine("Bulk status: " + statusResponse.Status);
            Console.WriteLine("-------------------------------");

            if (statusResponse.Status == BulkStatus.PENDING)
            {
                Console.WriteLine("Fetched bulk is in PENDING status, attempting to cancel bulk.");
                Console.WriteLine("-------------------------------");

                CancelBulkStatusAsync(bulkId);

                statusResponse = await GetBulkStatusAsync(bulkId);

                Console.WriteLine("Fetched bulk status after cancelation.");
                Console.WriteLine("Bulk status: " + statusResponse.Status);
            }
            else
            {
                Console.WriteLine("Fetched bulk is not in PENDING status, aborting update.");
            }

            Console.WriteLine("-------------------------------");
        }
Beispiel #10
0
        /// <summary>
        /// 批量添加(没有就创建,有就修改覆盖)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <param name="indexName"></param>
        /// <param name="typeName"></param>
        /// <returns></returns>
        public bool SetMuilt(IEnumerable <T> model, string indexName, string typeName)
        {
            BulkResponse result = (BulkResponse)_es.IndexMany <T>(model, indexName, typeName);

            return(result.IsValid);
        }
Beispiel #11
0
 protected virtual void OnSuccessfulBulkResponseContentMaterializer(HttpResponseMessage response, BulkResponse result)
 {
     using (var content = response.Content.ReadAsStream())
         ResponseMaterializer.PopulateBulkResponse(result, content);
 }
Beispiel #12
0
        protected void Page_Load(object sender, EventArgs e)
        {
            /*
             * 최대 100건의 세금계산서 발행을 한번의 요청으로 접수합니다.
             * - https://docs.popbill.com/taxinvoice/dotnet/api#BulkSubmit
             */

            // 팝빌회원 사업자번호, '-' 제외 10자리
            String testCorpNum = "1234567890";

            //  제출아이디, 최대 36자리 영문, 숫자, '-' 조합으로 구성
            String submitID = "20220525-BULK";

            // 세금계산서 객체정보 목록
            List <Taxinvoice> taxinvoiceList = new List <Taxinvoice>();

            // 지연발행 강제여부, 기본값 - False
            // 지연발행 세금계산서를 발행하는 경우, 가산세가 부과될 수 있습니다.
            // 지연발행 세금계산서를 신고해야 하는 경우 forceIssue 값을 true 선언하여 발행하실 수 있습니다.
            bool forceIssue = false;

            for (int i = 0; i < 100; i++)
            {
                // 세금계산서 정보 객체
                Taxinvoice taxinvoice = new Taxinvoice();

                // 기재상 작성일자, 날짜형식(yyyyMMdd)
                taxinvoice.writeDate = "20220525";

                // 과금방향, {정과금, 역과금}중 선택
                // - 정과금(공급자과금), 역과금(공급받는자과금)
                // - 역과금은 역발행 세금계산서를 발행하는 경우만 가능
                taxinvoice.chargeDirection = "정과금";

                // 발행형태, {정발행, 역발행, 위수탁} 중 기재
                taxinvoice.issueType = "정발행";

                // {영수, 청구, 없음} 중 기재
                taxinvoice.purposeType = "영수";

                // 과세형태, {과세, 영세, 면세} 중 기재
                taxinvoice.taxType = "과세";


                /*****************************************************************
                *                         공급자 정보                           *
                *****************************************************************/

                // 공급자 사업자번호, '-' 제외 10자리
                taxinvoice.invoicerCorpNum = "1234567890";

                // 공급자 종사업장 식별번호. 필요시 기재. 형식은 숫자 4자리.
                taxinvoice.invoicerTaxRegID = "";

                // 공급자 상호
                taxinvoice.invoicerCorpName = "공급자 상호";

                // 공급자 문서번호, 최대 24자리, 영문, 숫자 '-', '_'를 조합하여 사업자별로 중복되지 않도록 구성
                taxinvoice.invoicerMgtKey = submitID + "-" + i;

                // 공급자 대표자 성명
                taxinvoice.invoicerCEOName = "공급자 대표자 성명";

                // 공급자 주소
                taxinvoice.invoicerAddr = "공급자 주소";

                // 공급자 종목
                taxinvoice.invoicerBizClass = "공급자 종목";

                // 공급자 업태
                taxinvoice.invoicerBizType = "공급자 업태,업태2";

                // 공급자 담당자 성명
                taxinvoice.invoicerContactName = "공급자 담당자명";

                // 공급자 담당자 메일주소
                taxinvoice.invoicerEmail = "";

                // 공급자 담당자 연락처
                taxinvoice.invoicerTEL = "";

                // 공급자 담당자 휴대폰번호
                taxinvoice.invoicerHP = "";

                // 발행 안내 문자 전송여부 (true / false 중 택 1)
                // └ true = 전송 , false = 미전송
                // └ 공급받는자 (주)담당자 휴대폰번호 {invoiceeHP1} 값으로 문자 전송
                // - 전송 시 포인트 차감되며, 전송실패시 환불처리
                taxinvoice.invoicerSMSSendYN = false;


                /*********************************************************************
                *                         공급받는자 정보                           *
                *********************************************************************/

                // 공급받는자 구분, {사업자, 개인, 외국인} 중 기재
                taxinvoice.invoiceeType = "사업자";

                // 공급받는자 사업자번호
                // - {invoiceeType}이 "사업자" 인 경우, 사업자번호 (하이픈 ('-') 제외 10자리)
                // - {invoiceeType}이 "개인" 인 경우, 주민등록번호 (하이픈 ('-') 제외 13자리)
                // - {invoiceeType}이 "외국인" 인 경우, "9999999999999" (하이픈 ('-') 제외 13자리)
                taxinvoice.invoiceeCorpNum = "8888888888";

                // 공급받는자 상호
                taxinvoice.invoiceeCorpName = "공급받는자 상호";

                // [역발행시 필수] 공급받는자 문서번호, 최대 24자리, 영문, 숫자 '-', '_'를 조합하여 사업자별로 중복되지 않도록 구성
                taxinvoice.invoiceeMgtKey = "";

                // 공급받는자 대표자 성명
                taxinvoice.invoiceeCEOName = "공급받는자 대표자 성명";

                // 공급받는자 주소
                taxinvoice.invoiceeAddr = "공급받는자 주소";

                // 공급받는자 종목
                taxinvoice.invoiceeBizClass = "공급받는자 종목";

                // 공급받는자 업태
                taxinvoice.invoiceeBizType = "공급받는자 업태";

                // 공급받는자 담당자 연락처
                taxinvoice.invoiceeTEL1 = "";

                // 공급받는자 담당자명
                taxinvoice.invoiceeContactName1 = "공급받는자 담당자명";

                // 공급받는자 담당자 메일주소
                // 팝빌 개발환경에서 테스트하는 경우에도 안내 메일이 전송되므로,
                // 실제 거래처의 메일주소가 기재되지 않도록 주의
                taxinvoice.invoiceeEmail1 = "";

                // 공급받는자 담당자 휴대폰번호
                taxinvoice.invoiceeHP1 = "";

                // 역발행시 알림문자 전송여부
                taxinvoice.invoiceeSMSSendYN = false;


                /*********************************************************************
                *                          세금계산서 정보                          *
                *********************************************************************/

                // 공급가액 합계
                taxinvoice.supplyCostTotal = "100000";

                // 세액 합계
                taxinvoice.taxTotal = "10000";

                // 합계금액,  공급가액 합계 + 세액 합계
                taxinvoice.totalAmount = "110000";

                // 기재상 일련번호 항목
                taxinvoice.serialNum = "123";

                // 기재상 현금 항목
                taxinvoice.cash = "";

                // 기재상 수표 항목
                taxinvoice.chkBill = "";

                // 기재상 어음 항목
                taxinvoice.note = "";

                // 기재상 외상미수금 항목
                taxinvoice.credit = "";

                // 기재상 비고 항목
                taxinvoice.remark1 = "비고1";
                taxinvoice.remark2 = "비고2";
                taxinvoice.remark3 = "비고3";

                // 기재상 권 항목, 최대값 32767
                // 미기재시 taxinvoice.kwon = null;
                taxinvoice.kwon = 1;

                // 기재상 호 항목, 최대값 32767
                // 미기재시 taxinvoice.ho = null;
                taxinvoice.ho = 1;


                // 사업자등록증 이미지 첨부여부 (true / false 중 택 1)
                // └ true = 첨부 , false = 미첨부(기본값)
                // - 팝빌 사이트 또는 인감 및 첨부문서 등록 팝업 URL (GetSealURL API) 함수를 이용하여 등록
                taxinvoice.businessLicenseYN = false;

                // 통장사본 이미지 첨부여부 (true / false 중 택 1)
                // └ true = 첨부 , false = 미첨부(기본값)
                // - 팝빌 사이트 또는 인감 및 첨부문서 등록 팝업 URL (GetSealURL API) 함수를 이용하여 등록
                taxinvoice.bankBookYN = false;


                /**************************************************************************
                 *        수정세금계산서 정보 (수정세금계산서 작성시에만 기재
                 * - 수정세금계산서 관련 정보는 연동매뉴얼 또는 개발가이드 링크 참조
                 * - [참고] 수정세금계산서 작성방법 안내 - https://docs.popbill.com/taxinvoice/modify?lang=dotnet
                 *************************************************************************/

                // 수정사유코드, 1~6까지 선택기재.
                // taxinvoice.modifyCode = null;

                // 수정세금계산서 작성시 원본세금계산서의 국세청승인번호
                // taxinvoice.orgNTSConfirmNum = "";


                /**************************************************************************
                *                         상세항목(품목) 정보                            *
                * - 상세항목 정보는 세금계산서 필수기재사항이 아니므로 작성하지 않더라도 *
                *   세금계산서 발행이 가능합니다.                                        *
                * - 최대 99건까지 작성가능                                               *
                **************************************************************************/

                taxinvoice.detailList = new List <TaxinvoiceDetail>();

                TaxinvoiceDetail detail = new TaxinvoiceDetail();

                detail.serialNum  = 1;          // 일련번호, 1부터 순차기재
                detail.purchaseDT = "20220525"; // 거래일자
                detail.itemName   = "품목명";      // 품목명
                detail.spec       = "규격";       // 규격
                detail.qty        = "1";        // 수량
                detail.unitCost   = "50000";    // 단가
                detail.supplyCost = "50000";    // 공급가액
                detail.tax        = "5000";     // 세액
                detail.remark     = "품목비고";     //비고

                taxinvoice.detailList.Add(detail);

                detail = new TaxinvoiceDetail();

                detail.serialNum  = 2;          // 일련번호, 1부터 순차기재
                detail.purchaseDT = "20220525"; // 거래일자
                detail.itemName   = "품목명";      // 품목명
                detail.spec       = "규격";       // 규격
                detail.qty        = "1";        // 수량
                detail.unitCost   = "50000";    // 단가
                detail.supplyCost = "50000";    // 공급가액
                detail.tax        = "5000";     // 세액
                detail.remark     = "품목비고";     //비고

                taxinvoice.detailList.Add(detail);


                /*************************************************************************
                *                           추가담당자 정보                              *
                * - 세금계산서 발행안내 메일을 수신받을 공급받는자 담당자가 다수인 경우  *
                *   담당자 정보를 추가하여 발행안내메일을 다수에게 전송할 수 있습니다.   *
                * - 최대 5개까지 기재가능                                                *
                *************************************************************************/

                taxinvoice.addContactList = new List <TaxinvoiceAddContact>();

                TaxinvoiceAddContact addContact = new TaxinvoiceAddContact();

                addContact.serialNum   = 1;        // 일련번호, 1부터 순차기재
                addContact.email       = "";       // 추가담당자 메일주소
                addContact.contactName = "추가담당자명"; // 추가담당자 성명

                taxinvoice.addContactList.Add(addContact);

                TaxinvoiceAddContact addContact2 = new TaxinvoiceAddContact();

                addContact2.serialNum   = 2;        // 일련번호, 1부터 순차기재
                addContact2.email       = "";       // 추가담당자 메일주소
                addContact2.contactName = "추가담당자명"; // 추가담당자 성명

                taxinvoice.addContactList.Add(addContact2);

                taxinvoiceList.Add(taxinvoice);
            }
            try
            {
                BulkResponse response = Global.taxinvoiceService.BulkSubmit(testCorpNum, submitID, taxinvoiceList, forceIssue);

                code      = response.code.ToString();
                message   = response.message;
                receiptID = response.receiptID;
            }
            catch (PopbillException ex)
            {
                code    = ex.code.ToString();
                message = ex.Message;
            }
        }