cancel
Showing results for 
Search instead for 
Did you mean: 

Make customer profile when charging card

I'm currently charging a customer and then trying to create a customer profile based on that charge.  The problem is that when I try and actually create the customer it fails, telling me that there is no response and instead prints out `

AttributeError: no such child: {AnetApi/xml/v1/schema/AnetApiSchema.xsd}customerProfileId




Here is the code, and below this chunk is a bit more explanation and what I'm doing to parse the response.

    merchantAuth = apicontractsv1.merchantAuthenticationType()
    merchantAuth.name = app_config.AUTHORIZE_KEYS['apiLoginId']
    merchantAuth.transactionKey = app_config.AUTHORIZE_KEYS['transactionKey']
    # Create the payment object for a payment nonce
    opaqueData = apicontractsv1.opaqueDataType()
    opaqueData.dataDescriptor = request.form['dataDesc']
    opaqueData.dataValue = request.form['dataValue']

    # Add the payment data to a paymentType object
    paymentOne = apicontractsv1.paymentType()
    paymentOne.opaqueData = opaqueData

    # Create order information
    order = apicontractsv1.orderType()
    order.invoiceNumber = "invoice_%s" % user.id
    order.description = "Awesome"
    # Set the customer's identifying information
    customerData = apicontractsv1.customerDataType()
    customerData.type = "individual"
    customerData.id = "cus_%s" % user.id
    customerData.email = email
    # Giving the credit card info
    # Setting billing information
    billto = apicontractsv1.nameAndAddressType()
    billto.firstName = request.form['firstName']
    billto.lastName = request.form['lastName']
    billto.address = address1
    billto.city = city
    billto.state = state
    billto.zip = zipcode
    billto.country = country
    item = request.form['item']
    if item == 'dollar':
        amount = "3.00"
    if item == "monthly":
        amount = "5.00"
        length = 1
    if item == "annual":
        amount = "50.00"
        length = 12
    # Create order information
    order = apicontractsv1.orderType()
    order.invoiceNumber = "invoice_%s" % user.id
    order.description = "Awesomeness"

    # # Set the customer's Bill To address
    customerAddress = apicontractsv1.customerAddressType()
    customerAddress.firstName = request.form['firstName']
    customerAddress.lastName = request.form['lastName']
    customerAddress.address = address1
    customerAddress.city = city
    customerAddress.state = state
    customerAddress.zip = zipcode
    customerAddress.country = country

    # Create customer profile on transaction
    createcustomerprofile = apicontractsv1.customerProfilePaymentType()
    createcustomerprofile.createProfile = True

    # Create a transactionRequestType object and add the previous objects to it.
    transactionrequest = apicontractsv1.transactionRequestType()
    transactionrequest.transactionType = "authCaptureTransaction"
    transactionrequest.amount = amount
    transactionrequest.payment = paymentOne
    transactionrequest.order = order
    transactionrequest.billTo = customerAddress
    transactionrequest.customer = customerData
    transactionrequest.profile = createcustomerprofile

    # Assemble the complete transaction request
    createtransactionrequest = apicontractsv1.createTransactionRequest()
    createtransactionrequest.merchantAuthentication = merchantAuth
    createtransactionrequest.refId = refId
    createtransactionrequest.transactionRequest = transactionrequest

    # Create the controller
    createtransactioncontroller = createTransactionController(createtransactionrequest)
    createtransactioncontroller.setenvironment(app_config.AUTH_NET_ENVIRONMENT)
    createtransactioncontroller.execute()



