Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add postNotification method to userOperations #58

Open
wants to merge 1 commit into from

3 participants

dhaber Craig Walls Anton O.
dhaber

Hi,

The Facebook API now supports sending notifications from your app to a user. This commit adds a postNotifcation method to userOperations to allow this from within Spring Social. It includes the new interface method, the implementation and some tests.

You can find details from Facebook here: https://developers.facebook.com/docs/app_notifications/

Thanks!
Doug

Craig Walls
Owner

Doug: Thanks for the contribution. I'll try to take a deeper look at this, review it, and merge it in the next couple of weeks.

The one thing that I notice is that it requires an App access token, thus FacebookTemplate would have to be constructed with the app access token instead of a user access token (which is not common or even ideal). I've got some thoughts on how to construct (or be given from the connect framework) a FacebookTemplate that has both a user access token for most operations and an app access token for those operations that need it. I've created https://jira.springsource.org/browse/SOCIALFB-101 to track this. I may attack SOCIALFB-101 and your pull request together, thus there may be some changes to your code to account for whatever I come up with for app access tokens.

Also, just to make sure: Have you signed the contribute agreement at https://jira.springsource.org/browse/SOCIALFB-101 yet? If not, the legal-minded people here would be happy if you did. Thanks.

Craig Walls
Owner

Correction: THe link for the contributor agreement is at https://support.springsource.com/spring_committer_signup

dhaber

Thanks @habuma ! I signed the agreement.

Anton O.

What is the status of this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 14, 2012
This page is out of date. Refresh to see the latest.
19 spring-social-facebook/src/main/java/org/springframework/social/facebook/api/UserOperations.java
View
@@ -90,4 +90,23 @@
* @throws MissingAuthorizationException if FacebookTemplate was not created with an access token.
*/
List<Reference> search(String query);
+
+ /**
+ * Posts a short free-form message to the user's notification list
+ * NOTE: This will only work with an APP access token (not a user access token)
+ * SEE: https://developers.facebook.com/docs/app_notifications/
+ *
+ * @param userId the Facebook user ID
+ * @param href The relative path/GET params of the target (for example, "index.html?gift_id=123",
+ * or "?gift_id=123"). Then we will construct proper target URL based on your app settings. The
+ * logic is that, on web, if Canvas setting exists, we always show “Canvas URL + href”. If not,
+ * we show nothing. In the future (not in this version), we will also use existing URL
+ * re-writing logic to support mobile canvas and native mobile apps. We also append some special
+ * tracking params (fb_source, notif_id, notif_t) to the target URL for developers to track at
+ * their side. One example of target URL displayed in the jewel is:
+ * https://apps.facebook.com/bzhang_og/?fb_source=notification&notif_id=notif_514699839_145756436&ref=notif&notif_t=app_notification
+ * @param template The customized text of the notification.
+ * @return
+ */
+ boolean postNotifcation(String userId, String href, String template);
}
14 spring-social-facebook/src/main/java/org/springframework/social/facebook/api/impl/UserTemplate.java
View
@@ -18,6 +18,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import org.codehaus.jackson.JsonNode;
import org.springframework.social.facebook.api.FacebookProfile;
@@ -93,4 +94,17 @@ public FacebookProfile getUserProfile(String facebookId) {
}
return permissions;
}
+
+ @SuppressWarnings("unchecked")
+ public boolean postNotifcation(String userId, String href, String template) {
+ requireAuthorization();
+
+ MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
+ map.set("href", href);
+ map.set("template", template);
+
+ String uri = GraphApi.GRAPH_API_URL + userId + "/notifications";
+ Map<String, Object> response = restTemplate.postForObject(uri, map, Map.class);
+ return (Boolean)response.get("success");
+ }
}
34 spring-social-facebook/src/test/java/org/springframework/social/facebook/api/UserTemplateTest.java
View
@@ -25,8 +25,10 @@
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
+import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.social.NotAuthorizedException;
+import org.springframework.social.OperationNotPermittedException;
/**
* @author Craig Walls
@@ -206,6 +208,38 @@ public void search() {
public void search_unauthorized() {
unauthorizedFacebook.userOperations().search("Michael Scott");
}
+
+ @Test
+ public void sendNotification(){
+ mockServer.expect(requestTo("https://graph.facebook.com/123/notifications"))
+ .andExpect(method(POST))
+ .andExpect(header("Authorization", "OAuth someAccessToken"))
+ .andRespond(withSuccess(jsonResource("testdata/notifications"), MediaType.APPLICATION_JSON));
+
+ assertTrue(facebook.userOperations().postNotifcation("123", "href", "template"));
+ }
+
+
+ @Test(expected = OperationNotPermittedException.class)
+ public void sendNotification_invalidUser(){
+ mockServer.expect(requestTo("https://graph.facebook.com/123/notifications"))
+ .andExpect(method(POST))
+ .andExpect(header("Authorization", "OAuth someAccessToken"))
+ .andRespond(withStatus(HttpStatus.FORBIDDEN).body(jsonResource("testdata/error-permission")).contentType(MediaType.APPLICATION_JSON));
+
+ facebook.userOperations().postNotifcation("123", "href", "template");
+ }
+
+ @Test(expected = NotAuthorizedException.class)
+ public void sendNotification_invalidAppId(){
+ mockServer.expect(requestTo("https://graph.facebook.com/123/notifications"))
+ .andExpect(method(POST))
+ .andExpect(header("Authorization", "OAuth someAccessToken"))
+ .andRespond(withStatus(HttpStatus.UNAUTHORIZED).body(jsonResource("testdata/error-invalid-access-token")).contentType(MediaType.APPLICATION_JSON));
+
+ facebook.userOperations().postNotifcation("123", "href", "template");
+ }
+
private void assertBasicProfileData(FacebookProfile profile, boolean withMiddleName) {
assertEquals("123456789", profile.getId());
7 ...book/src/test/resources/org/springframework/social/facebook/api/testdata/error-invalid-access-token.json
View
@@ -0,0 +1,7 @@
+{
+ "error": {
+ "message": "Invalid OAuth access token.",
+ "type": "OAuthException",
+ "code": 190
+ }
+}
3  ...g-social-facebook/src/test/resources/org/springframework/social/facebook/api/testdata/notifications.json
View
@@ -0,0 +1,3 @@
+{
+ "success" : true
+}
Something went wrong with that request. Please try again.