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
09-13-2017 10:56 AM - edited 09-13-2017 10:58 AM
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"
}
}
09-13-2017 12:10 PM
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
09-13-2017 12:14 PM
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": {
09-13-2017 12:34 PM - edited 09-13-2017 12:35 PM
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 = TrueAnd then later adding it in
transactionrequest.profile = createcustomerprofile
But it's not creating the profile
09-13-2017 12:38 PM
09-13-2017 12:40 PM - edited 09-13-2017 12:41 PM
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.
09-13-2017 01:21 PM
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()
09-14-2017 02:02 AM - edited 09-14-2017 02:05 AM
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?
09-14-2017 05:51 PM
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_itemsBy 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.
09-15-2017 04:39 AM - edited 09-15-2017 04:44 AM