stripe.net - how to process subscriptionService.Get with no results - c#

The stripe.com API only returns active subscriptions. I want to verify when I delete a subscription.
So this is going to return an error. I am not sure how to code for it.
I would prefer to make this call based on the subscriptionId. Will this cause an exception or will it return an error code?
Retrieving a subscription
var subscriptionService = new StripeSubscriptionService();
StripeSubscription stripeSubscription = subscriptionService.Get(*subscriptionId*);
Another options which is somewhat of a hack is to return all the subscriptions for the given customer and test to see if the subscriptionId was returned.
List all subscriptions for a customer
var subscriptionService = new StripeSubscriptionService();
IEnumerable<StripeSubscription> responses = subscriptionService .List(*customerId*);
foreach( var response in responses )
{
if (response.subscriptionId == subscriptionId)
{
// subscription exists and was not deleted
exit;
}
}

Per their documentation, https://stripe.com/docs/api they have 2 different APIs. You're trying to use the RESTful API, which is for retrieving information on demand.
They also have a WebHooks API, which requires you have an endpoint listening on your site which can accept event notifications. You configure these through your Dashboard with them.
The event type you're looking for specifically is probably the customer.subscription.deleted event, but there's a lot more you can do with them and I'd encourage you to explore all of those Webhooks.
I can't offer a code sample, as I don't use their service.

The strip.net example shows the subscriptionService.Cancel as a methed:
var subscriptionService = new StripeSubscriptionService();
subscriptionService.Cancel(*customerId*, *subscriptionId*);
But you can also use it as a function and it returns the subscription object.
var subscriptionService = new StripeSubscriptionService();
StripeSubscription stripeSubscription = subscriptionService.Cancel(*customerId*, *subscriptionId*);
If (stripeSubscription.Status != "canceled")
{
//subscription not cancelled
// take action
}
Per Stripe API docs:
Returns:
The canceled subscription object. Its subscription status will be set to "canceled" unless you've set at_period_end to true when canceling, in which case the status will remain "active" but the cancel_at_period_end attribute will change to true.One of the fiels is .status , witch is set to canceled.

Related

Change Microsoft Graph Resource for Sharepoint Webhook

I am currently working out the Microsoft Graph tutorial with C# .Net Core, and in the process I came across the following C#-method for Subscription:
[HttpGet]
public async Task<ActionResult<string>> Get()
{
var graphServiceClient = GetGraphClient();
var sub = new Microsoft.Graph.Subscription();
sub.ChangeType = "updated";
sub.NotificationUrl = config.Ngrok + "/api/notifications";
sub.Resource = "/users";
sub.ExpirationDateTime = DateTime.UtcNow.AddMinutes(15);
sub.ClientState = "SecretClientState";
var newSubscription = await graphServiceClient
.Subscriptions
.Request()
.AddAsync(sub);
Subscriptions[newSubscription.Id] = newSubscription;
if (subscriptionTimer == null)
{
subscriptionTimer = new Timer(CheckSubscriptions, null, 5000, 15000);
}
return $"Subscribed. Id: {newSubscription.Id}, Expiration: {newSubscription.ExpirationDateTime}";
}
and wanted to know how I can change it for sharepoint lists instead of users.
If I change it to /sites/{site-id} or similar it does not work. (see sub.Resource)
Github-Link: MS Repo
Microsoft Graph API uses a webhook mechanism to deliver change notifications to clients. Using the Microsoft Graph API, an app can subscribe to changes for list under a SharePoint site.
Resource Path - Changes to content within the list:
/sites/{id}/lists/{id}
For details round how to subscribe to and handle incoming notifications, see Set up notifications for changes in user data
Also make sure you check necessary permissions needed here.
I found the solution myself with the sub.Resource: /sites/{site-id}/lists/{list-id}

MS Graph Service Client - How to prove a subscription was created?

