use of com.helger.phase4.messaging.domain.AS4UserMessage in project phase4 by phax.
the class UserMessageOneAttachmentTest method testUserMessageMimeSignedEncryptedSuccess.
@Test
public void testUserMessageMimeSignedEncryptedSuccess() throws Exception {
final ICommonsList<WSS4JAttachment> aAttachments = new CommonsArrayList<>();
aAttachments.add(WSS4JAttachment.createOutgoingFileAttachment(Phase4OutgoingAttachment.builder().data(ClassPathResource.getAsFile(AS4TestConstants.TEST_SOAP_BODY_PAYLOAD_XML)).mimeTypeXML().build(), s_aResMgr));
final AS4UserMessage aMsg = MockMessages.createUserMessageNotSigned(m_eSOAPVersion, null, aAttachments);
final Document aSignedDoc = AS4Signer.createSignedMessage(m_aCryptoFactory, aMsg.getAsSoapDocument(), m_eSOAPVersion, aMsg.getMessagingID(), aAttachments, s_aResMgr, false, AS4SigningParams.createDefault());
final AS4MimeMessage aMimeMsg = AS4Encryptor.encryptMimeMessage(m_eSOAPVersion, aSignedDoc, aAttachments, m_aCryptoFactory, false, s_aResMgr, m_aCryptParams);
final String sResponse = sendMimeMessage(new HttpMimeMessageEntity(aMimeMsg), true, null);
assertTrue(sResponse.contains(AS4TestConstants.RECEIPT_ASSERTCHECK));
assertTrue(sResponse.contains(ECryptoAlgorithmSign.SIGN_ALGORITHM_DEFAULT.getAlgorithmURI()));
assertTrue(sResponse.contains(ECryptoAlgorithmSignDigest.SIGN_DIGEST_ALGORITHM_DEFAULT.getAlgorithmURI()));
}
use of com.helger.phase4.messaging.domain.AS4UserMessage in project phase4 by phax.
the class AS4RequestHandler method _createReversedUserMessage.
/**
* Takes an UserMessage and switches properties to reverse the direction. So
* previously it was C1 => C4, now its C4 => C1 Also adds attachments if there
* are some that should be added.
*
* @param eSoapVersion
* of the message
* @param sResponseMessageID
* The AS4 message ID of the response
* @param aUserMessage
* the message that should be reversed
* @param aResponseAttachments
* attachment that should be added
* @return the reversed usermessage in document form
*/
@Nonnull
private static AS4UserMessage _createReversedUserMessage(@Nonnull final ESoapVersion eSoapVersion, @Nonnull @Nonempty final String sResponseMessageID, @Nonnull final Ebms3UserMessage aUserMessage, @Nonnull final ICommonsList<WSS4JAttachment> aResponseAttachments) {
// Use current time
final Ebms3MessageInfo aEbms3MessageInfo = MessageHelperMethods.createEbms3MessageInfo(sResponseMessageID, aUserMessage.getMessageInfo().getMessageId());
final Ebms3PayloadInfo aEbms3PayloadInfo = MessageHelperMethods.createEbms3PayloadInfo(false, aResponseAttachments);
// Invert from and to role from original user message
final Ebms3PartyInfo aEbms3PartyInfo = MessageHelperMethods.createEbms3ReversePartyInfo(aUserMessage.getPartyInfo());
// Should be exactly the same as incoming message
final Ebms3CollaborationInfo aEbms3CollaborationInfo = aUserMessage.getCollaborationInfo();
// Need to switch C1 and C4 around from the original usermessage
// TODO make customizable via profile
final Ebms3MessageProperties aEbms3MessageProperties = new Ebms3MessageProperties();
{
Ebms3Property aFinalRecipient = null;
Ebms3Property aOriginalSender = null;
for (final Ebms3Property aProp : aUserMessage.getMessageProperties().getProperty()) {
if (aProp.getName().equals(CAS4.ORIGINAL_SENDER))
aOriginalSender = aProp;
else if (aProp.getName().equals(CAS4.FINAL_RECIPIENT))
aFinalRecipient = aProp;
}
if (aOriginalSender == null)
throw new IllegalStateException("Failed to determine new OriginalSender");
if (aFinalRecipient == null)
throw new IllegalStateException("Failed to determine new FinalRecipient");
aFinalRecipient.setName(CAS4.ORIGINAL_SENDER);
aOriginalSender.setName(CAS4.FINAL_RECIPIENT);
aEbms3MessageProperties.addProperty(aFinalRecipient);
aEbms3MessageProperties.addProperty(aOriginalSender);
}
return AS4UserMessage.create(aEbms3MessageInfo, aEbms3PayloadInfo, aEbms3CollaborationInfo, aEbms3PartyInfo, aEbms3MessageProperties, eSoapVersion);
}
use of com.helger.phase4.messaging.domain.AS4UserMessage in project phase4 by phax.
the class AS4RequestHandler method _handleSoapMessage.
@Nullable
private IAS4ResponseFactory _handleSoapMessage(@Nonnull final HttpHeaderMap aHttpHeaders, @Nonnull final Document aSoapDocument, @Nonnull final ESoapVersion eSoapVersion, @Nonnull final ICommonsList<WSS4JAttachment> aIncomingAttachments, @Nonnull final ICommonsList<Ebms3Error> aErrorMessagesTarget) throws WSSecurityException, MessagingException, Phase4Exception {
final SOAPHeaderElementProcessorRegistry aRegistry = SOAPHeaderElementProcessorRegistry.createDefault(m_aPModeResolver, m_aCryptoFactory, (IPMode) null);
final IAS4MessageState aState = AS4IncomingHandler.processEbmsMessage(m_aResHelper, m_aLocale, aRegistry, aHttpHeaders, aSoapDocument, eSoapVersion, aIncomingAttachments, m_aIncomingProfileSelector, aErrorMessagesTarget);
final IPMode aPMode = aState.getPMode();
final PModeLeg aEffectiveLeg = aState.getEffectivePModeLeg();
final String sMessageID = aState.getMessageID();
final ICommonsList<WSS4JAttachment> aDecryptedAttachments = aState.hasDecryptedAttachments() ? aState.getDecryptedAttachments() : aState.getOriginalAttachments();
final Node aPayloadNode = aState.getSoapBodyPayloadNode();
final Ebms3UserMessage aEbmsUserMessage = aState.getEbmsUserMessage();
final Ebms3SignalMessage aEbmsSignalMessage = aState.getEbmsSignalMessage();
if (aState.isSoapHeaderElementProcessingSuccessful()) {
final String sProfileID = aState.getProfileID();
if (LOGGER.isDebugEnabled())
LOGGER.debug("No checking for duplicate message with message ID '" + sMessageID + "' and profile ID '" + sProfileID + "'");
final boolean bIsDuplicate = MetaAS4Manager.getIncomingDuplicateMgr().registerAndCheck(sMessageID, sProfileID, aPMode == null ? null : aPMode.getID()).isBreak();
if (bIsDuplicate) {
LOGGER.error("Not invoking SPIs, because message with Message ID '" + sMessageID + "' was already handled!");
aErrorMessagesTarget.add(EEbmsError.EBMS_OTHER.getAsEbms3Error(m_aLocale, sMessageID, "Another message with the same Message ID '" + sMessageID + "' was already received!"));
} else {
if (LOGGER.isDebugEnabled())
LOGGER.debug("Message is not a duplicate");
}
}
final SPIInvocationResult aSPIResult = new SPIInvocationResult();
// Storing for two-way response messages
final ICommonsList<WSS4JAttachment> aResponseAttachments = new CommonsArrayList<>();
// Invoke SPIs if
// * No errors so far (sign, encrypt, ...)
// * Valid PMode
// * Exactly one UserMessage or SignalMessage
// * No ping/test message
// * No Duplicate message ID
final boolean bCanInvokeSPIs = aErrorMessagesTarget.isEmpty() && !aState.isPingMessage();
if (bCanInvokeSPIs) {
// PMode may be null for receipts
if (aPMode == null || aPMode.getMEPBinding().isSynchronous() || aPMode.getMEPBinding().isAsynchronousInitiator() || aState.getEffectivePModeLegNumber() != 1) {
// Call synchronous
// Might add to aErrorMessages
// Might add to aResponseAttachments
// Might add to m_aPullReturnUserMsg
_invokeSPIsForIncoming(aHttpHeaders, aEbmsUserMessage, aEbmsSignalMessage, aPayloadNode, aDecryptedAttachments, aPMode, aState, aErrorMessagesTarget, aResponseAttachments, aSPIResult);
if (aSPIResult.isFailure())
LOGGER.warn("Error invoking synchronous SPIs");
else if (LOGGER.isDebugEnabled())
LOGGER.debug("Successfully invoked synchronous SPIs");
if (m_aSoapProcessingFinalizedCB != null)
m_aSoapProcessingFinalizedCB.onProcessingFinalized(true);
} else {
// Call asynchronous
// Only leg1 can be async!
final IThrowingRunnable<Exception> r = () -> {
// Start async
final ICommonsList<Ebms3Error> aLocalErrorMessages = new CommonsArrayList<>();
final ICommonsList<WSS4JAttachment> aLocalResponseAttachments = new CommonsArrayList<>();
final SPIInvocationResult aAsyncSPIResult = new SPIInvocationResult();
_invokeSPIsForIncoming(aHttpHeaders, aEbmsUserMessage, aEbmsSignalMessage, aPayloadNode, aDecryptedAttachments, aPMode, aState, aLocalErrorMessages, aLocalResponseAttachments, aAsyncSPIResult);
final IAS4ResponseFactory aAsyncResponseFactory;
final String sResponseMessageID;
if (aAsyncSPIResult.isSuccess()) {
// SPI processing succeeded
assert aLocalErrorMessages.isEmpty();
// The response user message has no explicit payload. All data of
// the response user message is in the local attachments
sResponseMessageID = MessageHelperMethods.createRandomMessageID();
final AS4UserMessage aResponseUserMsg = _createReversedUserMessage(eSoapVersion, sResponseMessageID, aEbmsUserMessage, aLocalResponseAttachments);
// Send UserMessage
final AS4SigningParams aSigningParams = new AS4SigningParams().setFromPMode(aEffectiveLeg.getSecurity());
// Use the original receiver ID as the alias into the keystore for
// encrypting the response message
final String sEncryptionAlias = aEbmsUserMessage.getPartyInfo().getTo().getPartyIdAtIndex(0).getValue();
final AS4CryptParams aCryptParams = new AS4CryptParams().setFromPMode(aEffectiveLeg.getSecurity()).setAlias(sEncryptionAlias);
aAsyncResponseFactory = _createResponseUserMessage(aState, aEffectiveLeg.getProtocol().getSoapVersion(), aResponseUserMsg, aResponseAttachments, aSigningParams, aCryptParams);
} else {
// SPI processing failed
// Send ErrorMessage Undefined - see
// https://github.com/phax/phase4/issues/4
final AS4ErrorMessage aResponseErrorMsg = AS4ErrorMessage.create(eSoapVersion, aState.getMessageID(), aLocalErrorMessages);
sResponseMessageID = aResponseErrorMsg.getEbms3SignalMessage().getMessageInfo().getMessageId();
// Pass error messages to the outside
if (m_aErrorConsumer != null && aLocalErrorMessages.isNotEmpty())
m_aErrorConsumer.onAS4ErrorMessage(aState, aLocalErrorMessages, aResponseErrorMsg);
aAsyncResponseFactory = new AS4ResponseFactoryXML(m_aMessageMetadata, aState, sResponseMessageID, aResponseErrorMsg.getAsSoapDocument(), eSoapVersion.getMimeType());
}
// where to send it back (must be determined by SPI!)
final String sAsyncResponseURL = aAsyncSPIResult.getAsyncResponseURL();
if (StringHelper.hasNoText(sAsyncResponseURL))
throw new IllegalStateException("No asynchronous response URL present - please check your SPI implementation");
if (LOGGER.isDebugEnabled())
LOGGER.debug("Responding asynchronous to: " + sAsyncResponseURL);
// Ensure HttpEntity is repeatable
HttpEntity aHttpEntity = aAsyncResponseFactory.getHttpEntityForSending(eSoapVersion.getMimeType());
aHttpEntity = m_aResHelper.createRepeatableHttpEntity(aHttpEntity);
// Use the prebuilt entity for dumping
_invokeSPIsForResponse(aState, aAsyncResponseFactory, aHttpEntity, eSoapVersion.getMimeType(), sResponseMessageID);
// invoke client with new document
final BasicHttpPoster aSender = new BasicHttpPoster();
final Document aAsyncResponse;
if (true) {
final HttpHeaderMap aResponseHttpHeaders = null;
// TODO make async send parameters customizable
final HttpRetrySettings aRetrySettings = new HttpRetrySettings();
aAsyncResponse = aSender.sendGenericMessageWithRetries(sAsyncResponseURL, aResponseHttpHeaders, aHttpEntity, sMessageID, aRetrySettings, new ResponseHandlerXml(), m_aOutgoingDumper, m_aRetryCallback);
} else {
aAsyncResponse = aSender.sendGenericMessage(sAsyncResponseURL, null, aHttpEntity, new ResponseHandlerXml());
}
AS4HttpDebug.debug(() -> "SEND-RESPONSE [async sent] received: " + XMLWriter.getNodeAsString(aAsyncResponse, AS4HttpDebug.getDebugXMLWriterSettings()));
};
final CompletableFuture<Void> aFuture = PhotonWorkerPool.getInstance().runThrowing(CAS4.LIB_NAME + " async processing", r);
if (m_aSoapProcessingFinalizedCB != null) {
// Give the outside world the possibility to get notified when the
// processing is done
aFuture.thenRun(() -> m_aSoapProcessingFinalizedCB.onProcessingFinalized(false));
}
}
}
// Try building error message
final String sResponseMessageID;
final IAS4ResponseFactory ret;
if (!aState.isSoapHeaderElementProcessingSuccessful() || aState.getEbmsError() == null) {
// Not an incoming Ebms Error Message
if (aErrorMessagesTarget.isNotEmpty()) {
if (LOGGER.isDebugEnabled())
LOGGER.debug("Creating AS4 error message with these " + aErrorMessagesTarget.size() + " errors: " + aErrorMessagesTarget.getAllMapped(Ebms3Error::getDescriptionValue));
final AS4ErrorMessage aResponseErrorMsg = AS4ErrorMessage.create(eSoapVersion, aState.getMessageID(), aErrorMessagesTarget);
// Call optional consumer
if (m_aErrorConsumer != null)
m_aErrorConsumer.onAS4ErrorMessage(aState, aErrorMessagesTarget, aResponseErrorMsg);
// When aLeg == null, the response is true
if (_isSendErrorAsResponse(aEffectiveLeg)) {
sResponseMessageID = aResponseErrorMsg.getEbms3SignalMessage().getMessageInfo().getMessageId();
ret = new AS4ResponseFactoryXML(m_aMessageMetadata, aState, sResponseMessageID, aResponseErrorMsg.getAsSoapDocument(), eSoapVersion.getMimeType());
} else {
LOGGER.warn("Not sending back the error, because sending error response is prohibited in PMode");
sResponseMessageID = null;
ret = null;
}
} else {
// Do not respond to receipt (except with error message - see above)
if (aEbmsSignalMessage == null || aEbmsSignalMessage.getReceipt() == null) {
// So now the incoming message is a user message or a pull request
if (aPMode.getMEP().isOneWay() || aPMode.getMEPBinding().isAsynchronous()) {
// the pull phase
if (aPMode.getMEPBinding().equals(EMEPBinding.PULL) || (aPMode.getMEPBinding().equals(EMEPBinding.PULL_PUSH) && aSPIResult.hasPullReturnUserMsg()) || (aPMode.getMEPBinding().equals(EMEPBinding.PUSH_PULL) && aSPIResult.hasPullReturnUserMsg())) {
// TODO would be nice to have attachments here I guess
final AS4UserMessage aResponseUserMsg = new AS4UserMessage(eSoapVersion, aSPIResult.getPullReturnUserMsg());
sResponseMessageID = aResponseUserMsg.getEbms3UserMessage().getMessageInfo().getMessageId();
ret = new AS4ResponseFactoryXML(m_aMessageMetadata, aState, sResponseMessageID, aResponseUserMsg.getAsSoapDocument(), eSoapVersion.getMimeType());
} else if (aEbmsUserMessage != null) {
// We received an incoming user message and no errors occurred
final boolean bSendReceiptAsResponse = _isSendReceiptAsResponse(aEffectiveLeg);
if (bSendReceiptAsResponse) {
sResponseMessageID = MessageHelperMethods.createRandomMessageID();
ret = _createResponseReceiptMessage(aState, aSoapDocument, eSoapVersion, sResponseMessageID, aEffectiveLeg, aEbmsUserMessage, aResponseAttachments);
} else {
// TODO what shall we send back here?
LOGGER.info("Not sending back the Receipt response, because sending Receipt response is prohibited in PMode");
sResponseMessageID = null;
ret = null;
}
} else {
sResponseMessageID = null;
ret = null;
}
} else {
// synchronous TWO - WAY (= "SYNC")
final PModeLeg aLeg2 = aPMode.getLeg2();
if (aLeg2 == null)
throw new Phase4Exception("PMode has no leg2!");
if (MEPHelper.isValidResponseTypeLeg2(aPMode.getMEP(), aPMode.getMEPBinding(), EAS4MessageType.USER_MESSAGE)) {
sResponseMessageID = MessageHelperMethods.createRandomMessageID();
final AS4UserMessage aResponseUserMsg = _createReversedUserMessage(eSoapVersion, sResponseMessageID, aEbmsUserMessage, aResponseAttachments);
final AS4SigningParams aSigningParams = new AS4SigningParams().setFromPMode(aLeg2.getSecurity());
final String sEncryptionAlias = aEbmsUserMessage.getPartyInfo().getTo().getPartyIdAtIndex(0).getValue();
final AS4CryptParams aCryptParams = new AS4CryptParams().setFromPMode(aLeg2.getSecurity()).setAlias(sEncryptionAlias);
ret = _createResponseUserMessage(aState, aLeg2.getProtocol().getSoapVersion(), aResponseUserMsg, aResponseAttachments, aSigningParams, aCryptParams);
} else {
sResponseMessageID = null;
ret = null;
}
}
} else {
sResponseMessageID = null;
ret = null;
}
}
} else {
sResponseMessageID = null;
ret = null;
}
// Create the HttpEntity on demand
_invokeSPIsForResponse(aState, ret, null, eSoapVersion.getMimeType(), sResponseMessageID);
return ret;
}
use of com.helger.phase4.messaging.domain.AS4UserMessage in project phase4 by phax.
the class MainPhase4PeppolSenderIntunor method main.
public static void main(final String[] args) {
WebScopeManager.onGlobalBegin(MockServletContext.create());
// Dump (for debugging purpose only)
AS4DumpManager.setIncomingDumper(new AS4IncomingDumperFileBased());
AS4DumpManager.setOutgoingDumper(new AS4OutgoingDumperFileBased());
try {
final Element aPayloadElement = DOMReader.readXMLDOM(new File("src/test/resources/examples/base-example.xml")).getDocumentElement();
if (aPayloadElement == null)
throw new IllegalStateException("Failed to read XML file to be send");
// Start configuring here
final IParticipantIdentifier aReceiverID = Phase4PeppolSender.IF.createParticipantIdentifierWithDefaultScheme("9914:intunor-test");
final IAS4ClientBuildMessageCallback aBuildMessageCallback = new IAS4ClientBuildMessageCallback() {
public void onAS4Message(final AbstractAS4Message<?> aMsg) {
final AS4UserMessage aUserMsg = (AS4UserMessage) aMsg;
LOGGER.info("Sending out AS4 message with message ID '" + aUserMsg.getEbms3UserMessage().getMessageInfo().getMessageId() + "'");
LOGGER.info("Sending out AS4 message with conversation ID '" + aUserMsg.getEbms3UserMessage().getCollaborationInfo().getConversationId() + "'");
}
};
final ESimpleUserMessageSendResult eResult;
eResult = Phase4PeppolSender.builder().documentTypeID(Phase4PeppolSender.IF.createDocumentTypeIdentifierWithDefaultScheme("urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1")).processID(Phase4PeppolSender.IF.createProcessIdentifierWithDefaultScheme("urn:fdc:peppol.eu:2017:poacc:billing:01:1.0")).senderParticipantID(Phase4PeppolSender.IF.createParticipantIdentifierWithDefaultScheme("9915:phase4-test-sender")).receiverParticipantID(aReceiverID).senderPartyID("POP000306").payload(aPayloadElement).smpClient(new SMPClientReadOnly(Phase4PeppolSender.URL_PROVIDER, aReceiverID, ESML.DIGIT_TEST)).rawResponseConsumer(new AS4RawResponseConsumerWriteToFile()).validationConfiguration(PeppolValidation3_13_0.VID_OPENPEPPOL_INVOICE_V3, new Phase4PeppolValidatonResultHandler()).buildMessageCallback(aBuildMessageCallback).sendMessageAndCheckForReceipt();
LOGGER.info("Peppol send result: " + eResult);
} catch (final Exception ex) {
LOGGER.error("Error sending Peppol message via AS4", ex);
} finally {
WebScopeManager.onGlobalEnd();
}
}
use of com.helger.phase4.messaging.domain.AS4UserMessage in project phase4 by phax.
the class MainPhase4PeppolSenderOZGRE method main.
public static void main(final String[] args) {
WebScopeManager.onGlobalBegin(MockServletContext.create());
// Dump (for debugging purpose only)
AS4DumpManager.setIncomingDumper(new AS4IncomingDumperFileBased());
AS4DumpManager.setOutgoingDumper(new AS4OutgoingDumperFileBased());
try {
final boolean bVerify = false;
final Element aPayloadElement = DOMReader.readXMLDOM(new File("src/test/resources/" + (bVerify ? "zre/Verifizierungs_Rechnung_PEPPOL.xml" : "examples/xrechnung-2.0.0-ubl-inv.xml"))).getDocumentElement();
if (aPayloadElement == null)
throw new IllegalStateException("Failed to read XML file to be send");
// Start configuring here
final IParticipantIdentifier aReceiverID = Phase4PeppolSender.IF.createParticipantIdentifierWithDefaultScheme("0204:99661-WEBSERVICEOZG-28");
final IAS4ClientBuildMessageCallback aBuildMessageCallback = new IAS4ClientBuildMessageCallback() {
public void onAS4Message(final AbstractAS4Message<?> aMsg) {
final AS4UserMessage aUserMsg = (AS4UserMessage) aMsg;
LOGGER.info("Sending out AS4 message with message ID '" + aUserMsg.getEbms3UserMessage().getMessageInfo().getMessageId() + "'");
LOGGER.info("Sending out AS4 message with conversation ID '" + aUserMsg.getEbms3UserMessage().getCollaborationInfo().getConversationId() + "'");
}
};
final ESimpleUserMessageSendResult eResult = Phase4PeppolSender.builder().documentTypeID(Phase4PeppolSender.IF.createDocumentTypeIdentifierWithDefaultScheme(bVerify ? "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0::2.1" : "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0::2.1")).processID(Phase4PeppolSender.IF.createProcessIdentifierWithDefaultScheme("urn:fdc:peppol.eu:2017:poacc:billing:01:1.0")).senderParticipantID(Phase4PeppolSender.IF.createParticipantIdentifierWithDefaultScheme("9915:phase4-test-sender")).receiverParticipantID(aReceiverID).senderPartyID("POP000306").payload(aPayloadElement).smpClient(new SMPClientReadOnly(Phase4PeppolSender.URL_PROVIDER, aReceiverID, ESML.DIGIT_TEST)).rawResponseConsumer(new AS4RawResponseConsumerWriteToFile()).buildMessageCallback(aBuildMessageCallback).sendMessageAndCheckForReceipt();
LOGGER.info("Peppol send result: " + eResult);
} catch (final Exception ex) {
LOGGER.error("Error sending Peppol message via AS4", ex);
} finally {
WebScopeManager.onGlobalEnd();
}
}
Aggregations