odoo IAP 服务

IAP

IAP的概念

# IAP流程3种实体:  客户   , 服务提供者  和 Odoo自身
	# 客户 安装提供服务的模块,即可使用这个模块
    # 服务 提供给开发人员。 客户的有足够的余额,服务提供者会扣除余额并提供服务
    # Odoo 作为中间商  25%的佣金

    
# IAP服务流
	1. 客户 向 服务提供商发起 提供服务请求。	  客户将传递账号令牌,服务提供商使用令牌来识别用户
    2. 接受到客户请求服务后。 服务商检查 Odoo IAP客户的账号里是否有足够的余额。没有余额则拒绝掉本次服务
    3. 在保留余额后,服务者执行服务。 某些情况下,服务提供者会调用外部服务来执行所请求的服务
    4. 执行完服务后,服务提供者回到Odoo API来获取所预留的余额。 如果请求的服务未能正常提供服务,服务提供者会要求Odoo释放所预留余额
    5. 服务提供者会回到客户。 通知他们请求服务成功,返回一些成功信息
    
    
    # 余额不足时
    1.服务提供者返回到客户并告知他们在账户中没有足够的余额,显示用户可以购买服务的信息(一个Odoo服务包链接)。

	2.  客户重定向到Odoo并进行服务的充值。

注册OdooIAP服务

# https://iap.odoo.com/
# 注册一个IAP服务
	# 1. 保存  秘钥

创建IAP模块

#   开发一个 提供 IAP 服务的模块

# 1. 模型, 视图,
	pass 跳过

# 2. 定义要处理 当前模型的函数
 @api.model
    def _books_data_by_isbn(self, isbn):
        book = self.search([('isbn', '=', isbn)], limit=1)  # 搜索到isbn 这本书 ,并返回 
        if book:
            return {
                'status': 'found',
                'data': {
                    'name': book.name,
                    'isbn': book.isbn,
                    'date_release': book.date_release,
                    'cover_image': book.cover_image,
                    'authors': [a.name for a in book.author_ids]
                }
            }
        else:
            return {
                'status': 'not found',
            }

        
# 3.  在controllers 中 配置一个 处理接口
	# ir.config_parameter  系统参数模型
    # account_token   客户令牌
    
	@http.route('/get_book_data', type='json', auth="public") # type=限定传输数据类型为json
    def get_book_data(self, account_token, isbn_number):
        # 获取 service_key  ,
        service_key = request.env['ir.config_parameter'].sudo().get_param('iap.isbn_service_key', False)
        
        if not service_key:
            return {
                'status': 'service is not active'
            }
        credits_to_reserve = 1
        data = {}

        # iap.charge 方法 。 处理从客户账户中获取余额的流程,参数:环境,服务秘钥,客户账户令牌和获取的金额
               # 此方法会创建上下文, 异常时 在 __emter__  抛出异常
       # credit_template 是 指定模型调用的模板 
        with iap.charge(request.env, service_key, account_token, credits_to_reserve,
                        credit_template='iap_isbn_service.no_credit_info'):
			
            data = request.env['book.info'].sudo()._books_data_by_isbn(isbn_number)
            if data['status'] == 'not found':
                raise Exception('Book not found')
        return data

授权并收取IAP余额

# 1. 设置 isbn_server_key 字段。 在配置中添加
	from odoo import models, fields
    class ConfigSettings(models.TransientModel):
      		_inherit = 'res.config.settings'
			
            # config_parameter 参数 是指定存储到ir.config_paramete 模型中 ,称之为系统参数
            # 获取系统参数可以通过 get_param() 函数 	
            		# `self.env['ir.config_parameter'].sudo().get_param('iap.isbn_service_key',False)`
     		 isbn_service_key = fields.Char("ISBN service key",  config_parameter='iap.isbn_service_key')
            
# 2. account_token 是标识用户的客户令牌
		account_token   是 服务端价差当前客户余额时,服务者发送给客户端的令牌
        
# 3. 调用 iap.charge()   四个参数:环境,服务秘钥,客户令牌,获取的金额
		# 没有足够余额时 , 会抛出InsufficientCreditError错误
    
    	# 多条数据 请求 iap服务时的方法
        def  xxx(self,account_token,isbn_list=None):
                    .....
                    isbn_list = [el for el in isbn_list]  # 多条数据 , 调用服务
                    credits_to_reserve = len(isbn_list)
                    data_fond = []

                    with iap.charge(request.env, service_key, account_token, credits_to_reserve,
                                    credit_template='iap_isbn_service.no_credit_info') as transection:

                        for isbn in isbn_list:
                            data = request.env['book.info'].sudo()._books_data_by_isbn(isbn)
                            if data['status'] == 'not found':
                                data_fond.append(data_fond)
                        transection.credit = len(data_fond)
                    return data_fond
                
# 4. 确保 它能够处理 JSON-RPC2的请求

JSON-RPC2 api

img

创建IAP客户端模块

#  1. 添加 button 视图,对应到具体方法
    <button name="fetch_book_data"
              string="Fetch Book Data" type="object"/>
        
        
# 2. 发起调用服务的请求
	    def fetch_book_data(self):
                self.ensure_one()  # 确保是一条数据 
                if not self.isbn:   # 如果 这条数据没由isbn 书号,抛出用户错误
                    raise UserError("Please add  ISBN number")

                user_token = self.env['iap.account'].get('book_isbn')  # 用户调用注册过的服务,服务端生成 令牌
                params = {
                    'account_token': user_token.account_token,
                    'isbn_number': self.isbn
                }
                service_endpoint = 'http://localhost:8888'
                result = jsonrpc(service_endpoint + '/get_book_data', params=params)
                if result.get('status') == 'found':
                    self.write(self.process_result(result['data']))
                return True
# process_result() 函数调用 服务完成后处理的结果
	
    @api.model
    def process_result(self, result):
                authors = []
                existing_author_ids = []
                for author_name in result['authors']:
                    author = self.env['res.partner'].search([('name', '=', author_name)], limit=1)
                    if author:
                        existing_author_ids.append(author.id)
                    else:
                        authors.append((0, 0, {'name': author_name}))
                if existing_author_ids:
                    authors.append((6, 0, existing_author_ids))
                return {
                    'author_ids': authors,
                    'name': result.get('name'),
                    'isbn': result.get('isbn'),
                    'cover_image': result.get('cover_image'),
                    'date_release': result.get('date_release'),
                }
posted @ 2021-03-26 14:25  染指未来  阅读(227)  评论(0编辑  收藏  举报