The problem seems to occur when I try and prase the response. but when I actually run the code as is suggested in the developers documenation

 

   response = createtransactioncontroller.getresponse()
    logging.debug("%s" % response)
    if response is not None:
            # Check to see if the API request was successfully received and acted upon
        if response.messages.resultCode == "Ok":
            # Since the API request was successful, look for a transaction response
            # and parse it to display the results of authorizing the card
            if hasattr(response.transactionResponse, 'messages') == True:
                if hasattr(response.profileResponse, 'messages') == True:
                    print('made it here')
                models.Payment(user=user, payment_date=datetime.utcnow(),
                                         authorize={'email': email, 'updated': False,
                                                    'address': u'%s %s' % (address1, address2),
                                                    'messages': {'transId':'%s' % response.transactionResponse.transId,
                                                    'responseCode':'%s' % response.transactionResponse.responseCode,
                                                    'auth_code':'%s' % response.transactionResponse.messages.message[0].code,
                                                    'Description':'%s' % response.transactionResponse.messages.message[0].description,
                                                    'email':email},
                                                    # 'customerProfileId': '%s' % response.profileResponse.customerProfileId,
                                                    # 'customerPaymentProfileIdList': '%s' % response.profileResponse.customerPaymentProfileIdList,
                                                    })




Given their [documentation][1] shows that the you can create the customer when making the transaction not sure why it's returning that it's not working.

Also when I check the [schema for the xml response][2] it seems I'm setting it correctly.


  [1]: http://developer.authorize.net/api/reference/index.html#payment-transactions-charge-a-credit-card
  [2]: https://api.authorize.net/xml/v1/schema/AnetApiSchema.xsd

 

nadermx
Contributor
19 REPLIES 19

Ok, I tried changing the order, but it now in the log file it shows

 

Customer profile creation failed. This payment method does not support profile creation.

Your log should look like below:

2017-09-15 07:47:36,412 performing custom validation..
2017-09-15 07:47:36,413 Executing http post to url: https://apitest.authorize.net/xml/v1/request.api
2017-09-15 07:47:36,413 building request..
2017-09-15 07:47:36,921 Starting new HTTPS connection (1): apitest.authorize.net
2017-09-15 07:47:37,027 building request..
2017-09-15 07:47:37,044 Request is: <?xml version="1.0" ?>
<createTransactionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
	<merchantAuthentication>
		<name></name>
		<transactionKey></transactionKey>
	</merchantAuthentication>
	<clientId>sdk-python-1.0.14</clientId>
	<refId>MerchantID-0001</refId>
	<transactionRequest>
		<transactionType>authCaptureTransaction</transactionType>
		<amount>12.23</amount>
		<payment>
			<creditCard>
				<cardNumber>4111111111111111</cardNumber>
				<expirationDate>2020-12</expirationDate>
				<cardCode>123</cardCode>
			</creditCard>
		</payment>
		<profile>
			<createProfile>true</createProfile>
		</profile>
		<order>
			<invoiceNumber>10101</invoiceNumber>
			<description>Golf Shirts</description>
		</order>
		<lineItems>
			<lineItem>
				<itemId>12345</itemId>
				<name>first</name>
				<description>Here's the first line item</description>
				<quantity>2.0</quantity>
				<unitPrice>12.95</unitPrice>
			</lineItem>
			<lineItem>
				<itemId>67890</itemId>
				<name>second</name>
				<description>Here's the second line item</description>
				<quantity>3.0</quantity>
				<unitPrice>7.95</unitPrice>
			</lineItem>
		</lineItems>
		<customer>
			<type>individual</type>
			<id>90999456654</id>
			<email>BubbaJohnson@example.com</email>
		</customer>
		<billTo>
			<firstName>Ellen</firstName>
			<lastName>Johnson</lastName>
			<company>Souveniropolis</company>
			<address>14 Main Street</address>
			<city>Pecan Springs</city>
			<state>TX</state>
			<zip>44628</zip>
			<country>USA</country>
		</billTo>
		<transactionSettings>
			<setting>
				<settingName>duplicateWindow</settingName>
				<settingValue>600</settingValue>
			</setting>
		</transactionSettings>
	</transactionRequest>
</createTransactionRequest>

The Python that created the log above is below:

"""
Charge a credit card
"""

import imp
import os
import sys
# print sys.path
from authorizenet import apicontractsv1
from authorizenet.apicontrollers import createTransactionController

CONSTANTS = imp.load_source('modulename', 'constants.py')


