Броски ссылок на первую службу API данных HTTP-запрос не авторизован с помощью схемы аутентификации клиента "Anonymous"
Я интегрирую API для сервиса шлюза оплаты First Data в свой проект. Примерно 3 недели назад моя интеграция работала. Мы перезагрузили сервер, и теперь интеграция больше не работает. При публикации моего приложения на компьютере разработчика, оно работает, но что-то в нашей производственной среде на данный момент не соответствует сервису.
Изучение сообщения об ошибке приводит меня к проблемам службы с проверкой подлинности, но нет учетных данных сервера, которые нужно отправить службе, которую вызывает мое приложение. Я думаю; более или менее, это проблема с IIS, но у меня есть время, пытаясь выяснить это.
Моя интеграция заключается в следующем...
Учебный класс
public class Merchant
{
private readonly string _gatewayId;
private readonly string _password;
private readonly string _keyId;
private readonly string _hmac;
private readonly bool _isDemo;
// POST URLs
private const string ProdUrl = "https://api.globalgatewaye4.firstdata.com/transaction/v14";
private const string TestUrl = "https://api.demo.globalgatewaye4.firstdata.com/transaction/v14";
public Merchant(string gatewayId, string password, string hmac, string keyId, bool isDemo = true)
{
_gatewayId = gatewayId;
_password = password;
_hmac = hmac;
_keyId = keyId;
_isDemo = isDemo;
}
public MerchantResponse Charge(
string orderId, // Order ID / Reference Number
string cardHoldersName, // Card Holder Name
string cardNumber, // Card number
string amount, // Payment amount
string expirationMonth, // Card Exp. Month
string expirationYear, // Card Exp. Year
string ccv, // CCV code
string address, // Address
string zip) // Zip
{
var client = new ServiceSoapClient(new BasicHttpBinding(BasicHttpSecurityMode.Transport), new EndpointAddress(_isDemo ? TestUrl : ProdUrl));
client.ChannelFactory.Endpoint.Behaviors.Add(new HmacHeaderBehaivour(_hmac, _keyId));
TransactionResult result = client.SendAndCommit(new Transaction
{
ExactID = _gatewayId,
Password = _password,
Transaction_Type = "00",
Card_Number = cardNumber,
CardHoldersName = cardHoldersName,
DollarAmount = amount,
Expiry_Date = string.Format("{0:D2}{1}", expirationMonth, expirationYear),
Customer_Ref = orderId.ToString(),
//VerificationStr1 = address + "|" + zip + "|" + "US",
//VerificationStr2 = ccv
});
var response = new MerchantResponse
{
IsTransactionApproved = result.Transaction_Approved,
IsError = result.Transaction_Error
};
if (!result.Transaction_Approved && !result.Transaction_Error)
{
// Format Response String
response.Message =
result.Authorization_Num + "|" + // Authorization Number
result.Transaction_Tag + "|" + // Transaction Tag (Transaction ID)
result.CardHoldersName + "|" + // Cardholder's Name
result.DollarAmount + "|" + // Transaction Amount
result.Customer_Ref + "|" + // Cust. Reference Number
result.EXact_Message + "|" + // Response Message
result.Bank_Message + "|" + // Bank Response Message
result.Card_Number + "|" + // Card Number
result.CardType + "|" + // Card Type
result.ZipCode // Zip Code
;
}
if (!result.Transaction_Approved && result.Transaction_Error)
{
// Format Response String
response.Message =
result.Authorization_Num + "|" + // Authorization Number
result.Transaction_Tag + "|" + // Transaction Tag (Transaction ID)
result.CardHoldersName + "|" + // Cardholder's Name
result.DollarAmount + "|" + // Transaction Amount
result.Customer_Ref + "|" + // Cust. Reference Number
result.EXact_Message + "|" + // Response Message
result.Bank_Message + "|" + // Bank Response Message
result.Card_Number + "|" + // Card Number
result.CardType + "|" + // Card Type
result.ZipCode // Zip Code
;
}
if (result.Transaction_Approved)
{
// Format Response String
response.Message =
result.Authorization_Num + "|" + // Authorization Number
result.Transaction_Tag + "|" + // Transaction Tag (Transaction ID)
result.CardHoldersName + "|" + // Cardholder's Name
result.DollarAmount + "|" + // Transaction Amount
result.Customer_Ref + "|" + // Cust. Reference Number
result.EXact_Message + "|" + // Response Message
result.Bank_Message + "|" + // Bank Response Message
result.Card_Number + "|" + // Card Number
result.CardType + "|" + // Card Type
result.ZipCode // Zip Code
;
}
return response;
}
class HmacHeaderBehaivour : IEndpointBehavior
{
private readonly string _hmac;
private readonly string _keyId;
public HmacHeaderBehaivour(string hmac, string keyId)
{
_hmac = hmac;
_keyId = keyId;
}
public void Validate(ServiceEndpoint endpoint)
{
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new HmacHeaderInspector(_hmac, _keyId));
}
}
class HmacHeaderInspector : IClientMessageInspector
{
private readonly string _hmac;
private readonly string _keyId;
public HmacHeaderInspector(string hmac, string keyId)
{
_hmac = hmac;
_keyId = keyId;
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
request = buffer.CreateMessage();
Message msg = buffer.CreateMessage();
ASCIIEncoding encoder = new ASCIIEncoding();
var sb = new StringBuilder();
var xmlWriter = XmlWriter.Create(sb, new XmlWriterSettings
{
OmitXmlDeclaration = true
});
var writer = XmlDictionaryWriter.CreateDictionaryWriter(xmlWriter);
msg.WriteStartEnvelope(writer);
msg.WriteStartBody(writer);
msg.WriteBodyContents(writer);
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
writer.Flush();
string body = sb.ToString().Replace(" />", "/>");
byte[] xmlByte = encoder.GetBytes(body);
SHA1CryptoServiceProvider sha1Crypto = new SHA1CryptoServiceProvider();
string hash = BitConverter.ToString(sha1Crypto.ComputeHash(xmlByte)).Replace("-", "");
string hashedContent = hash.ToLower();
//assign values to hashing and header variables
string time = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
string hashData = "POST\ntext/xml; charset=utf-8\n" + hashedContent + "\n" + time + "\n/transaction/v14";
//hmac sha1 hash with key + hash_data
HMAC hmacSha1 = new HMACSHA1(Encoding.UTF8.GetBytes(_hmac)); //key
byte[] hmacData = hmacSha1.ComputeHash(Encoding.UTF8.GetBytes(hashData)); //data
//base64 encode on hmac_data
string base64Hash = Convert.ToBase64String(hmacData);
HttpRequestMessageProperty httpRequestMessage;
object httpRequestMessageObject;
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject))
{
httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
httpRequestMessage.Headers["X-GGe4-Content-SHA1"] = hashedContent;
httpRequestMessage.Headers["X-GGe4-Date"] = time;
httpRequestMessage.Headers["Authorization"] = "GGE4_API " + _keyId + ":" + base64Hash;
}
else
{
httpRequestMessage = new HttpRequestMessageProperty();
httpRequestMessage.Headers["X-GGe4-Content-SHA1"] = hashedContent;
httpRequestMessage.Headers["X-GGe4-Date"] = time;
httpRequestMessage.Headers["Authorization"] = "GGE4_API " + _keyId + ":" + base64Hash;
request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
}
return null;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
}
}
Адрес для обслуживания клиентов
https://api.globalgatewaye4.firstdata.com/transaction/v14/wsdl
Конфигурация для справочной службы
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ServiceSoap">
<security mode="Transport" />
</binding>
<binding name="ServiceSoap1" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://api.globalgatewaye4.firstdata.com/transaction/v14"
binding="basicHttpBinding" bindingConfiguration="ServiceSoap"
contract="FirstDataReference.ServiceSoap" name="ServiceSoap" />
</client>
</system.serviceModel>
Трассировка полного стека
The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was ''.
Трассировка стека сервера:
HTTP-запрос не авторизован с помощью схемы аутентификации клиента "Anonymous". Заголовок аутентификации, полученный от сервера, был ''.
в System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(запрос HttpWebRequest, ответ HttpWebResponse, WebException responseException, HttpChannelFactory1 factory)
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory
1 фабрика, WebException responseException, ChannelBinding channelBinding) в System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(тайм-аут TimeSpan) в системном сообщении System.ServiceModel.Channels.RequestShannel (RequestShannel) RequestShannel.RequestShannel.RequestShannel..Dispatcher.RequestChannelBinder.Request (сообщение-сообщение, время ожидания TimeSpan) в System.ServiceModel.Channels.ServiceChannel.Call (действие String, односторонний логический метод, операция ProxyOperationRuntime, Object[] ins, выходы Object [], TimeSpan тайм-аут) в System.ServiceM.Channels.ServiceChannelProxy.InvokeService(операция IMethodCallMessageCall, операция ProxyOperationRuntime) в System.ServiceModel.Channels.ServiceChannelProxy.Invoke(сообщение IMessage)
Исключение, переброшенное в [0]: в System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) в System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(тип MessageData& msgData. ServiceSoap.SendAndCommit(запрос SendAndCommitRequest) по адресу MyApplication.FirstDataReference.ServiceSoapClient.MyApplication.FirstDataReference.ServiceSoap.SendAndCommit(запрос SendAndCommitRequest String, StringNumbering, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, StringMing expirationYear, String ccv, String address, String zip) в MyApplication.controls.Confirmation.Step2SubmitButton_Click(Отправитель объекта, EventArgs e)
Я хочу верить, что существует проблема, когда мое приложение пытается использовать ссылку на службу в сравнении с самой конечной точкой.