wcf - Royal Mail Shipping API C# -


i'm trying integrate royal mail soap api .net code. have followed advice here consume wcf royal mail api in c# console application , here c# wcf namespaces move header & use ns prefix.

i have created custom iclientmessageformatter able attach namespaces beginning of soap envelope, still can't seem work. keep receiving following error. not establish trust relationship ssl/tls secure channel authority 'api.royalmail.com', , inner exception is: remote certificate invalid according validation procedure.

i using visual studio 13 , .net version 3.5, i've tried numerous other versions no further progress. when debug can see normal message been passed royalmailmessage when runs onwritestartenvelope can't see changes _message object. i've created trace see soap request been sent.

i have sent xml request royal mail support validate reason failing due namespaces not been declared in envelope , missing prefixes.

royalmail.cs

internal class royalmail {     private readonly x509certificate2 _certificate;     private readonly config _config;      public royalmail()     {         _config = new config();         _config.loadconfig();          // load ssl certificate (check file exists)         var certificatepath = (path.getdirectoryname(system.reflection.assembly.getexecutingassembly().location) + @"\" + _config.getcertificatename());          if (!file.exists(certificatepath))         {             throw new exception(@"the royal mail certificate missing plugins directory. please place file " + _config.getcertificatename() + " in same directory plugin dll file & relaunch filemaker.\n\n" + certificatepath);         }          _certificate = new x509certificate2(certificatepath, _config.getcertificatepassword());          // check it's in certificate          var store = new x509store(storename.my, storelocation.currentuser);         store.open(openflags.readwrite);         if (!store.certificates.contains(_certificate))         {             store.add(_certificate);             messagebox.show("certificate installed computer trust store");         }         store.close();      }       /*      *       * soap service & methods      *       */      private shippingapiporttypeclient getproxy()     {          var mybinding = new basichttpbinding(basichttpsecuritymode.transport)         {             maxreceivedmessagesize = 2147483647         };         mybinding.security.transport.clientcredentialtype = httpclientcredentialtype.certificate;         var uri = new uri(_config.getendpointurl());         var endpointidentity = endpointidentity.creatednsidentity("api.royalmail.com");          var shippingclient = new shippingapiporttypeclient(mybinding, new endpointaddress(uri, endpointidentity, new addressheadercollection()));         if (shippingclient.clientcredentials != null)             shippingclient.clientcredentials.clientcertificate.certificate = _certificate;          foreach (var od in shippingclient.endpoint.contract.operations)         {            od.behaviors.add(new royalmailiendpointbehavior());         }          return shippingclient;     }      private securityheadertype getsecurityheadertype()     {         var securityheader = new securityheadertype();          var creationdate = datetime.utcnow.tostring("yyyy-mm-ddthh:mm:ssz");          var nonce = (new random().next(0, int.maxvalue)).tostring();          var hashedpassword = getsha1(_config.getpassword());          var concatednateddigestinput = string.concat(nonce, creationdate, encoding.default.getstring(hashedpassword));         var digest = getsha1(concatednateddigestinput);          var passworddigest = convert.tobase64string(digest);          var encodednonce = convert.tobase64string(encoding.default.getbytes(nonce));          var doc = new xmldocument();         using (var writer = doc.createnavigator().appendchild())         {             writer.writestartdocument();             writer.writestartelement("wsse", "security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");             writer.writestartelement("wsse", "usernametoken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");             writer.writeelementstring("wsse", "username", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", _config.getusername());             writer.writeelementstring("wsse", "password", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", passworddigest);             writer.writeelementstring("wsse", "nonce", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", encodednonce);             writer.writeelementstring("wsse", "created", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", creationdate);             writer.writeendelement();             writer.writeendelement();             writer.writeenddocument();             writer.flush();         }          if (doc.documentelement != null)         {             doc.documentelement.removeallattributes();              var headers = doc.documentelement.childnodes.cast<xmlelement>().toarray();              securityheader.any = headers;         }          return securityheader;     }      private integrationheader getintegrationheader()     {          var header = new integrationheader();          var created = datetime.now;         var createdat = datetime.utcnow.tostring("yyyy-mm-ddthh:mm:ssz");          header.datetime = created;         header.version = int.parse(_config.getversion());         header.datetimespecified = true;         header.versionspecified = true;          var idstructure = new identificationstructure {applicationid = _config.getapplicationid()};          var nonce = new random().next(0, int.maxvalue).tostring();          idstructure.transactionid = calculatemd5hash(nonce + createdat);          header.identification = idstructure;          return header;     }      private static byte[] getsha1(string input)     {         return sha1managed.create().computehash(encoding.default.getbytes(input));     }      public string calculatemd5hash(string input)     {         // step 1, calculate md5 hash input         var md5 = md5.create();         var inputbytes = encoding.ascii.getbytes(input);         var hash = md5.computehash(inputbytes);          // step 2, convert byte array hex string         var sb = new stringbuilder();         foreach (var t in hash)         {             sb.append(t.tostring("x2"));         }         return sb.tostring();     }      /*      * check response footer errors & warnings service      * if error return true can inform file maker of error      * ignore warnings      *       */     private static void checkerrorsandwarnings(integrationfooter integrationfooter)     {         if (integrationfooter != null)         {             if (integrationfooter.errors != null && integrationfooter.errors.length > 0)             {                 var errors = integrationfooter.errors;                 foreach (var error in errors)                 {                     messagebox.show("royal mail request error: " + error.errordescription + ". " + error.errorresolution, "royal mail request error", messageboxbuttons.ok, messageboxicon.error, messageboxdefaultbutton.button1);                 }                 if (errors.length > 0)                 {                     return;                 }             }              if (integrationfooter.warnings != null && integrationfooter.warnings.length > 0)             {                 var warnings = integrationfooter.warnings;                 foreach (var warning in warnings)                 {                     messagebox.show("royal mail request warning: " + warning.warningdescription + ". " + warning.warningresolution, "royal mail request warning", messageboxbuttons.ok, messageboxicon.warning, messageboxdefaultbutton.button1);                 }             }         }     }      /*      * show message box soap error if receive fault code service      *      */     private static void showsoapexception(faultexception e)     {         var message = e.createmessagefault();         var errordetail = message.getdetail<xmlelement>();         var errordetails = errordetail.childnodes;         var fullerrordetails = "";          (var = 0; < errordetails.count; i++)         {             var xmlnode = errordetails.item(i);             if (xmlnode != null)                 fullerrordetails += xmlnode.name + ": " + xmlnode.innertext + "\n";         }          messagebox.show("an error occured royal mail service: " + message.reason + "\n\n" + fullerrordetails, "royal mail soap error", messageboxbuttons.ok, messageboxicon.error, messageboxdefaultbutton.button1);     }      public createshipmentresponse sendcreateshipmentrequest(createshipmentform shippingform)     {         var client = getproxy();          try         {             var request = new createshipmentrequest {integrationheader = getintegrationheader()};             var shipment = new requestedshipment();              // shipment type code (delivery or return)             var shipmenttype = new referencedatatype {code = shippingform.shippingtype};             shipment.shipmenttype = shipmenttype;              // service type code (1:24h 1st class, 2: 48h 2nd class, d: special delivery guaranteed, h: hm forces (bfpo), i: international, r: tracked returns, t: tracked domestic)             var servicetype = new referencedatatype {code = shippingform.servicetype};             shipment.servicetype = servicetype;              // service offering (see royal mail service offering type codes. many list)             var serviceofferingtypecontainer = new serviceofferingtype();             var serviceoffering = new referencedatatype {code = shippingform.serviceoffering};             serviceofferingtypecontainer.serviceofferingcode = serviceoffering;             shipment.serviceoffering = serviceofferingtypecontainer;              // service format code             var serviceformattypecontainer = new serviceformattype();             var serviceformat = new referencedatatype {code = shippingform.serviceformat};             serviceformattypecontainer.serviceformatcode = serviceformat;             shipment.serviceformat = serviceformattypecontainer;              // shipping date             shipment.shippingdate = shippingform.shippingdate;             shipment.shippingdatespecified = true;              shipment.signature = true;              shipment.signaturespecified = true;              // sender reference number (e.g. invoice number or ra number)             shipment.senderreference = shippingform.invoicenumber;              /*              * service enhancements             */              var serviceenhancements = new list<serviceenhancementtype>();             shipment.serviceenhancements = serviceenhancements.toarray();               /*              * recipient contact details             */              var recipientcontact = new contact();             recipientcontact.complementaryname = shippingform.company;             recipientcontact.name = shippingform.name;              if(!shippingform.emailaddress.equals("")) {                 var email = new digitaladdress {electronicaddress = shippingform.emailaddress};                 recipientcontact.electronicaddress = email;             }              if(!shippingform.mobilenumber.equals("")) {                 var tel = new telephonenumber();                 var phoneregex = new regex(@"[^\d]");                 tel.telephonenumber1 = phoneregex.replace(shippingform.mobilenumber, "");                 tel.countrycode = "00" + shippingform.countrydiallingcode;                 recipientcontact.telephonenumber = tel;             }              shipment.recipientcontact = recipientcontact;              /*              * recipient address              *              */             var recipientaddress = new address             {                 addressline1 = shippingform.addressline1,                 addressline2 = shippingform.addressline2,                 addressline3 = shippingform.addressline3,                 addressline4 = shippingform.county,                 posttown = shippingform.town             };             var country = new countrytype();             var countrycode = new referencedatatype { code = shippingform.countrycode };             country.countrycode = countrycode;             recipientaddress.country = country;             recipientaddress.postcode = shippingform.postcode;              recipientaddress.stateorprovince = new stateorprovincetype {stateorprovincecode = new referencedatatype()};              shipment.recipientaddress = recipientaddress;              // shipment items              var items = new list<item> ();              foreach(var in shippingform.items) {                 var item = new item                 {                     numberofitems = i.products.count.tostring(),                     weight = new dimension                     {                         value = i.weight*1000,                         unitofmeasure = new unitofmeasuretype {unitofmeasurecode = new referencedatatype {code = "g"}}                     }                 };                  items.add(item);             }              if (shippingform.servicetype.contains("international"))             {                 var internationalinfo = new internationalinfo                 {                     shipperexportervatno = _config.getvatnumber(),                     documentsonly = false,                     shipmentdescription = "invoice number: " + shippingform.invoicenumber,                     invoicedate = datetime.now,                     termsofdelivery = "exw",                     invoicedatespecified = true,                     purchaseorderref = shippingform.invoicenumber                 };                  var parcels = new list<parcel>();                 foreach (var in shippingform.items)                 {                     var parcel = new parcel                     {                         weight = new dimension                         {                             value = i.weight*1000,                             unitofmeasure = new unitofmeasuretype                             {                                 unitofmeasurecode = new referencedatatype {code = "g"}                             }                         },                         invoicenumber = shippingform.invoicenumber,                         purposeofshipment = new referencedatatype {code = "31"}                     };                       var contents = new list<contentdetail>();                     foreach (var product in i.products)                     {                         var contentdetail = new contentdetail                         {                             articlereference = product.sku,                             countryofmanufacture = new countrytype                             {                                 countrycode = new referencedatatype                                 {                                     code = product.countryofmanufacture                                 }                             },                             currencycode = new referencedatatype {code = product.currencycode},                             description = product.name,                             unitquantity = product.qty.tostring(),                             unitvalue = product.price,                             unitweight = new dimension                             {                                 value = convert.tosingle(product.weight*1000),                                 unitofmeasure = new unitofmeasuretype                                 {                                     unitofmeasurecode = new referencedatatype {code = "g"}                                 }                             }                         };                          contents.add(contentdetail);                     }                      //parcel.contentdetails = contents.toarray();                      parcels.add(parcel);                 }                  internationalinfo.parcels = parcels.toarray();                  shipment.internationalinfo = internationalinfo;             }             else             {                 shipment.items = items.toarray();             }              request.requestedshipment = shipment;              var response = client.createshipment(getsecurityheadertype(), request);              // show errors , warnings             checkerrorsandwarnings(response.integrationfooter);              return response;          }         catch (timeoutexception e)         {             client.abort();             messagebox.show("request timed out: " + e.message, "request timeout", messageboxbuttons.ok, messageboxicon.error, messageboxdefaultbutton.button1);         }         catch (faultexception e)         {             client.abort();             showsoapexception(e);         }         catch (communicationexception e)         {             client.abort();             messagebox.show("a communication error has occurred: " + e.message + " - " + e.stacktrace, "communication error", messageboxbuttons.ok, messageboxicon.error, messageboxdefaultbutton.button1);         }         catch (exception e)         {             client.abort();             messagebox.show(e.message, "royal mail error", messageboxbuttons.ok, messageboxicon.error, messageboxdefaultbutton.button1);         }          return null;     } } 

royalmailmessage.cs

class royalmailmessage : message {     public message _message;      public royalmailmessage(message message)     {         _message = message;     }      public override messageheaders headers     {                 {             return _message.headers;         }     }     public override messageproperties properties     {                 {             return _message.properties;         }     }      public override messageversion version     {                 {             return _message.version;         }     }      protected override void onwritestartbody(xmldictionarywriter writer)     {         writer.writestartelement("body", "http://schemas.xmlsoap.org/soap/envelope/");     }      protected override void onwritebodycontents(xmldictionarywriter writer)     {         _message.writebodycontents(writer);     }      protected override void onwritestartenvelope(xmldictionarywriter writer)     {         writer.writestartelement("soapenv", "envelope", "http://schemas.xmlsoap.org/soap/envelope/");         writer.writeattributestring("xmlns", "v2", null, "http://www.royalmailgroup.com/api/ship/v2");         writer.writeattributestring("xmlns", "v1", null, "http://www.royalmailgroup.com/integration/core/v1");         writer.writeattributestring("xmlns", "xsi", null, "http://www.w3.org/2001/xmlschema-instance");         writer.writeattributestring("xmlns", "xsd", null, "http://www.w3.org/2001/xmlschema");     } } 

royalmailmessageformatter.cs

public class royalmailmessageformatter : iclientmessageformatter {     private readonly iclientmessageformatter _formatter;      public royalmailmessageformatter(iclientmessageformatter formatter)     {         _formatter = formatter;     }      public object deserializereply(message message, object[] parameters)     {         return _formatter.deserializereply(message, parameters);     }      public message serializerequest(messageversion messageversion, object[] parameters)     {         var message = _formatter.serializerequest(messageversion, parameters);         return new royalmailmessage(message);     } } 

royalmailiendpointbehavior.cs

internal class royalmailiendpointbehavior : ioperationbehavior {     public void applyclientbehavior(operationdescription description, clientoperation proxy)     {         proxy.formatter = new royalmailmessageformatter(proxy.formatter);     }      public void addbindingparameters(operationdescription operationdescription, bindingparametercollection bindingparameters)     {      }      public void applydispatchbehavior(operationdescription operationdescription, dispatchoperation dispatchoperation)     {      }      public void validate(operationdescription operationdescription)     {      }  } 

the error getting because of certificate.

having said that, think should use v2 of api although still awful, there examples out there , don't need use cert.

rick strahl has changed namespaces in v2 version, see here https://weblog.west-wind.com/posts/2016/apr/02/custom-message-formatting-in-wcf-to-add-all-namespaces-to-the-soap-envelope .


Comments

Popular posts from this blog

php - Wordpress website dashboard page or post editor content is not showing but front end data is showing properly -

How to get the ip address of VM and use it to configure SSH connection dynamically in Ansible -

javascript - Get parameter of GET request -