Notification on change of data in Xamarin/C# - c#

Hi so I've implemented a method based on this answer:
How to get notification in xamarin forms on firebase data change?
But I'm having trouble getting it working.
Here's my code:
void DoFirebaseObserve()
{
var firebase = new FirebaseClient(Constants.FirebaseProjectUrl);
firebase.Child("RegisterUserTable").AsObservable<RegisterUser>().Subscribe(obs =>
{
switch (obs.EventType)
{
case Firebase.Database.Streaming.FirebaseEventType.InsertOrUpdate:
Console.WriteLine("InsertOrUpdate");
break;
case Firebase.Database.Streaming.FirebaseEventType.Delete:
Console.WriteLine("Delete");
break;
default:
break;
}
});
}
I call this code in the OnAppearing method of my app's home page. I've tried with and without the while (true) {} condition.
When I add, update or delete a record in firebase, nothing happens in my application. The writelines are never called.
Any help would be appreciated. Thanks.

So I worked out how to do it through using Google Cloud Functions in the Firebase console.
Step 1. Set up FCM in your .Net code
Follow this tutorial:
https://learn.microsoft.com/en-us/xamarin/android/data-cloud/google-messaging/remote-notifications-with-fcm?tabs=macos
Once you have got your FCM token from that device, you can add it to your realtime database (I did this myself in the firebase console manually for testing).
Step 2. Set up Cloud Functions
Follow this tutorial:
https://www.youtube.com/watch?v=bpI3Bbhlcas&t=1104s&ab_channel=uNicoDev
Step 3. Create a function to send the message
You can use this node.js code in your cloud functions to send up to 500 devices:
// Create a list containing up to 500 registration tokens.
// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
'YOUR_REGISTRATION_TOKEN_1',
// …
'YOUR_REGISTRATION_TOKEN_N',
];
const message = {
data: {score: '850', time: '2:45'},
tokens: registrationTokens,
};
admin.messaging().sendMulticast(message)
.then((response) => {
console.log(response.successCount + ' messages were sent successfully');
});
Source: https://firebase.google.com/docs/cloud-messaging/send-message#node.js_1
Code Example
Some of my code to help you get an idea of how to go about doing something like this. Can't guarantee this is the optimal method but it works.
const reference = "JourneyTbl/{journeyId}";
// newJourneyAdded | listener method | Send push notif when new journey created:
exports.newJourneyAdded = functions.database.ref(reference)
.onCreate((event, context) => {
// where fcm tokens are stored:
const refNotifications = "NotificationTbl";
// get ref to RegNotTable:
const refFcm = admin.database().ref(refNotifications);
// array to hold all fcms from table:
const allFcms = [];
// get value of "NotificationTbl":
refFcm.on("value", (snapshot) => {
// check if there's any children:
if (snapshot.hasChildren()) {
// loop through children:
snapshot.forEach((element) => {
// stringify the data:
const asString = JSON.stringify(element);
// parse that as a JSON object:
const asJson = JSON.parse(asString);
// add fcm token to array:
allFcms.push(asJson.fcm);
});
}
// if array contains something:
if (allFcms.length > 0) {
// construct message to send:
const msg = {
notification: {
title: "Notification Title goes here",
body: "Notification Body goes here ",
},
tokens: allFcms, // pass the tokens
};
// send that message:
admin.messaging().sendMulticast(msg)
.then((response) => {
console.log(response.successCount + " mgs were sent sfly");
});
} else {
console.log("No devices in FCM tokens list");
}
});
return "ok";
});

Related

how to get AWS SMS publish results in code

