def get_embed_context(self, context): # list countries for billing address form context["authorizenet_countries"] = frappe.get_list( "Country", fields=["country_name", "name"], ignore_permissions=1) default_country = frappe.get_value("System Settings", "System Settings", "country") default_country_doc = next((x for x in context["authorizenet_countries"] if x.name == default_country), None) country_idx = context["authorizenet_countries"].index( default_country_doc) context["authorizenet_countries"].pop(country_idx) context["authorizenet_countries"] = [ default_country_doc ] + context["authorizenet_countries"] context["year"] = datetime.today().year # get the authorizenet user record authnet_user = get_authorizenet_user() if authnet_user: context["stored_payments"] = authnet_user.get( "stored_payments", [])
def get_context(context): context.no_cache = 1 # get request name from query string request_name = frappe.form_dict.get("req") # or from pathname, this works better for redirection on auth errors if not request_name: path_parts = context.get("pathname", "").split('/') request_name = path_parts[-1] # attempt to fetch AuthorizeNet Request record try: request = frappe.get_doc("AuthorizeNet Request", request_name) except Exception as ex: request = None # Captured/Authorized transaction redirected to home page # TODO: Should we redirec to a "Payment already received" Page? if not request or (request and request.get('status') in ("Captured", "Authorized")): frappe.local.flags.redirect_location = '/' raise frappe.Redirect # list countries for billing address form context["authorizenet_countries"] = frappe.get_list( "Country", fields=["country_name", "name"]) if request_name and request: for key in expected_keys: context[key] = request.get(key) context["reference_doc"] = frappe.get_doc( request.get("reference_doctype"), request.get("reference_docname")) context["request_name"] = request_name context["year"] = datetime.today().year # get the authorizenet user record authnet_user = get_authorizenet_user(request.get("payer_name")) context["authnet_user"] = authnet_user #add=get_primary_address(request.get("payer_name"),'1509101163') #context['address']=add if authnet_user: context["stored_payments"] = authnet_user.get( "stored_payments", []) else: frappe.redirect_to_message( _('Some information is missing'), _('Looks like someone sent you to an incomplete URL. Please ask them to look into it.' )) frappe.local.flags.redirect_location = frappe.local.response.location raise frappe.Redirect return context
def process_payment(self): # used for feedback about which payment was used authorizenet_data = {} # the current logged in contact contact = get_contact() # get authorizenet user if available authnet_user = get_authorizenet_user() # the cc data available data = self.process_data # get auth keys settings = self.get_settings() # fetch redirect info redirect_to = data.get("notes", {}).get("redirect_to") or None redirect_message = data.get("notes", {}).get("redirect_message") or None # uses dummy request doc for unittests as we are only testing processing if not data.get("unittest"): if data.get("name"): request = frappe.get_doc("AuthorizeNet Request", data.get("name")) else: # Create request from scratch when embeding form on the fly # # This allows payment processing without having to pre-create # a request first. # # This path expects all the payment request information to be # available!! # # keys expected: ('amount', 'currency', 'order_id', 'title', \ # 'description', 'payer_email', 'payer_name', \ # 'reference_docname', 'reference_doctype') request = self.build_authorizenet_request(**{ \ key: data[key] for key in \ ('amount', 'currency', 'order_id', 'title', \ 'description', 'payer_email', 'payer_name', \ 'reference_docname', 'reference_doctype') }) data["name"] = request.get("name") else: request = frappe.get_doc({"doctype": "AuthorizeNet Request"}) request.flags.ignore_permissions = 1 # set the max log level as per settings request.max_log_level(self.log_level) try: if self.card_info: # ensure card fields exist required_card_fields = [ 'name_on_card', 'card_number', 'exp_month', 'exp_year', 'card_code' ] for f in required_card_fields: if not self.card_info.get(f): request.status = "Error" return request, None, "Missing field: %s" % f, {} # prepare authorize api authorize.Configuration.configure( authorize.Environment.TEST if self.use_sandbox else authorize.Environment.PRODUCTION, settings.api_login_id, settings.api_transaction_key) # cache billing fields as per authorize api requirements billing = authnet_address(self.billing_info) if self.shipping_info: shipping = authnet_address(self.shipping_info) else: shipping = None # attempt to find valid email address email = self.process_data.get("payer_email") if email: email = email.split(',')[0] if "@" not in email and contact: email = contact.get("email_id") if "@" not in email: if contact and contact.user: email = frappe.get_value("User", contact.user, "email_id") if "@" not in email: log("AUTHNET FAILURE! Bad email: {0}".format( email)) raise ValueError( "There are no valid emails associated with this customer" ) # build transaction data transaction_data = { "order": { "invoice_number": data["order_id"] }, "amount": flt(self.process_data.get("amount")), "email": email, "description": self.card_info.get("name_on_card"), "customer_type": "individual" } # track ip for tranasction records if frappe.local.request_ip: transaction_data.update({ "extra_options": { "customer_ip": frappe.local.request_ip } }) # get authorizenet profile informatio for stored payments authorizenet_profile = self.process_data.get( "authorizenet_profile") # use card # see: https://vcatalano.github.io/py-authorize/transaction.html if self.card_info != None: # exp formating for sale/auth api expiration_date = "{0}/{1}".format( self.card_info.get("exp_month"), self.card_info.get("exp_year")) transaction_data.update({ "credit_card": { "card_number": self.card_info.get("card_number"), "expiration_date": expiration_date, "card_code": self.card_info.get("card_code") } }) elif authorizenet_profile: # if the customer_id isn't provided, then fetch from authnetuser if not authorizenet_profile.get("customer_id"): authorizenet_profile["customer_id"] = authnet_user.get( "authorizenet_id") # or stored payment transaction_data.update({ "customer_id": authorizenet_profile.get("customer_id"), "payment_id": authorizenet_profile.get("payment_id") }) # track transaction payment profile ids to return later authorizenet_data.update({ "customer_id": authorizenet_profile.get("customer_id"), "payment_id": authorizenet_profile.get("payment_id") }) else: raise "Missing Credit Card Information" name_parts = self.card_info["name_on_card"].split(' ') first_name = name_parts[0] last_name = " ".join(name_parts[1:]) # add billing information if available if len(billing.keys()): transaction_data["billing"] = billing transaction_data["billing"]["first_name"] = first_name transaction_data["billing"]["last_name"] = last_name if shipping and len(shipping.keys()): transaction_data["shipping"] = billing transaction_data["shipping"]["first_name"] = first_name transaction_data["shipping"]["last_name"] = last_name # include line items if available if self.process_data.get("line_items"): transaction_data["line_items"] = self.process_data.get( "line_items") request.log_action("Requesting Transaction: %s" % \ json.dumps(transaction_data), "Debug") # performt transaction finally result = authorize.Transaction.sale(transaction_data) request.log_action(json.dumps(result), "Debug") # if all went well, record transaction id request.transaction_id = result.transaction_response.trans_id request.status = "Captured" request.flags.ignore_permissions = 1 except AuthorizeInvalidError as iex: # log validation errors request.log_action(frappe.get_traceback(), "Error") request.status = "Error" error_msg = "" errors = [] if iex.children and len(iex.children) > 0: for field_error in iex.children: print(field_error.asdict()) for field_name, error in field_error.asdict().iteritems(): errors.append(error) error_msg = "\n".join(errors) request.error_msg = error_msg except AuthorizeResponseError as ex: # log authorizenet server response errors result = ex.full_response request.log_action(json.dumps(result), "Debug") request.log_action(str(ex), "Error") request.status = "Error" request.error_msg = ex.text redirect_message = str(ex) if result and hasattr(result, 'transaction_response'): # if there is extra transaction data, log it errors = result.transaction_response.errors request.log_action( "\n".join([err.error_text for err in errors]), "Error") request.log_action(frappe.get_traceback(), "Error") request.transaction_id = result.transaction_response.trans_id redirect_message = "Success" pass except Exception as ex: log(frappe.get_traceback()) # any other errors request.log_action(frappe.get_traceback(), "Error") request.status = "Error" request.error_msg = "[UNEXPECTED ERROR]: {0}".format(ex) pass # now check if we should store payment information on success if request.status in ("Captured", "Authorized") and \ self.card_info and \ self.card_info.get("store_payment") and \ contact: try: # create customer if authnet_user doesn't exist if not authnet_user: request.log_action("Creating AUTHNET customer", "Info") customer_result = authorize.Customer.from_transaction( request.transaction_id) request.log_action("Success", "Debug") authnet_user = frappe.get_doc({ "doctype": "AuthorizeNet Users", "authorizenet_id": customer_result.customer_id, "contact": contact.name }) card_store_info = { "card_number": self.card_info.get("card_number"), "expiration_month": self.card_info.get("exp_month"), "expiration_year": self.card_info.get("exp_year"), "card_code": self.card_info.get("card_code"), "billing": self.billing_info } request.log_action("Storing Payment Information With AUTHNET", "Info") request.log_action(json.dumps(card_store_info), "Debug") try: card_result = authorize.CreditCard.create( authnet_user.get("authorizenet_id"), card_store_info) except AuthorizeResponseError as ex: card_result = ex.full_response request.log_action(json.dumps(card_result), "Debug") request.log_action(str(ex), "Error") try: # duplicate payment profile if card_result["messages"][0]["message"][ "code"] == "E00039": request.log_action( "Duplicate payment profile, ignore", "Error") else: raise ex except: raise ex request.log_action("Success: %s" % card_result.payment_id, "Debug") address_short = "{0}, {1} {2}".format(billing.get("city"), billing.get("state"), billing.get("pincode")) card_label = "{0}{1}".format( get_card_accronym(self.card_info.get("card_number")), self.card_info.get("card_number")[-4:]) authnet_user.flags.ignore_permissions = 1 authnet_user.append( "stored_payments", { "doctype": "AuthorizeNet Stored Payment", "short_text": "%s %s" % (card_label, address_short), "long_text": "{0}\n{1}\n{2}, {3} {4}\n{5}".format( card_label, billing.get("address", ""), billing.get("city", ""), billing.get("state", ""), billing.get("pincode", ""), frappe.get_value( "Country", filters={ "name": self.billing_info.get("country") }, fieldname="country_name")), "address_1": self.billing_info.get("address_1"), "address_2": self.billing_info.get("address_2"), "expires": "{0}-{1}-01".format(self.card_info.get("exp_year"), self.card_info.get("exp_month")), "city": self.billing_info.get("city"), "state": self.billing_info.get("state"), "postal_code": self.billing_info.get("pincode"), "country": frappe.get_value("Country", self.billing_info.get("country"), fieldname="code"), "payment_type": "Card", "authorizenet_payment_id": card_result.payment_id }) authorizenet_data.update({ "customer_id": authnet_user.get("authorizenet_id"), "payment_id": card_result.payment_id }) if not data.get("unittest"): authnet_user.save() request.log_action("Stored in DB", "Debug") except Exception as exx: # any other errors request.log_action(frappe.get_traceback(), "Error") raise exx return request, redirect_to, redirect_message, authorizenet_data
def process_payment(self): # used for feedback about which payment was used authorizenet_data = {"error": 0} #authorizenet_data = [] data = self.process_data settings = self.get_settings() if not data.get("unittest"): if data.get("name"): request = frappe.get_doc("AuthorizeNet Request", data.get("name")) else: request = self.build_authorizenet_request(**{ \ key: data[key] for key in \ ('amount', 'currency', 'order_id', 'title', \ 'description', 'payer_email', 'payer_name', \ 'reference_docname', 'reference_doctype') }) data["name"] = request.get("name") else: request = frappe.get_doc({"doctype": "AuthorizeNet Request"}) try: transaction_data = { "order": { "invoice_number": data["order_id"], "description": data["description"] }, "amount": flt(self.process_data.get("amount")), } shipment_charges = {} """get_reference= frappe.get_doc(request.reference_doctype,request.reference_docname) if request.reference_doctype == "Payment Entry": if len(get_reference.references) == 1: inv_ref=get_reference.references ship_charg=frappe.get_doc(inv_ref[0].reference_doctype,inv_ref[0].reference_name) if inv_ref[0].reference_doctype == "Sales Invoice": shipment_charges= { 'amount': ship_charg.shipment_amount, 'name': ship_charg.shipment_name, 'description':"", } elif inv_ref[0].reference_doctype == "Sales order": shipment_charges= { 'amount': ship_charg.shipment_cost, 'name': ship_charg.shipping_service, 'description':"", } elif request.reference_doctype == "Payment Request": ship_charg=frappe.get_doc(get_reference.reference_doctype,get_reference.reference_name) if get_reference.reference_doctype == "Sales Invoice": shipment_charges= { 'amount': ship_charg.shipment_amount, 'name': ship_charg.shipment_name, 'description':"", } elif get_reference.reference_doctype == 'Sales order': shipment_charges= { 'amount': ship_charg.shipment_cost, 'name': ship_charg.shipping_service, 'description':"", }""" if shipment_charges: transaction_data["shipping_and_handling"] = shipment_charges transaction_data["line_items"] = get_line_items( request.reference_doctype, request.reference_docname) transaction_data["user_fields"] = get_additional_info( request.reference_doctype, request.reference_docname) if frappe.local.request_ip: transaction_data.update({ "extra_options": { "customer_ip": frappe.local.request_ip } }) authorize.Configuration.configure( authorize.Environment.TEST if self.use_sandbox else authorize.Environment.PRODUCTION, settings.api_login_id, settings.api_transaction_key) """authorize.Configuration.configure( authorize.Environment.TEST, '6M7Hp5u6', '8d5MgF9zB6A272df', ) """ authnet_user = get_authorizenet_user(request.get("payer_name")) authorizenet_profile = self.process_data.get( "authorizenet_profile") #if user select already saved payment profile then authorizenet_profile is true if bool(authorizenet_profile) == False: name_parts = request.get("payer_name").split(' ') name_on_card = str(self.card_info.get("name_on_card")) billing = self.billing_info first_name = name_parts[0] last_name = " ".join(name_parts[1:]) address = self.billing_info address["first_name"] = first_name[:50] address["last_name"] = last_name[:50] address["company"] = request.get("payer_name")[:50] card_store_info = { "customer_type": "individual", "card_number": self.card_info.get("card_number"), "expiration_month": self.card_info.get("exp_month"), "expiration_year": self.card_info.get("exp_year"), "card_code": self.card_info.get("card_code"), "billing": address } try: if not authnet_user: #request.log_action("Creating AUTHNET customer", "Info") customer_result = authorize.Customer.create({ 'email': billing.get("auth_email"), 'description': request.get("payer_name"), 'customer_type': 'individual', 'billing': address, 'credit_card': { 'card_number': self.card_info.get("card_number"), 'card_code': self.card_info.get("card_code"), 'expiration_month': self.card_info.get("exp_month"), 'expiration_year': self.card_info.get("exp_year") } }) authnet_user = frappe.new_doc("AuthorizeNet Users") authnet_user.authorizenet_id = customer_result.customer_id authnet_user.contact = request.get("payer_name") authnet_user.email = billing.get("auth_email") authorize_payment_id = customer_result.payment_ids[0] else: card_result = authorize.CreditCard.create( authnet_user.get("authorizenet_id"), card_store_info) authorize_payment_id = card_result.payment_id authorizenet_data.update({ "customer_id": authnet_user.get("authorizenet_id"), "payment_id": authorize_payment_id, "name_on_card": name_on_card, }) authnet_user.append( "stored_payments", { "doctype": "AuthorizeNet Stored Payment", "long_text": "{0}\n{1}\n{2}, {3} {4}".format( billing.get("address", ""), billing.get("city", ""), billing.get("state", ""), billing.get( "zip", ""), "United States"), "address_1": self.billing_info.get("address"), "name_on_card": self.card_info.get("name_on_card"), "expires": "{0}-{1}-01".format( self.card_info.get("exp_year"), self.card_info.get("exp_month")), "city": self.billing_info.get("city"), "state": self.billing_info.get("state"), "postal_code": self.billing_info.get("zip"), "country": "United States", "authorizenet_payment_id": authorize_payment_id, "card_type": get_card_accronym( self.card_info.get("card_number")), "card_no": self.card_info.get("card_number")[-4:] }) authnet_user.save() transaction_data.update({ "customer_id": authnet_user.get("authorizenet_id"), "payment_id": authorize_payment_id, }) except AuthorizeResponseError as ex: card_result = ex.full_response authorizenet_data.update({ "customer_id": "0", "payment_id": "0", "name_on_card": "0", "error": card_result, "card_no": 0, "card_type": 0 }) request.log_action(json.dumps(card_result), "Debug") request.log_action(str(ex), "Error") try: # duplicate payment profile if card_result["messages"][0]["message"][ "code"] == "E00039": request.log_action( "Duplicate payment profile, ignore", "Error") else: raise ex except: raise ex else: name_on_card = str(authorizenet_profile.get("name_on_card")) authorizenet_data.update({ "customer_id": authnet_user.get("authorizenet_id"), "payment_id": authorizenet_profile.get("payment_id"), "name_on_card": name_on_card }) transaction_data.update({ "email": authorizenet_profile.get("auth_email"), "customer_id": authnet_user.get("authorizenet_id"), "payment_id": authorizenet_profile.get("payment_id"), }) result = authorize.Transaction.sale(transaction_data) request.log_action(json.dumps(result), "Debug") request.transaction_id = result.transaction_response.trans_id request.status = "Captured" authorizenet_data.update({ "card_type": result.transaction_response.account_type, "card_no": result.transaction_response.account_number }) except AuthorizeInvalidError as iex: # log validation errors request.log_action(frappe.get_traceback(), "Error") request.status = "Error" request.transaction_id = "0" error_msg = "" errors = [] if iex.children and len(iex.children) > 0: for field_error in iex.children: #print(field_error.asdict()) for error in field_error.asdict().items(): errors.append(error) #error_msg = "\n".join(errors) error_msg = str(errors) request.error_msg = error_msg authorizenet_data.update({ "customer_id": 0, "payment_id": "0", "name_on_card": "0", "error": error_msg, "card_no": 0, "card_type": 0 }) #redirect_message=error_msg #redirect_to='Error AuthorizeInvalidError' except AuthorizeResponseError as ex: # log authorizenet server response errors result = ex.full_response request.log_action(json.dumps(result), "Debug") request.log_action(str(ex), "Error") request.status = "Error" request.error_msg = ex.text request.transaction_id = "0" authorizenet_data.update({ "customer_id": 0, "payment_id": "0", "name_on_card": "0", "error": ex.text, "card_no": 0, "card_type": 0 }) #redirect_message = str(ex) #redirect_to='Error AuthorizeResponseError' except Exception as ex: #log(frappe.get_traceback()) # any other errors request.log_action(frappe.get_traceback(), "Error") request.status = "Error" request.error_msg = "[UNEXPECTED ERROR]: {0}".format(ex) #redirect_message ="[UNEXPECTED ERROR]: {0}".format(ex) #redirect_to='Error Exception ex' authorizenet_data.update({ "customer_id": 0, "payment_id": "0", "name_on_card": "0", "error": "[UNEXPECTED ERROR]: {0}".format(ex), "card_no": 0, "card_type": 0 }) return request, authorizenet_data