SSO:How to get array of groups in redmine ominiauth SAML plugin from the SAML respone? - single-sign-on

Implementing SSO for redmine: Idp- OpenAM, SP-redmine (Ominiauth SAML plugin)
I want to get list of groups which are assigned to user in redmine_ominiauth_saml plugin but I can get just single group which is first on SAML response in groups assertion.
So is there any different configuration for array attribute:
Mapping of attributes for SP on OpenAM:
groups=isMemberOf
last_name=sn
username=mail
first_name=givenName
email=mail
Mapping of attributes on Redmine:
"/opt/redmine/config/initializers/saml_3.0.rb"
:attribute_mapping => {
# How will we map attributes from SSO to redmine attribute
:login => 'extra.raw_info.username',
:firstname => 'extra.raw_info.first_name',
:lastname => 'extra.raw_info.last_name',
:mail => 'extra.raw_info.email',
:isMemberOf => 'extra.raw_info.groups'
}
SAML response contains attribute groups in array like this:
<saml:AttributeStatement>
<saml:Attribute Name="first_name">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="xs:string"
>umesh</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="username">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="xs:string"
>ubr#abc.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="email">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="xs:string"
>ubr#abc.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="last_name">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="xs:string"
>rajani</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="groups">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="xs:string"
>cn=ABC,ou=groups,dc=abc,dc=opendj,dc=com</saml:AttributeValue>
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="xs:string"
>cn=XYZ,ou=groups,dc=abc,dc=opendj,dc=com</saml:AttributeValue>
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="xs:string"
>cn=YZQ,ou=groups,dc=abc,dc=opendj,dc=com</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
I knew this code in SAML plugin gives me single group (code in ruby):
/opt/redmine/plugins/redmine_omniauth_saml/lib/redmine_omniauth_saml.rb
def user_attributes_from_saml(omniauth)
HashWithIndifferentAccess.new.tap do |h|
required_attribute_mapping.each do |symbol|
key = configured_saml[:attribute_mapping][symbol]
h[symbol] = key.split('.') # Get an array with nested keys: name.first will return [name, first]
.map {|x| [:[], x]} # Create pair elements being :[] symbol and the key
.inject(omniauth) do |hash, params| # For each key, apply method :[] with key as parameter
hash.send(*params)
end
**print "key:value "+key+":" +h[symbol]** # gives key value pair, first_name, group 'ABC' only leaves other group
end
end
end

Actually ruby-saml plugin is default retrun as attributes as single value.
We need to set as for multi value in ruby-saml plugin.
ruby-saml plugin have attributes.rb file.
Update the value of ##single_value_compatibility and set as "false"
Now you are getting full array of value.
Hope you issue will resolved.

Related

Schema validation error when using Restriction in EWS FindItem request

