# ProxyMocker **Repository Path**: rdtest/ProxyMocker ## Basic Information - **Project Name**: ProxyMocker - **Description**: 搭设mock服务,在不影响正常使用的情况下,按需拦截模拟 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2022-02-25 - **Last Updated**: 2022-06-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # proxyMocker 中转mocker服务 ## 流程设计 * mocker 前,流程如下: ![Image text](static/1.png) * mocker 后,流程如下: ![Image text](static/2.png) ![Image text](static/3.png) ## mocker 过滤过程 ![Image text](static/admin_filter.png) * 场景一:ip 不匹配,直接拦截请求,返回错误码 * 场景二:ip匹配-》api匹配-》参数匹配代码==True-》使用mock_pycode 运行结果响应 * 场景三:ip匹配-》(api不匹配 OR 参数匹配代码==False)-》转发到target_host,获取目标服务响应 ## 解决测试中的问题 1. 模拟第三方服务的各种响应情况(正确场景,错误场景,超时等) 2. 通过web后台,灵活配置过滤py代码,响应py代码 ## 使用实例 > 测试场景说明: 使用标普(第三方)出佣给个人的银行凭证来与内部结算中心的出佣申请进行对账。但是标普测试环境没有凭证。 #### 测试内容: 1.定时任务一:从结算中心(内部)定时检查已出佣,未获得凭证的单据-》然后调用钱包服务(内部)接口-》钱包服务调用标普接口获得银行回单—》结算中心更新出佣申请记录表中的receipt_url 字段,并保存pdf,插入附件记录表。 2.定时任务二:从结算中心(内部)定时检查已出佣,已获得凭证未校验的单据-》结算中心将银行凭证发送到RPA(AI识别,解析PDF中的单据金额等)获得凭证数据-》将凭证数据与平台出佣记录对比,对比后更新对比结果字段。 问题:标普测试环境,没有银行回单!!! #### 测试方法 1. 使用mock方法,将钱包调标普获得银行回单接口,改成钱包调mock服务(要指定请求参数来过滤,不能所有请求都mock),模拟返回银行回单URL 2. 修改银行回单pdf内容,一来验证RPA解析是否正确,二来应对凭证校验通过与不通过的情况。 #### proxyMocker 部署(根据自己情况,仅供参考) ##### 配置nginx `xxx.xxx.xxx.net.conf` ``` server { listen 80; server_name xxx.xxx.xxx.net; location / { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:8002; } # 非必须,本次测试中需要用到在线pdf,因此配置提供在线pdf预览下载 location ^~ /download { alias /home/guanfuchang/; autoindex on; autoindex_exact_size on; autoindex_localtime on; charset utf-8; if ($request_filename ~* ^.*?\.(txt|doc|pdf|rar|gz|zip|docx|exe|xlsx|ppt|pptx)$){ add_header Content-Disposition: 'p_w_upload;'; } } } ``` ##### 部署启动proxyMocker服务 ``` docker-compose up -d ``` ##### 修改相关配置 * 让开发修改钱包服务调标普的域名,修改为: `xxx.xxx.xxx.net` * 登录管理后台xxx.xxx.xxx.net/admin,修改过滤条件 >标普接口格式参考如下:
>[标普云] 发送请求 {"merCode":"xxx","reqData":{"taskNum":"RW162202421619283567"},"sign":"xxx","serviceName":"taskTradeReceiptInq","timestamp":1624957210673}
>[标普云] 接收响应 {"rspCode":"0000","rspMsg":"success","rspData":{"result":{"taskNum":"RW162202421619283567","tradeReceiptUrl":null},"code":"200","message":"操作成功"},"sign":"xxx","timestamp":"xxx"} ![Image text](static/admin_filter.png) ```python # _*_ coding:utf-8 _*_ def param_filter(querystring,params): # 根据需要,可以使用querystring和params参数,进行过滤,返回Trur or False,决定是否需要使用mock # querystring 格式为字符串,eg.name="Milton"&age=18 # params 格式(一般)为字典,eg.{"name":"Milton","age":18} # Create your filter code here,return True or False taskNum=params.get('reqData').get('taskNum') serviceName=params.get('serviceName') if taskNum=="RW161821364992319617781" and serviceName=="taskTradeReceiptInq":return True return False ``` ```python # _*_ coding:utf-8 _*_ import json def mock_resp(querystring,params): # 根据需要,可以获得querystring和params参数,进行逻辑处理,生成mocke响应内容 # querystring 格式为字符串,eg.name="Milton"&age=18 # params 格式(一般)为字典,eg.{"name":"Milton","age":18} # Create your mock code here return json.dumps({"rspCode":"0000","rspMsg":"success","rspData":{"result":{"taskNum":"RW161821364992319617781","tradeReceiptUrl":"http://pmocker.test.thinkinpower.net/download/1000.pdf"},"code":"200","message":"操作成功"},"sign":"6F8F78D771AB3AF1A5E5D6B34FE2B804","timestamp":"1624957192611"},ensure_ascii=False) ``` * 查看日志 ``` 接收到新请求----------------------------------------------------------------------》 2021-06-30 14:17:36.858 | DEBUG | mockerAPP.views:home:23 - 客户端请求参数处理结果: { "api": "/api/csp/v1", "host": "xxx.xxx.xxx.net", "method": "POST", "meta": {}, "querystring": "", "full_path": "/api/csp/v1", "content_type": "application/json", "headers": { "X_REAL_IP": "10.29.253.140", "X_FORWARDED_FOR": "120.79.181.239, 10.29.253.140", "CONNECTION": "close", "ACCEPT": "application/json", "ACCEPT_CHARSET": "", "USER_AGENT": "Java/1.8.0_191", "Content-Type": "application/json" }, "body": "{\"merCode\":\"abb33ccfeccj44gg\",\"reqData\":{\"taskNum\":\"RW161821364992319617781\"},\"sign\":\"57283A3437AA492157D62CC4E5B83093\",\"serviceName\":\"taskTradeReceiptInq\",\"timestamp\":1625040634780}", "ip": "120.79.181.239, 10.29.253.140" } 2021-06-30 14:17:36.876 | INFO | mockerAPP.views:mock_filter:108 - ip=120.79.181.239, 10.29.253.140 匹配fish记录条目:2 2021-06-30 14:17:36.879 | INFO | mockerAPP.views:mock_filter:108 - ip=120.79.181.239, 10.29.253.140 匹配fish记录条目:2 2021-06-30 14:17:36.892 | INFO | mockerAPP.views:mock_filter:115 - api_path=/api/csp/v1 匹配fish记录条目:1 2021-06-30 14:17:36.893 | INFO | mockerAPP.views:mock_filter:129 - type(querystring):,querystring:将传入到 precode 中进行处理 2021-06-30 14:17:36.894 | INFO | mockerAPP.views:mock_filter:130 - type(params):,params:{'merCode': 'abb33ccfeccj44gg', 'reqData': {'taskNum': 'RW161821364992319617781'}, 'sign': 'C84862FD5231327F3CDA6165580154DA', 'serviceName': 'taskTradeReceiptInq', 'timestamp': 1625033856846}将传入到 precode 中进行处理 2021-06-30 14:17:36.894 | INFO | mockerAPP.views:mock_filter:137 - pre_pycode 执行结果:True 2021-06-30 14:17:36.895 | WARNING | mockerAPP.views:mock_filter:140 - mocker处理--------------------------------------------------》 2021-06-30 14:17:36.922 | INFO | mockerAPP.views:mock_filter:148 - mock_pycode 执行结果:{"rspCode": "0000", "rspMsg": "success", "rspData": {"result": {"taskNum": "RW161821364992319617781", "tradeReceiptUrl": "http://pmocker.test.thinkinpower.net/download/1000.pdf"}, "code": "200", "message": "操作成功"}, "sign": "6F8F78D771AB3AF1A5E5D6B34FE2B804", "timestamp": "1624957192611"} 2021-06-30 14:17:36.923 | INFO | mockerAPP.views:mock_filter:115 - api_path=/api/csp/v1 匹配fish记录条目:1 2021-06-30 14:17:36.923 | INFO | mockerAPP.views:home:31 - mock 响应格式: 2021-06-30 14:17:36.925 | INFO | mockerAPP.views:home:19 - ```