def charge_credit_card(amount):
    """
    Charge a credit card
    """

    # Create a merchantAuthenticationType object with authentication details
    # retrieved from the constants file
    merchantAuth = apicontractsv1.merchantAuthenticationType()
    merchantAuth.name = CONSTANTS.apiLoginId
    merchantAuth.transactionKey = CONSTANTS.transactionKey

    # Create the payment data for a credit card
    creditCard = apicontractsv1.creditCardType()
    creditCard.cardNumber = "4111111111111111"
    creditCard.expirationDate = "2020-12"
    creditCard.cardCode = "123"

    # Add the payment data to a paymentType object
    payment = apicontractsv1.paymentType()
    payment.creditCard = creditCard

    # Create order information
    order = apicontractsv1.orderType()
    order.invoiceNumber = "10101"
    order.description = "Golf Shirts"

    # Set the customer's Bill To address
    customerAddress = apicontractsv1.customerAddressType()
    customerAddress.firstName = "Ellen"
    customerAddress.lastName = "Johnson"
    customerAddress.company = "Souveniropolis"
    customerAddress.address = "14 Main Street"
    customerAddress.city = "Pecan Springs"
    customerAddress.state = "TX"
    customerAddress.zip = "44628"
    customerAddress.country = "USA"
    
    # Create customer profile on transaction
    createcustomerprofile = apicontractsv1.customerProfilePaymentType()
    createcustomerprofile.createProfile = True
    
    # Set the customer's identifying information
    customerData = apicontractsv1.customerDataType()
    customerData.type = "individual"
    customerData.id = "90999456654"
    customerData.email = "BubbaJohnson@example.com"

    # Add values for transaction settings
    duplicateWindowSetting = apicontractsv1.settingType()
    duplicateWindowSetting.settingName = "duplicateWindow"
    duplicateWindowSetting.settingValue = "600"
    settings = apicontractsv1.ArrayOfSetting()
    settings.setting.append(duplicateWindowSetting)

    # setup individual line items
    line_item_1 = apicontractsv1.lineItemType()
    line_item_1.itemId = "12345"
    line_item_1.name = "first"
    line_item_1.description = "Here's the first line item"
    line_item_1.quantity = "2"
    line_item_1.unitPrice = "12.95"
    line_item_2 = apicontractsv1.lineItemType()
    line_item_2.itemId = "67890"
    line_item_2.name = "second"
    line_item_2.description = "Here's the second line item"
    line_item_2.quantity = "3"
    line_item_2.unitPrice = "7.95"

    # build the array of line items
    line_items = apicontractsv1.ArrayOfLineItem()
    line_items.lineItem.append(line_item_1)
    line_items.lineItem.append(line_item_2)

    # Create a transactionRequestType object and add the previous objects to it.
    transactionrequest = apicontractsv1.transactionRequestType()
    transactionrequest.transactionType = "authCaptureTransaction"
    transactionrequest.amount = amount
    transactionrequest.payment = payment
    transactionrequest.profile = createcustomerprofile
    transactionrequest.order = order
    transactionrequest.billTo = customerAddress
    transactionrequest.customer = customerData
    transactionrequest.transactionSettings = settings
    transactionrequest.lineItems = line_items


    # Assemble the complete transaction request
    createtransactionrequest = apicontractsv1.createTransactionRequest()
    createtransactionrequest.merchantAuthentication = merchantAuth
    createtransactionrequest.refId = "MerchantID-0001"
    createtransactionrequest.transactionRequest = transactionrequest
    createtransactionrequest.profile = "createProfile"
    # Create the controller
    createtransactioncontroller = createTransactionController(
        createtransactionrequest)
    createtransactioncontroller.execute()

    response = createtransactioncontroller.getresponse()
    print response
   
    if response is not None:
        print response
        # Check to see if the API request was successfully received and acted upon
        if response.messages.resultCode == "Ok":
            # Since the API request was successful, look for a transaction response
            # and parse it to display the results of authorizing the card
            if hasattr(response.transactionResponse, 'messages') is True:
                print(
                    'Successfully created transaction with Transaction ID: %s'
                    % response.transactionResponse.transId)
                print('Transaction Response Code: %s' %
                      response.transactionResponse.responseCode)
                print('Message Code: %s' %
                      response.transactionResponse.messages.message[0].code)
                print('Description: %s' % response.transactionResponse.
                      messages.message[0].description)
            else:
                print('Failed Transaction.')
                if hasattr(response.transactionResponse, 'errors') is True:
                    print('Error Code:  %s' % str(response.transactionResponse.
                                                  errors.error[0].errorCode))
                    print(
                        'Error message: %s' %
                        response.transactionResponse.errors.error[0].errorText)
        # Or, print errors if the API request wasn't successful
        else:
            print('Failed Transaction.')
            if hasattr(response, 'transactionResponse') is True and hasattr(
                    response.transactionResponse, 'errors') is True:
                print('Error Code: %s' % str(
                    response.transactionResponse.errors.error[0].errorCode))
                print('Error message: %s' %
                      response.transactionResponse.errors.error[0].errorText)
            else:
                print('Error Code: %s' %
                      response.messages.message[0]['code'].text)
                print('Error message: %s' %
                      response.messages.message[0]['text'].text)
    else:
        print('Null Response.')

    return response


