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

To create a Customer Profile from a Transaction, all you need is the Transaction Id, you don't need to send a CustomerProfileId.

<?xml version="1.0" encoding="utf-8"?>
<createCustomerProfileFromTransactionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
<merchantAuthentication>
<name>YOUR_API_LOGIN</name>
<transactionKey>YOUR_TRANSACTION_ KEY</transactionKey>
</merchantAuthentication>
<transId>TRANSACTION_ID</transId>
</createCustomerProfileFromTransactionRequest>

If you do send a customer profile Id, it should be sent like below:

<?xml version="1.0" encoding="utf-8"?>
<createCustomerProfileFromTransactionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
<merchantAuthentication>
<name>YOUR_API_LOGIN</name>
<transactionKey>YOUR_TRANSACTION_ KEY</transactionKey>
</merchantAuthentication>
<transId>TRANSACTION_ID</transId>
<customerProfileId>CUSTOMER_PROFILE_ID</customerProfileId>
</createCustomerProfileFromTransactionRequest>

 Or the JSON version:

{
    "createCustomerProfileFromTransactionRequest": {
        "merchantAuthentication": {
            "name": "YOUR_API_LOGIN",
            "transactionKey": "YOUR_TRANSACTION_KEY"
        },
        "transId": "TRANSACION_ID",
          "customerProfileId":"CUSTOMER_PROFILE_ID"
    }
}
Powered by NexWebSites.com -
Certified Authorize.net developers
NexusSoftware
Trusted Contributor

So I have to make two calls? Not one to create the profile?  Given what the documenation is leading me to believe I can simply send the create customer boolian in transaction and it should return the customer

You can create a profile from a transaction in one call by using a createTransactionRequest and specifying createProfile = true like below:

</creditCard>
    </payment>
    <profile>
    <createProfile>true</createProfile>
    </profile>
    <order>

Or the short JSON:

​    "cardCode": "999"
}
},
"profile":{
"createProfile": true
},
"lineItems": {

 

Powered by NexWebSites.com -
Certified Authorize.net developers

Right, that's what I'm doing in the code and it's not creating the customer,

 

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

And then later adding it in

 

    transactionrequest.profile = createcustomerprofile

But it's not creating the profile

Are you able to capture the full JSON or XML that is being posted?
Powered by NexWebSites.com -
Certified Authorize.net developers

Not sure how I would even go about doing that, since print doesn't work, when I try and import it via extree to parse it also errores out, given that I'm using the Authorize SDK I find it rather dificult to even figure out how I could get it to print that response.

Using the Python SDK, another way would be to create the customer profile and payment profile then charge this new payment profile:

from authorizenet import apicontractsv1
from authorizenet.constants import constants
from authorizenet.apicontrollers import *
from decimal import *
import random

# create customer profile
merchantAuth = apicontractsv1.merchantAuthenticationType()
merchantAuth.name = "YOUR_API_LOGIN"
merchantAuth.transactionKey = "YOUR_TRANSACTION_KEY"

createCustomerProfile = apicontractsv1.createCustomerProfileRequest()
createCustomerProfile.merchantAuthentication = merchantAuth
createCustomerProfile.profile = apicontractsv1.customerProfileType('jdoe' + str(random.randint(0, 10000)), 'Jane Doe', 'janedoe@gmail.com')

controller = createCustomerProfileController(createCustomerProfile)
controller.execute()

response = controller.getresponse()

if (response.messages.resultCode=="Ok"):
    print("Successfully created a customer profile with id: %s" % response.customerProfileId)
    customerProfileId = response.customerProfileId
    
    creditCard = apicontractsv1.creditCardType()
    creditCard.cardNumber = "4111111111111111"
    creditCard.expirationDate = "2021-12"

    payment = apicontractsv1.paymentType()
    payment.creditCard = creditCard

    billTo = apicontractsv1.customerAddressType()
    billTo.firstName = "Jane"
    billTo.lastName = "Doe"

    profile = apicontractsv1.customerPaymentProfileType()
    profile.payment = payment
    profile.billTo = billTo

    createCustomerPaymentProfile = apicontractsv1.createCustomerPaymentProfileRequest()
    createCustomerPaymentProfile.merchantAuthentication = merchantAuth
    createCustomerPaymentProfile.paymentProfile = profile
    print("customerProfileId in create_customer_payment_profile. customerProfileId = %s" %customerProfileId)
    createCustomerPaymentProfile.customerProfileId = str(customerProfileId)

    controller = createCustomerPaymentProfileController(createCustomerPaymentProfile)
    controller.execute()

    response = controller.getresponse()

    if (response.messages.resultCode=="Ok"):
        print("Successfully created a customer payment profile with id: %s" % response.customerPaymentProfileId)
        customerPaymentProfileId = response.customerPaymentProfileId
        
        profileToCharge = apicontractsv1.customerProfilePaymentType()
        profileToCharge.customerProfileId = str(customerProfileId)
        profileToCharge.paymentProfile = apicontractsv1.paymentProfile()
        profileToCharge.paymentProfile.paymentProfileId = str(customerPaymentProfileId)

        transactionrequest = apicontractsv1.transactionRequestType()
        transactionrequest.transactionType = "authCaptureTransaction"
        transactionrequest.amount = Decimal ('25.99')
        transactionrequest.profile = profileToCharge


        createtransactionrequest = apicontractsv1.createTransactionRequest()
        createtransactionrequest.merchantAuthentication = merchantAuth
        createtransactionrequest.refId = "RefId-001"

        createtransactionrequest.transactionRequest = transactionrequest
        createtransactioncontroller = createTransactionController(createtransactionrequest)
        createtransactioncontroller.execute()

        response = createtransactioncontroller.getresponse()

 

Powered by NexWebSites.com -
Certified Authorize.net developers

Sigh, I understand I could do it this way just don't understand why the documenation shows one thing and yet the functionality does not have this feature.  Spent quite a bit of time being aquiented with the sdk trying to set everything up, and the only solution is to add programming debt to the program

 

Is there any way that the it could be done with the call set up how my original code shows? Or is it just a feature that was never implimented into the sdk?

You almost had it with your initial posting. The order of the transactionrequest just needs to be modified a bit. By placing transactionrequest.profile = createcustomerprofile right after transactionrequest.payment = payment:

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

By the way, you should be able to see what XML is being posted by looking at the anetsdk.log in the root of your application. 

Powered by NexWebSites.com -
Certified Authorize.net developers