SDK writing idea of calling mobile phone charge recharge API



By dividing the data returned in the SDK method into two parts: normal return data and error return data, the caller can handle the interface call error more easily.
The process of SDK calling the third-party service interface is divided into three parts: data preparation, HTTP request and result processing to reuse the code.


Take the compilation of aggregated data mobile phone charging SDK as an example,Official document of mobile phone charging API

# encoding=utf-8
from urlparse import urljoin
from hashlib import md5
from datetime import datetime
from random import sample
import requests
import pytz

class APIError(object):
    def __init__(self, code, msg):
        self.code = code
        self.message = msg

class JuhePhoneChargeApi(object):

    API_PREFIX = ''
    def __init__(self, openid, key, api_entry=None):
        self._key = key
        self._openid = openid
        self._api_entry = api_entry or self.API_PREFIX

    def telcheck(self, phoneno, cardnum):
        params = {'phoneno': phoneno, 'cardnum': cardnum}
        return self._get(path='telcheck', params=params)

    def telquery(self, phoneno, cardnum):
        params = {
            'phoneno': phoneno,
            'cardnum': cardnum,
        return self._get(path='telquery', params=params)

    def onlineorder(self, phoneno, cardnum, orderid):
        params = {
            'phoneno': phoneno,
            'cardnum': cardnum,
            'orderid': orderid or self.create_orderid(),
        params.update({'sign': self._create_sign(**params)})

        return self._get(path='onlineorder', params=params)

    def ordersta(self, orderid):
        params = {'orderid': orderid}
        return self._get(path='orderid', params=params)

    def create_orderid(self):
        return ''.join((

    def _process_response(self, rsp):
        Do the same processing for the data returned by the third-party interface,
        :param rsp:
        : Return: normal return value of the interface, wrong object
        if rsp.status_code != 200:
            return None, APIError(rsp.status_code, 'http error')
            content = rsp.json()
            return None, APIError(99999, 'invalid rsp')
        if 'error_code' in content and content['error_code'] != 0:
            return None, APIError(content['error_code'], content['reason'])

        return content['result'], None

    def _get(self, path, params=None):
        if not params:
            params = {}

        headers = {'Content-type': 'application/json'}
        params.update({'key': self._key})

        rsp = requests.get(urljoin(self._api_entry, path), params=params, headers=headers)
        return self._process_response(rsp)

    def _create_sign(self, phoneno, cardnum, orderid=None):
        obj_str = ''.join((
            orderid or self.create_orderid()))

        m = md5()
        return m.hexdigest()

    def _create_code(self, number_len):
        ELEMENT = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
        return ''.join(sample(ELEMENT, number_len))