Frictionless requests are not working in FBUnitySDK - unity3d

This is the code of my FB.cs file which is a by default code from unity fb sdk. If you see at line number 10 I have already marked frictionless request as true by default by removing the variable and just putting the value as true.
private static bool frictionlessRequests=true;
public static void Init(InitDelegate onInitComplete, HideUnityDelegate onHideUnity = null, string authResponse = null)
{
Init(
onInitComplete,
FBSettings.AppId,
FBSettings.Cookie,
FBSettings.Logging,
FBSettings.Status,
FBSettings.Xfbml,
true,//FBSettings.FrictionlessRequests,
onHideUnity,
authResponse);
}
/**
* If you need a more programmatic way to set the facebook app id and other setting call this function.
* Useful for a build pipeline that requires no human input.
*/
public static void Init(
InitDelegate onInitComplete,
string appId,
bool cookie = true,
bool logging = true,
bool status = true,
bool xfbml = false,
bool frictionlessRequests = true,
HideUnityDelegate onHideUnity = null,
string authResponse = null)
{
FB.appId = appId;
FB.cookie = cookie;
FB.logging = logging;
FB.status = status;
FB.xfbml = xfbml;
FB.frictionlessRequests = frictionlessRequests;
FB.authResponse = authResponse;
FB.OnInitComplete = onInitComplete;
FB.OnHideUnity = onHideUnity;
if (!isInitCalled)
{
FbDebug.Info(String.Format("Using SDK {0}, Build {1}", FBBuildVersionAttribute.SDKVersion, FBBuildVersionAttribute.GetBuildVersionOfType(typeof(IFacebook))));
#if UNITY_EDITOR
FBComponentFactory.GetComponent<EditorFacebookLoader>();
#elif UNITY_WEBPLAYER
FBComponentFactory.GetComponent<CanvasFacebookLoader>();
#elif UNITY_IOS
FBComponentFactory.GetComponent<IOSFacebookLoader>();
#elif UNITY_ANDROID
FBComponentFactory.GetComponent<AndroidFacebookLoader>();
#else
throw new NotImplementedException("Facebook API does not yet support this platform");
#endif
isInitCalled = true;
return;
}
No I am calling Init using this.
FB.Init(OnInitComplete, OnHideUnity,null);
And I then when I try to send request using this code
public static function SendLifeBack(){
FB.AppRequest
(
"Enjoy a free Potion",
["USER_ID"],
null,
null,
null,
"life",
"Free Life",
LogCallback
);
}
There is not sign of frictionless request as there is no checkbox of
"don't ask me again before sending requests to this user"
Even if I make the line number 10 as default as
FBSettings.FrictionlessRequests
even then it is not working. I have checked the frictionless checkbox in FBSettings too.

Related

Getting Same response to any query in Watson Assistant V2 : Watson-Unity-SDK

I just got to a point where I could set-up the Watson Assistant V2 with Unity and trying to converse with an Assistant I created with a single Skill. I need further help to get the assistant set up to work with my Unity app.
In V1 of the assistant, it was possible to target a workspace and also the response was returning the intent, nodes visited so on. My queries were correctly processed and the responses were identical to the one on the "try it" application in the IBM cloud dashboard.
In the new version though, I am getting the same response for any query I send to the assistant. How can I target the right skill or rather pass correct settings to the assistant to get the correct responses?
IMAGE - Unity log showing assistant responses
[IMAGE - Assistant trial on dashboard][2]
The code I'm using to send queries and get responses is:
IEnumerator TokenExample()
{
// Create IAM token options and supply the apikey. IamUrl is the URL used to get the
// authorization token using the IamApiKey. It defaults to https://iam.bluemix.net/identity/token
TokenOptions iamTokenOptions = new TokenOptions()
{
IamApiKey = "API KEY",
IamUrl = "https://iam.bluemix.net/identity/token"
};
// Create credentials using the IAM token options
_credentials = new Credentials(iamTokenOptions, "https://gateway-fra.watsonplatform.net/assistant/api");
while (!_credentials.HasIamTokenData())
yield return null;
_assistant = new Assistant(_credentials);
_assistant.VersionDate = "2018-11-01";
Debug.Log(_assistant.GetServiceID()); // returns "AssitantV2"
}
public void PingAssistantV2() // triggered from a button press in UI
{
_assistant.CreateSession(OnCreateSession, OnFail, AssistantID); // Assistant ID is entered through the Inspector
}
public void OnCreateSession(SessionResponse response, Dictionary<string, object> customData)
{
Log.Debug("ExampleAssistantV2.OnMessage()", "Assistant: Create Session Response: {0}", customData["json"].ToString());
string _si = response.SessionId;
Debug.Log("SessionID: " +_si);
MessageInput mi = new MessageInput();
mi.Text = Query.textComponent.text; // get user query from an input field in unity UI
MessageRequest messageRequest = new MessageRequest()
{
Input = mi
};
Debug.LogFormat("<b> Query Sent: {0} </b>", Query.textComponent.text);
if (response.SessionId != null ) _assistant.Message(OnMessage, OnFail, AssistantID, _si, messageRequest);
}
private void OnMessage(MessageResponse AssistantResponse, Dictionary<string, object> customData)
{
Log.Debug("ExampleAssistant.OnMessage()", "Response: {0}", customData["json"].ToString());
Debug.LogFormat("<b> SUCCESS </b>");
Debug.Log(customData["json"].ToString());
// Convert resp to fsdata
fsData fsdata = null;
fsResult r = _serializer.TrySerialize(AssistantResponse.GetType(), AssistantResponse, out fsdata);
if (!r.Succeeded)
throw new WatsonException(r.FormattedMessages);
// Convert fsdata to MessageResponse
IBM.WatsonDeveloperCloud.Assistant.v2.MessageResponse messageResponse = new IBM.WatsonDeveloperCloud.Assistant.v2.MessageResponse();
object obj = messageResponse;
r = _serializer.TryDeserialize(fsdata, obj.GetType(), ref obj);
if (!r.Succeeded)
throw new WatsonException(r.FormattedMessages);
Response.text = AssistantResponse.Output.Generic.First().Text; // send response to unity UI text box
}
private void OnFail(RESTConnector.Error error, Dictionary<string, object> customData)
{
Log.Debug("OnFail()", "Failed: {0}", error.ToString());
Debug.LogFormat("<b> Failed </b>");
Debug.Log(error.ToString());
}
EDIT to address #Taj's comment
The Issue persists even with the sample for assitant V2 in the SDK:
Wrong Unity Responses v/s appropriate responses in dashboardtrail
The code adopted from the example included in the SDK:
/**
* Copyright 2018 IBM Corp. All Rights Reserved.
*
* 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.
*
*/
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using IBM.Watson.DeveloperCloud.Connection;
using IBM.Watson.DeveloperCloud.Logging;
using IBM.Watson.DeveloperCloud.Utilities;
using IBM.WatsonDeveloperCloud.Assistant.v2;
using UnityEngine;
using TMPro;
namespace IBM.Watson.DeveloperCloud.Services.Assistant.v2
{
public class ExampleAssistantV2 : MonoBehaviour
{
#region PLEASE SET THESE VARIABLES IN THE INSPECTOR
[Space(10)]
[Tooltip("The service URL (optional). This defaults to \"https://gateway.watsonplatform.net/assistant/api\"")]
[SerializeField]
private string _serviceUrl;
[Tooltip("The assistantId to run the example.")]
[SerializeField]
private string _assistantId;
[Tooltip("The version date with which you would like to use the service in the form YYYY-MM-DD.")]
[SerializeField]
private string _versionDate;
[Header("CF Authentication")]
[Tooltip("The authentication username.")]
[SerializeField]
private string _username;
[Tooltip("The authentication password.")]
[SerializeField]
private string _password;
[Header("IAM Authentication")]
[Tooltip("The IAM apikey.")]
[SerializeField]
private string _iamApikey;
[Tooltip("The IAM url used to authenticate the apikey (optional). This defaults to \"https://iam.bluemix.net/identity/token\".")]
[SerializeField]
private string _iamUrl;
#endregion
private Assistant _service;
private bool _createSessionTested = false;
private bool _messageTested = false;
private bool _deleteSessionTested = false;
private string _sessionId;
public TMP_InputField query;
public TextMeshProUGUI response;
private void Start()
{
LogSystem.InstallDefaultReactors();
Runnable.Run(CreateService());
}
private IEnumerator CreateService()
{
// Create credential and instantiate service
Credentials credentials = null;
if (!string.IsNullOrEmpty(_username) && !string.IsNullOrEmpty(_password))
{
// Authenticate using username and password
credentials = new Credentials(_username, _password, _serviceUrl);
}
else if (!string.IsNullOrEmpty(_iamApikey))
{
// Authenticate using iamApikey
TokenOptions tokenOptions = new TokenOptions()
{
IamApiKey = _iamApikey,
IamUrl = _iamUrl
};
credentials = new Credentials(tokenOptions, _serviceUrl);
// Wait for tokendata
while (!credentials.HasIamTokenData())
yield return null;
}
else
{
throw new WatsonException("Please provide either username and password or IAM apikey to authenticate the service.");
}
_service = new Assistant(credentials);
_service.VersionDate = _versionDate;
Runnable.Run(SessionCreate());
}
private IEnumerator SessionCreate()
{
Log.Debug("ExampleAssistantV2.Examples()", "Attempting to CreateSession");
_service.CreateSession(OnCreateSession, OnFail, _assistantId);
while (!_createSessionTested)
{
yield return null;
}
}
private IEnumerator Examples()
{
Log.Debug("ExampleAssistantV2.Examples()", "Attempting to Message");
MessageInput mi = new MessageInput(); // construct a messgae input
mi.Text = query.textComponent.text;
MessageRequest messageRequest = new MessageRequest() // construct a message request
{
Input = mi
};
Log.Debug("ExampleAssistantV2.OnDeleteSession()", "<b>Query: </b> <b>{0}</b>", messageRequest.Input.Text);
_service.Message(OnMessage, OnFail, _assistantId, _sessionId,messageRequest); // send a message request
while (!_messageTested)
{
yield return null;
}
//Log.Debug("ExampleAssistantV2.Examples()", "Attempting to DeleteSession");
//_service.DeleteSession(OnDeleteSession, OnFail, _assistantId, _sessionId);
//while (!_deleteSessionTested)
//{
// yield return null;
//}
//Log.Debug("ExampleAssistantV2.Examples()", "Assistant examples complete.");
}
private void OnDeleteSession(object response, Dictionary<string, object> customData)
{
Log.Debug("ExampleAssistantV2.OnDeleteSession()", "Session deleted.");
_createSessionTested = true;
}
private void OnMessage(MessageResponse _response, Dictionary<string, object> customData)
{
_messageTested = true;
response.text = _response.Output.Generic.First().Text; // trying to get response
Log.Debug("ExampleAssistantV2.OnDeleteSession()", "<b>RESPONSE: </b> <b>{0}</b>", response.text);
}
private void OnCreateSession(SessionResponse response, Dictionary<string, object> customData)
{
Log.Debug("ExampleAssistantV2.OnCreateSession()", "Session: <b>{0}</b>", response.SessionId);
_sessionId = response.SessionId;
_createSessionTested = true;
}
private void OnFail(RESTConnector.Error error, Dictionary<string, object> customData)
{
Log.Debug("ExampleAssistantV2.OnFail()", "Call failed: {0}: {1}", error.ErrorCode, error.ErrorMessage);
}
public void PingAssitant ()
{
Runnable.Run(Examples());
}
}
}
I can see from your log that you have a new sessionId each time you message. You do not need to create a session each time you send a message. The session should persist during the conversation. I moved the call to CreateSession to your TokenExample() and call PingAssistantV2() once you have a sessionId.
string _si = "";
IEnumerator TokenExample()
{
// Create IAM token options and supply the apikey. IamUrl is the URL used to get the
// authorization token using the IamApiKey. It defaults to https://iam.bluemix.net/identity/token
TokenOptions iamTokenOptions = new TokenOptions()
{
IamApiKey = "API KEY",
IamUrl = "https://iam.bluemix.net/identity/token"
};
// Create credentials using the IAM token options
_credentials = new Credentials(iamTokenOptions, "https://gateway-fra.watsonplatform.net/assistant/api");
while (!_credentials.HasIamTokenData())
yield return null;
_assistant = new Assistant(_credentials);
_assistant.VersionDate = "2018-11-01";
Debug.Log(_assistant.GetServiceID()); // returns "AssitantV2"
_assistant.CreateSession(OnCreateSession, OnFail, AssistantID); // Assistant ID is entered through the Inspector
}
public void PingAssistantV2() // triggered from a button press in UI
{
MessageInput mi = new MessageInput();
mi.Text = Query.textComponent.text; // get user query from an input field in unity UI
MessageRequest messageRequest = new MessageRequest()
{
Input = mi
};
Debug.LogFormat("<b> Query Sent: {0} </b>", Query.textComponent.text);
if (response.SessionId != null ) _assistant.Message(OnMessage, OnFail, AssistantID, _si, messageRequest);
}
public void OnCreateSession(SessionResponse response, Dictionary<string, object> customData)
{
Log.Debug("ExampleAssistantV2.OnMessage()", "Assistant: Create Session Response: {0}", customData["json"].ToString());
_si = response.SessionId;
Debug.Log("SessionID: " +_si);
PingAssistantV2();
}
private void OnMessage(MessageResponse AssistantResponse, Dictionary<string, object> customData)
{
Log.Debug("ExampleAssistant.OnMessage()", "Response: {0}", customData["json"].ToString());
Debug.LogFormat("<b> SUCCESS </b>");
Debug.Log(customData["json"].ToString());
// Convert resp to fsdata
fsData fsdata = null;
fsResult r = _serializer.TrySerialize(AssistantResponse.GetType(), AssistantResponse, out fsdata);
if (!r.Succeeded)
throw new WatsonException(r.FormattedMessages);
// Convert fsdata to MessageResponse
IBM.WatsonDeveloperCloud.Assistant.v2.MessageResponse messageResponse = new IBM.WatsonDeveloperCloud.Assistant.v2.MessageResponse();
object obj = messageResponse;
r = _serializer.TryDeserialize(fsdata, obj.GetType(), ref obj);
if (!r.Succeeded)
throw new WatsonException(r.FormattedMessages);
Response.text = AssistantResponse.Output.Generic.First().Text; // send response to unity UI text box
}
private void OnFail(RESTConnector.Error error, Dictionary<string, object> customData)
{
Log.Debug("OnFail()", "Failed: {0}", error.ToString());
Debug.LogFormat("<b> Failed </b>");
Debug.Log(error.ToString());
}
#taj your develop branch at https://github.com/watson-developer-cloud/unity-sdk/archive/develop.zip is now working! Thank you for your commitment towards sorting this out. I do not have sufficient rep to upvote your answer but ya, Kudos!
Working Code as provided by #taj on the WDC Slack channel:
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using IBM.Watson.DeveloperCloud.Connection;
using IBM.Watson.DeveloperCloud.Logging;
using IBM.Watson.DeveloperCloud.Utilities;
using IBM.WatsonDeveloperCloud.Assistant.v2;
using UnityEngine;
using TMPro;
namespace IBM.Watson.DeveloperCloud.Services.Assistant.v2
{
public class ExampleAssistantV2b : MonoBehaviour
{
#region PLEASE SET THESE VARIABLES IN THE INSPECTOR
[Space(10)]
[Tooltip("The service URL (optional). This defaults to \"https://gateway.watsonplatform.net/assistant/api\"")]
[SerializeField]
private string _serviceUrl;
[Tooltip("The assistantId to run the example.")]
[SerializeField]
private string _assistantId;
[Tooltip("The version date with which you would like to use the service in the form YYYY-MM-DD.")]
[SerializeField]
private string _versionDate;
[Header("CF Authentication")]
[Tooltip("The authentication username.")]
[SerializeField]
private string _username;
[Tooltip("The authentication password.")]
[SerializeField]
private string _password;
[Header("IAM Authentication")]
[Tooltip("The IAM apikey.")]
[SerializeField]
private string _iamApikey;
[Tooltip("The IAM url used to authenticate the apikey (optional). This defaults to \"https://iam.bluemix.net/identity/token\".")]
[SerializeField]
private string _iamUrl;
#endregion
private Assistant _service;
private string _sessionId;
public TMP_InputField query;
public TextMeshProUGUI response;
public List<string> testQueryList;
public int queryNum = 0;
private void Start()
{
LogSystem.InstallDefaultReactors();
testQueryList = new List<string>()
{
"",
"What are your hours?",
"Are you open on Christmas?",
"I would like to make an appointment",
"Friday at 12pm",
"yes"
};
Runnable.Run(CreateService());
}
private IEnumerator CreateService()
{
// Create credential and instantiate service
Credentials credentials = null;
if (!string.IsNullOrEmpty(_username) && !string.IsNullOrEmpty(_password))
{
// Authenticate using username and password
credentials = new Credentials(_username, _password, _serviceUrl);
}
else if (!string.IsNullOrEmpty(_iamApikey))
{
// Authenticate using iamApikey
TokenOptions tokenOptions = new TokenOptions()
{
IamApiKey = _iamApikey,
IamUrl = _iamUrl
};
credentials = new Credentials(tokenOptions, _serviceUrl);
// Wait for tokendata
while (!credentials.HasIamTokenData())
yield return null;
}
else
{
throw new WatsonException("Please provide either username and password or IAM apikey to authenticate the service.");
}
_service = new Assistant(credentials);
_service.VersionDate = _versionDate;
SessionCreate();
}
private void SessionCreate()
{
Log.Debug("ExampleAssistantV2.Examples()", "Attempting to CreateSession");
_service.CreateSession(OnCreateSession, OnFail, _assistantId);
}
private void Examples()
{
Log.Debug("ExampleAssistantV2.Examples()", "Attempting to Message");
MessageInput mi = new MessageInput(); // construct a messgae input
//mi.Text = query.textComponent.text;
mi.Text = testQueryList[queryNum];
MessageRequest messageRequest = new MessageRequest() // construct a message request
{
Input = mi
};
Log.Debug("ExampleAssistantV2.OnDeleteSession()", "<b>Query: </b> <b>{0}</b>", messageRequest.Input.Text);
_service.Message(OnMessage, OnFail, _assistantId, _sessionId, messageRequest); // send a message request
}
private void OnMessage(MessageResponse _response, Dictionary<string, object> customData)
{
//response.text = _response.Output.Generic[0].Text; // trying to get response
string assistantResponse = _response.Output.Generic[0].Text; // trying to get response
Log.Debug("ExampleAssistantV2.OnDeleteSession()", "<b>RESPONSE: </b> <b>{0}</b>", assistantResponse);
queryNum++;
}
private void OnCreateSession(SessionResponse response, Dictionary<string, object> customData)
{
Log.Debug("ExampleAssistantV2.OnCreateSession()", "Session: <b>{0}</b>", response.SessionId);
_sessionId = response.SessionId;
}
private void OnFail(RESTConnector.Error error, Dictionary<string, object> customData)
{
Log.Debug("ExampleAssistantV2.OnFail()", "Call failed: {0}: {1}", error.ErrorCode, error.ErrorMessage);
}
public void PingAssitant()
{
Examples();
}
}
}

Signing AWS Api Gateway request in Unity3D C#

I'm using Unity3D v5.5.1, with AWS-SDK-Unity v3.3.37.0.
Since the Api Gateway doesn't generate an SDK for C#/Unity3D I'm trying to sign (SigV4) the request my self and have encountered difficulties.
I've tried both manually signing and using the AWS4Signer.cs class.
The Api Gateway method has the Invoke with caller credentials, and just returns a Hello World as a response.
Within unity I have a facebook login button which returns the FB credentials and tokens. Using Cognito Federated Identity's GetCredentialsAsync method I get an ImmutableCredentials object with the Key, Secret and a Token.
To access the api gateway url I'm using the AWS4Signer class here to construct a signed request. In the example below I've tried both adding the security token to the url parameters and without, also signing it and not signing with the token. All options don't work (As stated in this post)
This results in either the following responses:
1. The request signature we calculated does not match the signature you provided
The security token included in the request is invalid.
How can I correctly sign the request from Unity3D?
Thanks in advance
TestGet method:
IEnumerator TestGet (ImmutableCredentials response)
{
ApiGatewayConfig clientConfig = new ApiGatewayConfig(); // a class I created wrapping the ClientConfig.cs
var metrics = new RequestMetrics();
var awsAccessKeyId = response.AccessKey;
var awsSecretAccessKey = response.SecretKey;
var awsToken = response.Token;
AmazonWebServiceRequest req = new MyRequest(); // a clas I created wrapping the AmazonWebServiceRequest.cs class
var url = "https://<url_to_api>.execute-api.us-east-1.amazonaws.com/dev/securehello";
IRequest request = new DefaultRequest(req,"execute-api");
request.UseQueryString = true;
request.HttpMethod = "GET";
request.Endpoint = new System.Uri (url);
request.ResourcePath = url;
request.ContentStream = new MemoryStream();
request.Parameters.Add("X-Amz-Expires",AWS4PreSignedUrlSigner.MaxAWS4PreSignedUrlExpiry.ToString(CultureInfo.InvariantCulture));
request.AuthenticationRegion = "us-east-1";
request.AlternateEndpoint = RegionEndpoint.USEast1;
request.UseSigV4 = true;
request.Headers.Add("X-Amz-Security-Token",awsToken);
request.Parameters.Add("X-Amz-Security-Token",awsToken);
AWS4Signer signer = new AWS4Signer();
Debug.Log ("a");
signer.Sign(request,clientConfig,metrics,awsAccessKeyId,awsSecretAccessKey);
var signerRes = signer.SignRequest(request,clientConfig,metrics,awsAccessKeyId,awsSecretAccessKey);
Debug.Log ("b");
var myParams = string.Format("{0}&X-Amz-Security-Token={1}",signerRes.ForQueryParameters,awsToken);
var dict = myParams.Split('&').Select(p=> p.Split('=')).GroupBy(p => p[0]).Select(p => p.First()).ToDictionary(p => p[0], p=>System.Uri.UnescapeDataString(p[1]));
var myEncodedParams = string.Empty;
bool isFirst = true;
foreach (var key in dict.Keys) {
myEncodedParams += string.Format("{0}{1}={2}",isFirst ? "" : "&",key,WWW.EscapeURL(dict[key]));
isFirst = false;
}
var finalUrl = string.Format ("{0}?{1}", request.Endpoint.AbsoluteUri,myEncodedParams);
UnityWebRequest uwr = new UnityWebRequest (finalUrl, "GET", new DownloadHandlerBuffer (), null);
Debug.Log ( string.Format("\n\n\n{0}\n\n\n",finalUrl));
Debug.Log ("Starting WebRequest");
yield return uwr.Send();
if (uwr.isError) {
Debug.LogError (uwr.error);
} else {
Debug.Log (uwr.downloadHandler.text);
}
Helper classes:
public class ApiGatewayConfig : ClientConfig
{
private static readonly string UserAgentString =
InternalSDKUtils.BuildUserAgentString("3.3.37.0");
private string _userAgent = UserAgentString;
public ApiGatewayConfig ()
{
this.AuthenticationServiceName = "execute-api";
}
/// <summary>
/// The constant used to lookup in the region hash the endpoint.
/// </summary>
public override string RegionEndpointServiceName
{
get
{
return "execute-api";
}
}
/// <summary>
/// Gets the ServiceVersion property.
/// </summary>
public override string ServiceVersion
{
get
{
return "2015-07-09";
}
}
/// <summary>
/// Gets the value of UserAgent property.
/// </summary>
public override string UserAgent
{
get
{
return _userAgent;
}
}
}
public class MyRequest : AmazonWebServiceRequest
{
public MyRequest () {}
}
Solved.
I've created some examples showing how to do this. Still work in progress, example shows how to sign a POST request from Unity 3D to Api Gateway endpoint that has "Invoke with caller credentials" (AWS_IAM).
Unity 3D Client:
https://github.com/guywald/serverless-auth-msg-board-unity3d-client
AWS Serverless backend (using Serverless Framework):
https://github.com/guywald/serverless-auth-msg-board

Parse.com - iOS push notifications and Unity integration

I notice that Parse Unity support still doesn't provide push notification for iOS.
Has anyone implemented a Unity plugin or another solution to support iOS Push Notifications via Parse?
(Cross posted on Unity Answers.)
It's actually possible now, using a ParseObject to mock up the ParseInstallation object.
Gist here: https://gist.github.com/gfosco/a3d092651c32ba3385e6
Explanation in the Parse Google Group: https://groups.google.com/d/msg/parse-developers/ku8-r91_o6s/6ioQ9T2TP7wJ
Attach this script to a GameObject, replace the important parts with your own:
using UnityEngine;
using System.Collections;
using Parse;
public class PushBehaviorScript : MonoBehaviour {
bool tokenSent = false;
public ParseObject currentInstallation = null;
void Start () {
if (PlayerPrefs.HasKey ("currentInstallation")) {
string objId = PlayerPrefs.GetString ("currentInstallation");
currentInstallation = ParseObject.CreateWithoutData ("_Installation", objId);
}
if (currentInstallation == null) {
#if UNITY_IPHONE && !UNITY_EDITOR
NotificationServices.RegisterForRemoteNotificationTypes (RemoteNotificationType.Alert | RemoteNotificationType.Badge | RemoteNotificationType.Sound);
#endif
}
}
void FixedUpdate () {
if (!tokenSent && currentInstallation == null) {
#if UNITY_IPHONE && !UNITY_EDITOR
byte[] token = NotificationServices.deviceToken;
if(token != null) {
tokenSent = true;
string tokenString = System.BitConverter.ToString(token).Replace("-", "").ToLower();
Debug.Log ("OnTokenReived");
Debug.Log (tokenString);
ParseObject obj = new ParseObject("_Installation");
obj["deviceToken"] = tokenString;
obj["appIdentifier"] = "com.parse.unitypush";
obj["deviceType"] = "ios";
obj["timeZone"] = "UTC";
obj["appName"] = "UnityPushTest";
obj["appVersion"] = "1.0.0";
obj["parseVersion"] = "1.3.0";
obj.SaveAsync().ContinueWith(t =>
{
if (obj.ObjectId != null) {
PlayerPrefs.SetString ("currentInstallation", obj.ObjectId);
}
});
}
#endif
}
}
}
To implement iOS push with parse.com You need to get the token from apple first. Then save Current instalation
Unity does have this functionality build in now.
//push notification
bool tokenSent = false;
void RegisterForPush()
{
Debug.Log("Register for push");
tokenSent = false;
#if UNITY_IOS
UnityEngine.iOS.NotificationServices.RegisterForNotifications(NotificationType.Alert |
NotificationType.Badge |
NotificationType.Sound, true);
#endif
}
void Update () {
if (!tokenSent) {
byte[] token = UnityEngine.iOS.NotificationServices.deviceToken;
if (token != null) {
// send token to a provider
tokenSent = true;
string hexToken = "%" + System.BitConverter.ToString(token).Replace('-', '%');
#if UNITY_IOS
ParseManager.instance.RegisterForPush(hexToken);
#endif
}
}
}
And inside ParseManager (or whatever class you use to manage parse>client communication)
public void RegisterForPush(string token) {
Debug.Log("Parse updating instalation");
ParseInstallation instalation = ParseInstallation.CurrentInstallation;
instalation["deviceToken"] = token;
instalation["user"] = ParseUser.CurrentUser.ObjectId;
instalation["timeZoneOffset"] = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
instalation.SaveAsync();
}
Tested on Unity 5.1.2 and iOS 8.4

CFC not found with paypal sdk

I am using a colfusion paypal SDK for direct payments, the link is here:
https://github.com/paypal/nvp-coldfusion-sdk
I have pasted the application.cfc file below. My issue is that every time I go to the samples --> dodirectpayment.cfm and submit the test form, It states "Error: Could not find the ColdFusion component or interface CallerService." I think this has to do with referencing the callerservice.cfc file, but can't figure out what is going wrong. Any help is much appreciated. The application.cfc is here.
<cfscript>
/**
#dateCreated "July 18, 2011"
#hint "You implement methods in Application.cfc to handle ColdFusion application events and set variables in the CFC to configure application characteristics."
*/
component output="false" {
/* **************************** APPLICATION VARIABLES **************************** */
THIS.name = "NVPSample";
THIS.applicationTimeout = createTimeSpan(0, 2, 0, 0);
customtagpaths = "{#getDirectoryFromPath(ExpandPath('../lib/'))#,#getDirectoryFromPath(ExpandPath('../lib/services/'))#}";
THIS.customTagPaths = customtagpaths;
THIS.serverSideFormValidation = true;
THIS.sessionManagement = true;
THIS.sessionTimeout = createTimeSpan(0, 0, 30, 0);
THIS.setClientCookies = true;
THIS.setDomainCookies = false;
THIS.scriptProtect = true;
THIS.secureJSON = false;
THIS.secureJSONPrefix = "";
THIS.enablerobustexception = true;
/* **************************** APPLICATION METHODS **************************** */
public void function onApplicationEnd(struct ApplicationScope=structNew()) {
return;
}
public boolean function onApplicationStart() {
return true;
}
public void function onCFCRequest(required string cfcname, required string method, required string args) {
return;
}
public void function onRequestEnd() {
return;
}
public boolean function onRequestStart(required string TargetPage) {
request.serverURL = "https://api-3t.sandbox.paypal.com/nvp";
/* SUBJECT to be uncommented for UNIPAY all the other credentials like API username,
password,signature can be commented for UNIPAY
To enable Payments for Third Party Email whcih will be passed along with Partner's 3token credentials
uncomment both subject and 3 token credentials.
*/
request.SUBJECT="sales-facilitator#totalsportsadvantage.com";
APIuserName = "sales-facilitator_api1.totalsportsadvantage.com";
APIPassword = "1387466817";
APISignature = "An5ns1Kso7MWUdW4ErQKJJJ4qi4-AMJWATXVSChE1ExjnH8FyoZD8U5Q";
/*
request.SUBJECT="clip_1309031681_biz#paypal.com";
APIuserName = "clip_1309031681_biz_api1.paypal.com";
APIPassword = "1309031732";
APISignature = "AFcWxV21C7fd0v3bYYYRCpSSRl31An2lFbilAjH412uQjiC0OEJh45pL";
*/
//condition to check if it is UNIPAY
if (isdefined("SUBJECT") && (isdefined("APIuserName") eq "false" && isdefined("APIPassword") eq "false" && isdefined("APISignature") eq "false") )
{
request.UNIPAYSUBJECT="#SUBJECT#";
request.USER = "";
request.PWD = "";
request.SIGNATURE = "";
}
//condition to check if it is Payments for Third Party Email
if (isdefined("SUBJECT") && isdefined("APIuserName") && isdefined("APIPassword") && isdefined("APISignature"))
{
request.UNIPAYSUBJECT="#SUBJECT#";
request.USER = "#APIuserName#";
request.PWD = "#APIPassword#";
request.SIGNATURE = "#APISignature#";
}
//condition to check if it is 3 token credentials
if (isdefined("SUBJECT") eq "false" && isdefined("APIuserName") && isdefined("APIPassword") && isdefined("APISignature") )
{
request.UNIPAYSUBJECT="";
request.USER = "#APIuserName#";
request.PWD = "#APIPassword#";
request.SIGNATURE = "#APISignature#";
}
request.PayPalURL = "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=";
request.version = "65.1";
/*
By default the API requests doesn't go through proxy. To route the requests through a proxy server
set "useProxy" value as "true" and set values for proxyName and proxyPort. Set proxyName with
the Host Name or the IP address of the proxy server. proxyPort should be a valid port number.
eg:
useProxy = "true";
proxyName = "127.0.0.1";
proxyPort = "8081";
*/
request.useProxy = "false";
request.proxyName = "";
request.proxyPort = "";
return true;
}
public void function onSessionEnd(required struct SessionScope, struct ApplicationScope=structNew()) {
return;
}
public void function onSessionStart() {
return;
}
}
</cfscript>
the getDirectoryFromPath did refer to an actual location of those files, but for some reason the application wasn't finding them in that location. The ultimate solution was to copy the files into the same folder as the application.cfc file and things are working as expected. Thanks for the help.

Error using facebook C# sdk with WPF web browser

I am new to facebook c# sdk. I followed the tutorial in this link.
I created an application that displays the user name after log in. Here is my code:
public partial class MainWindow : Window
{
private string appId = "appid";
private string extenededPermissions = "offline_access,publish_stream";
private Uri loginUrl = null;
private string accessToken = null;
private string userName = null;
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// Function to get the login url
/// with the requested permissions
/// </summary>
private void GetLoginUrl()
{
dynamic parameters = new ExpandoObject();
// add the client id
parameters.client_id = appId;
// add the redirect uri
parameters.redirect_uri = "https://www.facebook.com/connect/login_success.html";
// requested response
parameters.response_type = "token";
// type of display
parameters.display = "popup";
// If extended permissions are present
if (!string.IsNullOrWhiteSpace(extenededPermissions))
parameters.scope = extenededPermissions;
// Create the login url
Facebook fc = new FacebookClient();
loginUrl = fc.GetLoginUrl(parameters);
}
private void WindowLoaded(object sender, RoutedEventArgs e)
{
// get the login url
GetLoginUrl();
// Navigate to that page
webBrowser.Navigate(loginUrl);
}
private void webBrowser_Navigated(object sender, NavigationEventArgs e)
{
var fc = new FacebookClient();
FacebookOAuthResult fr;
// Check the returned url
if (fc.TryParseOAuthCallbackUrl(e.Uri, out fr))
{
// check if authentication is success or not
if (fr.IsSuccess)
{
getUserName(out userName);
}
else
{
var errorDes = fr.ErrorDescription;
var errorReason = fr.ErrorReason;
}
}
else
{
}
}
private void getUserName(out string name)
{
var fb = new FacebookClient(accessToken);
// Get the user details
dynamic result = fb.Get("me");
// Get the user name
name = result.name;
MessageBox.Show("Hai " + name + ",Welcome to my App");
}
}
My Problem is with the FacebookOAuthResult.
private void webBrowser_Navigated(object sender, NavigationEventArgs e)
{
var fc = new FacebookClient();
FacebookOAuthResult fr;
// Check the returned url
if (fc.TryParseOAuthCallbackUrl(e.Uri, out fr))
{
// check if authentication is success or not
if (fr.IsSuccess)
{
getUserName(out userName);
}
else
{
var errorDes = fr.ErrorDescription;
var errorReason = fr.ErrorReason;
}
}
else
{
}
}
After I logged in it is redirecting to redirect_uri. But the fc.TryParseOAuthCallbackUrl(e.Uri, out fr) fails though the webbrowser redirects to the Authentication successful page.
So I couldn't get the access token. What could the problem in my code be?
This doesn't answer the question, but I see you are asking for an offline_access permission. Facebook removed offline_access sometime ago. Instead you need an Extended Access Token. You get it by exchanging the access token you are trying to get, for an extended one. They last for about 2-3 months after which you have to get a new one.
Nevermind i have found out the solution..Thanks to the answers for the question!
I have added the Winforms web browser control to the wpf and the authentication is working.The problem is with WPF web browser. It simply omits the url after # token So the parseurl won't able to authenticate it.
Here's the modified code..
private void WindowLoaded(object sender, RoutedEventArgs e)
{
// create the windows form host
System.Windows.Forms.Integration.WindowsFormsHost sample =
new System.Windows.Forms.Integration.WindowsFormsHost();
// create a new web browser
webBrowser = new System.Windows.Forms.WebBrowser();
// add it to winforms
sample.Child = webBrowser;
// add it to wpf
canvas1.Children.Add(sample);
webBrowser.Navigated += webBrowser_Navigated;
webBrowser.Navigate(loginURL);
}
void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
// do the authentication
var fc = new FacebookClient();
FacebookOAuthResult fr;
// Check the returned url
if (fc.TryParseOAuthCallbackUrl(e.Url, out fr))
{
// check if authentication is success or not
if (fr.IsSuccess)
{
accessToken = fr.AccessToken;
// Actions to do
}
else
{
var errordes = fr.ErrorDescription;
var errorreason = fr.ErrorReason;
}
}
else
{
//Not a valid url
}
}
The problem is solved!!