Pandaiolo
Pandaiolo

Reputation: 11568

Cannot set existing payment profile to be the default for a customer

I am using the updateCustomerPaymentProfile endpoint to try to update a payment profile. This works well, except for the presence of one field: defaultPaymentProfile.

There are two different issues.

1. Authorize.Net Ruby SDK typing issue

The docs say defaultPaymentProfile is an expected field, but the type does not allow it in ruby SDK, see in the official source code:

https://github.com/AuthorizeNet/sdk-ruby/blob/002019e03a94ef582aa82983edf6a7a1a22b2316/lib/authorize...

I opened a Github issue about this.

I then monkey patched the type as following:

module AuthorizeNet::API 
  class CustomerPaymentProfileExType
    xml_accessor :defaultPaymentProfile
  end
end

After that, it accepts to send the request but I receive an error response as following:

AuthorizeNetException: E00003: The element 'paymentProfile' in namespace 
'AnetApi/xml/v1/schema/AnetApiSchema.xsd' has invalid child element 
'defaultPaymentProfile' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd

Which is the second issue...

2. Authorize.Net API not accepting the defaultPaymentProfile when updating a payment profile

For the record, I dumped the raw XML that is sent to the API once I patched the SDK to be able to actually reach the API:

<updateCustomerPaymentProfileRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
  <merchantAuthentication>
    <name>REDACTED</name>
    <transactionKey>REDACTED</transactionKey>
  </merchantAuthentication>
  <customerProfileId>REDACTED</customerProfileId>
  <paymentProfile>
    <customerType>individual</customerType>
    <billTo>
      <firstName>REDACTED</firstName>
      <lastName>REDACTED</lastName>
      <address>REDACTED</address>
      <city>REDACTED</city>
      <state>REDACTED</state>
      <zip>REDACTED</zip>
      <country>REDACTED</country>
      <phoneNumber>REDACTED</phoneNumber>
    </billTo>
    <payment>
      <creditCard>
        <cardNumber>XXXX4242</cardNumber>
        <expirationDate>2022-03</expirationDate>
      </creditCard>
    </payment>
    <customerPaymentProfileId>REDACTED</customerPaymentProfileId>
    <!-- This XML passes fine without the line below -->
    <defaultPaymentProfile>true</defaultPaymentProfile>
  </paymentProfile>
  <validationMode>liveMode</validationMode>
</updateCustomerPaymentProfileRequest>

This looks exactly the same as the request suggested by the official API docs, yet, the server respond with a E00003 error that I already shared above.

Notes

As a reference, the block of ruby code that I am using:

        profile = AuthorizeNet::API::CustomerPaymentProfileExType.new
        profile.customerPaymentProfileId = current_profile.customerPaymentProfileId
        profile.billTo = billTo
        profile.payment = AuthorizeNet::API::PaymentType.new(
          AuthorizeNet::API::CreditCardType.new(
            cc_data.cardNumber, cc_data.expirationDate
          )
        ) 
        profile.taxId = user.tax_id if user.tax_id
        profile.defaultPaymentProfile = true
        profile.customerType = 'individual'

        request = AuthorizeNet::API::UpdateCustomerPaymentProfileRequest.new
        request.paymentProfile = profile
        request.customerProfileId = customer_profile_id
        request.validationMode = AuthorizeNet::API::ValidationModeEnum::LiveMode

        response = transaction.update_customer_payment_profile(request)

What am I doing wrong?

Upvotes: 0

Views: 271

Answers (2)

Pandaiolo
Pandaiolo

Reputation: 11568

Thanks to @John Conde, I could fix the issue. The request payload is refused because the properties are not in the right order. 🤷

If you want to set an existing payment profile as the default one using the ruby SDK, you can do so by defining yourself the correct type, as following:

module AuthorizeNet::API 
  class CustomerPaymentProfileExTypePatched
    include ROXML
    xml_accessor :customerType
    xml_accessor :billTo, as: AuthorizeNet::API::CustomerAddressType
    xml_accessor :payment, as: AuthorizeNet::API::PaymentType
    xml_accessor :driversLicense, as: AuthorizeNet::API::DriversLicenseType
    xml_accessor :taxId
    xml_accessor :defaultPaymentProfile
    xml_accessor :subsequentAuthInformation
    xml_accessor :customerPaymentProfileId

    def initialize(customerType = nil, billTo = nil, payment = nil, driversLicense = nil, taxId = nil, defaultPaymentProfile = nil, subsequentAuthInformation = nil, customerPaymentProfileId = nil)
      @customerType = customerType
      @billTo = billTo
      @payment = payment
      @driversLicense = driversLicense
      @taxId = taxId
      @defaultPaymentProfile = defaultPaymentProfile
      @subsequentAuthInformation = subsequentAuthInformation
      @customerPaymentProfileId = customerPaymentProfileId
    end
  end
end

Then you can just use this type in your code:

profile = AuthorizeNet::API::CustomerPaymentProfileExTypePatched.new

Upvotes: 0

John Conde
John Conde

Reputation: 219794

The order of the elements matter. Move

<defaultPaymentProfile>true</defaultPaymentProfile>` 

above

<customerPaymentProfileId>REDACTED</customerPaymentProfileId>`
<updateCustomerPaymentProfileRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
  <merchantAuthentication>
    <name>REDACTED</name>
    <transactionKey>REDACTED</transactionKey>
  </merchantAuthentication>
  <customerProfileId>REDACTED</customerProfileId>
  <paymentProfile>
    <customerType>individual</customerType>
    <billTo>
      <firstName>REDACTED</firstName>
      <lastName>REDACTED</lastName>
      <address>REDACTED</address>
      <city>REDACTED</city>
      <state>REDACTED</state>
      <zip>REDACTED</zip>
      <country>REDACTED</country>
      <phoneNumber>REDACTED</phoneNumber>
    </billTo>
    <payment>
      <creditCard>
        <cardNumber>XXXX4242</cardNumber>
        <expirationDate>2022-03</expirationDate>
      </creditCard>
    </payment>
    <defaultPaymentProfile>true</defaultPaymentProfile>
    <customerPaymentProfileId>REDACTED</customerPaymentProfileId>
  </paymentProfile>
  <validationMode>liveMode</validationMode>
</updateCustomerPaymentProfileRequest>

Upvotes: 1

Related Questions