• Sathik
  • NEWBIE
  • 5 Points
  • Member since 2014
  • Software Engineer


  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 3
    Questions
  • 10
    Replies
Hi all,
I am getting below error while wsdl2apex conversion
Error:
Failed to Unable to find complexType for {http://tempuri.org/}

I have attached my code below:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="RTrakWebService" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://tempuri.org/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
    <wsdl:types>
            <xs:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
                <xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/RTrakWebService">
                    <xs:complexType name="CompositeType">
                        <xs:sequence>
                            <xs:element minOccurs="0" name="BoolValue" type="xs:boolean"/>
                            <xs:element minOccurs="0" name="StringValue" nillable="true" type="xs:string"/>
                        </xs:sequence>
                    </xs:complexType>
                    <xs:element name="CompositeType" nillable="true" type="tns:CompositeType"/>
                </xs:schema>
                <xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/RTrakWebService.Models">
                    <xs:complexType name="ArrayOfOpportunityModel">
                        <xs:sequence>
                            <xs:element minOccurs="0" maxOccurs="unbounded" name="OpportunityModel" nillable="true" type="tns:OpportunityModel"/>
                                </xs:sequence>
                    </xs:complexType>
                    <xs:element name="ArrayOfOpportunityModel" nillable="true" type="tns:ArrayOfOpportunityModel"/>
                    <xs:complexType name="OpportunityModel">
                        <xs:sequence>
                            <xs:element minOccurs="0" name="AccountName" nillable="true" type="xs:string"/>
                            <xs:element minOccurs="0" name="CloseDate" type="xs:dateTime"/>
                            <xs:element minOccurs="0" name="OpportunityName" nillable="true" type="xs:string"/>
                        </xs:sequence>
                    </xs:complexType>
                    <xs:element name="OpportunityModel" nillable="true" type="tns:OpportunityModel"/>
                </xs:schema> 
                <xs:element name="GetData">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element minOccurs="0" name="value" type="xs:int"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="GetDataResponse">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element minOccurs="0" name="GetDataResult" nillable="true" type="xs:string"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="GetDataUsingDataContract">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element minOccurs="0" name="composite" nillable="true" type="q1:CompositeType"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="GetDataUsingDataContractResponse">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element minOccurs="0" name="GetDataUsingDataContractResult" nillable="true" type="q2:CompositeType"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="GetAllOpportunities">
                    <xs:complexType>
                        <xs:sequence/>
                    </xs:complexType>
                </xs:element>
                <xs:element name="GetAllOpportunitiesResponse">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element minOccurs="0" name="GetAllOpportunitiesResult" nillable="true" type="q3:ArrayOfOpportunityModel"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>



Pls Help me ! 
if any one have solutions,pls let me know
  • October 21, 2014
  • Like
  • 0
I have tried with following code but Am getting following error {"error" : "invalid_grant"}.

if any one have solutions,pls let me know

public class Calender {
    public void Conn() {
        http h = new Http();
        Httprequest req = new HttpRequest();
        HttpResponse res = new HttpResponse();
        req.setEndpoint('https://accounts.google.com/o/oauth2/token');
        req.setMethod('GET');
     
        req.setHeader('ContentType','application/x-www-form-urlencoded');
     
        String Header = '{"alg":"RS256","typ":"JWT"}';
        String Header_Encode = EncodingUtil.base64Encode(blob.valueof(Header));
      
        // system.debug('Response ='+Header_Encode);
     
      
        // https://www.googleapis.com/auth/calender.readonly
        String claim_set = '{"iss":"119812430492-1olmin1inmkav7ek4tbmkk7cmc3htf41@developer.gserviceaccount.com"';
        claim_set += ',"scope":"https://www.googleapis.com/auth/calender.readonly"';
        claim_set += ',"aud":"https://accounts.google.com/o/oauth2/token"';
        claim_set += ',"exp":1328554385';
        claim_set += ',"iat":1328550785}';
       //String repChar = base64(blob.valueof(claim_set));
        // claim_set += ',"exp":"'+datetime.now().addHours(1).getTime()/1000+'"';
       // claim_set += '","iat":"'+datetime.now().getTime()/1000+'"}';
     
       // system.debug('Response ='+claim_set);
       // String UFTSTR = EncodingUtil.urlEncode(claim_set,'UTF-8');EncodingUtil.base64Encode
        String claim_set_Encode = base64(blob.valueof(claim_set));
      
        // system.debug('Response ='+claim_set_Encode);
     
        String Singature_Encode = Header_Encode+'.'+claim_set_Encode;
      
       // system.debug('Singature_Input ='+Singature_Encode);
   
     
        String key = 'MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL0Gla03iExJR6iI\n/b9KRtQoUR8ta8uhxOF3JVaiW7BVU5+3u5iIi52T7SQyxhci9lFZaVJLzdWA83wM\nn99Wvbk640KS0D5YR3F87FCovBbv/rbBJIzxoIrgS5iC1MYP+T1PUrLH2JIe+tCb\nYJ8gDixmKhSXPrqrWbmNoPH8QENlAgMBAAECgYAk0gmJ6k1UftnEjJrRDkjpvsi+\nh/x9eA9/09OkIpA1swlNDV8vgTmhAlWpPXK0wwy0H/SSIU4BDtNfEJ57xMvD2Uol\nqpjeui+5f6RfqA1U5kLzOruRlTYuEfG2XNC5pSuMci+u4J0GEB1uRVxG3YnlEXNV\nOmd78/VBazxY8QNXqQJBAOkoEKQYKCnArmNiic1J9X55sh41rQB/i4CMlrl/C+rY\nch4kk0kEdezRjZS3Ckhte+es317+CI975PpTXwsNnBcCQQDPi6ZOhdjB6Ksg9eDB\n6xKm/BCDrJKFSYUBqRpH7ewUa3rS7V6oQrXcgPeR3HjaBNLCGcUq18UXJlsAraAm\nad3jAkB3Imi2YD2NcA3rbHs7MVJGaMpxkz2t5n4SlkOhzt/5BNXyvv+fLK9Q7ZZp\nacnQTlkkfPm54RXgsw7CNf13eWHLAkEAl71HMwPCzUq5yxhZYg3nDjUeMdb7LP3q\ng6NJ9qrpvqgyHYK0gRp88iFMX9UsemGqYYUL1V352AoP4LgQbeVa9wJABz81deGp\nhBkpuJkooNODSSeLy9cXYCxEZc+o8kQRsuEkuGZda2kXgDvumWjD35en26hbjag3\nMSMW6kFgoa/nfA\u003d\u003d\n';
             
        blob privateKey = EncodingUtil.base64Decode(key);
      // system.debug('Singature_Input ='+privateKey);
       Singature_Encode = Singature_Encode.replaceAll('=','');
        String Singature_Encode_Url = EncodingUtil.urlEncode(Singature_Encode,'UTF-8');
        blob Signature_b =   blob.valueof(Singature_Encode_Url);
     
        String Sinatute_blob = base64(Crypto.sign('RSA-SHA256', Signature_b , privateKey));
            
        String JWT = Singature_Encode+'.'+Sinatute_blob;
     
        JWT = JWT.replaceAll('=','');
     
      // system.debug('JWT ='+JWT);
      
        String grt = 'urn:ietf:params:oauth:grant-type:jwt-bearer';
        req.setBody('grant_type='+grt+'&assertion='+JWT);
        res = h.send(req);
        String Response = res.getBody() +' '+ res.getStatusCode();
        system.debug('Response ='+Response);
      
    }
     private String base64(Blob b) {
        String ret = EncodingUtil.base64Encode(b);
        ret = ret.replaceAll('\\+', '-');
        ret = ret.replaceAll('/', '_');
        ret = ret.replaceAll('=', '');
        return ret;
    } 
   
     
}

Json Private key:"-----BEGIN PRIVATE KEY-----\nMIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL0Gla03iExJR6iI\n/b9KRtQoUR8ta8uhxOF3JVaiW7BVU5+3u5iIi52T7SQyxhci9lFZaVJLzdWA83wM\nn99Wvbk640KS0D5YR3F87FCovBbv/rbBJIzxoIrgS5iC1MYP+T1PUrLH2JIe+tCb\nYJ8gDixmKhSXPrqrWbmNoPH8QENlAgMBAAECgYAk0gmJ6k1UftnEjJrRDkjpvsi+\nh/x9eA9/09OkIpA1swlNDV8vgTmhAlWpPXK0wwy0H/SSIU4BDtNfEJ57xMvD2Uol\nqpjeui+5f6RfqA1U5kLzOruRlTYuEfG2XNC5pSuMci+u4J0GEB1uRVxG3YnlEXNV\nOmd78/VBazxY8QNXqQJBAOkoEKQYKCnArmNiic1J9X55sh41rQB/i4CMlrl/C+rY\nch4kk0kEdezRjZS3Ckhte+es317+CI975PpTXwsNnBcCQQDPi6ZOhdjB6Ksg9eDB\n6xKm/BCDrJKFSYUBqRpH7ewUa3rS7V6oQrXcgPeR3HjaBNLCGcUq18UXJlsAraAm\nad3jAkB3Imi2YD2NcA3rbHs7MVJGaMpxkz2t5n4SlkOhzt/5BNXyvv+fLK9Q7ZZp\nacnQTlkkfPm54RXgsw7CNf13eWHLAkEAl71HMwPCzUq5yxhZYg3nDjUeMdb7LP3q\ng6NJ9qrpvqgyHYK0gRp88iFMX9UsemGqYYUL1V352AoP4LgQbeVa9wJABz81deGp\nhBkpuJkooNODSSeLy9cXYCxEZc+o8kQRsuEkuGZda2kXgDvumWjD35en26hbjag3\nMSMW6kFgoa/nfA\u003d\u003d\n-----END PRIVATE KEY-----\n"
  • August 07, 2014
  • Like
  • 0
Hi all,
I am getting below error while wsdl2apex conversion
Error:
Failed to Unable to find complexType for {http://tempuri.org/}

I have attached my code below:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="RTrakWebService" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://tempuri.org/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
    <wsdl:types>
            <xs:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
                <xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/RTrakWebService">
                    <xs:complexType name="CompositeType">
                        <xs:sequence>
                            <xs:element minOccurs="0" name="BoolValue" type="xs:boolean"/>
                            <xs:element minOccurs="0" name="StringValue" nillable="true" type="xs:string"/>
                        </xs:sequence>
                    </xs:complexType>
                    <xs:element name="CompositeType" nillable="true" type="tns:CompositeType"/>
                </xs:schema>
                <xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/RTrakWebService.Models">
                    <xs:complexType name="ArrayOfOpportunityModel">
                        <xs:sequence>
                            <xs:element minOccurs="0" maxOccurs="unbounded" name="OpportunityModel" nillable="true" type="tns:OpportunityModel"/>
                                </xs:sequence>
                    </xs:complexType>
                    <xs:element name="ArrayOfOpportunityModel" nillable="true" type="tns:ArrayOfOpportunityModel"/>
                    <xs:complexType name="OpportunityModel">
                        <xs:sequence>
                            <xs:element minOccurs="0" name="AccountName" nillable="true" type="xs:string"/>
                            <xs:element minOccurs="0" name="CloseDate" type="xs:dateTime"/>
                            <xs:element minOccurs="0" name="OpportunityName" nillable="true" type="xs:string"/>
                        </xs:sequence>
                    </xs:complexType>
                    <xs:element name="OpportunityModel" nillable="true" type="tns:OpportunityModel"/>
                </xs:schema> 
                <xs:element name="GetData">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element minOccurs="0" name="value" type="xs:int"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="GetDataResponse">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element minOccurs="0" name="GetDataResult" nillable="true" type="xs:string"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="GetDataUsingDataContract">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element minOccurs="0" name="composite" nillable="true" type="q1:CompositeType"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="GetDataUsingDataContractResponse">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element minOccurs="0" name="GetDataUsingDataContractResult" nillable="true" type="q2:CompositeType"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="GetAllOpportunities">
                    <xs:complexType>
                        <xs:sequence/>
                    </xs:complexType>
                </xs:element>
                <xs:element name="GetAllOpportunitiesResponse">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element minOccurs="0" name="GetAllOpportunitiesResult" nillable="true" type="q3:ArrayOfOpportunityModel"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>



Pls Help me ! 
if any one have solutions,pls let me know
  • October 21, 2014
  • Like
  • 0
I have tried with following code but Am getting following error {"error" : "invalid_grant"}.

if any one have solutions,pls let me know

public class Calender {
    public void Conn() {
        http h = new Http();
        Httprequest req = new HttpRequest();
        HttpResponse res = new HttpResponse();
        req.setEndpoint('https://accounts.google.com/o/oauth2/token');
        req.setMethod('GET');
     
        req.setHeader('ContentType','application/x-www-form-urlencoded');
     
        String Header = '{"alg":"RS256","typ":"JWT"}';
        String Header_Encode = EncodingUtil.base64Encode(blob.valueof(Header));
      
        // system.debug('Response ='+Header_Encode);
     
      
        // https://www.googleapis.com/auth/calender.readonly
        String claim_set = '{"iss":"119812430492-1olmin1inmkav7ek4tbmkk7cmc3htf41@developer.gserviceaccount.com"';
        claim_set += ',"scope":"https://www.googleapis.com/auth/calender.readonly"';
        claim_set += ',"aud":"https://accounts.google.com/o/oauth2/token"';
        claim_set += ',"exp":1328554385';
        claim_set += ',"iat":1328550785}';
       //String repChar = base64(blob.valueof(claim_set));
        // claim_set += ',"exp":"'+datetime.now().addHours(1).getTime()/1000+'"';
       // claim_set += '","iat":"'+datetime.now().getTime()/1000+'"}';
     
       // system.debug('Response ='+claim_set);
       // String UFTSTR = EncodingUtil.urlEncode(claim_set,'UTF-8');EncodingUtil.base64Encode
        String claim_set_Encode = base64(blob.valueof(claim_set));
      
        // system.debug('Response ='+claim_set_Encode);
     
        String Singature_Encode = Header_Encode+'.'+claim_set_Encode;
      
       // system.debug('Singature_Input ='+Singature_Encode);
   
     
        String key = 'MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL0Gla03iExJR6iI\n/b9KRtQoUR8ta8uhxOF3JVaiW7BVU5+3u5iIi52T7SQyxhci9lFZaVJLzdWA83wM\nn99Wvbk640KS0D5YR3F87FCovBbv/rbBJIzxoIrgS5iC1MYP+T1PUrLH2JIe+tCb\nYJ8gDixmKhSXPrqrWbmNoPH8QENlAgMBAAECgYAk0gmJ6k1UftnEjJrRDkjpvsi+\nh/x9eA9/09OkIpA1swlNDV8vgTmhAlWpPXK0wwy0H/SSIU4BDtNfEJ57xMvD2Uol\nqpjeui+5f6RfqA1U5kLzOruRlTYuEfG2XNC5pSuMci+u4J0GEB1uRVxG3YnlEXNV\nOmd78/VBazxY8QNXqQJBAOkoEKQYKCnArmNiic1J9X55sh41rQB/i4CMlrl/C+rY\nch4kk0kEdezRjZS3Ckhte+es317+CI975PpTXwsNnBcCQQDPi6ZOhdjB6Ksg9eDB\n6xKm/BCDrJKFSYUBqRpH7ewUa3rS7V6oQrXcgPeR3HjaBNLCGcUq18UXJlsAraAm\nad3jAkB3Imi2YD2NcA3rbHs7MVJGaMpxkz2t5n4SlkOhzt/5BNXyvv+fLK9Q7ZZp\nacnQTlkkfPm54RXgsw7CNf13eWHLAkEAl71HMwPCzUq5yxhZYg3nDjUeMdb7LP3q\ng6NJ9qrpvqgyHYK0gRp88iFMX9UsemGqYYUL1V352AoP4LgQbeVa9wJABz81deGp\nhBkpuJkooNODSSeLy9cXYCxEZc+o8kQRsuEkuGZda2kXgDvumWjD35en26hbjag3\nMSMW6kFgoa/nfA\u003d\u003d\n';
             
        blob privateKey = EncodingUtil.base64Decode(key);
      // system.debug('Singature_Input ='+privateKey);
       Singature_Encode = Singature_Encode.replaceAll('=','');
        String Singature_Encode_Url = EncodingUtil.urlEncode(Singature_Encode,'UTF-8');
        blob Signature_b =   blob.valueof(Singature_Encode_Url);
     
        String Sinatute_blob = base64(Crypto.sign('RSA-SHA256', Signature_b , privateKey));
            
        String JWT = Singature_Encode+'.'+Sinatute_blob;
     
        JWT = JWT.replaceAll('=','');
     
      // system.debug('JWT ='+JWT);
      
        String grt = 'urn:ietf:params:oauth:grant-type:jwt-bearer';
        req.setBody('grant_type='+grt+'&assertion='+JWT);
        res = h.send(req);
        String Response = res.getBody() +' '+ res.getStatusCode();
        system.debug('Response ='+Response);
      
    }
     private String base64(Blob b) {
        String ret = EncodingUtil.base64Encode(b);
        ret = ret.replaceAll('\\+', '-');
        ret = ret.replaceAll('/', '_');
        ret = ret.replaceAll('=', '');
        return ret;
    } 
   
     
}

Json Private key:"-----BEGIN PRIVATE KEY-----\nMIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL0Gla03iExJR6iI\n/b9KRtQoUR8ta8uhxOF3JVaiW7BVU5+3u5iIi52T7SQyxhci9lFZaVJLzdWA83wM\nn99Wvbk640KS0D5YR3F87FCovBbv/rbBJIzxoIrgS5iC1MYP+T1PUrLH2JIe+tCb\nYJ8gDixmKhSXPrqrWbmNoPH8QENlAgMBAAECgYAk0gmJ6k1UftnEjJrRDkjpvsi+\nh/x9eA9/09OkIpA1swlNDV8vgTmhAlWpPXK0wwy0H/SSIU4BDtNfEJ57xMvD2Uol\nqpjeui+5f6RfqA1U5kLzOruRlTYuEfG2XNC5pSuMci+u4J0GEB1uRVxG3YnlEXNV\nOmd78/VBazxY8QNXqQJBAOkoEKQYKCnArmNiic1J9X55sh41rQB/i4CMlrl/C+rY\nch4kk0kEdezRjZS3Ckhte+es317+CI975PpTXwsNnBcCQQDPi6ZOhdjB6Ksg9eDB\n6xKm/BCDrJKFSYUBqRpH7ewUa3rS7V6oQrXcgPeR3HjaBNLCGcUq18UXJlsAraAm\nad3jAkB3Imi2YD2NcA3rbHs7MVJGaMpxkz2t5n4SlkOhzt/5BNXyvv+fLK9Q7ZZp\nacnQTlkkfPm54RXgsw7CNf13eWHLAkEAl71HMwPCzUq5yxhZYg3nDjUeMdb7LP3q\ng6NJ9qrpvqgyHYK0gRp88iFMX9UsemGqYYUL1V352AoP4LgQbeVa9wJABz81deGp\nhBkpuJkooNODSSeLy9cXYCxEZc+o8kQRsuEkuGZda2kXgDvumWjD35en26hbjag3\nMSMW6kFgoa/nfA\u003d\u003d\n-----END PRIVATE KEY-----\n"
  • August 07, 2014
  • Like
  • 0
 I have established a connection between Gmail calendar and salesforce using Google API's and Oouth, we intend on using this to access the calendars of the sales reps in our company to see their schedule and assign tasks accordingly.

Is there a way to access their calendar without giving their respective username and password (even if its the first time) , as this would be impossible when we have close to 500 sales reps. 

I have been trying to connect Salesforce and Google API using server to server application.

 

Intent :- To communicate data between Salesforce and Google Spreadsheet which is hosted in Google Sites and using some Google Forms, Google scripts and triggers to update data.

 

So, for doing this I need a server to server application model from Google as it wouldnt require a consent from user while its communicating data. for doing this I need to create a JWT and pass it to Google to get the token and proceed with the next steps.

 

JWT for Google requires a RSA with SHA256 signing of the msg using the private key that google has provided in the certificate when I created the server to server application in Google.

I havent found this info anywhere till now :(

In salesforce, we have a crypto class in which can sign with RSA SHA1 (or) generate digest with SHA256, I tried generating a digest using SHA256 and signing that digest usng RSA and the private key given by google. Even thats not working.

 

Google isnt accepting my assertion values (JWT) and its returning an invalid Grant message.

 

I have seen that Jeff douglas has posted some information about this here :-http://blog.jeffdouglas.com/2010/07/06/using-rsa-sha1-with-salesforce-crypto-class/

But unfortunately he has mentioned about domain model and asking us to upload a certificate to google, which i dont want to do or which is not my scenario.

 

Also Google requires a UT8 base64 URL encoded value at all places as mentioned in this link :-https://developers.google.com/accounts/docs/OAuth2ServiceAccount#libraries But salesforce has a separate URL encoding and a separate base64encoding method available in the EncodingUtil class.

 

I have a C# dotnet application which is generating the same value and its able to hit Google and get the value properly. But uses the certificate file and gets the privatekey directly. I used openssl to retrieve the privatekey from the .p12 certificate file provided by Google and have pasted it in my code. I am sure there is some problem in the signing part, because when I compare the values generated by my .NET application and Salesforce Apex code, its returning correct values, but when it comes to the signature part, the length is also same for the returned data (signature) from both .NET and SF but Google returns an invalid grant while calling from SF but returns a bearer token when I call it from my .NET application.

 

public class TestRestAPICall
{
    public class JWTClaimSet
    {
       public string iss {get;set;}
       public string scope {get;set;}
       public string aud {get;set;}
       public Long exp {get;set;}
       public Long iat {get;set;}
       //public string prn {get;set;}
    }

//@future (callout=true)
public static void LoginToGoogle()
{
    //Set your username and password here        
    String clientId = '851234545868.apps.googleusercontent.com';

    //Construct HTTP request and response
    Http http = new Http();
    HttpRequest req = new HttpRequest();
    HttpResponse res = new HttpResponse();


    String JWTHeader =  '{"typ":"JWT","alg":"RS256"}';
    //String Base64EncodedJWTHeader = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9'; //To encode later using code

    //Taken from .net application
// Since the information is going to be same, I have encoded it already in .NET and using it here
    String Base64EncodedJWTHeader = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9';
// Salesforce returns time in milliseconds, so we are dividing it by 1000 to set the seconds value instead of milliseconds value
    Long expires_at = math.roundToLong(DateTime.now().addMinutes(40).getTime() / 1000);
    Long issued_at = math.roundToLong(DateTime.now().addSeconds(-2).getTime() / 1000);
    //Long issued_at = 1372276504;
    //Long Expires_at = 1372279804;

    JWTClaimSet JWT = new JWTClaimSet();
    //JWT.prn = username;
    JWT.iss = '851234545868@developer.gserviceaccount.com';
    JWT.scope = 'https://www.googleapis.com/auth/drive.file';
    JWT.aud = 'https://accounts.google.com/o/oauth2/token';
    JWT.iat = issued_at;
    JWT.exp = expires_at;

    String strJWTJSON = JSON.Serialize(JWT);
    system.debug('Unencoded claimset::'+strJWTJSON);


    Blob ClaimsetBlob = Blob.valueOf(strJWTJSON);
    String Base64EncodedClaimset = EncodingUtil.base64Encode(ClaimsetBlob);
    //Base64EncodedClaimset = PerformPostBase64Encode(Base64EncodedClaimset);
    system.debug('Base64 Encoded Claimset::'+Base64EncodedClaimset);

    // constructing the base64 encoded string to sign it
    string Base64EncodedString = Base64EncodedJWTHeader + '.' + Base64EncodedClaimset;


    // Steps to sign the base64Encoded string
    String algorithmName = 'RSA';
    String key = 'MIICXAIBAAKBgQCi16h+5TeQU5Fo0DlR6+YmrzYXZ7DLxz+dBEnB8Hj0gznqlz8p7nQ7I4AV/SfiJQ6JbU16sKS5IW7Hob5ieW1DfwxYZeCSBPbEkt7eASrI8xqGU5RVewaQivY3vO+avgSSUT+ZU243XsDvZJQlkE3e46FhBvFedDQvuk2iEfgdxQIDAQABAoGAFaO882f4c0h3qUsKYvWLNxbPhFq2Js5KiM4aEximqi+KEb+ZmDPk5Dr6eXGTzDyKav7IbgZtTWDA/OxkhWeHelsMB9LqBq50L6hLHTK4hHecPrT3oN4GviUXh5y5Vt479A1TopjLKdt7V4AnAs0HEWJzar/euUa+T9eODPWPFP0CQQDWQeK2cqzWSVHUpkufp7a0Sc2RvfcIpOf8kRFBLnKiFGr7BscLz6qsaG1M8TyUNMrCquwLSNSDMvPjl6sCjgRPAkEAwpFx8+lspjN0yV5M5XHPmnoddTHwV/8QHoccMBBq0ZMFs2m1E/rFhwMHRBiFN6flbze8src7YnOmmtYqsGizqwJAfqoEtYel1ikST3zgSEqGIJ9hAEAlwt56pz27zaT/8AHSHQUstzbV14cE1u/muFddZyhU03cC62078djAKIp80QJAKMMT3ofOrVsmYnGRJpibZ7+hoEXgFm9nTx37N86YsmNc1GOW/iKRc2GdChUhA7H3DT/eForwtAWKp/Gqa97jlQJBAKjKOIKvdYS9fTpCzs1nUHg9rvVartRR5xxwLH57bBincuSJSBGjwd1FInAh2tgiUGPWGPsplShP87wao9+n9VQ=';
    Blob privateKey = EncodingUtil.base64Decode(key);

    Blob input = Blob.valueOf(Base64EncodedString);
    //Blob SHA256InputBlob = Crypto.generateDigest('SHA-256',input);

    Blob Blobsign = Crypto.sign(algorithmName, input , privateKey);


    // The following line is just for debugging and viewing the blob data in signature as string and its not used anywhere
    String signature = EncodingUtil.urlEncode(EncodingUtil.convertToHex(Blobsign),'UTF-8');

    system.debug('Unencoded signature ::'+signature);
    String base64EncodedSignature = EncodingUtil.base64Encode(Blobsign); 
    //base64EncodedSignature = PerformPostBase64Encode(base64EncodedSignature);
    system.debug('Base 64 encoded signature ::'+base64EncodedSignature );

    system.debug('Encoded assertion : ' + Base64EncodedString+'.'+base64EncodedSignature);

    string URLEncodedUTF8GrantType = encodingUtil.urlEncode('urn:ietf:params:oauth:grant-type:jwt-bearer','UTF-8');
    string URLEncodedUTF8Assertion = encodingUtil.urlEncode(Base64EncodedString+'.'+base64EncodedSignature,'UTF-8');        

    system.debug('URLEncodedUTF8GrantType : ' + URLEncodedUTF8GrantType);
    system.debug('URLEncodedUTF8Assertion : ' + URLEncodedUTF8Assertion);

    //Making the call out
    req.setEndpoint('https://accounts.google.com/o/oauth2/token');
    req.setMethod('POST');
    //req.setHeader('Content-Length', '-1');
    req.setHeader('Content-Type','application/x-www-form-urlencoded');
    //req.setHeader('grant_type',URLEncodedUTF8GrantType);
    //req.setHeader('assertion',URLEncodedUTF8Assertion);
    req.setBody('grant_type='+URLEncodedUTF8GrantType+'&assertion='+URLEncodedUTF8Assertion);
    res = http.send(req);
    system.debug('Response : '+res.getBody());
}

 public static String PerformPostBase64Encode(String s)
 {
    s = s.Replace('+', '-');
    s = s.Replace('/', '_');
    s = s.Split('=')[0]; // Remove any trailing '='s
    return s;
 }
}

 

 

I have also posted my problem at stackexchange, it would be great if anyone could help me out :-

 

http://salesforce.stackexchange.com/questions/13301/connect-apex-and-google-api-using-jwt-to-retrieve-oauth-2-0-token