'Exhanges a code for OAuth2Credentials.
Args:
code: string or dict, either the code as a string, or a dictionary
of the query parameters to the redirect_uri, which contains
the code.
http: httplib2.Http, optional http instance to use to do the fetch
Returns:
An OAuth2Credentials object that can be used to authorize requests.
Raises:
FlowExchangeError if a problem occured exchanging the code for a
refresh_token.'

@util.positional(2)
def step2_exchange(self, code, http=None):

    if (not (isinstance(code, str) or isinstance(code, unicode))):
        if ('code' not in code):
            if ('error' in code):
                error_msg = code['error']
            else:
                error_msg = 'No    code    was    supplied    in    the    query    parameters.'
            raise FlowExchangeError(error_msg)
        else:
            code = code['code']
    body = urllib.urlencode({'grant_type': 'authorization_code', 'client_id': self.client_id, 'client_secret': self.client_secret, 'code': code, 'redirect_uri': self.redirect_uri, 'scope': self.scope})
    headers = {'content-type': 'application/x-www-form-urlencoded'}
    if (self.user_agent is not None):
        headers['user-agent'] = self.user_agent
    if (http is None):
        http = httplib2.Http()
    (resp, content) = http.request(self.token_uri, method='POST', body=body, headers=headers)
    d = _parse_exchange_token_response(content)
    if ((resp.status == 200) and ('access_token' in d)):
        access_token = d['access_token']
        refresh_token = d.get('refresh_token', None)
        token_expiry = None
        if ('expires_in' in d):
            token_expiry = (datetime.datetime.utcnow() + datetime.timedelta(seconds=int(d['expires_in'])))
        if ('id_token' in d):
            d['id_token'] = _extract_id_token(d['id_token'])
        logger.info(('Successfully    retrieved    access    token:    %s' % content))
        return OAuth2Credentials(access_token, self.client_id, self.client_secret, refresh_token, token_expiry, self.token_uri, self.user_agent, id_token=d.get('id_token', None))
    else:
        logger.info(('Failed    to    retrieve    access    token:    %s' % content))
        if ('error' in d):
            error_msg = unicode(d['error'])
        else:
            error_msg = ('Invalid    response:    %s.' % str(resp.status))
        raise FlowExchangeError(error_msg)
