Skip to content

Commit

Permalink
Add MessageEvent to main SMS package
Browse files Browse the repository at this point in the history
  • Loading branch information
SMadani committed Jan 31, 2024
1 parent a4c6e5a commit 30c3016
Show file tree
Hide file tree
Showing 7 changed files with 353 additions and 3 deletions.
4 changes: 4 additions & 0 deletions src/main/java/com/vonage/client/incoming/MessageEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
import java.util.Date;
import java.util.TimeZone;

/**
* @deprecated Moved to {@link com.vonage.client.sms.MessageEvent}.
*/
@Deprecated
@JsonIgnoreProperties(ignoreUnknown = true)
public class MessageEvent implements Jsonable {
private String msisdn, to, messageId, text, keyword, timestamp, nonce, data, udh;
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/vonage/client/incoming/MessageType.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import com.fasterxml.jackson.annotation.JsonCreator;

@Deprecated
public enum MessageType {
TEXT, UNICODE, BINARY, UNKNOWN;

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/vonage/client/incoming/package-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
* limitations under the License.
*/
/**
* @deprecated This package will be removed in a future release.
* @deprecated This package will be removed in the next major release.
*/
package com.vonage.client.incoming;
208 changes: 208 additions & 0 deletions src/main/java/com/vonage/client/sms/MessageEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
/*
* Copyright 2024 Vonage
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.vonage.client.sms;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.vonage.client.Jsonable;
import com.vonage.client.JsonableBaseObject;
import java.time.Instant;

/**
* Represents an <a href=https://developer.vonage.com/en/messaging/sms/guides/inbound-sms>Inbound SMS webhook</a>.
*
* @since 8.3.0
*/
@JsonInclude(value = JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public final class MessageEvent extends JsonableBaseObject {
private String msisdn, to, messageId, text, keyword, nonce, data, udh;
private MessageType type;
private Instant messageTimestamp;
private Long timestamp;
private Boolean concat;
private Integer concatRef, concatTotal, concatPart;

private MessageEvent() {}

/**
* The phone number that this inbound message was sent from.
*
* @return The sender number in E.164 format.
*/
@JsonProperty("msisdn")
public String getMsisdn() {
return msisdn;
}

/**
* Phone number that the message was sent to. This is your virtual number.
*
* @return The recipient number in E.164 format.
*/
@JsonProperty("to")
public String getTo() {
return to;
}

/**
* Vonage's unique identifier for this message.
*
* @return The message ID.
*/
@JsonProperty("messageId")
public String getMessageId() {
return messageId;
}

/**
* Type of message.
*
* @return The message type as an enum.
*/
@JsonProperty("type")
public MessageType getType() {
return type;
}

/**
* Message body for this inbound message.
*
* @return The text message, or {@code null} if {@linkplain #getType()} is {@linkplain MessageType#BINARY}.
*/
@JsonProperty("text")
public String getText() {
return text;
}

/**
* The first word in the message body. This is typically used with short codes.
*
* @return The message keyword, or {@code null} if {@linkplain #getType()} is {@linkplain MessageType#BINARY}.
*/
@JsonProperty("keyword")
public String getKeyword() {
return keyword;
}

/**
* The binary content of this message.
*
* @return The message content as a string, or {@code null} if
* {@linkplain #getType()} is not {@linkplain MessageType#BINARY}.
*/
@JsonProperty("data")
public String getData() {
return data;
}

/**
* The hex encoded user data header.
*
* @return The user data header as a hex-encoded string, or {@code null} if
* {@linkplain #getType()} is not {@linkplain MessageType#BINARY}.
*/
@JsonProperty("udh")
public String getUdh() {
return udh;
}

/**
* The UTC±00:00 time when Vonage started to push this inbound message to your webhook endpoint.
*
* @return The message timestamp as an Instant.
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC")
@JsonProperty("message-timestamp")
public Instant getMessageTimestamp() {
return messageTimestamp;
}

/**
* The Unix timestamp representation of {@link #getMessageTimestamp()}.
*
* @return The Unix timestamp of the message as a Long, or {@code null} if unavailable.
*/
@JsonProperty("timestamp")
public Long getTimestamp() {
return timestamp;
}

/**
* A random string that adds an extra element of unpredictability into the signature for the request.
* You use the nonce and timestamp parameters with your shared secret to calculate and validate the
* signature for inbound messages.
*
* @return The nonce, or {@code null} if the message is unsigned.
*/
@JsonProperty("nonce")
public String getNonce() {
return nonce;
}

/**
* Whether the message exceeded the maximum-permitted length of a single message.
*
* @return {@code true} for multipart (concatenated) message, or {@code null} if not applicable.
*/
@JsonProperty("concat")
public Boolean getConcat() {
return concat;
}

/**
* The transaction reference. All parts of this message share this reference.
*
* @return The concatenation reference, or {@code null} if not applicable.
*/
@JsonProperty("concat-ref")
public Integer getConcatRef() {
return concatRef;
}

/**
* The number of parts in this concatenated message.
*
* @return Total number of messages used, or {@code null} if not applicable.
*/
@JsonProperty("concat-total")
public Integer getConcatTotal() {
return concatTotal;
}

/**
* The number of this part in the message. The first part of the message is 1.
*
* @return The sequence number (part) for this message, or {@code null} if not applicable.
*/
@JsonProperty("concat-part")
public Integer getConcatPart() {
return concatPart;
}

/**
* Creates an instance of this class from a JSON payload.
*
* @param json The JSON string to parse.
*
* @return An instance of this class with the fields populated, if present.
*/
public static MessageEvent fromJson(String json) {
return Jsonable.fromJson(json);
}
}
44 changes: 44 additions & 0 deletions src/main/java/com/vonage/client/sms/MessageType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2024 Vonage
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.vonage.client.sms;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;

/**
* Represents the SMS message type.
*
* @since 8.3.0
*/
public enum MessageType {
TEXT, UNICODE, BINARY, UNKNOWN;

@JsonCreator
public static MessageType fromString(String name) {
try {
return MessageType.valueOf(name.toUpperCase());
}
catch (IllegalArgumentException | NullPointerException ex) {
return UNKNOWN;
}
}

@JsonValue
@Override
public String toString() {
return name().toLowerCase();
}
}
4 changes: 2 additions & 2 deletions src/main/java/com/vonage/client/sms/package-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* for an overview of the concepts.
* <p>
*
* For more messaging channels, consider using the Messages API in the {@link com.vonage.client.messages}
* package, which also includes SMS and more features.
* For more messaging channels, consider using the Messages API in the {@link com.vonage.client.messages} package,
* which also includes SMS and more features, along with better support for webhooks and inbound messages.
*/
package com.vonage.client.sms;
93 changes: 93 additions & 0 deletions src/test/java/com/vonage/client/sms/MessageEventTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2024 Vonage
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.vonage.client.sms;

import com.vonage.client.TestUtils;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.assertNull;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public class MessageEventTest {

@Test
public void testDeserializeIncomingMessage() {
String json = """
{
"msisdn": "447700900001",
"to": "447700900000",
"messageId": "0A0000000123ABCD1",
"text": "Hello world",
"type": "text",
"keyword": "Hello",
"message-timestamp": "2020-01-01 12:00:00",
"timestamp": "1578787200",
"nonce": "aaaaaaaa-bbbb-cccc-dddd-0123456789ab",
"concat": "true",
"concat-ref": "1",
"concat-total": "3",
"concat-part": "2",
"data": "abc123",
"udh": "abc123"
}""";

var messageEvent = MessageEvent.fromJson(json);
TestUtils.testJsonableBaseObject(messageEvent);

assertEquals("447700900001", messageEvent.getMsisdn());
assertEquals("447700900000", messageEvent.getTo());
assertEquals("0A0000000123ABCD1", messageEvent.getMessageId());
assertEquals("Hello world", messageEvent.getText());
assertEquals("Hello", messageEvent.getKeyword());
assertEquals(1578787200L, messageEvent.getTimestamp());
assertEquals("aaaaaaaa-bbbb-cccc-dddd-0123456789ab", messageEvent.getNonce());
assertEquals(true, messageEvent.getConcat());
assertEquals(1, messageEvent.getConcatRef());
assertEquals(3, messageEvent.getConcatTotal());
assertEquals(2, messageEvent.getConcatPart());
assertEquals("abc123", messageEvent.getData());
assertEquals("abc123", messageEvent.getUdh());

var calendar = new GregorianCalendar(2020, Calendar.JANUARY, 1, 12, 0, 0);
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
var time = calendar.toZonedDateTime().toInstant();
assertEquals(time, messageEvent.getMessageTimestamp());
}

@Test
public void testUnknownMessageType() {
var me = MessageEvent.fromJson("{\"type\": \"pigeon\"}");
TestUtils.testJsonableBaseObject(me);
assertNull(me.getConcat());
assertNull(me.getMessageId());
assertNull(me.getMessageTimestamp());
assertNull(me.getConcatPart());
assertNull(me.getConcatTotal());
assertNull(me.getData());
assertNull(me.getUdh());
assertNull(me.getText());
assertNull(me.getMsisdn());
assertNull(me.getKeyword());
assertNull(me.getNonce());
assertNull(me.getTo());
assertEquals(MessageType.UNKNOWN, me.getType());

me = MessageEvent.fromJson("{}");
assertNull(me.getType());
}
}

0 comments on commit 30c3016

Please sign in to comment.