cancel
Showing results for 
Search instead for 
Did you mean: 

Setting GetCustomerProfile's unmaskExpirationDate to true returns expirationDate "XXXX".

In sample-code-csharp-master.zip from 3/23/2017 5:14 PM setting GetCustomerProfile's unmaskExpirationDate to true returns expirationDate "XXXX".  Would Authorize.Net fix GetCustomerProfile so setting unmaskExpirationDate to true returns the actual expiration date?  The Authorize.NET\Utility\HttpXmlUtility.cs code in the if statement below returned unmasked expiration dates:

 

 

 if (type.FullName == "AuthorizeNet.APICore.getCustomerProfileRequest")

 

 

but the else code from sdk-dotnet-master.zip 3/23/2017 12:30 PM returned "XXXX", rather than expiration date.  The else code did not send <unmaskExpirationDate> to Authorize.Net in the webRequest.GetRequestStream().  See second code chunk below.

 

 

 

  public ANetApiResponse Send(ANetApiRequest apiRequest) {
   //Authenticate it
   AuthenticateRequest(apiRequest);
   HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(_serviceUrl);
   webRequest.Method = "POST";
   webRequest.ContentType = "text/xml";
   webRequest.KeepAlive = true;
   //set the http connection timeout
   var httpConnectionTimeout = AuthorizeNet.Environment.getIntProperty(Constants.HttpConnectionTimeout);
   webRequest.Timeout = (httpConnectionTimeout != 0 ? httpConnectionTimeout : Constants.HttpConnectionDefaultTimeout);
   //set the time out to read/write from stream
   var httpReadWriteTimeout = AuthorizeNet.Environment.getIntProperty(Constants.HttpReadWriteTimeout);
   webRequest.ReadWriteTimeout = (httpReadWriteTimeout != 0 ? httpReadWriteTimeout : Constants.HttpReadWriteDefaultTimeout);
   // Serialize the request
   var type = apiRequest.GetType();
   if (type.FullName == "AuthorizeNet.APICore.getCustomerProfileRequest")
   {
    var req = (getCustomerProfileRequest)apiRequest;
    var s3 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><getCustomerProfileRequest xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
     + "xmlns:xsd =\"http://www.w3.org/2001/XMLSchema\" xmlns=\"AnetApi/xml/v1/schema/AnetApiSchema.xsd\">"
     + "<merchantAuthentication><name>" + req.merchantAuthentication.name + "</name>"
     + "<transactionKey>" + req.merchantAuthentication.Item + "</transactionKey></merchantAuthentication>"
     + "<customerProfileId>" + req.customerProfileId + "</customerProfileId>"
     + "<unmaskExpirationDate>" + (req.unmaskExpirationDate ? "true" : "false") + "</unmaskExpirationDate>"
     + "</getCustomerProfileRequest>";
    byte[] bytes = Encoding.UTF8.GetBytes(s3);
    webRequest.GetRequestStream().Write(bytes, 0, bytes.Length);
   }
   else
   {
    var serializer = new XmlSerializer(type);
    XmlWriter writer = new XmlTextWriter(webRequest.GetRequestStream(), Encoding.UTF8);
    serializer.Serialize(writer, apiRequest);
    writer.Close();
   }
   // Get the response
   WebResponse webResponse = webRequest.GetResponse();
   // Load the response from the API server into an XmlDocument.
   var xmlDoc = new XmlDocument();
   xmlDoc.Load(XmlReader.Create(webResponse.GetResponseStream(), new XmlReaderSettings()));

   var response = DecideResponse(xmlDoc);
   CheckForErrors(response, xmlDoc);
   return response;
  }

 

 

You can put the following code after var type = apiRequest.GetType(); to put apiRequest in a string.

var type = apiRequest.GetType();
var serializer2 = new XmlSerializer(type);
MemoryStream memoryStream = new MemoryStream();
XmlWriter writer2 = new XmlTextWriter(memoryStream, Encoding.UTF8);
serializer2.Serialize(writer2, apiRequest);
memoryStream.Position = 0;
var streamReader = new StreamReader(memoryStream);
var s = streamReader.ReadToEnd();
streamReader.Dispose();
memoryStream.Dispose();

 