I'm trying to find items in inbox with ItemClass = IPM.Note
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:wsi="http://ws-i.org/schemas/conformanceClaim/">
<soap:Header>
<t:RequestServerVersion Version="Exchange2010_SP2"></t:RequestServerVersion>
</soap:Header>
<soap:Body>
<FindItem Traversal="Shallow" xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
<ItemShape>
<t:BaseShape xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">IdOnly</t:BaseShape>
<t:AdditionalProperties xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<t:FieldURI FieldURI="item:ItemClass"></t:FieldURI>
</t:AdditionalProperties>
</ItemShape>
<IndexedPageItemView MaxEntriesReturned="50" Offset="0" BasePoint="Beginning"></IndexedPageItemView>
<Restriction>
<IsEqualTo>
<FieldURI FieldURI="item:ItemClass"></FieldURI>
<FieldURIOrConstant>
<Constant Value="IPM.Note"></Constant>
</FieldURIOrConstant>
</IsEqualTo>
</Restriction>
<ParentFolderIds>
<t:DistinguishedFolderId Id="inbox" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"></t:DistinguishedFolderId>
</ParentFolderIds>
</FindItem>
</soap:Body>
</soap:Envelope>
Resulting in this SchemaValidationError
a:ErrorSchemaValidation: The request failed schema validation: The element 'Restriction' in namespace 'http://schemas.microsoft.com/exchange/services/2006/messages' has invalid child element 'IsEqualTo' in namespace 'http://schemas.microsoft.com/exchange/services/2006/messages'. List of possible elements expected: 'SearchExpression' in namespace 'http://schemas.microsoft.com/exchange/services/2006/types'. [undefined] Error: a:ErrorSchemaValidation: The request failed schema validation: The element 'Restriction' in namespace 'http://schemas.microsoft.com/exchange/services/2006/messages' has invalid child element 'IsEqualTo' in namespace 'http://schemas.microsoft.com/exchange/services/2006/messages'. List of possible elements expected: 'SearchExpression' in namespace 'http://schemas.microsoft.com/exchange/services/2006/types'.
To my understaning, SearchExpression is an abstract type that can be replaced with IsEqualTo, among other types.
What am I missing here?
Some of these elements are in the 'types' namespace so they need the t: prefix
<Restriction>
<t:IsEqualTo>
<t:FieldURI FieldURI="item:ItemClass"></t:FieldURI>
<t:FieldURIOrConstant>
<t:Constant Value="IPM.Note"></t:Constant>
</t:FieldURIOrConstant>
</t:IsEqualTo>
</Restriction>

Invalid Soap Call

