I am using stripe API and .net to create subscriptions.
my issue is that when i create a subscription the meta data is saved on the subscription instead of being saved on the payment.
is there a way to save the meta data on the first subscription payment instead?
that is what i have tried so far :
var subscriptionOptions = new SubscriptionCreateOptions
{
Customer = customerID,
Items = new List<SubscriptionItemOptions>
{
new SubscriptionItemOptions
{
Price = priceID,
Quantity = 1
},
},
PaymentBehavior = "default_incomplete",
Metadata = new Dictionary<string, string>
{
{ "id", "123"},
{ "name", "david" },
},
};
subscriptionOptions.AddExpand("latest_invoice.payment_intent");
var subscriptionService = new SubscriptionService();
try
{
Subscription subscription = await subscriptionService.CreateAsync(subscriptionOptions);
return new SubscriptionCreateResponse
{
SubscriptionId = subscription.Id,
ClientSecret = subscription.LatestInvoice.PaymentIntent.ClientSecret,
};
}
No, the subscription metadata is not propagated to the generated invoices or the payment intents used within those invoices. If you want metadata on either of those, you'll need to set up a process to update that using your own code.
You could, for example, set this up using webhooks. You could listen for invoice.paid webhooks and then retrieve the subscription to get the metadata and update the Payment Intent related to that invoice.
Related
I have been trying for weeks to add a new Schema Extension for my Microsoft Graph based MVC application, essentially to store some basic variables along with a mail Message.
I've followed this example from GitHub and after some very frustrating days of working out that "Boolean" & "Integer" weren't supported property types, I then ran into the fabled "Insufficient privileges to complete the operation"...
I have been pulling my hair out trying to work out how and where I'm supposed to add my new extension, as it stands I'm trying to add it with the below code as an authenticated user (who is an admin):
SchemaExtension extensionPayload = new SchemaExtension()
{
Description = "my extension example",
Id = $"myExtensionExample",
Properties = new List<ExtensionSchemaProperty>()
{
new ExtensionSchemaProperty() { Name = "prop1", Type = "String" },
new ExtensionSchemaProperty() { Name = "prop2", Type = "String" }
},
TargetTypes = new List<string>()
{
"Message"
}
};
SchemaExtension test = await client
.SchemaExtensions
.Request()
.AddAsync(extensionPayload);
My Graph Client is generated with the below code:
public static async Task<GraphServiceClient> GetClient(HttpContextBase context)
{
string token = await GetAccessToken(context);
GraphServiceClient client = new GraphServiceClient(
new DelegateAuthenticationProvider(
(requestMessage) =>
{
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", token);
return Task.FromResult(0);
}
)
);
return client;
}
And my Oauth config requests the following permissions:
<add key="ida:AppScopes" value="User.Read Mail.ReadWrite Mail.Send Contacts.ReadWrite Directory.AccessAsUser.All" />
I've checked the Azure App Permissions of the account I'm testing with and they all appear to be correct? Is that where they're supposed to be??
ANY pointers would be greatly appreciated, as I've lost so much time trying to get what I thought was a very straight forward test app up and running.
According to the docs, using this call with Application permissions isn't supported.
I am trying to create a azure cosmos database and collection in my c# code.
await client.CreateDatabaseIfNotExistsAsync(new Database() { Id = "data"});
DocumentCollection dCollection = await client.CreateDocumentCollectionIfNotExistsAsync(UriFactory.CreateDatabaseUri("data"), new DocumentCollection { Id = "coll"}, new RequestOptions { OfferThroughput = 400, , PartitionKey = new PartitionKey("/id") });
// dashboardCollection.PartitionKey.Paths.Add("/id");
When I go to portal.azure.com and check my document DB, the collection is created. When I go to Scale and Settings for the collection, I don't see a partition key.
I created another collection manually and it shows the partition key in the Scale and Settings section.
The delete function is throwing an error because of this partition key error
Inserted a record with id 1 successfully into the document DB. The following delete fails saying that the partitionKey is invalid.
ResourceResponse<Document> response = await client.DeleteDocumentAsync(UriFactory.CreateDocumentUri("data", "coll", "1"), new RequestOptions { PartitionKey = new PartitionKey("1") });
I am from the CosmosDB engineering team.
When creating a DocumentCollection, please ensure that the partition key is provided in the DocumentCollection object, like so:
PartitionKeyDefinition pkDefn = new PartitionKeyDefinition() { Paths = new Collection<string>() { "/id" } };
DocumentCollection dCollection = await client.CreateDocumentCollectionIfNotExistsAsync(UriFactory.CreateDatabaseUri("data"), new DocumentCollection { Id = "coll", PartitionKey = pkDefn }, new RequestOptions { OfferThroughput = 400, PartitionKey = new PartitionKey("/id") });
The PartitionKey on the RequestOptions is not honored during collection CRUD requests, since we expect the PartitionKey to be part of the collection object. The PartitionKey on the RequestOptions is honored during document CRUD requests.
I have a table of random unique number that they served as account Id for a user.
This scenario will use in Register method of Web API to get first unique Number and attached it into a user and after a successful creation, the fetched unique Number will be removed from database:
public async Task<ActionResult> Register([FromBody] RegisterDto model)
{
//get the first unique number from the database
var UniqueNumber = _context.UniqueNumbers.First();
var user = new User
{
UserName = model.Email,
Email = model.Email,
PhoneNumber = model.PhoneNumber,
FirstName = model.FirstName,
LastName = model.LastName,
UserProfile = new UserProfile()
{
AccountNumber = UniqueNumber.Number,
},
};
//creating user
var createResult = await _userManager.CreateAsync(user, model.Password);
if (!createResult.Succeeded) return BadRequest(new { isSucceeded = createResult.Succeeded, errors = createResult.Errors });
//Delete the fetched UniqueId from the database
_context.UniqueNumbers.Remove(UniqueNumber);
_context.SaveChanges();
return Ok(new
{
isSucceeded = true
});
}
My question is how do I prevent collision in multiple calls on API since it may return same unique number for multiple calls?
On EF Core and Microsoft SQL Server you should simply use a SEQUENCE object to generate your keys. See Sequences - EF Core
If really, really want to proceed with your original design you could use FromSql to run a DELETE … OUTPUT, something like:
var UniqueNumber = _context.UniqueNumbers.FromSql("delete top (1) from UniqueNumbers output deleted.*").Single();
I use Paypal .Net SDK (https://github.com/paypal/PayPal-NET-SDK ) for payment API calls. It needs an APIContext object to be passed in API calls.
By using clientid and clientsecret of my paypal app, I can obtain accesstoken to create the APIContext object. But this makes payment into my merchant account.
I wanted to make payment and refund API calls on behalf of other merchants. For that I used Paypal Permission SDK (https://github.com/paypal/permissions-sdk-dotnet) to obatain permissions from Third Party Merchants. Once a merchant grants permission, I get token and secret. At this stage I cannot find any documentation how do I use that token and secret to call paypal API?
Can anyone guide me how to use that token and secret (received from permission API) to make valid APIContext, which can be used to call various paypal.net sdk API calls?
My answer is a bit late, but may help others as I found this question when searching for how to do this.
This applies if using the PayPal .NET SDK.
Create a PayPal.Api.Payee object and add this to your PayPal.Api.Transaction object that you use to make your payment.
Example 1:
var payee = new PayPal.Api.Payee()
{
email = "test#example.com"
}
var transaction = new PayPal.Api.Transaction();
transaction.payee = payee;
Example 2:
var paypal = new PayPal.Api.Transaction()
{
description = "Transaction description.",
invoice_number = "123",
amount = new Amount()
{
currency = "USD",
total = "100.00",
details = new Details()
{
tax = "0",
shipping = "25.00",
subtotal = "75.00"
}
},
item_list = new ItemList()
{
items = new List<Item>()
{
new Item()
{
name = "title",
currency = "USD",
price = "75.00",
quantity = "1",
sku = "MySKU"
}
}
},
payee = new Payee()
{
email = "email#example.com"
}
};
Instead of email you could use merchant_id or phone to identify the third party to receive the funds.
Note: the third party must have granted your PayPal application the appropriate permission for the type of transaction you are attempting.
I am trying to add multiple users async with AAD graph Like this:
IUser user1 = ...;
IUser user2 = ...;
IUser user3 = ...;
List<Task> addTasks = new List<Task>();
addTasks.Add(activeDirectoryClient.Users.AddUserAsync(user1));
addTasks.Add(activeDirectoryClient.Users.AddUserAsync(user2));
addTasks.Add(activeDirectoryClient.Users.AddUserAsync(user3));
await Task.WhenAll(addTasks);
I get this error message :
{"odata.error":{"code":"Request_BadRequest","message":{"lang":"en","value":"Another object with the same value for property userPrincipalName already exists."},"values":[{"item":"PropertyName","value":"userPrincipalName"},{"item":"PropertyErrorCode","value":"ObjectConflict"}]}}
If I use this code :
IUser user1 = ...;
IUser user2 = ...;
IUser user3 = ...;
List<Task> addTasks = new List<Task>();
await activeDirectoryClient.Users.AddUserAsync(user1);
await activeDirectoryClient.Users.AddUserAsync(user2);
await activeDirectoryClient.Users.AddUserAsync(user3);
This is working well.
Maybe we can't add multiple users in AAD at the same time ?
EDIT
Here is the users part:
IUser newStudentUser = new User
{
DisplayName = $"Etudiant de l'école {school}",
UserPrincipalName = $"etudiant-{school}#........fr",
AccountEnabled = true,
MailNickname = $"Etudiant {school}",
UsageLocation = "US",
PasswordProfile = new PasswordProfile
{
Password = "......."
}
};
IUser newTeacherUser = new User
{
DisplayName = $"Professeur de l'école {school}",
UserPrincipalName = $"professeur-{school}#........fr",
AccountEnabled = true,
MailNickname = $"Professeur {school}",
UsageLocation = "US",
PasswordProfile = new PasswordProfile
{
Password = "......."
}
};
IUser newDirectorUser = new User
{
DisplayName = $"Directeur de l'école {school}",
UserPrincipalName = $"directeur-{school}#........fr",
AccountEnabled = true,
MailNickname = $"Directeur {school}",
UsageLocation = "US",
PasswordProfile = new PasswordProfile
{
Password = "......."
}
};
In your case, you want to batch the creation of multiple users.
At present, the GraphClient does support batch processing but there are some limitation (Batch processing | Graph API concepts):
A single batch can contain a maximum of five queries and/or change sets combined.
A change set can contain a maximum of one source object modification and up to 20 add-link and delete-link operations combined. All operations in the change set must be on a single source entity.
So in your case you can't batch the creation of more than 5 users.
While adding an entity to Graph API client, you can choose to defer the execution of the query using the deferredSave parameter.
await activeDirectoryClient.Users.AddUserAsync(user, deferredSave: true);
The Graph API client has a DataServiceContextWrapper that tracks changes. It provides a SaveChanges(Async) method.
await activeDirectoryClient.Context.SaveChangesAsync();
Calling this method you can specify the SaveChangesOptions:
Batch: All pending changes are saved in a single batch request.
BatchWithIndependentOperations: the one you want to use because the creation of the user should be in a single query.
ContinueOnError: Pending changes are saved by using multiple requests to the server, and the operation continues after an error occurs.
None: Pending changes are saved by using multiple requests to the server, but the operation stops on the first failure (default).
PatchOnUpdate:
ReplaceOnUpdate: Pending updates are made by replacing all values of the entity in the data source with values from the updated entity.
Now you have enough information to write the code to batch the creation of the users:
// Only 5 users per batch !!!!
var user1 = ...;
var user2 = ...;
var user3 = ...;
await activeDirectoryClient.Users.AddUserAsync(newStudentUser, deferredSave: true);
await activeDirectoryClient.Users.AddUserAsync(newTeacherUser, deferredSave: true);
await activeDirectoryClient.Users.AddUserAsync(newDirectorUser, deferredSave: true);
// In debug mode, you should use the SaveChangesAsync method with the default options
// Becasue the BatchWithIndependentOperations will not throw any exception even if there is a problem while creating the user.
//await activeDirectoryClient.Context.SaveChangesAsync();
await activeDirectoryClient.Context
.SaveChangesAsync(SaveChangesOptions.BatchWithIndependentOperations);