t3rminus / canada-post

Wrapper for the Canada Post API
MIT License
19 stars 10 forks source link

Clarification on constructing sku-list #9

Closed ssshake closed 2 years ago

ssshake commented 2 years ago

Hi, I can't find any good information on canada post's documentation and I'm unsure if I'm doing this correctly. For US orders I need to fill out customs. Inside of customs it requires a sku list which then contains an object for each item.

The problem is I can only get this to work with one item. Any more and canada post throws and error about duplicate sku-lists.

My skulist looks like this:

[
  {
    item: {
      customsNumberOfUnits: 3,
      customsDescription: 'test1,
      sku: '18828',
      unitWeight: '0.14',
      customsValuePerUnit: 35
    }
  },
  {
    item: {
      customsNumberOfUnits: 1,
      customsDescription: 'test2',
      sku: '19045',
      unitWeight: '0.01',
      customsValuePerUnit: 25
    }
  },
  {
    item: {
      customsNumberOfUnits: 1,
      customsDescription: 'test3',
      sku: '23959',
      unitWeight: '0.04',
      customsValuePerUnit: 25
    }
  }
]

The error from the API is CanadaPostError: /rs/8953013/ncshipment: cvc-model-group 3: in element {http://www.canadapost.ca/ws/ncshipment-v4}customs of type {http://www.canadapost.ca/ws/ncshipment-v4}CustomsType, duplicate element {http://www.canadapost.ca/ws/ncshipment-v4}sku-list

If I limit that skulist to one item everything is fine.

[
  {
    item: {
      customsNumberOfUnits: 3,
      customsDescription: 'test1,
      sku: '18828',
      unitWeight: '0.14',
      customsValuePerUnit: 35
    }
  }
]

I'm failing to understand why they say skulist is duplicated when it's not. And I'm failing to understand what the json representation should look like.

ssshake commented 2 years ago

To clear it up a bit this is what my customs object looks like

> orders.deliverySpec.customs
{
  currency: 'CAD',
  reasonForExport: 'SOG',
  skuList: [ { item: [Object] }, { item: [Object] }, { item: [Object] } ]
}
ssshake commented 2 years ago

I added some logging in _request of canadapost.js and I see that the json I'm supplying is being converted to this xml and there certainly is duplicate sku lists so the response from the API seems accurate.

Can you tell me how to construct the json so that the three items are in one sku-list instead of each one being in it's own sku list?


  '    <customs>\n' +
  '      <currency>CAD</currency>\n' +
  '      <reason-for-export>SOG</reason-for-export>\n' +
  '      <sku-list>\n' +
  '        <item>\n' +
  '          <customs-number-of-units>3</customs-number-of-units>\n' +
  '          <customs-description>Test1</customs-description>\n' +
  '          <sku>18828</sku>\n' +
  '          <unit-weight>0.14</unit-weight>\n' +
  '          <customs-value-per-unit>35</customs-value-per-unit>\n' +
  '        </item>\n' +
  '      </sku-list>\n' +
  '      <sku-list>\n' +
  '        <item>\n' +
  '          <customs-number-of-units>1</customs-number-of-units>\n' +
  '          <customs-description>Test2</customs-description>\n' +
  '          <sku>19045</sku>\n' +
  '          <unit-weight>0.01</unit-weight>\n' +
  '          <customs-value-per-unit>25</customs-value-per-unit>\n' +
  '        </item>\n' +
  '      </sku-list>\n' +
  '      <sku-list>\n' +
  '        <item>\n' +
  '          <customs-number-of-units>1</customs-number-of-units>\n' +
  '          <customs-description>Test3</customs-description>\n' +
  '          <sku>23959</sku>\n' +
  '          <unit-weight>0.04</unit-weight>\n' +
  '          <customs-value-per-unit>25</customs-value-per-unit>\n' +
  '        </item>\n' +
  '      </sku-list>\n' +
  '    </customs>\n' +
ssshake commented 2 years ago

I've narrowed where this conversion issue is happening to here, with the output of xml2js builder buildObject.

const builder = new xml2js.Builder();
body = builder.buildObject(CanadaPostClient.normalizeObject(params, true));

The input is the the format I've provided above, the output produces the multiple sku lists.

What I've since learned is if I just pass in the sku-list itself to buildObject() it returns one sku-list with all items in it.


Welcome to Node.js v14.15.4.
Type ".help" for more information.
> const xml2js = require('xml2js');
undefined
> const builder = new xml2js.Builder();
undefined
> let temp = builder.buildObject({'sku-list': [ { item: {name: "hi"} }, { item: {name: "bye"} }, { item: {name: "sigh"} } ] })
undefined
> console.log(temp)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sku-list>
  <item>
    <name>hi</name>
  </item>
  <item>
    <name>bye</name>
  </item>
  <item>
    <name>sigh</name>
  </item>
</sku-list>

However once I start adding some siblings to the sku-list object that's when the issue introduced itself. In this example I add currency and reason-for-export, doing this results in one sku-list for each item. Because there are multiple sku-lists the canada post api is rejecting the request.


temp = builder.buildObject({currency: 'CAD', 'reason-for-export': 'SOG', 'sku-list': [ { item: {name: "hi"} }, { item: {name: "bye"} }, { item: {name: "sigh"} } ] })
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n' +
  '<root>\n' +
  '  <currency>CAD</currency>\n' +
  '  <reason-for-export>SOG</reason-for-export>\n' +
  '  <sku-list>\n' +
  '    <item>\n' +
  '      <name>hi</name>\n' +
  '    </item>\n' +
  '  </sku-list>\n' +
  '  <sku-list>\n' +
  '    <item>\n' +
  '      <name>bye</name>\n' +
  '    </item>\n' +
  '  </sku-list>\n' +
  '  <sku-list>\n' +
  '    <item>\n' +
  '      <name>sigh</name>\n' +
  '    </item>\n' +
  '  </sku-list>\n' +
  '</root>'
ssshake commented 2 years ago

OK after doing this investigation and reading some things online I've learned that my json structure was not correct.

To make this XML

<sku-list>
  <item>1</item>
  <item>2</item>
  <item>3</item>
</sku-list>

You need to provide this JSON

{ 
    'sku-list': { 
        item: [ 1,2,3 ] 
    } 
}

The odd/unfortunate thing about it is the original structure I was using is valid some of the time (2 of the three scenarios exhibited). This makes it a confusing thing to try to figure out.

Perhaps someone else can learn from my reporting.