Why doesn't this soap call work for this URL ?
http://services.aonaware.com/DictService/DictService.asmx?op=Define
<v:Envelope xmlns:i="http://www.w3.org/1999/XMLSchema-instance" xmlns:d="http://www.w3.org/1999/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/envelope/">
<v:Header />
<v:Body>
<Define xmlns="http://tempuri.org/" id="o0" c:root="1">
<word i:type="d:string">Name</word>
</Define>
</v:Body>
</v:Envelope>
But this one does
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://services.aonaware.com/webservices/">
<soapenv:Header/>
<soapenv:Body>
<web:Define>
<!--Optional:-->
<web:word>Test</web:word>
</web:Define>
</soapenv:Body>
</soapenv:Envelope>
Because they are different: not only in content but also in namespace definition, to correct the first one you've to atleast use the correct namespace so use http://services.aonaware.com/webservices/ for your <Define> element as you do in the second one:
<v:Envelope xmlns:i="http://www.w3.org/1999/XMLSchema-instance" xmlns:d="http://www.w3.org/1999/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/envelope/">
<v:Header />
<v:Body>
<Define xmlns="http://services.aonaware.com/webservices/" id="o0" c:root="1">
<word i:type="d:string">Name</word>
</Define>
</v:Body>
</v:Envelope>
Then make sure also that id an c:root are valid attributes in your xsd for <Definition> and i:type it's a correct one for <word>.
EDIT
I invoke http://services.aonaware.com/DictService/DictService.asmx with SOAPUI using my corrected request and it response correctly:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<DefineResponse xmlns="http://services.aonaware.com/webservices/">
<DefineResult>
<Word>Name</Word>
<Definitions>
<Definition>
<Word>Name</Word>
<Dictionary>
<Id>gcide</Id>
<Name>The Collaborative International Dictionary of English v.0.44</Name>
</Dictionary>
<WordDefinition>Name \Name\ (n[=a]m), n. [AS. nama; akin to D. naam, OS. & OHG.
...
[1913 Webster]</WordDefinition>
</Definition>
<Definition>
<Word>Name</Word>
<Dictionary>
<Id>gcide</Id>
<Name>The Collaborative International Dictionary of English v.0.44</Name>
</Dictionary>
<WordDefinition>Name \Name\ (n[=a]m), v. t. [imp. & p. p. {Named} (n[=a]md); p.
...
</WordDefinition>
</Definition>
</Definitions>
</DefineResult>
</DefineResponse>
</soap:Body>
</soap:Envelope>
Hope this helps,

How to 'set' read-only calendar appointment properties (related to meetings)?

I'm recreating calendar meeting events in a sychronization tool (using CreateItem), basically preserving some properties for meetings and writing them back.
However, there are some properties that are read-only, and I see no way to preserve their state:
IsMeeting
IsCancelled
MeetingRequestWasSent
IsOnlineMeeting
Some of these boolean values are stored in property AppointmentState, but that is read-only too:
Name Bit Description
None 0x0000 No flags have been set. This is only used for an appointment that does not include attendees.
Meeting 0x0001 This appointment is a meeting.
Received 0x0002 This appointment has been received.
Canceled 0x0004 This appointment has been canceled.
Is IsMeeting maybe automatically set if I set other meeting-properties, like e.g. OptionalAttendees or RequiredAttendees? That would help with one of the four, if I knew which properties trigger the setting of IsMeeting.
(Yes, this is a follow-up to Meeting request properties not settable in EWS SOAP calls?).
You should be able to use MAPI Extended Properties:
Appointment state is
Named Prop Name: id: 0x8217=33303 = PidLidAppointmentStateFlags, dispidApptStateFlags
Named Prop Guid: {00062002-0000-0000-C000-000000000046} = PSETID_Appointment
So SOAP that should be something like
<t:ExtendedProperty>
<t:ExtendedFieldURI DistinguishedPropertySetId="Appointment" PropertyId="33303" PropertyType="Integer" />
<t:Value>1</t:Value>
</t:ExtendedProperty>
(I use the managed API for that, and got that XML from the trace-log, hope that is something you can use)
[Edited by the OP] This is the complete call that does the job:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:typ="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:mes="http://schemas.microsoft.com/exchange/services/2006/messages">
<soapenv:Header>
<typ:RequestServerVersion Version="Exchange2007_SP1"/>
<typ:MailboxCulture>en-US</typ:MailboxCulture>
<typ:TimeZoneContext>
<typ:TimeZoneDefinition Id="W. Europe Standard Time"/>
</typ:TimeZoneContext>
</soapenv:Header>
<soapenv:Body>
<mes:UpdateItem ConflictResolution="AutoResolve" SendMeetingInvitationsOrCancellations="SendOnlyToChanged">
<mes:ItemChanges>
<typ:ItemChange>
<typ:ItemId <t:ItemId Id="AAMkA[snip]xAAA=" ChangeKey="Dw[snip]Mar"/>
<typ:Updates>
<typ:SetItemField>
<typ:ExtendedFieldURI DistinguishedPropertySetId="Appointment" PropertyId="33303" PropertyType="Integer"/>
<typ:CalendarItem>
<typ:ExtendedProperty>
<typ:ExtendedFieldURI DistinguishedPropertySetId="Appointment" PropertyId="33303" PropertyType="Integer"/>
<typ:Value>5</typ:Value>
</typ:ExtendedProperty>
</typ:CalendarItem>
</typ:SetItemField>
</typ:Updates>
</typ:ItemChange>
</mes:ItemChanges>
</mes:UpdateItem>
</soapenv:Body>
</soapenv:Envelope>
Strangely, the result says "Success", but reports a (one) conflict. I have no idea which one:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<h:ServerVersionInfo MajorVersion="15" MinorVersion="1" MajorBuildNumber="225" MinorBuildNumber="19" Version="V2_48" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</s:Header>
<s:Body>
<m:UpdateItemResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:UpdateItemResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:Items>
<t:CalendarItem>
<t:ItemId Id="AAMk[snip]xAAA=" ChangeKey="DwA[snip]aMat"/>
</t:CalendarItem>
</m:Items>
<m:ConflictResults>
<t:Count>1</t:Count>
</m:ConflictResults>
</m:UpdateItemResponseMessage>
</m:ResponseMessages>
</m:UpdateItemResponse>
</s:Body>
</s:Envelope>

Querying Exchange Web Services fails with 400 Bad Request

I am trying to get some information from a specific calendar using EWS and Powershell.
I have a powershell function that I use to query EWS
Function EWSSoapRequest
{
param (
$soapRequest,
$exchangeServerAddress
)
# Create the request
$webRequest = [System.Net.WebRequest]::Create($exchangeServerAddress)
$webRequest.ContentType = "text/xml"
$webRequest.Headers.Add("Translate", "F")
$webRequest.Method = "Post"
$webRequest.Credentials = $credentials
# Setup the soap request to send to the server
$content = [System.Text.Encoding]::UTF8.GetBytes($soapRequest)
$webRequest.ContentLength = $content.Length
$requestStream = $webRequest.GetRequestStream()
$requestStream.Write($content, 0, $content.Length)
$requestStream.Close()
# Get the xml response from the server
$webResponse = $webRequest.GetResponse()
$responseStream = $webResponse.GetResponseStream()
$responseXml = [xml](new-object System.IO.StreamReader $responseStream).ReadToEnd()
$responseStream.Close()
$webResponse.Close()
$responseXml
}
I can get the list of calendar items just fine, using this XML:
$soapRequestOverview = #'
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<t:RequestServerVersion Version="Exchange2010_SP2" />
<t:ExchangeImpersonation>
<t:ConnectingSID>
<t:SmtpAddress>user#domain.dk</t:SmtpAddress>
</t:ConnectingSID>
</t:ExchangeImpersonation>
</soap:Header>
<soap:Body>
<FindItem Traversal="Shallow" xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
<ItemShape>
<t:BaseShape>IdOnly</t:BaseShape>
<t:AdditionalProperties>
<t:FieldURI FieldURI="calendar:Start"/>
<t:FieldURI FieldURI="calendar:End"/>
<t:FieldURI FieldURI="item:Subject"/>
</t:AdditionalProperties>
</ItemShape>
<CalendarView MaxEntriesReturned="100" StartDate="{0}" EndDate="{1}"/>
<ParentFolderIds>
<t:DistinguishedFolderId Id="calendar"/>
</ParentFolderIds>
</FindItem>
</soap:Body>
</soap:Envelope>
'#
That gives me a list of entries in the given calendar (I replace the state and end date before calling the web service function. Then from the list of calendar items returned I use the ItemID property to try and query detailed information like location etc. But it is here I run into problems.
I use this XML to make the query and use the EWSSoapRequest function as before, but I keep getting 400 Bad request back. If I copy/paste the xml into SoapUI then I get a response just fine with the expected data.
$SoapRequestDetail = #'
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<t:RequestServerVersion Version="Exchange2010_SP2" />
<t:ExchangeImpersonation>
<t:ConnectingSID>
<t:SmtpAddress>user#domain.dk</t:SmtpAddress>
</t:ConnectingSID>
</t:ExchangeImpersonation>
</soap:Header>
<soap:Body>
<m:GetItem>
<m:ItemShape>
<t:BaseShape>AllProperties</t:BaseShape>
</m:ItemShape>
<m:ItemIds>
<t:ItemId Id="AAMkADU3MzNlNjQxLTA3NDYtNDA4MS1hMmJhLTg5MmUxOTM2NzI3YwBGAAAAAABifraNBbAgRq+5NEGUOyNbBwBOxvhv/eH/R6wHrO/Hc4RhAAABnAHkAAChTN/6w47WS4YxX5iYDfnHAABfYm2zAAA=" />
</m:ItemIds>
</m:GetItem>
</soap:Body>
</soap:Envelope>
'#
Is it just me overlooking something obvious ?
Try using this XML instead
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<soap:Header>
<t:RequestServerVersion Version="Exchange2010_SP2" />
<t:ExchangeImpersonation>
<t:ConnectingSID>
<t:SmtpAddress>user#domain.com</t:SmtpAddress>
</t:ConnectingSID>
</t:ExchangeImpersonation>
</soap:Header>
<soap:Body>
<GetItem
xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<ItemShape>
<t:BaseShape>AllProperties</t:BaseShape>
</ItemShape>
<ItemIds>
<t:ItemId Id="AAAlAF" />
</ItemIds>
</GetItem>
</soap:Body>
</soap:Envelope>
Cheers
Glen

Customer attributes not saving on Add

So I've been experimenting with adding customers to QuickBooks Online from a local database instance at our business. I want to keep track of our internal customer reference numbers in QBO, so have tried to save those to several different attributes like AcctNum, ExternalKey, ExternalId, AlternateId, or even directly to the Id attribute. After attempting to save to these fields, the return result looks good.
var qbCustomer = new Customer
{
AcctNum = customer.CustRef.ToString(CultureInfo.InvariantCulture),
ExternalKey = new IdType {idDomain = idDomainEnum.NG, Value = customer.CustRef.ToString(CultureInfo.InvariantCulture)},
Id = new IdType {idDomain = idDomainEnum.NG, Value = customer.CustRef.ToString(CultureInfo.InvariantCulture)},
Name = customer.CustName1,
FamilyName = customer.CustRef.ToString(CultureInfo.InvariantCulture),
};
Customer resultCustomer = dataServices.Add(qbCustomer);
But the next time I retrieve those customers, all of those fields are just null. Why are these fields not saving? Is there another more appropriate field to use to store an external ID besides just using one of the plain text fields (Name, Address, etc.)?
UPDATE:
Here's the raw XML exchange.
What I sent when adding a new customer:
<?xml version="1.0" encoding="utf-8"?>
<q1:Customer xmlns="http://www.intuit.com/sb/cdm/qbo" xmlns:q1="http://www.intuit.com/sb/cdm/v2">
<q1:Id>7</q1:Id>
<q1:ExternalKey>7</q1:ExternalKey>
<q1:TypeOf>Person</q1:TypeOf>
<q1:Name>Customer Name</q1:Name>
<q1:FamilyName>7</q1:FamilyName>
<q1:AcctNum>7</q1:AcctNum>
</q1:Customer>
Intuit's response:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Customer xmlns="http://www.intuit.com/sb/cdm/v2" xmlns:qbp="http://www.intuit.com/sb/cdm/qbopayroll/v1" xmlns:qbo="http://www.intuit.com/sb/cdm/qbo">
<Id idDomain="QBO">12</Id>
<SyncToken>0</SyncToken>
<MetaData><CreateTime>2013-07-25T13:51:43-07:00</CreateTime><LastUpdatedTime>2013-07-25T13:51:43-07:00</LastUpdatedTime></MetaData>
<Name>Customer Name</Name>
<WebSite/>
<Email/>
<FamilyName>7</FamilyName>
<CustomField xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="StringTypeCustomField"><DefinitionId>Preferred Delivery Method</DefinitionId><Value>DONT</Value></CustomField>
<CustomField xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="StringTypeCustomField"><DefinitionId>Resale Number</DefinitionId></CustomField>
<CustomField xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="BooleanTypeCustomField"><DefinitionId>Bill With Parent</DefinitionId><Value>false</Value></CustomField>
<ShowAs>Erik Kunze/Magdalena Guarda Munoz</ShowAs>
<OpenBalance><Amount>0</Amount></OpenBalance>
</Customer>
My retrieval later:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<qbo:SearchResults xmlns="http://www.intuit.com/sb/cdm/v2" xmlns:qbp="http://www.intuit.com/sb/cdm/qbopayroll/v1" xmlns:qbo="http://www.intuit.com/sb/cdm/qbo">
<qbo:CdmCollections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Customers">
<Customer>
<Id idDomain="QBO">12</Id>
<SyncToken>0</SyncToken>
<MetaData><CreateTime>2013-07-25T13:51:43-07:00</CreateTime><LastUpdatedTime>2013-07-25T13:51:43-07:00</LastUpdatedTime></MetaData>
<Name>Customer Name</Name>
<WebSite/>
<Email/>
<FamilyName>7</FamilyName>
<CustomField xsi:type="BooleanTypeCustomField"><DefinitionId>Bill With Parent</DefinitionId><Value>false</Value></CustomField>
<CustomField xsi:type="StringTypeCustomField"><DefinitionId>Preferred Delivery Method</DefinitionId><Value>DONT</Value></CustomField>
<ShowAs>Erik Kunze/Magdalena Guarda Munoz</ShowAs>
<OpenBalance><Amount>0</Amount></OpenBalance>
</Customer>
</qbo:CdmCollections>
<qbo:Count>1</qbo:Count>
<qbo:CurrentPage>1</qbo:CurrentPage>
</qbo:SearchResults>
There's no AcctNum in the raw XML anywhere.
You are referring QBD's customer endpoint in apiexplorer.
Correct QBO link - https://developer.intuit.com/apiexplorer?apiname=V2QBO#Customer
Api Docs & Sample Create request - https://developer.intuit.com/docs/0025_quickbooksapi/0050_data_services/v2/0400_quickbooks_online/customer#Sample_Create_Request_XML
Simplest request body to create QBO customer -
<Customer xmlns:ns2="http://www.intuit.com/sb/cdm/qbo" xmlns="http://www.intuit.com/sb/cdm/v2" xmlns:ns3="http://www.intuit.com/sb/cdm/baseexceptionmodel/xsd">
<TypeOf>Person</TypeOf>
<Name>TestQBCustomer12345</Name>
</Customer>
Simplest Response
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Customer xmlns="http://www.intuit.com/sb/cdm/v2" xmlns:qbp="http://www.intuit.com/sb/cdm/qbopayroll/v1" xmlns:qbo="http://www.intuit.com/sb/cdm/qbo">
<Id idDomain="QBO">14</Id>
<SyncToken>0</SyncToken>
<MetaData>
<CreateTime>2013-07-25T14:08:49-07:00</CreateTime>
<LastUpdatedTime>2013-07-25T14:08:49-07:00</LastUpdatedTime>
</MetaData>
<Name>TestQBCustomer12345</Name>
<WebSite/>
<Email/>
<CustomField xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="StringTypeCustomField">
<DefinitionId>Preferred Delivery Method</DefinitionId>
<Value>DONT</Value>
</CustomField>
<CustomField xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="StringTypeCustomField">
<DefinitionId>Resale Number</DefinitionId>
</CustomField>
<CustomField xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="BooleanTypeCustomField">
<DefinitionId>Bill With Parent</DefinitionId>
<Value>false</Value>
</CustomField>
<ShowAs>TestQBCustomer12345</ShowAs>
<OpenBalance>
<Amount>0</Amount>
</OpenBalance>
</Customer>
You can test it first using apiexplorer then use the proper setters to do the same in your code.
Please let me know how it goes.
Thanks
Refer to the documentation:
https://developer.intuit.com/docs/0025_quickbooksapi/0050_data_services/v2/0500_quickbooks_windows/0600_object_reference/customer
You'll note that:
Id is an internal key generated by IPP/IDS - it's NOT something you can set yourself.
ExternalKey is the same situation - it's generated by IPP/IDS, not set-able by you.
ExternalId is marked "UNSUPPORTED FIELD."
AlternateId is marked "NOT SUPPORTED."
The only one of these fields that should work is:
AcctNum
If you're still having problems with that field, the way to troubleshoot is to get the raw XML outgoing request from Intuit, the raw XML that you get back (showing success) and then the raw response that you get back when you query it, showing that it's NULL.