I have the following code: (which used to work and really should work from what I understand from MS' documentation)
[Route("msgraphsubscription")]
[HttpPost]
[AllowAnonymous]
public async Task<String> msgraphsubscription()
{
try{
this.userId = "<guid>"
GraphServiceClient graphClient = await GenerateGraphAuthToken(this.accountManagerParameters);
var subscription = new Subscription
{
ChangeType = "updated",
NotificationUrl= notificationURL,
Resource = $"users/{userId}/drive/root",
ExpirationDateTime = DateTimeOffset.Parse("2021-04-23T18:23:45.9356913Z"),
ClientState = "secretClientValue",
LatestSupportedTlsVersion = "v1_2"
};
await graphClient.Subscriptions
.Request()
.AddAsync(subscription);
return $"New subscriptionID: {subscription.Id.ToString()}";
}
catch(Exception ex){
Console.Write(ex);
return "";
}
When I run this code, I get the following error on the return statement in the try{} block:
{System.NullReferenceException: Object reference not set to an instance of an object.
at msgraphtests.msgraphsubscription() in /src/demos/msgraph/SubscriptionManager.cs:line 132}
error CS1733: Expected expression
What's Broken / Not working
The code actually creates a subscription. But... it doesn't return the subscription ID.
What I've Checked
Verified data. Using Postman, I have created a subscription request using the exact same user, and notification url. I pasted both notification URLs from the POSTMAN request and from my app into a text editor, along with both user ids. Then I do a search and verify that the URL from postman actually matches the one from the vscode file. So i'm fairly certain it's not a typo in those fields.
I put a breakpoint though on the return statement, and checked out the contents of my "subscription" variable and this is what it shows:
{Microsoft.Graph.Subscription}
AdditionalData [IDictionary]:null
ApplicationId [string]:null
ChangeType [string]:"updated"
ClientState [string]:"secretClientValue"
CreatorId [string]:null
EncryptionCertificate [string]:null
EncryptionCertificateId [string]:null
ExpirationDateTime:{2021-04-23 6:23:45 PM +00:00}
Resource [string]:"users//drive/root"
But in postman, i see this new subscription:
{
"id": "a5234fffd-75f0-3364-bd12-ddddassf",
"resource": "users/<userguid>/drive/root",
"applicationId": "asdfasdf-97ec-1b33-8888-asdfasdf",
"changeType": "updated",
"clientState": null,
"notificationUrl": "<mynotificationURL>",
"notificationQueryOptions": null,
"lifecycleNotificationUrl": null,
"expirationDateTime": "2021-04-23T18:23:45.9356913Z",
"creatorId": "asdfr-52f5-4822-fffs-afwerwer",
"includeResourceData": null,
"latestSupportedTlsVersion": "v1_2",
"encryptionCertificate": null,
"encryptionCertificateId": null
},
I changed the code to explicitly request the subscription.Id to be returned like this:
await graphClient.Subscriptions
.Request()
.Select(subscription => new {
subscription.Id,
subscription.ExpirationDateTime
})
.AddAsync(subscription);
return $"New subscriptionID: {subscription.ToString()}";
There are no errors... but the id with a value of Null is still being returned to me.
Question
Does anyone know of another way to "prove" the subscription was created using the subscription object itself? (what artifacts can i check in the subscription object?) Did something change on the MS end? cuz this used to work just fine.
THanks.
By looking at your code, it seems that you're expecting that Microsoft's code updates the Subscription object you pass into .AddAsync() method.
However, looking at Microsoft's implementation of the method, they are returning a whole new object back. So, you should do the following:
Subscription subscription = await graphClient.Subscriptions
.Request()
.AddAsync(subscription);

Proper Way To See If Square Checkout Process Completed

I am currently working on a C# Windows Form project that requires the user to pay prior to any processing taking place. I am using the Square .Net SDK for payment processing and have successfully managed to get a payment through to the sandbox environment using the Checkout URL generated by the Checkout API. My question is whether there is a simple way to get whether the payment process has been completed. Right now, I am just polling the API with the same order (with identical idempotency keys) and waiting for it to return an error that the order is no longer valid. Here is the backbone of my current code:
var bodyOrderLineItems = new List<CreateOrderRequestLineItem>();
long totalCost = 100;
var charge0 = new Money.Builder().Amount(totalCost).Currency("USD").Build();
bodyOrderLineItems.Add(new CreateOrderRequestLineItem.Builder("1").Name("Incredibly Valuable Product").BasePriceMoney(charge0).Build());
var order = new CreateOrderRequest.Builder()
.ReferenceId("reference_id")
.LineItems(bodyOrderLineItems)
.Build();
var body = new CreateCheckoutRequest.Builder("Test_iKey4", order)
.AskForShippingAddress(false)
.Build();
var checkoutApi = client.CheckoutApi;
try
{
CreateCheckoutResponse result = checkoutApi.CreateCheckout(locationsString, body);
System.Diagnostics.Process.Start(result.Checkout.CheckoutPageUrl);
while (true)
{
System.Threading.Thread.Sleep(5000);
//while payment hasn't gone through
try
{
result = checkoutApi.CreateCheckout(locationsString, body);
}
catch (ApiException e)
{
MessageBox.Show(e.Errors[0].Detail);
break;
}
}
MessageBox.Show("Payment Must Have Gone Through");
}
catch (ApiException e) { MessageBox.Show(e.Errors[0].Detail); };
Is this a valid approach? While this does seem to work, I feel like I am flooding the api with requests. I am pretty inexperienced with the Square API, so any help would be appreciated.
Typically the Checkout API is used within a website, as it includes a parameter redirect_url so that when the payment is complete, the user is redirected back to your side and it includes url parameters such as the transaction id. If you don't have a website, you can instead sign up for webhooks. The PAYMENT_UPDATED webhook will be sent out when a payment has been processed, so you do not need to do polling; just listen for the webhook.

Subscribe to Outlook/Office 365 API Status Code NotFound in C#

I am getting an issue when creating subscription.
My steps are:
Register app at https://apps.dev.microsoft.com
Update permissions
Read Mail and User's info
Then update code, do same steps at https://learn.microsoft.com/en-us/outlook/rest/dotnet-tutorial
After login, I can get access token
Screen after login
Then I try to create a subscription for Inbox
var newSub = new Subscription
{
Resource = "me/mailFolders{'Inbox'}/messages",
ChangeType = "created,updated",
NotificationUrl = notificationUrl,
ClientState = clientState,
ExpirationDateTime = DateTime.Now.AddMinutes(15)
};
var result = await graphClient.Subscriptions.Request().AddAsync(newSub);
Implement for notification in notification URL - I can get validation token and return in plain text.
public async Task<ActionResult> Listen()
{
if (Request.QueryString["validationToken"] != null)
{
var token = Request.QueryString["validationToken"];
return Content(token, "plain/text");
}
}
But I always get this error.
Is there anyone know problem?
You must expose a public HTTPS endpoint to create a subscription and receive notifications from Microsoft Graph.

Existing authentication with ServiceStack ServerEventsClient

I'm looking for a way to use an existing session ID with the ServiceStack ServerEventsClient. I'd like to use server events, but access will need to be limited to authenticated users.
For JsonServiceClient, I have a method in a library referenced by all of our projects which returns an authenticated JsonServiceClient ready to be used. The purpose is to make development a bit faster by keeping all auth info in one place:
public static JsonServiceClient GetAuthenticatedServiceClient()
{
var ServiceClient = new JsonServiceClient(globals.ApiUrl)
{
RequestFilter = request => request.UserAgent = globals.ClientSoftware.ToString()
};
var CookieQuery = (from c in globals.AuthCookieContainer
where c.Name == "ss-id"
where c.Expires > DateTime.Now
select c);
if (CookieQuery.Count() > 0)
{
ServiceClient.CookieContainer.Add(CookieQuery.FirstOrDefault());
}
else
{
throw new Exceptions.ApiNotAuthenticatedException();
}
return ServiceClient;
}
My question is: Is there a way to implement something similar to the above method for ServerEventsClient? I'm trying to avoid sending an Authenticate request, since I've already got an easy way to get to session information on the client.
The ServerEventsClient.ServiceClient used to maintain the CookieContainer for each ServerEvents request is just a JsonServiceClient so you can access its concrete type with just:
var client = (JsonServiceClient)serverEventsClient.ServiceClient;
So you can take the same approach of transferring cookies between any service client.
The ServerEventsClient.Authenticate literally just makes an Authenticate request on the same ServerEventsClient.ServiceClient instance so it gets populated with the returned cookies from a successful response.

Categories

Resources