if (os.path.basename(__file__) == os.path.basename(sys.argv[0])):
    charge_credit_card(CONSTANTS.amount)

 

Powered by NexWebSites.com -
Certified Authorize.net developers

Not sure if it's because I'm using the payment nooce, but my log file does not show the request, only the response

 

 

2017-09-15 13:58:27,152 performing custom validation..
2017-09-15 13:58:27,152 Executing http post to url: https://apitest.authorize.net/xml/v1/request.api
2017-09-15 13:58:27,152 building request..
2017-09-15 13:58:27,159 Starting new HTTPS connection (1): apitest.authorize.net
2017-09-15 13:58:30,192 "POST /xml/v1/request.api HTTP/1.1" 200 1138
2017-09-15 13:58:30,206 Multiple accepting paths for <class 'authorizenet.apicontractsv1.CTD_ANON_10'>
2017-09-15 13:58:30,206 Multiple accepting paths for <class 'authorizenet.apicontractsv1.CTD_ANON_9'>
2017-09-15 13:58:30,214 Multiple accepting paths for {AnetApi/xml/v1/schema/AnetApiSchema.xsd}transactionResponse
2017-09-15 13:58:30,216 Multiple accepting paths for <class 'authorizenet.apicontractsv1.CTD_ANON_73'>
2017-09-15 13:58:30,223 Received response: <?xml version="1.0" encoding="utf-8"?>
<createTransactionResponse xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<refId>ref 1505509107.15</refId>
<messages>
<resultCode>Ok</resultCode>
<message>
<code>I00001</code>
<text>Successful.</text>
</message>
</messages>
<transactionResponse>
<responseCode>1</responseCode>
<authCode>D3ZWDA</authCode>
<avsResultCode>Y</avsResultCode>
<cvvResultCode>P</cvvResultCode>
<cavvResultCode>2</cavvResultCode>
<transId>40007132129</transId>
<refTransID/>
<transHash>4AA30C7C2091E9DDF6E8516503EE8D5E</transHash>
<testRequest>0</testRequest>
<accountNumber>XXXX4242</accountNumber>
<accountType>Visa</accountType>
<messages>
<message>
<code>1</code>
<description>This transaction has been approved.</description>
</message>
</messages>
<transHashSha2/>
</transactionResponse>
<profileResponse>
<messages>
<resultCode>Error</resultCode>
<message>
<code>E00103</code>
<text>Customer profile creation failed. This payment method does not support profile creation.</text>
</message>
</messages>
</profileResponse>
</createTransactionResponse>

This is the code I'm using, in the order as you suggested

 

 


# Create a merchantAuthenticationType object with authentication details
# retrieved from the constants file
merchantAuth = apicontractsv1.merchantAuthenticationType()
merchantAuth.name = app_config.AUTHORIZE_KEYS['apiLoginId']
merchantAuth.transactionKey = app_config.AUTHORIZE_KEYS['transactionKey']

