Closed AndreyPolovodov closed 2 months ago
Please provide minimal reproducible example of what you expect to achieve there. For further discussion I suggest you to join our telegram group https://t.me/joinchat/B35YY0QbLfd034CFnvCtCA.
I want to get valid json as you can see on screen (this is provider requirement). They don't want a "string", they want JSON-node.
So, here is whay they want:
And here is what I can do now with string providerData (i just put JObject.ToString() result into providerData):
As you can see, there is no JSON-node, but just a string with escaped quotes.
The question is - how to get what they want using SendInvoiceAsync? I don't see the way.
await _botClient.SendInvoiceAsync(identifier, "",
"desc", "payload", paymentToken, "start_parameter", "RUB",
prices,
/* WHAT TO PLACE HERE TO GET IT AS A PART OF VALID JSON */,
So, is it enought as reproducible example or not?
Who are “they”? Bot API clearly states that provider data is a json encoded string, there’s nothing indicating that it should be a valid json node without any particular schema.
Yandex. See here for example, if you are interested in. I captured my first screenshot from that page.
Possibly you are right but Im not sure actually.
Here is quote from a telegram bot api:
A JSON-serialized data about the invoice, which will be shared with the payment provider. A detailed description of required fields should be provided by the payment provider.
So, there is a "data" and "fields". But at the same time there is type of parameter "String".
It probably means that you should serialize required provider data as a json string and pass it as json as is. It’s either Telegram or the provider job to deserialize it back.
According to the official documentation for sendInvoice provider_data parameter
provider_data
is a JSON-serialized data about the invoice, which will be shared with the payment provider. A detailed description of required fields should be provided by the payment provider.
So this property is provider-specific I i don't see a way for us to provide a convenient way of serializing this data in our library. You have to serialize this data yourself and specify it as a parameter for SendInvoiceAsync.
In your case it could be something like this:
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
var receipt = new Receipt()
{
Items = new Item[] { new Item() { Description = "Product", Quantity = 1.0M } }
};
var providerData = JsonConvert.SerializeObject(receipt);
Console.WriteLine(providerData);
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
public class Item
{
[JsonProperty(Required = Required.Always)]
public string Description { get; set; }
[JsonProperty(Required = Required.Always)]
public decimal Quantity { get; set; }
}
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
public class Receipt
{
[JsonProperty(Required = Required.Always)]
public Item[] Items { get; set; }
}
With a resulting string:
{"items":[{"description":"Product","quantity":1.0}]}
And a complete request would look like this:
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using Telegram.Bot.Requests;
using Telegram.Bot.Types.Payments;
var receipt = new Receipt()
{
Items = new Item[] { new Item() { Description = "Product", Quantity = 1.0M } }
};
LabeledPrice[] productPrices =
{
new LabeledPrice(label: "PART_OF_PRODUCT_PRICE_1", amount: 150),
new LabeledPrice(label: "PART_OF_PRODUCT_PRICE_2", amount: 2029),
};
var invoice = new Invoice
{
Title = "PRODUCT_TITLE",
Currency = "CAD",
StartParameter = "start_param",
TotalAmount = 1,
Description = "PRODUCT_DESCRIPTION",
};
var sendInvoiceRequest = new SendInvoiceRequest(
chatId: 1,
title: invoice.Title,
description: invoice.Description,
payload: "payload",
providerToken: "providerToken",
startParameter: invoice.StartParameter,
currency: invoice.Currency,
prices: productPrices
)
{
PhotoUrl = "url",
PhotoWidth = 600,
PhotoHeight = 400,
NeedShippingAddress = true,
IsFlexible = true,
NeedName = true,
NeedEmail = true,
NeedPhoneNumber = true,
SendEmailToProvider = true,
SendPhoneNumberToProvider = true,
ProviderData = providerData
};
var invoiceRequest = JsonConvert.SerializeObject(sendInvoiceRequest);
Console.WriteLine(invoiceRequest);
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
public class Item
{
[JsonProperty(Required = Required.Always)]
public string Description { get; set; }
[JsonProperty(Required = Required.Always)]
public decimal Quantity { get; set; }
}
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
public class Receipt
{
[JsonProperty(Required = Required.Always)]
public Item[] Items { get; set; }
}
Which gives us a valid JSON request:
{
"chat_id": 1,
"title": "PRODUCT_TITLE",
"description": "PRODUCT_DESCRIPTION",
"payload": "payload",
"provider_token": "providerToken",
"start_parameter": "start_param",
"currency": "CAD",
"prices": [
{
"label": "PART_OF_PRODUCT_PRICE_1",
"amount": 150
},
{
"label": "PART_OF_PRODUCT_PRICE_2",
"amount": 2029
}
],
"provider_data": "{\"items\":[{\"description\":\"Product\",\"quantity\":1.0}]}",
"photo_url": "url",
"photo_width": 600,
"photo_height": 400,
"need_name": true,
"need_phone_number": true,
"need_email": true,
"need_shipping_address": true,
"send_phone_number_to_provider": true,
"send_email_to_provider": true,
"is_flexible": true
}
@karb0f0s There’s a way to make the library do the conversion for you (making a breaking change) but it will require SendInvoiceAsync
method and SendInvoiceRequest
to become generic or provider_data to have object
type. It will also require a custom json converter which will make future possibility of STJ support without pulling in Newtonsoft impossible. I don’t think it’s worth it.
@karb0f0s Thank you for a sample... Anyway, this string will give us "provider_data" with just a string value, not a JSON-node. Possible it's ok but it not looks like in yandex documentation. So, I will ask provider (yandex) support about that. There is still exists the possibility of error in their documentation.
@tuscen yes, that what I was looking for initially... object or JObject.
@AndreyPolovodov it may be that yandex docs aren't correct regardless this particular case. Try deserializing all the required data as json object and test it with a test token. It should work.
I see your point. Same example here https://habr.com/ru/company/yamoney/blog/351766/. It looks like provider_data should be a valid JSON node. Can you confirm, that serialized JSON string doesn't work as expected?
Can you confirm, that serialized JSON string doesn't work as expected?
I just trying to understand what is wrong with payments in my bot and have just found this one. Possibly it's not the only one, so, I can't confirm right now - but I will do it later (and will ask yandex to be sure).
@AndreyPolovodov Hi, were you able to get reply from Yandex and resolve your issue?
Hi, @karb0f0s, sorry, not yet, but I remeber about and will give feedback a bit later.
Closing this.
Github Issues are for issues within our library code, not for helping you solve your client's requirements. For Bot API, ProviderData is a string. It's up to you to serialize your JSON to a string.
Here is a sample of result Im trying to get... There is a problem with quotes escaping - I don't see the way how to pass a string into current version of SendInvoiceAsync to get valid json in request to telegram api. If just I don't see the way - please, let me know... Thank you.