bobjones
Member
9 REPLIES 9

Hi @bobjones,

 

Can I ask you to clarify? Are you talking about the GetCustomerProfile.cs sample?

 

Are you saying that if you add change the request code to send unmaskExpirationDate, the expiration date is still returned masked?

 

For reference, here's the section where you'd add code to send unmaskExpirationDate, starting at line 28:

 

            var request = new getCustomerProfileRequest();
            request.customerProfileId = customerProfileId;
            request.unmaskExpirationDate = true;
Aaron
All Star

I tried 2 separate test cases: 1) from sample-code-csharp-master.zip and 2) from sdk-dotnet-master.zip:

 

1) Correct, in sample-code-csharp-master\CustomerProfiles\GetCustomerProfile.cs I changed

   var request = new getCustomerProfileRequest();

      request.customerProfileId = customerProfileId;

to

   var request = new getCustomerProfileRequest();

     request.customerProfileId = customerProfileId;

   request.unmaskExpirationDate = true;

Which returned profile.paymentProfiles[0].payment.item.expirationDate as "XXXX".  Though request.unmaskExpirationDate = true; should return unmasked dates like "2018-01"

ExpirationDateXXXX

 

2) In sdk-dotnet-master.zip Authorize.NET\Utility\HttpXmlUtility.cs

  public ANetApiResponse Send(ANetApiRequest apiRequest) {

...

   var type = apiRequest.GetType();

    var serializer = new XmlSerializer(type);
    XmlWriter writer = new XmlTextWriter(webRequest.GetRequestStream(), Encoding.UTF8);
    serializer.Serialize(writer, apiRequest);
    writer.Close();

is not putting <unmaskExpirationDate>true</unmaskExpirationDate> in serialized version of the apiRequest.  Perhaps the Authorize.NET\Api\Contracts\V1\AnetApiSchema.generated.cs serialization code has an error, though I didn't spot the error:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]

[System.SerializableAttribute()]

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.ComponentModel.DesignerCategoryAttribute("code")]

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="AnetApi/xml/v1/schema/AnetApiSchema.xsd")]

[System.Xml.Serialization.XmlRootAttribute(Namespace="AnetApi/xml/v1/schema/AnetApiSchema.xsd", IsNullable=false)]

public partial class getCustomerProfileRequest : ANetApiRequest {

 

/// <remarks/>

public string customerProfileId;

 

/// <remarks/>

public bool unmaskExpirationDate;

 

/// <remarks/>

[System.Xml.Serialization.XmlIgnoreAttribute()]

public bool unmaskExpirationDateSpecified;

}

 

The following code after var type = apiRequest.GetType(); to put apiRequest in a string.
var type = apiRequest.GetType();
var serializer2 = new XmlSerializer(type);
MemoryStream memoryStream = new MemoryStream();
XmlWriter writer2 = new XmlTextWriter(memoryStream, Encoding.UTF8);
serializer2.Serialize(writer2, apiRequest);
memoryStream.Position = 0;
var streamReader = new StreamReader(memoryStream);
var s = streamReader.ReadToEnd();
streamReader.Dispose();
memoryStream.Dispose();

 

var s contains the following, which is missing <unmaskExpirationDate>true</unmaskExpirationDate>:

 

<?xml version=\"1.0\" encoding=\"utf-8\"?><getCustomerProfileRequest xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"AnetApi/xml/v1/schema/AnetApiSchema.xsd\"><merchantAuthentication><name>xxxxxxxxxx</name><transactionKey>xxxxxxxxxxxxxxxx</transactionKey></merchantAuthentication><customerProfileId>nnnnnnnnnn</customerProfileId></getCustomerProfileRequest>

 

rather than the following

 

<?xml version=\"1.0\" encoding=\"utf-8\"?><getCustomerProfileRequest xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd =\"http://www.w3.org/2001/XMLSchema\" xmlns=\"AnetApi/xml/v1/schema/AnetApiSchema.xsd\"><merchantAuthentication><name>xxxxxxxxxx</name><transactionKey>xxxxxxxxxxxxxxxx</transactionKey></merchantAuthentication><customerProfileId>nnnnnnnnnn</customerProfileId><unmaskExpirationDate>true</unmaskExpirationDate></getCustomerProfileRequest>