# Create the payment object for a payment nonce
opaqueData = apicontractsv1.opaqueDataType()
opaqueData.dataDescriptor = request.form['dataDesc']
opaqueData.dataValue = request.form['dataValue']

# Add the payment data to a paymentType object
paymentOne = apicontractsv1.paymentType()
paymentOne.opaqueData = opaqueData

# Create order information
order = apicontractsv1.orderType()
order.invoiceNumber = "invoice_%s_%s" % (randint(0, 100), user.id)
order.description = "The thing you upgraded"

# # Set the customer's Bill To address
customerAddress = apicontractsv1.customerAddressType()
customerAddress.firstName = request.form['firstName']
customerAddress.lastName = request.form['lastName']
customerAddress.address = address1
customerAddress.city = city
customerAddress.state = state
customerAddress.zip = zipcode
customerAddress.country = country

# Set the customer's identifying information
customerData = apicontractsv1.customerDataType()
customerData.type = "individual"
customerData.id = "cus_%s" % user.id
customerData.email = email

# Add values for transaction settings
duplicateWindowSetting = apicontractsv1.settingType()
duplicateWindowSetting.settingName = "duplicateWindow"
duplicateWindowSetting.settingValue = "600"
settings = apicontractsv1.ArrayOfSetting()
settings.setting.append(duplicateWindowSetting)

# Create customer profile on transaction
createcustomerprofile = apicontractsv1.customerProfilePaymentType()
createcustomerprofile.createProfile = True

# Create a transactionRequestType object and add the previous objects to it.
transactionrequest = apicontractsv1.transactionRequestType()
transactionrequest.transactionType = "authCaptureTransaction"
transactionrequest.amount = amount
transactionrequest.payment = paymentOne
transactionrequest.profile = createcustomerprofile
transactionrequest.order = order
transactionrequest.billTo = customerAddress
transactionrequest.customer = customerData
transactionrequest.transactionSettings = settings

# Assemble the complete transaction request
createtransactionrequest = apicontractsv1.createTransactionRequest()
createtransactionrequest.merchantAuthentication = merchantAuth
createtransactionrequest.refId = refId
createtransactionrequest.transactionRequest = transactionrequest
createtransactionrequest.profile = "createProfile"

# Create the controller
createtransactioncontroller = createTransactionController(createtransactionrequest)
createtransactioncontroller.setenvironment(app_config.AUTH_NET_ENVIRONMENT)
createtransactioncontroller.execute()

response = createtransactioncontroller.getresponse()

It is because you are using opaqueData, this payment method does not support profile creation.

Powered by NexWebSites.com -
Certified Authorize.net developers

So in order to use this functionality you have to run the credit card through your server? What's the point of accept.js then?

@nadermx

 

Using a nonce from Accept.js to create a transaction and a profile at the same time is not currently supported, but is something we plan to fix in a future release.  You can create a customer profile with the nonce and then perform a transaction using the customer profile.

 

Richard

Is there a ETA to this? I'll do a workaround till it's resolved.

Also, it seems there is another issue.

 

If I try and make a customer by sending the credit card information instead of the noonce and then within the same function try and make a ARB off that customer profile, it does not register, tells me that

 

<ARBCreateSubscriptionResponse xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<messages>
<resultCode>Error</resultCode>
<message>
<code>E00040</code>
<text>The record cannot be found.</text>
</message>
</messages>
</ARBCreateSubscriptionResponse>

 

So is there a delay between when a customer is created before you can send another request to create the ARB?  Since clearly it does make the profile, I can see it in the CIM, as well as the payment profile.

 

 

Do I have to set this up as a seperate function that runs a cron a day later or something since it appears, as I had suspected earlier, that trying to run 2 calls within one function with your SDK makes it so nothing works.

 

@nadermx Creating a customer profile is done in realtime, but follow-on transactions to use a customer profile use replicated date for performance reasons.  You may experience some delay in the sandbox but should perform much faster in production.  If you get an E00040 when trying to create a transaction from a newly created customer profile, you can simply wait a few seconds and try again.

 

Our product team is aware of this issue and are working on improving performance.

 

Richard