def query_subscription_payment_supported_banks(self): """ query subscription payment supported banks :return: beecloud.entity.BCResult """ query_param = _TmpObject() attach_app_sign(query_param, BCReqType.QUERY, self.bc_app) url = get_rest_root_url() + 'subscription_banks' tmp_resp = http_get(url, self.bc_app.timeout, params=obj_to_dict(query_param)) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.banks = resp_dict.get('banks') bc_result.common_banks = resp_dict.get('common_banks') return bc_result
def refund(self, refund_params): """ refund API, refund fee should not be greater than bill total fee; need_approval is for pre refund, you have to call [audit_pre_refunds] later on to execute real refund if the bill is paid with ali, you have to input your password on the returned url page refer to restful API https://beecloud.cn/doc/?index=rest-api #3 :param refund_params: beecloud.entity.BCRefundReqParams :return: beecloud.entity.BCResult """ if self.bc_app.is_test_mode: return report_not_supported_err('refund') attach_app_sign(refund_params, BCReqType.REFUND, self.bc_app) tmp_resp = http_post(self._bill_refund_url(), refund_params, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.id = resp_dict.get('id') # url will be returned if bill is refunded and channel is in (ALI_APP, ALI_WEB, ALI_QRCODE) bc_result.url = resp_dict.get('url') return bc_result
def verify_card_factors(bc_app, name, id_no, card_no=None, mobile=None): """ verify bank card factors :param bc_app: beecloud.entity.BCApp :param name: id card name :param id_no: id card number :param card_no: bank card number :param mobile: mobile bind to bank card :return: """ tmp_obj = _TmpObject() tmp_obj.name = name tmp_obj.id_no = id_no tmp_obj.card_no = card_no tmp_obj.mobile = mobile attach_app_sign(tmp_obj, BCReqType.PAY, bc_app) tmp_resp = http_post(get_rest_root_url() + "auth", tmp_obj, bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.card_id = resp_dict.get('card_id') bc_result.auth_result = resp_dict.get('auth_result') bc_result.auth_msg = resp_dict.get('auth_msg') return bc_result
def _query_order_by_id(self, order_id, query_type): if query_type == _OrderType.BILL: partial_url = get_random_host() + self._query_bill_url() elif query_type == _OrderType.REFUND: partial_url = get_random_host() + self._query_refund_url() else: return query_params = _TmpObject() attach_app_sign(query_params, BCReqType.QUERY, self.bc_app) url = partial_url + '/' + order_id + '?para=' + obj_to_quote_str(query_params) tmp_resp = http_get(url, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: if query_type == _OrderType.BILL: order_dict = resp_dict.get('pay') bc_result.pay = self._parse_dict_to_obj(order_dict, _OrderType.BILL) else: order_dict = resp_dict.get('refund') bc_result.refund = self._parse_dict_to_obj(order_dict, _OrderType.REFUND) return bc_result
def audit_pre_refunds(self, pre_refund_params): """ batch manage pre refunds; pre refund id list is required; each refund result is kept in result_map refer to restful API https://beecloud.cn/doc/ #4 :param pre_refund_params: beecloud.entity.BCPreRefundReqParams :return: beecloud.entity.BCResult """ if self.bc_app.is_test_mode: return report_not_supported_err('audit_pre_refunds') attach_app_sign(pre_refund_params, BCReqType.PAY, self.bc_app) tmp_resp = http_put(self._bill_refund_url(), pre_refund_params, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: # if agree is true and refund successfully bc_result.result_map = resp_dict.get('result_map') bc_result.url = resp_dict.get('url') return bc_result
def rest_delete_object(bc_app, url, obj_id, **kwargs): """ :param bc_app: used to attach app sign :param url: used to post request :param obj_id: object id :param kwargs: optional key/value pairs arguments :return: beecloud.entity.BCResult """ tmp_obj = _TmpObject() if kwargs: for k, v in kwargs.items(): if v: setattr(tmp_obj, k, v) attach_app_sign(tmp_obj, BCReqType.PAY, bc_app) req_url = url + '/' + obj_id + '?' + compatible_urlencode(tmp_obj) tmp_resp = http_del(req_url, bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.id = resp_dict.get("id") return bc_result
def _query_orders_count(self, query_params, query_type): if query_params.need_detail or query_params.skip or query_params.limit: raise ValueError('need_detail or skip or limit should NOT be used to query order count') if query_type == _OrderType.BILL: if query_params.refund_no: raise ValueError('refund_no should NOT be used to query bills') if query_params.need_approval: raise ValueError('need_approval should NOT be used to query bills') partial_url = get_random_host() + self._query_bills_url() + '/count' elif query_type == _OrderType.REFUND: if query_params.spay_result: raise ValueError('spay_result should NOT be used to query refunds') partial_url = get_random_host() + self._query_refunds_url() + '/count' else: return attach_app_sign(query_params, BCReqType.QUERY, self.bc_app) url = partial_url + '?para=' + obj_to_quote_str(query_params) tmp_resp = http_get(url, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.count = resp_dict.get('count') return bc_result
def report_not_supported_err(method_name): err_result = BCResult() err_result.result_code = NOT_SUPPORTED_CODE err_result.result_msg = NOT_SUPPORTED_NAME err_result.err_detail = u'[{:s}] does NOT support test mode currently!'.format( method_name) return err_result
def refund(self, refund_params): """ refund API, refund fee should not be greater than bill total fee; need_approval is for pre refund, you have to call [audit_pre_refunds] later on to execute real refund if the bill is paid with ali, you have to input your password on the returned url page refer to restful API https://beecloud.cn/doc/ #3 :param refund_params: beecloud.entity.BCRefundReqParams :return: beecloud.entity.BCResult """ if self.bc_app.is_test_mode: return report_not_supported_err('refund') attach_app_sign(refund_params, BCReqType.REFUND, self.bc_app) tmp_resp = http_post(self._bill_refund_url(), refund_params, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.id = resp_dict.get('id') # url will be returned if bill is refunded and channel is in (ALI_APP, ALI_WEB, ALI_QRCODE) bc_result.url = resp_dict.get('url') return bc_result
def query_bc_transfer_supported_banks(self, transfer_type): """ query bc_transfer supported banks, used by BCCardTransferParams field: bank_fullname :param transfer_type: P_DE:对私借记卡, P_CR:对私信用卡, C:对公账户 :return: """ query_param = _TmpObject() query_param.type = transfer_type url = get_rest_root_url() + 'rest/bc_transfer/banks?para=' + obj_to_quote_str(query_param) tmp_resp = http_get(url, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.size = resp_dict.get('size') bc_result.bank_list = resp_dict.get('bank_list') return bc_result
def query_refund_status(self, channel, refund_no): """ query refund status, it is for WX, YEE, KUAIQIAN, BD refer to https://beecloud.cn/doc/ #9 :param channel: str of WX, YEE, KUAIQIAN, BD :param refund_no: refund number :return: beecloud.entity.BCResult """ if self.bc_app.is_test_mode: return report_not_supported_err('query_refunds_count') query_params = _TmpObject() query_params.channel = channel query_params.refund_no = refund_no attach_app_sign(query_params, BCReqType.QUERY, self.bc_app) url = get_random_host() + self._query_refund_url() + '/status?para=' + obj_to_quote_str(query_params) tmp_resp = http_get(url, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.refund_status = resp_dict.get('refund_status') return bc_result
def send_sms_passcode(bc_app, phone): """ send sms verify code :param bc_app: beecloud.entity.BCApp :param phone: phone number passcode sent to :return: beecloud.entity.BCResult, which contains sms_id """ tmp_obj = _TmpObject() tmp_obj.phone = phone attach_app_sign(tmp_obj, BCReqType.PAY, bc_app) tmp_resp = http_post(get_rest_root_url() + "sms", tmp_obj, bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.sms_id = resp_dict.get('sms_id') return bc_result
def attach_buyer_history_bills(bc_app, bill_info): """ query merchant users :param bc_app: beecloud.entity.BCApp :param bill_info: {buyer_id: [bill_no...]...} dict, key is buyer id, value is bill number list that belong to the buyer :return: result contains failed_bills, which indicates the bills that fail to connect to the buyer, failed_bills is also dict like bill_info """ req_param = _TmpObject() req_param.bill_info = bill_info attach_app_sign(req_param, BCReqType.QUERY, bc_app) url = get_rest_root_url() + 'rest/history_bills' tmp_resp = http_put(url, req_param, bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if resp_dict.get('failed_bills'): bc_result.failed_bills = resp_dict.get('failed_bills') return bc_result
def offline_refund(self, refund_params): """ offline payment refund API, refund fee should not be greater than bill total fee; need_approval is not allowed for offline refund refer to restful API https://beecloud.cn/doc/?index=rest-api-offline #6 :param refund_params: beecloud.entity.BCRefundReqParams :return: beecloud.entity.BCResult """ if self.bc_app.is_test_mode: return report_not_supported_err('offline_refund') attach_app_sign(refund_params, BCReqType.REFUND, self.bc_app) tmp_resp = http_post(self._offline_refund_url(), refund_params, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.id = resp_dict.get('id') setattr(bc_result, "refund_result", resp_dict.get('refund_result')) return bc_result
def _bill_transfer(self, url, transfer_params): attach_app_sign(transfer_params, BCReqType.TRANSFER, self.bc_app) req_dict = {} for k, v in transfer_params.__dict__.items(): if v: if k == 'redpack_info': # WX_REDPACK req_dict[k] = obj_to_dict(v) elif k == 'transfer_data': # batch_transfer req_dict[k] = [ obj_to_dict(item) for item in transfer_params.transfer_data ] else: req_dict[k] = v tmp_resp = http_post(url, req_dict, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.id = resp_dict.get('id') # for ali bc_result.url = resp_dict.get('url') return bc_result
def _bill_transfer(self, url, transfer_params): attach_app_sign(transfer_params, BCReqType.TRANSFER, self.bc_app) req_dict = {} for k, v in transfer_params.__dict__.items(): if v: if k == 'redpack_info': # WX_REDPACK req_dict[k] = obj_to_dict(v) elif k == 'transfer_data': # batch_transfer req_dict[k] = [obj_to_dict(item) for item in transfer_params.transfer_data] else: req_dict[k] = v tmp_resp = http_post(url, req_dict, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.id = resp_dict.get('id') # for ali bc_result.url = resp_dict.get('url') return bc_result
def query_bc_transfer_supported_banks(self, transfer_type): """ query bc_transfer supported banks, used by BCCardTransferParams field: bank_fullname :param transfer_type: P_DE:对私借记卡, P_CR:对私信用卡, C:对公账户 :return: """ query_param = _TmpObject() query_param.type = transfer_type url = get_rest_root_url( ) + 'rest/bc_transfer/banks?para=' + obj_to_quote_str(query_param) tmp_resp = http_get(url, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.size = resp_dict.get('size') bc_result.bank_list = resp_dict.get('bank_list') return bc_result
def audit_pre_refunds(self, pre_refund_params): """ batch manage pre refunds; pre refund id list is required; each refund result is kept in result_map refer to restful API https://beecloud.cn/doc/?index=rest-api #4 :param pre_refund_params: beecloud.entity.BCPreRefundReqParams :return: beecloud.entity.BCResult """ if self.bc_app.is_test_mode: return report_not_supported_err('audit_pre_refunds') attach_app_sign(pre_refund_params, BCReqType.REFUND, self.bc_app) tmp_resp = http_put(self._bill_refund_url(), pre_refund_params, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: # if agree is true and refund successfully bc_result.result_map = resp_dict.get('result_map') bc_result.url = resp_dict.get('url') return bc_result
def _query_orders(self, query_params, query_type): if query_type == _OrderType.BILL: if query_params.refund_no: raise ValueError('refund_no should NOT be used to query bills') if query_params.need_approval: raise ValueError( 'need_approval should NOT be used to query bills') partial_url = self._query_bills_url() elif query_type == _OrderType.REFUND: if query_params.spay_result: raise ValueError( 'spay_result should NOT be used to query refunds') partial_url = self._query_refunds_url() else: return if not query_params: query_params = _TmpObject() attach_app_sign(query_params, BCReqType.QUERY, self.bc_app) url = partial_url + '?para=' + obj_to_quote_str(query_params) tmp_resp = http_get(url, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: if query_type == _OrderType.BILL: order_dict_arr = resp_dict.get('bills') class_name = BCBill else: order_dict_arr = resp_dict.get('refunds') class_name = BCRefund orders = [] if order_dict_arr: orders = [ parse_dict_to_obj(order_dict, class_name) for order_dict in order_dict_arr ] bc_result.count = len(orders) if query_type == _OrderType.BILL: bc_result.bills = orders else: bc_result.refunds = orders return bc_result
def _query_orders(self, query_params, query_type): if query_type == _OrderType.BILL: if query_params.refund_no: raise ValueError('refund_no should NOT be used to query bills') if query_params.need_approval: raise ValueError('need_approval should NOT be used to query bills') partial_url = self._query_bills_url() elif query_type == _OrderType.REFUND: if query_params.spay_result: raise ValueError('spay_result should NOT be used to query refunds') partial_url = self._query_refunds_url() else: return if not query_params: query_params = _TmpObject() attach_app_sign(query_params, BCReqType.QUERY, self.bc_app) url = partial_url + '?para=' + obj_to_quote_str(query_params) tmp_resp = http_get(url, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: if query_type == _OrderType.BILL: order_dict_arr = resp_dict.get('bills') class_name = BCBill else: order_dict_arr = resp_dict.get('refunds') class_name = BCRefund orders = [] if order_dict_arr: orders = [parse_dict_to_obj(order_dict, class_name) for order_dict in order_dict_arr] bc_result.count = len(orders) if query_type == _OrderType.BILL: bc_result.bills = orders else: bc_result.refunds = orders return bc_result
def rest_query_objects(bc_app, url, query_param, json_obj_name, object_type, para_query_mode=False): """ query object list by conditions :param bc_app: used to attach app sign :param url: do NOT contain params at the end :param query_param: query condition object beecloud.entity.BCQueryCriteria, more specific conditions can be attached to it :param json_obj_name: like 'plans' for plan list query :param object_type: object type like beecloud.entity.BCPlan :param para_query_mode: true if query string is para={}, else k1=v1&k2=v2 :return: beecloud.entity.BCResult """ if not query_param: query_param = _TmpObject() attach_app_sign(query_param, BCReqType.QUERY, bc_app) if para_query_mode: url = url + '?para=' + obj_to_quote_str(query_param) tmp_resp = http_get(url, bc_app.timeout) else: tmp_resp = http_get(url, bc_app.timeout, obj_to_dict(query_param)) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: # if only query count if hasattr(query_param, 'count_only') and query_param.count_only: bc_result.total_count = resp_dict.get('total_count') else: if resp_dict.get(json_obj_name): setattr(bc_result, json_obj_name, [ parse_dict_to_obj(dict_data, object_type) for dict_data in resp_dict.get(json_obj_name) if dict_data ]) else: setattr(bc_result, json_obj_name, []) return bc_result
def batch_add_merchant_users(bc_app, merchant, buyer_ids): """ add merchant user :param bc_app: beecloud.entity.BCApp :param merchant: merchant account :param buyer_ids: merchant unique user id list :return: beecloud.entity.BCResult """ req_param = _TmpObject() req_param.email = merchant req_param.buyer_ids = buyer_ids attach_app_sign(req_param, BCReqType.PAY, bc_app) url = get_rest_root_url() + 'rest/users' tmp_resp = http_post(url, req_param, bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) return bc_result
def add_merchant_user(bc_app, buyer_id): """ add merchant user :param bc_app: beecloud.entity.BCApp :param buyer_id: merchant unique user id, can be used as buyer id for bill :return: beecloud.entity.BCResult """ req_param = _TmpObject() req_param.buyer_id = buyer_id attach_app_sign(req_param, BCReqType.PAY, bc_app) url = get_rest_root_url() + 'rest/user' tmp_resp = http_post(url, req_param, bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) return bc_result
def rest_query_object_by_id(bc_app, url, obj_id, json_obj_name, object_type, para_query_mode=False): """ query object by id :param bc_app: used to attach app sign :param url: do NOT contain params at the end :param obj_id: object id :param json_obj_name: like 'plan' for plan query :param object_type: object type like beecloud.entity.BCPlan :param para_query_mode: true if query string is para={}, else k1=v1&k2=v2 :return: beecloud.entity.BCResult """ query_param = _TmpObject() attach_app_sign(query_param, BCReqType.QUERY, bc_app) if para_query_mode: url = url + '/' + obj_id + '?para=' + obj_to_quote_str(query_param) tmp_resp = http_get(url, bc_app.timeout) else: tmp_resp = http_get(url + '/' + obj_id, bc_app.timeout, obj_to_dict(query_param)) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: setattr(bc_result, json_obj_name, parse_dict_to_obj(resp_dict.get(json_obj_name), object_type)) return bc_result
def offline_revert(self, bill_no, channel=None, method='REVERT'): """ offline payment revert API, WX_NATIVE is not supported refer to restful API https://beecloud.cn/doc/?index=rest-api-offline #4 :param bill_no: bill number :param channel: bill payment channel like ALI_SCAN :param method: currently only support 'REVERT' :return: beecloud.entity.BCResult """ if self.bc_app.is_test_mode: return report_not_supported_err('offline_revert') tmp_obj = _TmpObject() if channel: setattr(tmp_obj, 'channel', channel) setattr(tmp_obj, 'method', method) attach_app_sign(tmp_obj, BCReqType.PAY, self.bc_app) tmp_resp = http_post(self._offline_pay_url() + '/' + bill_no, tmp_obj, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: setattr(bc_result, "revert_status", resp_dict.get('revert_status')) return bc_result
def query_offline_bill_status(self, bill_no, channel=None): """ query offline bill status refer to https://beecloud.cn/doc/?index=rest-api-offline #3 :param bill_no: bill number :param channel: bill payment channel like WX_SCAN :return: beecloud.entity.BCResult """ if self.bc_app.is_test_mode: return report_not_supported_err('query_offline_bill_status') query_params = _TmpObject() setattr(query_params, 'bill_no', bill_no) if channel: setattr(query_params, 'channel', channel) attach_app_sign(query_params, BCReqType.QUERY, self.bc_app) url = get_rest_root_url() + 'rest/offline/bill/status' tmp_resp = http_post(url, query_params, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: setattr(bc_result, 'pay_result', resp_dict.get('pay_result')) return bc_result
def rest_add_object(bc_app, url, obj, json_obj_name, obj_type): """ :param bc_app: used to attach app sign :param url: used to post request :param obj: like beecloud.entity.BCPlan :param json_obj_name: object json name returned when successful, like 'plan' :param obj_type: like beecloud.entity.BCPlan :return: beecloud.entity.BCResult """ attach_app_sign(obj, BCReqType.PAY, bc_app) tmp_resp = http_post(url, obj, bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: setattr(bc_result, json_obj_name, parse_dict_to_obj(resp_dict.get(json_obj_name), obj_type)) return bc_result
def query_merchant_users(bc_app, merchant=None, start_time=None, end_time=None): """ query merchant users :param bc_app: beecloud.entity.BCApp :param merchant: merchant account, if not passed, only users associated with app will be returned :param start_time: if passed, only users registered after it will be returned :param end_time: if passed, only users registered before it will be returned :return: result contains beecloud.entity.MerchantUser list """ req_param = _TmpObject() if merchant: req_param.email = merchant if start_time: req_param.start_time = start_time if end_time: req_param.end_time = end_time attach_app_sign(req_param, BCReqType.QUERY, bc_app) url = get_rest_root_url() + 'rest/users?para=' + obj_to_quote_str(req_param) tmp_resp = http_get(url, bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: user_dict_arr = resp_dict.get('users') class_name = BCMerchantUser users = [] if user_dict_arr: users = [parse_dict_to_obj(user_dict, class_name) for user_dict in user_dict_arr] bc_result.users = users return bc_result
def rest_query_objects(bc_app, url, query_param, json_obj_name, object_type, para_query_mode=False): """ query object list by conditions :param bc_app: used to attach app sign :param url: do NOT contain params at the end :param query_param: query condition object beecloud.entity.BCQueryCriteria, more specific conditions can be attached to it :param json_obj_name: like 'plans' for plan list query :param object_type: object type like beecloud.entity.BCPlan :param para_query_mode: true if query string is para={}, else k1=v1&k2=v2 :return: beecloud.entity.BCResult """ if not query_param: query_param = _TmpObject() attach_app_sign(query_param, BCReqType.QUERY, bc_app) if para_query_mode: url = url + '?para=' + obj_to_quote_str(query_param) tmp_resp = http_get(url, bc_app.timeout) else: tmp_resp = http_get(url, bc_app.timeout, obj_to_dict(query_param)) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: # if only query count if hasattr(query_param, 'count_only') and query_param.count_only: bc_result.total_count = resp_dict.get('total_count') else: if resp_dict.get(json_obj_name): setattr(bc_result, json_obj_name, [parse_dict_to_obj(dict_data, object_type) for dict_data in resp_dict.get(json_obj_name) if dict_data]) else: setattr(bc_result, json_obj_name, []) return bc_result
def setUp(self): self.bc_app = BCApp() self.bc_app.app_id = 'your_app_id' self.bc_app.app_secret = 'your_app_sec' self.bc_app.master_secret = 'your_master_sec' self.bc_pay = BCPay() self.bc_pay.register_app(self.bc_app) # set up err result self.http_err = BCResult() self.http_err.result_code = NETWORK_ERROR_CODE self.http_err.result_msg = 404 self.http_err.err_detail = 'not found' self.timeout_err = BCResult() self.timeout_err.result_code = NETWORK_ERROR_CODE self.timeout_err.result_msg = NETWORK_ERROR_NAME self.timeout_err.err_detail = 'ConnectionError: normally caused by timeout'
def international_pay(self, pay_params): """ international pay -- PayPal refer to https://github.com/beecloud/beecloud-rest-api/tree/master/international #2 credit_card_info should be type of beecloud.entity.BCPayPalCreditCard :param pay_params: beecloud.entity.BCInternationalPayParams :return: beecloud.entity.BCResult """ if self.bc_app.is_test_mode: return report_not_supported_err('international_pay') attach_app_sign(pay_params, BCReqType.PAY, self.bc_app) req_dict = {} for k, v in pay_params.__dict__.items(): if v: if k == 'credit_card_info': req_dict[k] = obj_to_dict(v) else: req_dict[k] = v tmp_resp = http_post(self._international_pay_url(), req_dict, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.id = resp_dict.get('id') # url is returned when channel is PAYPAL_PAYPAL bc_result.url = resp_dict.get('url') # credit_card_id is returned when channel is PAYPAL_CREDITCARD bc_result.credit_card_id = resp_dict.get('credit_card_id') return bc_result
def offline_pay(self, pay_params): """ offline payment API, different channels have different requirements for request params and the return params varies. refer to restful API https://beecloud.cn/doc/?index=rest-api-offline #2 :param pay_params: beecloud.entity.BCPayReqParams :return: beecloud.entity.BCResult """ if self.bc_app.is_test_mode: return report_not_supported_err('offline_pay') self._add_sdk_version(pay_params) attach_app_sign(pay_params, BCReqType.PAY, self.bc_app) tmp_resp = http_post(self._offline_pay_url(), pay_params, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.id = resp_dict.get('id') if resp_dict.get('pay_result') is not None: setattr(bc_result, 'pay_result', resp_dict.get('pay_result')) if resp_dict.get('code_url'): setattr(bc_result, 'code_url', resp_dict.get('code_url')) if resp_dict.get('channel_type'): setattr(bc_result, 'channel_type', resp_dict.get('channel_type')) return bc_result
def _deal_with_invalid_resp(http_resp): resp = BCResult() resp.result_code = NETWORK_ERROR_CODE resp.result_msg = http_resp.status_code resp.err_detail = http_resp.reason return URL_REQ_FAIL, resp
def _deal_with_conn_error(): resp = BCResult() resp.result_code = NETWORK_ERROR_CODE resp.result_msg = NETWORK_ERROR_NAME resp.err_detail = 'ConnectionError: normally caused by timeout' return URL_REQ_FAIL, resp
def pay(self, pay_params): """ payment API, different channels have different requirements for request params and the return params varies. refer to restful API https://beecloud.cn/doc/ #2 :param pay_params: beecloud.entity.BCPayReqParams :return: beecloud.entity.BCResult """ attach_app_sign(pay_params, BCReqType.PAY, self.bc_app) tmp_resp = http_post(self._bill_pay_url(), pay_params, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.id = resp_dict.get('id') # most channel will return url or html bc_result.html = resp_dict.get('html') bc_result.url = resp_dict.get('url') # WX_NATIVE if pay_params.channel == BCChannelType.WX_NATIVE: bc_result.code_url = resp_dict.get('code_url') # WX_JSAPI if pay_params.channel == BCChannelType.WX_JSAPI: bc_result.app_id = resp_dict.get('app_id') bc_result.package = resp_dict.get('package') bc_result.nonce_str = resp_dict.get('nonce_str') bc_result.timestamp = resp_dict.get('timestamp') bc_result.pay_sign = resp_dict.get('pay_sign') bc_result.sign_type = resp_dict.get('sign_type') return bc_result
def pay(self, pay_params): """ payment API, different channels have different requirements for request params and the return params varies. refer to restful API https://beecloud.cn/doc/?index=rest-api #2 :param pay_params: beecloud.entity.BCPayReqParams :return: beecloud.entity.BCResult """ self._add_sdk_version(pay_params) attach_app_sign(pay_params, BCReqType.PAY, self.bc_app) tmp_resp = http_post(self._bill_pay_url(), pay_params, self.bc_app.timeout) # if err encountered, [0] equals 0 if not tmp_resp[0]: return tmp_resp[1] # [1] contains result dict resp_dict = tmp_resp[1] bc_result = BCResult() set_common_attr(resp_dict, bc_result) if not bc_result.result_code: bc_result.id = resp_dict.get('id') # most channel will return url or html if resp_dict.get('html'): bc_result.html = resp_dict.get('html') if resp_dict.get('url'): bc_result.url = resp_dict.get('url') # WX_NATIVE or BC_NATIVE or BC_ALI_QRCODE if resp_dict.get('code_url'): bc_result.code_url = resp_dict.get('code_url') # WX_JSAPI if pay_params.channel == BCChannelType.WX_JSAPI: bc_result.app_id = resp_dict.get('app_id') bc_result.package = resp_dict.get('package') bc_result.nonce_str = resp_dict.get('nonce_str') bc_result.timestamp = resp_dict.get('timestamp') bc_result.pay_sign = resp_dict.get('pay_sign') bc_result.sign_type = resp_dict.get('sign_type') return bc_result
def report_not_supported_err(method_name): err_result = BCResult() err_result.result_code = NOT_SUPPORTED_CODE err_result.result_msg = NOT_SUPPORTED_NAME err_result.err_detail = u'[{:s}] does NOT support test mode currently!'.format(method_name) return err_result