Thanks, @bobjones. This is really helpful. We have code in the SDK to mask sensitive data for things like logging, and my initiatl thought was that this code was going nuts and masking things that shouldn't be masked. However, if it's really just never getting that parameter in the request, that would be another issue entirely.

 

I'll go ahead and open an issue for the SDK on GitHub, so that the SDK developers can take a look at it and hopefully get it fixed.

 

Thanks again.

Does Authorize.Net send me another email when the fix is on Github sdk-dotnet-master.zip and sample-code-csharp-master.zip?  I'd like to remove my custom XML in Authorize.NET\Utility\HttpXmlUtility.cs. This is my first Authorize.Net bug fix request.

In your case, I would suggest going to the .Net SDK repository and the C# sample code repository on GitHub, then clicking the "Watch" button on the upper right of each page. That would subscribe you to notifications for each repository so that when something is changed, you'll get an email.

Are SDK code releases done quarterly?
How about adding a Message to "Setting GetCustomerProfile's unmaskExpirationDate to true returns expirationDate XXXX" to send me an email when it is fixed?  The email would be more convenient to me than searching github entries like "Merge pull request #164 from AuthorizeNet/future", https://github.com/AuthorizeNet/sdk-dotnet/pull/164.  Though I don't know if Authorize.Net's bug tracking capabilities allow such a response.

I checked the Post's Subscriptions, "Email me when someone replies".

Hi @bobjones,

 

I can try, but I can't guarantee anything. If this is fixed in a future SDK release, then:

 

  1. I have to know the SDK is updated (highly likely)
  2. I have to know the fix is in that update (slightly less likely, depending on whether that's specifically called out in any release note or notes on a commit, or whether the issue on GitHub is marked closed at that time. Those things should all be happening, but, developers...)
  3. Once I see that the fix happened, I have to remember "Oh, there's a user @bobjones who wanted me to post a message in the forums so that he can be notified that the bug is fixed" (likelihood of me remembering that ranges from highly likely to zilch depending on how much time has passed, what day of the week it is, what time of day, how much caffeine I've had that day, what other things I've been tasked at remembering at that time, whether or not my kids woke me up the night before, etc).

In short, I'm human and tasking a human with what should be an automated process is potentially troublesome. We don't have any way in our internal bug tracking to automatically email an external party when something's fixed. However, that's why we use GitHub for our SDK development. Since everything happens in the open out there, it's a lot easier for someone to see what happens and when.

 

GitHub doesn't seem to have a way to just subscribe to a particular issue to get updates on it, but if you comment on the issue, then you're recorded as being involved, so you can get notifications of any update to that issue itself. That way, you don't have to be notified of all commits or changes if you don't want to.

 

Your issue is at https://github.com/AuthorizeNet/sdk-dotnet/issues/169 if you'd like to comment on that to get notifications.

 

Sorry we don't have an easier way to track what you've reported. I still really appreciate that you took the time to report this, and wish I had a better way to keep you in the loop.

 I've been waiting for this feature for YEARS and gave up several times in the past.

 

Now I see that the SOAP API is deprecated I finally made the push over to the AuthorizeNET nuget package for .NET.

 

My first attempt returned XXXX-XX for the expiration date, then I made one small change and now finally I get back "2017-01" for the expiration date via this request.

 

var request = new getCustomerProfileRequest
{
   customerProfileId = "1506932163",
   unmaskExpirationDate = true,
   unmaskExpirationDateSpecified = true   // yes this is dumb but it works
};

var controller = new getCustomerProfileController(request);
controller.Execute();

var response = controller.GetApiResponse();

string expirationDate = (response.profile.paymentProfiles.First().payment.Item as creditCardMaskedType).expirationDate;

 

WOOHOO!!!!   expirationDate == "2017-01"

simeyla
Contributor

I'm using the similar account to attach with my affiliate program. Its easy to get payment from individual account. I tried it with my dispose it well website.

ksjie33w
Member