我有一个ASP.NET网站,需要检查用户提供的增值税。 VIES Service可用于公开SOAP API的对象。
我需要一个简单的示例,说明如何使用此服务验证增值税。在PHP中,这是以下4行:https://stackoverflow.com/a/14340495。对于C#,我发现2010年以来有些文章不起作用,或者是数十行甚至数百行的“包装器”,“辅助服务”等。
我不需要任何东西,有人可以提供类似PHP的四层衬套来检查C#中的增值税吗?谢谢。
在.NET平台上,通常使用Web服务,以便我们生成代理类。通常,可以使用Visual Studio“添加Web引用”完成此操作,只需在其中填写WSDL的路径即可。另一种方法是使用wsdl.exe或svcutil.exe生成源类。
然后只消耗该类,并验证增值税是否成为一线客:
DateTime date = new checkVatPortTypeClient().checkVat(ref countryCode, ref vatNumber, out isValid, out name, out address);
生成代理提供了强类型的API以使用整个服务,我们不需要手动创建肥皂信封并解析输出文本。比yours更简单,安全和通用的解决方案。
这里是一个自给自足(没有WCF,没有WSDL,...)实用程序类,它将检查增值税号并获取有关公司的信息(名称和地址)。如果增值税号无效或发生任何错误,它将返回null。
// sample calling code
Console.WriteLine(EuropeanVatInformation.Get("FR89831948815"));
...
public class EuropeanVatInformation
{
private EuropeanVatInformation() { }
public string CountryCode { get; private set; }
public string VatNumber { get; private set; }
public string Address { get; private set; }
public string Name { get; private set; }
public override string ToString() => CountryCode + " " + VatNumber + ": " + Name + ", " + Address.Replace("\n", ", ");
public static EuropeanVatInformation Get(string countryCodeAndVatNumber)
{
if (countryCodeAndVatNumber == null)
throw new ArgumentNullException(nameof(countryCodeAndVatNumber));
if (countryCodeAndVatNumber.Length < 3)
return null;
return Get(countryCodeAndVatNumber.Substring(0, 2), countryCodeAndVatNumber.Substring(2));
}
public static EuropeanVatInformation Get(string countryCode, string vatNumber)
{
if (countryCode == null)
throw new ArgumentNullException(nameof(countryCode));
if (vatNumber == null)
throw new ArgumentNullException(nameof(vatNumber));
countryCode = countryCode.Trim();
vatNumber = vatNumber.Trim().Replace(" ", string.Empty);
const string url = "http://ec.europa.eu/taxation_customs/vies/services/checkVatService";
const string xml = @"<s:Envelope xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'><s:Body><checkVat xmlns='urn:ec.europa.eu:taxud:vies:services:checkVat:types'><countryCode>{0}</countryCode><vatNumber>{1}</vatNumber></checkVat></s:Body></s:Envelope>";
try
{
using (var client = new WebClient())
{
var doc = new XmlDocument();
doc.LoadXml(client.UploadString(url, string.Format(xml, countryCode, vatNumber)));
var response = doc.SelectSingleNode("//*[local-name()='checkVatResponse']") as XmlElement;
if (response == null || response["valid"]?.InnerText != "true")
return null;
var info = new EuropeanVatInformation();
info.CountryCode = response["countryCode"].InnerText;
info.VatNumber = response["vatNumber"].InnerText;
info.Name = response["name"]?.InnerText;
info.Address = response["address"]?.InnerText;
return info;
}
}
catch
{
return null;
}
}
}
我发现的最简单的方法就是发送XML并在返回时对其进行解析:
var wc = new WebClient();
var request = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:urn=""urn:ec.europa.eu:taxud:vies:services:checkVat:types"">
<soapenv:Header/>
<soapenv:Body>
<urn:checkVat>
<urn:countryCode>COUNTRY</urn:countryCode>
<urn:vatNumber>VATNUMBER</urn:vatNumber>
</urn:checkVat>
</soapenv:Body>
</soapenv:Envelope>";
request = request.Replace("COUNTRY", countryCode);
request = request.Replace("VATNUMBER", theRest);
String response;
try
{
response = wc.UploadString("http://ec.europa.eu/taxation_customs/vies/services/checkVatService", request);
}
catch
{
// service throws WebException e.g. when non-EU VAT is supplied
}
var isValid = response.Contains("<valid>true</valid>");
更新:我已经将此书发布为NuGet库。
https://github.com/TriggerMe/CSharpVatChecker
var vatQuery = new VATQuery();
var vatResult = await vatQuery.CheckVATNumberAsync("IE", "3041081MH"); // The Squarespace VAT Number
Console.WriteLine(vatResult.Valid); // Is the VAT Number valid?
Console.WriteLine(vatResult.Name); // Name of the organisation
基于帕维尔·霍德克的:
VIES提供的URL中的类型http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl从wsdl生成Service类。
按Go并选择服务,为名称空间提供适当的名称,例如Services.VATCheck
reference.cs
的文件重命名为VATCheck,这也会重命名该类。在控制器中,使用以下代码来调用该调用,确保它是异步的(最终可能需要一段时间才能加载所有数据)
public async Task<IActionResult> CheckVAT()
{
var countryCode = "BE";
var vatNumber = "123456789";
try
{
checkVatPortType test = new checkVatPortTypeClient(checkVatPortTypeClient.EndpointConfiguration.checkVatPort, "http://ec.europa.eu/taxation_customs/vies/services/checkVatService");
checkVatResponse response = await test.checkVatAsync(new checkVatRequest { countryCode = countryCode, vatNumber = vatNumber });
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
return Ok();
}
[请注意,您可以清理此呼叫,但这完全取决于您。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BTWCheck.eu.europa.ec;
namespace BTWCheck
{
class Program
{
static void Main(string[] args)
{
// VS 2017
// add service reference -> button "Advanced" -> button "Add Web Reference" ->
// URL = http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl
string Landcode = "NL";
string BTWNummer = "820471616B01"; // VAT nr BOL.COM
checkVatService test = new checkVatService();
test.checkVat(ref Landcode, ref BTWNummer, out bool GeldigBTWNr, out string Naam, out string Adres);
Console.WriteLine(Landcode + BTWNummer + " " + GeldigBTWNr);
Console.WriteLine(Naam+Adres);
Console.ReadKey();
}
}
}