I'm trying to configure an Azure Table Storage output binding for an Azure Function (in JavaScript) using an identity-based connection instead of a connection string. I believe I've setup the Function as per the docs but I'm getting this error:
System.Private.CoreLib: Exception while executing function: Functions.AzureTvDataFetcher. Microsoft.Azure.WebJobs.Extensions.Storage: Storage account connection string 'AzureWebJobsAzuretvTableStorageConnection' does not exist. Make sure that it is a defined App Setting.
The error mentions that it should be a defined app setting, which it is. This is my local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "node",
"AzuretvTableStorageConnection__tableServiceUri": "https://<account-name>.table.core.windows.net"
}
}
And these are the triggers/bindings defined in function.json:
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "table",
"tableName": "azuretv",
"name": "azuretvTableBinding",
"direction": "out",
"connection": "AzuretvTableStorageConnection"
}
]
}
The docs mention that it requires the extension bundle version 2.x, which is installed, see my host.json:
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[2.*, 3.0.0)"
},
So I'm not sure what I'm doing wrong. If I use a connection string instead it works fine. I've also deployed the Function app, created a managed identity for it and assigned the Storage Table Data Contributor role to the storage account but I still get the same error. Any ideas?
I have an azure function that I want to send a message to a service bus that has a correlation filter on it. Specifically the correlation filter is on the label/subject with a value of 'APPLICATION'. correlation filter
How do I send the message from the azure function so that it will set this value and the subscription will receive the message?
Currently the function is set up something like this:
index.js:
module.exports = async function(context, inMessage) {
context.bindings.outMessage = someJavascriptObject;
}
function.json:
{
"bindings": [
{
"name": "inMessage",
"type": "serviceBusTrigger",
"direction": "in",
"topicName": "some_topic_1",
"subscriptionName": "SUBSCRIPTION_NAME",
"connection": "CONNECTION_STRING_1"
},
{
"name": "outMessage",
"type": "serviceBus",
"topicName": "some_topic_2",
"connection": "CONNECTION_STRING_2",
"direction": "out"
},
]
}
This is not currently supported. Please see https://github.com/Azure/azure-sdk-for-net/issues/21884
I'm trying to implement PayPal payments in our shopping cart using a combination of the JavaScript SDK and server side REST calls. I render the buttons using the JavaScript SDK and have the createOrder and onApprove methods call endpoints on my server, as the examples given by PayPal do (JavaScript SDK example). These, in turn, call to the PayPal REST API.
All of this works great IF I'm doing a capture. However, our requirements are to do an authorization. This doesn't appear to work. The createOrder call successfully completes and the onApprove method is hit. However it fails when the server side REST call is made with an error:
issue":"AMOUNT_CANNOT_BE_SPECIFIED","description":"An authorization amount can only be specified if an Order has been saved by calling /v2/checkout/orders/{order_id}/save. Please save the order and try again."}],"
There is no mention that I can find of having to call this save method and indeed, if I try to call that method, I get an error indicating the transaction was not yet approved by the customer.
This also works fine when using the pure client side method of doing this, but we would like to avoid that for a number of reasons. The PayPal documentation seems to indicate that this should be possible.
A simplified/sanitized version of my code is below:
<script src="https://www.paypal.com/sdk/js?client-id=KEY¤cy=USD&disable-funding=card&components=funding-eligibility,buttons&intent=authorize&commit=true"></script>
<script>
paypal.Buttons({
createOrder: function (data, actions) {
return fetch("/checkout/paypal/order", {
method: "post",
body: $("#checkoutForm").serialize(),
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
}).then((order) => {
return order.json();
})
.then((orderData) => {
return orderData.OrderId;
});
},
onApprove: function (data, actions) {
return fetch("/checkout/paypal/authorize", {
method: "post",
body: $('#checkoutForm').serialize(),
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
})
.then((result) => {
console.log(result.json());
});
}
}).render('#paypal-button-container');
</script>
The backend goes through a controller and a number of services, but ultimately the resulting requests (using the C# SDK package: PayPalCheckoutSdk) looks like this:
Create Order:
public async Task<PayPalOrderResponseDTO> CreateOrder(PayPalOrderRequestDTO orderRequest)
{
OrderRequest ppor = new OrderRequest()
{
CheckoutPaymentIntent = "AUTHORIZE",
PurchaseUnits = new List<PurchaseUnitRequest>()
{
new PurchaseUnitRequest()
{
AmountWithBreakdown = new AmountWithBreakdown()
{
CurrencyCode = "USD",
Value = orderRequest.Total.ToString()
},
ShippingDetail = new ShippingDetail()
{
Name = new Name()
{
FullName = $"{orderRequest.ShippingAddress.FirstName} {orderRequest.ShippingAddress.LastName}"
},
AddressPortable = new AddressPortable()
{
AddressLine1 = orderRequest.ShippingAddress.Address1,
AddressLine2 = orderRequest.ShippingAddress.Address2,
AddressLine3 = orderRequest.ShippingAddress.Address3,
AdminArea2 = orderRequest.ShippingAddress.City,
AdminArea1 = orderRequest.ShippingAddress.State,
PostalCode = orderRequest.ShippingAddress.ZipCode,
CountryCode = orderRequest.ShippingAddress.CountryID
}
}
}
},
ApplicationContext = new ApplicationContext()
{
ShippingPreference = "SET_PROVIDED_ADDRESS",
LandingPage = "LOGIN",
UserAction = "PAY_NOW"
}
};
OrdersCreateRequest request = new OrdersCreateRequest();
request.Prefer("return=minimal");
request.RequestBody(ppor);
PayPalHttp.HttpResponse response = await _ppClient.Execute(request).ConfigureAwait(false);
System.Net.HttpStatusCode statusCode = response.StatusCode;
if (statusCode != System.Net.HttpStatusCode.Created)
{
// HANDLE ERROR
}
Order order = response.Result<Order>();
return new PayPalOrderResponseDTO()
{
Status = response.StatusCode.ToString(),
OrderID = order.Id
};
}
Authorize order:
public async Task<PayPalPaymentResponseDTO> Authorize(PayPalPaymentRequestDTO request)
{
OrdersAuthorizeRequest oar = new OrdersAuthorizeRequest(request.OrderID);
oar.RequestBody(new AuthorizeRequest()
{
Amount = new Money() { CurrencyCode = "USD", Value = request.Total },
ReferenceId = request.refId
});
PayPalHttp.HttpResponse response = await _ppClient.Execute(oar).ConfigureAwait(false);
Order order = response.Result<Order>();
return new PayPalPaymentResponseDTO()
{
StatusCode = (int)response.StatusCode,
ID = order.Id
};
}
As I said, this all works perfectly if I change it to use a "CAPTURE" intent. It's only when I attempt a "AUTHORIZE" that I get this error. I tried doing the final authorization call without the amount, just in case, but got an error indicating that the required payment amount field was missing.
Does any one have any ideas, or is this just not possible without doing an older-style redirect? I'd like to avoid both that and using the purely client side method of handling this using something like, e.g.:
paypal.Buttons({
// Sets up the transaction when a payment button is clicked
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [{
amount: {
value: '77.44' // Can also reference a variable or function
}
}]
});
},
// Finalize the transaction after payer approval
onApprove: (data, actions) => {
return actions.order.capture().then(function(orderData) {
// Successful capture! For dev/demo purposes:
console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
actions.redirect('thank_you.html');
});
}
}).render('#paypal-button-container');
It is possible. The REST API call to authorize the order should be a POST with no payload body.
Here is an example log, triggered by createOrder on the server:
POST to v2/checkout/orders
{
"intent": "AUTHORIZE",
"purchase_units": [
{
"amount": {
"currency_code": "USD",
"value": "500",
"breakdown": {
"item_total": {
"currency_code": "USD",
"value": "500"
}
}
},
"items": [
{
"name": "Name of Item #1 (can be viewed in the upper-right dropdown during payment approval)",
"description": "Optional description; item details will also be in the completed paypal.com transaction view",
"unit_amount": {
"currency_code": "USD",
"value": "500"
},
"quantity": "1"
}
]
}
]
}
Response data
{
"id": "3J6935353G362625A",
"status": "CREATED",
"links": [
{
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/3J6935353G362625A",
"rel": "self",
"method": "GET"
},
{
"href": "https://www.sandbox.paypal.com/checkoutnow?token=3J6935353G362625A",
"rel": "approve",
"method": "GET"
},
{
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/3J6935353G362625A",
"rel": "update",
"method": "PATCH"
},
{
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/3J6935353G362625A/authorize",
"rel": "authorize",
"method": "POST"
}
]
}
Followed by this on the server, triggered after onApprove:
Empty POST to v2/checkout/orders/3J6935353G362625A/authorize
Response data
{
"id": "3J6935353G362625A",
"status": "COMPLETED",
"purchase_units": [
{
"reference_id": "default",
"shipping": {
"name": {
"full_name": "Sandbox Buyer"
},
"address": {
"address_line_1": "123 street name",
"admin_area_2": "Phoenix",
"admin_area_1": "AZ",
"postal_code": "85001",
"country_code": "US"
}
},
"payments": {
"authorizations": [
{
"status": "CREATED",
"id": "9V1555595X9968645",
"amount": {
"currency_code": "USD",
"value": "500.00"
},
"seller_protection": {
"status": "ELIGIBLE",
"dispute_categories": [
"ITEM_NOT_RECEIVED",
"UNAUTHORIZED_TRANSACTION"
]
},
"expiration_time": "2022-05-13T20:14:50Z",
"links": [
{
"href": "https://api.sandbox.paypal.com/v2/payments/authorizations/9V1555595X9968645",
"rel": "self",
"method": "GET"
},
{
"href": "https://api.sandbox.paypal.com/v2/payments/authorizations/9V1555595X9968645/capture",
"rel": "capture",
"method": "POST"
},
{
"href": "https://api.sandbox.paypal.com/v2/payments/authorizations/9V1555595X9968645/void",
"rel": "void",
"method": "POST"
},
{
"href": "https://api.sandbox.paypal.com/v2/payments/authorizations/9V1555595X9968645/reauthorize",
"rel": "reauthorize",
"method": "POST"
},
{
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/3J6935353G362625A",
"rel": "up",
"method": "GET"
}
],
"create_time": "2022-04-14T20:14:50Z",
"update_time": "2022-04-14T20:14:50Z"
}
]
}
}
],
"payer": {
"name": {
"given_name": "Sandbox",
"surname": "Buyer"
},
"email_address": "sandboxbuyer#sandbox.com",
"payer_id": "THLKV8VCTCSKL",
"address": {
"country_code": "US"
}
},
"links": [
{
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/3J6935353G362625A",
"rel": "self",
"method": "GET"
}
]
}
A sample to do this with the Checkout-NET-SDK is here.
My team is building a health app and thus using Asymmetrik FHIR API Server. We need to save a bundle consisting of Condition, Observation and Procedure. The bundle should create each individual object in their respective tables. But when we are using postman to hit the base URL with a very simple bundle object it is giving Invalid URL. Each service is individually working fine and able to create respective objects. How can we enable the root URL of this FHIR server?
POST URL: http://localhost:3000/4_0_0/
POST Object:
{
"resourceType": "Bundle",
"id": "f001",
"type": "transaction",
"entry": [
{
"resource": {
"resourceType": "Observation",
"status": "registered"
},
"request": {
"method": "POST",
"url": "Observation"
}
},
{
"resource": {
"resourceType": "Condition",
"code": {
"coding": {
"system": "http://hl7.org/fhir/ValueSet/condition-code",
"code": "",
"display": ""
}
}
},
"request": {
"method": "POST",
"url": "Condition"
}
}
]
}
ERROR:
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "not-found",
"details": {
"text": "Invalid url: /4_0_0/"
}
}
]
}
I'm trying to add a document to my DocumentDB with the incoming payloads to an HttpTriggered Azure Function. This is the function.json content:
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req"
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "documentDB",
"name": "email",
"databaseName": "crawler",
"collectionName": "SendGrid",
"createIfNotExists": true,
"connection": "noho_DOCUMENTDB",
"direction": "out"
}
],
"disabled": false
}
And this is my function:
module.exports = function (context, req) {
try{
if (req.body) {
context.bindings.email = req.body;
context.res = {
status: 200,
body: req.body
};
}
else {
context.res = {
status: 400,
body: "Please pass a name on the query string or in the request body"
};
}
} catch(e) {
context.log(e);
context.res = {
status: 500,
body: e
};
}
context.done();
return req.body;
};
It fails and throws an exception while processing an input POST request with the following message:
Exception while executing function: Functions.SendGridJs.
Microsoft.Azure.Documents.Client: Value cannot be null.
Parameter name: document.
I've setup the integration through the Azure Function integration wizard and not through code deployment. So, I'm assuming that Azure is taking care of the setup code.
Both of your function.json and code of index.js are OK. You need to feed valid JSON string into req.body.
Here is my testing screenshot.
If I specify invalid JSON in the request body, I will get the same error as yours.