Jump to content

API - updateclient - customfields - python


JonTheWong

Recommended Posts

Hello,

I'm working on a python script and i'd like to insert customfields on the updateclient call.

This is a json of tblcustomfields

{"id":"2","type":"client","relid":"0","fieldname":"status","fieldtype":"dropdown","description":"","fieldoptions":"notVerified,verified","regexpr":"","adminonly":"on","required":"","showorder":"","showinvoice":"","sortorder":"0","created_at":"0000-00-00 00:00:00","updated_at":"0000-00-00 00:00:00"},

tblcustomfieldsvalues

{"id":"5","fieldid":"2","relid":"297","value":"verified","created_at":"2019-11-05 04:38:50","updated_at":"2019-11-05 04:38:50"},
{"id":"6","fieldid":"3","relid":"297","value":"","created_at":"2019-11-05 04:38:50","updated_at":"2019-11-05 04:38:50"},
{"id":"7","fieldid":"4","relid":"297","value":"","created_at":"2019-11-05 04:38:50","updated_at":"2019-11-05 04:38:50"},
{"id":"8","fieldid":"6","relid":"297","value":"","created_at":"2019-11-05 04:38:50","updated_at":"2019-11-05 04:38:50"}

 

Now when it comes to pushing the data, the documentation isn't clear. All i'm seeing is;

customfields|string|Base64 encoded serialized array of custom field values|Optional

Based on web searching, its not getting clearer.

Here is a snipped of my last code.

cstatus = { "fieldid": "2", "value": "verified" }
encoded = base64.b64encode(b'cstatus')
with requests.Session() as session_whmcs_bounces:
	session_whmcs_bounces.headers.update(whmcs_auth)
    whmcs_bounces_payload = { 'identifier': whmcs_ident, 'secret': whmcs_secret, 'responsetype': whmcs_response, 'action': "UpdateClient", 'clientemail': email, 'status': "Inactive", 'marketingoptin': 0, 'notes': '--- Bounces ---\nCreated: %s\nStatus: %s\nReason: %s\n---Bounces---' % (timeconvert,status,reason), 'customfields': encoded }

 

i tried using the json.dumps/json.loads techniques to serialize the data, but in my mind i don't have to since the data is already serialized, i just have to encode it.

I also tried variations, as in just the ID and value { "2": "verified" } / { "id": "2", "value": "verified" } and different combinations. Been at it for a few hours and can't seem to find much information.

Ideally i'd like to update multiple sections based on the json reply.

The flow i'm trying to achieve is this;

Receive client information from datasource.

{
      "email": "example@domain.tld",
      "type": "prospect",
      "status": "verified",
      "firstName": "Jon",
      "lastName": "Wong",
      "position": "Senior Linux Administrator",
      "sourcePage": "https:\/\/www.linkedin.com\/in\/jonthewong"
    }

Add it or Update it into WHMCS

Use extra fields as customfields.

In this case, type/status/position/sourcepage

The python code shown is for a separate part of the project, but the customfields base64,serialization still apply.

If anyone has any experience or suggestions i'd appreciate it.

Thank you.

On a side note, I'm using Python 3.7 + requests/time/json/base64/getpass I'm open to adding other libs, but ideally i'd prefer using the ones i already have build for this env.

Link to comment
Share on other sites

  • 6 months later...
  • 1 month later...

Right, so I am doing some python automatisation myself and was stuck on this problem for half a day, so if anyone needs info on how to send customfields param to WHMCS api with python here it is.

This is a simple script to AddOrder with some custom fields in it:

import requests
import base64
import phpserialize


# Setting up default settings
identifier = "yourIdentifier"
secret = "yourSecret"

url = "yourAPIurl"

# Making the customfields string
customfieldsVALUE = base64.b64encode(phpserialize.dumps({'fieldID':'fieldVALUE', 'fieldID2':'fieldVALUE2'}))

# Assigning params to a dict
params = {
  'identifier': identifier,
  'secret': secret,
  'action': "AddOrder",
  'responsetype': "json",
  'clientid': 'yourClientID',
  'paymentmethod': 'yourPaymentMethod',
  'pid': 'yourPuschaseID',
  'domain': 'yourDomain',
  'billingcycle': 'yourBillingCycle',
  'customfields': customfieldsVALUE #this is the string that i setup above
}

# sending the request
r = requests.post(url, params=params)
answer = r.text # this returns a big string, you need to convert it into json if you want to use the answer in any way

print(answer)

Main thing to understand is that the API is asking for base64 encoded serialized array(or in python case a dictionary), and it wants us to use the php serialize, so to get around that we have to import custom lib(i used phpserialize), that can serialize data in php way, and use it on our array of customfield key and value pairs before we encode it with base64:

customfieldsVALUE = base64.b64encode(phpserialize.dumps({'fieldID':'fieldVALUE', 'fieldID2':'fieldVALUE2'}))

 

Link to comment
Share on other sites

customfieldsVALUE = base64.b64encode(phpserialize.dumps({'fieldID':'fieldVALUE', 'fieldID2':'fieldVALUE2'}))

Just perfect, working for me on Python 3.7

Thanks a bunch i appreciate the feedback.

If anyone is having issues finding the fieldID; its in 'tblcustomfields' in the database.  Nothing special if its a dropdown, link or text fieldtype. Haven't testing it with any validation but i assume thats frontend vs a direct api entry.

Edited by jwong
Link to comment
Share on other sites

  • 2 months later...

@pentom12 This is what i have;

serializedcustomfields = base64.b64encode(phpserialize.dumps({cidStatus: 'verified', cidType: 'prospect', cidTitle: title, cidDomain: domain, cidSource: sourcepage, cidResults: size, cidWebmail: webmail}))

params = {
            'identifier': identifier,
            'secret': secret,
            'responsetype': 'JSON',
            'action': 'AddClient',
            'currency': 1,
            'groupid': groupid,
            'notes': 'import',
            'marketingoptin': True,
            'noemail': True,
            'skipvalidation': True,
            'customfields': serializedcustomfields,
            'companyname': companyname,
            'phonenumber': phonenumber,
            'address1': address1,
            'city': city,
            'state': state,
            'country': country,
            'postcode': postcode,
            'email': email,
            }

res = requests.post(posturi, data=params, verify=True, timeout=120)

It looks like your trying to add custom fields to products. What "action" are you trying to add serialized custom fields too?

I'm using it in the "AddClient" request. Verify that your method supports custom fields.

good luck

 

Edited by JonTheWong
syntax highlight
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use & Guidelines and understand your posts will initially be pre-moderated