/dhl-bcs

client for DHL Business Customer Shipping API version 2

Primary LanguageRubyMIT LicenseMIT

Dhl::Bcs

This is a client for the DHL Business Customer Shipping (BCS) API version 2.0. It is inspired by the DHL intraship gem which implements API version 1.0 which is expired. The Dhl::Bcs gem uses Savon 2 to communicate via SOAP with the DHL API. The DHL BCS API is just for standard parcels. If you are looking for shipping of express parcels this gem is not for you.

Installation

Add this line to your application's Gemfile:

gem 'dhl-bcs'

And then execute:

$ bundle

Or install it yourself as:

$ gem install dhl-bcs

Usage

Initialize a new API client using

client = Dhl::Bcs.client(config, options)

Config is the following hash:

config = {
  api_user: 'The user for API BasicAuth', #mandatory
  api_pwd: 'The password for API BasicAuth', #mandatory
  user: 'your BCS user name', #mandatory
  signature: 'Your BCS user password', #mandatory
  ekp: 'Your DHL EKP (first part of your DHL Account number)', #mandatory
  participation_number: 'Your DHL participation_number (last two characters of your DHL Account number)' #mandatory
}

Options is an optional parameter and can contain the following parameters:

options = {
 test: true, # If test is set, all API calls go against the DHL test system (defaults to false)
 log: false # If log is set, you get all logging (with request and response XML) to your standard logger. (defaults to true)
}

Where do I get all these numbers?

If you are confused about all the number and credential stuff here is a short explanation.

DHL uses a customer integration gateway (cig) for its services. You have to register your app first at the developer portal of dhl, define an app_id and get a token for that. api_user is your app_id and api_pwd is the token you get. This is basically needed to communicate with the DHL services.

To identify as a BCS user you have to give your credentials of the BCS website as user and signature.

The billing works with a number (Abrechnungsnummer) with 14 chars that consists of three parts. The first 10 digits are your EKP (Einheitliche Kunden- und Produktnummer) that you get from your DHL contract.

The next 2 digits are product dependent (Verfahren), so you don't have to specify it, because they are known if you specify a product at the shipment.

The last 2 chars, the participation_number (Teilnahme-Nummer) can be digits or uppercase characters. This is contract dependent and used to specify billing conditions.

Create shipments

To create a shipment at DHL you need a sender_address, a receiver_address, and informations about the parcel.

shipment = Dhl::Bcs.build_shipment(
  shipper: {
    name: 'Christoph Wagner',
    company: 'webit! Gesellschaft für neue Medien mbH',
    street_name: 'Schandauer Straße',
    street_number: '34',
    zip: '01309',
    city: 'Dresden',
    country_code: 'DE',
    email: 'wagner@webit.de'
  },
  receiver: {
    name: 'Jane Doe',
    street_name: 'Willy-Brandt-Straße',
    street_number: '1',
    zip: '10557',
    city: 'Berlin',
    country_code: 'DE',
    email: 'jane.doe@example.com'
  },
  weight: 3.5,
  length: 10,
  width: 20,
  height: 30,
  shipment_date: Date.new(2016, 7, 13)
)

client.create_shipment_order(shipment)

You will get a result that looks like this:

[
  {
    status: { status_code: '0', status_text: 'ok', status_message: 'Der Webservice wurde ohne Fehler ausgeführt.' },
    shipment_number: '22222222201019582121',
    label_url: 'https://cig.dhl.de/gkvlabel/SANDBOX/dhl-vls/gw/shpmntws/printShipment?token=JD7HKktuvugIFEkhSvCfbEz4J8Ah0dkcVuw4PzBGRyRnW%2FwEPAwfytLtb31e7gMDsSX32%2BEB5exp8nNPs%2FhJSQ%3D%3D',
  }
]

This is an Array of Hashes, cause it is possible to send up to 30 parcels at the same time, with the API. Say you want to send 3 parcels to the same address you can also do something like that:

shipper = Dhl::Bcs.build_shipper(
  name: 'Christoph Wagner',
  company: 'webit! Gesellschaft für neue Medien mbH',
  street_name: 'Schandauer Straße',
  street_number: '34',
  zip: '01309',
  city: 'Dresden',
  country_code: 'DE',
  email: 'wagner@webit.de'
)

receiver = Dhl::Bcs.build_receiver(
  name: 'Jane Doe',
  street_name: 'Willy-Brandt-Straße',
  street_number: '1',
  zip: '10557',
  city: 'Berlin',
  country_code: 'DE',
  email: 'jane.doe@example.com'
)

