package org.remitt.plugin.eligibility; import java.io.ByteArrayInputStream; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.pb.x12.Context; import org.pb.x12.Segment; import org.pb.x12.X12; import org.remitt.prototype.EligibilityInterface; import org.remitt.prototype.EligibilityParameter; import org.remitt.prototype.EligibilityResponse; import org.remitt.prototype.EligibilityStatus; import org.remitt.server.Configuration; import WebServices.GatewayEDI.MyNameValue; import com.sshtools.j2ssh.SftpClient; import com.sshtools.j2ssh.SshClient; import com.sshtools.j2ssh.authentication.AuthenticationProtocolState; import com.sshtools.j2ssh.authentication.PasswordAuthenticationClient; import com.sshtools.j2ssh.transport.IgnoreHostKeyVerification; public class SftpEligibility implements EligibilityInterface { static final Logger log = Logger.getLogger(SftpEligibility.class); /** * Should override this method to specify ETIN for a payer. * * @return */ public String getETIN() { return ""; } public String getInsuranceName() { return ""; } public String getInsuranceAddressLine1() { return ""; } public String getInsuranceAddressCity() { return ""; } public String getInsuranceAddressState() { return ""; } public String getInsuranceAddressPostalCode() { return ""; } public boolean isProduction() { return true; } @Override public String getPluginName() { return "SftpEligibility"; } @Override public Double getPluginVersion() { return 0.1; } @Override public EligibilityResponse checkEligibility(String userName, Map<EligibilityParameter, String> values, boolean resubmission, Integer jobId) throws Exception { // Form X12 5010 270 message X12 m = new X12(new Context()); Integer segmentCount = 0; SimpleDateFormat yyyymmdd = new SimpleDateFormat("yyyyMMdd"); SimpleDateFormat hhmm = new SimpleDateFormat("hhmm"); DecimalFormat nineDigitFormat = new DecimalFormat("000000000"); { // ISA Segment ISA = m.addSegment("ISA"); ISA.addElement(1, "00"); // Authorization implementation qualifier ISA.addElement(2, " "); // Authorization information ISA.addElement(3, "00"); // No security info present ISA.addElement(4, " "); // Authorization information ISA.addElement(5, "ZZ"); // Sender qualifier ISA.addElement(6, ""); // Sender id ISA.addElement(7, "ZZ"); // Receiver qualifier ISA.addElement(8, ""); // Receiver id ISA.addElement(9, yyyymmdd.format(new Date())); // YYYYMMDD ISA.addElement(10, hhmm.format(new Date())); // HHMM ISA.addElement(11, "^"); // Separator ISA.addElement(12, "00501"); ISA.addElement(13, nineDigitFormat.format(jobId)); // Control number // (9 digits) ISA.addElement(14, "1"); // ACK requested ISA.addElement(15, isProduction() ? "P" : "T"); // Production/testing } { // GS Segment GS = m.addSegment("GS"); GS.addElement(1, "XX"); GS.addElement(2, ""); // Sender code GS.addElement(3, ""); // Receiver code GS.addElement(4, yyyymmdd.format(new Date())); // YYYYMMDD GS.addElement(5, hhmm.format(new Date())); // HHMM GS.addElement(6, nineDigitFormat.format(jobId)); GS.addElement(7, "X"); GS.addElement(8, "005010X279A1"); } { // ST : ST*270*0001*005010X279A1~ Segment ST = m.addSegment("ST"); ST.addElement(1, "270"); ST.addElement(2, "0001"); // FIXME: should increment ST.addElement(3, "005010X279A1"); segmentCount++; } { // BHT Segment BHT = m.addSegment("BHT"); BHT.addElement(1, "0022"); // Information source BHT.addElement(2, "13"); // Request BHT.addElement(3, ""); // Reference identifier, situational BHT.addElement(4, new SimpleDateFormat("yyyyMMdd").format(new Date())); // CCYYMMDD // // // FIXME BHT.addElement(5, new SimpleDateFormat("HHmmss").format(new Date())); // HHMMSS // // // FIXME // BHT.addElement(6, ""); // RT = spend down, RU = medical services // reservation segmentCount++; } // Loop 2000 { // HL : HL*1**20*1~ Segment HL = m.addSegment("HL"); HL.addElement(1, "1"); HL.addElement(2, ""); HL.addElement(3, "20"); // 20 = information source HL.addElement(4, "1"); // 1 = additional HL segments segmentCount++; } // Loop 2100A { // NM1 : NM1*PR*2*ABC INSURANCE COMPANY*****PI*842610001~ Segment NM1 = m.addSegment("NM1"); NM1.addElement(1, "PR"); // PR = payer NM1.addElement(2, "2"); // 2 = non person entity NM1.addElement(3, getInsuranceName()); NM1.addElement(4, ""); NM1.addElement(5, ""); NM1.addElement(6, ""); NM1.addElement(7, ""); NM1.addElement(8, "PI"); // PI = payer identifier NM1.addElement(8, getETIN()); segmentCount++; } // Loop 2000B { // HL : HL*2*1*21*1~ Segment HL = m.addSegment("HL"); HL.addElement(1, "2"); // this HL segment HL.addElement(2, "1"); // parent number HL.addElement(3, "21"); // 21 = information receiver HL.addElement(4, "1"); segmentCount++; } // Loop 2100B { // NM1 : Segment NM1 = m.addSegment("NM1"); NM1.addElement(1, "1P"); // 1P = provider NM1.addElement(2, "1"); // entity type person NM1.addElement(3, ""); // last name NM1.addElement(4, ""); // first name NM1.addElement(5, ""); // middle name NM1.addElement(6, ""); // prefix NM1.addElement(7, ""); // suffix NM1.addElement(8, "XX"); // XX = NPI NM1.addElement(9, values.get(EligibilityParameter.ELIGIBILITY_PARAMETER_NPI)); // NPI // identifier segmentCount++; } if (false) { Segment REF = m.addSegment("REF"); REF.addElement(1, ""); REF.addElement(2, ""); REF.addElement(3, ""); segmentCount++; } { Segment N3 = m.addSegment("N3"); N3.addElement(1, ""); // address line 1 N3.addElement(2, ""); // address line 2 segmentCount++; } { Segment N4 = m.addSegment("N4"); N4.addElement(1, ""); // city N4.addElement(2, ""); // state N4.addElement(3, ""); // postal code segmentCount++; } // Loop 2000C: Subscriber Level { // HL : HL*3*2*22*1~ Segment HL = m.addSegment("HL"); HL.addElement(1, "3"); HL.addElement(2, "2"); HL.addElement(3, "22"); // 22 = subscriber level HL.addElement(4, "1"); // 1 = additional HL segments segmentCount++; } // TRN segment, situational // Loop 2100C: Subscriber name { // NM1 : Segment NM1 = m.addSegment("NM1"); NM1.addElement(1, "IL"); // IL = insured/subscribed NM1.addElement(2, "1"); // entity type person NM1.addElement( 3, values.get(EligibilityParameter.ELIGIBILITY_PARAMETER_INSURED_LAST_NAME)); // last // name NM1.addElement( 4, values.get(EligibilityParameter.ELIGIBILITY_PARAMETER_INSURED_FIRST_NAME)); // first // name NM1.addElement(5, ""); // middle name NM1.addElement(6, ""); // prefix NM1.addElement(7, ""); // suffix NM1.addElement(8, "MI"); // MI = member identification number NM1.addElement( 9, values.get(EligibilityParameter.ELIGIBILITY_PARAMETER_INSURANCE_ID)); segmentCount++; } if (false) { Segment REF = m.addSegment("REF"); REF.addElement(1, ""); REF.addElement(2, ""); REF.addElement(3, ""); segmentCount++; } { Segment N3 = m.addSegment("N3"); N3.addElement(1, ""); // address line 1 N3.addElement(2, ""); // address line 2 segmentCount++; } { Segment N4 = m.addSegment("N4"); N4.addElement(1, ""); // city N4.addElement( 2, values.get(EligibilityParameter.ELIGIBILITY_PARAMETER_INSURED_STATE)); // state N4.addElement(3, ""); // postal code segmentCount++; } // PRV - Provider Information // DMG - Subscriber demographic information { Segment DMG = m.addSegment("DMG"); DMG.addElement(1, "D8"); // D8 = DOB DMG.addElement( 2, values.get(EligibilityParameter.ELIGIBILITY_PARAMETER_INSURED_DOB)); // DOB DMG.addElement( 3, values.get(EligibilityParameter.ELIGIBILITY_PARAMETER_INSURED_GENDER)); // gender segmentCount++; } // DMG - Subscriber demographic information { Segment DMG = m.addSegment("DMG"); DMG.addElement(1, "102"); // issue DMG.addElement(2, "D8"); // D8 = date DMG.addElement( 3, values.get(EligibilityParameter.ELIGIBILITY_PARAMETER_CARD_ISSUE_DATE)); // date // issued segmentCount++; } // Loop 2100C // EQ // AMT // AMT // III // REF // DTP { segmentCount++; // this segment Segment SE = m.addSegment("SE"); SE.addElement(1, segmentCount.toString()); SE.addElement(2, "0001"); } { // GE Segment GE = m.addSegment("GE"); GE.addElement(1, "1"); // Number of transactions GE.addElement(2, nineDigitFormat.format(jobId)); // == GS06 } { // IEA Segment IEA = m.addSegment("IEA"); IEA.addElement(1, "1"); // Number of included functional groups IEA.addElement(2, nineDigitFormat.format(jobId)); // Interchange control number } // Actual transmittal transmit(userName, m.toString()); EligibilityResponse er = new EligibilityResponse(); er.setStatus(EligibilityStatus.PROCESSING); return er; } protected void transmit(String userName, String payload) throws Exception { SshClient ssh = new SshClient(); String tempPathName = getOutputFileName(payload.getBytes()); String host = getSftpHost(userName); Integer port = getSftpPort(userName); String sftpUser = getSftpUser(userName); String sftpPassword = getSftpPassword(userName); String sftpPath = getSftpPath(userName); // Perform initial connection ssh.connect(host, port, new IgnoreHostKeyVerification()); // Authenticate PasswordAuthenticationClient passwordAuthenticationClient = new PasswordAuthenticationClient(); passwordAuthenticationClient.setUsername(sftpUser); passwordAuthenticationClient.setPassword(sftpPassword); int result = ssh.authenticate(passwordAuthenticationClient); if (result != AuthenticationProtocolState.COMPLETE) { throw new Exception("Login to " + host + ":" + port + " " + sftpUser + "/" + sftpPassword + " failed"); } // Open the SFTP channel SftpClient client = ssh.openSftpClient(); if (sftpPath != null && sftpPath != "") { client.cd(sftpPath); } // Convert string to input stream for transfer ByteArrayInputStream bs = new ByteArrayInputStream(payload.getBytes()); // Send the file client.put(bs, tempPathName); // Disconnect client.quit(); ssh.disconnect(); } protected void addNameValue(List<MyNameValue> dest, Map<EligibilityParameter, String> map, EligibilityParameter mapName, String name) { if (map.get(mapName) != null) { MyNameValue nv = new MyNameValue(); nv.setName(name); nv.setValue(map.get(mapName)); dest.add(nv); } } @Override public String[] getPluginConfigurationOptions() { return new String[] { "sftpUsername", "sftpPassword" }; } protected String getSftpHost(String userName) { return Configuration.getPluginOption(this, userName, "sftpHost"); } protected Integer getSftpPort(String userName) { return Integer.parseInt(Configuration.getPluginOption(this, userName, "sftpPort")); } protected String getSftpUser(String userName) { return Configuration.getPluginOption(this, userName, "sftpUsername"); } protected String getSftpPassword(String userName) { return Configuration.getPluginOption(this, userName, "sftpPassword"); } protected String getSftpPath(String userName) { return Configuration.getPluginOption(this, userName, "sftpPath"); } protected String getOutputFileName(byte[] input) { String outputType = "x12"; return new Long(System.currentTimeMillis()).toString() + "." + outputType; } }