I've scoured the AWS documentation to see if there is a a way to get the SMS delivery log via code, but i'm at a miss, I can get the logs via cloud watch but I want to get them in code so if there is a failure ( like delivery.providerResponse
Unknown error attempting to reach phone) I can dequeue the number
this is my code for sending texts, it gets a response code OK all the time even if i've hit my credit limit, the number isnt valid. Viewing failures in the console is great and all, but i want to update my queue programmatically based on success/failure
Regex rgx = new Regex(#"^(07\d{8,12}|447\d{7,11})$");
foreach (var item in accountTextDatas)
{
if (rgx.IsMatch(item.Phone1))
{
item.Phone1 = ReplaceFirst(item.Phone1, "0", "+44");
}
await Task.Delay(2000);
var request = new PublishRequest()
{
Message = $"words go here"
PhoneNumber = item.Phone1,
};
var response = await client.PublishAsync(request);
context.Logger.LogInformation("Response Code to " + item.Phone1 + " " + response.HttpStatusCode);
}
You can fetch the delivery status logs in your code through the CloudWatch API
The CLI equivalent would be something like:
aws logs describe-log-streams --log-group-name sns/$REGION/$ACCOUNT_ID/DirectPublishToPhoneNumber/Failure
{
"logStreams": [
{
"logStreamName": "SOME_LOG_STREAM_NAME", ...
aws logs get-log-events --log-group-name sns/$REGION/$ACCOUNT_ID/DirectPublishToPhoneNumber/Failure --log-stream-name SOME_LOG_STREAM_NAME
{
"events": [
{
"timestamp": 1650659779468,
"message": "{\"notification\":{\"messageId\": ...

Getting error with Stripe: No such payment_intent: 'my payment intent id'

sorry I'm pretty new to coding so I don't know many of the abbreviations/shorthand stuff.
So I'm working with React and C# trying to use Stripe to handle payments and I've gotten to the point where I am getting back a payment_intent id, client_secret, and payment method Id, but when I run the code:
const result = await stripe.confirmCardPayment(this.state.clientSecret, {
payment_method: paymentMethodRQ.paymentMethod.id,
});
I get the error:
No such payment_intent. Which is a 404 for the /v1/payment_intent/confirm
I guess that means the payment intent isn't actually being created since it doesn't show up on the Stripe dashboard either. Not really sure how to fix this. Most of the other similar questions either use different languages or don't address how to solve my particular issue. I followed the documentation for collecting payments then paying out, found at https://stripe.com/docs/connect/collect-then-transfer-guide#setup
This is my React code for the submit:
handleSubmit = async (event) => {
event.preventDefault();
const { stripe, elements } = this.props;
if (!stripe || !elements) {
_logger("Stripe.js has not yet loaded.");
// Make sure to disable form submission until Stripe.js has loaded.
return;
}
const paymentMethodRQ = await stripe.createPaymentMethod({
type: "card",
card: elements.getElement(CardElement),
});
const result = await stripe.confirmCardPayment(this.state.clientSecret, {
payment_method: paymentMethodRQ.paymentMethod.id,
});
if (result.error) {
toast.error("payment not processed");
_logger(result.error.message, "payment not processed");
} else {
toast.success("The payment processing!");
if (result.paymentIntent.status === "succeeded") {
_logger("payument successful");
// havent gotten to this part yet
}
}
};
I am passing in an amount and currency for the PaymentIntentCreateOptions from React.
and this is my controller for the payment intent in Visual Studio:
[HttpPost("paymentintent")]
public async Task<IActionResult> PaymentIntent(PaymentIntentCreateOptions options)
{
StripeConfiguration.ApiKey = "my test secret key";
ItemResponse<PaymentIntentModel> response = new ItemResponse<PaymentIntentModel>();
var service = new PaymentIntentService();
var paymentIntent = service.Create(options);
Logger.LogInformation(paymentIntent.ToString());
var paymentIntentModel = new PaymentIntentModel();
paymentIntentModel.Id = paymentIntent.Id;
paymentIntentModel.ClientSecretKey = paymentIntent.ClientSecret;
response.Item = paymentIntentModel;
return Ok200(response);
}
You have to make sure that your public key you declare in the frontend matches your public key in your stripe account otherwise you will get this error.

Upload progress Aspnet Boilerplate & Angular 7 [duplicate]

Thus there are many ad hoc libraries supporting upload/download progress in angular2, I do not know how to use native angular2 http api to show progress while doing upload/download.
The reason why I want to use native http api is because I want to utilize:
http interceptors (http API wrappers) around native http api that validate, cache & enrich the actual http request being sent such as this & this
Angular's http api is much more robust than any ad hoc APIs
There is a nice article about how to do upload/download using angular's http api
But the article mentions that there is no native way to support progress.
Did anyone try using http api for showing progress?
If not, do you know an issue in the angular repo for this?
As of Angular 4.3.x and beyond versions, it can be achieved using the new HttpClient from #angular/common/http.
Read the Listening to progress events section.
Simple upload example (copied from the section mentioned above):
const req = new HttpRequest('POST', '/upload/file', file, {
reportProgress: true,
});
http.request(req).subscribe(event => {
// Via this API, you get access to the raw event stream.
// Look for upload progress events.
if (event.type === HttpEventType.UploadProgress) {
// This is an upload progress event. Compute and show the % done:
const percentDone = Math.round(100 * event.loaded / event.total);
console.log(`File is ${percentDone}% uploaded.`);
} else if (event instanceof HttpResponse) {
console.log('File is completely uploaded!');
}
});
And for downloading, it might be something like pretty much the same:
const req = new HttpRequest('GET', '/download/file', {
reportProgress: true,
});
http.request(req).subscribe(event => {
// Via this API, you get access to the raw event stream.
// Look for download progress events.
if (event.type === HttpEventType.DownloadProgress) {
// This is an download progress event. Compute and show the % done:
const percentDone = Math.round(100 * event.loaded / event.total);
console.log(`File is ${percentDone}% downloaded.`);
} else if (event instanceof HttpResponse) {
console.log('File is completely downloaded!');
}
});
Remember in case that you're monitoring a download, the Content-Length has to be set, otherwise, there's no way to the request to be measured.
I would suggest using the native JavaScript XHR wrapped as an Observable, it's fairly easy to create on your own:
upload(file: File): Observable<string | number> {
let fd: FormData = new FormData();
fd.append("file", file);
let xhr = new XMLHttpRequest;
return Observable.create(observer => {
xhr.addEventListener("progress", (progress) => {
let percentCompleted;
// Checks if we can really track the progress
if (progress.lengthComputable) {
// progress.loaded is a number between 0 and 1, so we'll multiple it by 100
percentCompleted = Math.round(progress.loaded / progress.total * 100);
if (percentCompleted < 1) {
observer.next(0);
} else {
// Emit the progress percentage
observer.next(percentCompleted);
}
}
});
xhr.addEventListener("load", (e) => {
if (e.target['status'] !== 200) observer.error(e.target['responseText']);
else observer.complete(e.target['responseText']);
});
xhr.addEventListener("error", (err) => {
console.log('upload error', err);
observer.error('Upload error');
});
xhr.addEventListener("abort", (abort) => {
console.log('upload abort', abort);
observer.error('Transfer aborted by the user');
});
xhr.open('POST', 'http://some-dummy-url.com/v1/media/files');
// Add any headers if necessary
xhr.setRequestHeader("Authorization", `Bearer rqrwrewrqe`);
// Send off the file
xhr.send(fd);
// This function will get executed once the subscription
// has been unsubscribed
return () => xhr.abort()
});
}
And this is how one would use it:
// file is an instance of File that you need to retrieve from input[type="file"] element
const uploadSubscription = this.upload(file).subscribe(progress => {
if (typeof progress === Number) {
console.log("upload progress:", progress);
}
});
// To abort the upload
// we should check whether the subscription is still active
if (uploadSubscription) uploadSubscription.unsubscribe();
This is now possible, check out https://angular.io/guide/http#tracking-and-showing-request-progress.
I could give an example here but I think that the official example from the Angular docs would be better

Phone Number Authentication for Firebase Through Unity (C#)

I'm trying to get phone number authentication for Unity up and running but I am getting no SMS response. The documentation online is super unclear about how to do this. I'd much rather have Google Auth for Firebase but apparently it isn't supported yet. Can anyone help me figure out how to get this up and running?
Here is what I have so far...
public class SignIn : MonoBehaviour {
private string phoneNumber;
private string secureCode;
private uint phoneAuthTimeoutMs;
private Firebase.Auth.FirebaseAuth firebaseAuth;
private Credential credential;
private string verificationId;
private string verificationCode;
public Text PhoneNumberInputFieldText;
public Text SecureCodeInputFieldText;
public Button SendSecureCodeButton;
public Button SubmitSecureCodeButton;
// Use this for initialization
void Start()
{
SendSecureCodeButton.GetComponent<Button>().onClick.AddListener(() => StartSignIn());
}
// Update is called once per frame
void Update () {
}
void StartSignIn()
{
firebaseAuth = Firebase.Auth.FirebaseAuth.DefaultInstance;
phoneAuthTimeoutMs = 60000;
phoneNumber = PhoneNumberInputFieldText.text;
Debug.Log(phoneNumber);
if (PlayerPrefs.GetString("secureCode") != null)
{
verificationId = PlayerPrefs.GetString("secureCode");
}
PhoneAuthProvider provider = PhoneAuthProvider.GetInstance(firebaseAuth);
provider.VerifyPhoneNumber(phoneNumber, phoneAuthTimeoutMs, null,
verificationCompleted: (credential) =>
{
// Auto-sms-retrieval or instant validation has succeeded (Android only).
// There is no need to input the verification code.
// `credential` can be used instead of calling GetCredential().
},
verificationFailed: (error) =>
{
// The verification code was not sent.
// `error` contains a human readable explanation of the problem.
},
codeSent: (id, token) =>
{
//Prompt here to type in SecureCode
PlayerPrefs.SetString("secureCode", id);
credential = provider.GetCredential(verificationId, verificationCode);
firebaseAuth.SignInWithCredentialAsync(credential).ContinueWith(task => {
if (task.IsFaulted)
{
Debug.LogError("SignInWithCredentialAsync encountered an error: " +
task.Exception);
return;
}
FirebaseUser newUser = task.Result;
Debug.Log("User signed in successfully");
// This should display the phone number.
Debug.Log("Phone number: " + newUser.PhoneNumber);
// The phone number providerID is 'phone'.
Debug.Log("Phone provider ID: " + newUser.ProviderId);
});
// Verification code was successfully sent via SMS.
// `id` contains the verification id that will need to passed in with
// the code from the user when calling GetCredential().
// `token` can be used if the user requests the code be sent again, to
// tie the two requests together.
},
codeAutoRetrievalTimeOut: (id) =>
{
// Called when the auto-sms-retrieval has timed out, based on the given
// timeout parameter.
// `id` contains the verification id of the request that timed out.
});
}
}
Thanks in advance!
Here is my Firebase Console:
I'll post an answer but i'll edit this.
Try a simplier sending SMS phone verification
Firebase.Auth.FirebaseAuth auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
phoneNumber = "your phone number here";//state the phone number here first
uint phoneAuthTimeoutMs = 10000;
PhoneAuthProvider provider = PhoneAuthProvider.GetInstance(auth);
provider.VerifyPhoneNumber(phoneNumber, phoneAuthTimeoutMs,null,
verificationCompleted: (credential) => {
},
verificationFailed: (error) => {
},
codeSent: (id, token) => {
MyText.text = "SMS Has been sent " + id;
},
codeAutoRetrievalTimeOut : (id) => {
});
MyText.text += "HMM";
Then please tell me if it works. Now if it works we will proceed to the next step

Braintree Webhook - Check URL not working

I have set up a webhook in my Braintree account https://example.com/Webhook/Accept
I have the site setup to create a Customer & Subscription via a purchase link.
When I make a purchase via the link these are both created ok in the Braintree vault, the webhook fires and I receive 2 notifications.
This all seems great, all is working, except the for 'Check URL' in the Braintree Control panel Webhook section, where im getting a HTTP error 500 internal server error.
I think its a bt_challenge issue on the GET but having tried a few variations I simply cant get it working.
Here is my controller:
public class WebhookController : Controller
{
public IBraintreeConfiguration config = new BraintreeConfiguration();
public ActionResult Accept()
{
CrmDB db = new CrmDB();
Log log;
var gateway = config.GetGateway();
if (Request.HttpMethod == "POST")
{
WebhookNotification webhookNotification = gateway.WebhookNotification.Parse(
Request.Params["bt_signature"],
Request.Params["bt_payload"]
);
string message = string.Format(
"[Webhook Received {0}] | Kind: {1} | Subscription: {2}",
webhookNotification.Timestamp.Value,
webhookNotification.Kind,
webhookNotification.Subscription.Id
);
System.Console.WriteLine(message);
// Save to Db
log = new Log
{
Stamp = DateTime.Now,
App = "api/Webhook/Accept",
IsInsight = true,
Insight = message
};
// Db
db.Log.Add(log);
db.SaveChanges();
return new HttpStatusCodeResult(200);
}
else
{
string msg = gateway.WebhookNotification.Verify(Request.QueryString["bt_challenge"]);
// Save to Db
log = new Log
{
Stamp = DateTime.Now,
App = "Webhook - bt_challenge",
IsInsight = true,
Insight = msg
};
// Db
db.Log.Add(log);
db.SaveChanges();
return Content(msg);
}
}
}
I believe the issue is in the else section (ie HTTP GET) but I cant work out what it is.
Why am I getting the 500 internal error from Webhook control Panel?

Categories

Resources