shipment1 = Dhl::Bcs.build_shipment(shipper: shipper, receiver: receiver, weight: 3)
shipment2 = Dhl::Bcs.build_shipment(shipper: shipper, receiver: receiver, weight: 3.5)
shipment3 = Dhl::Bcs.build_shipment(shipper: shipper, receiver: receiver, weight: 4)

client.create_shipment_order(shipment1, shipment2, shipment3)

International Shipments

In order to send parcels outside of the EU, one should provide information about the content of the shipment.
Dhl offers cn23 document, which is data for the Customs as this kind of shipment is considered Export of goods. As an output one gets, in addition to the label, a url for the document in an A4-format ready to be printed.

The way to implement that is identical of shipper's and receiver's ones.

export_document = {
  invoice_number = 'ABCDEF...',
  export_type = 'Document',  #  could be one of these ['RETURN_OF_GOODS','PRESENT','COMMERCIAL_SAMPLE','DOCUMENT','OTHER']
  export_type_description = 'some desc', # should be set if `export_type` was set to 'OTHER'
  terms_of_trade = 'DDP', # could be one of these ['DDP','DXV','DDU','DDX']
  place_of_commital= 'Bern',
  permit_number = 1232135,
  attestation_number = 1234345,
  with_electronic_export_notification = true, # true|false
  export_doc_positions: [
    {
      description: 'content1',
      country_code_origing: 'CN',
      customs_tariff_number: '1234567',
      ammount: 1,
      net_weight_in_kg: 0.2,
      customs_value: 25.00
    },
    {
      description: 'content2',
      country_code_origing: 'DE',
      customs_tariff_number: '00222011',
      ammount: 1,
      net_weight_in_kg: 1.2,
      customs_value: 112.00
    }
  ]
}

shipment = Dhl::Bcs.build_shipment(export_document: export_document, shipper: shipper, receiver: receiver)

and then one gets a result like this:

[
  {
    status: { status_code: '0', status_text: 'ok', status_message: 'Der Webservice wurde ohne Fehler ausgeführt.' },
    shipment_number: '22222222201019582121',
    label_url: 'https://cig.dhl.de/gkvlabel/SANDBOX/dhl-vls/gw/shpmntws/printShipment?token=JD7HKktuvugIFEkhSvCfbEz4J8Ah0dkcVuw4PzBGRyRnW%2FwEPAwfytLtb31e7gMDsSX32%2BEB5exp8nNPs%2FhJSQ%3D%3D',
    export_label_url: 'https://cig.dhl.de/gkvlabel/SANDBOX/dhl-vls/gw/shpmntws/printShipment?token=Vfov%2BMinVhMH6nQVfvSCmNUSRNnaQNHKPaiLiWtXsqm%2BENCM6wnStB2C44rl6BEmSxbrPeaTQwBhoHBr802FnuftGVJ9uVM0C0ztLpxNfyc%3D',
  }
]

Validate shipments

client.validate_shipment(shipment1, shipment2, shipment3)

Update shipment

You can update a shipment at DHL. It is the same like deleting it and creating a new one just with one request. So you will get a new shipping number for it and so on. To update a shipment you need the shipment number of the old one and give a complete new shipment that is created instead. This works for one shipment at a time.

client.update_shipment_order('22222222901010000944', shipment)

Other methods

The methods delete_shipment_order, get_label, get_export_doc and do_manifest works technically the same. They took one or many (up to 30) shipment numbers and do something with these shipments at DHL.

To delete a shipment you can use:

client.delete_shipment_order('22222222901010000944')

As result you will get one Hash like:

{
  '22222222901010000944' => {
    status: { status_code: '0', status_text: 'ok', status_message: nil }
  }
}

Services

There is a basic support to add Services to a shipment in this gem.

shipment.services << Dhl::Bcs.build_service(name: 'IndividualSenderRequirement', attributes: { active: '1', details: 'Test' })

A service has a name and attributes. Sometimes a service has children, for example the 'IdentCheck'-Service.

shipment.services << Dhl::Bcs.build_service(name: 'IdentCheck', attributes: { active: '1' }, children: { 'Ident' => { surname: 'Doe', given_name: 'Jon Doe', date_of_birth: '1980-12-24', minimum_age: '18' } })

Check out the DHL developer documentation to configure the services you need.

Get API version

client.get_version

You don't need a shipment for that.

Logging

If you need the last made request and its response from the client you can use:

client.last_log

This works even if you used the option log: false at the client. This option controlls just the output in the log file or console.

Everything else

Have a deeper look at the code of this gem and find out how things work. You can help to implement missing things or extend this documentation.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/webit-de/dhl-bcs. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.