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 = True
And 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_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.
09-15-2017 04:39 AM - edited 09-15-2017 04:44 AM