From 45ae6cf36e6857ff9cbd1ea57193d3403fdbf034 Mon Sep 17 00:00:00 2001 From: liangzai <2440983361@qq.com> Date: Wed, 10 Jun 2026 20:32:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=A4=84=E7=90=86=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/product_prune/main.go | 237 + config.yaml | 38 +- .../product_application_service_impl.go | 4 - internal/config/config.go | 28 + internal/container/container.go | 7 +- internal/domains/api/dto/api_request_dto.go | 129 +- .../api/services/api_request_service.go | 313 +- .../api/services/form_config_service.go | 137 +- .../processors/comb/comb86pm_processor.go | 36 - .../processors/comb/combhzy2_processor.go | 148 - .../processors/comb/combhzy2_transform.go | 2053 -------- .../processors/comb/combwd01_processor.go | 91 - .../api/services/processors/dependencies.go | 8 +- .../processors/dwbg/dwbg5sam_processor.go | 67 - .../processors/dwbg/dwbg6a2c_processor.go | 67 - .../processors/dwbg/dwbg7f3a_processor.go | 51 - .../processors/dwbg/dwbg8b4d_processor.go | 4622 ----------------- .../dwbg/dwbg8b4d_processor_test.go | 1327 ----- .../processors/flxg/flxg0687_processor.go | 39 - .../processors/flxg/flxg0v3b_processor.go | 51 - .../processors/flxg/flxg0v4b_processor.go | 527 -- .../processors/flxg/flxg162a_processor.go | 57 - .../processors/flxg/flxg2e8f_processor.go | 60 - .../processors/flxg/flxg3a9b_processor.go | 63 - .../processors/flxg/flxg3d56_processor.go | 66 - .../processors/flxg/flxg54f5_processor.go | 45 - .../processors/flxg/flxg5876_processor.go | 45 - .../processors/flxg/flxg5a3b_processor.go | 58 - .../processors/flxg/flxg5b2e_processor.go | 88 - .../processors/flxg/flxg75fe_processor.go | 40 - .../processors/flxg/flxg7e8f_processor.go | 49 - .../processors/flxg/flxg8a3f_processor.go | 86 - .../processors/flxg/flxg8b4d_processor.go | 104 - .../processors/flxg/flxg9687_processor.go | 57 - .../processors/flxg/flxg970f_processor.go | 51 - .../processors/flxg/flxg9c1d_processor.go | 58 - .../processors/flxg/flxgbc21_processor.go | 38 - ...b4f_processor.go => flxgc4ct_processor.go} | 8 +- .../processors/flxg/flxgc9d1_processor.go | 57 - .../processors/flxg/flxgca3d_processor.go | 57 - .../processors/flxg/flxgdea8_processor.go | 56 - .../processors/flxg/flxgdea9_processor.go | 57 - .../processors/flxg/flxgdec7_processor.go | 51 - .../processors/flxg/flxgdjg3_processor.go | 54 - .../processors/flxg/flxgji17_processor.go | 14 + .../processors/flxg/flxgk5d2_processor.go | 63 - ...0s4_processor.go => flxgmmg7_processor.go} | 6 +- .../processors/ivyz/ivyz0b03_processor.go | 51 - .../processors/ivyz/ivyz0s0d_processor.go | 45 - .../processors/ivyz/ivyz18hy_processor.go | 63 - .../processors/ivyz/ivyz1c9d_processor.go | 52 - .../processors/ivyz/ivyz1j7h_processor.go | 46 - .../processors/ivyz/ivyz2125_processor.go | 38 - .../processors/ivyz/ivyz28hy_processor.go | 54 - .../processors/ivyz/ivyz2a8b_processor.go | 161 - .../processors/ivyz/ivyz2b2t_processor.go | 58 - .../processors/ivyz/ivyz2c1p_processor.go | 56 - .../processors/ivyz/ivyz2mn6_processor.go | 54 - .../processors/ivyz/ivyz385e_processor.go | 49 - .../processors/ivyz/ivyz38sr_processor.go | 56 - .../processors/ivyz/ivyz3a7f_processor.go | 50 - .../ivyz/ivyz3p9m_processor copy.go | 64 - .../processors/ivyz/ivyz3p9m_processor.go | 168 - .../processors/ivyz/ivyz48sr_processor.go | 58 - .../processors/ivyz/ivyz4e8b_processor.go | 84 - .../processors/ivyz/ivyz5733_processor.go | 83 - .../processors/ivyz/ivyz5a9o_processor.go | 57 - .../processors/ivyz/ivyz5e22_processor.go | 66 - .../processors/ivyz/ivyz5e3f_processor.go | 56 - .../processors/ivyz/ivyz6g7h_processor.go | 46 - .../processors/ivyz/ivyz6m8p_processor.go | 46 - ...jj6_processor.go => ivyz6w0u_processor.go} | 6 +- .../processors/ivyz/ivyz7c9d_processor.go | 47 - .../processors/ivyz/ivyz7f2a_processor.go | 95 - .../processors/ivyz/ivyz7f3a_processor.go | 56 - .../processors/ivyz/ivyz81nc_processor.go | 96 - .../processors/ivyz/ivyz8i9j_processor.go | 47 - .../processors/ivyz/ivyz9363_processor.go | 68 - .../processors/ivyz/ivyz9a2b_processor.go | 51 - .../processors/ivyz/ivyz9d2e_processor.go | 51 - .../processors/ivyz/ivyz9h2m_processor.go | 47 - .../processors/ivyz/ivyz9k2l_processor.go | 103 - .../processors/ivyz/ivyz9k7f_processor.go | 48 - .../processors/ivyz/ivyz9ohn_processor.go | 14 + .../processors/ivyz/ivyza1b3_processor.go | 49 - .../processors/ivyz/ivyzadee_processor.go | 38 - ...xf6_processor.go => ivyzbi6f_processor.go} | 6 +- .../processors/ivyz/ivyzbpq2_processor.go | 51 - .../processors/ivyz/ivyzdxmd_processor.go | 29 + .../processors/ivyz/ivyze42i_processor.go | 24 + .../processors/ivyz/ivyzfic1_processor.go | 55 - .../processors/ivyz/ivyzfo5k_processor.go | 24 + .../processors/ivyz/ivyzgz08_processor.go | 51 - .../processors/ivyz/ivyzkj31_processor.go | 24 + .../processors/ivyz/ivyzn2p8_processor.go | 121 - .../processors/ivyz/ivyzo4rx_processor.go | 14 + .../processors/ivyz/ivyzocr1_processor.go | 48 - .../processors/ivyz/ivyzocr2_processor.go | 56 - ...1o6_processor.go => ivyzoqfb_processor.go} | 6 +- .../processors/ivyz/ivyzp2q6_processor.go | 84 - .../processors/ivyz/ivyzpyso_processor.go | 14 + .../processors/ivyz/ivyzrht5_processor.go | 14 + .../processors/ivyz/ivyzsfel_processor.go | 52 - .../processors/ivyz/ivyzsq0e_processor.go | 24 + .../processors/ivyz/ivyzwvya_processor.go | 24 + .../processors/ivyz/ivyzx5q2_processor.go | 63 - .../processors/ivyz/ivyzx5qz_processor.go | 48 - .../processors/ivyz/ivyzydqm_processor.go | 14 + .../processors/ivyz/ivyzyqkx_processor.go | 14 + .../processors/ivyz/ivyzzqt3_processor.go | 212 - .../processors/ivyz/ivyzzscg_processor.go | 28 + .../processors/jrzq/jrzq09j8_processor.go | 62 - .../processors/jrzq/jrzq0a03_processor.go | 57 - .../processors/jrzq/jrzq0b6y_processor.go | 40 - .../processors/jrzq/jrzq0l85_processor.go | 47 - ...07t_processor.go => jrzq1aij_processor.go} | 6 +- .../processors/jrzq/jrzq1d09_processor.go | 62 - .../processors/jrzq/jrzq1e7b_processor.go | 62 - .../processors/jrzq/jrzq1p5g_processor.go | 48 - .../processors/jrzq/jrzq1w4x_processor.go | 64 - .../processors/jrzq/jrzq2f8a_processor.go | 62 - .../processors/jrzq/jrzq3ag6_processor.go | 63 - .../processors/jrzq/jrzq3c7b_processor.go | 62 - .../processors/jrzq/jrzq3c9R_processor.go | 62 - .../processors/jrzq/jrzq3p01_processor.go | 56 - .../processors/jrzq/jrzq4aa8_processor.go | 57 - .../processors/jrzq/jrzq4b6c_processor.go | 61 - .../processors/jrzq/jrzq5e9f_processor.go | 62 - ...hz4_processor.go => jrzq65zo_processor.go} | 6 +- .../processors/jrzq/jrzq6f2a_processor.go | 47 - .../processors/jrzq/jrzq7f1a_processor.go | 62 - .../processors/jrzq/jrzq8203_processor.go | 57 - .../processors/jrzq/jrzq8a2d_processor.go | 59 - .../processors/jrzq/jrzq8b3c_processor.go | 47 - .../processors/jrzq/jrzq8f7c_processor.go | 62 - .../processors/jrzq/jrzq9a1w_processor.go | 40 - .../processors/jrzq/jrzq9d4e_processor.go | 47 - .../processors/jrzq/jrzq9e2a_processor.go | 48 - .../processors/jrzq/jrzqacab_processor.go | 51 - ...4tf_processor.go => jrzqah34_processor.go} | 6 +- .../processors/jrzq/jrzqbqir_processor.go | 50 + .../processors/jrzq/jrzqdcbe_processor.go | 62 - .../processors/jrzq/jrzqdmlo_processor.go | 14 + ...1o0_processor.go => jrzqi079_processor.go} | 6 +- ...ztf_processor.go => jrzqly6d_processor.go} | 6 +- .../processors/jrzq/jrzqmdq1_processor.go | 28 + ...kk6_processor.go => jrzqml9g_processor.go} | 6 +- ...7md_processor.go => jrzqmlzx_processor.go} | 6 +- ...zxf_processor.go => jrzqnep0_processor.go} | 6 +- ...z2y_processor.go => jrzqnk43_processor.go} | 6 +- ...8v8_processor.go => jrzqnkei_processor.go} | 6 +- ...5f4_processor.go => jrzqnvm8_processor.go} | 6 +- .../processors/jrzq/jrzqo6l7_processor.go | 64 - .../processors/jrzq/jrzqo7l1_processor.go | 67 - .../processors/jrzq/jrzqocre_processor.go | 52 - .../processors/jrzq/jrzqocry_processor.go | 48 - .../processors/jrzq/jrzqoicn_processor.go | 14 + ...3hm_processor.go => jrzqqd4f_processor.go} | 6 +- ...9v9_processor.go => jrzqqkec_processor.go} | 6 +- .../processors/jrzq/jrzqs7g0_processor.go | 61 - ...0md_processor.go => jrzqtm1v_processor.go} | 6 +- ...2o1_processor.go => jrzqv7yz_processor.go} | 6 +- .../processors/jrzq/jrzqv87m_processor.go | 50 - ...t43_processor.go => jrzqvbhj_processor.go} | 6 +- .../processors/jrzq/jrzqvt72_processor.go | 50 - ...7d1_processor.go => jrzqx5dm_processor.go} | 6 +- ...z3y_processor.go => jrzqz05i_processor.go} | 6 +- .../processors/pdfg/pdfg01gz_processor.go | 498 -- .../processors/qcxg/qcxg1h7y_processor.go | 47 - .../processors/qcxg/qcxg1u4u_processor.go | 49 - .../processors/qcxg/qcxg2t6s_processor.go | 47 - .../processors/qcxg/qcxg3b8z_processor.go | 48 - .../processors/qcxg/qcxg3m7z_processor.go | 50 - .../processors/qcxg/qcxg3y6b_processor.go | 49 - .../processors/qcxg/qcxg3z3l_processor.go | 48 - .../processors/qcxg/qcxg4896_processor.go | 52 - .../processors/qcxg/qcxg4d2e_processor.go | 47 - .../processors/qcxg/qcxg4i1z_processor.go | 46 - .../processors/qcxg/qcxg521l_processor.go | 14 + .../processors/qcxg/qcxg5f3a_processor.go | 52 - .../processors/qcxg/qcxg5u0z_processor.go | 46 - .../processors/qcxg/qcxg6b4e_processor.go | 45 - .../processors/qcxg/qcxg76va_processor.go | 14 + .../processors/qcxg/qcxg7a2b_processor.go | 38 - .../processors/qcxg/qcxg8a3d_processor.go | 49 - .../processors/qcxg/qcxg9f5c_processor.go | 48 - .../processors/qcxg/qcxg9p1c_processor.go | 77 - .../processors/qcxg/qcxgfv9w_processor.go | 14 + .../processors/qcxg/qcxggb2q_processor.go | 79 - .../processors/qcxg/qcxggfww_processor.go | 14 + .../processors/qcxg/qcxggj3a_processor.go | 46 - ...4cl_processor.go => qcxgijy3_processor.go} | 6 +- .../processors/qcxg/qcxgjj2a_processor.go | 48 - .../processors/qcxg/qcxgm7r9_processor.go | 48 - .../processors/qcxg/qcxgp00w_processor.go | 45 - .../processors/qcxg/qcxgp1w3_processor.go | 48 - .../processors/qcxg/qcxgu2k4_processor.go | 48 - .../processors/qcxg/qcxgy7f2_processor.go | 50 - .../processors/qcxg/qcxgyqdc_processor.go | 14 + .../processors/qcxg/qcxgyts2_processor.go | 44 - .../processors/qcxg/qcxgywsv_processor.go | 14 + .../processors/qygl/coment01_processor.go | 69 - .../processors/qygl/qygl23t7_processor.go | 121 - .../processors/qygl/qygl2acd_processor.go | 57 - .../processors/qygl/qygl2b5c_processor.go | 59 - .../processors/qygl/qygl2nao_processor.go | 58 - .../processors/qygl/qygl2s0w_processor.go | 79 - .../processors/qygl/qygl3f8e_processor.go | 1141 ---- .../processors/qygl/qygl45bd_processor.go | 66 - .../processors/qygl/qygl4b2e_processor.go | 59 - .../processors/qygl/qygl5a3c_processor.go | 59 - .../processors/qygl/qygl5a9t_processor.go | 64 - .../processors/qygl/qygl5cmp_processor.go | 128 - .../processors/qygl/qygl5f6a_processor.go | 48 - .../processors/qygl/qygl5s1i_processor.go | 59 - .../processors/qygl/qygl66sl_processor.go | 53 - .../processors/qygl/qygl6f2d_processor.go | 45 - .../processors/qygl/qygl6s1b_processor.go | 128 - .../processors/qygl/qygl7c1a_processor.go | 61 - .../processors/qygl/qygl7d9a_processor.go | 59 - ...1u9_processor.go => qygl7hbn_processor.go} | 118 +- ...sor_test.go => qygl7hbn_processor_test.go} | 8 +- ...4s6_processor.go => qygl7z0o_processor.go} | 6 +- .../processors/qygl/qygl8261_processor.go | 45 - .../processors/qygl/qygl8271_processor.go | 90 - .../processors/qygl/qygl8848_processor.go | 68 - .../processors/qygl/qygl8b4d_processor.go | 59 - .../processors/qygl/qygl9e2f_processor.go | 59 - .../processors/qygl/qygl9myb_processor.go | 27 + .../processors/qygl/qygl9t1q_processor.go | 55 - .../processors/qygl/qyglalpk_processor.go | 14 + .../processors/qygl/qyglb4c0_processor.go | 105 - .../processors/qygl/qygldj12_processor.go | 67 - .../processors/qygl/qyglj0q1_processor.go | 65 - .../qygl/qyglj1u9_processor_build.go | 10 +- ...h7y_processor.go => qygllucm_processor.go} | 8 +- .../processors/qygl/qyglnio8_processor.go | 46 - .../processors/qygl/qyglp0ht_processor.go | 68 - .../processors/qygl/qygludjg_processor.go | 28 + .../processors/qygl/qygluy3s_processor.go | 56 - ...r76_processor.go => qyglwv7u_processor.go} | 6 +- .../processors/qygl/qyglwyek_processor.go | 28 + .../processors/qygl/reportstore/store.go | 70 + .../processors/shujubao_recursive_parse.go | 58 + .../api/services/processors/test/README.md | 94 - .../processors/test/test_processor.go | 120 - .../api/services/processors/tianyuan_proxy.go | 53 + .../services/processors/validate_tianyuan.go | 18 + .../processors/yysy/yysy09cd_processor.go | 111 - .../processors/yysy/yysy0yyv_processor.go | 24 + .../processors/yysy/yysy35ta_processor.go | 48 - .../processors/yysy/yysy3e7f_processor.go | 44 - .../processors/yysy/yysy3m8s_processor.go | 45 - .../processors/yysy/yysy4b21_processor.go | 45 - .../processors/yysy/yysy4b37_processor.go | 45 - .../processors/yysy/yysy4f2e_processor.go | 62 - .../processors/yysy/yysy6d9a_processor.go | 101 - .../processors/yysy/yysy6f2b_processor.go | 49 - .../processors/yysy/yysy6f2e_processor.go | 58 - .../processors/yysy/yysy7d3e_processor.go | 113 - .../processors/yysy/yysy8b1c_processor.go | 100 - .../processors/yysy/yysy8c2d_processor.go | 47 - .../processors/yysy/yysy8f3a_processor.go | 51 - .../processors/yysy/yysy9a1b_processor.go | 158 - .../processors/yysy/yysy9e4a_processor.go | 57 - .../processors/yysy/yysy9f1b_processor.go | 114 - .../processors/yysy/yysybe08_processor.go | 134 - .../processors/yysy/yysybe08test_processor.go | 82 - .../processors/yysy/yysyc4r9_processor.go | 46 - .../processors/yysy/yysyd50f_processor.go | 51 - .../processors/yysy/yysye7v5_processor.go | 44 - .../processors/yysy/yysyf2t7_processor.go | 49 - .../processors/yysy/yysyf7db_processor.go | 133 - .../processors/yysy/yysyglsf_processor.go | 14 + .../processors/yysy/yysyh6d2_processor.go | 52 - .../processors/yysy/yysyh6f3_processor.go | 48 - .../processors/yysy/yysyjxzf_processor.go | 24 + .../processors/yysy/yysyk8r3_processor.go | 44 - .../processors/yysy/yysyk9r4_processor.go | 49 - .../processors/yysy/yysyktqo_processor.go | 24 + .../processors/yysy/yysyn8di_processor.go | 24 + .../processors/yysy/yysyp0t4_processor.go | 44 - .../processors/yysy/yysyp7pl_processor.go | 24 + .../processors/yysy/yysys66t_processor.go | 24 + .../processors/yysy/yysys9w1_processor.go | 44 - .../processors/yysy/yysyuo7e_processor.go | 24 + .../processors/yysy/yysyxaes_processor.go | 24 + .../processors/yysy/yysyxhho_processor.go | 24 + .../enterprise_info_submit_record_service.go | 114 +- .../tianyuanapi/tianyuanapi_factory.go | 51 + .../tianyuanapi/tianyuanapi_service.go | 285 + .../tianyuanapi/tianyuanapi_service_test.go | 18 + .../http/handlers/qygl_report_handler.go | 20 +- 293 files changed, 2028 insertions(+), 23462 deletions(-) create mode 100644 cmd/product_prune/main.go delete mode 100644 internal/domains/api/services/processors/comb/comb86pm_processor.go delete mode 100644 internal/domains/api/services/processors/comb/combhzy2_processor.go delete mode 100644 internal/domains/api/services/processors/comb/combhzy2_transform.go delete mode 100644 internal/domains/api/services/processors/comb/combwd01_processor.go delete mode 100644 internal/domains/api/services/processors/dwbg/dwbg5sam_processor.go delete mode 100644 internal/domains/api/services/processors/dwbg/dwbg6a2c_processor.go delete mode 100644 internal/domains/api/services/processors/dwbg/dwbg7f3a_processor.go delete mode 100644 internal/domains/api/services/processors/dwbg/dwbg8b4d_processor.go delete mode 100644 internal/domains/api/services/processors/dwbg/dwbg8b4d_processor_test.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg0687_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg0v3b_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg0v4b_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg162a_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg2e8f_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg3a9b_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg3d56_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg54f5_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg5876_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg5a3b_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg5b2e_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg75fe_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg7e8f_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg8a3f_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg8b4d_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg9687_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg970f_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxg9c1d_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxgbc21_processor.go rename internal/domains/api/services/processors/flxg/{flxghb4f_processor.go => flxgc4ct_processor.go} (80%) delete mode 100644 internal/domains/api/services/processors/flxg/flxgc9d1_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxgca3d_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxgdea8_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxgdea9_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxgdec7_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxgdjg3_processor.go create mode 100644 internal/domains/api/services/processors/flxg/flxgji17_processor.go delete mode 100644 internal/domains/api/services/processors/flxg/flxgk5d2_processor.go rename internal/domains/api/services/processors/flxg/{flxgg0s4_processor.go => flxgmmg7_processor.go} (88%) delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz0b03_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz0s0d_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz18hy_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz1c9d_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz1j7h_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz2125_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz28hy_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz2a8b_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz2b2t_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz2c1p_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz2mn6_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz385e_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz38sr_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz3a7f_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz3p9m_processor copy.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz3p9m_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz48sr_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz4e8b_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz5733_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz5a9o_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz5e22_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz5e3f_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz6g7h_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz6m8p_processor.go rename internal/domains/api/services/processors/ivyz/{ivyzvjj6_processor.go => ivyz6w0u_processor.go} (88%) delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz7c9d_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz7f2a_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz7f3a_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz81nc_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz8i9j_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz9363_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz9a2b_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz9d2e_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz9h2m_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz9k2l_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyz9k7f_processor.go create mode 100644 internal/domains/api/services/processors/ivyz/ivyz9ohn_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyza1b3_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyzadee_processor.go rename internal/domains/api/services/processors/ivyz/{ivyzvxf6_processor.go => ivyzbi6f_processor.go} (88%) delete mode 100644 internal/domains/api/services/processors/ivyz/ivyzbpq2_processor.go create mode 100644 internal/domains/api/services/processors/ivyz/ivyzdxmd_processor.go create mode 100644 internal/domains/api/services/processors/ivyz/ivyze42i_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyzfic1_processor.go create mode 100644 internal/domains/api/services/processors/ivyz/ivyzfo5k_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyzgz08_processor.go create mode 100644 internal/domains/api/services/processors/ivyz/ivyzkj31_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyzn2p8_processor.go create mode 100644 internal/domains/api/services/processors/ivyz/ivyzo4rx_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyzocr1_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyzocr2_processor.go rename internal/domains/api/services/processors/ivyz/{ivyzv1o6_processor.go => ivyzoqfb_processor.go} (88%) delete mode 100644 internal/domains/api/services/processors/ivyz/ivyzp2q6_processor.go create mode 100644 internal/domains/api/services/processors/ivyz/ivyzpyso_processor.go create mode 100644 internal/domains/api/services/processors/ivyz/ivyzrht5_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyzsfel_processor.go create mode 100644 internal/domains/api/services/processors/ivyz/ivyzsq0e_processor.go create mode 100644 internal/domains/api/services/processors/ivyz/ivyzwvya_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyzx5q2_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyzx5qz_processor.go create mode 100644 internal/domains/api/services/processors/ivyz/ivyzydqm_processor.go create mode 100644 internal/domains/api/services/processors/ivyz/ivyzyqkx_processor.go delete mode 100644 internal/domains/api/services/processors/ivyz/ivyzzqt3_processor.go create mode 100644 internal/domains/api/services/processors/ivyz/ivyzzscg_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq09j8_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq0a03_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq0b6y_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq0l85_processor.go rename internal/domains/api/services/processors/jrzq/{jrzqv07t_processor.go => jrzq1aij_processor.go} (88%) delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq1d09_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq1e7b_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq1p5g_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq1w4x_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq2f8a_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq3ag6_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq3c7b_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq3c9R_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq3p01_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq4aa8_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq4b6c_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq5e9f_processor.go rename internal/domains/api/services/processors/jrzq/{jrzqbhz4_processor.go => jrzq65zo_processor.go} (88%) delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq6f2a_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq7f1a_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq8203_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq8a2d_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq8b3c_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq8f7c_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq9a1w_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq9d4e_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzq9e2a_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzqacab_processor.go rename internal/domains/api/services/processors/jrzq/{jrzqv4tf_processor.go => jrzqah34_processor.go} (88%) create mode 100644 internal/domains/api/services/processors/jrzq/jrzqbqir_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzqdcbe_processor.go create mode 100644 internal/domains/api/services/processors/jrzq/jrzqdmlo_processor.go rename internal/domains/api/services/processors/jrzq/{jrzqv1o0_processor.go => jrzqi079_processor.go} (88%) rename internal/domains/api/services/processors/jrzq/{jrzqvztf_processor.go => jrzqly6d_processor.go} (88%) create mode 100644 internal/domains/api/services/processors/jrzq/jrzqmdq1_processor.go rename internal/domains/api/services/processors/jrzq/{jrzqvkk6_processor.go => jrzqml9g_processor.go} (88%) rename internal/domains/api/services/processors/jrzq/{jrzqv7md_processor.go => jrzqmlzx_processor.go} (88%) rename internal/domains/api/services/processors/jrzq/{jrzqvzxf_processor.go => jrzqnep0_processor.go} (88%) rename internal/domains/api/services/processors/jrzq/{jrzqvz2y_processor.go => jrzqnk43_processor.go} (88%) rename internal/domains/api/services/processors/jrzq/{jrzqv8v8_processor.go => jrzqnkei_processor.go} (88%) rename internal/domains/api/services/processors/jrzq/{jrzqv5f4_processor.go => jrzqnvm8_processor.go} (88%) delete mode 100644 internal/domains/api/services/processors/jrzq/jrzqo6l7_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzqo7l1_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzqocre_processor.go delete mode 100644 internal/domains/api/services/processors/jrzq/jrzqocry_processor.go create mode 100644 internal/domains/api/services/processors/jrzq/jrzqoicn_processor.go rename internal/domains/api/services/processors/jrzq/{jrzqv3hm_processor.go => jrzqqd4f_processor.go} (88%) rename internal/domains/api/services/processors/jrzq/{jrzqv9v9_processor.go => jrzqqkec_processor.go} (88%) delete mode 100644 internal/domains/api/services/processors/jrzq/jrzqs7g0_processor.go rename internal/domains/api/services/processors/jrzq/{jrzqv0md_processor.go => jrzqtm1v_processor.go} (88%) rename internal/domains/api/services/processors/jrzq/{jrzqv2o1_processor.go => jrzqv7yz_processor.go} (88%) delete mode 100644 internal/domains/api/services/processors/jrzq/jrzqv87m_processor.go rename internal/domains/api/services/processors/jrzq/{jrzqvt43_processor.go => jrzqvbhj_processor.go} (88%) delete mode 100644 internal/domains/api/services/processors/jrzq/jrzqvt72_processor.go rename internal/domains/api/services/processors/jrzq/{jrzqv7d1_processor.go => jrzqx5dm_processor.go} (88%) rename internal/domains/api/services/processors/jrzq/{jrzqvz3y_processor.go => jrzqz05i_processor.go} (88%) delete mode 100644 internal/domains/api/services/processors/pdfg/pdfg01gz_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg1h7y_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg1u4u_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg2t6s_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg3b8z_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg3m7z_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg3y6b_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg3z3l_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg4896_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg4d2e_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg4i1z_processor.go create mode 100644 internal/domains/api/services/processors/qcxg/qcxg521l_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg5f3a_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg5u0z_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg6b4e_processor.go create mode 100644 internal/domains/api/services/processors/qcxg/qcxg76va_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg7a2b_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg8a3d_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg9f5c_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxg9p1c_processor.go create mode 100644 internal/domains/api/services/processors/qcxg/qcxgfv9w_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxggb2q_processor.go create mode 100644 internal/domains/api/services/processors/qcxg/qcxggfww_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxggj3a_processor.go rename internal/domains/api/services/processors/qcxg/{qcxgm4cl_processor.go => qcxgijy3_processor.go} (88%) delete mode 100644 internal/domains/api/services/processors/qcxg/qcxgjj2a_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxgm7r9_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxgp00w_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxgp1w3_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxgu2k4_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxgy7f2_processor.go create mode 100644 internal/domains/api/services/processors/qcxg/qcxgyqdc_processor.go delete mode 100644 internal/domains/api/services/processors/qcxg/qcxgyts2_processor.go create mode 100644 internal/domains/api/services/processors/qcxg/qcxgywsv_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/coment01_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl23t7_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl2acd_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl2b5c_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl2nao_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl2s0w_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl3f8e_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl45bd_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl4b2e_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl5a3c_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl5a9t_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl5cmp_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl5f6a_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl5s1i_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl66sl_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl6f2d_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl6s1b_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl7c1a_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl7d9a_processor.go rename internal/domains/api/services/processors/qygl/{qyglj1u9_processor.go => qygl7hbn_processor.go} (53%) rename internal/domains/api/services/processors/qygl/{qyglj1u9_processor_test.go => qygl7hbn_processor_test.go} (83%) rename internal/domains/api/services/processors/qygl/{qyglv4s6_processor.go => qygl7z0o_processor.go} (88%) delete mode 100644 internal/domains/api/services/processors/qygl/qygl8261_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl8271_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl8848_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl8b4d_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl9e2f_processor.go create mode 100644 internal/domains/api/services/processors/qygl/qygl9myb_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygl9t1q_processor.go create mode 100644 internal/domains/api/services/processors/qygl/qyglalpk_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qyglb4c0_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygldj12_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qyglj0q1_processor.go rename internal/domains/api/services/processors/qygl/{qyglbh7y_processor.go => qygllucm_processor.go} (76%) delete mode 100644 internal/domains/api/services/processors/qygl/qyglnio8_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qyglp0ht_processor.go create mode 100644 internal/domains/api/services/processors/qygl/qygludjg_processor.go delete mode 100644 internal/domains/api/services/processors/qygl/qygluy3s_processor.go rename internal/domains/api/services/processors/qygl/{qyglvr76_processor.go => qyglwv7u_processor.go} (87%) create mode 100644 internal/domains/api/services/processors/qygl/qyglwyek_processor.go create mode 100644 internal/domains/api/services/processors/qygl/reportstore/store.go create mode 100644 internal/domains/api/services/processors/shujubao_recursive_parse.go delete mode 100644 internal/domains/api/services/processors/test/README.md delete mode 100644 internal/domains/api/services/processors/test/test_processor.go create mode 100644 internal/domains/api/services/processors/tianyuan_proxy.go create mode 100644 internal/domains/api/services/processors/validate_tianyuan.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy09cd_processor.go create mode 100644 internal/domains/api/services/processors/yysy/yysy0yyv_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy35ta_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy3e7f_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy3m8s_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy4b21_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy4b37_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy4f2e_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy6d9a_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy6f2b_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy6f2e_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy7d3e_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy8b1c_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy8c2d_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy8f3a_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy9a1b_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy9e4a_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysy9f1b_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysybe08_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysybe08test_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysyc4r9_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysyd50f_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysye7v5_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysyf2t7_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysyf7db_processor.go create mode 100644 internal/domains/api/services/processors/yysy/yysyglsf_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysyh6d2_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysyh6f3_processor.go create mode 100644 internal/domains/api/services/processors/yysy/yysyjxzf_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysyk8r3_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysyk9r4_processor.go create mode 100644 internal/domains/api/services/processors/yysy/yysyktqo_processor.go create mode 100644 internal/domains/api/services/processors/yysy/yysyn8di_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysyp0t4_processor.go create mode 100644 internal/domains/api/services/processors/yysy/yysyp7pl_processor.go create mode 100644 internal/domains/api/services/processors/yysy/yysys66t_processor.go delete mode 100644 internal/domains/api/services/processors/yysy/yysys9w1_processor.go create mode 100644 internal/domains/api/services/processors/yysy/yysyuo7e_processor.go create mode 100644 internal/domains/api/services/processors/yysy/yysyxaes_processor.go create mode 100644 internal/domains/api/services/processors/yysy/yysyxhho_processor.go create mode 100644 internal/infrastructure/external/tianyuanapi/tianyuanapi_factory.go create mode 100644 internal/infrastructure/external/tianyuanapi/tianyuanapi_service.go create mode 100644 internal/infrastructure/external/tianyuanapi/tianyuanapi_service_test.go diff --git a/cmd/product_prune/main.go b/cmd/product_prune/main.go new file mode 100644 index 0000000..6b0eca8 --- /dev/null +++ b/cmd/product_prune/main.go @@ -0,0 +1,237 @@ +// 按产品导出 JSON 清理数据库:软删除「导出中已下线」或「不在有效列表」的产品及其目录关联数据。 +// +// go run ./cmd/product_prune -dry-run +// go run ./cmd/product_prune -export ../public_product_export_2026-06-10_163520.json +package main + +import ( + "encoding/json" + "flag" + "fmt" + "log" + "os" + "sort" + "strings" + + "hyapi-server/internal/config" + "hyapi-server/internal/domains/product/entities" + "hyapi-server/internal/infrastructure/database" + + "go.uber.org/zap" + "gorm.io/gorm" +) + +type exportProduct struct { + ID string `json:"id"` + Code string `json:"code"` + DeletedAt *string `json:"deleted_at"` +} + +func main() { + exportPath := flag.String("export", "../public_product_export_2026-06-10_163520.json", "产品导出 JSON 路径") + dryRun := flag.Bool("dry-run", false, "仅统计,不写库") + pruneSubscriptions := flag.Bool("prune-subscriptions", true, "同时软删除指向已清理产品的订阅") + flag.Parse() + + activeCodes, err := loadActiveCodes(*exportPath) + if err != nil { + log.Fatalf("读取导出文件失败: %v", err) + } + log.Printf("导出中有效产品(deleted_at 为空)共 %d 个", len(activeCodes)) + + cfg, err := config.LoadConfig() + if err != nil { + log.Fatalf("加载配置失败: %v", err) + } + + logger, _ := zap.NewProduction() + defer logger.Sync() + + dbCfg := database.Config{ + Host: cfg.Database.Host, + Port: cfg.Database.Port, + User: cfg.Database.User, + Password: cfg.Database.Password, + Name: cfg.Database.Name, + SSLMode: cfg.Database.SSLMode, + Timezone: cfg.Database.Timezone, + MaxOpenConns: cfg.Database.MaxOpenConns, + MaxIdleConns: cfg.Database.MaxIdleConns, + ConnMaxLifetime: cfg.Database.ConnMaxLifetime, + } + dbWrapper, err := database.NewConnection(dbCfg) + if err != nil { + log.Fatalf("连接数据库失败: %v", err) + } + db := dbWrapper.DB + + var products []entities.Product + if err := db.Unscoped().Select("id", "code", "deleted_at").Find(&products).Error; err != nil { + log.Fatalf("查询产品失败: %v", err) + } + + var removeIDs []string + var removeCodes []string + for _, p := range products { + code := strings.TrimSpace(strings.ToUpper(p.Code)) + if code == "" { + removeIDs = append(removeIDs, p.ID) + removeCodes = append(removeCodes, p.Code) + continue + } + if _, ok := activeCodes[code]; !ok { + removeIDs = append(removeIDs, p.ID) + removeCodes = append(removeCodes, p.Code) + } + } + + sort.Strings(removeCodes) + log.Printf("数据库产品总数 %d,待清理 %d", len(products), len(removeIDs)) + if len(removeCodes) > 0 { + limit := len(removeCodes) + if limit > 30 { + limit = 30 + } + log.Printf("待清理产品编号示例(前 %d 个): %s", limit, strings.Join(removeCodes[:limit], ", ")) + } + + if len(removeIDs) == 0 { + log.Println("无需清理") + return + } + + if *dryRun { + log.Println("dry-run 模式,未修改数据库") + printRelatedCounts(db, removeIDs, *pruneSubscriptions) + return + } + + err = db.Transaction(func(tx *gorm.DB) error { + if err := softDeleteByProductOrPackage(tx, &entities.ProductPackageItem{}, removeIDs); err != nil { + return fmt.Errorf("product_package_item: %w", err) + } + if err := softDeleteByProductID(tx, &entities.ProductDocumentation{}, removeIDs); err != nil { + return fmt.Errorf("product_documentation: %w", err) + } + if err := softDeleteByProductID(tx, &entities.ProductApiConfig{}, removeIDs); err != nil { + return fmt.Errorf("product_api_config: %w", err) + } + if err := softDeleteByProductID(tx, &entities.ProductParameter{}, removeIDs); err != nil { + return fmt.Errorf("product_parameter: %w", err) + } + if err := softDeleteByProductID(tx, &entities.ProductUIComponent{}, removeIDs); err != nil { + return fmt.Errorf("product_ui_component: %w", err) + } + if err := softDeleteByProductID(tx, &entities.ComponentReportDownload{}, removeIDs); err != nil { + return fmt.Errorf("component_report_download: %w", err) + } + if *pruneSubscriptions { + if err := softDeleteByProductID(tx, &entities.Subscription{}, removeIDs); err != nil { + return fmt.Errorf("subscription: %w", err) + } + } + res := tx.Where("id IN ?", removeIDs).Delete(&entities.Product{}) + if res.Error != nil { + return fmt.Errorf("product: %w", res.Error) + } + log.Printf("已软删除 product %d 行", res.RowsAffected) + return nil + }) + if err != nil { + log.Fatalf("清理失败: %v", err) + } + log.Println("清理完成") +} + +func loadActiveCodes(path string) (map[string]struct{}, error) { + raw, err := os.ReadFile(path) + if err != nil { + return nil, err + } + var rows []exportProduct + if err := json.Unmarshal(raw, &rows); err != nil { + return nil, err + } + active := make(map[string]struct{}) + for _, r := range rows { + if !isExportActive(r.DeletedAt) { + continue + } + code := strings.TrimSpace(strings.ToUpper(r.Code)) + if code != "" { + active[code] = struct{}{} + } + } + return active, nil +} + +func isExportActive(deletedAt *string) bool { + if deletedAt == nil { + return true + } + s := strings.TrimSpace(*deletedAt) + return s == "" || strings.EqualFold(s, "null") +} + +func softDeleteByProductID(tx *gorm.DB, model interface{}, productIDs []string) error { + if len(productIDs) == 0 { + return nil + } + res := tx.Where("product_id IN ?", productIDs).Delete(model) + if res.Error != nil { + return res.Error + } + if res.RowsAffected > 0 { + log.Printf("已软删除 %T %d 行", model, res.RowsAffected) + } + return nil +} + +func softDeleteByProductOrPackage(tx *gorm.DB, model interface{}, productIDs []string) error { + if len(productIDs) == 0 { + return nil + } + res := tx.Where("product_id IN ? OR package_id IN ?", productIDs, productIDs).Delete(model) + if res.Error != nil { + return res.Error + } + if res.RowsAffected > 0 { + log.Printf("已软删除 %T %d 行", model, res.RowsAffected) + } + return nil +} + +func printRelatedCounts(db *gorm.DB, productIDs []string, subs bool) { + checks := []struct { + name string + fn func() int64 + }{ + {"product_package_item", func() int64 { + var n int64 + db.Model(&entities.ProductPackageItem{}).Where("product_id IN ? OR package_id IN ?", productIDs, productIDs).Count(&n) + return n + }}, + {"product_documentation", countByProduct(db, &entities.ProductDocumentation{}, productIDs)}, + {"product_api_config", countByProduct(db, &entities.ProductApiConfig{}, productIDs)}, + {"product_parameter", countByProduct(db, &entities.ProductParameter{}, productIDs)}, + {"product_ui_component", countByProduct(db, &entities.ProductUIComponent{}, productIDs)}, + {"component_report_download", countByProduct(db, &entities.ComponentReportDownload{}, productIDs)}, + } + if subs { + checks = append(checks, struct { + name string + fn func() int64 + }{"subscription", countByProduct(db, &entities.Subscription{}, productIDs)}) + } + for _, c := range checks { + log.Printf("[dry-run] 关联 %s 约 %d 行", c.name, c.fn()) + } +} + +func countByProduct(db *gorm.DB, model interface{}, productIDs []string) func() int64 { + return func() int64 { + var n int64 + db.Model(model).Where("product_id IN ?", productIDs).Count(&n) + return n + } +} diff --git a/config.yaml b/config.yaml index e256445..743d49c 100644 --- a/config.yaml +++ b/config.yaml @@ -222,8 +222,8 @@ daily_ratelimit: enable_referer: true # 是否检查Referer allowed_referers: # 允许的Referer - - "https://console.haiyudata.com" # 天元API控制台 - - "https://consoletest.haiyudata.com" # 天元API测试控制台 + - "https://console.haiyudata.com" # 天远API控制台 + - "https://consoletest.haiyudata.com" # 天远API测试控制台 enable_proxy_check: false # 是否检查代理 enable_geo_block: false # 是否启用地理位置阻止 @@ -621,6 +621,36 @@ shumai: max_age: 30 compress: true +# =========================================== +# 天远 API 中转(与对外 API 同协议) +# =========================================== +tianyuanapi: + base_url: "https://api.haiyudata.com" + access_id: "请配置中转账号Access-Id" + encryption_key: "请配置十六进制加密密钥" + timeout: 30s + logging: + enabled: true + log_dir: "logs/external_services" + use_daily: true + enable_level_separation: true + level_configs: + info: + max_size: 100 + max_backups: 5 + max_age: 30 + compress: true + error: + max_size: 200 + max_backups: 10 + max_age: 90 + compress: true + warn: + max_size: 100 + max_backups: 5 + max_age: 30 + compress: true + # =========================================== # ✨ 数据宝配置走实时接口 # =========================================== @@ -654,7 +684,6 @@ shujubao: max_age: 30 compress: true - # =========================================== # 🌐 诺尔智汇配置 # =========================================== @@ -687,7 +716,6 @@ nuoer: max_age: 30 compress: true - # =========================================== # ✨ 汇博(BHSC)配置 # =========================================== @@ -725,4 +753,4 @@ huibo: max_size: 100 max_backups: 5 max_age: 30 - compress: true \ No newline at end of file + compress: true diff --git a/internal/application/product/product_application_service_impl.go b/internal/application/product/product_application_service_impl.go index 6836ad8..b2824d0 100644 --- a/internal/application/product/product_application_service_impl.go +++ b/internal/application/product/product_application_service_impl.go @@ -1039,8 +1039,6 @@ func (s *ProductApplicationServiceImpl) getDTOMap() map[string]interface{} { "IVYZ9A2B": &dto.IVYZ9A2BReq{}, "IVYZ7F2A": &dto.IVYZ7F2AReq{}, "IVYZ4E8B": &dto.IVYZ4E8BReq{}, - "IVYZ1C9D": &dto.IVYZ1C9DReq{}, - "IVYZGZ08": &dto.IVYZGZ08Req{}, "FLXG8A3F": &dto.FLXG8A3FReq{}, "FLXG5B2E": &dto.FLXG5B2EReq{}, "COMB298Y": &dto.COMB298YReq{}, @@ -1074,9 +1072,7 @@ func (s *ProductApplicationServiceImpl) getDTOMap() map[string]interface{} { "IVYZ7F3A": &dto.IVYZ7F3AReq{}, "IVYZ3P9M": &dto.IVYZ3P9MReq{}, "IVYZ3A7F": &dto.IVYZ3A7FReq{}, - "IVYZ9D2E": &dto.IVYZ9D2EReq{}, "DWBG7F3A": &dto.DWBG7F3AReq{}, - "YYSY8F3A": &dto.YYSY8F3AReq{}, "QCXG9P1C": &dto.QCXG9P1CReq{}, "JRZQ9E2A": &dto.JRZQ9E2AReq{}, "YYSY9A1B": &dto.YYSY9A1BReq{}, diff --git a/internal/config/config.go b/internal/config/config.go index d591855..8a1bef4 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -40,6 +40,7 @@ type Config struct { Xingwei XingweiConfig `mapstructure:"xingwei"` Jiguang JiguangConfig `mapstructure:"jiguang"` Shumai ShumaiConfig `mapstructure:"shumai"` + Tianyuanapi TianyuanapiConfig `mapstructure:"tianyuanapi"` Shujubao ShujubaoConfig `mapstructure:"shujubao"` Nuoer NuoerConfig `mapstructure:"nuoer"` Huibo HuiboConfig `mapstructure:"huibo"` @@ -656,6 +657,33 @@ type ShumaiLevelFileConfig struct { Compress bool `mapstructure:"compress"` } +// TianyuanapiConfig 天远 API 中转配置 +type TianyuanapiConfig struct { + BaseURL string `mapstructure:"base_url"` + AccessID string `mapstructure:"access_id"` + EncryptionKey string `mapstructure:"encryption_key"` + Timeout time.Duration `mapstructure:"timeout"` + + Logging TianyuanapiLoggingConfig `mapstructure:"logging"` +} + +// TianyuanapiLoggingConfig 天远 API 日志配置 +type TianyuanapiLoggingConfig struct { + Enabled bool `mapstructure:"enabled"` + LogDir string `mapstructure:"log_dir"` + UseDaily bool `mapstructure:"use_daily"` + EnableLevelSeparation bool `mapstructure:"enable_level_separation"` + LevelConfigs map[string]TianyuanapiLevelFileConfig `mapstructure:"level_configs"` +} + +// TianyuanapiLevelFileConfig 天远 API 级别文件配置 +type TianyuanapiLevelFileConfig struct { + MaxSize int `mapstructure:"max_size"` + MaxBackups int `mapstructure:"max_backups"` + MaxAge int `mapstructure:"max_age"` + Compress bool `mapstructure:"compress"` +} + // ShujubaoConfig 数据宝配置 type ShujubaoConfig struct { URL string `mapstructure:"url"` diff --git a/internal/container/container.go b/internal/container/container.go index 2c37aa9..e87d534 100644 --- a/internal/container/container.go +++ b/internal/container/container.go @@ -49,6 +49,7 @@ import ( "hyapi-server/internal/infrastructure/external/sms" "hyapi-server/internal/infrastructure/external/storage" "hyapi-server/internal/infrastructure/external/tianyancha" + "hyapi-server/internal/infrastructure/external/tianyuanapi" "hyapi-server/internal/infrastructure/external/westdex" "hyapi-server/internal/infrastructure/external/xingwei" "hyapi-server/internal/infrastructure/external/yushan" @@ -397,10 +398,14 @@ func NewContainer() *Container { func(cfg *config.Config) (*jiguang.JiguangService, error) { return jiguang.NewJiguangServiceWithConfig(cfg) }, - // ShumaiService - 数脉服务 + // ShumaiService - 数脉服务(保留配置,处理器已改走天远中转) func(cfg *config.Config) (*shumai.ShumaiService, error) { return shumai.NewShumaiServiceWithConfig(cfg) }, + // TianyuanapiService - 天远 API 中转 + func(cfg *config.Config) (*tianyuanapi.TianyuanapiService, error) { + return tianyuanapi.NewTianyuanapiServiceWithConfig(cfg) + }, // ShujubaoService - 数据宝服务 func(cfg *config.Config) (*shujubao.ShujubaoService, error) { return shujubao.NewShujubaoServiceWithConfig(cfg) diff --git a/internal/domains/api/dto/api_request_dto.go b/internal/domains/api/dto/api_request_dto.go index e09ca82..b9ea2f4 100644 --- a/internal/domains/api/dto/api_request_dto.go +++ b/internal/domains/api/dto/api_request_dto.go @@ -105,7 +105,7 @@ type JRZQDCBEReq struct { BankCard string `json:"bank_card" validate:"required,validBankCard"` Name string `json:"name" validate:"required,min=1,validName"` } -type JRZQACABReq struct { +type JRZQOICNReq struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` IDCard string `json:"id_card" validate:"required,validIDCard"` BankCard string `json:"bank_card" validate:"required,validBankCard"` @@ -118,24 +118,24 @@ type QYGL2ACDReq struct { LegalPerson string `json:"legal_person" validate:"required,min=1,validName"` EntCode string `json:"ent_code" validate:"required,validUSCI"` } -type QYGLUY3SReq struct { +type QYGLALPKReq struct { EntName string `json:"ent_name" validate:"omitempty,min=1,validEnterpriseName"` EntRegno string `json:"ent_reg_no" validate:"omitempty"` EntCode string `json:"ent_code" validate:"omitempty,validUSCI"` } -type QYGLJ1U9Req struct { +type QYGL7HBNReq struct { EntName string `json:"ent_name" validate:"required,min=1,validEnterpriseName"` EntCode string `json:"ent_code" validate:"required,validUSCI"` } -type JRZQOCRYReq struct { +type JRZQDMLOReq struct { PhotoData string `json:"photo_data" validate:"required,validBase64Image"` } -type JRZQOCREReq struct { +type JRZQMDQ1Req struct { PhotoData string `json:"photo_data" validate:"omitempty,validBase64Image"` ImageUrl string `json:"image_url" validate:"omitempty,url"` } -type YYSYK9R4Req struct { +type YYSYGLSFReq struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` @@ -145,7 +145,7 @@ type YYSY35TAReq struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type QCXG9F5CReq struct { +type QCXGFV9WReq struct { PlateNo string `json:"plate_no" validate:"required"` } type QCXG3M7ZReq struct { @@ -153,19 +153,19 @@ type QCXG3M7ZReq struct { Name string `json:"name" validate:"required,min=1,validName"` PlateColor string `json:"plate_color" validate:"omitempty"` } -type QCXG3B8ZReq struct { +type QCXG76VAReq struct { PlateNo string `json:"plate_no" validate:"required"` } -type QCXGM7R9Req struct { +type QCXGGFWWReq struct { PlateNo string `json:"plate_no" validate:"required"` } -type QCXGP1W3Req struct { +type QCXGYQDCReq struct { PlateNo string `json:"plate_no" validate:"required"` } -type QCXG5U0ZReq struct { +type QCXG521LReq struct { VinCode string `json:"vin_code" validate:"required"` } -type QCXGU2K4Req struct { +type QCXGYWSVReq struct { PlateNo string `json:"plate_no" validate:"required"` } type QCXGY7F2Req struct { @@ -609,7 +609,7 @@ type YYSY6F2BReq struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type IVYZOCR1Req struct { +type IVYZ9OHNReq struct { PhotoData string `json:"photo_data" validate:"omitempty,validBase64Image"` ImageUrl string `json:"image_url" validate:"omitempty,url"` } @@ -617,12 +617,12 @@ type YYSY8B1CReq struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type QYGLJ0Q1Req struct { +type QYGL9MYBReq struct { EntName string `json:"ent_name" validate:"omitempty,min=1,validEnterpriseName"` EntCode string `json:"ent_code" validate:"omitempty,validUSCI"` } -type IVYZ18HYReq struct { +type IVYZYQKXReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MaritalType string `json:"marital_type" validate:"required" oneof=10 20 30 40` @@ -631,21 +631,21 @@ type IVYZ18HYReq struct { AuthDate string `json:"auth_date" validate:"omitempty"` } -type IVYZ38SRReq struct { +type IVYZRHT5Req struct { ManName string `json:"man_name" validate:"required,min=1,validName"` ManIDCard string `json:"man_id_card" validate:"required,validIDCard"` WomanName string `json:"woman_name" validate:"required,min=1,validName"` WomanIDCard string `json:"woman_id_card" validate:"required,validIDCard"` } -type IVYZ5E22Req struct { +type IVYZPYSOReq struct { ManName string `json:"man_name" validate:"required,min=1,validName"` ManIDCard string `json:"man_id_card" validate:"required,validIDCard"` WomanName string `json:"woman_name" validate:"required,min=1,validName"` WomanIDCard string `json:"woman_id_card" validate:"required,validIDCard"` Authorized string `json:"authorized" validate:"required,oneof=0 1"` } -type IVYZ48SRReq struct { +type IVYZYDQMReq struct { ManName string `json:"man_name" validate:"required,min=1,validName"` ManIDCard string `json:"man_id_card" validate:"required,validIDCard"` WomanName string `json:"woman_name" validate:"required,min=1,validName"` @@ -653,18 +653,21 @@ type IVYZ48SRReq struct { MaritalType string `json:"marital_type" validate:"required" oneof=10 20 30 40` AuthAuthorizeFileCode string `json:"auth_authorize_file_code" validate:"required"` } -type IVYZ28HYReq struct { +type IVYZO4RXReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` } -type FLXGDJG3Req struct { +type FLXGJI17Req struct { IDCard string `json:"id_card" validate:"required,validIDCard"` } -type QYGLDJ12Req struct { +type QYGLUDJGReq struct { EntName string `json:"ent_name" validate:"omitempty,min=1,validEnterpriseName"` EntCode string `json:"ent_code" validate:"omitempty,validUSCI"` EntRegNo string `json:"ent_reg_no" validate:"omitempty"` } + +// QYGLWYEKReq 企业税收违法核查入参(与年报核验字段一致) +type QYGLWYEKReq = QYGLUDJGReq type YYSY6D9AReq struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` IDCard string `json:"id_card" validate:"required,validIDCard"` @@ -983,45 +986,45 @@ type YYSY9E4AReq struct { } // YYSY运营商相关API DTO -type YYSY3M8SReq struct { +type YYSY0YYVReq struct { Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type YYSYC4R9Req struct { +type YYSYS66TReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type YYSYH6D2Req struct { +type YYSYN8DIReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type YYSYH6F3Req struct { +type YYSYXHHOReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type YYSYP0T4Req struct { +type YYSYUO7EReq struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type YYSYE7V5Req struct { +type YYSYKTQOReq struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type YYSYS9W1Req struct { +type YYSYXAESReq struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type YYSYK8R3Req struct { +type YYSYJXZFReq struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type YYSYF2T7Req struct { +type YYSYP7PLReq struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` DateRange string `json:"date_range" validate:"required,validDateRange"` } @@ -1037,18 +1040,18 @@ type IVYZ3M8SReq struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type IVYZ9K7FReq struct { +type IVYZSQ0EReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` } -type IVYZA1B3Req struct { +type IVYZE42IReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` PhotoData string `json:"photo_data" validate:"required,validBase64Image"` } -type IVYZFIC1Req struct { +type IVYZDXMDReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` PhotoData string `json:"photo_data" validate:"omitempty,validBase64Image"` @@ -1065,11 +1068,11 @@ type IVYZP0T4Req struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type IVYZX5QZReq struct { +type IVYZWVYAReq struct { ReturnURL string `json:"return_url" validate:"required,validReturnURL"` } -type IVYZX5Q2Req struct { +type IVYZKJ31Req struct { Token string `json:"token" validate:"required"` } @@ -1080,69 +1083,69 @@ type JRZQ1P5GReq struct { AuthAuthorizeFileCode string `json:"auth_authorize_file_code" validate:"required"` } -type JRZQBHZ4Req struct { +type JRZQ65ZOReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type QCXGM4CLReq struct { +type QCXGIJY3Req struct { IDCard string `json:"id_card" validate:"required,validIDCard"` } -type JRZQV8V8Req struct { +type JRZQNKEIReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQV9V9Req struct { +type JRZQQKECReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQV1O0Req struct { +type JRZQI079Req struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQV2O1Req struct { +type JRZQV7YZReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type IVYZV1O6Req struct { +type IVYZOQFBReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` } -type QYGLV4S6Req struct { +type QYGL7Z0OReq struct { EntCode string `json:"ent_code" validate:"required,validUSCI"` EntName string `json:"ent_name" validate:"required,min=1,validEnterpriseName"` } -type JRZQV7D1Req struct { +type JRZQX5DMReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQV07TReq struct { +type JRZQ1AIJReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQVZ3YReq struct { +type JRZQZ05IReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQVZ2YReq struct { +type JRZQNK43Req struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` @@ -1154,91 +1157,91 @@ type JRZQVT72Req struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQV5F4Req struct { +type JRZQNVM8Req struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type QYGLVR76Req struct { +type QYGLWV7UReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` } -type IVYZVXF6Req struct { +type IVYZBI6FReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type IVYZVJJ6Req struct { +type IVYZ6W0UReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQV7MDReq struct { +type JRZQMLZXReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQV3HMReq struct { +type JRZQQD4FReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQVT43Req struct { +type JRZQVBHJReq struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQV87MReq struct { +type JRZQBQIRReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQV0MDReq struct { +type JRZQTM1VReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQVZXFReq struct { +type JRZQNEP0Req struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type FLXGG0S4Req struct { +type FLXGMMG7Req struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` } -type JRZQVZTFReq struct { +type JRZQLY6DReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQV4TFReq struct { +type JRZQAH34Req struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type JRZQVKK6Req struct { +type JRZQML9GReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` } -type FLXGHB4FReq struct { +type FLXGC4CTReq struct { IDCard string `json:"id_card" validate:"required,validIDCard"` Name string `json:"name" validate:"required,min=1,validName"` AuthPDFBase64 string `json:"auth_pdf_base64" validate:"required,validAuthPDFBase64"` } -type QYGLBH7YReq struct { +type QYGLLUCMReq struct { EntName string `json:"ent_name" validate:"required,min=1,validEnterpriseName"` AuthPDFBase64 string `json:"auth_pdf_base64" validate:"required,validAuthPDFBase64"` } diff --git a/internal/domains/api/services/api_request_service.go b/internal/domains/api/services/api_request_service.go index a36eca3..95b298e 100644 --- a/internal/domains/api/services/api_request_service.go +++ b/internal/domains/api/services/api_request_service.go @@ -10,14 +10,11 @@ import ( api_repositories "hyapi-server/internal/domains/api/repositories" "hyapi-server/internal/domains/api/services/processors" "hyapi-server/internal/domains/api/services/processors/comb" - "hyapi-server/internal/domains/api/services/processors/dwbg" "hyapi-server/internal/domains/api/services/processors/flxg" "hyapi-server/internal/domains/api/services/processors/ivyz" "hyapi-server/internal/domains/api/services/processors/jrzq" - "hyapi-server/internal/domains/api/services/processors/pdfg" "hyapi-server/internal/domains/api/services/processors/qcxg" "hyapi-server/internal/domains/api/services/processors/qygl" - "hyapi-server/internal/domains/api/services/processors/test" "hyapi-server/internal/domains/api/services/processors/yysy" "hyapi-server/internal/domains/product/services" "hyapi-server/internal/infrastructure/external/alicloud" @@ -26,7 +23,7 @@ import ( "hyapi-server/internal/infrastructure/external/muzi" nuoerext "hyapi-server/internal/infrastructure/external/nuoer" "hyapi-server/internal/infrastructure/external/shujubao" - "hyapi-server/internal/infrastructure/external/shumai" + "hyapi-server/internal/infrastructure/external/tianyuanapi" "hyapi-server/internal/infrastructure/external/tianyancha" "hyapi-server/internal/infrastructure/external/westdex" "hyapi-server/internal/infrastructure/external/xingwei" @@ -67,7 +64,7 @@ func NewApiRequestService( zhichaService *zhicha.ZhichaService, xingweiService *xingwei.XingweiService, jiguangService *jiguang.JiguangService, - shumaiService *shumai.ShumaiService, + tianyuanapiService *tianyuanapi.TianyuanapiService, nuoerService *nuoerext.NuoerService, huiboService *huibo.HuiboService, validator interfaces.RequestValidator, @@ -84,7 +81,7 @@ func NewApiRequestService( zhichaService, xingweiService, jiguangService, - shumaiService, + tianyuanapiService, nuoerService, huiboService, validator, @@ -106,7 +103,7 @@ func NewApiRequestServiceWithRepos( zhichaService *zhicha.ZhichaService, xingweiService *xingwei.XingweiService, jiguangService *jiguang.JiguangService, - shumaiService *shumai.ShumaiService, + tianyuanapiService *tianyuanapi.TianyuanapiService, nuoerService *nuoerext.NuoerService, huiboService *huibo.HuiboService, validator interfaces.RequestValidator, @@ -134,7 +131,7 @@ func NewApiRequestServiceWithRepos( zhichaService, xingweiService, jiguangService, - shumaiService, + tianyuanapiService, nuoerService, huiboService, validator, @@ -166,256 +163,88 @@ func registerAllProcessors(combService *comb.CombService) { // 定义所有处理器映射 processorMap := map[string]processors.ProcessorFunc{ // FLXG系列处理器 - "FLXG0V3B": flxg.ProcessFLXG0V3Bequest, - "FLXG0V4B": flxg.ProcessFLXG0V4BRequest, - "FLXG162A": flxg.ProcessFLXG162ARequest, - "FLXG3D56": flxg.ProcessFLXG3D56Request, - "FLXG54F5": flxg.ProcessFLXG54F5Request, - "FLXG5876": flxg.ProcessFLXG5876Request, - "FLXG75FE": flxg.ProcessFLXG75FERequest, - "FLXG9687": flxg.ProcessFLXG9687Request, - "FLXG970F": flxg.ProcessFLXG970FRequest, - "FLXGC9D1": flxg.ProcessFLXGC9D1Request, - "FLXGCA3D": flxg.ProcessFLXGCA3DRequest, - "FLXGDEC7": flxg.ProcessFLXGDEC7Request, - "FLXG8A3F": flxg.ProcessFLXG8A3FRequest, - "FLXG5B2E": flxg.ProcessFLXG5B2ERequest, - "FLXG0687": flxg.ProcessFLXG0687Request, - "FLXGBC21": flxg.ProcessFLXGBC21Request, - "FLXGDEA8": flxg.ProcessFLXGDEA8Request, - "FLXGDEA9": flxg.ProcessFLXGDEA9Request, - "FLXG5A3B": flxg.ProcessFLXG5A3BRequest, - "FLXG9C1D": flxg.ProcessFLXG9C1DRequest, - "FLXG2E8F": flxg.ProcessFLXG2E8FRequest, - "FLXG7E8F": flxg.ProcessFLXG7E8FRequest, - "FLXG3A9B": flxg.ProcessFLXG3A9BRequest, - "FLXGK5D2": flxg.ProcessFLXGK5D2Request, - "FLXGDJG3": flxg.ProcessFLXGDJG3Request, //董监高司法综合信息核验 - "FLXGG0S4": flxg.ProcessFLXGG0S4Request, //个人诉讼定制版 - "FLXGHB4F": flxg.ProcessFLXGHB4FRequest, //个人涉诉案件查询汇博 + "FLXGJI17": flxg.ProcessFLXGJI17Request, //董监高司法综合信息核验 + "FLXGMMG7": flxg.ProcessFLXGMMG7Request, //个人诉讼定制版 + "FLXGC4CT": flxg.ProcessFLXGC4CTRequest, //个人涉诉案件查询汇博 // JRZQ系列处理器 - "JRZQ8203": jrzq.ProcessJRZQ8203Request, - "JRZQ0A03": jrzq.ProcessJRZQ0A03Request, - "JRZQ4AA8": jrzq.ProcessJRZQ4AA8Request, - "JRZQDCBE": jrzq.ProcessJRZQDCBERequest, - "JRZQACAB": jrzq.ProcessJRZQACABERequest, // 银行卡四要素 - "JRZQ09J8": jrzq.ProcessJRZQ09J8Request, - "JRZQ1D09": jrzq.ProcessJRZQ1D09Request, - "JRZQ3C7B": jrzq.ProcessJRZQ3C7BRequest, - "JRZQ8A2D": jrzq.ProcessJRZQ8A2DRequest, - "JRZQ5E9F": jrzq.ProcessJRZQ5E9FRequest, - "JRZQ4B6C": jrzq.ProcessJRZQ4B6CRequest, - "JRZQ7F1A": jrzq.ProcessJRZQ7F1ARequest, - "JRZQ9E2A": jrzq.ProcessJRZQ9E2ARequest, - "JRZQ6F2A": jrzq.ProcessJRZQ6F2ARequest, - "JRZQ8B3C": jrzq.ProcessJRZQ8B3CRequest, - "JRZQ9D4E": jrzq.ProcessJRZQ9D4ERequest, - "JRZQ0L85": jrzq.ProcessJRZQ0L85Request, - "JRZQ2F8A": jrzq.ProcessJRZQ2F8ARequest, - "JRZQ1E7B": jrzq.ProcessJRZQ1E7BRequest, - "JRZQ3C9R": jrzq.ProcessJRZQ3C9RRequest, - "JRZQ0B6Y": jrzq.ProcessJRZQ0B6YRequest, - "JRZQ9A1W": jrzq.ProcessJRZQ9A1WRequest, - "JRZQ8F7C": jrzq.ProcessJRZQ8F7CRequest, - "JRZQ1W4X": jrzq.ProcessJRZQ1W4XRequest, - "JRZQ3P01": jrzq.ProcessJRZQ3P01Request, - "JRZQ3AG6": jrzq.ProcessJRZQ3AG6Request, - "JRZQO6L7": jrzq.ProcessJRZQO6L7Request, // 全国自然人经济特征评分模型v3 简版 - "JRZQO7L1": jrzq.ProcessJRZQO7L1Request, // 全国自然人经济特征评分模型v4 详版 - "JRZQS7G0": jrzq.ProcessJRZQS7G0Request, // 社保综合评分V1 - "JRZQ1P5G": jrzq.ProcessJRZQ1P5GRequest, // 全国自然人借贷压力指数查询(2) - "JRZQOCRE": jrzq.ProcessJRZQOCREERequest, // 银行卡OCR数卖 - "JRZQOCRY": jrzq.ProcessJRZQOCRYERequest, // 银行卡OCR数据宝 - "JRZQBHZ4": jrzq.ProcessJRZQBHZ4Request, // 支付行为指数诺尔 - "JRZQV8V8": jrzq.ProcessJRZQV8V8Request, //风险量级V8 - "JRZQV9V9": jrzq.ProcessJRZQV9V9Request, //风险量级V9 - "JRZQV1O0": jrzq.ProcessJRZQV1O0Request, //风险量级V10 - "JRZQV2O1": jrzq.ProcessJRZQV2O1Request, //信用全景V21 - "JRZQV7D1": jrzq.ProcessJRZQV7D1Request, //借贷意向验证 - "JRZQV07T": jrzq.ProcessJRZQV07TRequest, //洞侦多头履约行为 - "JRZQVZ3Y": jrzq.ProcessJRZQVZ3YRequest, //租赁申请意向 - "JRZQVZ2Y": jrzq.ProcessJRZQVZ2YRequest, //租赁申请意向V22 - "JRZQV5F4": jrzq.ProcessJRZQV5F4Request, //风险变量V5F4 - "JRZQV7MD": jrzq.ProcessJRZQV7MDRequest, //特殊名单 - "JRZQV3HM": jrzq.ProcessJRZQV3HMRequest, //债务逾期黑名单V3_1 - "JRZQVT43": jrzq.ProcessJRZQVT43Request, //投诉风险筛查V709 - "JRZQV87M": jrzq.ProcessJRZQV87MReqest, //黑名单V110_c10 - "JRZQV0MD": jrzq.ProcessJRZQV0MDRequest, //特殊名单1010 - "JRZQVZXF": jrzq.ProcessJRZQVZXFRequest, //智享分 - "JRZQVZTF": jrzq.ProcessJRZQVZTFRequest, //智瞳-通用版 - "JRZQV4TF": jrzq.ProcessJRZQV4TFRequest, //智瞳分尊享版 - "JRZQVKK6": jrzq.ProcessJRZQVKK6Request, //坤羽模型V3-标签版 + "JRZQOICN": jrzq.ProcessJRZQOICNRequest, // 银行卡四要素 + "JRZQMDQ1": jrzq.ProcessJRZQMDQ1Request, // 银行卡OCR数卖 + "JRZQDMLO": jrzq.ProcessJRZQDMLORequest, // 银行卡OCR数据宝 + "JRZQ65ZO": jrzq.ProcessJRZQ65ZORequest, // 支付行为指数诺尔 + "JRZQNKEI": jrzq.ProcessJRZQNKEIRequest, //风险量级V8 + "JRZQQKEC": jrzq.ProcessJRZQQKECRequest, //风险量级V9 + "JRZQI079": jrzq.ProcessJRZQI079Request, //风险量级V10 + "JRZQV7YZ": jrzq.ProcessJRZQV7YZRequest, //信用全景V21 + "JRZQX5DM": jrzq.ProcessJRZQX5DMRequest, //借贷意向验证 + "JRZQ1AIJ": jrzq.ProcessJRZQ1AIJRequest, //洞侦多头履约行为 + "JRZQZ05I": jrzq.ProcessJRZQZ05IRequest, //租赁申请意向 + "JRZQNK43": jrzq.ProcessJRZQNK43Request, //租赁申请意向V22 + "JRZQNVM8": jrzq.ProcessJRZQNVM8Request, //风险变量V5F4 + "JRZQMLZX": jrzq.ProcessJRZQMLZXRequest, //特殊名单 + "JRZQQD4F": jrzq.ProcessJRZQQD4FRequest, //债务逾期黑名单V3_1 + "JRZQVBHJ": jrzq.ProcessJRZQVBHJRequest, //投诉风险筛查V709 + "JRZQBQIR": jrzq.ProcessJRZQBQIRRequest, //黑名单V110_c10 + "JRZQTM1V": jrzq.ProcessJRZQTM1VRequest, //特殊名单1010 + "JRZQNEP0": jrzq.ProcessJRZQNEP0Request, //智享分 + "JRZQLY6D": jrzq.ProcessJRZQLY6DRequest, //智瞳-通用版 + "JRZQAH34": jrzq.ProcessJRZQAH34Request, //智瞳分尊享版 + "JRZQML9G": jrzq.ProcessJRZQML9GRequest, //坤羽模型V3-标签版 // QYGL系列处理器 - "QYGL8261": qygl.ProcessQYGL8261Request, - "QYGL2ACD": qygl.ProcessQYGL2ACDRequest, - "QYGL45BD": qygl.ProcessQYGL45BDRequest, - "QYGL6F2D": qygl.ProcessQYGL6F2DRequest, - "QYGL8271": qygl.ProcessQYGL8271Request, - "QYGLB4C0": qygl.ProcessQYGLB4C0Request, - "QYGL23T7": qygl.ProcessQYGL23T7Request, // 企业三要素验证 - "QYGL5A3C": qygl.ProcessQYGL5A3CRequest, // 对外投资历史 - "QYGL8B4D": qygl.ProcessQYGL8B4DRequest, // 融资历史 - "QYGL9E2F": qygl.ProcessQYGL9E2FRequest, // 行政处罚 - "QYGL7C1A": qygl.ProcessQYGL7C1ARequest, // 经营异常 - "QYGL3F8E": qygl.ProcessQYGL3F8ERequest, // 人企关系加强版 - "QYGL7D9A": qygl.ProcessQYGL7D9ARequest, // 欠税公告 - "QYGL4B2E": qygl.ProcessQYGL4B2ERequest, // 税收违法 - "COMENT01": qygl.ProcessCOMENT01Request, // 企业风险报告 - "QYGL5F6A": qygl.ProcessQYGL5F6ARequest, // 企业相关查询 - "QYGL2B5C": qygl.ProcessQYGL2B5CRequest, // 企业联系人实际经营地址 - "QYGL6S1B": qygl.ProcessQYGL6S1BRequest, //董监高司法综合信息核验 - "QYGL9T1Q": qygl.ProcessQYGL9T1QRequest, //全国企业借贷意向验证查询_V1 - "QYGL5A9T": qygl.ProcessQYGL5A9TRequest, //全国企业各类工商风险统计数量查询 - "QYGL2S0W": qygl.ProcessQYGL2S0WRequest, //失信被执行企业个人查询 - "QYGL5CMP": qygl.ProcessQYGL5CMPRequest, //企业五要素验证 - "QYGL66SL": qygl.ProcessQYGL66SLRequest, //全国企业司法模型服务查询_V1 - "QYGL2NAO": qygl.ProcessQYGL2naoRequest, //股权变更 - "QYGLNIO8": qygl.ProcessQYGLNIO8Request, //企业基本信息 - "QYGLP0HT": qygl.ProcessQYGLP0HTRequest, //股权穿透 - "QYGL5S1I": qygl.ProcessQYGL5S1IRequest, //企业司法涉诉I - "QYGLJ1U9": qygl.ProcessQYGLJ1U9Request, //企业全景报告(聚合 QYGLUY3S/QYGLJ0Q1/QYGL5S1I) - "QYGLJ0Q1": qygl.ProcessQYGLJ0Q1Request, //企业股权结构全景查询 - "QYGLUY3S": qygl.ProcessQYGLUY3SRequest, //企业经营状态全景查询 - "QYGLDJ12": qygl.ProcessQYGLDJ12Request, //企业年报信息核验 - "QYGL8848": qygl.ProcessQYGL8848Request, //企业税收违法核查 - "QYGLVR76": qygl.ProcessQYGLVR76Request, //人企关联 - "QYGLV4S6": qygl.ProcessQYGLV4S6Request, //企业诉讼定制版 - "QYGLBH7Y": qygl.ProcessQYGLBH7YRequest, //企业案件查询汇博 + "QYGL7HBN": qygl.ProcessQYGL7HBNRequest, //企业全景报告(聚合 QYGLUY3S/QYGLJ0Q1/QYGL5S1I) + "QYGL9MYB": qygl.ProcessQYGL9MYBRequest, //企业股权结构全景查询 + "QYGLALPK": qygl.ProcessQYGLALPKRequest, //企业经营状态全景查询 + "QYGLUDJG": qygl.ProcessQYGLUDJGRequest, //企业年报信息核验 + "QYGLWYEK": qygl.ProcessQYGLWYEKRequest, //企业税收违法核查 + "QYGLWV7U": qygl.ProcessQYGLWV7URequest, //人企关联 + "QYGL7Z0O": qygl.ProcessQYGL7Z0ORequest, //企业诉讼定制版 + "QYGLLUCM": qygl.ProcessQYGLLUCMRequest, //企业案件查询汇博 // YYSY系列处理器 - "YYSY35TA": yysy.ProcessYYSY35TARequest, //运营商归属地数卖 - "YYSYD50F": yysy.ProcessYYSYD50FRequest, - "YYSY09CD": yysy.ProcessYYSY09CDRequest, - "YYSY4B21": yysy.ProcessYYSY4B21Request, - "YYSY4B37": yysy.ProcessYYSY4B37Request, - "YYSY6F2E": yysy.ProcessYYSY6F2ERequest, - "YYSYBE08": yysy.ProcessYYSYBE08Request, - "YYSYBE08TEST": yysy.ProcessYYSYBE08testRequest, // 二要素(阿里云市场),与 YYSYBE08 入参一致 - "YYSYF7DB": yysy.ProcessYYSYF7DBRequest, - "YYSY4F2E": yysy.ProcessYYSY4F2ERequest, - "YYSY8B1C": yysy.ProcessYYSY8B1CRequest, - "YYSY6D9A": yysy.ProcessYYSY6D9ARequest, - "YYSY3E7F": yysy.ProcessYYSY3E7FRequest, - "YYSY8F3A": yysy.ProcessYYSY8F3ARequest, - "YYSY9A1B": yysy.ProcessYYSY9A1BRequest, - "YYSY8C2D": yysy.ProcessYYSY8C2DRequest, - "YYSY7D3E": yysy.ProcessYYSY7D3ERequest, - "YYSY9E4A": yysy.ProcessYYSY9E4ARequest, - "YYSY9F1B": yysy.ProcessYYSY9F1BYequest, - "YYSY6F2B": yysy.ProcessYYSY6F2BRequest, - "YYSY3M8S": yysy.ProcessYYSY3M8SRequest, //运营商二要素查询 - "YYSYC4R9": yysy.ProcessYYSYC4R9Request, //运营商三要素详版查询 - "YYSYH6D2": yysy.ProcessYYSYH6D2Request, //运营商三要素简版查询 - "YYSYP0T4": yysy.ProcessYYSYP0T4Request, //在网时长查询 - "YYSYE7V5": yysy.ProcessYYSYE7V5Request, //手机在网状态查询 - "YYSYS9W1": yysy.ProcessYYSYS9W1Request, //手机携号转网查询 - "YYSYK8R3": yysy.ProcessYYSYK8R3Request, //手机空号检测查询 - "YYSYH6F3": yysy.ProcessYYSYH6F3Request, //运营商三要素即时版查询 - "YYSYK9R4": yysy.ProcessYYSYK9R4Request, //全网手机三要素验证1979周更新版 - "YYSYF2T7": yysy.ProcessYYSYF2T7Request, //手机二次放号检测查询 + "YYSY0YYV": yysy.ProcessYYSY0YYVRequest, //运营商二要素查询 + "YYSYS66T": yysy.ProcessYYSYS66TRequest, //运营商三要素详版查询 + "YYSYN8DI": yysy.ProcessYYSYN8DIRequest, //运营商三要素简版查询 + "YYSYUO7E": yysy.ProcessYYSYUO7ERequest, //在网时长查询 + "YYSYKTQO": yysy.ProcessYYSYKTQORequest, //手机在网状态查询 + "YYSYXAES": yysy.ProcessYYSYXAESRequest, //手机携号转网查询 + "YYSYJXZF": yysy.ProcessYYSYJXZFRequest, //手机空号检测查询 + "YYSYXHHO": yysy.ProcessYYSYXHHORequest, //运营商三要素即时版查询 + "YYSYGLSF": yysy.ProcessYYSYGLSFRequest, //全网手机三要素验证1979周更新版 + "YYSYP7PL": yysy.ProcessYYSYP7PLRequest, //手机二次放号检测查询 // IVYZ系列处理器 - "IVYZ0B03": ivyz.ProcessIVYZ0B03Request, - "IVYZ2125": ivyz.ProcessIVYZ2125Request, - "IVYZ385E": ivyz.ProcessIVYZ385ERequest, - "IVYZ5733": ivyz.ProcessIVYZ5733Request, - "IVYZ9363": ivyz.ProcessIVYZ9363Request, - "IVYZ9A2B": ivyz.ProcessIVYZ9A2BRequest, - "IVYZADEE": ivyz.ProcessIVYZADEERequest, - "IVYZ7F2A": ivyz.ProcessIVYZ7F2ARequest, - "IVYZ4E8B": ivyz.ProcessIVYZ4E8BRequest, - "IVYZ1C9D": ivyz.ProcessIVYZ1C9DRequest, - "IVYZGZ08": ivyz.ProcessIVYZGZ08Request, - "IVYZ2A8B": ivyz.ProcessIVYZ2A8BRequest, - "IVYZ7C9D": ivyz.ProcessIVYZ7C9DRequest, - "IVYZ5E3F": ivyz.ProcessIVYZ5E3FRequest, - "IVYZ7F3A": ivyz.ProcessIVYZ7F3ARequest, - "IVYZ3P9M": ivyz.ProcessIVYZ3P9MRequest, - "IVYZ3A7F": ivyz.ProcessIVYZ3A7FRequest, - "IVYZ9D2E": ivyz.ProcessIVYZ9D2ERequest, - "IVYZ81NC": ivyz.ProcessIVYZ81NCRequest, - "IVYZ2MN6": ivyz.ProcessIVYZ2MN6Request, - "IVYZ6G7H": ivyz.ProcessIVYZ6G7HRequest, - "IVYZ8I9J": ivyz.ProcessIVYZ8I9JRequest, - "IVYZ9K2L": ivyz.ProcessIVYZ9K2LRequest, - "IVYZ2C1P": ivyz.ProcessIVYZ2C1PRequest, - "IVYZP2Q6": ivyz.ProcessIVYZP2Q6Request, - "IVYZ2B2T": ivyz.ProcessIVYZ2B2TRequest, //能力资质核验(学历) - "IVYZ5A9O": ivyz.ProcessIVYZ5A9ORequest, //全国⾃然⼈⻛险评估评分模型 - "IVYZ6M8P": ivyz.ProcessIVYZ6M8PRequest, //职业资格证书 - "IVYZ9H2M": ivyz.ProcessIVYZ9H2MRequest, //极光个人婚姻查询(V2版) - "IVYZZQT3": ivyz.ProcessIVYZZQT3Request, //人脸比对V3 - "IVYZBPQ2": ivyz.ProcessIVYZBPQ2Request, //人脸比对V2 - "IVYZSFEL": ivyz.ProcessIVYZSFELRequest, //全国自然人人像三要素核验_V1 - "IVYZ0S0D": ivyz.ProcessIVYZ0S0DRequest, //劳动仲裁信息查询(个人版) - "IVYZ1J7H": ivyz.ProcessIVYZ1J7HRequest, //行驶证核查v2 - "IVYZ9K7F": ivyz.ProcessIVYZ9K7FRequest, //身份证实名认证即时版 - "IVYZA1B3": ivyz.ProcessIVYZA1B3Request, //公安三要素人脸识别 - "IVYZFIC1": ivyz.ProcessIVYZFIC1Request, //人脸身份证比对(数脉) - "IVYZN2P8": ivyz.ProcessIVYZN2P8Request, //身份证实名认证政务版 - "IVYZX5QZ": ivyz.ProcessIVYZX5QZRequest, //活体检测 - "IVYZX5Q2": ivyz.ProcessIVYZX5Q2Request, //活体识别步骤二 - "IVYZOCR1": ivyz.ProcessIVYZOCR1Request, //身份证OCR - "IVYZOCR2": ivyz.ProcessIVYZOCR2Request, //身份证OCR2数卖 - "IVYZ18HY": ivyz.ProcessIVYZ18HYRequest, //婚姻状况核验V2(单人) - "IVYZ28HY": ivyz.ProcessIVYZ28HYRequest, //婚姻状况核验(单人) - "IVYZ38SR": ivyz.ProcessIVYZ38SRRequest, //婚姻状态核验(双人) - "IVYZ48SR": ivyz.ProcessIVYZ48SRRequest, //婚姻状态核验V2(双人) - "IVYZ5E22": ivyz.ProcessIVYZ5E22Request, //双人婚姻评估查询zhicha版本 - "IVYZV1O6": ivyz.ProcessIVYZV1O6Request, //身份风险V106 - "IVYZVXF6": ivyz.ProcessIVYZVXF6Request, //消费能力 - "IVYZVJJ6": ivyz.ProcessIVYZVJJ6Request, //收入等级 + "IVYZSQ0E": ivyz.ProcessIVYZSQ0ERequest, //身份证实名认证即时版 + "IVYZE42I": ivyz.ProcessIVYZE42IRequest, //公安三要素人脸识别 + "IVYZDXMD": ivyz.ProcessIVYZDXMDRequest, //人脸身份证比对(数脉) + "IVYZFO5K": ivyz.ProcessIVYZFO5KRequest, //身份证实名认证政务版 + "IVYZWVYA": ivyz.ProcessIVYZWVYARequest, //活体检测 + "IVYZKJ31": ivyz.ProcessIVYZKJ31Request, //活体识别步骤二 + "IVYZ9OHN": ivyz.ProcessIVYZ9OHNRequest, //身份证OCR + "IVYZZSCG": ivyz.ProcessIVYZZSCGRequest, //身份证OCR2数卖 + "IVYZYQKX": ivyz.ProcessIVYZYQKXRequest, //婚姻状况核验V2(单人) + "IVYZO4RX": ivyz.ProcessIVYZO4RXRequest, //婚姻状况核验(单人) + "IVYZRHT5": ivyz.ProcessIVYZRHT5Request, //婚姻状态核验(双人) + "IVYZYDQM": ivyz.ProcessIVYZYDQMRequest, //婚姻状态核验V2(双人) + "IVYZPYSO": ivyz.ProcessIVYZPYSORequest, //双人婚姻评估查询zhicha版本 + "IVYZOQFB": ivyz.ProcessIVYZOQFBRequest, //身份风险V106 + "IVYZBI6F": ivyz.ProcessIVYZBI6FRequest, //消费能力 + "IVYZ6W0U": ivyz.ProcessIVYZ6W0URequest, //收入等级 // COMB系列处理器 - 只注册有自定义逻辑的组合包 - "COMB86PM": comb.ProcessCOMB86PMRequest, // 有自定义逻辑:重命名ApiCode - "COMBHZY2": comb.ProcessCOMBHZY2Request, // 自定义处理:生成合规报告 - "COMBWD01": comb.ProcessCOMBWD01Request, // 自定义处理:将返回结构从数组改为对象 // QCXG系列处理器 - "QCXG7A2B": qcxg.ProcessQCXG7A2BRequest, - "QCXG9P1C": qcxg.ProcessQCXG9P1CRequest, - "QCXG8A3D": qcxg.ProcessQCXG8A3DRequest, - "QCXG6B4E": qcxg.ProcessQCXG6B4ERequest, - "QCXG4896": qcxg.ProcessQCXG4896Request, - "QCXG5F3A": qcxg.ProcessQCXG5F3ARequest, // 极光个人车辆查询 - "QCXG4D2E": qcxg.ProcessQCXG4D2ERequest, // 极光名下车辆数量查询 - "QCXGJJ2A": qcxg.ProcessQCXGJJ2ARequest, // vin码查车辆信息(一对多) - "QCXGGJ3A": qcxg.ProcessQCXGGJ3ARequest, // 车辆vin码查询号牌 - "QCXGYTS2": qcxg.ProcessQCXGYTS2Request, // 车辆二要素核验v2 - "QCXGP00W": qcxg.ProcessQCXGP00WRequest, // 车辆出险详版查询 - "QCXGGB2Q": qcxg.ProcessQCXGGB2QRequest, // 车辆二要素核验V1 - "QCXG4I1Z": qcxg.ProcessQCXG4I1ZRequest, // 车辆过户详版查询 - "QCXG1H7Y": qcxg.ProcessQCXG1H7YRequest, // 车辆过户简版查询 - "QCXG3Z3L": qcxg.ProcessQCXG3Z3LRequest, // 车辆维保详细版查询 - "QCXG3Y6B": qcxg.ProcessQCXG3Y6BRequest, // 车辆维保简版查询 - "QCXG2T6S": qcxg.ProcessQCXG2T6SRequest, // 车辆里程记录(品牌查询) - "QCXG1U4U": qcxg.ProcessQCXG1U4URequest, // - "QCXG9F5C": qcxg.ProcessQCXG9F5CERequest, //疑似营运车辆注册平台数 10386 - "QCXG3B8Z": qcxg.ProcessQCXG3B8ZRequest, //疑似运营车辆查询(月度里程)10268 - "QCXGP1W3": qcxg.ProcessQCXGP1W3Request, //疑似运营车辆查询(季度里程)10269 - "QCXGM7R9": qcxg.ProcessQCXGM7R9Request, //疑似运营车辆查询(半年度里程)10270 - "QCXGU2K4": qcxg.ProcessQCXGU2K4Request, //疑似运营车辆查询(年度里程)10271 - "QCXG5U0Z": qcxg.ProcessQCXG5U0ZRequest, // 车辆静态信息查询 10479 - "QCXGY7F2": qcxg.ProcessQCXGY7F2Request, // 二手车VIN估值 10443 - "QCXG3M7Z": qcxg.ProcessQCXG3M7ZRequest, //人车关系核验(ETC)10093 月更 - "QCXGM4CL": qcxg.ProcessQCXGM4CLRequest, // 名下车辆诺尔 + "QCXGFV9W": qcxg.ProcessQCXGFV9WRequest, //疑似营运车辆注册平台数 10386 + "QCXG76VA": qcxg.ProcessQCXG76VARequest, //疑似运营车辆查询(月度里程)10268 + "QCXGYQDC": qcxg.ProcessQCXGYQDCRequest, //疑似运营车辆查询(季度里程)10269 + "QCXGGFWW": qcxg.ProcessQCXGGFWWRequest, //疑似运营车辆查询(半年度里程)10270 + "QCXGYWSV": qcxg.ProcessQCXGYWSVRequest, //疑似运营车辆查询(年度里程)10271 + "QCXG521L": qcxg.ProcessQCXG521LRequest, // 车辆静态信息查询 10479 + "QCXGIJY3": qcxg.ProcessQCXGIJY3Request, // 名下车辆诺尔 // DWBG系列处理器 - 多维报告 - "DWBG6A2C": dwbg.ProcessDWBG6A2CRequest, - "DWBG8B4D": dwbg.ProcessDWBG8B4DRequest, - "DWBG7F3A": dwbg.ProcessDWBG7F3ARequest, - "DWBG5SAM": dwbg.ProcessDWBG5SAMRequest, // FLXG系列处理器 - 风险管控 (包含原FXHY功能) - "FLXG8B4D": flxg.ProcessFLXG8B4DRequest, - - // TEST系列处理器 - 测试用处理器 - "TEST001": test.ProcessTestRequest, - "TEST002": test.ProcessTestErrorRequest, - "TEST003": test.ProcessTestTimeoutRequest, // PDFG系列处理器 - PDF生成 - "PDFG01GZ": pdfg.ProcessPDFG01GZRequest, } // 批量注册到组合包服务 diff --git a/internal/domains/api/services/form_config_service.go b/internal/domains/api/services/form_config_service.go index 2ac6c17..b221a87 100644 --- a/internal/domains/api/services/form_config_service.go +++ b/internal/domains/api/services/form_config_service.go @@ -121,8 +121,6 @@ func (s *FormConfigServiceImpl) getDTOStruct(ctx context.Context, apiCode string "IVYZ9A2B": &dto.IVYZ9A2BReq{}, "IVYZ7F2A": &dto.IVYZ7F2AReq{}, "IVYZ4E8B": &dto.IVYZ4E8BReq{}, - "IVYZ1C9D": &dto.IVYZ1C9DReq{}, - "IVYZGZ08": &dto.IVYZGZ08Req{}, "FLXG8A3F": &dto.FLXG8A3FReq{}, "FLXG5B2E": &dto.FLXG5B2EReq{}, "COMB298Y": &dto.COMB298YReq{}, @@ -156,10 +154,8 @@ func (s *FormConfigServiceImpl) getDTOStruct(ctx context.Context, apiCode string "IVYZ7F3A": &dto.IVYZ7F3AReq{}, "IVYZ3P9M": &dto.IVYZ3P9MReq{}, "IVYZ3A7F": &dto.IVYZ3A7FReq{}, - "IVYZ9D2E": &dto.IVYZ9D2EReq{}, "IVYZ9K2L": &dto.IVYZ9K2LReq{}, "DWBG7F3A": &dto.DWBG7F3AReq{}, - "YYSY8F3A": &dto.YYSY8F3AReq{}, "QCXG9P1C": &dto.QCXG9P1CReq{}, "JRZQ9E2A": &dto.JRZQ9E2AReq{}, "YYSY9A1B": &dto.YYSY9A1BReq{}, @@ -178,7 +174,7 @@ func (s *FormConfigServiceImpl) getDTOStruct(ctx context.Context, apiCode string "QCXG8A3D": &dto.QCXG8A3DReq{}, "QCXG6B4E": &dto.QCXG6B4EReq{}, "QYGL2B5C": &dto.QYGL2B5CReq{}, - "QYGLJ1U9": &dto.QYGLJ1U9Req{}, + "QYGL7HBN": &dto.QYGL7HBNReq{}, "JRZQ2F8A": &dto.JRZQ2F8AReq{}, "JRZQ1E7B": &dto.JRZQ1E7BReq{}, "JRZQ3C9R": &dto.JRZQ3C9RReq{}, @@ -203,7 +199,6 @@ func (s *FormConfigServiceImpl) getDTOStruct(ctx context.Context, apiCode string "IVYZ6M8P": &dto.IVYZ6M8PReq{}, //职业资格证书 "IVYZ9H2M": &dto.IVYZ9H2MReq{}, //极光个人婚姻查询(V2版) "QYGL5CMP": &dto.QYGL5CMPReq{}, //企业五要素验证 - "QCXG4896": &dto.QCXG4896Req{}, //网约车风险查询 "IVYZZQT3": &dto.IVYZZQT3Req{}, //人脸比对V3 "IVYZBPQ2": &dto.IVYZBPQ2Req{}, //人脸比对V2 "IVYZSFEL": &dto.IVYZSFELReq{}, //全国自然人人像三要素核验_V1 @@ -231,78 +226,78 @@ func (s *FormConfigServiceImpl) getDTOStruct(ctx context.Context, apiCode string "JRZQO6L7": &dto.JRZQO6L7Req{}, //全国自然人经济特征评分模型v3 简版 "JRZQO7L1": &dto.JRZQO7L1Req{}, //全国自然人经济特征评分模型v4 详版 "JRZQS7G0": &dto.JRZQS7G0Req{}, //社保综合评分V1 - "IVYZ9K7F": &dto.IVYZ9K7FReq{}, //身份证实名认证即时版 - "YYSY3M8S": &dto.YYSY3M8SReq{}, //运营商二要素查询 - "YYSYC4R9": &dto.YYSYC4R9Req{}, //运营商三要素详版查询 - "YYSYH6D2": &dto.YYSYH6D2Req{}, //运营商三要素简版政务版查询 - "YYSYP0T4": &dto.YYSYP0T4Req{}, //在网时长查询 - "YYSYE7V5": &dto.YYSYE7V5Req{}, //手机在网状态查询 - "YYSYS9W1": &dto.YYSYS9W1Req{}, //手机携号转网查询 - "YYSYK8R3": &dto.YYSYK8R3Req{}, //手机空号检测查询 - "YYSYF2T7": &dto.YYSYF2T7Req{}, //手机二次放号检测查询 - "IVYZA1B3": &dto.IVYZA1B3Req{}, //公安三要素人脸识别 - "IVYZFIC1": &dto.IVYZFIC1Req{}, //人脸身份证比对(数脉) - "IVYZX5QZ": &dto.IVYZX5QZReq{}, //活体识别 - "IVYZN2P8": &dto.IVYZ9K7FReq{}, //身份证实名认证政务版 - "YYSYH6F3": &dto.YYSYH6F3Req{}, //运营商三要素简版即时版查询 - "IVYZX5Q2": &dto.IVYZX5Q2Req{}, //活体识别步骤二 + "IVYZSQ0E": &dto.IVYZSQ0EReq{}, //身份证实名认证即时版 + "YYSY0YYV": &dto.YYSY0YYVReq{}, //运营商二要素查询 + "YYSYS66T": &dto.YYSYS66TReq{}, //运营商三要素详版查询 + "YYSYN8DI": &dto.YYSYN8DIReq{}, //运营商三要素简版政务版查询 + "YYSYUO7E": &dto.YYSYUO7EReq{}, //在网时长查询 + "YYSYKTQO": &dto.YYSYKTQOReq{}, //手机在网状态查询 + "YYSYXAES": &dto.YYSYXAESReq{}, //手机携号转网查询 + "YYSYJXZF": &dto.YYSYJXZFReq{}, //手机空号检测查询 + "YYSYP7PL": &dto.YYSYP7PLReq{}, //手机二次放号检测查询 + "IVYZE42I": &dto.IVYZE42IReq{}, //公安三要素人脸识别 + "IVYZDXMD": &dto.IVYZDXMDReq{}, //人脸身份证比对(数脉) + "IVYZWVYA": &dto.IVYZWVYAReq{}, //活体识别 + "IVYZFO5K": &dto.IVYZSQ0EReq{}, //身份证实名认证政务版 + "YYSYXHHO": &dto.YYSYXHHOReq{}, //运营商三要素简版即时版查询 + "IVYZKJ31": &dto.IVYZKJ31Req{}, //活体识别步骤二 "PDFG01GZ": &dto.PDFG01GZReq{}, // "QYGL5S1I": &dto.QYGL5S1IReq{}, //企业司法涉诉V2 - "JRZQACAB": &dto.JRZQACABReq{}, //银行卡四要素 - "QCXG9F5C": &dto.QCXG9F5CReq{}, //疑似营运车辆注册平台数 10386 - "QCXG3B8Z": &dto.QCXG3B8ZReq{}, //疑似运营车辆查询(月度里程)10268 - "QCXGP1W3": &dto.QCXGP1W3Req{}, //疑似运营车辆查询(季度里程)10269 - "QCXGM7R9": &dto.QCXGM7R9Req{}, //疑似运营车辆查询(半年度里程)10270 - "QCXGU2K4": &dto.QCXGU2K4Req{}, //疑似运营车辆查询(年度里程)10271 - "QCXG5U0Z": &dto.QCXG5U0ZReq{}, //车辆静态信息查询 10479 + "JRZQOICN": &dto.JRZQOICNReq{}, //银行卡四要素 + "QCXGFV9W": &dto.QCXGFV9WReq{}, //疑似营运车辆注册平台数 10386 + "QCXG76VA": &dto.QCXG76VAReq{}, //疑似运营车辆查询(月度里程)10268 + "QCXGYQDC": &dto.QCXGYQDCReq{}, //疑似运营车辆查询(季度里程)10269 + "QCXGGFWW": &dto.QCXGGFWWReq{}, //疑似运营车辆查询(半年度里程)10270 + "QCXGYWSV": &dto.QCXGYWSVReq{}, //疑似运营车辆查询(年度里程)10271 + "QCXG521L": &dto.QCXG521LReq{}, //车辆静态信息查询 10479 "QCXGY7F2": &dto.QCXGY7F2Req{}, //二手车VIN估值 10443 - "YYSYK9R4": &dto.YYSYK9R4Req{}, //全网手机三要素验证1979周更新版 + "YYSYGLSF": &dto.YYSYGLSFReq{}, //全网手机三要素验证1979周更新版 "QCXG3M7Z": &dto.QCXG3M7ZReq{}, //人车关系核验(ETC)10093 月更 "JRZQ1P5G": &dto.JRZQ1P5GReq{}, //全国自然人借贷压力指数查询(2) - "IVYZOCR1": &dto.IVYZOCR1Req{}, //身份证OCR - "IVYZOCR2": &dto.IVYZOCR1Req{}, //身份证OCR2数卖 - "QYGLJ0Q1": &dto.QYGLJ0Q1Req{}, //企业股权结构全景查询 - "QYGLUY3S": &dto.QYGLUY3SReq{}, //企业全量信息核验V2 可用 - "JRZQOCRE": &dto.JRZQOCREReq{}, //银行卡OCR数卖 - "JRZQOCRY": &dto.JRZQOCRYReq{}, //银行卡OCR数据宝 + "IVYZ9OHN": &dto.IVYZ9OHNReq{}, //身份证OCR + "IVYZZSCG": &dto.IVYZ9OHNReq{}, //身份证OCR2数卖 + "QYGL9MYB": &dto.QYGL9MYBReq{}, //企业股权结构全景查询 + "QYGLALPK": &dto.QYGLALPKReq{}, //企业全量信息核验V2 可用 + "JRZQMDQ1": &dto.JRZQMDQ1Req{}, //银行卡OCR数卖 + "JRZQDMLO": &dto.JRZQDMLOReq{}, //银行卡OCR数据宝 "YYSY35TA": &dto.YYSY35TAReq{}, //运营商归属地数卖 - "QYGLDJ12": &dto.QYGLDJ12Req{}, //企业年报信息核验 - "FLXGDJG3": &dto.FLXGDJG3Req{}, //董监高司法综合信息核验 - "QYGL8848": &dto.QYGLDJ12Req{}, //企业税收违法核查 - "IVYZ18HY": &dto.IVYZ18HYReq{}, //婚姻状况核验V2(单人) - "IVYZ28HY": &dto.IVYZ28HYReq{}, //婚姻状况核验(单人) - "IVYZ38SR": &dto.IVYZ38SRReq{}, //婚姻状态核验(双人) - "IVYZ48SR": &dto.IVYZ48SRReq{}, //婚姻状态核验V2(双人) - "IVYZ5E22": &dto.IVYZ5E22Req{}, //双人婚姻评估查询zhicha版本 + "QYGLUDJG": &dto.QYGLUDJGReq{}, //企业年报信息核验 + "FLXGJI17": &dto.FLXGJI17Req{}, //董监高司法综合信息核验 + "QYGLWYEK": &dto.QYGLWYEKReq{}, //企业税收违法核查 + "IVYZYQKX": &dto.IVYZYQKXReq{}, //婚姻状况核验V2(单人) + "IVYZO4RX": &dto.IVYZO4RXReq{}, //婚姻状况核验(单人) + "IVYZRHT5": &dto.IVYZRHT5Req{}, //婚姻状态核验(双人) + "IVYZYDQM": &dto.IVYZYDQMReq{}, //婚姻状态核验V2(双人) + "IVYZPYSO": &dto.IVYZPYSOReq{}, //双人婚姻评估查询zhicha版本 "DWBG5SAM": &dto.DWBG5SAMReq{}, //海宇指迷报告 - "QCXGM4CL": &dto.QCXGM4CLReq{}, //名下车辆诺尔 - "JRZQBHZ4": &dto.JRZQBHZ4Req{}, //支付行为指数诺尔 - "JRZQV8V8": &dto.JRZQV8V8Req{}, //风险量级V8 - "JRZQV9V9": &dto.JRZQV9V9Req{}, //风险量级V9 - "JRZQV1O0": &dto.JRZQV1O0Req{}, //风险量级V10 - "JRZQV2O1": &dto.JRZQV2O1Req{}, //信用全景V21 - "IVYZV1O6": &dto.IVYZV1O6Req{}, //身份风险V106 - "JRZQV7D1": &dto.JRZQV7D1Req{}, //借贷意向验证 - "JRZQV07T": &dto.JRZQV07TReq{}, //洞侦多头履约行为 - "JRZQVZ3Y": &dto.JRZQVZ3YReq{}, //租赁申请意向 - "JRZQVZ2Y": &dto.JRZQVZ2YReq{}, //租赁申请意向V22 - "JRZQV5F4": &dto.JRZQV5F4Req{}, //风险变量V5F4 - "QYGLVR76": &dto.QYGLVR76Req{}, //人企关联 - "IVYZVXF6": &dto.IVYZVXF6Req{}, //消费能力 - "IVYZVJJ6": &dto.IVYZVJJ6Req{}, //收入等级VJJ6 - "JRZQV7MD": &dto.JRZQV7MDReq{}, //特殊名单 - "JRZQV3HM": &dto.JRZQV3HMReq{}, //债务逾期黑名单V3_1 - "JRZQVT43": &dto.JRZQVT43Req{}, //投诉风险筛查V709 - "JRZQV87M": &dto.JRZQV87MReq{}, //黑名单V110_c10 - "JRZQV0MD": &dto.JRZQV0MDReq{}, //特殊名单 - "JRZQVZXF": &dto.JRZQVZXFReq{}, //智享分 - "QYGLV4S6": &dto.QYGLV4S6Req{}, //企业诉讼定制版 - "FLXGG0S4": &dto.FLXGG0S4Req{}, //个人涉诉定制版 - "JRZQVZTF": &dto.JRZQVZTFReq{}, //智瞳-通用版 - "JRZQV4TF": &dto.JRZQV4TFReq{}, //智瞳分尊享版 - "JRZQVKK6": &dto.JRZQVKK6Req{}, //坤羽模型V3-标签版 - "FLXGHB4F": &dto.FLXGHB4FReq{}, //汇博-个人涉诉 - "QYGLBH7Y": &dto.QYGLBH7YReq{}, //汇博-企业涉诉 + "QCXGIJY3": &dto.QCXGIJY3Req{}, //名下车辆诺尔 + "JRZQ65ZO": &dto.JRZQ65ZOReq{}, //支付行为指数诺尔 + "JRZQNKEI": &dto.JRZQNKEIReq{}, //风险量级V8 + "JRZQQKEC": &dto.JRZQQKECReq{}, //风险量级V9 + "JRZQI079": &dto.JRZQI079Req{}, //风险量级V10 + "JRZQV7YZ": &dto.JRZQV7YZReq{}, //信用全景V21 + "IVYZOQFB": &dto.IVYZOQFBReq{}, //身份风险V106 + "JRZQX5DM": &dto.JRZQX5DMReq{}, //借贷意向验证 + "JRZQ1AIJ": &dto.JRZQ1AIJReq{}, //洞侦多头履约行为 + "JRZQZ05I": &dto.JRZQZ05IReq{}, //租赁申请意向 + "JRZQNK43": &dto.JRZQNK43Req{}, //租赁申请意向V22 + "JRZQNVM8": &dto.JRZQNVM8Req{}, //风险变量V5F4 + "QYGLWV7U": &dto.QYGLWV7UReq{}, //人企关联 + "IVYZBI6F": &dto.IVYZBI6FReq{}, //消费能力 + "IVYZ6W0U": &dto.IVYZ6W0UReq{}, //收入等级VJJ6 + "JRZQMLZX": &dto.JRZQMLZXReq{}, //特殊名单 + "JRZQQD4F": &dto.JRZQQD4FReq{}, //债务逾期黑名单V3_1 + "JRZQVBHJ": &dto.JRZQVBHJReq{}, //投诉风险筛查V709 + "JRZQBQIR": &dto.JRZQBQIRReq{}, //黑名单V110_c10 + "JRZQTM1V": &dto.JRZQTM1VReq{}, //特殊名单 + "JRZQNEP0": &dto.JRZQNEP0Req{}, //智享分 + "QYGL7Z0O": &dto.QYGL7Z0OReq{}, //企业诉讼定制版 + "FLXGMMG7": &dto.FLXGMMG7Req{}, //个人涉诉定制版 + "JRZQLY6D": &dto.JRZQLY6DReq{}, //智瞳-通用版 + "JRZQAH34": &dto.JRZQAH34Req{}, //智瞳分尊享版 + "JRZQML9G": &dto.JRZQML9GReq{}, //坤羽模型V3-标签版 + "FLXGC4CT": &dto.FLXGC4CTReq{}, //汇博-个人涉诉 + "QYGLLUCM": &dto.QYGLLUCMReq{}, //汇博-企业涉诉 } diff --git a/internal/domains/api/services/processors/comb/comb86pm_processor.go b/internal/domains/api/services/processors/comb/comb86pm_processor.go deleted file mode 100644 index cd02d4a..0000000 --- a/internal/domains/api/services/processors/comb/comb86pm_processor.go +++ /dev/null @@ -1,36 +0,0 @@ -package comb - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessCOMB86PMRequest COMB86PM API处理方法 -func ProcessCOMB86PMRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.COMB86PMReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 调用组合包服务处理请求 - // Options会自动传递给所有子处理器 - combinedResult, err := deps.CombService.ProcessCombRequest(ctx, params, deps, "COMB86PM") - if err != nil { - return nil, err - } - // 如果有ApiCode为FLXG54F5的子产品,改名为FLXG54F6 - for _, resp := range combinedResult.Responses { - if resp.ApiCode == "FLXGBC21" { - resp.ApiCode = "FLXG54F5" - } - } - return json.Marshal(combinedResult) -} diff --git a/internal/domains/api/services/processors/comb/combhzy2_processor.go b/internal/domains/api/services/processors/comb/combhzy2_processor.go deleted file mode 100644 index c119874..0000000 --- a/internal/domains/api/services/processors/comb/combhzy2_processor.go +++ /dev/null @@ -1,148 +0,0 @@ -package comb - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/shared/logger" - - "go.uber.org/zap" -) - -// ProcessCOMBHZY2Request 处理 COMBHZY2 组合包请求 -func ProcessCOMBHZY2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - log := logger.GetGlobalLogger() - - var req dto.COMBHZY2Req - if err := json.Unmarshal(params, &req); err != nil { - log.Error("COMBHZY2请求参数反序列化失败", - zap.Error(err), - zap.String("params", string(params)), - zap.String("api_code", "COMBHZY2"), - ) - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(req); err != nil { - log.Error("COMBHZY2请求参数验证失败", - zap.Error(err), - zap.String("api_code", "COMBHZY2"), - ) - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - combinedResult, err := deps.CombService.ProcessCombRequest(ctx, params, deps, "COMBHZY2") - if err != nil { - log.Error("COMBHZY2组合包服务调用失败", - zap.Error(err), - zap.String("api_code", "COMBHZY2"), - ) - return nil, err - } - - if combinedResult == nil { - log.Error("COMBHZY2组合包响应为空", - zap.String("api_code", "COMBHZY2"), - ) - return nil, errors.New("组合包响应为空") - } - - log.Info("COMBHZY2组合包服务调用成功", - zap.Int("子产品数量", len(combinedResult.Responses)), - zap.String("api_code", "COMBHZY2"), - ) - - sourceCtx, err := buildSourceContextFromCombined(ctx, combinedResult) - if err != nil { - log.Error("COMBHZY2构建源数据上下文失败", - zap.Error(err), - zap.String("api_code", "COMBHZY2"), - ) - return nil, err - } - - report := buildTargetReport(ctx, sourceCtx) - - reportBytes, err := json.Marshal(report) - if err != nil { - log.Error("COMBHZY2报告序列化失败", - zap.Error(err), - zap.String("api_code", "COMBHZY2"), - ) - return nil, errors.Join(processors.ErrSystem, err) - } - - return reportBytes, nil -} - -func buildSourceContextFromCombined(ctx context.Context, result *processors.CombinedResult) (*sourceContext, error) { - log := logger.GetGlobalLogger() - - if result == nil { - log.Error("组合包响应为空", zap.String("api_code", "COMBHZY2")) - return nil, errors.New("组合包响应为空") - } - - src := sourceFile{Responses: make([]sourceResponse, 0, len(result.Responses))} - successCount := 0 - failedCount := 0 - - for _, resp := range result.Responses { - if !resp.Success { - log.Warn("子产品调用失败,跳过", - zap.String("api_code", resp.ApiCode), - zap.String("error", resp.Error), - zap.String("parent_api_code", "COMBHZY2"), - ) - failedCount++ - continue - } - - if resp.Data == nil { - log.Warn("子产品数据为空,跳过", - zap.String("api_code", resp.ApiCode), - zap.String("parent_api_code", "COMBHZY2"), - ) - failedCount++ - continue - } - - raw, err := json.Marshal(resp.Data) - if err != nil { - log.Error("序列化子产品数据失败", - zap.Error(err), - zap.String("api_code", resp.ApiCode), - zap.String("parent_api_code", "COMBHZY2"), - ) - failedCount++ - continue - } - - src.Responses = append(src.Responses, sourceResponse{ - ApiCode: resp.ApiCode, - Data: raw, - Success: resp.Success, - }) - successCount++ - } - - log.Info("组合包子产品处理完成", - zap.Int("成功数量", successCount), - zap.Int("失败数量", failedCount), - zap.Int("总数量", len(result.Responses)), - zap.String("api_code", "COMBHZY2"), - ) - - if len(src.Responses) == 0 { - log.Error("组合包子产品全部调用失败", - zap.Int("总数量", len(result.Responses)), - zap.String("api_code", "COMBHZY2"), - ) - return nil, errors.New("组合包子产品全部调用失败") - } - - return buildSourceContext(ctx, src) -} diff --git a/internal/domains/api/services/processors/comb/combhzy2_transform.go b/internal/domains/api/services/processors/comb/combhzy2_transform.go deleted file mode 100644 index 148a816..0000000 --- a/internal/domains/api/services/processors/comb/combhzy2_transform.go +++ /dev/null @@ -1,2053 +0,0 @@ -package comb - -import ( - "context" - "crypto/rand" - "encoding/hex" - "encoding/json" - "fmt" - "strconv" - "strings" - "time" - - "hyapi-server/internal/shared/logger" - - "go.uber.org/zap" -) - -// ======================= -// 原始数据结构 -// ======================= - -// sourceFile 对应 source.json 顶层结构,包含组合包所有子产品响应 -type sourceFile struct { - Responses []sourceResponse `json:"responses"` -} - -// sourceResponse 描述每个子产品在源数据中的响应格式 -type sourceResponse struct { - ApiCode string `json:"api_code"` - Data json.RawMessage `json:"data"` - Success bool `json:"success"` -} - -// --- DWBG8B4D --- - -// baseProductData 映射 DWBG8B4D 产品的 data 节点,用于基础信息与风险指标 -type baseProductData struct { - BaseInfo baseInfo `json:"baseInfo"` - CheckSuggest string `json:"checkSuggest"` - CreditScore int `json:"creditScore"` - ElementVerificationDetail elementVerificationDetail `json:"elementVerificationDetail"` - FraudRule string `json:"fraudRule"` - FraudScore int `json:"fraudScore"` - LeasingRiskAssessment baseLeasingRiskAssessment `json:"leasingRiskAssessment"` - LoanEvaluationVerification loanEvaluationVerificationDetail `json:"loanEvaluationVerificationDetail"` - OverdueRiskProduct overdueRiskProduct `json:"overdueRiskProduct"` - RiskSupervision riskSupervision `json:"riskSupervision"` - RiskWarning riskWarning `json:"riskWarning"` - StandLiveInfo standLiveInfo `json:"standLiveInfo"` - VerifyRule string `json:"verifyRule"` - MultCourtInfo multCourtInfo `json:"multCourtInfo"` -} - -// baseInfo 存放被查询人的基础身份信息 -type baseInfo struct { - Age int `json:"age"` - Channel string `json:"channel"` - IdCard string `json:"idCard"` - Location string `json:"location"` - Name string `json:"name"` - Phone string `json:"phone"` - PhoneArea string `json:"phoneArea"` - Sex string `json:"sex"` - Status int `json:"status"` -} - -// elementVerificationDetail 用于要素及运营商核验结果 -type elementVerificationDetail struct { - PersonCheckDetails simpleCheckDetail `json:"personCheckDetails"` - PhoneCheckDetails simpleCheckDetail `json:"phoneCheckDetails"` - OnlineRiskFlag int `json:"onlineRiskFlag"` - PhoneVailRiskFlag int `json:"phoneVailRiskFlag"` -} - -// simpleCheckDetail 表示某项核验结果的简要描述 -type simpleCheckDetail struct { - Ele string `json:"ele"` - Result string `json:"result"` -} - -// baseLeasingRiskAssessment 3C 租赁多头风险统计字段 -type baseLeasingRiskAssessment struct { - RiskFlag int `json:"riskFlag"` - ThreeCInstitutionApplicationCountLast12M string `json:"threeCInstitutionApplicationCountLast12Months"` - ThreeCPlatformApplicationCountLast12M string `json:"threeCPlatformApplicationCountLast12Months"` - ThreeCInstitutionApplicationCountLast6M string `json:"threeCInstitutionApplicationCountLast6Months"` - ThreeCPlatformApplicationCountLast6M string `json:"threeCPlatformApplicationCountLast6Months"` - ThreeCInstitutionApplicationCountLast3M string `json:"threeCInstitutionApplicationCountLast3Months"` - ThreeCPlatformApplicationCountLast3M string `json:"threeCPlatformApplicationCountLast3Months"` - ThreeCInstitutionApplicationCountLast1M string `json:"threeCInstitutionApplicationCountLastMonth"` - ThreeCPlatformApplicationCountLast1M string `json:"threeCPlatformApplicationCountLastMonth"` - ThreeCInstitutionApplicationCountLast7D string `json:"threeCInstitutionApplicationCountLast7Days"` - ThreeCPlatformApplicationCountLast7D string `json:"threeCPlatformApplicationCountLast7Days"` - ThreeCInstitutionApplicationCountLast3D string `json:"threeCInstitutionApplicationCountLast3Days"` - ThreeCPlatformApplicationCountLast3D string `json:"threeCPlatformApplicationCountLast3Days"` - ThreeCInstitutionApplicationCountLast14D string `json:"threeCInstitutionApplicationCountLast14Days"` - ThreeCPlatformApplicationCountLast14D string `json:"threeCPlatformApplicationCountLast14Days"` - ThreeCInstitutionApplicationCountLast12MNig string `json:"threeCInstitutionApplicationCountLast12MonthsNight"` - ThreeCPlatformApplicationCountLast12MNig string `json:"threeCPlatformApplicationCountLast12MonthsNight"` -} - -// loanEvaluationVerificationDetail 信贷意向与时间段风险统计 -type loanEvaluationVerificationDetail struct { - BusinessLoanPerformances []loanPerformance `json:"businessLoanPerformances"` - CustomerLoanPerformances []loanPerformance `json:"customerLoanPerformances"` - TimeLoanPerformances []loanPerformance `json:"timeLoanPerformances"` - RiskFlag int `json:"riskFlag"` -} - -// loanPerformance 描述某类别在不同统计窗口内的申请次数 -type loanPerformance struct { - Type string `json:"type"` - Last12Month string `json:"last12Month"` - Last12MonthCount string `json:"last12MonthCount"` - Last6Month string `json:"last6Month"` - Last6MonthCount string `json:"last6MonthCount"` - Last3Month string `json:"last3Month"` - Last3MonthCount string `json:"last3MonthCount"` - Last1Month string `json:"last1Month"` - Last1MonthCount string `json:"last1MonthCount"` - Last7Day string `json:"last7Day"` - Last7DayCount string `json:"last7DayCount"` - Last15Day string `json:"last15Day"` - Last15DayCount string `json:"last15DayCount"` -} - -// overdueRiskProduct 当前逾期相关信息(本报告暂未直接使用) -type overdueRiskProduct struct { - CurrentOverdueAmount string `json:"currentOverdueAmount"` -} - -// riskSupervision 租赁监管相关字段(本报告暂未直接使用) -type riskSupervision struct { - LeastApplicationTime string `json:"leastApplicationTime"` -} - -// riskWarning 各类风险命中指标集合 -type riskWarning struct { - FrequentApplicationRecent int `json:"frequentApplicationRecent"` - FrequentBankApplications int `json:"frequentBankApplications"` - FrequentNonBankApplications int `json:"frequentNonBankApplications"` - HasCriminalRecord int `json:"hasCriminalRecord"` - HighDebtPressure int `json:"highDebtPressure"` - IsAntiFraudInfo int `json:"isAntiFraudInfo"` - IsEconomyFront int `json:"isEconomyFront"` - IsDisrupSocial int `json:"isDisrupSocial"` - IsKeyPerson int `json:"isKeyPerson"` - IsTrafficRelated int `json:"isTrafficRelated"` - IdCardTwoElementMismatch int `json:"idCardTwoElementMismatch"` - PhoneThreeElementMismatch int `json:"phoneThreeElementMismatch"` - IdCardPhoneProvinceMismatch int `json:"idCardPhoneProvinceMismatch"` - TotalRiskCounts int `json:"totalRiskCounts"` - Level string `json:"level"` - ShortPhoneDuration int `json:"shortPhoneDuration"` - ShortPhoneDurationSlight int `json:"shortPhoneDurationSlight"` - NoPhoneDuration int `json:"noPhoneDuration"` - MoreFrequentBankApplications int `json:"moreFrequentBankApplications"` - MoreFrequentNonBankApplications int `json:"moreFrequentNonBankApplications"` - FrequentRentalApplications int `json:"frequentRentalApplications"` - VeryFrequentRentalApplications int `json:"veryFrequentRentalApplications"` - HitCriminalRisk int `json:"hitCriminalRisk"` - HitExecutionCase int `json:"hitExecutionCase"` - RiskLevel string `json:"riskLevel"` - HitCurrentOverdue int `json:"hitCurrentOverdue"` - HitHighRiskNonBankLastTwoYears int `json:"hitHighRiskNonBankLastTwoYears"` - HitHighRiskBankLastTwoYears int `json:"hitHighRiskBankLastTwoYears"` - HitHighRiskBank int `json:"hitHighRiskBank"` -} - -// standLiveInfo 活体核验结果(本报告暂未直接使用) -type standLiveInfo struct { - FinalAuthResult string `json:"finalAuthResult"` -} - -// multCourtInfo 司法风险核验产品,统一承载涉案/执行/失信/限高四类公告 -type multCourtInfo struct { - LegalCasesFlag int `json:"legalCasesFlag"` - LegalCases []multCaseItem `json:"legalCases"` - ExecutionCasesFlag int `json:"executionCasesFlag"` - ExecutionCases []multCaseItem `json:"executionCases"` - DisinCasesFlag int `json:"disinCasesFlag"` - DisinCases []multCaseItem `json:"disinCases"` - LimitCasesFlag int `json:"limitCasesFlag"` - LimitCases []multCaseItem `json:"limitCases"` -} - -// multCaseItem 司法各类公告的通用记录结构 -type multCaseItem struct { - CaseNumber string `json:"caseNumber"` - CaseType string `json:"caseType"` - Court string `json:"court"` - LitigantType string `json:"litigantType"` - FilingTime string `json:"filingTime"` - DisposalTime string `json:"disposalTime"` - CaseStatus string `json:"caseStatus"` - ExecutionAmount string `json:"executionAmount"` - RepaidAmount string `json:"repaidAmount"` - CaseReason string `json:"caseReason"` - DisposalMethod string `json:"disposalMethod"` - JudgmentResult string `json:"judgmentResult"` -} - -// --- FLXG7E8F --- - -// judicialProductData 对应 FLXG7E8F 司法产品数据 -type judicialProductData struct { - JudicialData judicialWrapper `json:"judicial_data"` -} - -// judicialWrapper 聚合司法产品下的各类列表信息 -type judicialWrapper struct { - LawsuitStat lawsuitStat `json:"lawsuitStat"` - ConsumptionRestrictionList []consumptionRestriction `json:"consumptionRestrictionList"` - BreachCaseList []breachCase `json:"breachCaseList"` -} - -// lawsuitStat 按案件类型、执行情况等维度统计的结构化数据 -type lawsuitStat struct { - CasesTree casesTree `json:"cases_tree"` - Civil lawCategory `json:"civil"` - Criminal lawCategory `json:"criminal"` - Administrative lawCategory `json:"administrative"` - Preservation lawCategory `json:"preservation"` - Bankrupt lawCategory `json:"bankrupt"` - Implement lawCategory `json:"implement"` -} - -// lawCategory 包装同类案件的集合 -type lawCategory struct { - Cases []judicialCase `json:"cases"` -} - -// casesTree 旧格式的案件分类(当前主要使用 lawCategory) -type casesTree struct { - Criminal []judicialCase `json:"criminal"` - Civil []judicialCase `json:"civil"` -} - -// judicialCase 司法案件公共字段 -type judicialCase struct { - CaseNumber string `json:"c_ah"` - CaseType int `json:"case_type"` - StageType int `json:"stage_type"` - Najbs string `json:"n_ajbs"` - Court string `json:"n_jbfy"` - FilingDate string `json:"d_larq"` - JudgeResult string `json:"n_jafs"` - CaseStatus string `json:"n_ajjzjd"` - ApplyAmount float64 `json:"n_sqzxbdje"` - CaseCategory string `json:"n_jaay"` -} - -// consumptionRestriction 限制高消费记录 -type consumptionRestriction struct { - CaseNumber string `json:"caseNumber"` - IssueDate string `json:"issueDate"` - ExecutiveCourt string `json:"executiveCourt"` -} - -// breachCase 失信被执行人记录 -type breachCase struct { - CaseNumber string `json:"caseNumber"` - FileDate string `json:"fileDate"` - IssueDate string `json:"issueDate"` - ExecutiveCourt string `json:"executiveCourt"` - FulfillStatus string `json:"fulfillStatus"` - EstimatedJudgementAmount float64 `json:"estimatedJudgementAmount"` - EnforcementBasisNumber string `json:"enforcementBasisNumber"` - EnforcementBasisOrganization string `json:"enforcementBasisOrganization"` -} - -// --- JRZQ9D4E --- - -// contentsProductData 对应 JRZQ9D4E 产品的数据内容 -type contentsProductData struct { - Contents map[string]string `json:"contents"` - ResponseID string `json:"responseId"` - Score string `json:"score"` - Reason string `json:"reason"` -} - -// --- JRZQ6F2A --- - -// riskScreenProductData 对应 JRZQ6F2A 产品的风控决策结果 -type riskScreenProductData struct { - RiskScreenV2 riskScreenV2 `json:"risk_screen_v2"` -} - -// riskScreenV2 风险引擎输出的决策、模型等信息 -type riskScreenV2 struct { - Code string `json:"code"` - Decision string `json:"decision"` - Message string `json:"message"` - FulinFlag int `json:"fulinHitFlag"` - Id string `json:"id"` - Knowledge riskScreenKnowledge `json:"knowledge"` - Models []riskScreenModel `json:"models"` - Variables []riskScreenVariable `json:"variables"` -} - -// riskScreenKnowledge 风险知识库命中的规则编码 -type riskScreenKnowledge struct { - Code string `json:"code"` -} - -// riskScreenModel 风控模型得分信息 -type riskScreenModel struct { - SceneCode string `json:"sceneCode"` - Score string `json:"score"` -} - -type riskScreenVariable struct { - VariableName string `json:"variableName"` - VariableValue map[string]string `json:"variableValue"` -} - -// ======================= -// 目标数据结构 -// ======================= - -// targetReport 与 target.json 结构一一对应的报告格式 -type targetReport struct { - ReportSummary reportSummary `json:"reportSummary"` - BasicInfo reportBasicInfo `json:"basicInfo"` - RiskIdentification riskIdentification `json:"riskIdentification"` - CreditAssessment creditAssessment `json:"creditAssessment"` - LeasingRiskAssessment leasingRiskAssessment `json:"leasingRiskAssessment"` - ComprehensiveAnalysis []string `json:"comprehensiveAnalysis"` - ReportFooter reportFooter `json:"reportFooter"` -} - -// reportSummary 对应 target.json 中 reportSummary 节点 -type reportSummary struct { - RuleValidation summaryRuleValidation `json:"ruleValidation"` - AntiFraudScore summaryAntiFraudScore `json:"antiFraudScore"` - AntiFraudRule summaryAntiFraudRule `json:"antiFraudRule"` - AbnormalRulesHit abnormalHit `json:"abnormalRulesHit"` -} - -type summaryRuleValidation struct { - Code string `json:"code,omitempty"` - Result string `json:"result,omitempty"` -} - -type summaryAntiFraudScore struct { - Level string `json:"level,omitempty"` -} - -type summaryAntiFraudRule struct { - Level string `json:"level,omitempty"` - Code string `json:"code,omitempty"` -} - -// abnormalHit 表示异常规则汇总 -type abnormalHit struct { - Count int `json:"count"` - Alert string `json:"alert"` -} - -// reportBasicInfo 对应 target.json 中 basicInfo 节点 -type reportBasicInfo struct { - Name string `json:"name"` - Phone string `json:"phone"` - IdCard string `json:"idCard"` - ReportID string `json:"reportId"` - Verifications []verificationItem `json:"verifications"` -} - -// verificationItem 描述核验项的展示信息 -type verificationItem struct { - Item string `json:"item"` - Description string `json:"description"` - Result string `json:"result"` - Details string `json:"details,omitempty"` -} - -// riskIdentification 对应 target.json 中 riskIdentification 节点 -type riskIdentification struct { - Title string `json:"title"` - CaseAnnouncements caseAnnouncementSection `json:"caseAnnouncements"` - EnforcementAnnouncements enforcementAnnouncementSection `json:"enforcementAnnouncements"` - DishonestAnnouncements dishonestAnnouncementSection `json:"dishonestAnnouncements"` - HighConsumptionRestrictionAnn highRestrictionAnnouncementSection `json:"highConsumptionRestrictionAnnouncements"` -} - -type caseAnnouncementSection struct { - Title string `json:"title"` - Records []caseAnnouncementRecord `json:"records"` -} - -type caseAnnouncementRecord struct { - CaseNumber string `json:"caseNumber"` - CaseType string `json:"caseType"` - FilingDate string `json:"filingDate"` - Authority string `json:"authority"` -} - -type enforcementAnnouncementSection struct { - Title string `json:"title"` - Records []enforcementAnnouncementRecord `json:"records"` -} - -type enforcementAnnouncementRecord struct { - CaseNumber string `json:"caseNumber"` - TargetAmount string `json:"targetAmount"` - FilingDate string `json:"filingDate"` - Court string `json:"court"` - Status string `json:"status"` -} - -type dishonestAnnouncementSection struct { - Title string `json:"title"` - Records []dishonestAnnouncementRecord `json:"records"` -} - -type dishonestAnnouncementRecord struct { - DishonestPerson string `json:"dishonestPerson"` - IdCard string `json:"idCard"` - Court string `json:"court"` - FilingDate string `json:"filingDate"` - PerformanceStatus string `json:"performanceStatus"` -} - -type highRestrictionAnnouncementSection struct { - Title string `json:"title"` - Records []highRestrictionAnnouncementRecord `json:"records"` -} - -type highRestrictionAnnouncementRecord struct { - RestrictedPerson string `json:"restrictedPerson"` - IdCard string `json:"idCard"` - Court string `json:"court"` - StartDate string `json:"startDate"` - Measure string `json:"measure"` -} - -// creditAssessment 对应 target.json 中 creditAssessment 节点 -type creditAssessment struct { - Title string `json:"title"` - LoanIntentionByCustomerType assessmentSection[loanIntentionRecord] `json:"loanIntentionByCustomerType"` - LoanIntentionAbnormalTimes assessmentSection[abnormalTimeRecord] `json:"loanIntentionAbnormalTimes"` -} - -// leasingRiskAssessment 对应 target.json 中 leasingRiskAssessment 节点 -type leasingRiskAssessment struct { - Title string `json:"title"` - MultiLender3C assessmentSection[multiLenderRecord] `json:"multiLenderRisk3C"` -} - -// assessmentSection 泛型结构,封装任意记录列表及标题 -type assessmentSection[T any] struct { - Title string `json:"title"` - Records []T `json:"records"` -} - -// loanIntentionRecord 对应 loanIntentionByCustomerType.records 项 -type loanIntentionRecord struct { - CustomerType string `json:"customerType"` - ApplicationCount int `json:"applicationCount"` - RiskLevel string `json:"riskLevel"` -} - -// abnormalTimeRecord 对应 loanIntentionAbnormalTimes.records 项 -type abnormalTimeRecord struct { - TimePeriod string `json:"timePeriod"` - MainInstitutionType string `json:"mainInstitutionType"` - RiskLevel string `json:"riskLevel"` -} - -// multiLenderRecord 对应 multiLenderRisk3C.records 项 -type multiLenderRecord struct { - InstitutionType string `json:"institutionType"` - AppliedCount int `json:"appliedCount"` - InUseCount int `json:"inUseCount"` - TotalCreditLimit float64 `json:"totalCreditLimit"` - TotalDebtBalance float64 `json:"totalDebtBalance"` - RiskLevel string `json:"riskLevel"` -} - -// reportFooter 对应 target.json 中 reportFooter 节点 -type reportFooter struct { - DataSource string `json:"dataSource"` - GenerationTime string `json:"generationTime"` - Disclaimer string `json:"disclaimer"` -} - -// ======================= -// 上下文结构 -// ======================= - -// sourceContext 缓存各子产品解析后的结构,方便后续加工 -type sourceContext struct { - BaseData *baseProductData - JudicialData *judicialProductData - ContentsData *contentsProductData - RiskScreen *riskScreenProductData -} - -// ======================= -// 主流程 -// ======================= - -// buildSourceContext 根据 source.json 解析出各子产品的结构化数据 -func buildSourceContext(ctx context.Context, src sourceFile) (*sourceContext, error) { - log := logger.GetGlobalLogger() - result := &sourceContext{} - - for _, resp := range src.Responses { - if !resp.Success { - continue - } - - // 检查数据是否为空 - if len(resp.Data) == 0 { - log.Warn("子产品数据为空,跳过解析", - zap.String("api_code", resp.ApiCode), - zap.String("parent_api_code", "COMBHZY2"), - ) - continue - } - - switch strings.ToUpper(resp.ApiCode) { - case "DWBG8B4D": - var data baseProductData - if err := json.Unmarshal(resp.Data, &data); err != nil { - log.Error("解析DWBG8B4D数据失败,使用兼容处理", - zap.Error(err), - zap.String("api_code", resp.ApiCode), - zap.String("data_preview", string(resp.Data[:min(100, len(resp.Data))])), - ) - // 尝试部分解析,即使失败也继续 - if partialErr := json.Unmarshal(resp.Data, &data); partialErr != nil { - log.Warn("DWBG8B4D数据格式异常,将使用空结构", - zap.Error(partialErr), - zap.String("api_code", resp.ApiCode), - ) - // 使用空结构,不返回错误 - data = baseProductData{} - } - } - result.BaseData = &data - case "FLXG7E8F": - var data judicialProductData - if err := json.Unmarshal(resp.Data, &data); err != nil { - log.Warn("解析FLXG7E8F数据失败,使用兼容处理", - zap.Error(err), - zap.String("api_code", resp.ApiCode), - zap.String("data_preview", string(resp.Data[:min(100, len(resp.Data))])), - ) - // 使用空结构,不返回错误 - data = judicialProductData{} - } - result.JudicialData = &data - case "JRZQ9D4E": - var data contentsProductData - if err := json.Unmarshal(resp.Data, &data); err != nil { - log.Warn("解析JRZQ9D4E数据失败,使用兼容处理", - zap.Error(err), - zap.String("api_code", resp.ApiCode), - zap.String("data_preview", string(resp.Data[:min(100, len(resp.Data))])), - ) - // 使用空结构,不返回错误 - data = contentsProductData{} - } - result.ContentsData = &data - case "JRZQ6F2A": - var data riskScreenProductData - if err := json.Unmarshal(resp.Data, &data); err != nil { - log.Warn("解析JRZQ6F2A数据失败,使用兼容处理", - zap.Error(err), - zap.String("api_code", resp.ApiCode), - zap.String("data_preview", string(resp.Data[:min(100, len(resp.Data))])), - ) - // 使用空结构,不返回错误 - data = riskScreenProductData{} - } - result.RiskScreen = &data - default: - log.Debug("未知的子产品API代码,跳过", - zap.String("api_code", resp.ApiCode), - zap.String("parent_api_code", "COMBHZY2"), - ) - } - } - - if result.BaseData == nil { - log.Warn("未获取到DWBG8B4D核心数据,将使用空结构", - zap.String("api_code", "COMBHZY2"), - ) - // 使用空结构,不返回错误,让后续处理能够继续 - result.BaseData = &baseProductData{} - } - - return result, nil -} - -// min 辅助函数,返回两个整数中的较小值 -func min(a, b int) int { - if a < b { - return a - } - return b -} - -// ======================= -// 构建目标报告 -// ======================= - -// buildTargetReport 将上下文数据映射为 target.json 完整结构 -func buildTargetReport(ctx context.Context, sourceCtx *sourceContext) targetReport { - log := logger.GetGlobalLogger() - - // 使用recover捕获panic,确保不会导致整个请求失败 - defer func() { - if r := recover(); r != nil { - log.Error("构建目标报告时发生panic,使用默认值", - zap.Any("panic", r), - zap.String("api_code", "COMBHZY2"), - ) - } - }() - - report := targetReport{ - ReportSummary: buildReportSummary(ctx, sourceCtx), - BasicInfo: buildBasicInfo(ctx, sourceCtx), - RiskIdentification: buildRiskIdentification(ctx, sourceCtx), - CreditAssessment: buildCreditAssessment(ctx, sourceCtx), - LeasingRiskAssessment: buildLeasingRiskAssessment(ctx, sourceCtx), - ComprehensiveAnalysis: buildComprehensiveAnalysis(ctx, sourceCtx), - ReportFooter: buildReportFooter(ctx, sourceCtx), - } - - return report -} - -// buildReportSummary 组装 reportSummary,包括规则、反欺诈信息 -func buildReportSummary(ctx context.Context, sourceCtx *sourceContext) reportSummary { - log := logger.GetGlobalLogger() - const strategyCode = "STR0042314/贷前-经营性租赁全量策略" - - summary := reportSummary{ - RuleValidation: summaryRuleValidation{ - Code: strategyCode, - Result: "未命中", - }, - AntiFraudScore: summaryAntiFraudScore{ - Level: "未命中", - }, - AntiFraudRule: summaryAntiFraudRule{ - Level: "未命中", - Code: strategyCode, - }, - AbnormalRulesHit: abnormalHit{ - Count: 0, - Alert: "无风险", - }, - } - - if sourceCtx == nil || sourceCtx.BaseData == nil { - log.Warn("BaseData为空,使用默认summary值", - zap.String("api_code", "COMBHZY2"), - ) - return summary - } - - // 兼容处理:安全访问字段 - verifyResult := "" - if sourceCtx.BaseData.VerifyRule != "" { - verifyResult = strings.TrimSpace(sourceCtx.BaseData.VerifyRule) - } - if verifyResult == "" { - verifyResult = "未命中" - } - summary.RuleValidation.Result = verifyResult - - scoreLevel := riskLevelFromScore(sourceCtx.BaseData.FraudScore) - summary.AntiFraudScore.Level = scoreLevel - - fraudRuleLevel := "" - if sourceCtx.BaseData.FraudRule != "" { - fraudRuleLevel = strings.TrimSpace(sourceCtx.BaseData.FraudRule) - } - if fraudRuleLevel == "" || fraudRuleLevel == "-" { - fraudRuleLevel = "未命中" - } - summary.AntiFraudRule.Level = fraudRuleLevel - - // 兼容处理:安全访问RiskWarning - riskCount := 0 - if sourceCtx.BaseData.RiskWarning.TotalRiskCounts > 0 { - riskCount = sourceCtx.BaseData.RiskWarning.TotalRiskCounts - } - summary.AbnormalRulesHit.Count = riskCount - summary.AbnormalRulesHit.Alert = buildRiskWarningAlert(sourceCtx.BaseData.RiskWarning) - - return summary -} - -// buildBasicInfo 组装 basicInfo,包含基础信息与核验列表 -func buildBasicInfo(ctx context.Context, sourceCtx *sourceContext) reportBasicInfo { - log := logger.GetGlobalLogger() - - // 兼容处理:安全访问BaseData和BaseInfo - var base baseInfo - if sourceCtx != nil && sourceCtx.BaseData != nil { - base = sourceCtx.BaseData.BaseInfo - } else { - log.Warn("BaseData或BaseInfo为空,使用默认值", - zap.String("api_code", "COMBHZY2"), - ) - base = baseInfo{} - } - - reportID := generateReportID() - - verifications := make([]verificationItem, 0, 5) - - elementResult, elementDetails := buildElementVerificationResult(sourceCtx) - verifications = append(verifications, verificationItem{ - Item: "要素核查", - Description: "使用姓名、手机号、身份证信息进行三要素核验", - Result: elementResult, - Details: elementDetails, - }) - - carrierResult, carrierDetails := buildCarrierVerificationResult(sourceCtx) - verifications = append(verifications, verificationItem{ - Item: "运营商检验", - Description: "检查手机号在运营商处的状态及在线时长", - Result: carrierResult, - Details: carrierDetails, - }) - - // 兼容处理:从DWBG8B4D.multCourtInfo获取司法记录条数,并按案件类型拆分 - totalExecution := 0 - totalDishonest := 0 - totalRestriction := 0 - criminalCount := 0 - civilCount := 0 - administrativeCount := 0 - preservationCount := 0 - bankruptCount := 0 - - if sourceCtx != nil && sourceCtx.BaseData != nil { - mc := sourceCtx.BaseData.MultCourtInfo - totalExecution = safeLen(mc.ExecutionCases) - totalDishonest = safeLen(mc.DisinCases) - totalRestriction = safeLen(mc.LimitCases) - - for _, c := range mc.LegalCases { - switch strings.TrimSpace(c.CaseType) { - case "刑事案件": - criminalCount++ - case "民事案件": - civilCount++ - case "行政案件": - administrativeCount++ - case "保全审查": - preservationCount++ - case "破产清算": - bankruptCount++ - default: - // 其它类型暂不单独展示,只参与是否有司法记录的判断 - civilCount++ - } - } - } - - totalLegal := criminalCount + civilCount + administrativeCount + preservationCount + bankruptCount - - if totalLegal > 0 || totalExecution > 0 || totalDishonest > 0 || totalRestriction > 0 { - detailParts := make([]string, 0, 8) - addCaseDetail := func(label string, count int) { - if count > 0 { - detailParts = append(detailParts, fmt.Sprintf("%s%d条", label, count)) - } - } - - addCaseDetail("刑事案件", criminalCount) - addCaseDetail("民事案件", civilCount) - addCaseDetail("行政案件", administrativeCount) - addCaseDetail("保全审查案件", preservationCount) - addCaseDetail("强制清算与破产案件", bankruptCount) - addCaseDetail("执行案件", totalExecution) - addCaseDetail("失信案件", totalDishonest) - addCaseDetail("限高案件", totalRestriction) - - details := buildCaseDetails(detailParts) - verifications = append(verifications, verificationItem{ - Item: "法院信息", - Description: "检测被查询人的借贷风险情况,及在司法体系中是否存在行为风险", - Result: "高风险", - Details: details, - }) - } else { - verifications = append(verifications, verificationItem{ - Item: "法院信息", - Description: "检测被查询人的借贷风险情况,及在司法体系中是否存在行为风险", - Result: "未命中", - }) - } - - loanRiskResult, loanRiskDetails := buildLoanRiskResult(sourceCtx) - verifications = append(verifications, verificationItem{ - Item: "借贷评估", - Description: "综合近12个月借贷申请情况评估风险", - Result: loanRiskResult, - Details: loanRiskDetails, - }) - - otherDetails := gatherOtherRiskDetails(sourceCtx) - if otherDetails != "" { - verifications = append(verifications, verificationItem{ - Item: "其他", - Description: "其它规则风险", - Result: otherDetails, - }) - } - - return reportBasicInfo{ - Name: base.Name, - Phone: base.Phone, - IdCard: base.IdCard, - ReportID: reportID, - Verifications: verifications, - } -} - -// safeLen 安全获取切片长度,避免nil指针 -func safeLen[T any](s []T) int { - if s == nil { - return 0 - } - return len(s) -} - -// buildRiskIdentification 组装 riskIdentification,各列表对标 target.json -func buildRiskIdentification(ctx context.Context, sourceCtx *sourceContext) riskIdentification { - log := logger.GetGlobalLogger() - - identification := riskIdentification{ - Title: "风险识别产品", - CaseAnnouncements: caseAnnouncementSection{ - Title: "涉案公告列表", - Records: make([]caseAnnouncementRecord, 0), - }, - EnforcementAnnouncements: enforcementAnnouncementSection{ - Title: "执行公告列表", - Records: make([]enforcementAnnouncementRecord, 0), - }, - DishonestAnnouncements: dishonestAnnouncementSection{ - Title: "失信公告列表", - Records: make([]dishonestAnnouncementRecord, 0), - }, - HighConsumptionRestrictionAnn: highRestrictionAnnouncementSection{ - Title: "限高公告列表", - Records: make([]highRestrictionAnnouncementRecord, 0), - }, - } - - // 兼容处理:从DWBG8B4D.multCourtInfo获取司法信息 - if sourceCtx == nil || sourceCtx.BaseData == nil { - log.Debug("BaseData为空,返回空的风险识别数据", - zap.String("api_code", "COMBHZY2"), - ) - return identification - } - mc := sourceCtx.BaseData.MultCourtInfo - baseName := "" - baseID := "" - baseName = sourceCtx.BaseData.BaseInfo.Name - baseID = sourceCtx.BaseData.BaseInfo.IdCard - - // 涉案公告列表:直接使用multCourtInfo.legalCases - caseRecords := make([]caseAnnouncementRecord, 0) - for _, c := range mc.LegalCases { - record := caseAnnouncementRecord{ - CaseNumber: defaultIfEmpty(c.CaseNumber, "-"), - CaseType: defaultIfEmpty(c.CaseType, "-"), - FilingDate: defaultIfEmpty(c.FilingTime, ""), - Authority: defaultIfEmpty(c.Court, ""), - } - caseRecords = append(caseRecords, record) - } - identification.CaseAnnouncements.Records = caseRecords - - // 执行公告列表:multCourtInfo.executionCases - enfRecords := make([]enforcementAnnouncementRecord, 0, len(mc.ExecutionCases)) - for _, c := range mc.ExecutionCases { - amountStr := strings.TrimSpace(c.ExecutionAmount) - targetAmount := "-" - if amountStr != "" && amountStr != "-" { - targetAmount = formatCurrencyYuan(parseFloatSafe(amountStr)) - } - record := enforcementAnnouncementRecord{ - CaseNumber: defaultIfEmpty(c.CaseNumber, "-"), - TargetAmount: targetAmount, - FilingDate: defaultIfEmpty(c.FilingTime, ""), - Court: defaultIfEmpty(c.Court, ""), - Status: defaultIfEmpty(c.CaseStatus, "-"), - } - enfRecords = append(enfRecords, record) - } - identification.EnforcementAnnouncements.Records = enfRecords - - // 失信公告列表:multCourtInfo.disinCases - dishonestRecords := make([]dishonestAnnouncementRecord, 0, len(mc.DisinCases)) - for _, item := range mc.DisinCases { - record := dishonestAnnouncementRecord{ - DishonestPerson: defaultIfEmpty(baseName, "-"), - IdCard: defaultIfEmpty(baseID, "-"), - Court: defaultIfEmpty(item.Court, ""), - FilingDate: defaultIfEmpty(item.FilingTime, item.DisposalTime), - PerformanceStatus: defaultIfEmpty(item.JudgmentResult, defaultIfEmpty(item.CaseStatus, "-")), - } - dishonestRecords = append(dishonestRecords, record) - } - identification.DishonestAnnouncements.Records = dishonestRecords - - // 限高公告列表:multCourtInfo.limitCases - limitRecords := make([]highRestrictionAnnouncementRecord, 0, len(mc.LimitCases)) - for _, item := range mc.LimitCases { - record := highRestrictionAnnouncementRecord{ - RestrictedPerson: defaultIfEmpty(baseName, "-"), - IdCard: defaultIfEmpty(baseID, "-"), - Court: defaultIfEmpty(item.Court, ""), - StartDate: defaultIfEmpty(item.FilingTime, item.DisposalTime), - Measure: "限制高消费", - } - limitRecords = append(limitRecords, record) - } - identification.HighConsumptionRestrictionAnn.Records = limitRecords - - return identification -} - -// buildCreditAssessment 组装 creditAssessment,包含客户类型与异常时间段 -func buildCreditAssessment(ctx context.Context, sourceCtx *sourceContext) creditAssessment { - log := logger.GetGlobalLogger() - - assessment := creditAssessment{ - Title: "信贷评估产品", - LoanIntentionByCustomerType: assessmentSection[loanIntentionRecord]{ - Title: "本人在各类机构的借贷意向表现", - Records: []loanIntentionRecord{}, - }, - LoanIntentionAbnormalTimes: assessmentSection[abnormalTimeRecord]{ - Title: "异常时间段借贷申请情况", - Records: []abnormalTimeRecord{}, - }, - } - - // 兼容处理:安全提取指标 - metrics := extractApplyLoanMetrics(sourceCtx) - if len(metrics) == 0 { - log.Debug("未获取到借贷指标数据,返回空的信贷评估", - zap.String("api_code", "COMBHZY2"), - ) - return assessment - } - - totalBankKeys := []string{"als_m12_id_bank_allnum", "als_m12_cell_bank_allnum"} - totalNonBankKeys := []string{"als_m12_id_nbank_allnum", "als_m12_cell_nbank_allnum"} - bankNightKeys := []string{"als_m12_id_bank_night_allnum", "als_m12_cell_bank_night_allnum"} - nonBankNightKeys := []string{"als_m12_id_nbank_night_allnum", "als_m12_cell_nbank_night_allnum"} - bankWeekKeys := []string{"als_m12_id_bank_week_allnum", "als_m12_cell_bank_week_allnum"} - nonBankWeekKeys := []string{"als_m12_id_nbank_week_allnum", "als_m12_cell_nbank_week_allnum"} - - customerMappings := []struct { - CustomerType string - Keys []string - }{ - {"持牌网络小贷", []string{"als_m12_id_nbank_nsloan_allnum", "als_m12_cell_nbank_nsloan_allnum"}}, - {"持牌消费金融", []string{"als_m12_id_nbank_cons_allnum", "als_m12_cell_nbank_cons_allnum"}}, - {"持牌融资租赁机构", []string{"als_m12_id_nbank_finlea_allnum", "als_m12_cell_nbank_finlea_allnum"}}, - {"持牌汽车金融", []string{"als_m12_id_nbank_autofin_allnum", "als_m12_cell_nbank_autofin_allnum"}}, - {"其他非银机构", []string{"als_m12_id_nbank_else_allnum", "als_m12_id_nbank_oth_allnum", "als_m12_cell_nbank_else_allnum", "als_m12_cell_nbank_oth_allnum"}}, - } - - for _, mapping := range customerMappings { - count := sumMetrics(metrics, mapping.Keys...) - record := loanIntentionRecord{ - CustomerType: mapping.CustomerType, - ApplicationCount: count, - RiskLevel: riskLevelFromCount(count), - } - assessment.LoanIntentionByCustomerType.Records = append(assessment.LoanIntentionByCustomerType.Records, record) - } - - timeMappings := []struct { - TimePeriod string - Pairs []struct { - Label string - Count int - } - }{ - { - TimePeriod: "夜间(22:00-06:00)", - Pairs: []struct { - Label string - Count int - }{ - {"银行类机构", sumMetrics(metrics, bankNightKeys...)}, - {"非银金融机构", sumMetrics(metrics, nonBankNightKeys...)}, - }, - }, - { - TimePeriod: "周末", - Pairs: []struct { - Label string - Count int - }{ - {"银行类机构", sumMetrics(metrics, bankWeekKeys...)}, - {"非银金融机构", sumMetrics(metrics, nonBankWeekKeys...)}, - }, - }, - { - TimePeriod: "工作日工作时间", - Pairs: []struct { - Label string - Count int - }{ - {"银行类机构", sumMetrics(metrics, totalBankKeys...) - sumMetrics(metrics, append(bankNightKeys, bankWeekKeys...)...)}, - {"非银金融机构", sumMetrics(metrics, totalNonBankKeys...) - sumMetrics(metrics, append(nonBankNightKeys, nonBankWeekKeys...)...)}, - }, - }, - } - - for _, mapping := range timeMappings { - labels := make([]string, 0, len(mapping.Pairs)) - totalCount := 0 - for _, pair := range mapping.Pairs { - count := pair.Count - if count < 0 { - count = 0 - } - totalCount += count - if count > 0 && !containsLabel(labels, pair.Label) { - labels = append(labels, pair.Label) - } - } - - if len(labels) == 0 { - labels = append(labels, "无机构命中") - } - - record := abnormalTimeRecord{ - TimePeriod: mapping.TimePeriod, - MainInstitutionType: joinWithChineseComma(labels), - } - if mapping.TimePeriod == "工作日工作时间" { - record.RiskLevel = riskLevelFromCount(totalCount) - } else { - record.RiskLevel = riskLevelFromStrictCount(totalCount) - } - assessment.LoanIntentionAbnormalTimes.Records = append(assessment.LoanIntentionAbnormalTimes.Records, record) - } - - return assessment -} - -// buildLeasingRiskAssessment 组装 leasingRiskAssessment 中的 3C 多头信息 -func buildLeasingRiskAssessment(ctx context.Context, sourceCtx *sourceContext) leasingRiskAssessment { - log := logger.GetGlobalLogger() - - assessment := leasingRiskAssessment{ - Title: "租赁风险评估产品", - MultiLender3C: assessmentSection[multiLenderRecord]{ - Title: "3C机构多头借贷风险", - Records: []multiLenderRecord{}, - }, - } - - // 兼容处理:安全访问ContentsData - if sourceCtx == nil || sourceCtx.ContentsData == nil || len(sourceCtx.ContentsData.Contents) == 0 { - log.Debug("ContentsData为空或Contents为空,返回空的租赁风险评估", - zap.String("api_code", "COMBHZY2"), - ) - return assessment - } - - contents := sourceCtx.ContentsData.Contents - - // 消费金融机构指标,优先使用近12个月的机构数,其次退化到近一年内的其它统计 - consumerApplied := pickFirstInt(contents, "BH_A074", "BH_A065", "BH_A055") - consumerInUse := pickFirstInt(contents, "BH_F004") - consumerCredit := pickFirstFloat(contents, "BH_E044", "BH_E034", "BH_E014") - consumerDebt := pickFirstFloat(contents, "BH_F014", "BH_B264", "BH_B238") - assessment.MultiLender3C.Records = append(assessment.MultiLender3C.Records, multiLenderRecord{ - InstitutionType: "消费金融", - AppliedCount: consumerApplied, - InUseCount: consumerInUse, - TotalCreditLimit: consumerCredit, - TotalDebtBalance: consumerDebt, - RiskLevel: riskLevelFromCount(consumerApplied), - }) - - // 小贷公司指标,同样按优先级取值 - smallApplied := pickFirstInt(contents, "BH_A093", "BH_A084", "BH_A075") - smallInUse := pickFirstInt(contents, "BH_F005") - smallCredit := pickFirstFloat(contents, "BH_E045", "BH_E035", "BH_E015") - smallDebt := pickFirstFloat(contents, "BH_F015", "BH_B266", "BH_B239") - assessment.MultiLender3C.Records = append(assessment.MultiLender3C.Records, multiLenderRecord{ - InstitutionType: "小贷公司", - AppliedCount: smallApplied, - InUseCount: smallInUse, - TotalCreditLimit: smallCredit, - TotalDebtBalance: smallDebt, - RiskLevel: riskLevelFromCount(smallApplied), - }) - - // 其它非银机构通过"非银机构"总量减去已统计的两类机构,避免缺失字段导致的重复 - totalNonBankApplied := pickFirstInt(contents, "BH_A355", "BH_A344", "BH_A339") - otherApplied := totalNonBankApplied - consumerApplied - smallApplied - if otherApplied < 0 { - otherApplied = 0 - } - - totalInUse := pickFirstInt(contents, "BH_F003") - otherInUse := totalInUse - consumerInUse - smallInUse - if otherInUse < 0 { - otherInUse = 0 - } - - totalCredit := pickFirstFloat(contents, "BH_E046", "BH_E032") - otherCredit := totalCredit - consumerCredit - smallCredit - if otherCredit < 0 { - otherCredit = 0 - } - - totalDebt := pickFirstFloat(contents, "BH_F013", "BH_B262", "BH_B274") - otherDebt := totalDebt - consumerDebt - smallDebt - if otherDebt < 0 { - otherDebt = 0 - } - - assessment.MultiLender3C.Records = append(assessment.MultiLender3C.Records, multiLenderRecord{ - InstitutionType: "其他非银机构", - AppliedCount: otherApplied, - InUseCount: otherInUse, - TotalCreditLimit: otherCredit, - TotalDebtBalance: otherDebt, - RiskLevel: riskLevelFromCount(otherApplied), - }) - - return assessment -} - -// buildComprehensiveAnalysis 汇总最终的文字结论(仅输出存在风险的要点) -func buildComprehensiveAnalysis(ctx context.Context, sourceCtx *sourceContext) []string { - log := logger.GetGlobalLogger() - - analysis := make([]string, 0, 8) - if sourceCtx == nil || sourceCtx.BaseData == nil { - log.Debug("BaseData为空,返回空的综合分析", - zap.String("api_code", "COMBHZY2"), - ) - return analysis - } - - summary := buildReportSummary(ctx, sourceCtx) - highRiskDetected := false - mediumRiskDetected := false - - if msg, high, medium := buildRuleSummaryBullet(summary); msg != "" { - analysis = append(analysis, msg) - highRiskDetected = highRiskDetected || high - mediumRiskDetected = mediumRiskDetected || medium - } - - if msg, high, medium := buildRuleHitBullet(summary); msg != "" { - analysis = append(analysis, msg) - highRiskDetected = highRiskDetected || high - mediumRiskDetected = mediumRiskDetected || medium - } - - judicialBullet, judicialHigh, judicialMedium := buildJudicialBullet(sourceCtx) - if judicialBullet != "" { - analysis = append(analysis, judicialBullet) - highRiskDetected = highRiskDetected || judicialHigh - mediumRiskDetected = mediumRiskDetected || judicialMedium - } - - if msg, high, medium := buildLoanAssessmentBullet(ctx, sourceCtx); msg != "" { - analysis = append(analysis, msg) - highRiskDetected = highRiskDetected || high - mediumRiskDetected = mediumRiskDetected || medium - } - - if msg, high, medium := buildOtherRiskBullet(sourceCtx, judicialBullet != ""); msg != "" { - analysis = append(analysis, msg) - highRiskDetected = highRiskDetected || high - mediumRiskDetected = mediumRiskDetected || medium - } - - if msg, high, medium := buildMultiLenderBullet(ctx, sourceCtx); msg != "" { - analysis = append(analysis, msg) - highRiskDetected = highRiskDetected || high - mediumRiskDetected = mediumRiskDetected || medium - } - - // 兼容处理:安全访问RiskWarning - risk := sourceCtx.BaseData.RiskWarning - if hasHighRiskHit(risk) { - highRiskDetected = true - } else if hasMediumRiskHit(risk) { - mediumRiskDetected = true - } - - if highRiskDetected { - analysis = append(analysis, "风险提示:系统识别出该用户存在多项高风险因素,建议谨慎评估信用状况并加强风险管控措施。") - } else if mediumRiskDetected { - analysis = append(analysis, "风险提示:系统识别出该用户存在一定风险因素,建议保持关注并做好人工复核。") - } - - return analysis -} - -// buildReportFooter 填充数据来源与免责声明 -func buildReportFooter(ctx context.Context, sourceCtx *sourceContext) reportFooter { - return reportFooter{ - DataSource: "海宇数据报告", - GenerationTime: time.Now().Format("2006-01-02"), - Disclaimer: fmt.Sprintf("本报告基于%s数据生成,仅供参考,具体审批以最终审核为准。", time.Now().Format("2006-01-02")), - } -} - -// ======================= -// 工具函数 -// ======================= - -// mapDecision 翻译风控决策枚举值 -func mapDecision(decision string) string { - switch strings.ToLower(decision) { - case "accept": - return "通过" - case "reject": - return "拒绝" - case "review": - return "需复核" - } - return "未知" -} - -// mapDecisionLevel 将决策映射到风险等级描述 -func mapDecisionLevel(decision string) string { - switch strings.ToLower(decision) { - case "accept": - return "正常" - case "reject": - return "高风险" - case "review": - return "需人工复核" - } - return "" -} - -// firstModelSceneCode 获取模型列表中的首个场景编码 -func firstModelSceneCode(models []riskScreenModel) string { - if len(models) == 0 { - return "" - } - return models[0].SceneCode -} - -// riskLevelFromCount 根据命中次数给出风险等级 -func riskLevelFromCount(count int) string { - switch { - case count <= 0: - return "无风险" - case count < 6: - return "低风险" - case count <= 12: - return "中风险" - default: - return "高风险" - } -} - -// riskLevelFromScore 根据 fraudScore 数值映射风险等级 -func riskLevelFromScore(score int) string { - switch { - case score < 0: - return "未命中" - case score <= 59: - return "低风险" - case score <= 79: - return "中风险" - case score <= 100: - return "高风险" - default: - return "未命中" - } -} - -// buildRiskWarningAlert 依据 riskWarning 中的命中情况给出提示级别 -func buildRiskWarningAlert(r riskWarning) string { - if hasHighRiskHit(r) { - return "高风险提示" - } - if hasMediumRiskHit(r) { - return "中风险提示" - } - return "无风险" -} - -// defaultIfEmpty 当原值为空时回退至默认值 -func defaultIfEmpty(val, fallback string) string { - if strings.TrimSpace(val) == "" { - return fallback - } - return val -} - -// mapRiskFlag 将风险标记的数值型结果转换为文本 -func mapRiskFlag(flag int) string { - switch flag { - case 0: - return "未命中" - case 1: - return "异常" - case 2: - return "正常" - default: - return "未知" - } -} - -// gatherOtherRiskDetails 汇总其它风险命中项的说明文本 -func gatherOtherRiskDetails(sourceCtx *sourceContext) string { - if sourceCtx == nil || sourceCtx.BaseData == nil { - return "" - } - hits := make([]string, 0, 4) - // 兼容处理:安全访问RiskWarning - risk := sourceCtx.BaseData.RiskWarning - if risk.IsAntiFraudInfo > 0 { - hits = append(hits, "涉赌涉诈风险") - } - if risk.PhoneThreeElementMismatch > 0 { - hits = append(hits, "手机号三要素不一致") - } - if risk.IdCardPhoneProvinceMismatch > 0 { - hits = append(hits, "身份证与手机号归属地不一致") - } - if risk.HasCriminalRecord > 0 { - hits = append(hits, "历史前科记录") - } - if risk.IsEconomyFront > 0 { - hits = append(hits, "经济类前科风险") - } - if risk.IsDisrupSocial > 0 { - hits = append(hits, "妨害社会管理秩序风险") - } - if risk.IsKeyPerson > 0 { - hits = append(hits, "重点人员风险") - } - if risk.IsTrafficRelated > 0 { - hits = append(hits, "涉交通案件风险") - } - if risk.FrequentRentalApplications > 0 { - hits = append(hits, "租赁机构申请极为频繁") - } - if risk.VeryFrequentRentalApplications > 0 { - hits = append(hits, "租赁机构申请次数极多") - } - // 兼容处理:根据DWBG8B4D.multCourtInfo判断是否存在司法记录 - if sourceCtx != nil && sourceCtx.BaseData != nil { - mc := sourceCtx.BaseData.MultCourtInfo - totalCase := safeLen(mc.LegalCases) - totalExecution := safeLen(mc.ExecutionCases) - totalDishonest := safeLen(mc.DisinCases) - totalRestriction := safeLen(mc.LimitCases) - if totalCase > 0 || totalExecution > 0 || totalDishonest > 0 || totalRestriction > 0 { - hits = append(hits, "存在司法风险记录") - } - } - if len(hits) == 0 { - return "" - } - return strings.Join(hits, "、") -} - -func buildRuleSummaryBullet(summary reportSummary) (string, bool, bool) { - type item struct { - label string - level string - } - - items := []item{ - {label: "规则验证", level: strings.TrimSpace(summary.RuleValidation.Result)}, - {label: "反欺诈得分", level: strings.TrimSpace(summary.AntiFraudScore.Level)}, - {label: "反欺诈规则", level: strings.TrimSpace(summary.AntiFraudRule.Level)}, - } - - phrases := make([]string, 0, len(items)) - highLabels := make([]string, 0, len(items)) - riskCount := 0 - highCount := 0 - mediumCount := 0 - - for _, item := range items { - if !isMeaningfulRiskValue(item.level) { - continue - } - riskCount++ - - sentence := fmt.Sprintf("%s结果为%s", item.label, item.level) - - switch { - case strings.Contains(item.level, "高风险"): - highCount++ - highLabels = append(highLabels, item.label) - sentence = fmt.Sprintf("%s判定为高风险", item.label) - case strings.Contains(item.level, "中风险"): - mediumCount++ - sentence = fmt.Sprintf("%s判定为中风险", item.label) - case strings.Contains(item.level, "低风险"): - sentence = fmt.Sprintf("%s判定为低风险", item.label) - default: - sentence = fmt.Sprintf("%s结果为%s", item.label, item.level) - } - - phrases = append(phrases, sentence) - } - - if riskCount == 0 { - return "", false, false - } - - if highCount == riskCount { - subject := joinWithChineseComma(highLabels) - sentence := fmt.Sprintf("该用户%s均为高风险,表明该用户存在较高的信用风险。", subject) - return sentence, true, false - } - - sentence := joinWithChineseComma(phrases) + "。" - high := highCount > 0 - medium := !high && mediumCount > 0 - return sentence, high, medium -} - -func buildRuleHitBullet(summary reportSummary) (string, bool, bool) { - if summary.AbnormalRulesHit.Count <= 0 { - return "", false, false - } - - alert := strings.TrimSpace(summary.AbnormalRulesHit.Alert) - if alert == "" || alert == "无风险" { - return "", false, false - } - - sentence := fmt.Sprintf("系统共识别%d项规则命中(%s)。", summary.AbnormalRulesHit.Count, alert) - if strings.Contains(alert, "高风险") { - return sentence, true, false - } - return sentence, false, true -} - -func buildJudicialBullet(ctx *sourceContext) (string, bool, bool) { - if ctx == nil || ctx.BaseData == nil { - return "", false, false - } - mc := ctx.BaseData.MultCourtInfo - parts := make([]string, 0, 6) - - addPart := func(label string, count int) { - if count > 0 { - parts = append(parts, fmt.Sprintf("%s%d条", label, count)) - } - } - - addPart("涉案公告", len(mc.LegalCases)) - addPart("执行案件", len(mc.ExecutionCases)) - addPart("失信记录", len(mc.DisinCases)) - addPart("限高记录", len(mc.LimitCases)) - - if len(parts) == 0 { - return "", false, false - } - - sentence := "法院信息显示" + joinWithChineseComma(parts) + ",属于司法高风险因素。" - return sentence, true, false -} - -func buildLoanAssessmentBullet(ctx context.Context, sourceCtx *sourceContext) (string, bool, bool) { - assessment := buildCreditAssessment(ctx, sourceCtx) - records := assessment.LoanIntentionByCustomerType.Records - if len(records) == 0 { - return "", false, false - } - - type phrase struct { - text string - level string - } - - phrases := make([]phrase, 0, len(records)) - high := false - medium := false - - for _, record := range records { - level := strings.TrimSpace(record.RiskLevel) - if level == "" || level == "无风险" || level == "低风险" { - continue - } - - txt := fmt.Sprintf("%s近12个月申请机构数%d家,风险等级为%s", record.CustomerType, record.ApplicationCount, level) - phrases = append(phrases, phrase{text: txt, level: level}) - - if level == "高风险" { - high = true - } else { - medium = true - } - } - - if len(phrases) == 0 { - return "", false, false - } - - parts := make([]string, len(phrases)) - for i, p := range phrases { - parts[i] = p.text - } - - sentence := "借贷评估显示" + joinWithChineseComma(parts) + "。" - return sentence, high, medium -} - -func buildMultiLenderBullet(ctx context.Context, sourceCtx *sourceContext) (string, bool, bool) { - assessment := buildCreditAssessment(ctx, sourceCtx) - records := assessment.LoanIntentionAbnormalTimes.Records - if len(records) == 0 { - return "", false, false - } - - phrases := make([]string, 0, len(records)) - high := false - medium := false - - for _, record := range records { - level := strings.TrimSpace(record.RiskLevel) - if level == "" || level == "无风险" || strings.Contains(record.MainInstitutionType, "无机构命中") { - continue - } - - phrases = append(phrases, fmt.Sprintf("%s阶段主要由%s发起,风险等级为%s", record.TimePeriod, record.MainInstitutionType, level)) - - if level == "高风险" { - high = true - } else { - medium = true - } - } - - if len(phrases) == 0 { - return "", false, false - } - - sentence := "多头借贷风险在" + joinWithChineseComma(phrases) + "。" - return sentence, high, medium -} - -func buildOtherRiskBullet(ctx *sourceContext, skipJudicial bool) (string, bool, bool) { - otherDetails := gatherOtherRiskDetails(ctx) - if otherDetails == "" { - return "", false, false - } - - items := strings.Split(otherDetails, "、") - filtered := make([]string, 0, len(items)) - high := false - medium := false - - for _, item := range items { - trimmed := strings.TrimSpace(item) - if trimmed == "" { - continue - } - if skipJudicial && trimmed == "存在司法风险记录" { - continue - } - filtered = append(filtered, trimmed) - - if strings.Contains(trimmed, "涉赌") || strings.Contains(trimmed, "前科") || strings.Contains(trimmed, "重点人员") { - high = true - } else { - medium = true - } - } - - if len(filtered) == 0 { - return "", high, medium - } - - sentence := "其他风险因素包括:" + joinWithChineseComma(filtered) + "。" - return sentence, high, medium -} - -func isMeaningfulRiskValue(value string) bool { - if value == "" { - return false - } - normalized := strings.ReplaceAll(value, " ", "") - switch normalized { - case "-", "未命中", "无风险", "正常": - return false - } - return true -} - -func updateSeverityFlags(value string, high, medium bool) (bool, bool) { - switch { - case strings.Contains(value, "高风险"): - high = true - case strings.Contains(value, "中风险"): - medium = true - case strings.Contains(value, "低风险"), strings.Contains(value, "命中"): - medium = true - } - return high, medium -} - -// parseRatio 解析类似 "3/2" 的分子分母格式 -func parseRatio(value string) (int, int) { - parts := strings.Split(value, "/") - if len(parts) != 2 { - return parseIntSafe(value), 0 - } - return parseIntSafe(parts[0]), parseIntSafe(parts[1]) -} - -// parseIntSafe 安全地将字符串转为整数 -func parseIntSafe(value string) int { - value = strings.TrimSpace(value) - if value == "" || value == "-" { - return 0 - } - result, err := strconv.Atoi(value) - if err != nil { - return 0 - } - return result -} - -// parseFloatSafe 安全地解析字符串为浮点数 -func parseFloatSafe(value string) float64 { - value = strings.TrimSpace(value) - if value == "" || value == "-" { - return 0 - } - result, err := strconv.ParseFloat(value, 64) - if err != nil { - return 0 - } - return result -} - -// getContentInt 从 JRZQ9D4E contents 中读取整数值 -func getContentInt(contents map[string]string, key string) int { - if contents == nil { - return 0 - } - if val, ok := contents[key]; ok { - return parseIntSafe(val) - } - return 0 -} - -// getContentFloat 从 JRZQ9D4E contents 中读取浮点数字段 -func getContentFloat(contents map[string]string, key string) float64 { - if contents == nil { - return 0 - } - if val, ok := contents[key]; ok { - return parseFloatSafe(val) - } - return 0 -} - -// pickFirstInt 依次尝试多个 key,返回首个非零整数 -func pickFirstInt(contents map[string]string, keys ...string) int { - for _, key := range keys { - if v := getContentInt(contents, key); v != 0 { - return v - } - } - return 0 -} - -// pickFirstFloat 依次尝试多个 key,返回首个非零浮点数 -func pickFirstFloat(contents map[string]string, keys ...string) float64 { - for _, key := range keys { - if v := getContentFloat(contents, key); v != 0 { - return v - } - } - return 0 -} - -// convertCaseAnnouncements 转换各类案件记录为 target 所需的涉案公告结构 -func convertCaseAnnouncements(cases []judicialCase, defaultType string) []caseAnnouncementRecord { - records := make([]caseAnnouncementRecord, 0, len(cases)) - for _, c := range cases { - caseType := defaultType - if caseType == "" { - caseType = caseTypeName(c.CaseType) - } - record := caseAnnouncementRecord{ - CaseNumber: c.CaseNumber, - Authority: c.Court, - FilingDate: c.FilingDate, - CaseType: caseType, - } - records = append(records, record) - } - return records -} - -// convertEnforcementAnnouncements 转换执行案件数据为执行公告列表 -func convertEnforcementAnnouncements(cases []judicialCase) []enforcementAnnouncementRecord { - records := make([]enforcementAnnouncementRecord, 0, len(cases)) - for _, c := range cases { - record := enforcementAnnouncementRecord{ - CaseNumber: c.CaseNumber, - TargetAmount: formatCurrencyYuan(c.ApplyAmount), - FilingDate: c.FilingDate, - Court: c.Court, - Status: defaultIfEmpty(c.CaseStatus, "-"), - } - records = append(records, record) - } - return records -} - -// convertDishonestAnnouncements 将失信记录转为失信公告列表 -func convertDishonestAnnouncements(items []breachCase, name, id string) []dishonestAnnouncementRecord { - records := make([]dishonestAnnouncementRecord, 0, len(items)) - for _, item := range items { - record := dishonestAnnouncementRecord{ - DishonestPerson: name, - IdCard: id, - Court: item.ExecutiveCourt, - FilingDate: defaultIfEmpty(item.FileDate, item.IssueDate), - PerformanceStatus: defaultIfEmpty(item.FulfillStatus, "-"), - } - records = append(records, record) - } - return records -} - -// convertConsumptionRestrictions 将限高记录转为限高公告列表 -func convertConsumptionRestrictions(items []consumptionRestriction, name, id string) []highRestrictionAnnouncementRecord { - records := make([]highRestrictionAnnouncementRecord, 0, len(items)) - for _, item := range items { - record := highRestrictionAnnouncementRecord{ - RestrictedPerson: name, - IdCard: id, - Court: item.ExecutiveCourt, - StartDate: item.IssueDate, - Measure: "限制高消费", - } - records = append(records, record) - } - return records -} - -// caseTypeName 根据案件类型编码给出默认名称 -func caseTypeName(code int) string { - switch code { - case 100: - return "民事案件" - case 200: - return "刑事案件" - case 300: - return "行政案件" - default: - return "" - } -} - -// formatCurrencyYuan 将金额格式化为"千分位+元",为空时返回 "-" -func formatCurrencyYuan(amount float64) string { - if amount <= 0 { - return "-" - } - val := strconv.FormatFloat(amount, 'f', 2, 64) - parts := strings.Split(val, ".") - intPart := addThousandsSeparator(parts[0]) - if len(parts) == 2 && strings.TrimRight(parts[1], "0") != "" { - return intPart + "." + strings.TrimRight(parts[1], "0") + "元" - } - return intPart + "元" -} - -// addThousandsSeparator 为整数部分添加千分位分隔 -func addThousandsSeparator(value string) string { - if len(value) <= 3 { - return value - } - var builder strings.Builder - mod := len(value) % 3 - if mod == 0 { - mod = 3 - } - builder.WriteString(value[:mod]) - for i := mod; i < len(value); i += 3 { - builder.WriteString(",") - builder.WriteString(value[i : i+3]) - } - return builder.String() -} - -// buildLoanRiskResult 根据 riskWarning 命中情况生成借贷评估结果 -func buildLoanRiskResult(sourceCtx *sourceContext) (string, string) { - if sourceCtx == nil || sourceCtx.BaseData == nil { - return "正常", "" - } - - // 兼容处理:安全访问RiskWarning - risk := sourceCtx.BaseData.RiskWarning - hits := make([]string, 0, 3) - - if risk.HitHighRiskBankLastTwoYears > 0 { - hits = append(hits, "命中近两年银行高风险") - } - if risk.HitHighRiskNonBankLastTwoYears > 0 { - hits = append(hits, "命中近两年非银高风险") - } - if risk.HitCurrentOverdue > 0 { - hits = append(hits, "命中当前逾期") - } - - if len(hits) == 0 { - return "正常", "" - } - - result := "命中" - details := strings.Join(hits, "、") - return result, details -} - -// joinWithChineseComma 使用中文顿号串联文本 -func joinWithChineseComma(parts []string) string { - if len(parts) == 0 { - return "" - } - joined := strings.Join(parts, ",") - sep := fmt.Sprintf("%c", rune(0x3001)) - return strings.ReplaceAll(joined, ",", sep) -} - -// buildCaseDetails 兼容旧调用,复用中文顿号拼接逻辑 -func buildCaseDetails(parts []string) string { - return joinWithChineseComma(parts) -} - -// buildElementVerificationResult 根据 riskWarning 的要素相关项生成结果 -func buildElementVerificationResult(sourceCtx *sourceContext) (string, string) { - if sourceCtx == nil || sourceCtx.BaseData == nil { - return "正常", "" - } - // 兼容处理:安全访问RiskWarning - risk := sourceCtx.BaseData.RiskWarning - hits := make([]string, 0, 2) - if risk.IdCardTwoElementMismatch > 0 { - hits = append(hits, "身份证二要素不一致") - } - if risk.PhoneThreeElementMismatch > 0 { - hits = append(hits, "手机号三要素不一致") - } - if len(hits) == 0 { - return "正常", "" - } - return "命中", joinWithChineseComma(hits) -} - -// buildCarrierVerificationResult 根据 riskWarning 的运营商相关项生成结果 -func buildCarrierVerificationResult(sourceCtx *sourceContext) (string, string) { - if sourceCtx == nil || sourceCtx.BaseData == nil { - return "正常", "" - } - // 兼容处理:安全访问RiskWarning - risk := sourceCtx.BaseData.RiskWarning - hits := make([]string, 0, 4) - if risk.ShortPhoneDuration > 0 { - hits = append(hits, "手机在网时长极短") - } - if risk.ShortPhoneDurationSlight > 0 { - hits = append(hits, "手机在网时长较短") - } - if risk.IdCardPhoneProvinceMismatch > 0 { - hits = append(hits, "身份证号手机号归属地不一致") - } - if risk.NoPhoneDuration > 0 { - hits = append(hits, "手机号在网状态异常") - } - if len(hits) == 0 { - return "正常", "" - } - return "命中", joinWithChineseComma(hits) -} - -// generateReportID 生成报告ID(RPT-前缀 + 随机十六进制) -func generateReportID() string { - buf := make([]byte, 4) - if _, err := rand.Read(buf); err != nil { - return time.Now().Format("20060102") + fmt.Sprintf("%010x", time.Now().UnixNano()) - } - datePart := time.Now().Format("20060102") - return datePart + strings.ToUpper(hex.EncodeToString(buf)) -} - -// mapTimeType 将时间段编码映射为展示文案与机构类型 -func mapTimeType(value string) (string, string) { - switch { - case strings.Contains(value, "夜间"): - return "夜间(22:00-06:00)", mapInstitutionType(value) - case strings.Contains(value, "周末"): - return "周末", mapInstitutionType(value) - case strings.Contains(value, "节假日"): - return "节假日", mapInstitutionType(value) - default: - return "工作日", mapInstitutionType(value) - } -} - -// mapInstitutionType 根据描述判断机构大类 -func mapInstitutionType(value string) string { - if strings.Contains(value, "银行") { - return "银行类机构" - } - return "非银金融机构" -} - -// hasHighRiskHit 判断 riskWarning 是否命中任一高风险项 -func hasHighRiskHit(r riskWarning) bool { - return r.FrequentApplicationRecent > 0 || - r.FrequentBankApplications > 0 || - r.FrequentNonBankApplications > 0 || - r.HasCriminalRecord > 0 || - r.HighDebtPressure > 0 || - r.PhoneThreeElementMismatch > 0 || - r.ShortPhoneDuration > 0 || - r.ShortPhoneDurationSlight > 0 || - r.VeryFrequentRentalApplications > 0 || - r.FrequentRentalApplications > 0 || - r.HitCriminalRisk > 0 || - r.HitExecutionCase > 0 || - r.HitHighRiskBankLastTwoYears > 0 || - r.HitHighRiskNonBankLastTwoYears > 0 || - r.HitHighRiskBank > 0 -} - -// hasMediumRiskHit 判断 riskWarning 是否命中任一中风险项 -func hasMediumRiskHit(r riskWarning) bool { - return r.IdCardPhoneProvinceMismatch > 0 || - r.IsAntiFraudInfo > 0 || - r.HitCurrentOverdue > 0 || - r.MoreFrequentBankApplications > 0 || - r.MoreFrequentNonBankApplications > 0 -} - -func extractApplyLoanMetrics(sourceCtx *sourceContext) map[string]int { - // 兼容处理:安全访问RiskScreen - if sourceCtx == nil || sourceCtx.RiskScreen == nil { - return nil - } - - // 兼容处理:安全访问Variables数组 - if sourceCtx.RiskScreen.RiskScreenV2.Variables == nil { - return nil - } - - for _, variable := range sourceCtx.RiskScreen.RiskScreenV2.Variables { - if strings.EqualFold(variable.VariableName, "bairong_applyloan_extend") { - // 兼容处理:安全访问VariableValue - if variable.VariableValue == nil { - continue - } - results := make(map[string]int, len(variable.VariableValue)) - for key, val := range variable.VariableValue { - results[key] = parseMetricValue(val) - } - return results - } - } - - return nil -} - -func parseMetricValue(raw string) int { - trimmed := strings.TrimSpace(raw) - if trimmed == "" || trimmed == "空" || trimmed == "N" { - return 0 - } - value, err := strconv.ParseFloat(trimmed, 64) - if err != nil { - return 0 - } - return int(value + 0.5) -} - -func sumMetrics(metrics map[string]int, keys ...string) int { - idVal := 0 - cellVal := 0 - - for _, key := range keys { - v := metrics[key] - if strings.Contains(key, "_id_") { - if v > idVal { - idVal = v - } - } else if strings.Contains(key, "_cell_") { - if v > cellVal { - cellVal = v - } - } else { - if v > idVal { - idVal = v - } - } - } - - if cellVal > idVal { - return cellVal - } - return idVal -} - -func containsLabel(labels []string, target string) bool { - for _, label := range labels { - if label == target { - return true - } - } - return false -} - -// riskLevelFromStrictCount 特殊时段风险等级(夜间/周末) -func riskLevelFromStrictCount(count int) string { - switch { - case count <= 0: - return "无风险" - case count < 3: - return "低风险" - case count <= 6: - return "中风险" - default: - return "高风险" - } -} diff --git a/internal/domains/api/services/processors/comb/combwd01_processor.go b/internal/domains/api/services/processors/comb/combwd01_processor.go deleted file mode 100644 index 81f4401..0000000 --- a/internal/domains/api/services/processors/comb/combwd01_processor.go +++ /dev/null @@ -1,91 +0,0 @@ -package comb - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/shared/logger" - - "go.uber.org/zap" -) - -// ProcessCOMBWD01Request 处理 COMBWD01 组合包请求 -// 将返回结构从数组改为以 api_code 为 key 的对象结构 -func ProcessCOMBWD01Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - log := logger.GetGlobalLogger() - - // 调用组合包服务处理请求 - combinedResult, err := deps.CombService.ProcessCombRequest(ctx, params, deps, "COMBWD01") - if err != nil { - log.Error("COMBWD01组合包服务调用失败", - zap.Error(err), - zap.String("api_code", "COMBWD01"), - ) - return nil, err - } - - if combinedResult == nil { - log.Error("COMBWD01组合包响应为空", - zap.String("api_code", "COMBWD01"), - ) - return nil, errors.New("组合包响应为空") - } - - log.Info("COMBWD01组合包服务调用成功", - zap.Int("子产品数量", len(combinedResult.Responses)), - zap.String("api_code", "COMBWD01"), - ) - - // 将数组结构转换为对象结构 - responsesMap := make(map[string]*ResponseItem) - for _, resp := range combinedResult.Responses { - item := &ResponseItem{ - ApiCode: resp.ApiCode, - Success: resp.Success, - } - - // 根据成功/失败状态设置 data 和 error 字段 - if resp.Success { - // 成功时:data 有值(可能为 nil),error 为 null - item.Data = resp.Data - item.Error = nil - } else { - // 失败时:data 为 null,error 有值 - item.Data = nil - if resp.Error != "" { - item.Error = resp.Error - } else { - item.Error = "未知错误" - } - } - - responsesMap[resp.ApiCode] = item - } - - // 构建新的响应结构 - result := map[string]interface{}{ - "responses": responsesMap, - } - - // 序列化并返回 - resultBytes, err := json.Marshal(result) - if err != nil { - log.Error("COMBWD01响应序列化失败", - zap.Error(err), - zap.String("api_code", "COMBWD01"), - ) - return nil, errors.Join(processors.ErrSystem, err) - } - - return resultBytes, nil -} - -// ResponseItem 响应项结构 -type ResponseItem struct { - ApiCode string `json:"api_code"` - Success bool `json:"success"` - Data interface{} `json:"data"` - Error interface{} `json:"error"` -} diff --git a/internal/domains/api/services/processors/dependencies.go b/internal/domains/api/services/processors/dependencies.go index c3fbb39..aee4c06 100644 --- a/internal/domains/api/services/processors/dependencies.go +++ b/internal/domains/api/services/processors/dependencies.go @@ -11,7 +11,7 @@ import ( "hyapi-server/internal/infrastructure/external/muzi" "hyapi-server/internal/infrastructure/external/nuoer" "hyapi-server/internal/infrastructure/external/shujubao" - "hyapi-server/internal/infrastructure/external/shumai" + "hyapi-server/internal/infrastructure/external/tianyuanapi" "hyapi-server/internal/infrastructure/external/tianyancha" "hyapi-server/internal/infrastructure/external/westdex" "hyapi-server/internal/infrastructure/external/xingwei" @@ -41,7 +41,7 @@ type ProcessorDependencies struct { ZhichaService *zhicha.ZhichaService XingweiService *xingwei.XingweiService JiguangService *jiguang.JiguangService - ShumaiService *shumai.ShumaiService + TianyuanapiService *tianyuanapi.TianyuanapiService NuoerService *nuoer.NuoerService HuiboService *huibo.HuiboService Validator interfaces.RequestValidator @@ -70,7 +70,7 @@ func NewProcessorDependencies( zhichaService *zhicha.ZhichaService, xingweiService *xingwei.XingweiService, jiguangService *jiguang.JiguangService, - shumaiService *shumai.ShumaiService, + tianyuanapiService *tianyuanapi.TianyuanapiService, nuoerService *nuoer.NuoerService, huiboService *huibo.HuiboService, validator interfaces.RequestValidator, @@ -89,7 +89,7 @@ func NewProcessorDependencies( ZhichaService: zhichaService, XingweiService: xingweiService, JiguangService: jiguangService, - ShumaiService: shumaiService, + TianyuanapiService: tianyuanapiService, NuoerService: nuoerService, HuiboService: huiboService, Validator: validator, diff --git a/internal/domains/api/services/processors/dwbg/dwbg5sam_processor.go b/internal/domains/api/services/processors/dwbg/dwbg5sam_processor.go deleted file mode 100644 index 87d0d86..0000000 --- a/internal/domains/api/services/processors/dwbg/dwbg5sam_processor.go +++ /dev/null @@ -1,67 +0,0 @@ -package dwbg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessDWBG5SAMRequest DWBG5SAM 海宇指迷报告 -func ProcessDWBG5SAMRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.DWBG5SAMReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "accessoryUrl": paramsDto.AuthorizationURL, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI112", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 过滤响应数据,删除指定字段 - if respMap, ok := respData.(map[string]interface{}); ok { - delete(respMap, "reportUrl") - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/dwbg/dwbg6a2c_processor.go b/internal/domains/api/services/processors/dwbg/dwbg6a2c_processor.go deleted file mode 100644 index 9e907b1..0000000 --- a/internal/domains/api/services/processors/dwbg/dwbg6a2c_processor.go +++ /dev/null @@ -1,67 +0,0 @@ -package dwbg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessDWBG6A2CRequest DWBG6A2C API处理方法 - 司南报告 -func ProcessDWBG6A2CRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.DWBG6A2CReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "accessoryUrl": paramsDto.AuthorizationURL, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI102", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 过滤响应数据,删除指定字段 - if respMap, ok := respData.(map[string]interface{}); ok { - delete(respMap, "reportUrl") - delete(respMap, "multCourtInfo") - // delete(respMap, "judiciaRiskInfos") - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/dwbg/dwbg7f3a_processor.go b/internal/domains/api/services/processors/dwbg/dwbg7f3a_processor.go deleted file mode 100644 index 8307b08..0000000 --- a/internal/domains/api/services/processors/dwbg/dwbg7f3a_processor.go +++ /dev/null @@ -1,51 +0,0 @@ -package dwbg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessDWBG7F3ARequest DWBG7F3A API处理方法 - 行为数据查询 -func ProcessDWBG7F3ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.DWBG7F3AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,使用xingwei服务的正确字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "phoneNumber": paramsDto.MobileNo, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1101695406546284544" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - // 查空情况,返回特定的查空错误 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/dwbg/dwbg8b4d_processor.go b/internal/domains/api/services/processors/dwbg/dwbg8b4d_processor.go deleted file mode 100644 index 707134c..0000000 --- a/internal/domains/api/services/processors/dwbg/dwbg8b4d_processor.go +++ /dev/null @@ -1,4622 +0,0 @@ -package dwbg - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - "sync" - "time" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/shared/logger" - - "go.uber.org/zap" -) - -// ProcessDWBG8B4DRequest DWBG8B4D API处理方法 - 谛听多维报告 -// 通过调用多个API组合成谛听报告格式 -func ProcessDWBG8B4DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.DWBG8B4DReq - - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - log := logger.GetGlobalLogger() - log.Info("开始处理谛听多维报告请求", - zap.String("name", paramsDto.Name), - zap.String("id_card", maskIDCard(paramsDto.IDCard)), - zap.String("mobile_no", maskMobile(paramsDto.MobileNo)), - ) - - // 并发调用多个API收集数据 - apiData := collectAPIData(ctx, paramsDto, deps, log) - - // 导出apiData为JSON文件,方便调试 - if err := exportAPIDataToJSON(apiData, paramsDto.IDCard, log); err != nil { - log.Warn("导出API数据到JSON文件失败", zap.Error(err)) - } - - // 将API数据转换为谛听报告格式 - report := transformToDitingReport(apiData, paramsDto, log) - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(report) - if err != nil { - log.Error("序列化谛听报告响应失败", zap.Error(err)) - return nil, errors.Join(processors.ErrSystem, err) - } - - log.Info("谛听多维报告处理完成") - return respBytes, nil -} - -// collectAPIData 并发调用多个API收集数据 -func collectAPIData(ctx context.Context, params dto.DWBG8B4DReq, deps *processors.ProcessorDependencies, log *zap.Logger) map[string]interface{} { - // 开发模式:从本地JSON文件读取数据(节省API调用成本) - if isDevelopmentMode() { - if mockData := loadMockAPIDataFromFile(log); mockData != nil { - log.Info("开发模式:从本地JSON文件加载API数据", zap.Int("api_count", len(mockData))) - return mockData - } - log.Warn("开发模式:无法从本地JSON文件加载数据,将调用远程API") - } - - apiData := make(map[string]interface{}) - - // 定义需要调用的API列表 - type apiCallInfo struct { - apiCode string - params map[string]interface{} - } - - apiCalls := []apiCallInfo{ - // 运营商三要素简版V政务版 (YYSYH6D2Req: id_card, name, mobile_no) - { - apiCode: "YYSYH6D2", - params: map[string]interface{}{ - "id_card": params.IDCard, - "name": params.Name, - "mobile_no": params.MobileNo, - }, - }, - // 手机在网时长B (YYSY8B1CReq: mobile_no) - { - apiCode: "YYSY8B1C", - params: map[string]interface{}{ - "mobile_no": params.MobileNo, - }, - }, - // 公安二要素认证即时版 (IVYZ9K7FReq: id_card, name) - { - apiCode: "IVYZ9K7F", - params: map[string]interface{}{ - "id_card": params.IDCard, - "name": params.Name, - }, - }, - // 涉赌涉诈风险评估 (FLXG8B4DReq: mobile_no, id_card, bank_card, authorized) - { - apiCode: "FLXG8B4D", - params: map[string]interface{}{ - "mobile_no": params.MobileNo, - "authorized": "1", - }, - }, - // 特殊名单验证B (JRZQ8A2DReq: mobile_no, id_card, name, authorized) - { - apiCode: "JRZQ8A2D", - params: map[string]interface{}{ - "mobile_no": params.MobileNo, - "id_card": params.IDCard, - "name": params.Name, - "authorized": "1", - }, - }, - // 3C租赁申请意向 (JRZQ1D09Req: mobile_no, id_card, name, authorized) - { - apiCode: "JRZQ1D09", - params: map[string]interface{}{ - "mobile_no": params.MobileNo, - "id_card": params.IDCard, - "name": params.Name, - "authorized": "1", - }, - }, - // 个人司法涉诉查询 (FLXG7E8FReq: name, id_card, mobile_no) - { - apiCode: "FLXG7E8F", - params: map[string]interface{}{ - "name": params.Name, - "id_card": params.IDCard, - "mobile_no": params.MobileNo, - }, - }, - // 借贷意向验证A (JRZQ6F2AReq: name, id_card, mobile_no) - { - apiCode: "JRZQ6F2A", - params: map[string]interface{}{ - "name": params.Name, - "id_card": params.IDCard, - "mobile_no": params.MobileNo, - }, - }, - // 借选指数评估 (JRZQ5E9FReq: mobile_no, id_card, name, authorized) - { - apiCode: "JRZQ5E9F", - params: map[string]interface{}{ - "mobile_no": params.MobileNo, - "id_card": params.IDCard, - "name": params.Name, - "authorized": "1", - }, - }, - // 公安不良人员名单(加强版) (FLXGDEA9Req: id_card, name, authorized) - { - apiCode: "FLXGDEA9", - params: map[string]interface{}{ - "id_card": params.IDCard, - "name": params.Name, - "authorized": "1", - }, - }, - // 手机号归属地核验 (YYSY9E4AReq: mobile_no) - { - apiCode: "YYSY9E4A", - params: map[string]interface{}{ - "mobile_no": params.MobileNo, - }, - }, - // 手机在网状态V即时版 (YYSYE7V5Req: mobile_no) - { - apiCode: "YYSYE7V5", - params: map[string]interface{}{ - "mobile_no": params.MobileNo, - }, - }, - } - - // 并发调用所有API - type processorResult struct { - apiCode string - data interface{} - err error - } - - results := make(chan processorResult, len(apiCalls)) - var wg sync.WaitGroup - - for _, apiCall := range apiCalls { - wg.Add(1) - go func(ac apiCallInfo) { - defer wg.Done() - defer func() { - if r := recover(); r != nil { - log.Error("调用API时发生panic", - zap.String("api_code", ac.apiCode), - zap.Any("panic", r), - ) - results <- processorResult{ac.apiCode, nil, fmt.Errorf("处理器panic: %v", r)} - } - }() - - paramsBytes, err := json.Marshal(ac.params) - if err != nil { - log.Warn("序列化API参数失败", - zap.String("api_code", ac.apiCode), - zap.Error(err), - ) - results <- processorResult{ac.apiCode, nil, err} - return - } - - data, err := callProcessor(ctx, ac.apiCode, paramsBytes, deps) - results <- processorResult{ac.apiCode, data, err} - }(apiCall) - } - - // 等待所有goroutine完成 - go func() { - wg.Wait() - close(results) - }() - - // 收集结果 - successCount := 0 - for result := range results { - if result.err != nil { - log.Warn("调用API失败,将使用默认值", - zap.String("api_code", result.apiCode), - zap.Error(result.err), - ) - apiData[result.apiCode] = nil - } else { - apiData[result.apiCode] = result.data - successCount++ - } - } - - log.Info("API调用完成", - zap.Int("total", len(apiCalls)), - zap.Int("success", successCount), - zap.Int("failed", len(apiCalls)-successCount), - ) - - return apiData -} - -// callProcessor 调用指定的处理器 -func callProcessor(ctx context.Context, apiCode string, params []byte, deps *processors.ProcessorDependencies) (interface{}, error) { - // 通过CombService获取处理器 - if combSvc, ok := deps.CombService.(interface { - GetProcessor(apiCode string) (processors.ProcessorFunc, bool) - }); ok { - processor, exists := combSvc.GetProcessor(apiCode) - if !exists { - return nil, fmt.Errorf("未找到处理器: %s", apiCode) - } - respBytes, err := processor(ctx, params, deps) - if err != nil { - return nil, err - } - var data interface{} - if err := json.Unmarshal(respBytes, &data); err != nil { - return nil, fmt.Errorf("解析响应失败: %w", err) - } - return data, nil - } - - return nil, fmt.Errorf("无法获取处理器: %s,CombService不支持GetProcessor方法", apiCode) -} - -// exportAPIDataToJSON 将API数据导出为JSON文件,方便调试 -func exportAPIDataToJSON(apiData map[string]interface{}, idCard string, log *zap.Logger) error { - // 创建导出目录(如果不存在) - exportDir := "api_data_export" - if err := os.MkdirAll(exportDir, 0755); err != nil { - return fmt.Errorf("创建导出目录失败: %w", err) - } - - // 使用身份证号后4位和时间戳生成文件名 - idCardSuffix := "" - if len(idCard) >= 4 { - idCardSuffix = idCard[len(idCard)-4:] - } - timestamp := time.Now().Format("20060102_150405") - filename := fmt.Sprintf("api_data_%s_%s.json", idCardSuffix, timestamp) - filepath := filepath.Join(exportDir, filename) - - // 将apiData序列化为格式化的JSON - jsonData, err := json.MarshalIndent(apiData, "", " ") - if err != nil { - return fmt.Errorf("序列化API数据失败: %w", err) - } - - // 写入文件 - if err := os.WriteFile(filepath, jsonData, 0644); err != nil { - return fmt.Errorf("写入JSON文件失败: %w", err) - } - - log.Info("API数据已导出到JSON文件", - zap.String("filepath", filepath), - zap.String("filename", filename), - ) - - return nil -} - -// transformToDitingReport 将API数据转换为谛听报告格式 -func transformToDitingReport(apiData map[string]interface{}, params dto.DWBG8B4DReq, log *zap.Logger) map[string]interface{} { - report := make(map[string]interface{}) - - // 1. baseInfo (基本信息) - report["baseInfo"] = buildBaseInfo(apiData, params, log) - - // 2. standLiveInfo (身份信息核验) - report["standLiveInfo"] = buildStandLiveInfo(apiData, log) - - // 3. checkSuggest (审核建议) - report["checkSuggest"] = buildCheckSuggest(apiData, log) - - // 4. fraudScore (反欺诈评分) - report["fraudScore"] = buildFraudScore(apiData, log) - - // 5. creditScore (信用评分) - report["creditScore"] = buildCreditScore(apiData, log) - - // 6. verifyRule (验证规则) - report["verifyRule"] = buildVerifyRule(apiData, log) - - // 7. fraudRule (反欺诈规则) - report["fraudRule"] = buildFraudRule(apiData, log) - - // 8. riskWarning (规则风险提示) - report["riskWarning"] = buildRiskWarning(apiData, log) - - // 9. elementVerificationDetail (要素、运营商、公安重点人员核查产品) - report["elementVerificationDetail"] = buildElementVerificationDetail(apiData, log) - - // 10. riskSupervision (关联风险监督) - report["riskSupervision"] = buildRiskSupervision(apiData, log) - - // 11. overdueRiskProduct (逾期风险产品) - report["overdueRiskProduct"] = buildOverdueRiskProduct(apiData, log) - - // 12. multCourtInfo (司法风险核验产品) - report["multCourtInfo"] = buildMultCourtInfo(apiData, log) - - // 13. loanEvaluationVerificationDetail (借贷评估产品) - report["loanEvaluationVerificationDetail"] = buildLoanEvaluationVerificationDetail(apiData, log) - - // 14. leasingRiskAssessment (租赁风险评估产品) - report["leasingRiskAssessment"] = buildLeasingRiskAssessment(apiData, log) - - return report -} - -// buildBaseInfo 构建基本信息 -func buildBaseInfo(apiData map[string]interface{}, params dto.DWBG8B4DReq, log *zap.Logger) map[string]interface{} { - baseInfo := make(map[string]interface{}) - - // 首先从传参中获取并脱敏姓名、身份证、手机号(这些字段始终从传参获取) - baseInfo["name"] = maskName(params.Name) - baseInfo["idCard"] = maskIDCard(params.IDCard) - baseInfo["phone"] = maskMobile(params.MobileNo) - - // 从运营商三要素获取数据 - yysyData := getMapValue(apiData, "YYSYH6D2") - if yysyData != nil { - if yysyMap, ok := yysyData.(map[string]interface{}); ok { - - // 从身份证号计算年龄和性别 - if age, sex := calculateAgeAndSex(params.IDCard); age > 0 { - baseInfo["age"] = age - baseInfo["sex"] = sex - } - - // 从运营商三要素获取户籍所在地(address字段) - if address, ok := yysyMap["address"].(string); ok && address != "" { - baseInfo["location"] = address - } else { - // 如果address不存在,尝试从身份证号获取 - if location := getLocationFromIDCard(params.IDCard); location != "" { - baseInfo["location"] = location - } - } - - // 从运营商数据获取 - if channel, ok := yysyMap["channel"].(string); ok { - baseInfo["channel"] = convertChannel(channel) - } - } - } - - // 从手机号归属地核验API获取归属地 - yysy9e4aData := getMapValue(apiData, "YYSY9E4A") - if yysy9e4aData != nil { - if yysy9e4aMap, ok := yysy9e4aData.(map[string]interface{}); ok { - var provinceName, cityName string - if province, ok := yysy9e4aMap["provinceName"].(string); ok { - provinceName = province - } - if city, ok := yysy9e4aMap["cityName"].(string); ok { - cityName = city - } - if provinceName != "" && cityName != "" { - baseInfo["phoneArea"] = provinceName + "-" + cityName - } else if provinceName != "" { - baseInfo["phoneArea"] = provinceName - } - } - } - - // 从手机在网状态V即时版获取号码状态 - yysy4b21Data := getMapValue(apiData, "YYSYE7V5") - if yysy4b21Data != nil { - if yysy4b21Map, ok := yysy4b21Data.(map[string]interface{}); ok { - baseInfo["status"] = convertStatusFromOnlineStatus(yysy4b21Map) - } - } else { - // 如果手机在网状态API失败,尝试从运营商三要素的result转换 - if yysyData != nil { - if yysyMap, ok := yysyData.(map[string]interface{}); ok { - if result, ok := yysyMap["result"].(string); ok { - baseInfo["status"] = convertStatus(result) - } else { - baseInfo["status"] = -1 - } - } - } - } - - // 如果数据缺失,使用默认值(name、idCard、phone已经在开头设置了,这里只需要设置其他字段) - if _, exists := baseInfo["age"]; !exists { - baseInfo["age"] = 0 - } - if _, exists := baseInfo["sex"]; !exists { - baseInfo["sex"] = "" - } - if _, exists := baseInfo["location"]; !exists { - baseInfo["location"] = "" - } - if _, exists := baseInfo["phoneArea"]; !exists { - baseInfo["phoneArea"] = "" - } - if _, exists := baseInfo["channel"]; !exists { - baseInfo["channel"] = "" - } - if _, exists := baseInfo["status"]; !exists { - baseInfo["status"] = -1 - } - - return baseInfo -} - -// buildStandLiveInfo 构建身份信息核验 -func buildStandLiveInfo(apiData map[string]interface{}, log *zap.Logger) map[string]interface{} { - standLiveInfo := make(map[string]interface{}) - - // 从公安二要素获取实名核验结果(必须从数据源获取,无默认值) - ivyzData := getMapValue(apiData, "IVYZ9K7F") - if ivyzData != nil { - if ivyzMap, ok := ivyzData.(map[string]interface{}); ok { - // 尝试从data字段获取(兼容旧格式) - var status string - if data, ok := ivyzMap["data"].(map[string]interface{}); ok { - if statusVal, ok := data["status"].(string); ok { - status = statusVal - } - } else { - // 如果没有data字段,直接使用desc或result字段(新格式) - if desc, ok := ivyzMap["desc"].(string); ok && desc != "" { - status = desc - } else if result, ok := ivyzMap["result"].(float64); ok { - // result为0表示一致,非0表示不一致 - if result == 0 { - status = "一致" - } else { - status = "不一致" - } - } else if result, ok := ivyzMap["result"].(string); ok && result != "" { - // result也可能是字符串类型 - if result == "0" { - status = "一致" - } else { - status = "不一致" - } - } - } - - if status != "" { - // "一致" -> "0", "不一致" -> "1" - if status == "一致" { - standLiveInfo["finalAuthResult"] = "0" - } else { - standLiveInfo["finalAuthResult"] = "1" - } - } - } - } - - // 从运营商三要素获取三要素核验结果 - yysyData := getMapValue(apiData, "YYSYH6D2") - if yysyData != nil { - if yysyMap, ok := yysyData.(map[string]interface{}); ok { - if result, ok := yysyMap["result"].(string); ok { - // "0" -> "0" (一致), "1" -> "1" (不一致) - if result == "0" { - standLiveInfo["verification"] = "0" - } else { - standLiveInfo["verification"] = "1" - } - } - } - } - - // 从手机在网时长获取在网时长 - yysy8b1cData := getMapValue(apiData, "YYSY8B1C") - if yysy8b1cData != nil { - if yysy8b1cMap, ok := yysy8b1cData.(map[string]interface{}); ok { - if inTime, ok := yysy8b1cMap["inTime"].(string); ok { - standLiveInfo["inTime"] = inTime - } else if inTime, ok := yysy8b1cMap["inTime"].(float64); ok { - standLiveInfo["inTime"] = strconv.FormatFloat(inTime, 'f', -1, 64) - } - } - } - - // 默认值(finalAuthResult没有默认值,必须从数据源获取) - if _, exists := standLiveInfo["verification"]; !exists { - standLiveInfo["verification"] = "-1" - } - if _, exists := standLiveInfo["inTime"]; !exists { - standLiveInfo["inTime"] = "-1" - } - - return standLiveInfo -} - -// buildCheckSuggest 构建审核建议 -func buildCheckSuggest(apiData map[string]interface{}, log *zap.Logger) string { - // 根据风险评分和规则计算审核建议 - fraudScore := getFraudScore(apiData) - creditScore := getCreditScore(apiData) - riskCounts := getTotalRiskCounts(apiData) - - // 高风险情况 - if fraudScore >= 80 || creditScore < 500 || riskCounts >= 5 { - return "建议拒绝" - } - - // 中风险情况 - if fraudScore >= 60 || creditScore < 800 || riskCounts >= 3 { - return "建议复议" - } - - // 低风险情况 - return "建议通过" -} - -// buildFraudScore 构建反欺诈评分 -func buildFraudScore(apiData map[string]interface{}, log *zap.Logger) int { - score := getFraudScore(apiData) - if score == -1 { - return -1 - } - return score -} - -// buildCreditScore 构建信用评分 -func buildCreditScore(apiData map[string]interface{}, log *zap.Logger) int { - score := getCreditScore(apiData) - if score == -1 { - return -1 - } - return score -} - -// buildVerifyRule 构建验证规则(根据司法相关风险判断) -func buildVerifyRule(apiData map[string]interface{}, log *zap.Logger) string { - // 先构建riskWarning以获取司法风险字段 - riskWarning := buildRiskWarning(apiData, log) - - // 检查高风险情况(优先级最高) - // 1. 命中刑事案件 - if hitCriminalRisk, ok := riskWarning["hitCriminalRisk"].(int); ok && hitCriminalRisk == 1 { - return "高风险" - } - - // 2. 命中执行案件/失信案件/限高案件 - if hitExecutionCase, ok := riskWarning["hitExecutionCase"].(int); ok && hitExecutionCase == 1 { - return "高风险" - } - - // 3. 命中破产清算 - if hitBankruptcyAndLiquidation, ok := riskWarning["hitBankruptcyAndLiquidation"].(int); ok && hitBankruptcyAndLiquidation == 1 { - return "高风险" - } - - // 检查中风险情况(且不是高风险) - // 1. 命中民事案件 - if hitCivilCase, ok := riskWarning["hitCivilCase"].(int); ok && hitCivilCase == 1 { - return "中风险" - } - - // 2. 命中行政案件 - if hitAdministrativeCase, ok := riskWarning["hitAdministrativeCase"].(int); ok && hitAdministrativeCase == 1 { - return "中风险" - } - - // 3. 命中保全审查 - if hitPreservationReview, ok := riskWarning["hitPreservationReview"].(int); ok && hitPreservationReview == 1 { - return "中风险" - } - - // 其他情况为低风险 - return "低风险" -} - -// buildFraudRule 构建反欺诈规则(综合考虑fraudScore、特殊名单和借选指数风险) -func buildFraudRule(apiData map[string]interface{}, log *zap.Logger) string { - fraudScore := getFraudScore(apiData) - - // 如果fraudScore无效,检查特殊名单和借选指数 - if fraudScore == -1 { - // 检查特殊名单 - jrzq8a2dData := getMapValue(apiData, "JRZQ8A2D") - if jrzq8a2dData != nil { - if jrzq8a2dMap, ok := jrzq8a2dData.(map[string]interface{}); ok { - if decision, ok := jrzq8a2dMap["Rule_final_decision"].(string); ok && decision == "Reject" { - return "高风险" - } - } - } - // 检查借选指数 - jrzq5e9fData := getMapValue(apiData, "JRZQ5E9F") - if jrzq5e9fData != nil { - if jrzq5e9fMap, ok := jrzq5e9fData.(map[string]interface{}); ok { - if xypCpl0081, ok := jrzq5e9fMap["xyp_cpl0081"].(string); ok && xypCpl0081 != "" { - if score, err := strconv.ParseFloat(xypCpl0081, 64); err == nil && score < 500 { - return "高风险" - } - } - } - } - return "低风险" - } - - // 根据fraudScore判断风险等级 - if fraudScore >= 80 { - return "高风险" - } else if fraudScore >= 60 { - return "中风险" - } - return "低风险" -} - -// buildRiskWarning 构建规则风险提示 -func buildRiskWarning(apiData map[string]interface{}, log *zap.Logger) map[string]interface{} { - riskWarning := make(map[string]interface{}) - - // 初始化所有风险字段为0 - riskFields := []string{ - "sfhyfxRiskHighCounts", "noPhoneDuration", "jdpgRiskMiddleCounts", - "idCardRiskMiddleCounts", "yqfxRiskMiddleCounts", "isDisrupSocial", - "sfhyfxRiskCounts", "hitCivilCase", "isAntiFraudInfo", - "zlfxpgRiskHighCounts", "gazdyrhyRiskMiddleCounts", "hitAdministrativeCase", - "frequentBankApplications", "yqfxRiskHighCounts", "isTrafficRelated", - "phoneThreeElementMismatch", "highDebtPressure", "hitCompensationCase", - "idCardRiskHighCounts", "yqfxRiskCounts", "idCardTwoElementMismatch", - "isKeyPerson", "zlfxpgRiskMiddleCounts", "shortPhoneDurationSlight", - "hitBankruptcyAndLiquidation", "highFraudGangLevel", "isEconomyFront", - "jdpgRiskHighCounts", "hasCriminalRecord", "veryFrequentRentalApplications", - "frequentNonBankApplications", "idCardRiskCounts", "frequentApplicationRecent", - "hitDirectlyUnderCase", "hitPreservationReview", "hitExecutionCase", - "gazdyrhyRiskCounts", "shortPhoneRiskMiddleCounts", "hitCurrentOverdue", - "jdpgRiskCounts", "idCardPhoneProvinceMismatch", "hitHighRiskBankLastTwoYears", - "shortPhoneRiskCounts", "sfhyfxRiskMiddleCounts", "gazdyrhyRiskHighCounts", - "frequentRentalApplications", "shortPhoneDuration", "zlfxpgRiskCounts", - "moreFrequentBankApplications", "hitHighRiskNonBankLastTwoYears", - "shortPhoneRiskHighCounts", "moreFrequentNonBankApplications", "hitCriminalRisk", - } - - for _, field := range riskFields { - riskWarning[field] = 0 - } - - // ========== 要素核查风险 ========== - // 身份证二要素信息对比结果不一致(高风险) - ivyzData := getMapValue(apiData, "IVYZ9K7F") - if ivyzData != nil { - if ivyzMap, ok := ivyzData.(map[string]interface{}); ok { - if data, ok := ivyzMap["data"].(map[string]interface{}); ok { - if status, ok := data["status"].(string); ok { - if status != "一致" { - riskWarning["idCardTwoElementMismatch"] = 1 - riskWarning["idCardRiskHighCounts"] = 1 - riskWarning["idCardRiskCounts"] = 1 - } - } - } - } - } - - // 手机三要素简版不一致(高风险) - yysyData := getMapValue(apiData, "YYSYH6D2") - if yysyData != nil { - if yysyMap, ok := yysyData.(map[string]interface{}); ok { - if result, ok := yysyMap["result"].(string); ok { - if result != "0" { - riskWarning["phoneThreeElementMismatch"] = 1 - } - } - } - } - - // ========== 运营商核验风险 ========== - // 手机在网时长极短(高风险) - yysy8b1cData := getMapValue(apiData, "YYSY8B1C") - if yysy8b1cData != nil { - if yysy8b1cMap, ok := yysy8b1cData.(map[string]interface{}); ok { - var inTimeStr string - if inTime, ok := yysy8b1cMap["inTime"].(string); ok { - inTimeStr = inTime - } else if inTime, ok := yysy8b1cMap["inTime"].(float64); ok { - inTimeStr = strconv.FormatFloat(inTime, 'f', -1, 64) - } - - if inTimeStr == "0" { - riskWarning["shortPhoneDuration"] = 1 - riskWarning["shortPhoneRiskCounts"] = 1 - riskWarning["shortPhoneRiskHighCounts"] = 1 - } else if inTimeStr == "3" { - riskWarning["shortPhoneDurationSlight"] = 1 - riskWarning["shortPhoneRiskCounts"] = 1 - riskWarning["shortPhoneRiskMiddleCounts"] = 1 - } - } - } - - // 手机在网状态为风险号(高风险) - yysy4b21Data := getMapValue(apiData, "YYSYE7V5") - if yysy4b21Data != nil { - if yysy4b21Map, ok := yysy4b21Data.(map[string]interface{}); ok { - var statusInt int - if statusVal, ok := yysy4b21Map["status"]; ok { - switch v := statusVal.(type) { - case int: - statusInt = v - case float64: - statusInt = int(v) - case string: - if parsed, err := strconv.Atoi(v); err == nil { - statusInt = parsed - } - } - } - - // status=1表示不在网,需要判断是否为风险号 - if statusInt == 1 { - if desc, ok := yysy4b21Map["desc"].(string); ok { - if strings.Contains(desc, "风险") { - riskWarning["noPhoneDuration"] = 1 - } - } - } - } - } - - // 身份证号手机号归属省不一致(中风险) - yysy9e4aData := getMapValue(apiData, "YYSY9E4A") - if yysy9e4aData != nil && yysyData != nil { - if yysy9e4aMap, ok := yysy9e4aData.(map[string]interface{}); ok { - if yysyMap, ok := yysyData.(map[string]interface{}); ok { - // 从身份证号获取地址 - var idCardAddress string - if address, ok := yysyMap["address"].(string); ok && address != "" { - idCardAddress = address - } - - // 从手机号归属地获取省份和城市 - var phoneProvince, phoneCity string - if provinceName, ok := yysy9e4aMap["provinceName"].(string); ok { - phoneProvince = provinceName - } - if cityName, ok := yysy9e4aMap["cityName"].(string); ok { - phoneCity = cityName - } - - // 使用智能比较函数判断是否一致 - if idCardAddress != "" && phoneProvince != "" { - if !compareLocation(idCardAddress, phoneProvince, phoneCity) { - riskWarning["idCardPhoneProvinceMismatch"] = 1 - } - } - } - } - } - - // ========== 公安重点人员核验风险 ========== - flxgdea9Data := getMapValue(apiData, "FLXGDEA9") - if flxgdea9Data != nil { - if flxgdea9Map, ok := flxgdea9Data.(map[string]interface{}); ok { - level, ok := flxgdea9Map["level"].(string) - if !ok { - // 尝试从其他可能的字段获取 - if levelVal, exists := flxgdea9Map["level"]; exists { - if levelStr, ok := levelVal.(string); ok { - level = levelStr - } else if levelFloat, ok := levelVal.(float64); ok { - level = strconv.FormatFloat(levelFloat, 'f', -1, 64) - } - } - } - - if level != "" && level != "0" { - // 解析level字段,判断风险类型 - levelParts := strings.Split(level, ",") - for _, part := range levelParts { - part = strings.TrimSpace(part) - if part == "" || part == "0" { - continue - } - - // 根据level代码判断风险类型 - if strings.HasPrefix(part, "A") { - riskWarning["hasCriminalRecord"] = 1 - } - if strings.HasPrefix(part, "B") { - riskWarning["isEconomyFront"] = 1 - } - if strings.HasPrefix(part, "C") { - riskWarning["isDisrupSocial"] = 1 - } - if strings.HasPrefix(part, "D") { - riskWarning["isKeyPerson"] = 1 - } - if strings.HasPrefix(part, "E") { - riskWarning["isTrafficRelated"] = 1 - } - } - - // 设置level字段 - riskWarning["level"] = level - } - } - } - - // 涉赌涉诈(中风险) - flxgData := getMapValue(apiData, "FLXG8B4D") - if flxgData != nil { - if flxgMap, ok := flxgData.(map[string]interface{}); ok { - if data, ok := flxgMap["data"].(map[string]interface{}); ok { - hasRisk := false - riskFields := []string{"moneyLaundering", "deceiver", "gamblerPlayer", "gamblerBanker"} - for _, field := range riskFields { - if val, ok := data[field].(string); ok { - if val != "" && val != "0" { - hasRisk = true - break - } - } - } - if hasRisk { - riskWarning["isAntiFraudInfo"] = 1 - } - } - } - } - - // ========== 逾期风险 ========== - jrzq8a2dData := getMapValue(apiData, "JRZQ8A2D") - if jrzq8a2dData != nil { - if jrzq8a2dMap, ok := jrzq8a2dData.(map[string]interface{}); ok { - // 检查是否有高风险记录(近两年) - // 注意:字段值为"0"表示命中,字段值为"空"表示未命中 - // 数据源中字段名可能是简化的(如nbank_bad而不是id_nbank_bad) - // 优先检查完整字段名,如果没有则检查简化字段名 - if idData, ok := jrzq8a2dMap["id"].(map[string]interface{}); ok { - // 检查银行高风险(近两年)- 使用id_bank_lost或bank_lost - if checkRiskFieldValue(idData, "id_bank_lost") || checkRiskFieldValue(idData, "bank_lost") { - riskWarning["hitHighRiskBankLastTwoYears"] = 1 - } - // 检查非银高风险(近两年)- 使用id_nbank_lost或nbank_lost - if checkRiskFieldValue(idData, "id_nbank_lost") || checkRiskFieldValue(idData, "nbank_lost") { - riskWarning["hitHighRiskNonBankLastTwoYears"] = 1 - } - // 检查银行一般风险(当前逾期)- 使用id_bank_overdue或bank_overdue - if checkRiskFieldValue(idData, "id_bank_overdue") || checkRiskFieldValue(idData, "bank_overdue") { - riskWarning["hitCurrentOverdue"] = 1 - } - // 检查非银一般风险(当前逾期)- 使用id_nbank_overdue或nbank_overdue - if checkRiskFieldValue(idData, "id_nbank_overdue") || checkRiskFieldValue(idData, "nbank_overdue") { - riskWarning["hitCurrentOverdue"] = 1 - } - } - } - } - - // ========== 司法风险核验 ========== - flxg5a3bData := getMapValue(apiData, "FLXG7E8F") - if flxg5a3bData != nil { - if flxg5a3bMap, ok := flxg5a3bData.(map[string]interface{}); ok { - // 检查judicial_data字段 - if judicialData, ok := flxg5a3bMap["judicial_data"].(map[string]interface{}); ok { - // 检查lawsuitStat - if lawsuitStat, ok := judicialData["lawsuitStat"].(map[string]interface{}); ok { - // 检查民事案件(必须检查cases数组,只有cases数组存在且不为空才算命中) - if civil, ok := lawsuitStat["civil"].(map[string]interface{}); ok { - // 只检查cases数组,如果cases数组存在且不为空,才标记为命中 - if cases, ok := civil["cases"].([]interface{}); ok && len(cases) > 0 { - riskWarning["hitCivilCase"] = 1 - } - // 注意:如果只有count而没有cases数组,不标记为命中 - // 因为count可能只是统计信息,不代表实际有案件详情 - } - - // 检查刑事案件(必须检查cases数组,只有cases数组存在且不为空才算命中) - if criminal, ok := lawsuitStat["criminal"].(map[string]interface{}); ok { - // 只检查cases数组,如果cases数组存在且不为空,才标记为命中 - if cases, ok := criminal["cases"].([]interface{}); ok && len(cases) > 0 { - riskWarning["hitCriminalRisk"] = 1 - } - // 注意:如果只有count而没有cases数组,不标记为命中 - // 因为count可能只是统计信息,不代表实际有案件详情 - } - - // 检查执行案件(必须检查cases数组,只有cases数组存在且不为空才算命中) - if implement, ok := lawsuitStat["implement"].(map[string]interface{}); ok { - // 只检查cases数组,如果cases数组存在且不为空,才标记为命中 - if cases, ok := implement["cases"].([]interface{}); ok && len(cases) > 0 { - riskWarning["hitExecutionCase"] = 1 - } - // 注意:如果只有count而没有cases数组,不标记为命中 - // 因为count可能只是统计信息,不代表实际有案件详情 - } - - // 检查失信案件 - if breachCaseList, ok := judicialData["breachCaseList"].([]interface{}); ok && len(breachCaseList) > 0 { - riskWarning["hitExecutionCase"] = 1 - } - - // 检查限高案件 - if consumptionRestrictionList, ok := judicialData["consumptionRestrictionList"].([]interface{}); ok && len(consumptionRestrictionList) > 0 { - riskWarning["hitExecutionCase"] = 1 - } - - // 检查行政案件(必须检查cases数组,只有cases数组存在且不为空才算命中) - if administrative, ok := lawsuitStat["administrative"].(map[string]interface{}); ok { - // 只检查cases数组,如果cases数组存在且不为空,才标记为命中 - if cases, ok := administrative["cases"].([]interface{}); ok && len(cases) > 0 { - riskWarning["hitAdministrativeCase"] = 1 - } - // 注意:如果只有count而没有cases数组,不标记为命中 - // 因为count可能只是统计信息,不代表实际有案件详情 - } - - // 检查保全审查(必须检查cases数组,只有cases数组存在且不为空才算命中) - if preservation, ok := lawsuitStat["preservation"].(map[string]interface{}); ok { - // 只检查cases数组,如果cases数组存在且不为空,才标记为命中 - if cases, ok := preservation["cases"].([]interface{}); ok && len(cases) > 0 { - riskWarning["hitPreservationReview"] = 1 - } - // 注意:如果只有count而没有cases数组,不标记为命中 - // 因为count可能只是统计信息,不代表实际有案件详情 - } - - // 检查破产清算(必须检查cases数组,只有cases数组存在且不为空才算命中) - if bankrupt, ok := lawsuitStat["bankrupt"].(map[string]interface{}); ok { - // 只检查cases数组,如果cases数组存在且不为空,才标记为命中 - if cases, ok := bankrupt["cases"].([]interface{}); ok && len(cases) > 0 { - riskWarning["hitBankruptcyAndLiquidation"] = 1 - } - // 注意:如果只有count而没有cases数组,不标记为命中 - // 因为count可能只是统计信息,不代表实际有案件详情 - } - } - - // 检查直辖案件和赔偿案件(从案件类型中判断) - // 直辖案件:通常指直辖市法院审理的案件,可以通过法院名称判断 - // 赔偿案件:通常案由中包含"赔偿"字样 - if lawsuitStat, ok := judicialData["lawsuitStat"].(map[string]interface{}); ok { - // 检查所有案件类型 - caseTypes := []string{"civil", "criminal", "implement", "administrative", "preservation", "bankrupt"} - for _, caseType := range caseTypes { - if caseData, ok := lawsuitStat[caseType].(map[string]interface{}); ok { - if cases, ok := caseData["cases"].([]interface{}); ok { - for _, caseItem := range cases { - if caseMap, ok := caseItem.(map[string]interface{}); ok { - // 检查是否为直辖案件(法院名称包含"直辖市"或特定直辖市名称) - if court, ok := caseMap["n_jbfy"].(string); ok { - // 检查是否为直辖市法院(北京、上海、天津、重庆) - if strings.Contains(court, "北京市") || strings.Contains(court, "上海市") || - strings.Contains(court, "天津市") || strings.Contains(court, "重庆市") { - riskWarning["hitDirectlyUnderCase"] = 1 - } - } - - // 检查是否为赔偿案件(案由中包含"赔偿") - if caseReason, ok := caseMap["n_laay"].(string); ok { - if strings.Contains(caseReason, "赔偿") { - riskWarning["hitCompensationCase"] = 1 - } - } - // 也检查案由树 - if caseReasonTree, ok := caseMap["n_laay_tree"].(string); ok { - if strings.Contains(caseReasonTree, "赔偿") { - riskWarning["hitCompensationCase"] = 1 - } - } - } - } - } - } - } - } - } - } - } - - // ========== 借贷评估风险 ========== - jrzq6f2aData := getMapValue(apiData, "JRZQ6F2A") - if jrzq6f2aData != nil { - if jrzq6f2aMap, ok := jrzq6f2aData.(map[string]interface{}); ok { - // 获取risk_screen_v2 - if riskScreenV2, ok := jrzq6f2aMap["risk_screen_v2"].(map[string]interface{}); ok { - // 获取variables - if variables, ok := riskScreenV2["variables"].([]interface{}); ok && len(variables) > 0 { - if variable, ok := variables[0].(map[string]interface{}); ok { - if variableValue, ok := variable["variableValue"].(map[string]interface{}); ok { - // 检查近期申请频率(近7天、近15天、近1个月) - checkRecentApplicationFrequency(variableValue, &riskWarning) - - // 检查银行/非银申请次数 - checkBankApplicationFrequency(variableValue, &riskWarning) - - // 检查偿债压力(从借选指数评估获取) - checkDebtPressure(apiData, &riskWarning) - - // 计算借贷评估风险计数 - calculateLoanRiskCounts(variableValue, &riskWarning) - } - } - } - } - } - } - - // ========== 租赁风险评估 ========== - jrzq1d09Data := getMapValue(apiData, "JRZQ1D09") - if jrzq1d09Data != nil { - if jrzq1d09Map, ok := jrzq1d09Data.(map[string]interface{}); ok { - // 检查3C租赁申请频率 - checkRentalApplicationFrequency(jrzq1d09Map, &riskWarning) - } - } - - // ========== 计算各种风险计数 ========== - // 计算sfhyfxRiskCounts(涉赌涉诈风险计数) - if val, ok := riskWarning["isAntiFraudInfo"].(int); ok && val == 1 { - riskWarning["sfhyfxRiskCounts"] = 1 - riskWarning["sfhyfxRiskHighCounts"] = 1 - } - - // 计算gazdyrhyRiskCounts(公安重点人员风险计数) - gazdyrhyRiskCount := 0 - if val, ok := riskWarning["hasCriminalRecord"].(int); ok && val == 1 { - gazdyrhyRiskCount++ - } - if val, ok := riskWarning["isEconomyFront"].(int); ok && val == 1 { - gazdyrhyRiskCount++ - } - if val, ok := riskWarning["isDisrupSocial"].(int); ok && val == 1 { - gazdyrhyRiskCount++ - } - if val, ok := riskWarning["isKeyPerson"].(int); ok && val == 1 { - gazdyrhyRiskCount++ - } - if val, ok := riskWarning["isTrafficRelated"].(int); ok && val == 1 { - gazdyrhyRiskCount++ - } - - if gazdyrhyRiskCount > 0 { - riskWarning["gazdyrhyRiskCounts"] = gazdyrhyRiskCount - if gazdyrhyRiskCount >= 3 { - riskWarning["gazdyrhyRiskHighCounts"] = 1 - } else { - riskWarning["gazdyrhyRiskMiddleCounts"] = 1 - } - } - - // 计算yqfxRiskCounts(逾期风险计数) - yqfxRiskCount := 0 - if val, ok := riskWarning["hitHighRiskBankLastTwoYears"].(int); ok && val == 1 { - yqfxRiskCount++ - } - if val, ok := riskWarning["hitHighRiskNonBankLastTwoYears"].(int); ok && val == 1 { - yqfxRiskCount++ - } - if val, ok := riskWarning["hitCurrentOverdue"].(int); ok && val == 1 { - yqfxRiskCount++ - } - - if yqfxRiskCount > 0 { - riskWarning["yqfxRiskCounts"] = yqfxRiskCount - if yqfxRiskCount >= 2 { - riskWarning["yqfxRiskHighCounts"] = 1 - } else { - riskWarning["yqfxRiskMiddleCounts"] = 1 - } - } - - // 计算zlfxpgRiskCounts(租赁风险评估风险计数) - zlfxpgRiskCount := 0 - if val, ok := riskWarning["frequentRentalApplications"].(int); ok && val == 1 { - zlfxpgRiskCount++ - } - if val, ok := riskWarning["veryFrequentRentalApplications"].(int); ok && val == 1 { - zlfxpgRiskCount++ - } - - if zlfxpgRiskCount > 0 { - riskWarning["zlfxpgRiskCounts"] = zlfxpgRiskCount - if zlfxpgRiskCount >= 2 { - riskWarning["zlfxpgRiskHighCounts"] = 1 - } else { - riskWarning["zlfxpgRiskMiddleCounts"] = 1 - } - } - - // 计算idCardRiskMiddleCounts(身份证风险中风险计数) - // 如果idCardPhoneProvinceMismatch为1,则idCardRiskMiddleCounts为1 - if val, ok := riskWarning["idCardPhoneProvinceMismatch"].(int); ok && val == 1 { - riskWarning["idCardRiskMiddleCounts"] = 1 - // 更新idCardRiskCounts - if currentCount, ok := riskWarning["idCardRiskCounts"].(int); ok { - riskWarning["idCardRiskCounts"] = currentCount + 1 - } else { - riskWarning["idCardRiskCounts"] = 1 - } - } - - // 计算总风险点数量(排除Counts字段和level字段) - totalRiskCounts := 0 - excludeFields := map[string]bool{ - "totalRiskCounts": true, - "level": true, - "sfhyfxRiskCounts": true, - "sfhyfxRiskHighCounts": true, - "sfhyfxRiskMiddleCounts": true, - "gazdyrhyRiskCounts": true, - "gazdyrhyRiskHighCounts": true, - "gazdyrhyRiskMiddleCounts": true, - "yqfxRiskCounts": true, - "yqfxRiskHighCounts": true, - "yqfxRiskMiddleCounts": true, - "zlfxpgRiskCounts": true, - "zlfxpgRiskHighCounts": true, - "zlfxpgRiskMiddleCounts": true, - "jdpgRiskCounts": true, - "jdpgRiskHighCounts": true, - "jdpgRiskMiddleCounts": true, - "idCardRiskCounts": true, - "idCardRiskHighCounts": true, - "idCardRiskMiddleCounts": true, - "shortPhoneRiskCounts": true, - "shortPhoneRiskHighCounts": true, - "shortPhoneRiskMiddleCounts": true, - } - - for _, field := range riskFields { - if excludeFields[field] { - continue - } - if count, ok := riskWarning[field].(int); ok { - totalRiskCounts += count - } - } - riskWarning["totalRiskCounts"] = totalRiskCounts - - // level字段需要从公安不良人员名单中提取 - level := getRiskLevel(apiData) - if level != "" { - riskWarning["level"] = level - } else { - riskWarning["level"] = "" - } - - return riskWarning -} - -// checkRiskField 检查风险字段并设置风险警告(已废弃,使用checkRiskFieldValue代替) -func checkRiskField(data map[string]interface{}, prefix string, fieldName string, riskWarning *map[string]interface{}, targetField string) { - if prefixData, ok := data[prefix].(map[string]interface{}); ok { - if checkRiskFieldValue(prefixData, fieldName) { - (*riskWarning)[targetField] = 1 - } - } -} - -// checkRiskFieldValue 检查风险字段值(字段值为"0"表示命中,字段值为"空"表示未命中) -func checkRiskFieldValue(data map[string]interface{}, fieldName string) bool { - if val, ok := data[fieldName].(string); ok { - // 字段值为"0"表示命中 - return val == "0" - } - return false -} - -// buildElementVerificationDetail 构建要素、运营商、公安重点人员核查产品 -func buildElementVerificationDetail(apiData map[string]interface{}, log *zap.Logger) map[string]interface{} { - detail := make(map[string]interface{}) - - // 手机三要素简版风险标识 - yysyData := getMapValue(apiData, "YYSYH6D2") - if yysyData != nil { - if yysyMap, ok := yysyData.(map[string]interface{}); ok { - if result, ok := yysyMap["result"].(string); ok { - if result == "0" { - detail["sjsysFlag"] = 2 // 低风险 - } else { - detail["sjsysFlag"] = 1 // 高风险 - } - } - } - } - - // 手机三要素简版详情 - phoneCheckDetails := make(map[string]interface{}) - phoneCheckDetails["num"] = "1" - phoneCheckDetails["ele"] = "身份证号、手机号、姓名" - if yysyData != nil { - if yysyMap, ok := yysyData.(map[string]interface{}); ok { - if channel, ok := yysyMap["channel"].(string); ok { - phoneCheckDetails["phoneCompany"] = convertChannel(channel) - } - if result, ok := yysyMap["result"].(string); ok { - if result == "0" { - phoneCheckDetails["result"] = "一致" - } else { - phoneCheckDetails["result"] = "不一致" - } - } - } - } - detail["phoneCheckDetails"] = phoneCheckDetails - - // 身份证二要素风险标识 - ivyzData := getMapValue(apiData, "IVYZ9K7F") - if ivyzData != nil { - if ivyzMap, ok := ivyzData.(map[string]interface{}); ok { - // 尝试从data字段获取(兼容旧格式) - var status string - if data, ok := ivyzMap["data"].(map[string]interface{}); ok { - if statusVal, ok := data["status"].(string); ok { - status = statusVal - } - } else { - // 如果没有data字段,直接使用desc或result字段(新格式) - if desc, ok := ivyzMap["desc"].(string); ok { - status = desc - } else if result, ok := ivyzMap["result"].(float64); ok { - // result为0表示一致,非0表示不一致 - if result == 0 { - status = "一致" - } else { - status = "不一致" - } - } - } - - if status != "" { - if status == "一致" { - detail["sfzeysFlag"] = 2 // 低风险 - } else { - detail["sfzeysFlag"] = 1 // 高风险 - } - } - } - } - - // 身份证二要素验证详情 - personCheckDetails := make(map[string]interface{}) - personCheckDetails["num"] = "1" - personCheckDetails["ele"] = "身份证号、姓名" - if ivyzData != nil { - if ivyzMap, ok := ivyzData.(map[string]interface{}); ok { - // 尝试从data字段获取(兼容旧格式) - var status string - if data, ok := ivyzMap["data"].(map[string]interface{}); ok { - if statusVal, ok := data["status"].(string); ok { - status = statusVal - } - } else { - // 如果没有data字段,直接使用desc或result字段(新格式) - if desc, ok := ivyzMap["desc"].(string); ok { - status = desc - } else if result, ok := ivyzMap["result"].(float64); ok { - // result为0表示一致,非0表示不一致 - if result == 0 { - status = "一致" - } else { - status = "不一致" - } - } - } - - if status != "" { - personCheckDetails["result"] = status - } - } - } - detail["personCheckDetails"] = personCheckDetails - - // 手机在网时长风险标识 - yysy8b1cData := getMapValue(apiData, "YYSY8B1C") - if yysy8b1cData != nil { - if yysy8b1cMap, ok := yysy8b1cData.(map[string]interface{}); ok { - var inTimeStr string - if inTime, ok := yysy8b1cMap["inTime"].(string); ok { - inTimeStr = inTime - } else if inTime, ok := yysy8b1cMap["inTime"].(float64); ok { - inTimeStr = strconv.FormatFloat(inTime, 'f', -1, 64) - } - - if inTimeStr != "" { - // 根据在网时长判断风险 - if inTimeStr == "0" || inTimeStr == "3" { - detail["onlineRiskFlag"] = 1 // 高风险 - } else { - detail["onlineRiskFlag"] = 2 // 低风险 - } - - // 手机在网时长高级版 - onlineRiskList := make(map[string]interface{}) - onlineRiskList["num"] = "1" - if operators, ok := yysy8b1cMap["operators"].(string); ok { - onlineRiskList["lineType"] = operators - } - onlineRiskList["onLineTimes"] = formatOnlineTime(inTimeStr) - detail["onlineRiskList"] = onlineRiskList - } - } - } - - // 涉赌涉诈信息 - flxgData := getMapValue(apiData, "FLXG8B4D") - antiFraudInfo := make(map[string]interface{}) - if flxgData != nil { - if flxgMap, ok := flxgData.(map[string]interface{}); ok { - // 尝试从data字段获取(兼容旧格式) - var data map[string]interface{} - if dataVal, ok := flxgMap["data"].(map[string]interface{}); ok { - data = dataVal - } else { - // 如果没有data字段,直接使用flxgMap(新格式) - data = flxgMap - } - - if moneyLaundering, ok := data["moneyLaundering"].(string); ok { - antiFraudInfo["moneyLaundering"] = moneyLaundering - } - if deceiver, ok := data["deceiver"].(string); ok { - antiFraudInfo["deceiver"] = deceiver - } - if gamblerPlayer, ok := data["gamblerPlayer"].(string); ok { - antiFraudInfo["gamblerPlayer"] = gamblerPlayer - } - if gamblerBanker, ok := data["gamblerBanker"].(string); ok { - antiFraudInfo["gamblerBanker"] = gamblerBanker - } - if riskScore, ok := data["riskScore"].(string); ok { - antiFraudInfo["riskScore"] = riskScore - } - } - } - detail["antiFraudInfo"] = antiFraudInfo - - // 手机信息验证(phoneVailRiskFlag 和 phoneVailRisks) - yysy4b21Data := getMapValue(apiData, "YYSYE7V5") - phoneVailRisks := make(map[string]interface{}) - phoneVailRisks["num"] = "1" - if yysy4b21Data != nil { - if yysy4b21Map, ok := yysy4b21Data.(map[string]interface{}); ok { - var statusInt int - if statusVal, ok := yysy4b21Map["status"]; ok { - switch v := statusVal.(type) { - case int: - statusInt = v - case float64: - statusInt = int(v) - case string: - if parsed, err := strconv.Atoi(v); err == nil { - statusInt = parsed - } - } - } - - // status=1表示不在网,需要判断状态 - if statusInt == 1 { - detail["phoneVailRiskFlag"] = 1 // 高风险 - if desc, ok := yysy4b21Map["desc"].(string); ok { - phoneVailRisks["phoneStatus"] = desc - } else { - phoneVailRisks["phoneStatus"] = "不在网" - } - - // 获取运营商 - if channel, ok := yysy4b21Map["channel"].(string); ok { - phoneVailRisks["phoneCompany"] = convertChannelName(channel) - } - - // 获取在网时长 - if yysy8b1cData != nil { - if yysy8b1cMap, ok := yysy8b1cData.(map[string]interface{}); ok { - var inTimeStr string - if inTime, ok := yysy8b1cMap["inTime"].(string); ok { - inTimeStr = inTime - } else if inTime, ok := yysy8b1cMap["inTime"].(float64); ok { - inTimeStr = strconv.FormatFloat(inTime, 'f', -1, 64) - } - if inTimeStr != "" { - phoneVailRisks["phoneTimes"] = inTimeStr + "(单位:月)" - } - } - } - } else if statusInt == 0 { - detail["phoneVailRiskFlag"] = 2 // 低风险 - // 根据desc判断状态 - if desc, ok := yysy4b21Map["desc"].(string); ok { - if desc == "正常" { - phoneVailRisks["phoneStatus"] = "实号" - } else { - phoneVailRisks["phoneStatus"] = desc - } - } else { - phoneVailRisks["phoneStatus"] = "在网" - } - if channel, ok := yysy4b21Map["channel"].(string); ok { - phoneVailRisks["phoneCompany"] = convertChannelName(channel) - } - - // 获取在网时长(status=0时也要提取) - if yysy8b1cData != nil { - if yysy8b1cMap, ok := yysy8b1cData.(map[string]interface{}); ok { - var inTimeStr string - if inTime, ok := yysy8b1cMap["inTime"].(string); ok { - inTimeStr = inTime - } else if inTime, ok := yysy8b1cMap["inTime"].(float64); ok { - inTimeStr = strconv.FormatFloat(inTime, 'f', -1, 64) - } - if inTimeStr != "" { - phoneVailRisks["phoneTimes"] = inTimeStr + "(单位:月)" - } - } - } - } - } - } - detail["phoneVailRisks"] = phoneVailRisks - - // 身份证号手机号归属地(belongRiskFlag 和 belongRisks) - belongRisks := make(map[string]interface{}) - belongRisks["num"] = "1" - - // 重新获取数据 - yysy9e4aDataForBelong := getMapValue(apiData, "YYSY9E4A") - yysyDataForBelong := getMapValue(apiData, "YYSYH6D2") - - if yysy9e4aDataForBelong != nil && yysyDataForBelong != nil { - if yysy9e4aMap, ok := yysy9e4aDataForBelong.(map[string]interface{}); ok { - if yysyMapForBelong, ok := yysyDataForBelong.(map[string]interface{}); ok { - // 从身份证号地址获取省份和城市 - var personProvince, personCity string - var idCardAddress string - if address, ok := yysyMapForBelong["address"].(string); ok && address != "" { - idCardAddress = address - personProvince = extractProvinceFromAddress(address) - personCity = extractCityFromAddress(address) - } - - // 从手机号归属地获取省份和城市 - var phoneProvince, phoneCity string - if provinceName, ok := yysy9e4aMap["provinceName"].(string); ok { - phoneProvince = provinceName - } - if cityName, ok := yysy9e4aMap["cityName"].(string); ok { - phoneCity = cityName - } - - belongRisks["personProvence"] = personProvince - belongRisks["personCity"] = personCity - belongRisks["phoneProvence"] = phoneProvince - belongRisks["phoneCity"] = phoneCity - - // 获取手机卡类型 - if channel, ok := yysy9e4aMap["channel"].(string); ok { - belongRisks["phoneCardType"] = convertChannelName(channel) - } else if channel, ok := yysyMapForBelong["channel"].(string); ok { - belongRisks["phoneCardType"] = convertChannel(channel) - } - - // 判断归属地是否一致(使用智能比较函数) - if idCardAddress != "" && phoneProvince != "" { - if compareLocation(idCardAddress, phoneProvince, phoneCity) { - detail["belongRiskFlag"] = 2 // 低风险(一致) - } else { - detail["belongRiskFlag"] = 1 // 高风险(不一致) - } - } else { - detail["belongRiskFlag"] = 0 // 未查得 - } - } - } - } - detail["belongRisks"] = belongRisks - - // 公安重点人员核验产品(highRiskFlag 由 keyPersonCheckList 五项是否命中决定) - flxgdea9Data := getMapValue(apiData, "FLXGDEA9") - keyPersonCheckList := make(map[string]interface{}) - keyPersonCheckList["num"] = "1" - keyPersonCheckList["fontFlag"] = 0 - keyPersonCheckList["jingJiFontFlag"] = 0 - keyPersonCheckList["fangAiFlag"] = 0 - keyPersonCheckList["zhongDianFlag"] = 0 - keyPersonCheckList["sheJiaoTongFlag"] = 0 - - if flxgdea9Data != nil { - if flxgdea9Map, ok := flxgdea9Data.(map[string]interface{}); ok { - level, ok := flxgdea9Map["level"].(string) - if !ok { - if levelVal, exists := flxgdea9Map["level"]; exists { - if levelStr, ok := levelVal.(string); ok { - level = levelStr - } else if levelFloat, ok := levelVal.(float64); ok { - level = strconv.FormatFloat(levelFloat, 'f', -1, 64) - } - } - } - - // 仅根据 level 解析并填充 keyPersonCheckList 五项 - if level != "" && level != "0" { - levelParts := strings.Split(level, ",") - for _, part := range levelParts { - part = strings.TrimSpace(part) - if part == "" || part == "0" { - continue - } - if strings.HasPrefix(part, "A") { - keyPersonCheckList["fontFlag"] = 1 - } - if strings.HasPrefix(part, "B") { - keyPersonCheckList["jingJiFontFlag"] = 1 - } - if strings.HasPrefix(part, "C") { - keyPersonCheckList["fangAiFlag"] = 1 - } - if strings.HasPrefix(part, "D") { - keyPersonCheckList["zhongDianFlag"] = 1 - } - if strings.HasPrefix(part, "E") { - keyPersonCheckList["sheJiaoTongFlag"] = 1 - } - } - } - - } - } - detail["keyPersonCheckList"] = keyPersonCheckList - - // 仅根据 keyPersonCheckList 五项判定 highRiskFlag(不看是否有数据): - // 五项均未命中 → 0 无风险;仅 sheJiaoTongFlag 命中 → 2 低风险;其他任一项命中 → 1 高风险 - otherHit := keyPersonFlagEq1(keyPersonCheckList, "fontFlag") || - keyPersonFlagEq1(keyPersonCheckList, "jingJiFontFlag") || - keyPersonFlagEq1(keyPersonCheckList, "fangAiFlag") || - keyPersonFlagEq1(keyPersonCheckList, "zhongDianFlag") - sheJiaoHit := keyPersonFlagEq1(keyPersonCheckList, "sheJiaoTongFlag") - if otherHit { - detail["highRiskFlag"] = 1 // 高风险 - } else if sheJiaoHit { - detail["highRiskFlag"] = 2 // 低风险:仅涉交通命中 - } else { - detail["highRiskFlag"] = 0 // 无风险:五项均未命中 - } - - // 设置默认值 - if _, exists := detail["sjsysFlag"]; !exists { - detail["sjsysFlag"] = 0 - } - if _, exists := detail["sfzeysFlag"]; !exists { - detail["sfzeysFlag"] = 0 - } - if _, exists := detail["onlineRiskFlag"]; !exists { - detail["onlineRiskFlag"] = 0 - } - if _, exists := detail["highRiskFlag"]; !exists { - detail["highRiskFlag"] = 0 - } - if _, exists := detail["phoneVailRiskFlag"]; !exists { - detail["phoneVailRiskFlag"] = 0 - } - if _, exists := detail["belongRiskFlag"]; !exists { - detail["belongRiskFlag"] = 0 - } - - return detail -} - -// buildRiskSupervision 构建关联风险监督 -func buildRiskSupervision(apiData map[string]interface{}, log *zap.Logger) map[string]interface{} { - riskSupervision := make(map[string]interface{}) - - // 从3C租赁申请意向获取数据 - jrzq1d09Data := getMapValue(apiData, "JRZQ1D09") - - // 设置默认值 - riskSupervision["rentalRiskListIdCardRelationsPhones"] = 0 - riskSupervision["rentalRiskListPhoneRelationsIdCards"] = 0 - riskSupervision["details"] = "" // 默认无(空字符串) - riskSupervision["leastApplicationTime"] = "" - - if jrzq1d09Data != nil { - if jrzq1d09Map, ok := jrzq1d09Data.(map[string]interface{}); ok { - // 同一身份证关联手机号数(从 idcard_relation_phone 获取) - // 注意:字段名是idcard_relation_phone,表示同一身份证关联的手机号数 - if idcardRelationPhone, ok := jrzq1d09Map["idcard_relation_phone"].(int); ok { - riskSupervision["rentalRiskListIdCardRelationsPhones"] = idcardRelationPhone - } else if idcardRelationPhone, ok := jrzq1d09Map["idcard_relation_phone"].(float64); ok { - riskSupervision["rentalRiskListIdCardRelationsPhones"] = int(idcardRelationPhone) - } else if idcardRelationPhone, ok := jrzq1d09Map["idcard_relation_phone"].(string); ok && idcardRelationPhone != "" { - if count, err := strconv.Atoi(idcardRelationPhone); err == nil { - riskSupervision["rentalRiskListIdCardRelationsPhones"] = count - } - } - - // 同一手机号关联身份证号数(从 phone_relation_idard 获取) - // 注意:字段名是phone_relation_idard,表示同一手机号关联的身份证号数 - if phoneRelationIdcard, ok := jrzq1d09Map["phone_relation_idard"].(int); ok { - riskSupervision["rentalRiskListPhoneRelationsIdCards"] = phoneRelationIdcard - } else if phoneRelationIdcard, ok := jrzq1d09Map["phone_relation_idard"].(float64); ok { - riskSupervision["rentalRiskListPhoneRelationsIdCards"] = int(phoneRelationIdcard) - } else if phoneRelationIdcard, ok := jrzq1d09Map["phone_relation_idard"].(string); ok && phoneRelationIdcard != "" { - if count, err := strconv.Atoi(phoneRelationIdcard); err == nil { - riskSupervision["rentalRiskListPhoneRelationsIdCards"] = count - } - } - - // 最近一次申请时间(从 least_application_time 获取) - if leastApplicationTime, ok := jrzq1d09Map["least_application_time"].(string); ok && leastApplicationTime != "" { - riskSupervision["leastApplicationTime"] = leastApplicationTime - } - } - } - - return riskSupervision -} - -// buildOverdueRiskProduct 构建逾期风险产品 -func buildOverdueRiskProduct(apiData map[string]interface{}, log *zap.Logger) map[string]interface{} { - overdueRiskProduct := make(map[string]interface{}) - - // 设置默认值 - overdueRiskProduct["lyjlhyFlag"] = 0 - overdueRiskProduct["dkzhktjFlag"] = 0 - overdueRiskProduct["tsmdyzFlag"] = 0 - overdueRiskProduct["hasUnsettledOverdue"] = "未逾期" - overdueRiskProduct["currentOverdueInstitutionCount"] = "0" - overdueRiskProduct["currentOverdueAmount"] = "0" - overdueRiskProduct["settledInstitutionCount"] = "0" - overdueRiskProduct["totalLoanRepaymentAmount"] = "0" - overdueRiskProduct["totalLoanInstitutions"] = "0" - overdueRiskProduct["overdueLast1Day"] = "未逾期" - overdueRiskProduct["overdueLast7Days"] = "未逾期" - overdueRiskProduct["overdueLast14Days"] = "未逾期" - overdueRiskProduct["overdueLast30Days"] = "未逾期" - overdueRiskProduct["daysSinceLastSuccessfulRepayment"] = "0" - overdueRiskProduct["repaymentFailureCountLast7Days"] = "0" - overdueRiskProduct["repaymentFailureAmountLast7Days"] = "0" - overdueRiskProduct["repaymentSuccessCountLast7Days"] = "-" - overdueRiskProduct["repaymentSuccessAmountLast7Days"] = "-" - overdueRiskProduct["repaymentFailureCountLast14Days"] = "0" - overdueRiskProduct["repaymentFailureAmountLast14Days"] = "0" - overdueRiskProduct["repaymentSuccessCountLast14Days"] = "-" - overdueRiskProduct["repaymentSuccessAmountLast14Days"] = "-" - overdueRiskProduct["repaymentFailureCountLastMonth"] = "0" - overdueRiskProduct["repaymentFailureAmountLastMonth"] = "0" - overdueRiskProduct["repaymentSuccessCountLastMonth"] = "-" - overdueRiskProduct["repaymentSuccessAmountLastMonth"] = "-" - overdueRiskProduct["repaymentFailureCountLast3Months"] = "0" - overdueRiskProduct["repaymentFailureAmountLast3Months"] = "0" - overdueRiskProduct["repaymentSuccessCountLast3Months"] = "-" - overdueRiskProduct["repaymentSuccessAmountLast3Months"] = "-" - overdueRiskProduct["repaymentFailureCountLast6Months"] = "0" - overdueRiskProduct["repaymentFailureAmountLast6Months"] = "0" - overdueRiskProduct["repaymentSuccessCountLast6Months"] = "-" - overdueRiskProduct["repaymentSuccessAmountLast6Months"] = "-" - overdueRiskProduct["specialListVerification"] = []interface{}{} - - // 从借选指数评估获取数据(主要数据源) - jrzq5e9fData := getMapValue(apiData, "JRZQ5E9F") - if jrzq5e9fData != nil { - if jrzq5e9fMap, ok := jrzq5e9fData.(map[string]interface{}); ok { - // 当前是否存在逾期未结清 - if xypCpl0044, ok := jrzq5e9fMap["xyp_cpl0044"].(string); ok { - if xypCpl0044 == "1" { - overdueRiskProduct["hasUnsettledOverdue"] = "逾期" - } - } - - // 当前逾期机构数(需要区间化) - if xypCpl0071, ok := jrzq5e9fMap["xyp_cpl0071"].(string); ok && xypCpl0071 != "" { - overdueRiskProduct["currentOverdueInstitutionCount"] = convertXypCpl0071ToInterval(xypCpl0071) - } - - // 当前逾期金额(需要区间化) - if xypCpl0072, ok := jrzq5e9fMap["xyp_cpl0072"].(string); ok && xypCpl0072 != "" { - overdueRiskProduct["currentOverdueAmount"] = convertXypCpl0072ToInterval(xypCpl0072) - } - - // 已结清机构数(需要区间化) - if xypCpl0002, ok := jrzq5e9fMap["xyp_cpl0002"].(string); ok && xypCpl0002 != "" { - overdueRiskProduct["settledInstitutionCount"] = convertXypCpl0002ToInterval(xypCpl0002) - } - - // 贷款总机构数(需要区间化) - if xypCpl0001, ok := jrzq5e9fMap["xyp_cpl0001"].(string); ok && xypCpl0001 != "" { - overdueRiskProduct["totalLoanInstitutions"] = convertXypCpl0001ToInterval(xypCpl0001) - } - - // 贷款已还款总金额(使用xyp_t01aazzzc,需要区间化转换) - if xypT01aazzzc, ok := jrzq5e9fMap["xyp_t01aazzzc"].(string); ok && xypT01aazzzc != "" { - overdueRiskProduct["totalLoanRepaymentAmount"] = convertXypT01aazzzcToInterval(xypT01aazzzc) - } - - // 最近1天是否发生过逾期 - if xypCpl0028, ok := jrzq5e9fMap["xyp_cpl0028"].(string); ok { - if xypCpl0028 == "1" { - overdueRiskProduct["overdueLast1Day"] = "逾期" - } - } - - // 最近7天是否发生过逾期 - if xypCpl0029, ok := jrzq5e9fMap["xyp_cpl0029"].(string); ok { - if xypCpl0029 == "1" { - overdueRiskProduct["overdueLast7Days"] = "逾期" - } - } - - // 最近14天是否发生过逾期 - if xypCpl0030, ok := jrzq5e9fMap["xyp_cpl0030"].(string); ok { - if xypCpl0030 == "1" { - overdueRiskProduct["overdueLast14Days"] = "逾期" - } - } - - // 最近30天是否发生过逾期 - if xypCpl0031, ok := jrzq5e9fMap["xyp_cpl0031"].(string); ok { - if xypCpl0031 == "1" { - overdueRiskProduct["overdueLast30Days"] = "逾期" - } - } - - // 最近一次还款成功距离当前天数(需要区间化转换) - if xypCpl0068, ok := jrzq5e9fMap["xyp_cpl0068"].(string); ok && xypCpl0068 != "" { - overdueRiskProduct["daysSinceLastSuccessfulRepayment"] = convertXypCpl0068ToInterval(xypCpl0068) - } - - // 最近7天还款失败次数(需要区间化) - if xypCpl0018, ok := jrzq5e9fMap["xyp_cpl0018"].(string); ok && xypCpl0018 != "" { - overdueRiskProduct["repaymentFailureCountLast7Days"] = convertXypCpl0018ToInterval(xypCpl0018) - } - - // 最近7天还款失败金额(需要区间化) - if xypCpl0034, ok := jrzq5e9fMap["xyp_cpl0034"].(string); ok && xypCpl0034 != "" { - overdueRiskProduct["repaymentFailureAmountLast7Days"] = convertXypCpl0034ToInterval(xypCpl0034) - } - - // 最近7天还款成功次数(需要区间化) - if xypCpl0019, ok := jrzq5e9fMap["xyp_cpl0019"].(string); ok && xypCpl0019 != "" && xypCpl0019 != "0" { - overdueRiskProduct["repaymentSuccessCountLast7Days"] = convertXypCpl0019ToInterval(xypCpl0019) - } else { - overdueRiskProduct["repaymentSuccessCountLast7Days"] = "-" - } - - // 最近7天还款成功金额(需要区间化) - if xypCpl0035, ok := jrzq5e9fMap["xyp_cpl0035"].(string); ok && xypCpl0035 != "" && xypCpl0035 != "0" { - overdueRiskProduct["repaymentSuccessAmountLast7Days"] = convertXypCpl0035ToInterval(xypCpl0035) - } else { - overdueRiskProduct["repaymentSuccessAmountLast7Days"] = "-" - } - - // 最近14天还款失败次数(需要区间化) - if xypCpl0020, ok := jrzq5e9fMap["xyp_cpl0020"].(string); ok && xypCpl0020 != "" { - overdueRiskProduct["repaymentFailureCountLast14Days"] = convertXypCpl0020ToInterval(xypCpl0020) - } - - // 最近14天还款失败金额(需要区间化) - if xypCpl0036, ok := jrzq5e9fMap["xyp_cpl0036"].(string); ok && xypCpl0036 != "" { - overdueRiskProduct["repaymentFailureAmountLast14Days"] = convertXypCpl0036ToInterval(xypCpl0036) - } - - // 最近14天还款成功次数(需要区间化) - if xypCpl0021, ok := jrzq5e9fMap["xyp_cpl0021"].(string); ok && xypCpl0021 != "" && xypCpl0021 != "0" { - overdueRiskProduct["repaymentSuccessCountLast14Days"] = convertXypCpl0021ToInterval(xypCpl0021) - } else { - overdueRiskProduct["repaymentSuccessCountLast14Days"] = "-" - } - - // 最近14天还款成功金额(需要区间化) - if xypCpl0037, ok := jrzq5e9fMap["xyp_cpl0037"].(string); ok && xypCpl0037 != "" && xypCpl0037 != "0" { - overdueRiskProduct["repaymentSuccessAmountLast14Days"] = convertXypCpl0037ToInterval(xypCpl0037) - } else { - overdueRiskProduct["repaymentSuccessAmountLast14Days"] = "-" - } - - // 最近1个月还款失败次数(需要区间化) - if xypCpl0022, ok := jrzq5e9fMap["xyp_cpl0022"].(string); ok && xypCpl0022 != "" { - overdueRiskProduct["repaymentFailureCountLastMonth"] = convertXypCpl0022ToInterval(xypCpl0022) - } - - // 最近1个月还款失败金额(需要区间化) - if xypCpl0038, ok := jrzq5e9fMap["xyp_cpl0038"].(string); ok && xypCpl0038 != "" { - overdueRiskProduct["repaymentFailureAmountLastMonth"] = convertXypCpl0038ToInterval(xypCpl0038) - } - - // 最近1个月还款成功次数(需要区间化) - if xypCpl0023, ok := jrzq5e9fMap["xyp_cpl0023"].(string); ok && xypCpl0023 != "" && xypCpl0023 != "0" { - overdueRiskProduct["repaymentSuccessCountLastMonth"] = convertXypCpl0023ToInterval(xypCpl0023) - } else { - overdueRiskProduct["repaymentSuccessCountLastMonth"] = "-" - } - - // 最近1个月还款成功金额(需要区间化) - if xypCpl0039, ok := jrzq5e9fMap["xyp_cpl0039"].(string); ok && xypCpl0039 != "" && xypCpl0039 != "0" { - overdueRiskProduct["repaymentSuccessAmountLastMonth"] = convertXypCpl0039ToInterval(xypCpl0039) - } else { - overdueRiskProduct["repaymentSuccessAmountLastMonth"] = "-" - } - - // 最近3个月还款失败次数(需要区间化) - if xypCpl0024, ok := jrzq5e9fMap["xyp_cpl0024"].(string); ok && xypCpl0024 != "" { - overdueRiskProduct["repaymentFailureCountLast3Months"] = convertXypCpl0024ToInterval(xypCpl0024) - } - - // 最近3个月还款失败金额(需要区间化) - if xypCpl0040, ok := jrzq5e9fMap["xyp_cpl0040"].(string); ok && xypCpl0040 != "" { - overdueRiskProduct["repaymentFailureAmountLast3Months"] = convertXypCpl0040ToInterval(xypCpl0040) - } - - // 最近3个月还款成功次数(需要区间化) - if xypCpl0025, ok := jrzq5e9fMap["xyp_cpl0025"].(string); ok && xypCpl0025 != "" && xypCpl0025 != "0" { - overdueRiskProduct["repaymentSuccessCountLast3Months"] = convertXypCpl0025ToInterval(xypCpl0025) - } else { - overdueRiskProduct["repaymentSuccessCountLast3Months"] = "-" - } - - // 最近3个月还款成功金额(需要区间化) - if xypCpl0041, ok := jrzq5e9fMap["xyp_cpl0041"].(string); ok && xypCpl0041 != "" && xypCpl0041 != "0" { - overdueRiskProduct["repaymentSuccessAmountLast3Months"] = convertXypCpl0041ToInterval(xypCpl0041) - } else { - overdueRiskProduct["repaymentSuccessAmountLast3Months"] = "-" - } - - // 最近6个月还款失败次数(需要区间化) - if xypCpl0026, ok := jrzq5e9fMap["xyp_cpl0026"].(string); ok && xypCpl0026 != "" { - overdueRiskProduct["repaymentFailureCountLast6Months"] = convertXypCpl0026ToInterval(xypCpl0026) - } - - // 最近6个月还款失败金额(需要区间化) - if xypCpl0042, ok := jrzq5e9fMap["xyp_cpl0042"].(string); ok && xypCpl0042 != "" { - overdueRiskProduct["repaymentFailureAmountLast6Months"] = convertXypCpl0042ToInterval(xypCpl0042) - } - - // 最近6个月还款成功次数 - if xypCpl0027, ok := jrzq5e9fMap["xyp_cpl0027"].(string); ok && xypCpl0027 != "" && xypCpl0027 != "0" { - overdueRiskProduct["repaymentSuccessCountLast6Months"] = xypCpl0027 - } else { - overdueRiskProduct["repaymentSuccessCountLast6Months"] = "-" - } - - // 最近6个月还款成功金额 - if xypCpl0043, ok := jrzq5e9fMap["xyp_cpl0043"].(string); ok && xypCpl0043 != "" && xypCpl0043 != "0" { - overdueRiskProduct["repaymentSuccessAmountLast6Months"] = xypCpl0043 - } else { - overdueRiskProduct["repaymentSuccessAmountLast6Months"] = "-" - } - - // 判断风险标识 - hasOverdue := overdueRiskProduct["hasUnsettledOverdue"] == "逾期" - hasRecentOverdue := overdueRiskProduct["overdueLast7Days"] == "逾期" || - overdueRiskProduct["overdueLast14Days"] == "逾期" || - overdueRiskProduct["overdueLast30Days"] == "逾期" - - if hasOverdue || hasRecentOverdue { - overdueRiskProduct["lyjlhyFlag"] = 1 // 高风险 - overdueRiskProduct["dkzhktjFlag"] = 1 // 高风险 - } else { - overdueRiskProduct["lyjlhyFlag"] = 2 // 低风险 - overdueRiskProduct["dkzhktjFlag"] = 2 // 低风险 - } - } - } - - // 从特殊名单验证B获取数据 - jrzq8a2dData := getMapValue(apiData, "JRZQ8A2D") - if jrzq8a2dData != nil { - if jrzq8a2dMap, ok := jrzq8a2dData.(map[string]interface{}); ok { - // 构建specialListVerification列表 - specialListVerification := make([]interface{}, 0) - - // 检查各种特殊名单(字段名映射:源数据中字段名没有id_前缀) - specialListFields := []struct { - fieldName string - reason string - }{ - {"court_bad", "法院失信人"}, - {"court_executed", "法院被执行人"}, - {"bank_bad", "银行中风险"}, - {"bank_overdue", "银行一般风险"}, - {"bank_lost", "银行高风险"}, - {"nbank_bad", "非银中风险"}, - {"nbank_overdue", "非银一般风险"}, - {"nbank_lost", "非银高风险"}, - } - - // 检查id字段 - if idData, ok := jrzq8a2dMap["id"].(map[string]interface{}); ok { - for _, field := range specialListFields { - // 源数据中字段名是 court_executed,不是 id_court_executed - if val, ok := idData[field.fieldName].(string); ok && val == "0" { - // 根据源数据分析,val == "0" 表示命中 - specialListVerification = append(specialListVerification, map[string]interface{}{ - "mz": "通过身份证号查询" + field.reason, - "jg": "本人直接命中", - }) - // 添加命中次数 - allnumField := field.fieldName + "_allnum" - if allnumVal, ok := idData[allnumField].(string); ok && allnumVal != "" { - specialListVerification = append(specialListVerification, map[string]interface{}{ - "mz": field.reason + "命中次数", - "jg": allnumVal + "次", - }) - } - // 添加距今时间 - timeField := field.fieldName + "_time" - if timeVal, ok := idData[timeField].(string); ok && timeVal != "" { - specialListVerification = append(specialListVerification, map[string]interface{}{ - "mz": field.reason + "距今时间", - "jg": timeVal + "年", - }) - } - } - } - } - - // 检查cell字段(手机号相关) - if cellData, ok := jrzq8a2dMap["cell"].(map[string]interface{}); ok { - for _, field := range specialListFields { - // 源数据中字段名是 nbank_bad,不是 cell_nbank_bad - if val, ok := cellData[field.fieldName].(string); ok && val == "0" { - // 根据源数据分析,val == "0" 表示命中 - specialListVerification = append(specialListVerification, map[string]interface{}{ - "mz": "通过手机号查询" + field.reason, - "jg": "本人直接命中", - }) - // 添加命中次数 - allnumField := field.fieldName + "_allnum" - if allnumVal, ok := cellData[allnumField].(string); ok && allnumVal != "" { - specialListVerification = append(specialListVerification, map[string]interface{}{ - "mz": field.reason + "(手机号)命中次数", - "jg": allnumVal + "次", - }) - } - // 添加距今时间 - timeField := field.fieldName + "_time" - if timeVal, ok := cellData[timeField].(string); ok && timeVal != "" { - specialListVerification = append(specialListVerification, map[string]interface{}{ - "mz": field.reason + "(手机号)距今时间", - "jg": timeVal + "年", - }) - } - } - } - } - - if len(specialListVerification) > 0 { - overdueRiskProduct["specialListVerification"] = specialListVerification - overdueRiskProduct["tsmdyzFlag"] = 1 // 高风险 - } else { - overdueRiskProduct["tsmdyzFlag"] = 2 // 低风险 - } - } - } - - return overdueRiskProduct -} - -// buildMultCourtInfo 构建司法风险核验产品 -func buildMultCourtInfo(apiData map[string]interface{}, log *zap.Logger) map[string]interface{} { - multCourtInfo := make(map[string]interface{}) - - // 初始化默认值 - multCourtInfo["legalCases"] = []interface{}{} - multCourtInfo["executionCases"] = []interface{}{} - multCourtInfo["disinCases"] = []interface{}{} - multCourtInfo["limitCases"] = []interface{}{} - multCourtInfo["legalCasesFlag"] = 0 - multCourtInfo["executionCasesFlag"] = 0 - multCourtInfo["disinCasesFlag"] = 0 - multCourtInfo["limitCasesFlag"] = 0 - - // 从个人司法涉诉查询获取数据 - flxg7e8fData := getMapValue(apiData, "FLXG7E8F") - if flxg7e8fData != nil { - if flxg7e8fMap, ok := flxg7e8fData.(map[string]interface{}); ok { - // 获取judicial_data - if judicialData, ok := flxg7e8fMap["judicial_data"].(map[string]interface{}); ok { - // 处理lawsuitStat - if lawsuitStat, ok := judicialData["lawsuitStat"].(map[string]interface{}); ok { - // 收集所有涉案公告案件(民事、刑事、行政、保全、破产)- 都归到legalCases - legalCases := make([]interface{}, 0) - - // 处理民事案件(civil)- 结构:civil.cases[] - if civilVal, exists := lawsuitStat["civil"]; exists && civilVal != nil { - if civil, ok := civilVal.(map[string]interface{}); ok && len(civil) > 0 { - if cases, ok := civil["cases"].([]interface{}); ok && len(cases) > 0 { - for _, caseItem := range cases { - if caseMap, ok := caseItem.(map[string]interface{}); ok { - legalCase := convertCivilCase(caseMap) - if legalCase != nil { - legalCases = append(legalCases, legalCase) - } - } - } - } - } - } - - // 处理刑事案件(criminal)- 结构:criminal.cases[] - if criminalVal, exists := lawsuitStat["criminal"]; exists && criminalVal != nil { - if criminal, ok := criminalVal.(map[string]interface{}); ok && len(criminal) > 0 { - if cases, ok := criminal["cases"].([]interface{}); ok && len(cases) > 0 { - for _, caseItem := range cases { - if caseMap, ok := caseItem.(map[string]interface{}); ok { - legalCase := convertCriminalCase(caseMap) - if legalCase != nil { - legalCases = append(legalCases, legalCase) - } - } - } - } - } - } - - // 处理行政案件(administrative)- 结构:administrative.cases[] - if administrativeVal, exists := lawsuitStat["administrative"]; exists && administrativeVal != nil { - if administrative, ok := administrativeVal.(map[string]interface{}); ok && len(administrative) > 0 { - if cases, ok := administrative["cases"].([]interface{}); ok && len(cases) > 0 { - for _, caseItem := range cases { - if caseMap, ok := caseItem.(map[string]interface{}); ok { - legalCase := convertAdministrativeCase(caseMap) - if legalCase != nil { - legalCases = append(legalCases, legalCase) - } - } - } - } - } - } - - // 处理保全审查案件(preservation)- 结构:preservation.cases[] - if preservationVal, exists := lawsuitStat["preservation"]; exists && preservationVal != nil { - if preservation, ok := preservationVal.(map[string]interface{}); ok && len(preservation) > 0 { - if cases, ok := preservation["cases"].([]interface{}); ok && len(cases) > 0 { - for _, caseItem := range cases { - if caseMap, ok := caseItem.(map[string]interface{}); ok { - legalCase := convertPreservationCase(caseMap) - if legalCase != nil { - legalCases = append(legalCases, legalCase) - } - } - } - } - } - } - - // 处理破产清算案件(bankrupt)- 结构:bankrupt.cases[] - if bankruptVal, exists := lawsuitStat["bankrupt"]; exists && bankruptVal != nil { - if bankrupt, ok := bankruptVal.(map[string]interface{}); ok && len(bankrupt) > 0 { - if cases, ok := bankrupt["cases"].([]interface{}); ok && len(cases) > 0 { - for _, caseItem := range cases { - if caseMap, ok := caseItem.(map[string]interface{}); ok { - legalCase := convertBankruptCase(caseMap) - if legalCase != nil { - legalCases = append(legalCases, legalCase) - } - } - } - } - } - } - - // 如果有涉案公告案件,设置legalCases和legalCasesFlag - if len(legalCases) > 0 { - multCourtInfo["legalCases"] = legalCases - multCourtInfo["legalCasesFlag"] = 1 // 高风险 - } - - // 处理执行案件(executionCases)- 单独处理 - if implement, ok := lawsuitStat["implement"].(map[string]interface{}); ok { - if cases, ok := implement["cases"].([]interface{}); ok { - executionCases := make([]interface{}, 0) - for _, caseItem := range cases { - if caseMap, ok := caseItem.(map[string]interface{}); ok { - executionCase := convertExecutionCase(caseMap) - if executionCase != nil { - executionCases = append(executionCases, executionCase) - } - } - } - if len(executionCases) > 0 { - multCourtInfo["executionCases"] = executionCases - multCourtInfo["executionCasesFlag"] = 1 // 高风险 - } - } - } - } - - // 处理失信案件(disinCases) - if breachCaseList, ok := judicialData["breachCaseList"].([]interface{}); ok { - disinCases := make([]interface{}, 0) - for _, caseItem := range breachCaseList { - if caseMap, ok := caseItem.(map[string]interface{}); ok { - disinCase := convertBreachCase(caseMap) - if disinCase != nil { - disinCases = append(disinCases, disinCase) - } - } - } - if len(disinCases) > 0 { - multCourtInfo["disinCases"] = disinCases - multCourtInfo["disinCasesFlag"] = 1 // 高风险 - } - } - - // 处理限高案件(limitCases) - if consumptionRestrictionList, ok := judicialData["consumptionRestrictionList"].([]interface{}); ok { - limitCases := make([]interface{}, 0) - for _, caseItem := range consumptionRestrictionList { - if caseMap, ok := caseItem.(map[string]interface{}); ok { - limitCase := convertLimitCase(caseMap) - if limitCase != nil { - limitCases = append(limitCases, limitCase) - } - } - } - if len(limitCases) > 0 { - multCourtInfo["limitCases"] = limitCases - multCourtInfo["limitCasesFlag"] = 1 // 高风险 - } - } - } - } - } - - return multCourtInfo -} - -// convertCivilCase 转换民事案件 -func convertCivilCase(caseMap map[string]interface{}) map[string]interface{} { - caseInfo := make(map[string]interface{}) - - // 案号 - if cAh, ok := caseMap["c_ah"].(string); ok { - caseInfo["caseNumber"] = cAh - } else { - return nil // 案号是必需字段 - } - - // 案件类型 - // if nAjlx, ok := caseMap["n_ajlx"].(string); ok { - // caseInfo["caseType"] = nAjlx - // } else { - // caseInfo["caseType"] = "未知" - // } - caseInfo["caseType"] = "民事案件" - // 法院 - if nJbfy, ok := caseMap["n_jbfy"].(string); ok { - caseInfo["court"] = nJbfy - } else { - caseInfo["court"] = "" - } - - // 诉讼地位 - if nSsdw, ok := caseMap["n_ssdw"].(string); ok { - caseInfo["litigantType"] = nSsdw - } else { - caseInfo["litigantType"] = "" - } - - // 立案时间 - if dLarq, ok := caseMap["d_larq"].(string); ok { - caseInfo["filingTime"] = dLarq - } else { - caseInfo["filingTime"] = "" - } - - // 结案时间 - if dJarq, ok := caseMap["d_jarq"].(string); ok { - caseInfo["disposalTime"] = dJarq - } else { - caseInfo["disposalTime"] = "" - } - - // 案件状态 - if nAjjzjd, ok := caseMap["n_ajjzjd"].(string); ok { - caseInfo["caseStatus"] = nAjjzjd - } else { - caseInfo["caseStatus"] = "" - } - - // 执行金额(民事案件通常没有) - caseInfo["executionAmount"] = "" - caseInfo["repaidAmount"] = "" - - // 案由 - if nLaay, ok := caseMap["n_laay"].(string); ok { - caseInfo["caseReason"] = nLaay - } else { - caseInfo["caseReason"] = "未知" - } - - // 结案方式 - if nJafs, ok := caseMap["n_jafs"].(string); ok { - caseInfo["disposalMethod"] = nJafs - } else { - caseInfo["disposalMethod"] = "" - } - - // 判决结果(只使用详细的判决结果文本c_gkws_pjjg,如果没有则返回空字符串) - if cGkwsPjjg, ok := caseMap["c_gkws_pjjg"].(string); ok && cGkwsPjjg != "" { - caseInfo["judgmentResult"] = cGkwsPjjg - } else { - caseInfo["judgmentResult"] = "" - } - - return caseInfo -} - -// convertExecutionCase 转换执行案件 -func convertExecutionCase(caseMap map[string]interface{}) map[string]interface{} { - caseInfo := make(map[string]interface{}) - - // 案号 - if cAh, ok := caseMap["c_ah"].(string); ok { - caseInfo["caseNumber"] = cAh - } else { - return nil - } - - // 案件类型 - // if nAjlx, ok := caseMap["n_ajlx"].(string); ok { - // caseInfo["caseType"] = nAjlx - // } else if nJaay, ok := caseMap["n_jaay"].(string); ok { - // caseInfo["caseType"] = nJaay + "执行" - // } else { - // caseInfo["caseType"] = "执行" - // } - caseInfo["caseType"] = "执行案件" - // 法院 - if nJbfy, ok := caseMap["n_jbfy"].(string); ok { - caseInfo["court"] = nJbfy - } else { - caseInfo["court"] = "" - } - - // 诉讼地位 - if nSsdw, ok := caseMap["n_ssdw"].(string); ok { - caseInfo["litigantType"] = nSsdw - } else { - caseInfo["litigantType"] = "" - } - - // 立案时间 - if dLarq, ok := caseMap["d_larq"].(string); ok { - caseInfo["filingTime"] = dLarq - } else { - caseInfo["filingTime"] = "" - } - - // 结案时间 - if dJarq, ok := caseMap["d_jarq"].(string); ok { - caseInfo["disposalTime"] = dJarq - } else { - caseInfo["disposalTime"] = "" - } - - // 案件状态 - if nAjjzjd, ok := caseMap["n_ajjzjd"].(string); ok { - caseInfo["caseStatus"] = nAjjzjd - } else { - caseInfo["caseStatus"] = "" - } - - // 执行金额(支持字符串、数字和interface{}类型) - var executionAmountStr string - if nSqzxbdjeVal, exists := caseMap["n_sqzxbdje"]; exists && nSqzxbdjeVal != nil { - switch v := nSqzxbdjeVal.(type) { - case string: - if v != "" { - executionAmountStr = v - } - case float64: - executionAmountStr = strconv.FormatFloat(v, 'f', -1, 64) - case int: - executionAmountStr = strconv.Itoa(v) - case int64: - executionAmountStr = strconv.FormatInt(v, 10) - } - } - // 如果n_sqzxbdje没有值,尝试使用n_jabdje - if executionAmountStr == "" { - if nJabdjeVal, exists := caseMap["n_jabdje"]; exists && nJabdjeVal != nil { - switch v := nJabdjeVal.(type) { - case string: - if v != "" { - executionAmountStr = v - } - case float64: - executionAmountStr = strconv.FormatFloat(v, 'f', -1, 64) - case int: - executionAmountStr = strconv.Itoa(v) - case int64: - executionAmountStr = strconv.FormatInt(v, 10) - } - } - } - caseInfo["executionAmount"] = executionAmountStr - - // 已还款金额(从结案金额n_jabdje获取) - var repaidAmountStr string - if nJabdjeVal, exists := caseMap["n_jabdje"]; exists && nJabdjeVal != nil { - switch v := nJabdjeVal.(type) { - case string: - if v != "" { - repaidAmountStr = v - } - case float64: - repaidAmountStr = strconv.FormatFloat(v, 'f', -1, 64) - case int: - repaidAmountStr = strconv.Itoa(v) - case int64: - repaidAmountStr = strconv.FormatInt(v, 10) - } - } - caseInfo["repaidAmount"] = repaidAmountStr - - // 案由 - if nLaay, ok := caseMap["n_laay"].(string); ok { - caseInfo["caseReason"] = nLaay - } else { - caseInfo["caseReason"] = "未知" - } - - // 结案方式 - if nJafs, ok := caseMap["n_jafs"].(string); ok { - caseInfo["disposalMethod"] = nJafs - } else { - caseInfo["disposalMethod"] = "" - } - - caseInfo["judgmentResult"] = "" - - // 原案号(从c_ah_ys提取,保留完整值包括冒号后的ID) - if cAhYs, ok := caseMap["c_ah_ys"].(string); ok && cAhYs != "" { - caseInfo["oldCaseNumber"] = cAhYs - } else { - caseInfo["oldCaseNumber"] = "" - } - - return caseInfo -} - -// convertBreachCase 转换失信案件 -func convertBreachCase(caseMap map[string]interface{}) map[string]interface{} { - caseInfo := make(map[string]interface{}) - - // 案号 - if caseNumber, ok := caseMap["caseNumber"].(string); ok { - caseInfo["caseNumber"] = caseNumber - } else { - return nil - } - - // 案件类型 - caseInfo["caseType"] = "失信被执行人" - - // 法院 - if executiveCourt, ok := caseMap["executiveCourt"].(string); ok { - caseInfo["court"] = executiveCourt - } else { - caseInfo["court"] = "" - } - - // 诉讼地位 - caseInfo["litigantType"] = "被执行人" - - // 立案时间 - if fileDate, ok := caseMap["fileDate"].(string); ok { - caseInfo["filingTime"] = fileDate - } else { - caseInfo["filingTime"] = "" - } - - // 结案时间 - if issueDate, ok := caseMap["issueDate"].(string); ok { - caseInfo["disposalTime"] = issueDate - } else { - caseInfo["disposalTime"] = "" - } - - // 案件状态 - if fulfillStatus, ok := caseMap["fulfillStatus"].(string); ok { - if fulfillStatus == "全部未履行" { - caseInfo["caseStatus"] = "未结案" - } else { - caseInfo["caseStatus"] = "已结案" - } - } else { - caseInfo["caseStatus"] = "" - } - - // 执行金额 - if estimatedJudgementAmount, ok := caseMap["estimatedJudgementAmount"].(float64); ok { - caseInfo["executionAmount"] = strconv.FormatFloat(estimatedJudgementAmount, 'f', -1, 64) - } else { - caseInfo["executionAmount"] = "" - } - - caseInfo["repaidAmount"] = "" - - // 案由 - if obligation, ok := caseMap["obligation"].(string); ok { - caseInfo["caseReason"] = obligation - } else { - caseInfo["caseReason"] = "未知" - } - - // 结案方式 - if concreteDetails, ok := caseMap["concreteDetails"].(string); ok { - caseInfo["disposalMethod"] = concreteDetails - } else { - caseInfo["disposalMethod"] = "" - } - - caseInfo["judgmentResult"] = "" - - return caseInfo -} - -// convertLimitCase 转换限高案件 -func convertLimitCase(caseMap map[string]interface{}) map[string]interface{} { - caseInfo := make(map[string]interface{}) - - // 案号 - if caseNumber, ok := caseMap["caseNumber"].(string); ok { - caseInfo["caseNumber"] = caseNumber - } else { - return nil - } - - // 案件类型 - caseInfo["caseType"] = "限制消费令" - - // 法院 - if executiveCourt, ok := caseMap["executiveCourt"].(string); ok { - caseInfo["court"] = executiveCourt - } else { - caseInfo["court"] = "" - } - - // 诉讼地位 - caseInfo["litigantType"] = "被限制消费人" - - // 立案时间 - if issueDate, ok := caseMap["issueDate"].(string); ok { - caseInfo["filingTime"] = issueDate - } else { - caseInfo["filingTime"] = "" - } - - // 结案时间 - caseInfo["disposalTime"] = "" - caseInfo["caseStatus"] = "未结案" - caseInfo["executionAmount"] = "" - caseInfo["repaidAmount"] = "" - caseInfo["caseReason"] = "未知" - caseInfo["disposalMethod"] = "" - caseInfo["judgmentResult"] = "" - - return caseInfo -} - -// convertPreservationCase 转换保全审查案件 -func convertPreservationCase(caseMap map[string]interface{}) map[string]interface{} { - caseInfo := make(map[string]interface{}) - - // 案号 - if cAh, ok := caseMap["c_ah"].(string); ok { - caseInfo["caseNumber"] = cAh - } else { - return nil // 案号是必需字段 - } - - // 案件类型 - caseInfo["caseType"] = "保全审查" - - // 法院 - if nJbfy, ok := caseMap["n_jbfy"].(string); ok { - caseInfo["court"] = nJbfy - } else { - caseInfo["court"] = "" - } - - // 诉讼地位 - if nSsdw, ok := caseMap["n_ssdw"].(string); ok { - caseInfo["litigantType"] = nSsdw - } else { - caseInfo["litigantType"] = "" - } - - // 立案时间 - if dLarq, ok := caseMap["d_larq"].(string); ok { - caseInfo["filingTime"] = dLarq - } else { - caseInfo["filingTime"] = "" - } - - // 结案时间 - if dJarq, ok := caseMap["d_jarq"].(string); ok { - caseInfo["disposalTime"] = dJarq - } else { - caseInfo["disposalTime"] = "" - } - - // 案件状态 - if nAjjzjd, ok := caseMap["n_ajjzjd"].(string); ok { - caseInfo["caseStatus"] = nAjjzjd - } else { - caseInfo["caseStatus"] = "" - } - - // 执行金额(申请保全数额) - var executionAmountStr string - if nSqbqseVal, exists := caseMap["n_sqbqse"]; exists && nSqbqseVal != nil { - switch v := nSqbqseVal.(type) { - case string: - if v != "" { - executionAmountStr = v - } - case float64: - executionAmountStr = strconv.FormatFloat(v, 'f', -1, 64) - case int: - executionAmountStr = strconv.Itoa(v) - case int64: - executionAmountStr = strconv.FormatInt(v, 10) - } - } - caseInfo["executionAmount"] = executionAmountStr - - // 已还款金额(保全案件通常没有) - caseInfo["repaidAmount"] = "" - - // 案由 - if nLaay, ok := caseMap["n_laay"].(string); ok { - caseInfo["caseReason"] = nLaay - } else { - caseInfo["caseReason"] = "未知" - } - - // 结案方式 - if nJafs, ok := caseMap["n_jafs"].(string); ok { - caseInfo["disposalMethod"] = nJafs - } else { - caseInfo["disposalMethod"] = "" - } - - // 判决结果 - if cGkwsPjjg, ok := caseMap["c_gkws_pjjg"].(string); ok && cGkwsPjjg != "" { - caseInfo["judgmentResult"] = cGkwsPjjg - } else { - caseInfo["judgmentResult"] = "" - } - - return caseInfo -} - -// convertCriminalCase 转换刑事案件 -func convertCriminalCase(caseMap map[string]interface{}) map[string]interface{} { - caseInfo := make(map[string]interface{}) - - // 案号 - if cAh, ok := caseMap["c_ah"].(string); ok { - caseInfo["caseNumber"] = cAh - } else { - return nil // 案号是必需字段 - } - - // 案件类型 - // if nAjlx, ok := caseMap["n_ajlx"].(string); ok { - // caseInfo["caseType"] = nAjlx - // } else { - // caseInfo["caseType"] = "刑事案件" - // } - caseInfo["caseType"] = "刑事案件" - - // 法院 - if nJbfy, ok := caseMap["n_jbfy"].(string); ok { - caseInfo["court"] = nJbfy - } else { - caseInfo["court"] = "" - } - - // 诉讼地位 - if nSsdw, ok := caseMap["n_ssdw"].(string); ok { - caseInfo["litigantType"] = nSsdw - } else { - caseInfo["litigantType"] = "" - } - - // 立案时间 - if dLarq, ok := caseMap["d_larq"].(string); ok { - caseInfo["filingTime"] = dLarq - } else { - caseInfo["filingTime"] = "" - } - - // 结案时间 - if dJarq, ok := caseMap["d_jarq"].(string); ok { - caseInfo["disposalTime"] = dJarq - } else { - caseInfo["disposalTime"] = "" - } - - // 案件状态 - if nAjjzjd, ok := caseMap["n_ajjzjd"].(string); ok { - caseInfo["caseStatus"] = nAjjzjd - } else { - caseInfo["caseStatus"] = "" - } - - // 执行金额(刑事案件通常没有) - caseInfo["executionAmount"] = "" - caseInfo["repaidAmount"] = "" - - // 案由 - if nLaay, ok := caseMap["n_laay"].(string); ok { - caseInfo["caseReason"] = nLaay - } else { - caseInfo["caseReason"] = "未知" - } - - // 结案方式 - if nJafs, ok := caseMap["n_jafs"].(string); ok { - caseInfo["disposalMethod"] = nJafs - } else { - caseInfo["disposalMethod"] = "" - } - - // 判决结果(只使用详细的判决结果文本c_gkws_pjjg,如果没有则返回空字符串) - if cGkwsPjjg, ok := caseMap["c_gkws_pjjg"].(string); ok && cGkwsPjjg != "" { - caseInfo["judgmentResult"] = cGkwsPjjg - } else { - caseInfo["judgmentResult"] = "" - } - - return caseInfo -} - -// convertAdministrativeCase 转换行政案件 -func convertAdministrativeCase(caseMap map[string]interface{}) map[string]interface{} { - caseInfo := make(map[string]interface{}) - - // 案号 - if cAh, ok := caseMap["c_ah"].(string); ok { - caseInfo["caseNumber"] = cAh - } else { - return nil // 案号是必需字段 - } - - // 案件类型 - // if nAjlx, ok := caseMap["n_ajlx"].(string); ok { - // caseInfo["caseType"] = nAjlx - // } else { - // caseInfo["caseType"] = "行政案件" - // } - - caseInfo["caseType"] = "行政案件" - - // 法院 - if nJbfy, ok := caseMap["n_jbfy"].(string); ok { - caseInfo["court"] = nJbfy - } else { - caseInfo["court"] = "" - } - - // 诉讼地位 - if nSsdw, ok := caseMap["n_ssdw"].(string); ok { - caseInfo["litigantType"] = nSsdw - } else { - caseInfo["litigantType"] = "" - } - - // 立案时间 - if dLarq, ok := caseMap["d_larq"].(string); ok { - caseInfo["filingTime"] = dLarq - } else { - caseInfo["filingTime"] = "" - } - - // 结案时间 - if dJarq, ok := caseMap["d_jarq"].(string); ok { - caseInfo["disposalTime"] = dJarq - } else { - caseInfo["disposalTime"] = "" - } - - // 案件状态 - if nAjjzjd, ok := caseMap["n_ajjzjd"].(string); ok { - caseInfo["caseStatus"] = nAjjzjd - } else { - caseInfo["caseStatus"] = "" - } - - // 执行金额(行政案件通常没有) - caseInfo["executionAmount"] = "" - caseInfo["repaidAmount"] = "" - - // 案由 - if nLaay, ok := caseMap["n_laay"].(string); ok { - caseInfo["caseReason"] = nLaay - } else { - caseInfo["caseReason"] = "未知" - } - - // 结案方式 - if nJafs, ok := caseMap["n_jafs"].(string); ok { - caseInfo["disposalMethod"] = nJafs - } else { - caseInfo["disposalMethod"] = "" - } - - // 判决结果(只使用详细的判决结果文本c_gkws_pjjg,如果没有则返回空字符串) - if cGkwsPjjg, ok := caseMap["c_gkws_pjjg"].(string); ok && cGkwsPjjg != "" { - caseInfo["judgmentResult"] = cGkwsPjjg - } else { - caseInfo["judgmentResult"] = "" - } - - return caseInfo -} - -// convertBankruptCase 转换破产清算案件 -func convertBankruptCase(caseMap map[string]interface{}) map[string]interface{} { - caseInfo := make(map[string]interface{}) - - // 案号 - if cAh, ok := caseMap["c_ah"].(string); ok { - caseInfo["caseNumber"] = cAh - } else { - return nil // 案号是必需字段 - } - - // 案件类型 - // if nAjlx, ok := caseMap["n_ajlx"].(string); ok { - // caseInfo["caseType"] = nAjlx - // } else { - // caseInfo["caseType"] = "破产清算" - // } - caseInfo["caseType"] = "破产清算" - - // 法院 - if nJbfy, ok := caseMap["n_jbfy"].(string); ok { - caseInfo["court"] = nJbfy - } else { - caseInfo["court"] = "" - } - - // 诉讼地位 - if nSsdw, ok := caseMap["n_ssdw"].(string); ok { - caseInfo["litigantType"] = nSsdw - } else { - caseInfo["litigantType"] = "" - } - - // 立案时间 - if dLarq, ok := caseMap["d_larq"].(string); ok { - caseInfo["filingTime"] = dLarq - } else { - caseInfo["filingTime"] = "" - } - - // 结案时间 - if dJarq, ok := caseMap["d_jarq"].(string); ok { - caseInfo["disposalTime"] = dJarq - } else { - caseInfo["disposalTime"] = "" - } - - // 案件状态 - if nAjjzjd, ok := caseMap["n_ajjzjd"].(string); ok { - caseInfo["caseStatus"] = nAjjzjd - } else { - caseInfo["caseStatus"] = "" - } - - // 执行金额(破产案件通常没有) - caseInfo["executionAmount"] = "" - caseInfo["repaidAmount"] = "" - - // 案由 - if nLaay, ok := caseMap["n_laay"].(string); ok { - caseInfo["caseReason"] = nLaay - } else { - caseInfo["caseReason"] = "未知" - } - - // 结案方式 - if nJafs, ok := caseMap["n_jafs"].(string); ok { - caseInfo["disposalMethod"] = nJafs - } else { - caseInfo["disposalMethod"] = "" - } - - // 判决结果(只使用详细的判决结果文本c_gkws_pjjg,如果没有则返回空字符串) - if cGkwsPjjg, ok := caseMap["c_gkws_pjjg"].(string); ok && cGkwsPjjg != "" { - caseInfo["judgmentResult"] = cGkwsPjjg - } else { - caseInfo["judgmentResult"] = "" - } - - return caseInfo -} - -// buildLoanEvaluationVerificationDetail 构建借贷评估产品 -func buildLoanEvaluationVerificationDetail(apiData map[string]interface{}, log *zap.Logger) map[string]interface{} { - detail := make(map[string]interface{}) - - // 初始化默认值 - detail["riskFlag"] = 0 - detail["organLoanPerformances"] = []interface{}{} - detail["customerLoanPerformances"] = []interface{}{} - detail["businessLoanPerformances"] = []interface{}{} - detail["timeLoanPerformances"] = []interface{}{} - - // 从借贷意向验证A获取数据 - jrzq6f2aData := getMapValue(apiData, "JRZQ6F2A") - if jrzq6f2aData != nil { - if jrzq6f2aMap, ok := jrzq6f2aData.(map[string]interface{}); ok { - // 获取risk_screen_v2 - if riskScreenV2, ok := jrzq6f2aMap["risk_screen_v2"].(map[string]interface{}); ok { - // 获取variables - if variables, ok := riskScreenV2["variables"].([]interface{}); ok && len(variables) > 0 { - if variable, ok := variables[0].(map[string]interface{}); ok { - if variableValue, ok := variable["variableValue"].(map[string]interface{}); ok { - // 构建organLoanPerformances(本人在本机构借贷意向表现) - organLoanPerformances := buildOrganLoanPerformances(variableValue) - if len(organLoanPerformances) > 0 { - detail["organLoanPerformances"] = organLoanPerformances - } - - // 构建customerLoanPerformances(本人在各个客户类型借贷意向表现) - customerLoanPerformances := buildCustomerLoanPerformances(variableValue) - if len(customerLoanPerformances) > 0 { - detail["customerLoanPerformances"] = customerLoanPerformances - } - - // 构建businessLoanPerformances(本人在各个业务类型借贷意向表现) - businessLoanPerformances := buildBusinessLoanPerformances(variableValue) - if len(businessLoanPerformances) > 0 { - detail["businessLoanPerformances"] = businessLoanPerformances - } - - // 构建timeLoanPerformances(本人在异常时间段借贷意向表现) - timeLoanPerformances := buildTimeLoanPerformances(variableValue) - if len(timeLoanPerformances) > 0 { - detail["timeLoanPerformances"] = timeLoanPerformances - } - - // 判断风险标识:根据申请频率判断 - hasHighRisk := checkLoanRisk(variableValue) - if hasHighRisk { - detail["riskFlag"] = 1 // 高风险 - } else { - detail["riskFlag"] = 2 // 低风险 - } - } - } - } - } - } - } - - return detail -} - -// buildOrganLoanPerformances 构建本人在本机构借贷意向表现 -func buildOrganLoanPerformances(variableValue map[string]interface{}) []interface{} { - performances := make([]interface{}, 0) - - // 时间周期映射 - periodMap := map[string]string{ - "last7Day": "d7", - "last15Day": "d15", - "last1Month": "m1", - "last3Month": "m3", - "last6Month": "m6", - "last12Month": "m12", - } - - // 银行(格式:身份证/手机号) - bankPerf := make(map[string]interface{}) - bankPerf["applyCount"] = "银行" - for period, apiPeriod := range periodMap { - idAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_bank_allnum", apiPeriod)) - cellAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_cell_bank_allnum", apiPeriod)) - if idAllnum == "" { - idAllnum = "0" - } - if cellAllnum == "" { - cellAllnum = "0" - } - bankPerf[period] = fmt.Sprintf("%s/%s", idAllnum, cellAllnum) - } - performances = append(performances, bankPerf) - - // 非银(格式:身份证/手机号) - nbankPerf := make(map[string]interface{}) - nbankPerf["applyCount"] = "非银" - for period, apiPeriod := range periodMap { - idAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_nbank_allnum", apiPeriod)) - cellAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_cell_nbank_allnum", apiPeriod)) - if idAllnum == "" { - idAllnum = "0" - } - if cellAllnum == "" { - cellAllnum = "0" - } - nbankPerf[period] = fmt.Sprintf("%s/%s", idAllnum, cellAllnum) - } - performances = append(performances, nbankPerf) - - return performances -} - -// buildCustomerLoanPerformances 构建本人在各个客户类型借贷意向表现 -func buildCustomerLoanPerformances(variableValue map[string]interface{}) []interface{} { - performances := make([]interface{}, 0) - - // 客户类型列表 - customerTypes := []struct { - typeName string - prefix string - }{ - {"银行汇总", "bank"}, - {"传统银行", "bank_tra"}, - {"网络零售银行", "bank_ret"}, - {"非银汇总", "nbank"}, - {"持牌网络小贷", "nbank_nsloan"}, - {"持牌消费金融", "nbank_cons"}, - {"持牌融资租赁机构", "nbank_finlea"}, - {"持牌汽车金融", "nbank_autofin"}, - {"其他", "nbank_oth"}, - } - - periodMap := map[string]string{ - "last7Day": "d7", - "last15Day": "d15", - "last1Month": "m1", - "last3Month": "m3", - "last6Month": "m6", - "last12Month": "m12", - } - - for _, customerType := range customerTypes { - perf := make(map[string]interface{}) - perf["type"] = customerType.typeName - - for period, apiPeriod := range periodMap { - // 格式:身份证/手机号 - idOrgnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_%s_orgnum", apiPeriod, customerType.prefix)) - cellOrgnum := getStringValue(variableValue, fmt.Sprintf("als_%s_cell_%s_orgnum", apiPeriod, customerType.prefix)) - idAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_%s_allnum", apiPeriod, customerType.prefix)) - cellAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_cell_%s_allnum", apiPeriod, customerType.prefix)) - - if idOrgnum == "" { - idOrgnum = "0" - } - if cellOrgnum == "" { - cellOrgnum = "0" - } - if idAllnum == "" { - idAllnum = "0" - } - if cellAllnum == "" { - cellAllnum = "0" - } - - perf[period] = fmt.Sprintf("%s/%s", idOrgnum, cellOrgnum) - perf[period+"Count"] = fmt.Sprintf("%s/%s", idAllnum, cellAllnum) - } - - performances = append(performances, perf) - } - - return performances -} - -// buildBusinessLoanPerformances 构建本人在各个业务类型借贷意向表现 -func buildBusinessLoanPerformances(variableValue map[string]interface{}) []interface{} { - performances := make([]interface{}, 0) - - // 业务类型列表 - businessTypes := []struct { - typeName string - prefix string - }{ - {"信用卡(类信用卡)", "rel"}, - {"线上小额现金贷", "pdl"}, - {"汽车金融", "af"}, - {"线上消费分期", "coon"}, - {"线下消费分期", "cooff"}, - {"其他", "nbank_oth"}, // 修复:应该是nbank_oth而不是oth - } - - periodMap := map[string]string{ - "last7Day": "d7", - "last15Day": "d15", - "last1Month": "m1", - "last3Month": "m3", - "last6Month": "m6", - "last12Month": "m12", - } - - for _, businessType := range businessTypes { - perf := make(map[string]interface{}) - perf["type"] = businessType.typeName - - for period, apiPeriod := range periodMap { - // 格式:身份证/手机号 - idOrgnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_%s_orgnum", apiPeriod, businessType.prefix)) - cellOrgnum := getStringValue(variableValue, fmt.Sprintf("als_%s_cell_%s_orgnum", apiPeriod, businessType.prefix)) - idAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_%s_allnum", apiPeriod, businessType.prefix)) - cellAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_cell_%s_allnum", apiPeriod, businessType.prefix)) - - if idOrgnum == "" { - idOrgnum = "0" - } - if cellOrgnum == "" { - cellOrgnum = "0" - } - if idAllnum == "" { - idAllnum = "0" - } - if cellAllnum == "" { - cellAllnum = "0" - } - - perf[period] = fmt.Sprintf("%s/%s", idOrgnum, cellOrgnum) - perf[period+"Count"] = fmt.Sprintf("%s/%s", idAllnum, cellAllnum) - } - - performances = append(performances, perf) - } - - return performances -} - -// buildTimeLoanPerformances 构建本人在异常时间段借贷意向表现 -func buildTimeLoanPerformances(variableValue map[string]interface{}) []interface{} { - performances := make([]interface{}, 0) - - // 异常时间段类型 - timeTypes := []struct { - typeName string - timeType string - orgType string - }{ - {"夜间-银行", "night", "bank"}, - {"夜间-非银", "night", "nbank"}, - {"周末-银行", "week", "bank"}, - {"周末-非银", "week", "nbank"}, - } - - periodMap := map[string]string{ - "last7Day": "d7", - "last15Day": "d15", - "last1Month": "m1", - "last3Month": "m3", - "last6Month": "m6", - "last12Month": "m12", - } - - for _, timeType := range timeTypes { - perf := make(map[string]interface{}) - perf["type"] = timeType.typeName - - for period, apiPeriod := range periodMap { - // 格式:身份证/手机号 - idOrgnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_%s_%s_orgnum", apiPeriod, timeType.orgType, timeType.timeType)) - cellOrgnum := getStringValue(variableValue, fmt.Sprintf("als_%s_cell_%s_%s_orgnum", apiPeriod, timeType.orgType, timeType.timeType)) - idAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_%s_%s_allnum", apiPeriod, timeType.orgType, timeType.timeType)) - cellAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_cell_%s_%s_allnum", apiPeriod, timeType.orgType, timeType.timeType)) - - if idOrgnum == "" { - idOrgnum = "0" - } - if cellOrgnum == "" { - cellOrgnum = "0" - } - if idAllnum == "" { - idAllnum = "0" - } - if cellAllnum == "" { - cellAllnum = "0" - } - - perf[period] = fmt.Sprintf("%s/%s", idOrgnum, cellOrgnum) - perf[period+"Count"] = fmt.Sprintf("%s/%s", idAllnum, cellAllnum) - } - - performances = append(performances, perf) - } - - return performances -} - -// checkLoanRisk 检查借贷风险 -func checkLoanRisk(variableValue map[string]interface{}) bool { - // 检查近期申请频率是否过高(调高风险阈值:从>=5提高到>=10) - periods := []string{"d7", "d15", "m1", "m3"} - for _, period := range periods { - bankAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_bank_allnum", period)) - nbankAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_nbank_allnum", period)) - - if bankAllnum != "" && bankAllnum != "0" { - if count, err := strconv.Atoi(bankAllnum); err == nil && count >= 10 { - return true - } - } - if nbankAllnum != "" && nbankAllnum != "0" { - if count, err := strconv.Atoi(nbankAllnum); err == nil && count >= 10 { - return true - } - } - } - return false -} - -// getStringValue 安全获取字符串值 -func getStringValue(data map[string]interface{}, key string) string { - if val, ok := data[key]; ok { - if str, ok := val.(string); ok { - return str - } - } - return "" -} - -// convertXypT01aazzzcToInterval 将xyp_t01aazzzc的值转换为区间格式 -// 映射规则:1->(0,1000), 2->[1000,4800), 3->[4800,Inf) -func convertXypT01aazzzcToInterval(value string) string { - switch value { - case "1": - return "(0,1000)" - case "2": - return "[1000,4800)" - case "3": - return "[4800,+)" - default: - return "0" - } -} - -// convertXypCpl0068ToInterval 将xyp_cpl0068的值转换为区间格式 -// 映射规则:1->(0,5), 2->[5,50), 3->[50,160), 4->[160,Inf) -func convertXypCpl0068ToInterval(value string) string { - switch value { - case "1": - return "(0,5)" - case "2": - return "[5,50)" - case "3": - return "[50,160)" - case "4": - return "160+" - default: - return "0" - } -} - -// convertXypCpl0001ToInterval 将xyp_cpl0001的值转换为区间格式 -// 映射规则:1->(0,9), 2->[9,14), 3->[14,Inf) -func convertXypCpl0001ToInterval(value string) string { - switch value { - case "1": - return "(0,9)" - case "2": - return "[9,14)" - case "3": - return "[14,+)" - default: - return "0" - } -} - -// convertXypCpl0002ToInterval 将xyp_cpl0002的值转换为区间格式 -// 映射规则:1->(0,5), 2->[5,9), 3->[9,14), 4->[14,17), 5->[17,Inf) -func convertXypCpl0002ToInterval(value string) string { - switch value { - case "1": - return "(0,5)" - case "2": - return "[5,9)" - case "3": - return "[9,14)" - case "4": - return "[14,17)" - case "5": - return "[17,+)" - default: - return "0" - } -} - -// convertXypCpl0071ToInterval 将xyp_cpl0071的值转换为区间格式 -// 映射规则:1->[1,2), 2->[2,4), 3->[4,Inf) -func convertXypCpl0071ToInterval(value string) string { - switch value { - case "1": - return "[1,2)" - case "2": - return "[2,4)" - case "3": - return "[4,+)" - default: - return "0" - } -} - -// convertXypCpl0072ToInterval 将xyp_cpl0072的值转换为区间格式 -// 映射规则:1->(0,1000), 2->[1000,2000), 3->[2000,3000), 4->[3000,5000), 5->[5000,7000), 6->[7000,11000), 7->[11000,Inf) -func convertXypCpl0072ToInterval(value string) string { - switch value { - case "1": - return "(0,1000)" - case "2": - return "[1000,2000)" - case "3": - return "[2000,3000)" - case "4": - return "[3000,5000)" - case "5": - return "[5000,7000)" - case "6": - return "[7000,11000)" - case "7": - return "[11000,+)" - default: - return "0" - } -} - -// convertXypCpl0018ToInterval 将xyp_cpl0018的值转换为区间格式 -// 映射规则:1->(0,3), 2->[3,5), 3->[5,7), 4->[7,Inf) -func convertXypCpl0018ToInterval(value string) string { - switch value { - case "1": - return "(0,3)" - case "2": - return "[3,5)" - case "3": - return "[5,7)" - case "4": - return "[7,+)" - default: - return "0" - } -} - -// convertXypCpl0019ToInterval 将xyp_cpl0019的值转换为区间格式 -// 映射规则:1->(0,3), 2->[3,13), 3->[13,Inf) -func convertXypCpl0019ToInterval(value string) string { - switch value { - case "1": - return "(0,3)" - case "2": - return "[3,13)" - case "3": - return "[13,+)" - default: - return "0" - } -} - -// convertXypCpl0020ToInterval 将xyp_cpl0020的值转换为区间格式 -// 映射规则:1->(0,3), 2->[3,5), 3->[5,15), 4->[15,Inf) -func convertXypCpl0020ToInterval(value string) string { - switch value { - case "1": - return "(0,3)" - case "2": - return "[3,5)" - case "3": - return "[5,15)" - case "4": - return "[15,+)" - default: - return "0" - } -} - -// convertXypCpl0021ToInterval 将xyp_cpl0021的值转换为区间格式 -// 映射规则:1->(0,5), 2->[5,21), 3->[21,Inf) -func convertXypCpl0021ToInterval(value string) string { - switch value { - case "1": - return "(0,5)" - case "2": - return "[5,21)" - case "3": - return "[21,+)" - default: - return "0" - } -} - -// convertXypCpl0022ToInterval 将xyp_cpl0022的值转换为区间格式 -// 映射规则:1->(0,3), 2->[3,5), 3->[5,34), 4->[34,Inf) -func convertXypCpl0022ToInterval(value string) string { - switch value { - case "1": - return "(0,3)" - case "2": - return "[3,5)" - case "3": - return "[5,34)" - case "4": - return "[34,+)" - default: - return "0" - } -} - -// convertXypCpl0023ToInterval 将xyp_cpl0023的值转换为区间格式 -// 映射规则:1->(0,7), 2->[7,34), 3->[34,Inf) -func convertXypCpl0023ToInterval(value string) string { - switch value { - case "1": - return "(0,7)" - case "2": - return "[7,34)" - case "3": - return "[34,+)" - default: - return "0" - } -} - -// convertXypCpl0024ToInterval 将xyp_cpl0024的值转换为区间格式 -// 映射规则:1->(0,6), 2->[6,22), 3->[22,56), 4->[56,Inf) -func convertXypCpl0024ToInterval(value string) string { - switch value { - case "1": - return "(0,6)" - case "2": - return "[6,22)" - case "3": - return "[22,56)" - case "4": - return "[56,+)" - default: - return "0" - } -} - -// convertXypCpl0025ToInterval 将xyp_cpl0025的值转换为区间格式 -// 映射规则:1->(0,2), 2->[2,31), 3->[31,Inf) -func convertXypCpl0025ToInterval(value string) string { - switch value { - case "1": - return "(0,2)" - case "2": - return "[2,31)" - case "3": - return "[31,+)" - default: - return "0" - } -} - -// convertXypCpl0026ToInterval 将xyp_cpl0026的值转换为区间格式 -// 映射规则:1->(0,3), 2->[3,25), 3->[25,30), 4->[30,70), 5->[70,Inf) -func convertXypCpl0026ToInterval(value string) string { - switch value { - case "1": - return "(0,3)" - case "2": - return "[3,25)" - case "3": - return "[25,30)" - case "4": - return "[30,70)" - case "5": - return "[70,+)" - default: - return "0" - } -} - -// convertXypCpl0034ToInterval 将xyp_cpl0034的值转换为区间格式 -// 映射规则:1->(0,2000), 2->[2000,10000), 3->[10000,17000), 4->[17000,26000), 5->[26000,Inf) -func convertXypCpl0034ToInterval(value string) string { - switch value { - case "1": - return "(0,2000)" - case "2": - return "[2000,10000)" - case "3": - return "[10000,17000)" - case "4": - return "[17000,26000)" - case "5": - return "[26000,+)" - default: - return "0" - } -} - -// convertXypCpl0035ToInterval 将xyp_cpl0035的值转换为区间格式 -// 映射规则:1->(0,2000), 2->[2000,17000), 3->[17000,Inf) -func convertXypCpl0035ToInterval(value string) string { - switch value { - case "1": - return "(0,2000)" - case "2": - return "[2000,17000)" - case "3": - return "[17000,+)" - default: - return "0" - } -} - -// convertXypCpl0036ToInterval 将xyp_cpl0036的值转换为区间格式 -// 映射规则:1->(0,1000), 2->[1000,4000), 3->[4000,9000), 4->[9000,30000), 5->[30000,Inf) -func convertXypCpl0036ToInterval(value string) string { - switch value { - case "1": - return "(0,1000)" - case "2": - return "[1000,4000)" - case "3": - return "[4000,9000)" - case "4": - return "[9000,30000)" - case "5": - return "[30000,+)" - default: - return "0" - } -} - -// convertXypCpl0037ToInterval 将xyp_cpl0037的值转换为区间格式 -// 映射规则:1->(0,9000), 2->[9000,31000), 3->[31000,Inf) -func convertXypCpl0037ToInterval(value string) string { - switch value { - case "1": - return "(0,9000)" - case "2": - return "[9000,31000)" - case "3": - return "[31000,+)" - default: - return "0" - } -} - -// convertXypCpl0038ToInterval 将xyp_cpl0038的值转换为区间格式 -// 映射规则:1->(0,6000), 2->[6000,10000), 3->[10000,50000), 4->[50000,Inf) -func convertXypCpl0038ToInterval(value string) string { - switch value { - case "1": - return "(0,6000)" - case "2": - return "[6000,10000)" - case "3": - return "[10000,50000)" - case "4": - return "[50000,+)" - default: - return "0" - } -} - -// convertXypCpl0039ToInterval 将xyp_cpl0039的值转换为区间格式 -// 映射规则:1->(0,10000), 2->[10000,36000), 3->[36000,Inf) -func convertXypCpl0039ToInterval(value string) string { - switch value { - case "1": - return "(0,10000)" - case "2": - return "[10000,36000)" - case "3": - return "[36000,+)" - default: - return "0" - } -} - -// convertXypCpl0040ToInterval 将xyp_cpl0040的值转换为区间格式 -// 映射规则:1->(0,10000), 2->[10000,50000), 3->[50000,80000), 4->[80000,Inf) -func convertXypCpl0040ToInterval(value string) string { - switch value { - case "1": - return "(0,10000)" - case "2": - return "[10000,50000)" - case "3": - return "[50000,80000)" - case "4": - return "[80000,+)" - default: - return "0" - } -} - -// convertXypCpl0041ToInterval 将xyp_cpl0041的值转换为区间格式 -// 映射规则:1->(0,13000), 2->[13000,49000), 3->[49000,Inf) -func convertXypCpl0041ToInterval(value string) string { - switch value { - case "1": - return "(0,13000)" - case "2": - return "[13000,49000)" - case "3": - return "[49000,+)" - default: - return "0" - } -} - -// convertXypCpl0042ToInterval 将xyp_cpl0042的值转换为区间格式 -// 映射规则:1->(0,2000), 2->[2000,30000), 3->[30000,60000), 4->[60000,90000), 5->[90000,Inf) -func convertXypCpl0042ToInterval(value string) string { - switch value { - case "1": - return "(0,2000)" - case "2": - return "[2000,30000)" - case "3": - return "[30000,60000)" - case "4": - return "[60000,90000)" - case "5": - return "[90000,+)" - default: - return "0" - } -} - -// checkRecentApplicationFrequency 检查近期申请频率 -func checkRecentApplicationFrequency(variableValue map[string]interface{}, riskWarning *map[string]interface{}) { - // 检查近7天、近15天、近1个月的申请次数 - periods := []struct { - apiPeriod string - field string - }{ - {"d7", "frequentApplicationRecent"}, - {"d15", "frequentApplicationRecent"}, - {"m1", "frequentApplicationRecent"}, - } - - for _, period := range periods { - bankAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_bank_allnum", period.apiPeriod)) - nbankAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_nbank_allnum", period.apiPeriod)) - - // 如果近7天申请次数>=10,认为是极为频繁(调高风险阈值,进一步提高阈值) - if bankAllnum != "" && bankAllnum != "0" { - if count, err := strconv.Atoi(bankAllnum); err == nil && count >= 10 { - (*riskWarning)[period.field] = 1 - break - } - } - if nbankAllnum != "" && nbankAllnum != "0" { - if count, err := strconv.Atoi(nbankAllnum); err == nil && count >= 10 { - (*riskWarning)[period.field] = 1 - break - } - } - } -} - -// checkBankApplicationFrequency 检查银行/非银申请次数 -func checkBankApplicationFrequency(variableValue map[string]interface{}, riskWarning *map[string]interface{}) { - // 检查近6个月和近12个月的申请次数 - periods := []struct { - apiPeriod string - }{ - {"m6"}, - {"m12"}, - } - - bankTotal := 0 - nbankTotal := 0 - - for _, period := range periods { - bankAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_bank_allnum", period.apiPeriod)) - nbankAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_nbank_allnum", period.apiPeriod)) - - if bankAllnum != "" && bankAllnum != "0" { - if count, err := strconv.Atoi(bankAllnum); err == nil { - bankTotal += count - } - } - if nbankAllnum != "" && nbankAllnum != "0" { - if count, err := strconv.Atoi(nbankAllnum); err == nil { - nbankTotal += count - } - } - } - - // 银行申请次数极多(>=20,调高风险阈值,进一步提高阈值) - if bankTotal >= 20 { - (*riskWarning)["frequentBankApplications"] = 1 - } else if bankTotal >= 15 { - (*riskWarning)["moreFrequentBankApplications"] = 1 - } - - // 非银申请次数极多(>=20,调高风险阈值,进一步提高阈值) - if nbankTotal >= 20 { - (*riskWarning)["frequentNonBankApplications"] = 1 - } else if nbankTotal >= 15 { - (*riskWarning)["moreFrequentNonBankApplications"] = 1 - } -} - -// checkDebtPressure 检查偿债压力 -func checkDebtPressure(apiData map[string]interface{}, riskWarning *map[string]interface{}) { - // 从借选指数评估获取数据 - jrzq5e9fData := getMapValue(apiData, "JRZQ5E9F") - if jrzq5e9fData != nil { - if jrzq5e9fMap, ok := jrzq5e9fData.(map[string]interface{}); ok { - // 检查当前逾期金额和机构数 - currentOverdueAmount := getStringValue(jrzq5e9fMap, "xyp_cpl0072") - currentOverdueInstitutionCount := getStringValue(jrzq5e9fMap, "xyp_cpl0071") - - // 如果当前逾期金额较大或机构数较多,认为偿债压力极高 - if currentOverdueAmount != "" && currentOverdueAmount != "0" && currentOverdueAmount != "1" { - (*riskWarning)["highDebtPressure"] = 1 - } - if currentOverdueInstitutionCount != "" && currentOverdueInstitutionCount != "0" && currentOverdueInstitutionCount != "1" { - (*riskWarning)["highDebtPressure"] = 1 - } - } - } -} - -// calculateLoanRiskCounts 计算借贷评估风险计数 -func calculateLoanRiskCounts(variableValue map[string]interface{}, riskWarning *map[string]interface{}) { - // 计算jdpgRiskCounts(借贷评估风险计数) - jdpgRiskCount := 0 - if val, ok := (*riskWarning)["frequentApplicationRecent"].(int); ok && val == 1 { - jdpgRiskCount++ - } - if val, ok := (*riskWarning)["frequentBankApplications"].(int); ok && val == 1 { - jdpgRiskCount++ - } - if val, ok := (*riskWarning)["frequentNonBankApplications"].(int); ok && val == 1 { - jdpgRiskCount++ - } - if val, ok := (*riskWarning)["highDebtPressure"].(int); ok && val == 1 { - jdpgRiskCount++ - } - - if jdpgRiskCount > 0 { - (*riskWarning)["jdpgRiskCounts"] = jdpgRiskCount - if jdpgRiskCount >= 3 { - (*riskWarning)["jdpgRiskHighCounts"] = 1 - } else { - (*riskWarning)["jdpgRiskMiddleCounts"] = 1 - } - } -} - -// checkRentalApplicationFrequency 检查租赁申请频率 -func checkRentalApplicationFrequency(jrzq1d09Map map[string]interface{}, riskWarning *map[string]interface{}) { - // 检查近3个月和近6个月的申请次数 - periods := []struct { - apiPeriod string - }{ - {"m3"}, - {"m6"}, - {"m12"}, - } - - totalCount := 0 - - for _, period := range periods { - idAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_id_allnum", period.apiPeriod)) - cellAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_cell_allnum", period.apiPeriod)) - - // 取较大的值 - idCount := 0 - cellCount := 0 - if idAllnum != "" && idAllnum != "0" { - if count, err := strconv.Atoi(idAllnum); err == nil { - idCount = count - } - } - if cellAllnum != "" && cellAllnum != "0" { - if count, err := strconv.Atoi(cellAllnum); err == nil { - cellCount = count - } - } - - if idCount > cellCount { - totalCount += idCount - } else { - totalCount += cellCount - } - } - - // 租赁申请次数极多(>=20,调高风险阈值,进一步提高阈值) - if totalCount >= 20 { - (*riskWarning)["veryFrequentRentalApplications"] = 1 - (*riskWarning)["frequentRentalApplications"] = 1 - } else if totalCount >= 15 { - (*riskWarning)["frequentRentalApplications"] = 1 - } -} - -// buildLeasingRiskAssessment 构建租赁风险评估产品 -func buildLeasingRiskAssessment(apiData map[string]interface{}, log *zap.Logger) map[string]interface{} { - assessment := make(map[string]interface{}) - - // 设置默认值 - assessment["riskFlag"] = 0 - // 设置所有3C相关的字段为默认值 - timePeriods := []string{"3Days", "7Days", "14Days", "Month", "3Months", "6Months", "12Months"} - timeTypes := []string{"Night", "Weekend"} - queryTypes := []string{"Platform", "Institution"} - - for _, period := range timePeriods { - for _, queryType := range queryTypes { - fieldName := fmt.Sprintf("threeC%sApplicationCountLast%s", queryType, period) - assessment[fieldName] = "0/0" - for _, timeType := range timeTypes { - fieldName := fmt.Sprintf("threeC%sApplicationCountLast%s%s", queryType, period, timeType) - assessment[fieldName] = "0/0" - } - } - } - - // 从3C租赁申请意向获取数据 - jrzq1d09Data := getMapValue(apiData, "JRZQ1D09") - if jrzq1d09Data != nil { - if jrzq1d09Map, ok := jrzq1d09Data.(map[string]interface{}); ok { - // 映射规则: - // - Institution(3C机构): 使用id(身份证)查询的数据 - // - Platform(3C平台): 使用cell(手机号)查询的数据 - // 格式: "身份证/手机号",如果没有匹配的就是0 - - // 时间周期映射:3Days->d3, 7Days->d7, 14Days->d14, Month->m1, 3Months->m3, 6Months->m6, 12Months->m12 - periodMap := map[string]string{ - "3Days": "d3", - "7Days": "d7", - "14Days": "d14", - "Month": "m1", - "3Months": "m3", - "6Months": "m6", - "12Months": "m12", - } - - // 填充Institution字段(3C机构,格式:身份证/手机号) - for period, apiPeriod := range periodMap { - // 基础字段:threeCInstitutionApplicationCountLast{period} - fieldName := fmt.Sprintf("threeCInstitutionApplicationCountLast%s", period) - idAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_id_allnum", apiPeriod)) - cellAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_cell_allnum", apiPeriod)) - if idAllnum == "" { - idAllnum = "0" - } - if cellAllnum == "" { - cellAllnum = "0" - } - assessment[fieldName] = fmt.Sprintf("%s/%s", idAllnum, cellAllnum) - - // Weekend字段 - fieldNameWeekend := fmt.Sprintf("threeCInstitutionApplicationCountLast%sWeekend", period) - idWeekendAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_id_weekend_allnum", apiPeriod)) - cellWeekendAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_cell_weekend_allnum", apiPeriod)) - if idWeekendAllnum == "" { - idWeekendAllnum = "0" - } - if cellWeekendAllnum == "" { - cellWeekendAllnum = "0" - } - assessment[fieldNameWeekend] = fmt.Sprintf("%s/%s", idWeekendAllnum, cellWeekendAllnum) - - // Night字段 - fieldNameNight := fmt.Sprintf("threeCInstitutionApplicationCountLast%sNight", period) - idNightAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_id_night_allnum", apiPeriod)) - cellNightAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_cell_night_allnum", apiPeriod)) - if idNightAllnum == "" { - idNightAllnum = "0" - } - if cellNightAllnum == "" { - cellNightAllnum = "0" - } - assessment[fieldNameNight] = fmt.Sprintf("%s/%s", idNightAllnum, cellNightAllnum) - } - - // 填充Platform字段(3C平台,格式:身份证/手机号) - for period, apiPeriod := range periodMap { - // 基础字段:threeCPlatformApplicationCountLast{period} - fieldName := fmt.Sprintf("threeCPlatformApplicationCountLast%s", period) - idAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_id_allnum", apiPeriod)) - cellAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_cell_allnum", apiPeriod)) - if idAllnum == "" { - idAllnum = "0" - } - if cellAllnum == "" { - cellAllnum = "0" - } - assessment[fieldName] = fmt.Sprintf("%s/%s", idAllnum, cellAllnum) - - // Weekend字段 - fieldNameWeekend := fmt.Sprintf("threeCPlatformApplicationCountLast%sWeekend", period) - idWeekendAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_id_weekend_allnum", apiPeriod)) - cellWeekendAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_cell_weekend_allnum", apiPeriod)) - if idWeekendAllnum == "" { - idWeekendAllnum = "0" - } - if cellWeekendAllnum == "" { - cellWeekendAllnum = "0" - } - assessment[fieldNameWeekend] = fmt.Sprintf("%s/%s", idWeekendAllnum, cellWeekendAllnum) - - // Night字段 - fieldNameNight := fmt.Sprintf("threeCPlatformApplicationCountLast%sNight", period) - idNightAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_id_night_allnum", apiPeriod)) - cellNightAllnum := getStringValue(jrzq1d09Map, fmt.Sprintf("alc_%s_cell_night_allnum", apiPeriod)) - if idNightAllnum == "" { - idNightAllnum = "0" - } - if cellNightAllnum == "" { - cellNightAllnum = "0" - } - assessment[fieldNameNight] = fmt.Sprintf("%s/%s", idNightAllnum, cellNightAllnum) - } - - // 仅使用近12月(Last12,对应 m12)的次数作为判断依据, - // totalCount 取身份证维度和手机号维度中的较大值,而不是两者相加 - totalCount := 0 - - idKey12 := "alc_m12_id_allnum" - cellKey12 := "alc_m12_cell_allnum" - - idCount := 0 - cellCount := 0 - - // 身份证维度(近12月) - if v, ok := jrzq1d09Map[idKey12]; ok { - switch vv := v.(type) { - case string: - if vv != "" && vv != "0" { - if parsed, err := strconv.Atoi(vv); err == nil { - idCount = parsed - } - } - case float64: - if vv > 0 { - idCount = int(vv) - } - case int: - if vv > 0 { - idCount = vv - } - } - } - - // 手机号维度(近12月) - if v, ok := jrzq1d09Map[cellKey12]; ok { - switch vv := v.(type) { - case string: - if vv != "" && vv != "0" { - if parsed, err := strconv.Atoi(vv); err == nil { - cellCount = parsed - } - } - case float64: - if vv > 0 { - cellCount = int(vv) - } - case int: - if vv > 0 { - cellCount = vv - } - } - } - - // 使用身份证和手机号两个维度中的较大值作为近12月总次数 - if idCount >= cellCount { - totalCount = idCount - } else { - totalCount = cellCount - } - - // 根据近12月总申请次数设置风险标识: - // - totalCount == 0 -> 0 无风险 / 未查得 - // - 0 < totalCount <= 10 -> 2 低风险(有少量租赁申请) - // - totalCount > 10 -> 1 高风险(租赁申请很多) - if totalCount == 0 { - assessment["riskFlag"] = 0 - } else if totalCount <= 10 { - assessment["riskFlag"] = 2 - } else { - assessment["riskFlag"] = 1 - } - } - } - - return assessment -} - -// 辅助函数 - -func getMapValue(data map[string]interface{}, key string) interface{} { - if val, ok := data[key]; ok { - return val - } - return nil -} - -// keyPersonFlagEq1 判断 keyPersonCheckList 中某标识是否为 1(支持 int/float64) -func keyPersonFlagEq1(m map[string]interface{}, key string) bool { - v, ok := m[key] - if !ok { - return false - } - switch vv := v.(type) { - case int: - return vv == 1 - case float64: - return vv == 1 - default: - return false - } -} - -func maskName(name string) string { - if name == "" { - return "" - } - // 使用rune处理Unicode字符,支持中文等多字节字符 - runes := []rune(name) - if len(runes) <= 1 { - return name - } - if len(runes) == 2 { - // 两个字符:第一个字符 + "*" - return string(runes[0]) + "*" - } - // 三个或以上字符:第一个字符 + "*" + 最后一个字符 - return string(runes[0]) + "*" + string(runes[len(runes)-1]) -} - -func maskIDCard(idCard string) string { - if len(idCard) < 8 { - return idCard - } - return idCard[:4] + "**" + idCard[len(idCard)-6:] -} - -func maskMobile(mobile string) string { - if len(mobile) < 7 { - return mobile - } - return mobile[:3] + "****" + mobile[len(mobile)-4:] -} - -func calculateAgeAndSex(idCard string) (int, string) { - if len(idCard) != 18 { - return 0, "" - } - - // 提取出生年份 - yearStr := idCard[6:10] - year, err := strconv.Atoi(yearStr) - if err != nil { - return 0, "" - } - - now := time.Now() - - // 计算年龄(简化处理,使用当前年份) - age := now.Year() - year - - // 提取性别(第17位,奇数为男,偶数为女) - sexCode := idCard[16:17] - sexCodeInt, err := strconv.Atoi(sexCode) - if err != nil { - return age, "" - } - - sex := "女" - if sexCodeInt%2 == 1 { - sex = "男" - } - - return age, sex -} - -func getLocationFromIDCard(idCard string) string { - if len(idCard) < 6 { - return "" - } - // 这里需要根据身份证前6位查询地区代码表 - // 简化处理,返回空字符串 - return "" -} - -func getPhoneArea(mobile string) string { - // 这里需要根据手机号前7位查询归属地 - // 简化处理,返回空字符串 - return "" -} - -// normalizeProvinceName 标准化省份名称,用于比较 -// 处理各种格式:广西壮族自治区 -> 广西,北京市 -> 北京,内蒙古自治区 -> 内蒙古等 -func normalizeProvinceName(province string) string { - if province == "" { - return "" - } - - // 去除前后空格 - province = strings.TrimSpace(province) - - // 特殊处理:内蒙古(必须在最前面) - if strings.Contains(province, "内蒙古") { - return "内蒙古" - } - - // 处理自治区、特别行政区、直辖市等后缀 - suffixes := []string{ - "壮族自治区", "回族自治区", "维吾尔自治区", "自治区", - "特别行政区", "省", "市", - } - - normalized := province - for _, suffix := range suffixes { - if strings.HasSuffix(normalized, suffix) { - normalized = strings.TrimSuffix(normalized, suffix) - break - } - } - - return normalized -} - -// normalizeCityName 标准化城市名称,用于比较 -// 处理各种格式:南宁地区 -> 南宁,南宁市 -> 南宁等 -func normalizeCityName(city string) string { - if city == "" { - return "" - } - - // 去除前后空格 - city = strings.TrimSpace(city) - - // 处理各种后缀 - suffixes := []string{ - "地区", "市", "自治州", "盟", "县", "区", - } - - normalized := city - for _, suffix := range suffixes { - if strings.HasSuffix(normalized, suffix) { - normalized = strings.TrimSuffix(normalized, suffix) - break - } - } - - return normalized -} - -// extractProvinceFromAddress 从完整地址中提取省份名称 -func extractProvinceFromAddress(address string) string { - if address == "" { - return "" - } - - // 特殊处理:内蒙古(必须在最前面,因为"内蒙古"可能被其他模式误匹配) - if strings.HasPrefix(address, "内蒙古") { - return "内蒙古自治区" - } - - // 处理直辖市(必须在自治区之前) - if strings.HasPrefix(address, "北京") { - return "北京市" - } - if strings.HasPrefix(address, "上海") { - return "上海市" - } - if strings.HasPrefix(address, "天津") { - return "天津市" - } - if strings.HasPrefix(address, "重庆") { - return "重庆市" - } - - // 处理各种省份格式(按长度从长到短,避免误匹配) - patterns := []struct { - pattern string - extract func(string) string - }{ - // 处理"XX壮族自治区"格式(最长,优先匹配) - {"壮族自治区", func(addr string) string { - if idx := strings.Index(addr, "壮族自治区"); idx > 0 { - return addr[:idx+len("壮族自治区")] - } - return "" - }}, - // 处理"XX回族自治区"格式 - {"回族自治区", func(addr string) string { - if idx := strings.Index(addr, "回族自治区"); idx > 0 { - return addr[:idx+len("回族自治区")] - } - return "" - }}, - // 处理"XX维吾尔自治区"格式 - {"维吾尔自治区", func(addr string) string { - if idx := strings.Index(addr, "维吾尔自治区"); idx > 0 { - return addr[:idx+len("维吾尔自治区")] - } - return "" - }}, - // 处理"XX特别行政区"格式 - {"特别行政区", func(addr string) string { - if idx := strings.Index(addr, "特别行政区"); idx > 0 { - return addr[:idx+len("特别行政区")] - } - return "" - }}, - // 处理"XX自治区"格式(如西藏、宁夏,必须在其他自治区之后) - {"自治区", func(addr string) string { - if idx := strings.Index(addr, "自治区"); idx > 0 { - return addr[:idx+len("自治区")] - } - return "" - }}, - // 处理"XX省"格式(最后处理,因为可能与其他模式冲突) - {"省", func(addr string) string { - if idx := strings.Index(addr, "省"); idx > 0 { - return addr[:idx+len("省")] - } - return "" - }}, - } - - for _, p := range patterns { - if strings.Contains(address, p.pattern) { - if result := p.extract(address); result != "" { - return result - } - } - } - - return "" -} - -// extractCityFromAddress 从完整地址中提取城市名称 -func extractCityFromAddress(address string) string { - if address == "" { - return "" - } - - // 先提取省份,然后从剩余部分提取城市 - province := extractProvinceFromAddress(address) - if province == "" { - return "" - } - - // 去除省份部分 - cityPart := address[len(province):] - - // 处理各种城市格式 - patterns := []string{"地区", "市", "自治州", "盟"} - for _, pattern := range patterns { - if idx := strings.Index(cityPart, pattern); idx > 0 { - return cityPart[:idx+len(pattern)] - } - } - - return "" -} - -// compareLocation 比较两个地址是否一致(省份和城市) -// 使用号码归属地(格式:省份-城市)去匹配户籍所在地 -// 如果号码归属地中的省份和城市都出现在户籍所在地中,则认为一致 -// 返回true表示一致,false表示不一致 -func compareLocation(address1, province2, city2 string) bool { - if address1 == "" { - return false - } - - // 如果号码归属地只有省份,检查省份是否出现在户籍所在地中 - if province2 != "" && city2 == "" { - // 标准化省份名称,去除后缀 - province2Norm := normalizeProvinceName(province2) - // 检查标准化后的省份名称是否出现在户籍所在地中 - return strings.Contains(address1, province2Norm) - } - - // 如果号码归属地有省份和城市,检查两者是否都出现在户籍所在地中 - if province2 != "" && city2 != "" { - // 标准化省份和城市名称,去除后缀 - province2Norm := normalizeProvinceName(province2) - city2Norm := normalizeCityName(city2) - - // 检查省份和城市是否都出现在户籍所在地中 - provinceMatch := strings.Contains(address1, province2Norm) - cityMatch := strings.Contains(address1, city2Norm) - - return provinceMatch && cityMatch - } - - return false -} - -func convertChannel(channel string) string { - channelMap := map[string]string{ - "cmcc": "中国移动", - "cucc": "中国联通", - "ctcc": "中国电信", - "gdcc": "中国广电", - } - if converted, ok := channelMap[strings.ToLower(channel)]; ok { - return converted - } - return channel -} - -// convertChannelName 转换运营商名称(处理中文名称) -func convertChannelName(channel string) string { - // 如果已经是中文名称,直接返回 - if strings.Contains(channel, "移动") || strings.Contains(channel, "联通") || - strings.Contains(channel, "电信") || strings.Contains(channel, "广电") { - return channel - } - // 否则使用convertChannel转换 - return convertChannel(channel) -} - -// convertStatusFromOnlineStatus 根据手机在网状态V即时版的响应转换为status -// status: -1:未查得; 0:空号; 1:实号; 2:停机; 3:库无; 4:沉默号; 5:风险号 -func convertStatusFromOnlineStatus(data map[string]interface{}) int { - // 获取status字段(0-在网,1-不在网) - var statusVal interface{} - var ok bool - - // status可能是int或float64类型 - if statusVal, ok = data["status"]; !ok { - return -1 // 未查得 - } - - var statusInt int - switch v := statusVal.(type) { - case int: - statusInt = v - case float64: - statusInt = int(v) - case string: - if parsed, err := strconv.Atoi(v); err == nil { - statusInt = parsed - } else { - return -1 - } - default: - return -1 - } - - // status=0表示在网,直接返回实号 - if statusInt == 0 { - return 1 // 实号 - } - - // status=1表示不在网,需要根据desc字段判断具体原因 - if statusInt == 1 { - desc, ok := data["desc"].(string) - if !ok { - return 4 // 沉默号(默认) - } - - // 根据desc中的关键词判断状态 - if strings.Contains(desc, "停机") { - return 2 // 停机 - } else if strings.Contains(desc, "销号") || strings.Contains(desc, "空号") { - return 0 // 空号 - } else if strings.Contains(desc, "库无") { - return 3 // 库无 - } else if strings.Contains(desc, "风险") { - return 5 // 风险号 - } else { - return 4 // 沉默号(其他不在网情况) - } - } - - return -1 // 未查得 -} - -func convertStatus(result string) int { - // 根据运营商三要素的result字段转换为status(备用方法) - // result: "0" - 一致, "1" - 不一致, "2" - 无记录 - // status: -1:未查得; 0:空号; 1:实号; 2:停机; 3:库无; 4:沉默号; 5:风险号 - if result == "0" { - return 1 // 实号 - } else if result == "1" { - return 5 // 风险号 - } else if result == "2" { - return 3 // 库无 - } - return -1 // 未查得 -} - -func formatOnlineTime(inTime string) string { - // 格式化在网时长 - // 0: [0,3), 3: [3,6), 6: [6,12), 12: [12,24), 24: [24,+) - if inTime == "0" { - return "0,3(个月)" - } else if inTime == "3" { - return "3,6(个月)" - } else if inTime == "6" { - return "6,12(个月)" - } else if inTime == "12" { - return "12,24(个月)" - } else if inTime == "24" { - return "24,+(个月)" - } - return inTime + "(个月)" -} - -func getFraudScore(apiData map[string]interface{}) int { - // 从涉赌涉诈风险评估获取基础反欺诈评分 - flxgData := getMapValue(apiData, "FLXG8B4D") - baseScore := -1 - - if flxgData != nil { - flxgMap, ok := flxgData.(map[string]interface{}) - if ok { - // 风险等级到分数的映射 - riskLevelToScore := map[string]int{ - "0": 0, // 无风险 - "A": 35, // 较低风险(取区间中值) - "B": 60, // 低风险(取区间中值) - "C": 80, // 中风险(取区间中值) - "D": 95, // 高风险(取区间中值) - } - - // 尝试从data字段获取(兼容旧格式) - var data map[string]interface{} - if dataVal, ok := flxgMap["data"].(map[string]interface{}); ok { - data = dataVal - } else { - // 如果没有data字段,直接使用flxgMap(新格式) - data = flxgMap - } - - // 检查是否有riskScore字段且为0(表示无风险) - if riskScore, ok := data["riskScore"].(string); ok && riskScore == "0" { - // 检查所有风险字段是否都为0 - allZero := true - riskFields := []string{"moneyLaundering", "deceiver", "gamblerPlayer", "gamblerBanker"} - for _, field := range riskFields { - if val, ok := data[field].(string); ok && val != "" && val != "0" { - allZero = false - break - } - } - if allZero { - baseScore = 0 // 无风险 - } - } - - // 遍历所有风险字段,取最高风险等级对应的分数 - if baseScore == -1 { - maxScore := 0 - riskFields := []string{"moneyLaundering", "deceiver", "gamblerPlayer", "gamblerBanker"} - for _, field := range riskFields { - if val, ok := data[field].(string); ok && val != "" { - if score, exists := riskLevelToScore[val]; exists && score > maxScore { - maxScore = score - } - } - } - if maxScore > 0 { - baseScore = maxScore - } - } - } - } - - // 考虑特殊名单风险(JRZQ8A2D) - specialListScore := 0 - jrzq8a2dData := getMapValue(apiData, "JRZQ8A2D") - if jrzq8a2dData != nil { - if jrzq8a2dMap, ok := jrzq8a2dData.(map[string]interface{}); ok { - // 检查Rule_final_decision和Rule_final_weight - if decision, ok := jrzq8a2dMap["Rule_final_decision"].(string); ok && decision == "Reject" { - if weight, ok := jrzq8a2dMap["Rule_final_weight"].(string); ok && weight != "" { - if weightInt, err := strconv.Atoi(weight); err == nil { - // 权重越高,风险越大,转换为分数(权重0-100映射到分数0-100) - specialListScore = weightInt - } - } - } - } - } - - // 考虑借选指数风险(JRZQ5E9F) - creditRiskScore := 0 - jrzq5e9fData := getMapValue(apiData, "JRZQ5E9F") - if jrzq5e9fData != nil { - if jrzq5e9fMap, ok := jrzq5e9fData.(map[string]interface{}); ok { - // 从xyp_cpl0081获取信用评分,如果评分很低(<500),增加风险分数 - if xypCpl0081, ok := jrzq5e9fMap["xyp_cpl0081"].(string); ok && xypCpl0081 != "" { - if score, err := strconv.ParseFloat(xypCpl0081, 64); err == nil { - // 信用评分越低,风险越高 - // 如果信用评分<500,增加风险分数(500-900映射到0-40分) - if score < 500 { - creditRiskScore = int((500 - score) / 10) // 每10分信用评分差异对应1分风险分数 - if creditRiskScore > 40 { - creditRiskScore = 40 // 最高40分 - } - } - } - } - } - } - - // 综合评分:取baseScore、specialListScore、creditRiskScore的最大值 - finalScore := baseScore - if specialListScore > finalScore { - finalScore = specialListScore - } - if creditRiskScore > finalScore { - finalScore = creditRiskScore - } - - // 如果所有评分都是-1或0,返回-1 - if finalScore == -1 { - return -1 - } - - return finalScore -} - -func getCreditScore(apiData map[string]interface{}) int { - // 从借选指数评估获取信用评分 - jrzq5e9fData := getMapValue(apiData, "JRZQ5E9F") - if jrzq5e9fData == nil { - return -1 - } - - jrzq5e9fMap, ok := jrzq5e9fData.(map[string]interface{}) - if !ok { - return -1 - } - - // 获取xyp_cpl0081字段(信用风险评分,范围[0,1],分数越高信用越低) - xypCpl0081Val, ok := jrzq5e9fMap["xyp_cpl0081"] - if !ok { - // 如果字段不存在,返回900(默认信用较好) - return 900 - } - - // 转换为float64 - var xypCpl0081 float64 - var isValid bool - switch v := xypCpl0081Val.(type) { - case float64: - xypCpl0081 = v - isValid = true - case string: - if v == "" || v == "-1" { - // 如果为空或-1,返回900(默认信用较好) - return 900 - } - parsed, err := strconv.ParseFloat(v, 64) - if err != nil { - // 解析失败,返回900(默认信用较好) - return 900 - } - xypCpl0081 = parsed - isValid = true - case int: - xypCpl0081 = float64(v) - isValid = true - default: - // 类型不匹配,返回900(默认信用较好) - return 900 - } - - // 验证范围[0,1] - if !isValid || xypCpl0081 < 0 || xypCpl0081 > 1 { - // 如果不在有效范围内,返回900(默认信用较好) - return 900 - } - - // 映射公式:creditScore = 1000 - (xyp_cpl0081 * 700) - // 当xyp_cpl0081 = 0时,creditScore = 1000(信用最好) - // 当xyp_cpl0081 = 1时,creditScore = 300(信用最差) - creditScore := 1000 - (xypCpl0081 * 700) - - // 确保在[300,1000]范围内 - if creditScore < 300 { - creditScore = 300 - } else if creditScore > 1000 { - creditScore = 1000 - } - - return int(creditScore) -} - -// isDevelopmentMode 检查是否为开发模式 -func isDevelopmentMode() bool { - // 检查环境变量,优先级:DWBG_USE_MOCK_DATA > ENV > CONFIG_ENV > APP_ENV - if useMock := os.Getenv("DWBG_USE_MOCK_DATA"); useMock != "" { - return useMock == "1" || useMock == "true" || useMock == "yes" - } - - env := os.Getenv("ENV") - if env == "" { - env = os.Getenv("CONFIG_ENV") - } - if env == "" { - env = os.Getenv("APP_ENV") - } - - // 默认开发环境 - if env == "" { - return true - } - - return env == "development" -} - -// loadMockAPIDataFromFile 从本地JSON文件加载模拟API数据 -func loadMockAPIDataFromFile(log *zap.Logger) map[string]interface{} { - // 优先使用指定的文件路径 - mockDataPath := os.Getenv("DWBG_MOCK_DATA_PATH") - if mockDataPath == "" { - // 默认使用最新的导出文件 - mockDataPath = "api_data_export/api_data_4522_20260214_152339.json" - } - - // 检查文件是否存在 - if _, err := os.Stat(mockDataPath); os.IsNotExist(err) { - log.Warn("开发模式:模拟数据文件不存在", zap.String("path", mockDataPath)) - return nil - } - - // 读取文件内容 - fileData, err := os.ReadFile(mockDataPath) - if err != nil { - log.Warn("开发模式:读取模拟数据文件失败", zap.String("path", mockDataPath), zap.Error(err)) - return nil - } - - // 解析JSON - var apiData map[string]interface{} - if err := json.Unmarshal(fileData, &apiData); err != nil { - log.Warn("开发模式:解析模拟数据JSON失败", zap.String("path", mockDataPath), zap.Error(err)) - return nil - } - - log.Info("开发模式:成功加载模拟数据", - zap.String("path", mockDataPath), - zap.Int("api_count", len(apiData)), - ) - - return apiData -} - -func getTotalRiskCounts(apiData map[string]interface{}) int { - // 计算总风险点数量 - // 通过构建riskWarning来获取totalRiskCounts - riskWarning := buildRiskWarning(apiData, zap.NewNop()) - if totalRiskCounts, ok := riskWarning["totalRiskCounts"].(int); ok { - return totalRiskCounts - } - return 0 -} - -func getRiskLevel(apiData map[string]interface{}) string { - // 从公安不良人员名单获取风险等级 - flxgdea9Data := getMapValue(apiData, "FLXGDEA9") - if flxgdea9Data != nil { - // 根据实际API响应结构提取风险等级 - } - return "" -} diff --git a/internal/domains/api/services/processors/dwbg/dwbg8b4d_processor_test.go b/internal/domains/api/services/processors/dwbg/dwbg8b4d_processor_test.go deleted file mode 100644 index 6cb57b3..0000000 --- a/internal/domains/api/services/processors/dwbg/dwbg8b4d_processor_test.go +++ /dev/null @@ -1,1327 +0,0 @@ -package dwbg - -import ( - "encoding/json" - "strings" - "testing" - - "hyapi-server/internal/domains/api/dto" - - "go.uber.org/zap" -) - -// TestTransformToDitingReport 测试数据转换逻辑 -func TestTransformToDitingReport(t *testing.T) { - // 准备测试参数 - params := dto.DWBG8B4DReq{ - Name: "封伟", - IDCard: "320321199102011152", - MobileNo: "15812342970", - } - - // 准备模拟的API响应数据 - apiData := prepareMockAPIData() - - // 创建logger - log := zap.NewNop() - - // 执行转换 - report := transformToDitingReport(apiData, params, log) - - // 验证报告结构 - validateReportStructure(t, report) - - // 验证baseInfo - validateBaseInfo(t, report, params) - - // 验证riskWarning - validateRiskWarning(t, report) - - // 验证overdueRiskProduct - validateOverdueRiskProduct(t, report) - - // 输出完整的报告JSON用于调试 - reportJSON, _ := json.MarshalIndent(report, "", " ") - t.Logf("转换后的报告:\n%s", string(reportJSON)) -} - -// prepareMockAPIData 准备模拟的API响应数据 -func prepareMockAPIData() map[string]interface{} { - apiData := make(map[string]interface{}) - - // 1. 运营商三要素简版V政务版 (YYSYH6D2) - apiData["YYSYH6D2"] = map[string]interface{}{ - "result": "0", // 一致 - "channel": "cmcc", - "address": "江苏省徐州市沛县", - } - - // 2. 手机在网时长B (YYSY8B1C) - apiData["YYSY8B1C"] = map[string]interface{}{ - "inTime": "6", // 6-12个月 - "operators": "移动", - } - - // 3. 公安二要素认证即时版 (IVYZ9K7F) - apiData["IVYZ9K7F"] = map[string]interface{}{ - "data": map[string]interface{}{ - "status": "一致", - }, - } - - // 4. 手机号归属地核验 (YYSY9E4A) - apiData["YYSY9E4A"] = map[string]interface{}{ - "provinceName": "江苏", - "cityName": "徐州", - "channel": "cmcc", - } - - // 5. 手机在网状态V即时版 (YYSYE7V5) - apiData["YYSYE7V5"] = map[string]interface{}{ - "status": 0, // 在网 - "desc": "在网", - "channel": "cmcc", - } - - // 6. 涉赌涉诈风险评估 (FLXG8B4D) - apiData["FLXG8B4D"] = map[string]interface{}{ - "data": map[string]interface{}{ - "moneyLaundering": "0", - "deceiver": "0", - "gamblerPlayer": "0", - "gamblerBanker": "0", - "riskScore": "0", - }, - } - - // 7. 公安不良人员名单(加强版) (FLXGDEA9) - apiData["FLXGDEA9"] = map[string]interface{}{ - "level": "C2,C5", // 妨害社会管理秩序 - } - - // 8. 特殊名单验证B (JRZQ8A2D) - apiData["JRZQ8A2D"] = map[string]interface{}{ - "id": map[string]interface{}{ - "id_bank_lost": "1", - "id_nbank_lost": "1", - "id_bank_overdue": "1", - "id_nbank_overdue": "1", - }, - "cell": map[string]interface{}{ - "cell_bank_lost": "1", - "cell_nbank_lost": "1", - "cell_bank_overdue": "1", - "cell_nbank_overdue": "1", - }, - } - - // 9. 借选指数评估 (JRZQ5E9F) - apiData["JRZQ5E9F"] = map[string]interface{}{ - "xyp_cpl0001": "14", // 贷款总机构数 - "xyp_cpl0002": "17", // 已结清机构数 - "xyp_cpl0044": "1", // 当前是否存在逾期未结清 - "xyp_cpl0071": "1", // 当前逾期机构数 - "xyp_cpl0072": "1", // 当前逾期金额 - "xyp_cpl0028": "0", // 最近1天是否发生过逾期 - "xyp_cpl0029": "0", // 最近7天是否发生过逾期 - "xyp_cpl0030": "1", // 最近14天是否发生过逾期 - "xyp_cpl0031": "1", // 最近30天是否发生过逾期 - "xyp_cpl0068": "4", // 最近一次还款成功距离当前天数 (160+) - "xyp_cpl0018": "0", // 最近7天交易失败笔数 - "xyp_cpl0034": "0", // 最近7天还款失败金额 - "xyp_cpl0019": "0", // 最近7天还款成功次数 - "xyp_cpl0035": "0", // 最近7天还款成功金额 - "xyp_cpl0020": "2", // 最近14天交易失败笔数 - "xyp_cpl0036": "1", // 最近14天还款失败金额 - "xyp_cpl0021": "0", // 最近14天还款成功次数 - "xyp_cpl0037": "0", // 最近14天还款成功金额 - "xyp_cpl0022": "3", // 最近1个月交易失败笔数 - "xyp_cpl0038": "2", // 最近1个月还款失败金额 - "xyp_cpl0023": "0", // 最近1个月还款成功次数 - "xyp_cpl0039": "0", // 最近1个月还款成功金额 - "xyp_cpl0024": "4", // 最近3个月交易失败笔数 - "xyp_cpl0040": "3", // 最近3个月还款失败金额 - "xyp_cpl0025": "0", // 最近3个月还款成功次数 - "xyp_cpl0041": "0", // 最近3个月还款成功金额 - "xyp_cpl0026": "5", // 最近6个月交易失败笔数 - "xyp_cpl0042": "4", // 最近6个月还款失败金额 - "xyp_cpl0027": "0", // 最近6个月还款成功次数 - "xyp_cpl0043": "0", // 最近6个月还款成功金额 - "xyp_t01aazzzc": "3", // 还款成功_还款金额_最大值 (区间化: [4800,Inf)) - "xyp_cpl0081": "0.5", // 信用风险评分 (0-1之间,分数越高信用越低) -> 应该映射到650分 - } - - // 10. 个人司法涉诉查询 (FLXG7E8F) - apiData["FLXG7E8F"] = map[string]interface{}{ - "judicial_data": map[string]interface{}{ - "lawsuitStat": map[string]interface{}{ - "civil": map[string]interface{}{ - "cases": []interface{}{}, - }, - "criminal": map[string]interface{}{ - "cases": []interface{}{}, - }, - "implement": map[string]interface{}{ - "cases": []interface{}{ - map[string]interface{}{ - "c_ah": "(2023)赣1102执保608号", - "n_ajlx": "财产保全执行", - "n_jbfy": "上饶市信州区人民法院", - "n_ssdw": "被申请人", - "d_larq": "2023-05-12", - "d_jarq": "2023-05-17", - "n_ajjzjd": "已结案", - "n_sqzxbdje": 0.0, - "n_jabdje": 0.0, - "n_laay": "未知", - "n_jafs": "部分保全", - }, - }, - }, - }, - "breachCaseList": []interface{}{}, - "consumptionRestrictionList": []interface{}{}, - }, - } - - // 11. 借贷意向验证A (JRZQ6F2A) - apiData["JRZQ6F2A"] = map[string]interface{}{ - "risk_screen_v2": map[string]interface{}{ - "variables": []interface{}{ - map[string]interface{}{ - "variableValue": map[string]interface{}{ - // 银行数据 - "als_d7_id_bank_allnum": "0", - "als_d7_id_bank_orgnum": "0", - "als_d7_cell_bank_allnum": "0", - "als_d15_id_bank_allnum": "0", - "als_d15_id_bank_orgnum": "0", - "als_d15_cell_bank_allnum": "0", - "als_m1_id_bank_allnum": "0", - "als_m1_id_bank_orgnum": "0", - "als_m1_cell_bank_allnum": "0", - "als_m3_id_bank_allnum": "0", - "als_m3_id_bank_orgnum": "0", - "als_m3_cell_bank_allnum": "0", - "als_m6_id_bank_allnum": "2", - "als_m6_id_bank_orgnum": "2", - "als_m6_cell_bank_allnum": "0", - "als_m12_id_bank_allnum": "2", - "als_m12_id_bank_orgnum": "2", - "als_m12_cell_bank_allnum": "0", - // 非银数据 - "als_d7_id_nbank_allnum": "0", - "als_d7_id_nbank_orgnum": "0", - "als_d7_cell_nbank_allnum": "0", - "als_d15_id_nbank_allnum": "0", - "als_d15_id_nbank_orgnum": "0", - "als_d15_cell_nbank_allnum": "0", - "als_m1_id_nbank_allnum": "0", - "als_m1_id_nbank_orgnum": "0", - "als_m1_cell_nbank_allnum": "0", - "als_m3_id_nbank_allnum": "0", - "als_m3_id_nbank_orgnum": "0", - "als_m3_cell_nbank_allnum": "0", - "als_m6_id_nbank_allnum": "2", - "als_m6_id_nbank_orgnum": "2", - "als_m6_cell_nbank_allnum": "2", - "als_m12_id_nbank_allnum": "2", - "als_m12_id_nbank_orgnum": "2", - "als_m12_cell_nbank_allnum": "2", - // 网络零售银行 - "als_m6_id_bank_ret_allnum": "2", - "als_m6_id_bank_ret_orgnum": "2", - "als_m6_cell_bank_ret_allnum": "0", - "als_m12_id_bank_ret_allnum": "2", - "als_m12_id_bank_ret_orgnum": "2", - "als_m12_cell_bank_ret_allnum": "0", - // 持牌消费金融 - "als_m6_id_nbank_cons_allnum": "2", - "als_m6_id_nbank_cons_orgnum": "2", - "als_m6_cell_nbank_cons_allnum": "2", - "als_m12_id_nbank_cons_allnum": "2", - "als_m12_id_nbank_cons_orgnum": "2", - "als_m12_cell_nbank_cons_allnum": "2", - // 夜间-非银 - "als_m6_id_nbank_night_allnum": "1", - "als_m6_id_nbank_night_orgnum": "1", - "als_m6_cell_nbank_night_allnum": "1", - "als_m12_id_nbank_night_allnum": "1", - "als_m12_id_nbank_night_orgnum": "1", - "als_m12_cell_nbank_night_allnum": "1", - }, - }, - }, - }, - } - - // 12. 3C租赁申请意向 (JRZQ1D09) - apiData["JRZQ1D09"] = map[string]interface{}{ - "phone_relation_idard": "0", // 同一身份证关联手机号数 - "idcard_relation_phone": "0", // 同一手机号关联身份证数 - "least_application_time": "2025-06-02", - // 3个月数据 - "alc_m3_id_allnum": "2", - "alc_m3_cell_allnum": "1", - "alc_m3_id_weekend_allnum": "0", - "alc_m3_cell_weekend_allnum": "0", - "alc_m3_id_night_allnum": "0", - "alc_m3_cell_night_allnum": "0", - // 6个月数据 - "alc_m6_id_allnum": "2", - "alc_m6_cell_allnum": "1", - "alc_m6_id_weekend_allnum": "0", - "alc_m6_cell_weekend_allnum": "0", - "alc_m6_id_night_allnum": "0", - "alc_m6_cell_night_allnum": "0", - // 12个月数据 - "alc_m12_id_allnum": "3", - "alc_m12_cell_allnum": "2", - "alc_m12_id_weekend_allnum": "0", - "alc_m12_cell_weekend_allnum": "0", - "alc_m12_id_night_allnum": "0", - "alc_m12_cell_night_allnum": "0", - } - - return apiData -} - -// validateReportStructure 验证报告的基本结构 -func validateReportStructure(t *testing.T, report map[string]interface{}) { - requiredFields := []string{ - "baseInfo", - "standLiveInfo", - "checkSuggest", - "fraudScore", - "creditScore", - "verifyRule", - "fraudRule", - "riskWarning", - "elementVerificationDetail", - "riskSupervision", - "overdueRiskProduct", - "multCourtInfo", - "loanEvaluationVerificationDetail", - "leasingRiskAssessment", - } - - for _, field := range requiredFields { - if _, exists := report[field]; !exists { - t.Errorf("报告缺少必需字段: %s", field) - } - } -} - -// validateBaseInfo 验证基本信息 -func validateBaseInfo(t *testing.T, report map[string]interface{}, params dto.DWBG8B4DReq) { - baseInfo, ok := report["baseInfo"].(map[string]interface{}) - if !ok { - t.Fatal("baseInfo不是map类型") - } - - // 验证姓名脱敏 - if name, ok := baseInfo["name"].(string); ok { - if name == "" { - t.Error("name字段为空") - } - // 验证脱敏格式(应该包含*) - if !strings.Contains(name, "*") { - t.Errorf("name字段未脱敏: %s", name) - } - } else { - t.Error("name字段不存在或类型错误") - } - - // 验证身份证脱敏 - if idCard, ok := baseInfo["idCard"].(string); ok { - if idCard == "" { - t.Error("idCard字段为空") - } - // 验证脱敏格式(应该包含*) - if !strings.Contains(idCard, "*") { - t.Errorf("idCard字段未脱敏: %s", idCard) - } - } else { - t.Error("idCard字段不存在或类型错误") - } - - // 验证手机号脱敏 - if phone, ok := baseInfo["phone"].(string); ok { - if phone == "" { - t.Error("phone字段为空") - } - // 验证脱敏格式(应该包含*) - if !strings.Contains(phone, "*") { - t.Errorf("phone字段未脱敏: %s", phone) - } - } else { - t.Error("phone字段不存在或类型错误") - } - - // 验证年龄 - if age, ok := baseInfo["age"].(int); ok { - if age <= 0 || age > 150 { - t.Errorf("age字段值异常: %d", age) - } - } else { - t.Error("age字段不存在或类型错误") - } - - // 验证性别 - if sex, ok := baseInfo["sex"].(string); ok { - if sex != "男" && sex != "女" { - t.Errorf("sex字段值异常: %s", sex) - } - } else { - t.Error("sex字段不存在或类型错误") - } - - // 验证location - if location, ok := baseInfo["location"].(string); ok { - if location == "" { - t.Error("location字段为空") - } - } else { - t.Error("location字段不存在或类型错误") - } - - // 验证phoneArea - if phoneArea, ok := baseInfo["phoneArea"].(string); ok { - if phoneArea == "" { - t.Error("phoneArea字段为空") - } - // 验证格式(应该包含"-") - if !strings.Contains(phoneArea, "-") { - t.Errorf("phoneArea格式异常: %s", phoneArea) - } - } else { - t.Error("phoneArea字段不存在或类型错误") - } - - // 验证channel - if channel, ok := baseInfo["channel"].(string); ok { - if channel == "" { - t.Error("channel字段为空") - } - } else { - t.Error("channel字段不存在或类型错误") - } - - // 验证status - if status, ok := baseInfo["status"].(int); ok { - if status < -1 || status > 5 { - t.Errorf("status字段值异常: %d", status) - } - } else { - t.Error("status字段不存在或类型错误") - } -} - -// validateRiskWarning 验证风险警告 -func validateRiskWarning(t *testing.T, report map[string]interface{}) { - riskWarning, ok := report["riskWarning"].(map[string]interface{}) - if !ok { - t.Fatal("riskWarning不是map类型") - } - - // 验证totalRiskCounts - if totalRiskCounts, ok := riskWarning["totalRiskCounts"].(int); ok { - if totalRiskCounts < 0 { - t.Errorf("totalRiskCounts值异常: %d", totalRiskCounts) - } - } else { - t.Error("totalRiskCounts字段不存在或类型错误") - } - - // 验证level字段(应该是string类型) - if level, ok := riskWarning["level"].(string); ok { - // level可以是空字符串或包含风险等级代码 - _ = level - } else { - // level字段可能不存在,这是允许的 - } - - // 验证一些关键风险字段 - riskFields := []string{ - "idCardTwoElementMismatch", - "phoneThreeElementMismatch", - "shortPhoneDuration", - "noPhoneDuration", - "hasCriminalRecord", - "isDisrupSocial", - "hitExecutionCase", - } - - for _, field := range riskFields { - if val, ok := riskWarning[field].(int); ok { - if val != 0 && val != 1 { - t.Errorf("风险字段%s值异常: %d", field, val) - } - } - } -} - -// validateOverdueRiskProduct 验证逾期风险产品 -func validateOverdueRiskProduct(t *testing.T, report map[string]interface{}) { - overdueRiskProduct, ok := report["overdueRiskProduct"].(map[string]interface{}) - if !ok { - t.Fatal("overdueRiskProduct不是map类型") - } - - // 验证风险标识 - flags := []string{"lyjlhyFlag", "dkzhktjFlag", "tsmdyzFlag"} - for _, flag := range flags { - if val, ok := overdueRiskProduct[flag].(int); ok { - if val < 0 || val > 2 { - t.Errorf("风险标识%s值异常: %d", flag, val) - } - } - } - - // 验证hasUnsettledOverdue - if hasOverdue, ok := overdueRiskProduct["hasUnsettledOverdue"].(string); ok { - if hasOverdue != "逾期" && hasOverdue != "未逾期" { - t.Errorf("hasUnsettledOverdue值异常: %s", hasOverdue) - } - } - - // 验证totalLoanRepaymentAmount(应该是区间化格式) - if amount, ok := overdueRiskProduct["totalLoanRepaymentAmount"].(string); ok { - // 验证区间化格式(应该包含括号或方括号) - if amount != "0" && !strings.ContainsAny(amount, "()[]+") { - t.Errorf("totalLoanRepaymentAmount格式异常: %s", amount) - } - } - - // 验证daysSinceLastSuccessfulRepayment(应该是区间化格式) - if days, ok := overdueRiskProduct["daysSinceLastSuccessfulRepayment"].(string); ok { - // 验证区间化格式 - if days != "0" && !strings.ContainsAny(days, "()[]+") { - t.Errorf("daysSinceLastSuccessfulRepayment格式异常: %s", days) - } - } - - // 验证repaymentSuccessCount和repaymentSuccessAmount应该是"-"或数字 - successFields := []string{ - "repaymentSuccessCountLast7Days", - "repaymentSuccessAmountLast7Days", - "repaymentSuccessCountLast14Days", - "repaymentSuccessAmountLast14Days", - "repaymentSuccessCountLastMonth", - "repaymentSuccessAmountLastMonth", - "repaymentSuccessCountLast3Months", - "repaymentSuccessAmountLast3Months", - "repaymentSuccessCountLast6Months", - "repaymentSuccessAmountLast6Months", - } - - for _, field := range successFields { - if val, ok := overdueRiskProduct[field].(string); ok { - if val != "-" && val != "0" { - // 如果不是"-"或"0",应该是有效的数字或区间 - _ = val - } - } - } -} - -// TestBuildBaseInfo 测试基本信息构建 -func TestBuildBaseInfo(t *testing.T) { - params := dto.DWBG8B4DReq{ - Name: "张三", - IDCard: "110101199001011234", - MobileNo: "13800138000", - } - - apiData := map[string]interface{}{ - "YYSYH6D2": map[string]interface{}{ - "result": "0", - "channel": "cmcc", - "address": "北京市东城区", - }, - "YYSY9E4A": map[string]interface{}{ - "provinceName": "北京", - "cityName": "北京", - }, - "YYSYE7V5": map[string]interface{}{ - "status": 0, - "desc": "在网", - }, - } - - log := zap.NewNop() - baseInfo := buildBaseInfo(apiData, params, log) - - // 验证脱敏 - if name, ok := baseInfo["name"].(string); ok { - if !strings.Contains(name, "*") { - t.Errorf("姓名未脱敏: %s", name) - } - } - - if idCard, ok := baseInfo["idCard"].(string); ok { - if !strings.Contains(idCard, "*") { - t.Errorf("身份证未脱敏: %s", idCard) - } - } - - if phone, ok := baseInfo["phone"].(string); ok { - if !strings.Contains(phone, "*") { - t.Errorf("手机号未脱敏: %s", phone) - } - } - - // 验证年龄和性别 - if age, ok := baseInfo["age"].(int); ok { - // 根据身份证号110101199001011234,应该是1990年出生,2024年应该是34岁 - if age < 20 || age > 100 { - t.Errorf("年龄计算异常: %d", age) - } - } - - if sex, ok := baseInfo["sex"].(string); ok { - if sex != "男" && sex != "女" { - t.Errorf("性别计算异常: %s", sex) - } - } -} - -// TestBuildRiskWarning 测试风险警告构建 -func TestBuildRiskWarning(t *testing.T) { - apiData := map[string]interface{}{ - "IVYZ9K7F": map[string]interface{}{ - "data": map[string]interface{}{ - "status": "不一致", // 应该触发idCardTwoElementMismatch - }, - }, - "YYSYH6D2": map[string]interface{}{ - "result": "1", // 应该触发phoneThreeElementMismatch - }, - "YYSY8B1C": map[string]interface{}{ - "inTime": "0", // 应该触发shortPhoneDuration - }, - "FLXGDEA9": map[string]interface{}{ - "level": "C2,C5", // 应该触发isDisrupSocial - }, - } - - log := zap.NewNop() - riskWarning := buildRiskWarning(apiData, log) - - // 验证风险字段 - if idCardMismatch, ok := riskWarning["idCardTwoElementMismatch"].(int); ok { - if idCardMismatch != 1 { - t.Errorf("idCardTwoElementMismatch应该为1,实际为%d", idCardMismatch) - } - } - - if phoneMismatch, ok := riskWarning["phoneThreeElementMismatch"].(int); ok { - if phoneMismatch != 1 { - t.Errorf("phoneThreeElementMismatch应该为1,实际为%d", phoneMismatch) - } - } - - if shortDuration, ok := riskWarning["shortPhoneDuration"].(int); ok { - if shortDuration != 1 { - t.Errorf("shortPhoneDuration应该为1,实际为%d", shortDuration) - } - } - - if isDisrupSocial, ok := riskWarning["isDisrupSocial"].(int); ok { - if isDisrupSocial != 1 { - t.Errorf("isDisrupSocial应该为1,实际为%d", isDisrupSocial) - } - } - - // 验证totalRiskCounts - if totalRiskCounts, ok := riskWarning["totalRiskCounts"].(int); ok { - if totalRiskCounts <= 0 { - t.Errorf("totalRiskCounts应该大于0,实际为%d", totalRiskCounts) - } - } -} - -// TestBuildOverdueRiskProduct 测试逾期风险产品构建 -func TestBuildOverdueRiskProduct(t *testing.T) { - apiData := map[string]interface{}{ - "JRZQ5E9F": map[string]interface{}{ - "xyp_cpl0044": "1", // 有逾期 - "xyp_cpl0071": "1", // 当前逾期机构数 - "xyp_cpl0072": "1", // 当前逾期金额 - "xyp_cpl0029": "1", // 最近7天逾期 - "xyp_cpl0068": "4", // 最近一次还款成功距离当前天数 (160+) - "xyp_t01aazzzc": "3", // 还款成功_还款金额_最大值 ([4800,Inf)) - }, - "JRZQ8A2D": map[string]interface{}{ - "id": map[string]interface{}{ - "id_bank_overdue": "0", // 命中当前逾期 - }, - }, - } - - log := zap.NewNop() - overdueRiskProduct := buildOverdueRiskProduct(apiData, log) - - // 验证hasUnsettledOverdue - if hasOverdue, ok := overdueRiskProduct["hasUnsettledOverdue"].(string); ok { - if hasOverdue != "逾期" { - t.Errorf("hasUnsettledOverdue应该为'逾期',实际为%s", hasOverdue) - } - } - - // 验证overdueLast7Days - if overdue7Days, ok := overdueRiskProduct["overdueLast7Days"].(string); ok { - if overdue7Days != "逾期" { - t.Errorf("overdueLast7Days应该为'逾期',实际为%s", overdue7Days) - } - } - - // 验证daysSinceLastSuccessfulRepayment - if days, ok := overdueRiskProduct["daysSinceLastSuccessfulRepayment"].(string); ok { - if days != "160+" { - t.Errorf("daysSinceLastSuccessfulRepayment应该为'160+',实际为%s", days) - } - } - - // 验证totalLoanRepaymentAmount - if amount, ok := overdueRiskProduct["totalLoanRepaymentAmount"].(string); ok { - if amount != "[4800,Inf)" { - t.Errorf("totalLoanRepaymentAmount应该为'[4800,Inf)',实际为%s", amount) - } - } -} - -// TestBuildLeasingRiskAssessment 测试租赁风险评估构建 -func TestBuildLeasingRiskAssessment(t *testing.T) { - apiData := map[string]interface{}{ - "JRZQ1D09": map[string]interface{}{ - "alc_m3_id_allnum": "2", - "alc_m3_cell_allnum": "1", - "alc_m6_id_allnum": "2", - "alc_m6_cell_allnum": "1", - "alc_m12_id_allnum": "3", - "alc_m12_cell_allnum": "2", - }, - } - - log := zap.NewNop() - assessment := buildLeasingRiskAssessment(apiData, log) - - // 验证格式为"身份证/手机号" - if platform3Months, ok := assessment["threeCPlatformApplicationCountLast3Months"].(string); ok { - if !strings.Contains(platform3Months, "/") { - t.Errorf("threeCPlatformApplicationCountLast3Months格式异常: %s", platform3Months) - } - // 应该是"2/1" - if platform3Months != "2/1" { - t.Errorf("threeCPlatformApplicationCountLast3Months应该为'2/1',实际为%s", platform3Months) - } - } - - if institution12Months, ok := assessment["threeCInstitutionApplicationCountLast12Months"].(string); ok { - if !strings.Contains(institution12Months, "/") { - t.Errorf("threeCInstitutionApplicationCountLast12Months格式异常: %s", institution12Months) - } - // 应该是"3/2" - if institution12Months != "3/2" { - t.Errorf("threeCInstitutionApplicationCountLast12Months应该为'3/2',实际为%s", institution12Months) - } - } -} - -// TestBuildLoanEvaluationVerificationDetail 测试借贷评估产品构建 -func TestBuildLoanEvaluationVerificationDetail(t *testing.T) { - apiData := map[string]interface{}{ - "JRZQ6F2A": map[string]interface{}{ - "risk_screen_v2": map[string]interface{}{ - "variables": []interface{}{ - map[string]interface{}{ - "variableValue": map[string]interface{}{ - "als_m6_id_bank_allnum": "2", - "als_m6_cell_bank_allnum": "0", - "als_m6_id_nbank_allnum": "2", - "als_m6_cell_nbank_allnum": "2", - }, - }, - }, - }, - }, - } - - log := zap.NewNop() - detail := buildLoanEvaluationVerificationDetail(apiData, log) - - // 验证organLoanPerformances - if organLoanPerformances, ok := detail["organLoanPerformances"].([]interface{}); ok { - if len(organLoanPerformances) == 0 { - t.Error("organLoanPerformances为空") - } - - // 验证银行数据格式 - if bankPerf, ok := organLoanPerformances[0].(map[string]interface{}); ok { - if last6Month, ok := bankPerf["last6Month"].(string); ok { - if !strings.Contains(last6Month, "/") { - t.Errorf("last6Month格式异常: %s", last6Month) - } - // 应该是"2/0" - if last6Month != "2/0" { - t.Errorf("last6Month应该为'2/0',实际为%s", last6Month) - } - } - } - } -} - -// TestConvertXypT01aazzzcToInterval 测试区间化转换 -func TestConvertXypT01aazzzcToInterval(t *testing.T) { - testCases := []struct { - input string - expected string - }{ - {"1", "(0,1000)"}, - {"2", "[1000,4800)"}, - {"3", "[4800,Inf)"}, - {"0", "0"}, - {"", "0"}, - } - - for _, tc := range testCases { - result := convertXypT01aazzzcToInterval(tc.input) - if result != tc.expected { - t.Errorf("convertXypT01aazzzcToInterval(%s) = %s, 期望 %s", tc.input, result, tc.expected) - } - } -} - -// TestConvertXypCpl0068ToInterval 测试daysSinceLastSuccessfulRepayment区间化转换 -func TestConvertXypCpl0068ToInterval(t *testing.T) { - testCases := []struct { - input string - expected string - }{ - {"1", "(0,5)"}, - {"2", "[5,50)"}, - {"3", "[50,160)"}, - {"4", "160+"}, - {"0", "0"}, - {"", "0"}, - } - - for _, tc := range testCases { - result := convertXypCpl0068ToInterval(tc.input) - if result != tc.expected { - t.Errorf("convertXypCpl0068ToInterval(%s) = %s, 期望 %s", tc.input, result, tc.expected) - } - } -} - -// TestGetCreditScore 测试信用评分计算 -func TestGetCreditScore(t *testing.T) { - testCases := []struct { - name string - xypCpl0081 interface{} - expected int - }{ - {"有效值0", "0", 1000}, - {"有效值0.5", "0.5", 650}, - {"有效值1", "1", 300}, - {"有效值0.2", "0.2", 860}, - {"有效值0.8", "0.8", 440}, - {"字段不存在", nil, 900}, - {"字段为空字符串", "", 900}, - {"字段为-1", "-1", 900}, - {"float64类型", 0.5, 650}, - {"int类型", 0, 1000}, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - apiData := map[string]interface{}{} - if tc.xypCpl0081 != nil { - apiData["JRZQ5E9F"] = map[string]interface{}{ - "xyp_cpl0081": tc.xypCpl0081, - } - } else { - apiData["JRZQ5E9F"] = map[string]interface{}{} - } - - result := getCreditScore(apiData) - if result != tc.expected { - t.Errorf("getCreditScore(%v) = %d, 期望 %d", tc.xypCpl0081, result, tc.expected) - } - }) - } -} - -// TestGetFraudScore 测试反欺诈评分计算 -func TestGetFraudScore(t *testing.T) { - testCases := []struct { - name string - data map[string]interface{} - expected int - }{ - {"无风险", map[string]interface{}{ - "moneyLaundering": "0", - "deceiver": "0", - "gamblerPlayer": "0", - "gamblerBanker": "0", - "riskScore": "0", - }, 0}, - {"较低风险A", map[string]interface{}{ - "moneyLaundering": "A", - "deceiver": "0", - "gamblerPlayer": "0", - "gamblerBanker": "0", - }, 35}, - {"低风险B", map[string]interface{}{ - "moneyLaundering": "B", - "deceiver": "0", - "gamblerPlayer": "0", - "gamblerBanker": "0", - }, 60}, - {"中风险C", map[string]interface{}{ - "moneyLaundering": "C", - "deceiver": "0", - "gamblerPlayer": "0", - "gamblerBanker": "0", - }, 80}, - {"高风险D", map[string]interface{}{ - "moneyLaundering": "D", - "deceiver": "0", - "gamblerPlayer": "0", - "gamblerBanker": "0", - }, 95}, - {"多个风险取最高", map[string]interface{}{ - "moneyLaundering": "A", - "deceiver": "C", - "gamblerPlayer": "B", - "gamblerBanker": "0", - }, 80}, - {"数据不存在", nil, -1}, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - apiData := map[string]interface{}{} - if tc.data != nil { - apiData["FLXG8B4D"] = map[string]interface{}{ - "data": tc.data, - } - } - - result := getFraudScore(apiData) - if result != tc.expected { - t.Errorf("getFraudScore() = %d, 期望 %d", result, tc.expected) - } - }) - } -} - -// TestBuildMultCourtInfo 测试司法风险核验产品构建 -func TestBuildMultCourtInfo(t *testing.T) { - apiData := map[string]interface{}{ - "FLXG7E8F": map[string]interface{}{ - "judicial_data": map[string]interface{}{ - "lawsuitStat": map[string]interface{}{ - "civil": map[string]interface{}{ - "cases": []interface{}{}, - }, - "criminal": map[string]interface{}{ - "cases": []interface{}{}, - }, - "implement": map[string]interface{}{ - "cases": []interface{}{ - map[string]interface{}{ - "c_ah": "(2023)赣1102执保608号", - "n_ajlx": "财产保全执行", - "n_jbfy": "上饶市信州区人民法院", - "n_ssdw": "被申请人", - "d_larq": "2023-05-12", - "d_jarq": "2023-05-17", - "n_ajjzjd": "已结案", - "n_sqzxbdje": 0.0, - "n_jabdje": 0.0, - "n_laay": "未知", - "n_jafs": "部分保全", - }, - }, - }, - }, - "breachCaseList": []interface{}{}, - "consumptionRestrictionList": []interface{}{}, - }, - }, - } - - log := zap.NewNop() - multCourtInfo := buildMultCourtInfo(apiData, log) - - // 验证执行案件 - if executionCases, ok := multCourtInfo["executionCases"].([]interface{}); ok { - if len(executionCases) == 0 { - t.Error("executionCases应该包含案件") - } else { - if case1, ok := executionCases[0].(map[string]interface{}); ok { - if caseNumber, ok := case1["caseNumber"].(string); ok { - if caseNumber != "(2023)赣1102执保608号" { - t.Errorf("caseNumber应该为'(2023)赣1102执保608号',实际为%s", caseNumber) - } - } - } - } - } - - // 验证风险标识 - if executionCasesFlag, ok := multCourtInfo["executionCasesFlag"].(int); ok { - if executionCasesFlag != 1 { - t.Errorf("executionCasesFlag应该为1,实际为%d", executionCasesFlag) - } - } -} - -// TestBuildElementVerificationDetail 测试要素核查详情构建 -func TestBuildElementVerificationDetail(t *testing.T) { - apiData := map[string]interface{}{ - "YYSYH6D2": map[string]interface{}{ - "result": "1", // 不一致 - "channel": "cmcc", - "address": "江苏省徐州市", - }, - "IVYZ9K7F": map[string]interface{}{ - "data": map[string]interface{}{ - "status": "一致", - }, - }, - "YYSY8B1C": map[string]interface{}{ - "inTime": "3", // 3-6个月 - "operators": "移动", - }, - "YYSYE7V5": map[string]interface{}{ - "status": 1, // 不在网 - "desc": "风险号", - "channel": "cmcc", - }, - "YYSY9E4A": map[string]interface{}{ - "provinceName": "江苏", - "cityName": "徐州", - "channel": "cmcc", - }, - "FLXGDEA9": map[string]interface{}{ - "level": "A1,B2,C3", // 多种风险类型 - }, - } - - log := zap.NewNop() - detail := buildElementVerificationDetail(apiData, log) - - // 验证sjsysFlag(手机三要素风险标识) - if sjsysFlag, ok := detail["sjsysFlag"].(int); ok { - if sjsysFlag != 1 { - t.Errorf("sjsysFlag应该为1(高风险),实际为%d", sjsysFlag) - } - } - - // 验证phoneVailRiskFlag(手机信息验证风险标识) - if phoneVailRiskFlag, ok := detail["phoneVailRiskFlag"].(int); ok { - if phoneVailRiskFlag != 1 { - t.Errorf("phoneVailRiskFlag应该为1(高风险),实际为%d", phoneVailRiskFlag) - } - } - - // 验证highRiskFlag(公安重点人员风险标识) - if highRiskFlag, ok := detail["highRiskFlag"].(int); ok { - if highRiskFlag != 1 { - t.Errorf("highRiskFlag应该为1(高风险),实际为%d", highRiskFlag) - } - } - - // 验证keyPersonCheckList - if keyPersonCheckList, ok := detail["keyPersonCheckList"].(map[string]interface{}); ok { - if fontFlag, ok := keyPersonCheckList["fontFlag"].(int); ok { - if fontFlag != 1 { - t.Errorf("fontFlag应该为1,实际为%d", fontFlag) - } - } - if jingJiFontFlag, ok := keyPersonCheckList["jingJiFontFlag"].(int); ok { - if jingJiFontFlag != 1 { - t.Errorf("jingJiFontFlag应该为1,实际为%d", jingJiFontFlag) - } - } - if fangAiFlag, ok := keyPersonCheckList["fangAiFlag"].(int); ok { - if fangAiFlag != 1 { - t.Errorf("fangAiFlag应该为1,实际为%d", fangAiFlag) - } - } - } -} - -// TestBuildRiskSupervision 测试关联风险监督构建 -func TestBuildRiskSupervision(t *testing.T) { - apiData := map[string]interface{}{ - "JRZQ1D09": map[string]interface{}{ - "phone_relation_idard": "5", // 同一身份证关联手机号数 - "idcard_relation_phone": "3", // 同一手机号关联身份证数 - "least_application_time": "2025-06-02", - }, - } - - log := zap.NewNop() - riskSupervision := buildRiskSupervision(apiData, log) - - // 验证rentalRiskListIdCardRelationsPhones - if idCardRelationsPhones, ok := riskSupervision["rentalRiskListIdCardRelationsPhones"].(int); ok { - if idCardRelationsPhones != 5 { - t.Errorf("rentalRiskListIdCardRelationsPhones应该为5,实际为%d", idCardRelationsPhones) - } - } - - // 验证rentalRiskListPhoneRelationsIdCards - if phoneRelationsIdCards, ok := riskSupervision["rentalRiskListPhoneRelationsIdCards"].(int); ok { - if phoneRelationsIdCards != 3 { - t.Errorf("rentalRiskListPhoneRelationsIdCards应该为3,实际为%d", phoneRelationsIdCards) - } - } - - // 验证leastApplicationTime - if leastApplicationTime, ok := riskSupervision["leastApplicationTime"].(string); ok { - if leastApplicationTime != "2025-06-02" { - t.Errorf("leastApplicationTime应该为'2025-06-02',实际为%s", leastApplicationTime) - } - } -} - -// TestRiskCountsCalculation 测试风险计数计算 -func TestRiskCountsCalculation(t *testing.T) { - apiData := map[string]interface{}{ - "FLXGDEA9": map[string]interface{}{ - "level": "A1,B2,C3,D4,E5", // 多种风险类型 - }, - "FLXG8B4D": map[string]interface{}{ - "data": map[string]interface{}{ - "moneyLaundering": "A", // 有风险 - }, - }, - "JRZQ8A2D": map[string]interface{}{ - "id": map[string]interface{}{ - "id_bank_lost": "0", // 命中 - "id_nbank_lost": "0", // 命中 - "id_bank_overdue": "0", // 命中 - }, - }, - "JRZQ6F2A": map[string]interface{}{ - "risk_screen_v2": map[string]interface{}{ - "variables": []interface{}{ - map[string]interface{}{ - "variableValue": map[string]interface{}{ - "als_d7_id_bank_allnum": "10", // 频繁申请 - "als_d7_id_nbank_allnum": "10", // 频繁申请 - "als_m6_id_bank_allnum": "10", - "als_m6_id_nbank_allnum": "10", - "als_m12_id_bank_allnum": "10", - "als_m12_id_nbank_allnum": "10", - }, - }, - }, - }, - }, - "JRZQ1D09": map[string]interface{}{ - "alc_m3_id_allnum": "10", - "alc_m3_cell_allnum": "10", - "alc_m6_id_allnum": "10", - "alc_m6_cell_allnum": "10", - "alc_m12_id_allnum": "10", - "alc_m12_cell_allnum": "10", - }, - "JRZQ5E9F": map[string]interface{}{ - "xyp_cpl0072": "5", // 当前逾期金额较大 - "xyp_cpl0071": "5", // 当前逾期机构数较多 - }, - } - - log := zap.NewNop() - riskWarning := buildRiskWarning(apiData, log) - - // 验证gazdyrhyRiskCounts(公安重点人员风险计数) - if gazdyrhyRiskCounts, ok := riskWarning["gazdyrhyRiskCounts"].(int); ok { - if gazdyrhyRiskCounts < 5 { - t.Errorf("gazdyrhyRiskCounts应该至少为5,实际为%d", gazdyrhyRiskCounts) - } - } - - // 验证sfhyfxRiskCounts(涉赌涉诈风险计数) - if sfhyfxRiskCounts, ok := riskWarning["sfhyfxRiskCounts"].(int); ok { - if sfhyfxRiskCounts != 1 { - t.Errorf("sfhyfxRiskCounts应该为1,实际为%d", sfhyfxRiskCounts) - } - } - - // 验证yqfxRiskCounts(逾期风险计数) - if yqfxRiskCounts, ok := riskWarning["yqfxRiskCounts"].(int); ok { - if yqfxRiskCounts < 3 { - t.Errorf("yqfxRiskCounts应该至少为3,实际为%d", yqfxRiskCounts) - } - } - - // 验证frequentBankApplications - if frequentBankApplications, ok := riskWarning["frequentBankApplications"].(int); ok { - if frequentBankApplications != 1 { - t.Errorf("frequentBankApplications应该为1,实际为%d", frequentBankApplications) - } - } - - // 验证frequentRentalApplications - if frequentRentalApplications, ok := riskWarning["frequentRentalApplications"].(int); ok { - if frequentRentalApplications != 1 { - t.Errorf("frequentRentalApplications应该为1,实际为%d", frequentRentalApplications) - } - } - - // 验证highDebtPressure - if highDebtPressure, ok := riskWarning["highDebtPressure"].(int); ok { - if highDebtPressure != 1 { - t.Errorf("highDebtPressure应该为1,实际为%d", highDebtPressure) - } - } -} - -// TestDataFormatConversion 测试数据格式转换 -func TestDataFormatConversion(t *testing.T) { - // 测试身份证/手机号格式转换 - apiData := map[string]interface{}{ - "JRZQ6F2A": map[string]interface{}{ - "risk_screen_v2": map[string]interface{}{ - "variables": []interface{}{ - map[string]interface{}{ - "variableValue": map[string]interface{}{ - "als_m6_id_bank_allnum": "5", - "als_m6_cell_bank_allnum": "3", - }, - }, - }, - }, - }, - } - - log := zap.NewNop() - detail := buildLoanEvaluationVerificationDetail(apiData, log) - - // 验证格式为"身份证/手机号" - if organLoanPerformances, ok := detail["organLoanPerformances"].([]interface{}); ok { - if len(organLoanPerformances) > 0 { - if bankPerf, ok := organLoanPerformances[0].(map[string]interface{}); ok { - if last6Month, ok := bankPerf["last6Month"].(string); ok { - if !strings.Contains(last6Month, "/") { - t.Errorf("last6Month格式异常,应该包含'/',实际为%s", last6Month) - } - // 应该是"5/3" - if last6Month != "5/3" { - t.Errorf("last6Month应该为'5/3',实际为%s", last6Month) - } - } - } - } - } -} - -// TestDefaultValues 测试默认值设置 -func TestDefaultValues(t *testing.T) { - // 测试空数据情况 - apiData := map[string]interface{}{} - - params := dto.DWBG8B4DReq{ - Name: "测试", - IDCard: "110101199001011234", - MobileNo: "13800138000", - } - - log := zap.NewNop() - report := transformToDitingReport(apiData, params, log) - - // 验证baseInfo有默认值 - if baseInfo, ok := report["baseInfo"].(map[string]interface{}); ok { - if name, ok := baseInfo["name"].(string); ok { - if name == "" { - t.Error("name字段应该有默认值(脱敏后的姓名)") - } - } - if age, ok := baseInfo["age"].(int); ok { - if age < 0 { - t.Errorf("age字段默认值异常: %d", age) - } - } - } - - // 验证overdueRiskProduct有默认值 - if overdueRiskProduct, ok := report["overdueRiskProduct"].(map[string]interface{}); ok { - if hasOverdue, ok := overdueRiskProduct["hasUnsettledOverdue"].(string); ok { - if hasOverdue == "" { - t.Error("hasUnsettledOverdue应该有默认值") - } - } - // 验证repaymentSuccessCount默认值为"-" - if successCount, ok := overdueRiskProduct["repaymentSuccessCountLast7Days"].(string); ok { - if successCount != "-" { - t.Errorf("repaymentSuccessCountLast7Days默认值应该为'-',实际为%s", successCount) - } - } - } -} - -// TestEdgeCases 测试边界情况 -func TestEdgeCases(t *testing.T) { - // 测试手机在网状态的各种情况 - testCases := []struct { - name string - status interface{} - desc string - expected int - }{ - {"在网", 0, "在网", 1}, // 实号 - {"停机", 1, "停机", 2}, // 停机 - {"空号", 1, "空号", 0}, // 空号 - {"库无", 1, "库无", 3}, // 库无 - {"沉默号", 1, "其他", 4}, // 沉默号 - {"风险号", 1, "风险", 5}, // 风险号 - {"未查得", nil, "", 1}, // 未查得(会使用YYSYH6D2的result作为fallback,result="0"表示一致,status=1) - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - apiData := map[string]interface{}{ - "YYSYH6D2": map[string]interface{}{ - "result": "0", - "channel": "cmcc", - "address": "北京市东城区", - }, - "YYSY9E4A": map[string]interface{}{ - "provinceName": "北京", - "cityName": "北京", - }, - } - - // 只有当status不为nil时才添加YYSYE7V5数据 - if tc.status != nil { - apiData["YYSYE7V5"] = map[string]interface{}{ - "status": tc.status, - "desc": tc.desc, - "channel": "cmcc", - } - } - - log := zap.NewNop() - baseInfo := buildBaseInfo(apiData, dto.DWBG8B4DReq{ - Name: "测试", - IDCard: "110101199001011234", - MobileNo: "13800138000", - }, log) - - if status, ok := baseInfo["status"].(int); ok { - if status != tc.expected { - t.Errorf("status应该为%d,实际为%d", tc.expected, status) - } - } else if tc.expected != -1 { - t.Errorf("status字段不存在,期望为%d", tc.expected) - } - }) - } -} diff --git a/internal/domains/api/services/processors/flxg/flxg0687_processor.go b/internal/domains/api/services/processors/flxg/flxg0687_processor.go deleted file mode 100644 index 873c2c2..0000000 --- a/internal/domains/api/services/processors/flxg/flxg0687_processor.go +++ /dev/null @@ -1,39 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/yushan" -) - -// ProcessFLXG0687Request FLXG0687 API处理方法 -func ProcessFLXG0687Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG0687Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqData := map[string]interface{}{ - "keyWord": paramsDto.IDCard, - "type": 3, - } - - respBytes, err := deps.YushanService.CallAPI(ctx, "RIS031", reqData) - if err != nil { - if errors.Is(err, yushan.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg0v3b_processor.go b/internal/domains/api/services/processors/flxg/flxg0v3b_processor.go deleted file mode 100644 index 746dadf..0000000 --- a/internal/domains/api/services/processors/flxg/flxg0v3b_processor.go +++ /dev/null @@ -1,51 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessFLXG0V3Bequest FLXG0V3B API处理方法 -func ProcessFLXG0V3Bequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG0V3BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "id_card": encryptedIDCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G34BJ03", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg0v4b_processor.go b/internal/domains/api/services/processors/flxg/flxg0v4b_processor.go deleted file mode 100644 index ca7a095..0000000 --- a/internal/domains/api/services/processors/flxg/flxg0v4b_processor.go +++ /dev/null @@ -1,527 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "log" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" - - "github.com/tidwall/gjson" -) - -// ProcessFLXG0V4BRequest FLXG0V4B API处理方法(身份证排空入口,身份证身份证身份证身份证身份证) -func ProcessFLXG0V4BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG0V4BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - // 去掉司法案件案件去掉身份证号码 - if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" { - return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空")) - } - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - if deps.CallContext.ContractCode == "" { - return nil, fmt.Errorf("%s: %w", processors.ErrSystem, errors.New("合同编号不能为空")) - } - encryptedAuthAuthorizeFileCode, err := deps.WestDexService.Encrypt(deps.CallContext.ContractCode) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "idcard": encryptedIDCard, - "auth_authorizeFileCode": encryptedAuthAuthorizeFileCode, - "inquired_auth": fmt.Sprintf("authed:%s", paramsDto.AuthDate), - }, - } - log.Println("reqData", reqData) - respBytes, err := deps.WestDexService.CallAPI(ctx, "G22SC01", reqData) - if err != nil { - // 数据源错误 - if errors.Is(err, westdex.ErrDatasource) { - // 如果有返回内容,优先解析返回内容 - if respBytes != nil { - parsed, parseErr := ParseJsonResponse(respBytes) - if parseErr == nil { - // 通过gjson获取指定路径的数据 - contentResult := gjson.GetBytes(parsed, "G22SC0101.G22SC0102.content") - if contentResult.Exists() { - return []byte(contentResult.Raw), errors.Join(processors.ErrDatasource, err) - } - return parsed, errors.Join(processors.ErrDatasource, err) - } - // 解析失败,返回原始内容和系统错误 - return respBytes, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr) - } - // 没有返回内容,直接返回数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } - // 其他系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } - - // 正常返回 - 不管有没有deps.Options.Json都进行ParseJsonResponse - parsed, parseErr := ParseJsonResponse(respBytes) - if parseErr != nil { - return nil, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr) - } - - // 通过gjson获取指定路径的数据 - contentResult := gjson.GetBytes(parsed, "G22SC0101.G22SC0102.content") - if contentResult.Exists() { - return []byte(contentResult.Raw), nil - } else { - return nil, errors.Join(processors.ErrDatasource, err) - } - -} - -// Content 数据内容 -type FLXG0V4BResponse struct { - Sxbzxr Sxbzxr `json:"sxbzxr"` // 失信被执行人 - Entout Entout `json:"entout"` // 涉诉信息 - Xgbzxr Xgbzxr `json:"xgbzxr"` // 限高被执行人 -} - -// Sxbzxr 失信被执行人 -type Sxbzxr struct { - Msg string `json:"msg"` // 备注信息 - Data SxbzxrData `json:"data"` // 数据结果 -} - -// SxbzxrData 失信被执行人数据 -type SxbzxrData struct { - Sxbzxr []SxbzxrItem `json:"sxbzxr"` // 失信被执行人列表 -} - -// SxbzxrItem 失信被执行人项 -type SxbzxrItem struct { - Yw string `json:"yw"` // 生效法律文书确定的义务 - PjjeGj int `json:"pjje_gj"` // 判决金额_估计 - Xwqx string `json:"xwqx"` // 失信被执行人行为具体情形 - ID string `json:"id"` // 标识 - Zxfy string `json:"zxfy"` // 执行法院 - Ah string `json:"ah"` // 案号 - Zxyjwh string `json:"zxyjwh"` // 执行依据文号 - Lxqk string `json:"lxqk"` // 被执行人的履行情况 - Zxyjdw string `json:"zxyjdw"` // 出执行依据单位 - Fbrq string `json:"fbrq"` // 发布时间(日期) - Xb string `json:"xb"` // 性别 - Larq string `json:"larq"` // 立案日期 - Sf string `json:"sf"` // 省份 -} - -// Entout 涉诉信息 -type Entout struct { - Msg string `json:"msg"` // 备注信息 - Data EntoutData `json:"data"` // 数据结果 -} - -// EntoutData 涉诉信息数据 -type EntoutData struct { - Administrative Administrative `json:"administrative"` // 行政案件 - Implement Implement `json:"implement"` // 执行案件 - Count Count `json:"count"` // 统计 - Preservation Preservation `json:"preservation"` // 案件类型(非诉保全审查) - Crc int `json:"crc"` // 当事人变更码 - Civil Civil `json:"civil"` // 民事案件 - Criminal Criminal `json:"criminal"` // 刑事案件 - CasesTree CasesTree `json:"cases_tree"` // 串联树 - Bankrupt Bankrupt `json:"bankrupt"` // 强制清算与破产案件 -} - -// Administrative 行政案件 -type Administrative struct { - Cases []AdministrativeCase `json:"cases"` // 案件 - Count Count `json:"count"` // 统计 -} - -// AdministrativeCase 行政案件项 -type AdministrativeCase struct { - NjabdjeGjLevel int `json:"n_jabdje_gj_level"` // 结案标的金额估计等级 - NjbfyCj string `json:"n_jbfy_cj"` // 法院所属层级 - CgkwsGlah string `json:"c_gkws_glah"` // 相关案件号 - Njafs string `json:"n_jafs"` // 结案方式 - Nssdw string `json:"n_ssdw"` // 诉讼地位 - Djarq string `json:"d_jarq"` // 结案时间 - CgkwsPjjg string `json:"c_gkws_pjjg"` // 判决结果 - Nqsbdje int `json:"n_qsbdje"` // 起诉标的金额 - Ncrc int `json:"n_crc"` // 案件变更码 - Cssdy string `json:"c_ssdy"` // 所属地域 - Najjzjd string `json:"n_ajjzjd"` // 案件进展阶段 - Njaay string `json:"n_jaay"` // 结案案由 - Najlx string `json:"n_ajlx"` // 案件类型 - CahYs string `json:"c_ah_ys"` // 原审案号 - NlaayTree string `json:"n_laay_tree"` // 立案案由详细 - NjabdjeLevel int `json:"n_jabdje_level"` // 结案标的金额等级 - Nlaay string `json:"n_laay"` // 立案案由 - Najbs string `json:"n_ajbs"` // 案件标识 - Njbfy string `json:"n_jbfy"` // 经办法院 - CgkwsID string `json:"c_gkws_id"` // 公开文书ID - NjabdjeGj int `json:"n_jabdje_gj"` // 结案标的金额估计 - NpjVictory string `json:"n_pj_victory"` // 胜诉估计 - CgkwsDsr string `json:"c_gkws_dsr"` // 当事人 - Nslcx string `json:"n_slcx"` // 审理程序 - NqsbdjeLevel int `json:"n_qsbdje_level"` // 起诉标的金额等级 - CID string `json:"c_id"` // 案件唯一ID - NssdwYs string `json:"n_ssdw_ys"` // 一审诉讼地位 - Cslfsxx string `json:"c_slfsxx"` // 审理方式信息 - Cah string `json:"c_ah"` // 案号 - Cdsrxx []Dsrxx `json:"c_dsrxx"` // 当事人 - Dlarq string `json:"d_larq"` // 立案时间 - NjaayTree string `json:"n_jaay_tree"` // 结案案由详细 - CahHx string `json:"c_ah_hx"` // 后续案号 - Njabdje int `json:"n_jabdje"` // 结案标的金额 -} - -// Implement 执行案件 -type Implement struct { - Cases []ImplementCase `json:"cases"` // 案件 - Count Count `json:"count"` // 统计 -} - -// ImplementCase 执行案件项 -type ImplementCase struct { - Cdsrxx []Dsrxx `json:"c_dsrxx"` // 当事人 - Cssdy string `json:"c_ssdy"` // 所属地域 - NjabdjeGj int `json:"n_jabdje_gj"` // 结案标的金额估计 - Ncrc int `json:"n_crc"` // 案件变更码 - Nlaay string `json:"n_laay"` // 立案案由 - Cah string `json:"c_ah"` // 案号 - Nsqzxbdje int `json:"n_sqzxbdje"` // 申请执行标的金额 - CahYs string `json:"c_ah_ys"` // 原审案号 - CgkwsGlah string `json:"c_gkws_glah"` // 相关案件号 - Najbs string `json:"n_ajbs"` // 案件标识 - CgkwsPjjg string `json:"c_gkws_pjjg"` // 判决结果 - Njafs string `json:"n_jafs"` // 结案方式 - Njaay string `json:"n_jaay"` // 结案案由 - NjbfyCj string `json:"n_jbfy_cj"` // 法院所属层级 - CID string `json:"c_id"` // 案件唯一ID - Njabdje int `json:"n_jabdje"` // 结案标的金额 - Najjzjd string `json:"n_ajjzjd"` // 案件进展阶段 - Dlarq string `json:"d_larq"` // 立案时间 - Najlx string `json:"n_ajlx"` // 案件类型 - Nsjdwje int `json:"n_sjdwje"` // 实际到位金额 - CgkwsID string `json:"c_gkws_id"` // 公开文书ID - CahHx string `json:"c_ah_hx"` // 后续案号 - Nwzxje int `json:"n_wzxje"` // 未执行金额 - Djarq string `json:"d_jarq"` // 结案时间 - CgkwsDsr string `json:"c_gkws_dsr"` // 当事人 - Njbfy string `json:"n_jbfy"` // 经办法院 - Nssdw string `json:"n_ssdw"` // 诉讼地位 -} - -// Preservation 案件类型(非诉保全审查) -type Preservation struct { - Cases []PreservationCase `json:"cases"` // 案件 - Count Count `json:"count"` // 统计 -} - -// PreservationCase 非诉保全审查案件项 -type PreservationCase struct { - NjbfyCj string `json:"n_jbfy_cj"` // 法院所属层级 - Nssdw string `json:"n_ssdw"` // 诉讼地位 - Ncrc int `json:"n_crc"` // 案件变更码 - Cssdy string `json:"c_ssdy"` // 所属地域 - Dlarq string `json:"d_larq"` // 立案时间 - CgkwsID string `json:"c_gkws_id"` // 公开文书ID - CahYs string `json:"c_ah_ys"` // 原审案号 - Nsqbqse int `json:"n_sqbqse"` // 申请保全数额 - Djarq string `json:"d_jarq"` // 结案时间 - Najbs string `json:"n_ajbs"` // 案件标识 - CgkwsDsr string `json:"c_gkws_dsr"` // 当事人 - CgkwsPjjg string `json:"c_gkws_pjjg"` // 判决结果 - Njbfy string `json:"n_jbfy"` // 经办法院 - Njafs string `json:"n_jafs"` // 结案方式 - Cdsrxx []Dsrxx `json:"c_dsrxx"` // 当事人 - Najjzjd string `json:"n_ajjzjd"` // 案件进展阶段 - Najlx string `json:"n_ajlx"` // 案件类型 - CID string `json:"c_id"` // 案件唯一ID - Cah string `json:"c_ah"` // 案号 - NsqbqseLevel int `json:"n_sqbqse_level"` // 申请保全数额等级 - CahHx string `json:"c_ah_hx"` // 后续案号 - Csqbqbdw string `json:"c_sqbqbdw"` // 申请保全标的物 - CgkwsGlah string `json:"c_gkws_glah"` // 相关案件号 -} - -// Civil 民事案件 -type Civil struct { - Cases []CivilCase `json:"cases"` // 案件 - Count Count `json:"count"` // 统计 -} - -// CivilCase 民事案件项 -type CivilCase struct { - NjabdjeLevel int `json:"n_jabdje_level"` // 结案标的金额等级 - Nslcx string `json:"n_slcx"` // 审理程序 - NjabdjeGjLevel int `json:"n_jabdje_gj_level"` // 结案标的金额估计等级 - Najjzjd string `json:"n_ajjzjd"` // 案件进展阶段 - Njafs string `json:"n_jafs"` // 结案方式 - CgkwsPjjg string `json:"c_gkws_pjjg"` // 判决结果 - Cslfsxx string `json:"c_slfsxx"` // 审理方式信息 - Nlaay string `json:"n_laay"` // 立案案由 - CgkwsGlah string `json:"c_gkws_glah"` // 相关案件号 - Nssdw string `json:"n_ssdw"` // 诉讼地位 - NssdwYs string `json:"n_ssdw_ys"` // 一审诉讼地位 - NlaayTag string `json:"n_laay_tag"` // 立案案由标签 - NqsbdjeLevel int `json:"n_qsbdje_level"` // 起诉标的金额等级 - Ncrc int `json:"n_crc"` // 案件变更码 - CahHx string `json:"c_ah_hx"` // 后续案号 - NqsbdjeGjLevel int `json:"n_qsbdje_gj_level"` // 起诉标的金额估计等级 - Njbfy string `json:"n_jbfy"` // 经办法院 - Cah string `json:"c_ah"` // 案号 - Njabdje int `json:"n_jabdje"` // 结案标的金额 - NjabdjeGj int `json:"n_jabdje_gj"` // 结案标的金额估计 - NqsbdjeGj int `json:"n_qsbdje_gj"` // 起诉标的金额估计 - NjbfyCj string `json:"n_jbfy_cj"` // 法院所属层级 - Cssdy string `json:"c_ssdy"` // 所属地域 - Dlarq string `json:"d_larq"` // 立案时间 - CgkwsID string `json:"c_gkws_id"` // 公开文书ID - NpjVictory string `json:"n_pj_victory"` // 胜诉估计 - CgkwsDsr string `json:"c_gkws_dsr"` // 当事人 - Djarq string `json:"d_jarq"` // 结案时间 - Njaay string `json:"n_jaay"` // 结案案由 - NlaayTree string `json:"n_laay_tree"` // 立案案由详细 - Cdsrxx []Dsrxx `json:"c_dsrxx"` // 当事人 - CahYs string `json:"c_ah_ys"` // 原审案号 - Nqsbdje int `json:"n_qsbdje"` // 起诉标的金额 - NjaayTree string `json:"n_jaay_tree"` // 结案案由详细 - Najlx string `json:"n_ajlx"` // 案件类型 - CID string `json:"c_id"` // 案件唯一ID - Najbs string `json:"n_ajbs"` // 案件标识 -} - -// Criminal 刑事案件 -type Criminal struct { - Cases []CriminalCase `json:"cases"` // 案件 - Count Count `json:"count"` // 统计 -} - -// CriminalCase 刑事案件项 -type CriminalCase struct { - CgkwsDsr string `json:"c_gkws_dsr"` // 当事人 - NpcpcjeLevel int `json:"n_pcpcje_level"` // 判处赔偿金额等级 - Nbqqpcje int `json:"n_bqqpcje"` // 被请求赔偿金额 - NpcpcjeGjLevel int `json:"n_pcpcje_gj_level"` // 判处赔偿金额估计等级 - Dlarq string `json:"d_larq"` // 立案时间 - Djarq string `json:"d_jarq"` // 结案时间 - CahHx string `json:"c_ah_hx"` // 后续案号 - Njafs string `json:"n_jafs"` // 结案方式 - NjaayTag string `json:"n_jaay_tag"` // 结案案由标签 - Njbfy string `json:"n_jbfy"` // 经办法院 - NlaayTag string `json:"n_laay_tag"` // 立案案由标签 - Ndzzm string `json:"n_dzzm"` // 定罪罪名 - NjbfyCj string `json:"n_jbfy_cj"` // 法院所属层级 - NlaayTree string `json:"n_laay_tree"` // 立案案由详细 - NccxzxjeLevel int `json:"n_ccxzxje_level"` // 财产刑执行金额等级 - Ncrc int `json:"n_crc"` // 案件变更码 - Cdsrxx []Dsrxx `json:"c_dsrxx"` // 当事人 - NccxzxjeGjLevel int `json:"n_ccxzxje_gj_level"` // 财产刑执行金额估计等级 - Nfzje int `json:"n_fzje"` // 犯罪金额 - CgkwsID string `json:"c_gkws_id"` // 公开文书ID - Cah string `json:"c_ah"` // 案号 - Cssdy string `json:"c_ssdy"` // 所属地域 - Npcpcje int `json:"n_pcpcje"` // 判处赔偿金额 - CahYs string `json:"c_ah_ys"` // 原审案号 - Najjzjd string `json:"n_ajjzjd"` // 案件进展阶段 - CgkwsGlah string `json:"c_gkws_glah"` // 相关案件号 - CgkwsPjjg string `json:"c_gkws_pjjg"` // 判决结果 - Cslfsxx string `json:"c_slfsxx"` // 审理方式信息 - NpcpcjeGj int `json:"n_pcpcje_gj"` // 判处赔偿金额估计 - Najbs string `json:"n_ajbs"` // 案件标识 - Nlaay string `json:"n_laay"` // 立案案由 - Njaay string `json:"n_jaay"` // 结案案由 - Nssdw string `json:"n_ssdw"` // 诉讼地位 - NdzzmTree string `json:"n_dzzm_tree"` // 定罪罪名树 - NjaayTree string `json:"n_jaay_tree"` // 结案案由详细 - Npcjg string `json:"n_pcjg"` // 判处结果 - CID string `json:"c_id"` // 案件唯一ID - NssdwYs string `json:"n_ssdw_ys"` // 一审诉讼地位 - Nccxzxje int `json:"n_ccxzxje"` // 财产刑执行金额 - NfzjeLevel int `json:"n_fzje_level"` // 犯罪金额等级 - Nslcx string `json:"n_slcx"` // 审理程序 - Najlx string `json:"n_ajlx"` // 案件类型 - NbqqpcjeLevel int `json:"n_bqqpcje_level"` // 被请求赔偿金额等级 - NccxzxjeGj int `json:"n_ccxzxje_gj"` // 财产刑执行金额估计 -} - -// CasesTree 串联树 -type CasesTree struct { - Administrative []CasesTreeItem `json:"administrative"` // 行政案件 - Criminal []CasesTreeItem `json:"criminal"` // 刑事案件 - Civil []CasesTreeItem `json:"civil"` // 民事案件 -} - -// CasesTreeItem 串联树项 -type CasesTreeItem struct { - Cah string `json:"c_ah"` // 案号 - CaseType int `json:"case_type"` // 案件类型 - Najbs string `json:"n_ajbs"` // 案件标识 - StageType int `json:"stage_type"` // 审理阶段类型 - Next *CasesTreeItem `json:"next"` // 下一个案件 -} - -// Bankrupt 强制清算与破产案件 -type Bankrupt struct { - Cases []BankruptCase `json:"cases"` // 案件 - Count Count `json:"count"` // 统计 -} - -// BankruptCase 强制清算与破产案件项 -type BankruptCase struct { - Cdsrxx []Dsrxx `json:"c_dsrxx"` // 当事人 - CgkwsID string `json:"c_gkws_id"` // 公开文书ID - Najbs string `json:"n_ajbs"` // 案件标识 - NjbfyCj string `json:"n_jbfy_cj"` // 法院所属层级 - CgkwsDsr string `json:"c_gkws_dsr"` // 当事人 - CID string `json:"c_id"` // 案件唯一ID - Dlarq string `json:"d_larq"` // 立案时间 - Djarq string `json:"d_jarq"` // 结案时间 - Najlx string `json:"n_ajlx"` // 案件类型 - CgkwsGlah string `json:"c_gkws_glah"` // 相关案件号 - Njbfy string `json:"n_jbfy"` // 经办法院 - Najjzjd string `json:"n_ajjzjd"` // 案件进展阶段 - CgkwsPjjg string `json:"c_gkws_pjjg"` // 判决结果 - Cssdy string `json:"c_ssdy"` // 所属地域 - Ncrc int `json:"n_crc"` // 案件变更码 - Nssdw string `json:"n_ssdw"` // 诉讼地位 - Njafs string `json:"n_jafs"` // 结案方式 - Cah string `json:"c_ah"` // 案号 -} - -// Dsrxx 当事人 -type Dsrxx struct { - Nssdw string `json:"n_ssdw"` // 诉讼地位 - CMc string `json:"c_mc"` // 名称 - Ndsrlx string `json:"n_dsrlx"` // 当事人类型 -} - -// Count 统计 -type Count struct { - MoneyYuangao int `json:"money_yuangao"` // 原告金额 - AreaStat string `json:"area_stat"` // 涉案地点分布 - CountJieBeigao int `json:"count_jie_beigao"` // 被告已结案总数 - CountTotal int `json:"count_total"` // 案件总数 - MoneyWeiYuangao int `json:"money_wei_yuangao"` // 原告未结案金额 - CountWeiTotal int `json:"count_wei_total"` // 未结案总数 - MoneyWeiBeigao int `json:"money_wei_beigao"` // 被告未结案金额 - CountOther int `json:"count_other"` // 第三人总数 - MoneyBeigao int `json:"money_beigao"` // 被告金额 - CountYuangao int `json:"count_yuangao"` // 原告总数 - MoneyJieOther int `json:"money_jie_other"` // 第三人已结案金额 - MoneyTotal int `json:"money_total"` // 涉案总金额 - MoneyWeiTotal int `json:"money_wei_total"` // 未结案金额 - CountWeiYuangao int `json:"count_wei_yuangao"` // 原告未结案总数 - AyStat string `json:"ay_stat"` // 涉案案由分布 - CountBeigao int `json:"count_beigao"` // 被告总数 - MoneyJieYuangao int `json:"money_jie_yuangao"` // 原告已结金额 - JafsStat string `json:"jafs_stat"` // 结案方式分布 - MoneyJieBeigao int `json:"money_jie_beigao"` // 被告已结案金额 - CountWeiBeigao int `json:"count_wei_beigao"` // 被告未结案总数 - CountJieOther int `json:"count_jie_other"` // 第三人已结案总数 - CountJieTotal int `json:"count_jie_total"` // 已结案总数 - CountWeiOther int `json:"count_wei_other"` // 第三人未结案总数 - MoneyOther int `json:"money_other"` // 第三人金额 - CountJieYuangao int `json:"count_jie_yuangao"` // 原告已结案总数 - MoneyJieTotal int `json:"money_jie_total"` // 已结案金额 - MoneyWeiOther int `json:"money_wei_other"` // 第三人未结案金额 - MoneyWeiPercent float64 `json:"money_wei_percent"` // 未结案金额百分比 - LarqStat string `json:"larq_stat"` // 涉案时间分布 -} - -// Xgbzxr 限高被执行人 -type Xgbzxr struct { - Msg string `json:"msg"` // 备注信息 - Data XgbzxrData `json:"data"` // 数据结果 -} - -// XgbzxrData 限高被执行人数据 -type XgbzxrData struct { - Xgbzxr []XgbzxrItem `json:"xgbzxr"` // 限高被执行人列表 -} - -// XgbzxrItem 限高被执行人项 -type XgbzxrItem struct { - Ah string `json:"ah"` // 案号 - ID string `json:"id"` // 标识 - Zxfy string `json:"zxfy"` // 执行法院 - Fbrq string `json:"fbrq"` // 发布时间 -} - -// ParseWestResponse 解析西部返回的响应数据(获取data字段后解析) -// westResp: 西部返回的原始响应 -// Returns: 解析后的数据字节数组 -func ParseWestResponse(westResp []byte) ([]byte, error) { - dataResult := gjson.GetBytes(westResp, "data") - if !dataResult.Exists() { - return nil, errors.New("data not found") - } - return ParseJsonResponse([]byte(dataResult.Raw)) -} - -// ParseJsonResponse 直接解析JSON响应数据 -// jsonResp: JSON响应数据 -// Returns: 解析后的数据字节数组 -func ParseJsonResponse(jsonResp []byte) ([]byte, error) { - parseResult, err := RecursiveParse(string(jsonResp)) - if err != nil { - return nil, err - } - - resultResp, marshalErr := json.Marshal(parseResult) - if marshalErr != nil { - return nil, err - } - - return resultResp, nil -} - -// RecursiveParse 递归解析JSON数据 -func RecursiveParse(data interface{}) (interface{}, error) { - switch v := data.(type) { - case string: - var parsed interface{} - if err := json.Unmarshal([]byte(v), &parsed); err == nil { - return RecursiveParse(parsed) - } - return v, nil - case map[string]interface{}: - for key, val := range v { - parsed, err := RecursiveParse(val) - if err != nil { - return nil, err - } - v[key] = parsed - } - return v, nil - case []interface{}: - for i, item := range v { - parsed, err := RecursiveParse(item) - if err != nil { - return nil, err - } - v[i] = parsed - } - return v, nil - default: - return v, nil - } -} diff --git a/internal/domains/api/services/processors/flxg/flxg162a_processor.go b/internal/domains/api/services/processors/flxg/flxg162a_processor.go deleted file mode 100644 index 8ba6f13..0000000 --- a/internal/domains/api/services/processors/flxg/flxg162a_processor.go +++ /dev/null @@ -1,57 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessFLXG162ARequest FLXG162A API处理方法 -func ProcessFLXG162ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG162AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "id": encryptedIDCard, - "cell": encryptedMobileNo, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G32BJ05", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg2e8f_processor.go b/internal/domains/api/services/processors/flxg/flxg2e8f_processor.go deleted file mode 100644 index 87d1337..0000000 --- a/internal/domains/api/services/processors/flxg/flxg2e8f_processor.go +++ /dev/null @@ -1,60 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessFLXG2E8FRequest FLXG2E8F API处理方法 - 司法核验报告 -func ProcessFLXG2E8FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG2E8FReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "accessoryUrl": paramsDto.AuthorizationURL, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI101", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg3a9b_processor.go b/internal/domains/api/services/processors/flxg/flxg3a9b_processor.go deleted file mode 100644 index e86b349..0000000 --- a/internal/domains/api/services/processors/flxg/flxg3a9b_processor.go +++ /dev/null @@ -1,63 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessFLXG3A9BRequest FLXG3A9B API处理方法 - 法院被执行人限高版 -func ProcessFLXG3A9BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG3A9BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - if paramsDto.IDCard == "410482198504029333" { - return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空")) - } - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI045", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg3d56_processor.go b/internal/domains/api/services/processors/flxg/flxg3d56_processor.go deleted file mode 100644 index 4477fe6..0000000 --- a/internal/domains/api/services/processors/flxg/flxg3d56_processor.go +++ /dev/null @@ -1,66 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessFLXG3D56Request FLXG3D56 API处理方法 -func ProcessFLXG3D56Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG3D56Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "id": encryptedIDCard, - "cell": encryptedMobileNo, - }, - } - - // 只有当 TimeRange 不为空时才加密和传参 - if paramsDto.TimeRange != "" { - encryptedTimeRange, err := deps.WestDexService.Encrypt(paramsDto.TimeRange) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - reqData["data"].(map[string]interface{})["time_range"] = encryptedTimeRange - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G26BJ05", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg54f5_processor.go b/internal/domains/api/services/processors/flxg/flxg54f5_processor.go deleted file mode 100644 index 87d2d99..0000000 --- a/internal/domains/api/services/processors/flxg/flxg54f5_processor.go +++ /dev/null @@ -1,45 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessFLXG54F5Request FLXG54F5 API处理方法 -func ProcessFLXG54F5Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG54F5Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "mobile": encryptedMobileNo, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx,"G03HZ01", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg5876_processor.go b/internal/domains/api/services/processors/flxg/flxg5876_processor.go deleted file mode 100644 index a3f8201..0000000 --- a/internal/domains/api/services/processors/flxg/flxg5876_processor.go +++ /dev/null @@ -1,45 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessFLXG5876Request FLXG5876 易诉人识别API处理方法 -func ProcessFLXG5876Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG5876Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "phone": encryptedMobileNo, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G03XM02", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg5a3b_processor.go b/internal/domains/api/services/processors/flxg/flxg5a3b_processor.go deleted file mode 100644 index 93ef4e5..0000000 --- a/internal/domains/api/services/processors/flxg/flxg5a3b_processor.go +++ /dev/null @@ -1,58 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessFLXG5A3BRequest FLXG5A3B API处理方法 - 个人司法涉诉 -func ProcessFLXG5A3BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG5A3BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" { - return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空")) - } - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI006", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg5b2e_processor.go b/internal/domains/api/services/processors/flxg/flxg5b2e_processor.go deleted file mode 100644 index f3d008a..0000000 --- a/internal/domains/api/services/processors/flxg/flxg5b2e_processor.go +++ /dev/null @@ -1,88 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - "fmt" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" - - "github.com/tidwall/gjson" -) - -// ProcessFLXG5B2ERequest FLXG5B2E API处理方法 -func ProcessFLXG5B2ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG5B2EReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - if deps.CallContext.ContractCode == "" { - return nil, fmt.Errorf("%s: %w", processors.ErrSystem, errors.New("合同编号不能为空")) - } - encryptedAuthAuthorizeFileCode, err := deps.WestDexService.Encrypt(deps.CallContext.ContractCode) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "idcard": encryptedIDCard, - "auth_authorizeFileCode": encryptedAuthAuthorizeFileCode, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G36SC01", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - // 如果有返回内容,优先解析返回内容 - if respBytes != nil { - parsed, parseErr := ParseJsonResponse(respBytes) - if parseErr == nil { - // 通过gjson获取指定路径的数据 - contentResult := gjson.GetBytes(parsed, "G36SC0101.G36SC0102.content") - if contentResult.Exists() { - return []byte(contentResult.Raw), errors.Join(processors.ErrDatasource, err) - } - return parsed, errors.Join(processors.ErrDatasource, err) - } - // 解析失败,返回原始内容和系统错误 - return respBytes, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr) - } - // 没有返回内容,直接返回数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 正常返回 - 不管有没有deps.Options.Json都进行ParseJsonResponse - parsed, parseErr := ParseJsonResponse(respBytes) - if parseErr != nil { - return nil, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr) - } - - // 通过gjson获取指定路径的数据 - contentResult := gjson.GetBytes(parsed, "G36SC0101.G36SC0102.content") - if contentResult.Exists() { - return []byte(contentResult.Raw), nil - } else { - return nil, errors.Join(processors.ErrDatasource, err) - } -} diff --git a/internal/domains/api/services/processors/flxg/flxg75fe_processor.go b/internal/domains/api/services/processors/flxg/flxg75fe_processor.go deleted file mode 100644 index c01fb71..0000000 --- a/internal/domains/api/services/processors/flxg/flxg75fe_processor.go +++ /dev/null @@ -1,40 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessFLXG75FERequest FLXG75FE API处理方法 -func ProcessFLXG75FERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG75FEReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCard": paramsDto.IDCard, - "mobile": paramsDto.MobileNo, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx,"FLXG75FE", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg7e8f_processor.go b/internal/domains/api/services/processors/flxg/flxg7e8f_processor.go deleted file mode 100644 index de710d4..0000000 --- a/internal/domains/api/services/processors/flxg/flxg7e8f_processor.go +++ /dev/null @@ -1,49 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessFLXG7E8FRequest FLXG7E8F API处理方法 - 个人司法数据查询 -func ProcessFLXG7E8FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG7E8FReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" { - return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空")) - } - // 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "phoneNumber": paramsDto.MobileNo, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1101695378264092672" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg8a3f_processor.go b/internal/domains/api/services/processors/flxg/flxg8a3f_processor.go deleted file mode 100644 index be5a93c..0000000 --- a/internal/domains/api/services/processors/flxg/flxg8a3f_processor.go +++ /dev/null @@ -1,86 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" - - "github.com/tidwall/gjson" -) - -// ProcessFLXG8A3FRequest FLXG8A3F API处理方法 -func ProcessFLXG8A3FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG8A3FReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - if deps.CallContext.ContractCode == "" { - return nil, fmt.Errorf("%s: %w", processors.ErrSystem, errors.New("合同编号不能为空")) - } - encryptedAuthAuthorizeFileCode, err := deps.WestDexService.Encrypt(deps.CallContext.ContractCode) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "idcard": encryptedIDCard, - "auth_authorizeFileCode": encryptedAuthAuthorizeFileCode, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G37SC01", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - // 如果有返回内容,优先解析返回内容 - if respBytes != nil { - parsed, parseErr := ParseJsonResponse(respBytes) - if parseErr == nil { - // 通过gjson获取指定路径的数据 - contentResult := gjson.GetBytes(parsed, "G37SC0101.G37SC0102.content") - if contentResult.Exists() { - return []byte(contentResult.Raw), errors.Join(processors.ErrDatasource, err) - } - return parsed, errors.Join(processors.ErrDatasource, err) - } - // 解析失败,返回原始内容和系统错误 - return respBytes, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr) - } - // 没有返回内容,直接返回数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - // 正常返回 - 不管有没有deps.Options.Json都进行ParseJsonResponse - parsed, parseErr := ParseJsonResponse(respBytes) - if parseErr != nil { - return nil, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr) - } - - // 通过gjson获取指定路径的数据 - contentResult := gjson.GetBytes(parsed, "G37SC0101.G37SC0102.content") - if contentResult.Exists() { - return []byte(contentResult.Raw), nil - } else { - return nil, errors.Join(processors.ErrDatasource, err) - } -} diff --git a/internal/domains/api/services/processors/flxg/flxg8b4d_processor.go b/internal/domains/api/services/processors/flxg/flxg8b4d_processor.go deleted file mode 100644 index 1ed644b..0000000 --- a/internal/domains/api/services/processors/flxg/flxg8b4d_processor.go +++ /dev/null @@ -1,104 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - "fmt" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessFLXG8B4DRequest FLXG8B4D API处理方法 - 涉赌涉诈风险评估 -func ProcessFLXG8B4DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG8B4DReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 三选一校验:MobileNo、IDCard、BankCard 必须且只能有一个 - var fieldCount int - var selectedField string - var selectedValue string - - if paramsDto.MobileNo != "" { - fieldCount++ - selectedField = "mobile_no" - selectedValue = paramsDto.MobileNo - } - if paramsDto.IDCard != "" { - fieldCount++ - selectedField = "id_card" - selectedValue = paramsDto.IDCard - } - if paramsDto.BankCard != "" { - fieldCount++ - selectedField = "bank_card" - selectedValue = paramsDto.BankCard - } - - if fieldCount == 0 { - return nil, fmt.Errorf("%s: %w", processors.ErrInvalidParam, errors.New("必须提供手机号、身份证号或银行卡号中的其中一个")) - } - if fieldCount > 1 { - return nil, fmt.Errorf("%s: %w", processors.ErrInvalidParam, errors.New("只能提供手机号、身份证号或银行卡号中的一个,不能同时提供多个")) - } - - // 只对选中的字段进行加密 - var encryptedValue string - var err error - switch selectedField { - case "mobile_no": - encryptedValue, err = deps.ZhichaService.Encrypt(selectedValue) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - case "id_card": - encryptedValue, err = deps.ZhichaService.Encrypt(selectedValue) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - case "bank_card": - encryptedValue, err = deps.ZhichaService.Encrypt(selectedValue) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 构建请求数据,根据选中的字段类型设置对应的参数 - reqData := map[string]interface{}{ - "authorized": paramsDto.Authorized, - } - - switch selectedField { - case "mobile_no": - reqData["phone"] = encryptedValue - case "id_card": - reqData["idCard"] = encryptedValue - case "bank_card": - reqData["name"] = encryptedValue - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI027", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg9687_processor.go b/internal/domains/api/services/processors/flxg/flxg9687_processor.go deleted file mode 100644 index a48bd24..0000000 --- a/internal/domains/api/services/processors/flxg/flxg9687_processor.go +++ /dev/null @@ -1,57 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessFLXG9687Request FLXG9687 API处理方法 -func ProcessFLXG9687Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG9687Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "id": encryptedIDCard, - "cell": encryptedMobileNo, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G31BJ05", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg970f_processor.go b/internal/domains/api/services/processors/flxg/flxg970f_processor.go deleted file mode 100644 index f29bb98..0000000 --- a/internal/domains/api/services/processors/flxg/flxg970f_processor.go +++ /dev/null @@ -1,51 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessFLXG970FRequest FLXG970F 风险人员核验API处理方法 -func ProcessFLXG970FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG970FReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "cardNo": encryptedIDCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "WEST00028", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxg9c1d_processor.go b/internal/domains/api/services/processors/flxg/flxg9c1d_processor.go deleted file mode 100644 index 2bb0d97..0000000 --- a/internal/domains/api/services/processors/flxg/flxg9c1d_processor.go +++ /dev/null @@ -1,58 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessFLXG9C1DRequest FLXG9C1D API处理方法 - 法院信息详情高级版 -func ProcessFLXG9C1DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXG9C1DReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - if paramsDto.IDCard == "410482198504029333" { - return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空")) - } - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI007", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxgbc21_processor.go b/internal/domains/api/services/processors/flxg/flxgbc21_processor.go deleted file mode 100644 index ca3c801..0000000 --- a/internal/domains/api/services/processors/flxg/flxgbc21_processor.go +++ /dev/null @@ -1,38 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/yushan" -) - -// ProcessFLXGBC21Request FLXGbc21 API处理方法 -func ProcessFLXGBC21Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXGBC21Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - } - - respBytes, err := deps.YushanService.CallAPI(ctx, "MOB032", reqData) - if err != nil { - if errors.Is(err, yushan.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxghb4f_processor.go b/internal/domains/api/services/processors/flxg/flxgc4ct_processor.go similarity index 80% rename from internal/domains/api/services/processors/flxg/flxghb4f_processor.go rename to internal/domains/api/services/processors/flxg/flxgc4ct_processor.go index 5349440..bf07b2e 100644 --- a/internal/domains/api/services/processors/flxg/flxghb4f_processor.go +++ b/internal/domains/api/services/processors/flxg/flxgc4ct_processor.go @@ -9,9 +9,9 @@ import ( "hyapi-server/internal/domains/api/services/processors" ) -// ProcessFLXGHB4FRequest FLXGHB4F API处理方法 - 个人涉诉案件查询汇博 -func ProcessFLXGHB4FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXGHB4FReq +// ProcessFLXGC4CTRequest FLXGHB4F API处理方法 - 个人涉诉案件查询汇博 +func ProcessFLXGC4CTRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.FLXGC4CTReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } @@ -24,7 +24,7 @@ func ProcessFLXGHB4FRequest(ctx context.Context, params []byte, deps *processors return nil, errors.Join(processors.ErrInvalidParam, err) } - if _, err := deps.HuiboService.SaveAuthPDFLocally(ctx, "FLXGHB4F", paramsDto.AuthPDFBase64, paramsDto.IDCard); err != nil { + if _, err := deps.HuiboService.SaveAuthPDFLocally(ctx, "FLXGC4CT", paramsDto.AuthPDFBase64, paramsDto.IDCard); err != nil { return nil, errors.Join(processors.ErrInvalidParam, err) } diff --git a/internal/domains/api/services/processors/flxg/flxgc9d1_processor.go b/internal/domains/api/services/processors/flxg/flxgc9d1_processor.go deleted file mode 100644 index db76def..0000000 --- a/internal/domains/api/services/processors/flxg/flxgc9d1_processor.go +++ /dev/null @@ -1,57 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessFLXGC9D1Request FLXGC9D1 API处理方法 -func ProcessFLXGC9D1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXGC9D1Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "id": encryptedIDCard, - "cell": encryptedMobileNo, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G30BJ05", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxgca3d_processor.go b/internal/domains/api/services/processors/flxg/flxgca3d_processor.go deleted file mode 100644 index 9ac93d9..0000000 --- a/internal/domains/api/services/processors/flxg/flxgca3d_processor.go +++ /dev/null @@ -1,57 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessFLXGCA3DRequest FLXGCA3D API处理方法 -func ProcessFLXGCA3DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXGCA3DReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" { - return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空")) - } - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "id_card": encryptedIDCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G22BJ03", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - if respBytes != nil { - return respBytes, nil - } else { - return nil, errors.Join(processors.ErrDatasource, err) - } - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxgdea8_processor.go b/internal/domains/api/services/processors/flxg/flxgdea8_processor.go deleted file mode 100644 index d0e8e92..0000000 --- a/internal/domains/api/services/processors/flxg/flxgdea8_processor.go +++ /dev/null @@ -1,56 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessFLXGDEA8Request FLXGDEA8 API处理方法 -func ProcessFLXGDEA8Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXGDEA8Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI028", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxgdea9_processor.go b/internal/domains/api/services/processors/flxg/flxgdea9_processor.go deleted file mode 100644 index 9520a86..0000000 --- a/internal/domains/api/services/processors/flxg/flxgdea9_processor.go +++ /dev/null @@ -1,57 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessFLXGDEA9Request FLXGDEA9 API处理方法 -func ProcessFLXGDEA9Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXGDEA9Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" { - return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空")) - } - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI005", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxgdec7_processor.go b/internal/domains/api/services/processors/flxg/flxgdec7_processor.go deleted file mode 100644 index 5259818..0000000 --- a/internal/domains/api/services/processors/flxg/flxgdec7_processor.go +++ /dev/null @@ -1,51 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessFLXGDEC7Request FLXGDEC7 API处理方法 -func ProcessFLXGDEC7Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXGDEC7Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "id_card": encryptedIDCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G23BJ03", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxgdjg3_processor.go b/internal/domains/api/services/processors/flxg/flxgdjg3_processor.go deleted file mode 100644 index b955e39..0000000 --- a/internal/domains/api/services/processors/flxg/flxgdjg3_processor.go +++ /dev/null @@ -1,54 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessFLXGDJG3Request FLXGDJG3 董监高司法综合信息核验 API 处理方法(使用数据宝服务示例) -func ProcessFLXGDJG3Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXGDJG3Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建数据宝入参(sign 外的业务参数可按需 AES 加密后作为 bodyData) - reqParams := map[string]interface{}{ - "key": "1cce582f0a6f3ca40de80f1bea9b9698", - "idcard": paramsDto.IDCard, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10166" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - // 解析响应中的 JSON 字符串(使用 qyglb4c0 中的 RecursiveParse) - parsedResp, err := RecursiveParse(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(parsedResp) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxgji17_processor.go b/internal/domains/api/services/processors/flxg/flxgji17_processor.go new file mode 100644 index 0000000..65233ec --- /dev/null +++ b/internal/domains/api/services/processors/flxg/flxgji17_processor.go @@ -0,0 +1,14 @@ +package flxg + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessFLXGJI17Request FLXGDJG3 董监高司法综合信息核验(天远中转) +func ProcessFLXGJI17Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.FLXGJI17Req + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "FLXGDJG3", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/flxg/flxgk5d2_processor.go b/internal/domains/api/services/processors/flxg/flxgk5d2_processor.go deleted file mode 100644 index 45fbd42..0000000 --- a/internal/domains/api/services/processors/flxg/flxgk5d2_processor.go +++ /dev/null @@ -1,63 +0,0 @@ -package flxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessFLXGK5D2Request FLXGK5D2 API处理方法 - 法院被执行人高级版 -func ProcessFLXGK5D2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXGK5D2Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - if paramsDto.IDCard == "410482198504029333" { - return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空")) - } - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI046", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/flxg/flxgg0s4_processor.go b/internal/domains/api/services/processors/flxg/flxgmmg7_processor.go similarity index 88% rename from internal/domains/api/services/processors/flxg/flxgg0s4_processor.go rename to internal/domains/api/services/processors/flxg/flxgmmg7_processor.go index 8bba84a..7028e68 100644 --- a/internal/domains/api/services/processors/flxg/flxgg0s4_processor.go +++ b/internal/domains/api/services/processors/flxg/flxgmmg7_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessFLXGG0S4Request FLXGG0S4 API处理方法 - 个人诉讼定制版 -func ProcessFLXGG0S4Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.FLXGG0S4Req +// ProcessFLXGMMG7Request FLXGG0S4 API处理方法 - 个人诉讼定制版 +func ProcessFLXGMMG7Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.FLXGMMG7Req if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/ivyz/ivyz0b03_processor.go b/internal/domains/api/services/processors/ivyz/ivyz0b03_processor.go deleted file mode 100644 index c1b5ed8..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz0b03_processor.go +++ /dev/null @@ -1,51 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessIVYZ0B03Request IVYZ0B03 API处理方法 -func ProcessIVYZ0B03Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ0B03Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "phone": encryptedMobileNo, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G17BJ02", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz0s0d_processor.go b/internal/domains/api/services/processors/ivyz/ivyz0s0d_processor.go deleted file mode 100644 index d1734e8..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz0s0d_processor.go +++ /dev/null @@ -1,45 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessIVYZ0S0DRequest IVYZ0S0D API处理方法 - 劳动仲裁信息查询(个人版) -func ProcessIVYZ0S0DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ0S0DReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "id": paramsDto.IDCard, - "name": paramsDto.Name, - } - - // 调用极光API - respBytes, err := deps.JiguangService.CallAPI(ctx, "labor-arbitration-information", "labor-arbitration-information", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz18hy_processor.go b/internal/domains/api/services/processors/ivyz/ivyz18hy_processor.go deleted file mode 100644 index 11e3356..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz18hy_processor.go +++ /dev/null @@ -1,63 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessIVYZ18HYRequest IVYZ18HY 婚姻状况核验V2(单人) API 处理方法(使用数据宝服务示例) -func ProcessIVYZ18HYRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ18HYReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - fixedData := map[string]interface{}{"msg": "请联系商务咨询"} - fixedRespBytes, err := json.Marshal(fixedData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return fixedRespBytes, nil - - authDate := "" - if len(paramsDto.AuthDate) >= 8 { - authDate = paramsDto.AuthDate[len(paramsDto.AuthDate)-8:] - } - reqParams := map[string]interface{}{ - "key": "", - "idcard": paramsDto.IDCard, - "name": paramsDto.Name, - "maritalType": paramsDto.MaritalType, - "authcode": paramsDto.AuthAuthorizeFileBase64, - "authAuthorizeFileCode": paramsDto.AuthAuthorizeFileCode, - "authDate": authDate, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10333" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz1c9d_processor.go b/internal/domains/api/services/processors/ivyz/ivyz1c9d_processor.go deleted file mode 100644 index 9aa4652..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz1c9d_processor.go +++ /dev/null @@ -1,52 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessIVYZ1C9DRequest IVYZ1C9D API处理方法 -func ProcessIVYZ1C9DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ1C9DReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "xm": encryptedName, - "sfzh": encryptedIDCard, - "yearNum": paramsDto.Years, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G38SC02", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz1j7h_processor.go b/internal/domains/api/services/processors/ivyz/ivyz1j7h_processor.go deleted file mode 100644 index 76af6ab..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz1j7h_processor.go +++ /dev/null @@ -1,46 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessIVYZ1J7HRequest IVYZ1J7H API处理方法 - 行驶证核查v2 -func ProcessIVYZ1J7HRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ1J7HReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "plate": paramsDto.PlateNo, - "plateType": paramsDto.CarPlateType, - "name": paramsDto.Name, - } - - // 调用极光API - respBytes, err := deps.JiguangService.CallAPI(ctx, "vehicle-driving-license-v2", "vehicle/driving-license-v2", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz2125_processor.go b/internal/domains/api/services/processors/ivyz/ivyz2125_processor.go deleted file mode 100644 index 102f41b..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz2125_processor.go +++ /dev/null @@ -1,38 +0,0 @@ -package ivyz - -import ( - "context" - "errors" - - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessIVYZ2125Request IVYZ2125 API处理方法 -func ProcessIVYZ2125Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - return nil, errors.Join(processors.ErrSystem, errors.New("服务已停用")) - // var paramsDto dto.IVYZ2125Req - // if err := json.Unmarshal(params, ¶msDto); err != nil { - // return nil, errors.Join(processors.ErrSystem, err) - // } - - // if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - // return nil, errors.Join(processors.ErrInvalidParam, err) - // } - - // reqData := map[string]interface{}{ - // "name": paramsDto.Name, - // "idCard": paramsDto.IDCard, - // "mobile": paramsDto.Mobile, - // } - - // respBytes, err := deps.WestDexService.CallAPI(ctx, "IVYZ2125", reqData) - // if err != nil { - // if errors.Is(err, westdex.ErrDatasource) { - // return nil, errors.Join(processors.ErrDatasource, err) - // } else { - // return nil, errors.Join(processors.ErrSystem, err) - // } - // } - - // return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz28hy_processor.go b/internal/domains/api/services/processors/ivyz/ivyz28hy_processor.go deleted file mode 100644 index 9634274..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz28hy_processor.go +++ /dev/null @@ -1,54 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessIVYZ28HYRequest IVYZ28HY 婚姻状况核验单人) API 处理方法(使用数据宝服务示例) -func ProcessIVYZ28HYRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ28HYReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - fixedData := map[string]interface{}{"msg": "请联系商务咨询"} - fixedRespBytes, err := json.Marshal(fixedData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return fixedRespBytes, nil - - reqParams := map[string]interface{}{ - "key": "", - "idcard": paramsDto.IDCard, - "name": paramsDto.Name, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10149" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz2a8b_processor.go b/internal/domains/api/services/processors/ivyz/ivyz2a8b_processor.go deleted file mode 100644 index 8b69c02..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz2a8b_processor.go +++ /dev/null @@ -1,161 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - "strconv" - "strings" - "time" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ivyz2a8bShumaiResp 数脉 /v4/id_card/check 返回格式 -type ivyz2a8bShumaiResp struct { - Result float64 `json:"result"` - OrderNo string `json:"order_no"` - Desc string `json:"desc"` - Sex string `json:"sex"` - Birthday string `json:"birthday"` // yyyyMMdd - Address string `json:"address"` -} - -// ProcessIVYZ2A8BRequest IVYZ2A8B API处理方法 - 身份二要素认证政务版 数脉内部替换 -func ProcessIVYZ2A8BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ2A8BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "idcard": paramsDto.IDCard, - "name": paramsDto.Name, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/id_card/check" // 接口路径,根据数脉文档填写(如 v4/xxx) - - // 先尝试使用政务接口(app_id2 和 app_secret2) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true) - if err != nil { - // 使用实时接口(app_id 和 app_secret)重试 - respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false) - // 如果重试后仍然失败,或者原本就是查无记录错误,返回错误 - if err != nil { - if errors.Is(err, shumai.ErrNotFound) { - // 查无记录情况 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - } - - // 将数脉返回的新格式映射为原有 API 输出格式 - oldFormat, err := mapIVYZ2A8BShumaiToOld(respBytes) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return json.Marshal(oldFormat) -} - -func mapIVYZ2A8BShumaiToOld(respBytes []byte) (map[string]interface{}, error) { - var r ivyz2a8bShumaiResp - if err := json.Unmarshal(respBytes, &r); err != nil { - return nil, err - } - // final_auth_result: "0"=一致,"1"=不一致/无记录;按 result:0-一致,1-不一致,2-无记录(预留) - finalAuth := "1" - switch int(r.Result) { - case 0: - finalAuth = "0" - } - return map[string]interface{}{ - "final_auth_result": finalAuth, - "birthday": formatBirthdayOld(r.Birthday), - "address": r.Address, - "constellation": constellationFromBirthday(r.Birthday), - "gender": r.Sex, - "age": ageFromBirthday(r.Birthday), - }, nil -} - -func formatBirthdayOld(s string) string { - s = strings.TrimSpace(s) - if len(s) != 8 { - return s - } - for _, c := range s { - if c < '0' || c > '9' { - return s - } - } - return s[0:4] + "年" + s[4:6] + "月" + s[6:8] + "日" -} - -func constellationFromBirthday(s string) string { - if len(s) != 8 { - return "" - } - month, _ := strconv.Atoi(s[4:6]) - day, _ := strconv.Atoi(s[6:8]) - if month < 1 || month > 12 || day < 1 || day > 31 { - return "" - } - switch { - case (month == 12 && day >= 22) || (month == 1 && day <= 19): - return "魔羯座" - case (month == 1 && day >= 20) || (month == 2 && day <= 18): - return "水瓶座" - case (month == 2 && day >= 19) || (month == 3 && day <= 20): - return "双鱼座" - case (month == 3 && day >= 21) || (month == 4 && day <= 19): - return "白羊座" - case (month == 4 && day >= 20) || (month == 5 && day <= 20): - return "金牛座" - case (month == 5 && day >= 21) || (month == 6 && day <= 21): - return "双子座" - case (month == 6 && day >= 22) || (month == 7 && day <= 22): - return "巨蟹座" - case (month == 7 && day >= 23) || (month == 8 && day <= 22): - return "狮子座" - case (month == 8 && day >= 23) || (month == 9 && day <= 22): - return "处女座" - case (month == 9 && day >= 23) || (month == 10 && day <= 23): - return "天秤座" - case (month == 10 && day >= 24) || (month == 11 && day <= 22): - return "天蝎座" - case (month == 11 && day >= 23) || (month == 12 && day <= 21): - return "射手座" - default: - return "魔羯座" - } -} - -func ageFromBirthday(s string) string { - if len(s) < 4 { - return "" - } - y, err := strconv.Atoi(s[0:4]) - if err != nil || y <= 0 { - return "" - } - age := time.Now().Year() - y - if age < 0 { - age = 0 - } - return strconv.Itoa(age) -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz2b2t_processor.go b/internal/domains/api/services/processors/ivyz/ivyz2b2t_processor.go deleted file mode 100644 index c8fcda1..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz2b2t_processor.go +++ /dev/null @@ -1,58 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - "strconv" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessIVYZ2B2TRequest IVYZ2B2T API处理方法 能力资质核验(学历) -func ProcessIVYZ2B2TRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - - var paramsDto dto.IVYZ2B2TReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - encryptedQueryReasonId, err := deps.WestDexService.Encrypt(strconv.FormatInt(paramsDto.QueryReasonId, 10)) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "idCard": encryptedIDCard, - "name": encryptedName, - "queryReasonId": encryptedQueryReasonId, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G11JX01", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz2c1p_processor.go b/internal/domains/api/services/processors/ivyz/ivyz2c1p_processor.go deleted file mode 100644 index 77baea9..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz2c1p_processor.go +++ /dev/null @@ -1,56 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessIVYZ2C1PRequest IVYZ2C1P API处理方法 - 风控黑名单 -func ProcessIVYZ2C1PRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ2C1PReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI037", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz2mn6_processor.go b/internal/domains/api/services/processors/ivyz/ivyz2mn6_processor.go deleted file mode 100644 index 55154fb..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz2mn6_processor.go +++ /dev/null @@ -1,54 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessIVYZ2MN6Request IVYZ2MN6 API处理方法 -func ProcessIVYZ2MN6Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ2MN6Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI1004", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz385e_processor.go b/internal/domains/api/services/processors/ivyz/ivyz385e_processor.go deleted file mode 100644 index 39568a4..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz385e_processor.go +++ /dev/null @@ -1,49 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessIVYZ385ERequest IVYZ385E API处理方法 -func ProcessIVYZ385ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ385EReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "xm": encryptedName, - "gmsfzhm": encryptedIDCard, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "WEST00020", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz38sr_processor.go b/internal/domains/api/services/processors/ivyz/ivyz38sr_processor.go deleted file mode 100644 index 2502b21..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz38sr_processor.go +++ /dev/null @@ -1,56 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessIVYZ38SRRequest IVYZ38SR 婚姻状态核验(双人) API 处理方法(使用数据宝服务示例) -func ProcessIVYZ38SRRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ38SRReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - fixedData := map[string]interface{}{"msg": "请联系商务咨询"} - fixedRespBytes, err := json.Marshal(fixedData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return fixedRespBytes, nil - - reqParams := map[string]interface{}{ - "key": "", - "name": paramsDto.ManName, - "idcard": paramsDto.ManIDCard, - "woman_name": paramsDto.WomanName, - "woman_idcard": paramsDto.WomanIDCard, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10148" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz3a7f_processor.go b/internal/domains/api/services/processors/ivyz/ivyz3a7f_processor.go deleted file mode 100644 index c160a9c..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz3a7f_processor.go +++ /dev/null @@ -1,50 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessIVYZ3A7FRequest IVYZ3A7F API处理方法 - 行为数据查询 -func ProcessIVYZ3A7FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ3A7FReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,使用xingwei服务的正确字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1104648854749245440" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - // 查空情况,返回特定的查空错误 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz3p9m_processor copy.go b/internal/domains/api/services/processors/ivyz/ivyz3p9m_processor copy.go deleted file mode 100644 index 88c2fa3..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz3p9m_processor copy.go +++ /dev/null @@ -1,64 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/muzi" -) - -// ProcessIVYZ3P9MRequest IVYZ3P9M API处理方法 - 学历查询实时版 -func ProcessIVYZ3P9MRequest_2(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ3P9MReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.MuziService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedCertCode, err := deps.MuziService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // 处理 returnType 参数,默认为 "1" - returnType := paramsDto.ReturnType - if returnType == "" { - returnType = "1" - } - paramSign := map[string]interface{}{ - "returnType": returnType, - "realName": encryptedName, - "certCode": encryptedCertCode, - } - - reqData := map[string]interface{}{ - "realName": encryptedName, - "certCode": encryptedCertCode, - "returnType": returnType, - } - - respData, err := deps.MuziService.CallAPI(ctx, "PC0041", "/academic", reqData, paramSign) - if err != nil { - switch { - case errors.Is(err, muzi.ErrDatasource): - return nil, errors.Join(processors.ErrDatasource, err) - case errors.Is(err, muzi.ErrSystem): - return nil, errors.Join(processors.ErrSystem, err) - default: - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respData, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz3p9m_processor.go b/internal/domains/api/services/processors/ivyz/ivyz3p9m_processor.go deleted file mode 100644 index eed931e..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz3p9m_processor.go +++ /dev/null @@ -1,168 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - "strings" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessIVYZ3P9MRequest IVYZ3P9M API处理方法 - 学历查询实时版 -func ProcessIVYZ3P9MRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ3P9MReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "authorized": "1", - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI1004", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - out, err := mapZCI1004ToIVYZ3P9M(respData, paramsDto.Name, paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return json.Marshal(out) -} - -type zci1004Item struct { - EndDate string `json:"endDate"` - EducationLevel string `json:"educationLevel"` - LearningForm string `json:"learningForm"` -} - -type ivyz3p9mItem struct { - GraduationDate string `json:"graduationDate"` - StudentName string `json:"studentName"` - EducationLevel string `json:"educationLevel"` - LearningForm string `json:"learningForm"` - IDNumber string `json:"idNumber"` -} - -func mapZCI1004ToIVYZ3P9M(respData interface{}, name, idCard string) ([]ivyz3p9mItem, error) { - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, err - } - - var source []zci1004Item - if err := json.Unmarshal(respBytes, &source); err != nil { - var wrapped struct { - Data []zci1004Item `json:"data"` - } - if err2 := json.Unmarshal(respBytes, &wrapped); err2 != nil { - return nil, err - } - source = wrapped.Data - } - - out := make([]ivyz3p9mItem, 0, len(source)) - for _, it := range source { - out = append(out, ivyz3p9mItem{ - GraduationDate: normalizeDateDigits(it.EndDate), - StudentName: name, - EducationLevel: mapEducationLevelToCode(it.EducationLevel), - LearningForm: mapLearningFormToCode(it.LearningForm), - IDNumber: idCard, - }) - } - - return out, nil -} - -func mapEducationLevelToCode(level string) string { - v := normalizeText(level) - switch { - case strings.Contains(v, "第二学士"): - return "5" - case strings.Contains(v, "博士"): - return "4" - case strings.Contains(v, "硕士"): - return "3" - case strings.Contains(v, "本科"): - return "2" - case strings.Contains(v, "专科"), strings.Contains(v, "大专"): - return "1" - default: - return "99" - } -} - -func mapLearningFormToCode(form string) string { - v := normalizeText(form) - switch { - case strings.Contains(v, "脱产"): - return "1" - case strings.Contains(v, "普通全日制"): - return "2" - case strings.Contains(v, "全日制"): - return "3" - case strings.Contains(v, "开放教育"), strings.Contains(v, "开放大学"): - return "4" - case strings.Contains(v, "夜大学"), strings.Contains(v, "夜大"): - return "5" - case strings.Contains(v, "函授"): - return "6" - case strings.Contains(v, "网络教育"), strings.Contains(v, "网教"), strings.Contains(v, "远程教育"): - return "7" - case strings.Contains(v, "非全日制"): - return "8" - case strings.Contains(v, "业余"): - return "9" - case strings.Contains(v, "自学考试"), strings.Contains(v, "自考"): - // 自考在既有枚举中无直对应,兼容并入“业余” - return "9" - default: - return "99" - } -} - -func normalizeDateDigits(s string) string { - trimmed := strings.TrimSpace(s) - if trimmed == "" { - return "" - } - var b strings.Builder - for _, ch := range trimmed { - if ch >= '0' && ch <= '9' { - b.WriteRune(ch) - } - } - return b.String() -} - -func normalizeText(s string) string { - v := strings.TrimSpace(strings.ToLower(s)) - v = strings.ReplaceAll(v, " ", "") - v = strings.ReplaceAll(v, "-", "") - v = strings.ReplaceAll(v, "_", "") - return v -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz48sr_processor.go b/internal/domains/api/services/processors/ivyz/ivyz48sr_processor.go deleted file mode 100644 index 9167c3e..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz48sr_processor.go +++ /dev/null @@ -1,58 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessIVYZ48SRRequest IVYZ48SR 婚姻状态核验V2(双人) API 处理方法(使用数据宝服务示例) -func ProcessIVYZ48SRRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ48SRReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - fixedData := map[string]interface{}{"msg": "请联系商务咨询"} - fixedRespBytes, err := json.Marshal(fixedData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return fixedRespBytes, nil - - reqParams := map[string]interface{}{ - "key": "", - "name": paramsDto.ManName, - "idcard": paramsDto.ManIDCard, - "woman_name": paramsDto.WomanName, - "woman_idcard": paramsDto.WomanIDCard, - "marital_type": paramsDto.MaritalType, - "auth_authorize_file_code": paramsDto.AuthAuthorizeFileCode, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10332" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz4e8b_processor.go b/internal/domains/api/services/processors/ivyz/ivyz4e8b_processor.go deleted file mode 100644 index 0937525..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz4e8b_processor.go +++ /dev/null @@ -1,84 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - "fmt" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" - - "github.com/tidwall/gjson" -) - -// ProcessIVYZ4E8BRequest IVYZ4E8B API处理方法 -func ProcessIVYZ4E8BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ4E8BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "idNo": encryptedIDCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G09GZ02", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 解析响应,提取data字段中的hyzk - var respMap map[string]interface{} - if err := json.Unmarshal(respBytes, &respMap); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - dataStr, ok := respMap["data"].(string) - if !ok { - return nil, fmt.Errorf("%s: data字段格式错误", processors.ErrDatasource) - } - - // 使用gjson解析data字符串 - hyzk := "" - { - result := gjson.Get(dataStr, "hyzk") - if !result.Exists() { - return nil, fmt.Errorf("%s: data中缺少hyzk字段", processors.ErrDatasource) - } - hyzk = result.String() - } - - // 返回格式为 {"status": hyzk} - resp := map[string]interface{}{ - "status": hyzk, - } - finalBytes, err := json.Marshal(resp) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return finalBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz5733_processor.go b/internal/domains/api/services/processors/ivyz/ivyz5733_processor.go deleted file mode 100644 index db6988d..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz5733_processor.go +++ /dev/null @@ -1,83 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessIVYZ5733Request IVYZ5733 API处理方法 -func ProcessIVYZ5733Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ5733Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "idNo": encryptedIDCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G09GZ02", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 解析新源响应数据 - var newResp struct { - Status string `json:"status"` - } - if err := json.Unmarshal(respBytes, &newResp); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // 转换状态码 - var statusCode string - switch newResp.Status { - case "结婚": - statusCode = "IA" - case "离婚": - statusCode = "IB" - case "未查得": - statusCode = "INR" - default: - statusCode = "INR" - } - - // 构建旧格式响应 - oldResp := map[string]interface{}{ - "code": "0", - "data": map[string]interface{}{ - "data": statusCode + ":匹配不成功", - }, - "seqNo": "", - "message": "成功", - } - - // 返回旧格式响应 - return json.Marshal(oldResp) -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz5a9o_processor.go b/internal/domains/api/services/processors/ivyz/ivyz5a9o_processor.go deleted file mode 100644 index a5e65fd..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz5a9o_processor.go +++ /dev/null @@ -1,57 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessIVYZ5A9ORequest IVYZ5A9O API处理方法 全国⾃然⼈⻛险评估评分模型 -func ProcessIVYZ5A9ORequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - - var paramsDto dto.IVYZ5A9OReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - encryptedAuthAuthorizeFileCode, err := deps.WestDexService.Encrypt(paramsDto.AuthAuthorizeFileCode) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "idcard": encryptedIDCard, - "name": encryptedName, - "auth_authorizeFileCode": encryptedAuthAuthorizeFileCode, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G01SC01", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz5e22_processor.go b/internal/domains/api/services/processors/ivyz/ivyz5e22_processor.go deleted file mode 100644 index 5c758c1..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz5e22_processor.go +++ /dev/null @@ -1,66 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessIVYZ5E22Request API处理方法 - 双人婚姻评估查询 -func ProcessIVYZ5E22Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ5E22Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedManName, err := deps.ZhichaService.Encrypt(paramsDto.ManName) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedManIDCard, err := deps.ZhichaService.Encrypt(paramsDto.ManIDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - encryptedWomanName, err := deps.ZhichaService.Encrypt(paramsDto.WomanName) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - encryptedWomanIDCard, err := deps.ZhichaService.Encrypt(paramsDto.WomanIDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "nameMan": encryptedManName, - "idCardMan": encryptedManIDCard, - "nameWoman": encryptedWomanName, - "idCardWoman": encryptedWomanIDCard, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI042", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz5e3f_processor.go b/internal/domains/api/services/processors/ivyz/ivyz5e3f_processor.go deleted file mode 100644 index 5759d58..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz5e3f_processor.go +++ /dev/null @@ -1,56 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessIVYZ5E3FRequest IVYZ5E3F API处理方法 - 婚姻评估查询 -func ProcessIVYZ5E3FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ5E3FReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI029", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz6g7h_processor.go b/internal/domains/api/services/processors/ivyz/ivyz6g7h_processor.go deleted file mode 100644 index 64f9b64..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz6g7h_processor.go +++ /dev/null @@ -1,46 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessIVYZ6G7HRequest IVYZ6G7H API处理方法 - 个人婚姻状况查询v2 -func ProcessIVYZ6G7HRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ6G7HReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1104646268587536384" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz6m8p_processor.go b/internal/domains/api/services/processors/ivyz/ivyz6m8p_processor.go deleted file mode 100644 index 07a6693..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz6m8p_processor.go +++ /dev/null @@ -1,46 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessIVYZ6M8PRequest IVYZ6M8P 职业资格证书API处理方法 -func ProcessIVYZ6M8PRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ6M8PReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1147725836315455488" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyzvjj6_processor.go b/internal/domains/api/services/processors/ivyz/ivyz6w0u_processor.go similarity index 88% rename from internal/domains/api/services/processors/ivyz/ivyzvjj6_processor.go rename to internal/domains/api/services/processors/ivyz/ivyz6w0u_processor.go index c5f8949..804ec84 100644 --- a/internal/domains/api/services/processors/ivyz/ivyzvjj6_processor.go +++ b/internal/domains/api/services/processors/ivyz/ivyz6w0u_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessIVYZVJJ6Request IVYZVJJ6 API处理方法 -收入等级tax_income_level_v8 -func ProcessIVYZVJJ6Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZVJJ6Req +// ProcessIVYZ6W0URequest IVYZVJJ6 API处理方法 -收入等级tax_income_level_v8 +func ProcessIVYZ6W0URequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZ6W0UReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/ivyz/ivyz7c9d_processor.go b/internal/domains/api/services/processors/ivyz/ivyz7c9d_processor.go deleted file mode 100644 index 4ad6651..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz7c9d_processor.go +++ /dev/null @@ -1,47 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessIVYZ7C9DRequest IVYZ7C9D API处理方法 - 人脸识别 -func ProcessIVYZ7C9DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ7C9DReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCard": paramsDto.IDCard, - "returnUrl": paramsDto.ReturnURL, - "orderId": paramsDto.UniqueID, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI013", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz7f2a_processor.go b/internal/domains/api/services/processors/ivyz/ivyz7f2a_processor.go deleted file mode 100644 index ad70fe2..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz7f2a_processor.go +++ /dev/null @@ -1,95 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - "fmt" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" - - "github.com/tidwall/gjson" -) - -// ProcessIVYZ7F2ARequest IVYZ7F2A API处理方法 -func ProcessIVYZ7F2ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ7F2AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedManName, err := deps.WestDexService.Encrypt(paramsDto.ManName) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedManIDCard, err := deps.WestDexService.Encrypt(paramsDto.ManIDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedWomanName, err := deps.WestDexService.Encrypt(paramsDto.WomanName) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedWomanIDCard, err := deps.WestDexService.Encrypt(paramsDto.WomanIDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "manName": encryptedManName, - "manIdcard": encryptedManIDCard, - "womanName": encryptedWomanName, - "womanIdcard": encryptedWomanIDCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G10GZ02", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - var respMap map[string]interface{} - if err := json.Unmarshal(respBytes, &respMap); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - dataStr, ok := respMap["data"].(string) - if !ok { - return nil, fmt.Errorf("%s: data字段格式错误", processors.ErrDatasource) - } - - // 使用gjson解析data字符串 - hyzk := "" - { - result := gjson.Get(dataStr, "hyzk") - if !result.Exists() { - return nil, fmt.Errorf("%s: data中缺少hyzk字段", processors.ErrDatasource) - } - hyzk = result.String() - } - - // 返回格式为 {"status": hyzk} - resp := map[string]interface{}{ - "status": hyzk, - } - finalBytes, err := json.Marshal(resp) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return finalBytes, nil - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz7f3a_processor.go b/internal/domains/api/services/processors/ivyz/ivyz7f3a_processor.go deleted file mode 100644 index 4dd22a9..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz7f3a_processor.go +++ /dev/null @@ -1,56 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessIVYZ7F3ARequest IVYZ7F3A API处理方法 - 学历信息查询B -func ProcessIVYZ7F3ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ7F3AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI035", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz81nc_processor.go b/internal/domains/api/services/processors/ivyz/ivyz81nc_processor.go deleted file mode 100644 index 78eef02..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz81nc_processor.go +++ /dev/null @@ -1,96 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessIVYZ81NCRequest IVYZ81NC API处理方法 -func ProcessIVYZ81NCRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ81NCReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "authorized": "1", // 默认值 - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI029", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 解析响应数据,期望格式为 {"state": "1"} - var stateResp struct { - State string `json:"state"` - RegTime string `json:"regTime"` - } - - // 将 respData 转换为 JSON 字节再解析 - respDataBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := json.Unmarshal(respDataBytes, &stateResp); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // 根据 state 值转换为 81nc 格式 - var opType, opTypeDesc string - switch stateResp.State { - case "1": // 已婚 - opType = "IA" - opTypeDesc = "结婚" - case "2": // 未婚/未在民政局登记 - opType = "INR" - opTypeDesc = "匹配不成功" - case "3": // 离异 - opType = "IB" - opTypeDesc = "离婚" - default: - opType = "INR" - opTypeDesc = "匹配不成功" - } - - // 构建 81nc 格式响应 - result := map[string]interface{}{ - "code": "0", - "data": map[string]interface{}{ - "op_date": stateResp.RegTime, - "op_type": opType, - "op_type_desc": opTypeDesc, - }, - "message": "成功", - "seqNo": "", - } - - // 返回 81nc 格式响应 - return json.Marshal(result) -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz8i9j_processor.go b/internal/domains/api/services/processors/ivyz/ivyz8i9j_processor.go deleted file mode 100644 index d1a816c..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz8i9j_processor.go +++ /dev/null @@ -1,47 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessIVYZ8I9JRequest IVYZ8I9J API处理方法 - 互联网行为推测 -func ProcessIVYZ8I9JRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ8I9JReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "phoneNumber": paramsDto.MobileNo, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1074522823015198720" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz9363_processor.go b/internal/domains/api/services/processors/ivyz/ivyz9363_processor.go deleted file mode 100644 index 123a42e..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz9363_processor.go +++ /dev/null @@ -1,68 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - "strings" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessIVYZ9363Request IVYZ9363 API处理方法 -func ProcessIVYZ9363Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ9363Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - // 新增:身份证一致性校验 - if strings.EqualFold(strings.TrimSpace(paramsDto.ManIDCard), strings.TrimSpace(paramsDto.WomanIDCard)) { - return nil, errors.Join(processors.ErrInvalidParam, errors.New("请正确填写身份信息")) - } - - encryptedManName, err := deps.WestDexService.Encrypt(paramsDto.ManName) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedManIDCard, err := deps.WestDexService.Encrypt(paramsDto.ManIDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedWomanName, err := deps.WestDexService.Encrypt(paramsDto.WomanName) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedWomanIDCard, err := deps.WestDexService.Encrypt(paramsDto.WomanIDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name_man": encryptedManName, - "idcard_man": encryptedManIDCard, - "name_woman": encryptedWomanName, - "idcard_woman": encryptedWomanIDCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G10XM02", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz9a2b_processor.go b/internal/domains/api/services/processors/ivyz/ivyz9a2b_processor.go deleted file mode 100644 index 515ab34..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz9a2b_processor.go +++ /dev/null @@ -1,51 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessIVYZ9A2BRequest IVYZ9A2B API处理方法 -func ProcessIVYZ9A2BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ9A2BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name_value": encryptedName, - "id_card_value": encryptedIDCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G11BJ06", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz9d2e_processor.go b/internal/domains/api/services/processors/ivyz/ivyz9d2e_processor.go deleted file mode 100644 index 6351949..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz9d2e_processor.go +++ /dev/null @@ -1,51 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessIVYZ9D2ERequest IVYZ9D2E API处理方法 - 行为数据查询 -func ProcessIVYZ9D2ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ9D2EReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,使用xingwei服务的正确字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "scenario": paramsDto.UseScenario, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1104648845446279168" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - // 查空情况,返回特定的查空错误 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz9h2m_processor.go b/internal/domains/api/services/processors/ivyz/ivyz9h2m_processor.go deleted file mode 100644 index 8f72f2b..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz9h2m_processor.go +++ /dev/null @@ -1,47 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessIVYZ9H2MRequest IVYZ9H2M API处理方法 - 极光个人婚姻查询(V2版) -func ProcessIVYZ9H2MRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ9H2MReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "id_no": paramsDto.IDCard, - "name": paramsDto.Name, - } - - // 调用极光API - // apiCode: marriage-single-v2 (用于请求头) - // apiPath: marriage/single-v2 (用于URL路径) - respBytes, err := deps.JiguangService.CallAPI(ctx, "marriage-single-v2", "marriage/single-v2", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz9k2l_processor.go b/internal/domains/api/services/processors/ivyz/ivyz9k2l_processor.go deleted file mode 100644 index 033d19a..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz9k2l_processor.go +++ /dev/null @@ -1,103 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - "strconv" - "time" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" - - "github.com/tidwall/gjson" -) - -// ProcessIVYZ9K2LRequest IVYZ9K2L API处理方法 - 身份认证三要素(人脸图像版) -func ProcessIVYZ9K2LRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ9K2LReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 加密姓名 - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // 加密身份证号 - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // 生成时间戳(毫秒) - timestamp := strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10) - - // 获取自定义编号(从 WestDexService 配置中获取 secret_id) - config := deps.WestDexService.GetConfig() - customNumber := config.SecretID - - // 构建请求数据 - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "timeStamp": timestamp, - "customNumber": customNumber, - "xM": encryptedName, - "gMSFZHM": encryptedIDCard, - "photoData": paramsDto.PhotoData, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "idCardThreeElements", reqData) - if err != nil { - switch { - case errors.Is(err, westdex.ErrDatasource): - return nil, errors.Join(processors.ErrDatasource, err) - case errors.Is(err, westdex.ErrSystem): - return nil, errors.Join(processors.ErrSystem, err) - default: - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 使用gjson提取authResult字段 - // 尝试多个可能的路径 - var authResult string - paths := []string{ - "WEST00037.WEST00038.authResult", - "WEST00036.WEST00037.WEST00038.authResult", - "authResult", - } - - for _, path := range paths { - result := gjson.GetBytes(respBytes, path) - if result.Exists() { - authResult = result.String() - break - } - } - - // 如果找不到authResult,返回ErrDatasource - if authResult == "" { - return nil, errors.Join(processors.ErrDatasource, errors.New("响应中未找到authResult字段")) - } - - // 构建返回格式 {result: XXXX} - response := map[string]interface{}{ - "result": authResult, - } - - responseBytes, err := json.Marshal(response) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return responseBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz9k7f_processor.go b/internal/domains/api/services/processors/ivyz/ivyz9k7f_processor.go deleted file mode 100644 index 50c6b6a..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyz9k7f_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessIVYZ9K7FRequest IVYZ9K7F 身份证实名认证即时版 API处理方法 -func ProcessIVYZ9K7FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ9K7FReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "idcard": paramsDto.IDCard, - "name": paramsDto.Name, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/id_card/check" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrNotFound) { - // 查无记录情况 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyz9ohn_processor.go b/internal/domains/api/services/processors/ivyz/ivyz9ohn_processor.go new file mode 100644 index 0000000..9a254ae --- /dev/null +++ b/internal/domains/api/services/processors/ivyz/ivyz9ohn_processor.go @@ -0,0 +1,14 @@ +package ivyz + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessIVYZ9OHNRequest IVYZOCR1 身份证OCR(天远中转) +func ProcessIVYZ9OHNRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZ9OHNReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "IVYZOCR1", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/ivyz/ivyza1b3_processor.go b/internal/domains/api/services/processors/ivyz/ivyza1b3_processor.go deleted file mode 100644 index c320552..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyza1b3_processor.go +++ /dev/null @@ -1,49 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessIVYZA1B3Request IVYZA1B3 公安三要素人脸识别API处理方法 -func ProcessIVYZA1B3Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZA1B3Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "idcard": paramsDto.IDCard, - "name": paramsDto.Name, - "image": paramsDto.PhotoData, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/face_id_card/compare" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrNotFound) { - // 查无记录情况 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyzadee_processor.go b/internal/domains/api/services/processors/ivyz/ivyzadee_processor.go deleted file mode 100644 index 7c4ab98..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyzadee_processor.go +++ /dev/null @@ -1,38 +0,0 @@ -package ivyz - -import ( - "context" - "errors" - - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessIVYZADEERequest IVYZADEE API处理方法 -func ProcessIVYZADEERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - return nil, errors.Join(processors.ErrSystem, errors.New("服务已停用")) - // var paramsDto dto.IVYZADEEReq - // if err := json.Unmarshal(params, ¶msDto); err != nil { - // return nil, errors.Join(processors.ErrSystem, err) - // } - - // if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - // return nil, errors.Join(processors.ErrInvalidParam, err) - // } - - // reqData := map[string]interface{}{ - // "name": paramsDto.Name, - // "idCard": paramsDto.IDCard, - // "mobile": paramsDto.Mobile, - // } - - // respBytes, err := deps.WestDexService.CallAPI(ctx, "IVYZADEE", reqData) - // if err != nil { - // if errors.Is(err, westdex.ErrDatasource) { - // return nil, errors.Join(processors.ErrDatasource, err) - // } else { - // return nil, errors.Join(processors.ErrSystem, err) - // } - // } - - // return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyzvxf6_processor.go b/internal/domains/api/services/processors/ivyz/ivyzbi6f_processor.go similarity index 88% rename from internal/domains/api/services/processors/ivyz/ivyzvxf6_processor.go rename to internal/domains/api/services/processors/ivyz/ivyzbi6f_processor.go index cfbcd2b..0207276 100644 --- a/internal/domains/api/services/processors/ivyz/ivyzvxf6_processor.go +++ b/internal/domains/api/services/processors/ivyz/ivyzbi6f_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessIVYZVXF6Request IVYZVXF6 API处理方法 -消费能力 -func ProcessIVYZVXF6Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZVXF6Req +// ProcessIVYZBI6FRequest IVYZVXF6 API处理方法 -消费能力 +func ProcessIVYZBI6FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZBI6FReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/ivyz/ivyzbpq2_processor.go b/internal/domains/api/services/processors/ivyz/ivyzbpq2_processor.go deleted file mode 100644 index a2e7716..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyzbpq2_processor.go +++ /dev/null @@ -1,51 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessIVYZBPQ2Request IVYZBPQ2 人脸比对V2API处理方法 -func ProcessIVYZBPQ2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZBPQ2Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,使用xingwei服务的正确字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "image": paramsDto.PhotoData, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1104321425593790464" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - // 查空情况,返回特定的查空错误 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyzdxmd_processor.go b/internal/domains/api/services/processors/ivyz/ivyzdxmd_processor.go new file mode 100644 index 0000000..b4127a6 --- /dev/null +++ b/internal/domains/api/services/processors/ivyz/ivyzdxmd_processor.go @@ -0,0 +1,29 @@ +package ivyz + +import ( + "context" + "encoding/json" + "errors" + "strings" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessIVYZDXMDRequest IVYZFIC1 人脸身份证比对 API 处理方法 +func ProcessIVYZDXMDRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZDXMDReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + if strings.TrimSpace(paramsDto.PhotoData) == "" && strings.TrimSpace(paramsDto.ImageUrl) == "" { + return nil, errors.Join(processors.ErrInvalidParam, errors.New("image和url至少传一个")) + } + + return processors.CallTianyuanByProduct(ctx, deps, "IVYZFIC1", params) +} diff --git a/internal/domains/api/services/processors/ivyz/ivyze42i_processor.go b/internal/domains/api/services/processors/ivyz/ivyze42i_processor.go new file mode 100644 index 0000000..a6451cc --- /dev/null +++ b/internal/domains/api/services/processors/ivyz/ivyze42i_processor.go @@ -0,0 +1,24 @@ +package ivyz + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessIVYZE42IRequest IVYZA1B3 公安三要素人脸识别API处理方法 +func ProcessIVYZE42IRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZE42IReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "IVYZA1B3", params) +} diff --git a/internal/domains/api/services/processors/ivyz/ivyzfic1_processor.go b/internal/domains/api/services/processors/ivyz/ivyzfic1_processor.go deleted file mode 100644 index 5fca267..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyzfic1_processor.go +++ /dev/null @@ -1,55 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - "strings" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessIVYZFIC1Request IVYZFIC1 人脸身份证比对 API 处理方法(数脉) -func ProcessIVYZFIC1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZFIC1Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - if strings.TrimSpace(paramsDto.PhotoData) == "" && strings.TrimSpace(paramsDto.ImageUrl) == "" { - return nil, errors.Join(processors.ErrInvalidParam, errors.New("image和url至少传一个")) - } - - reqFormData := map[string]interface{}{ - "idcard": paramsDto.IDCard, - "name": paramsDto.Name, - "image": paramsDto.PhotoData, - "url": paramsDto.ImageUrl, - } - - apiPath := "/v4/face_id_card/compare" - - // 先尝试政务接口,再回退实时接口 - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true) - if err != nil { - respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false) - if err != nil { - if errors.Is(err, shumai.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, shumai.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyzfo5k_processor.go b/internal/domains/api/services/processors/ivyz/ivyzfo5k_processor.go new file mode 100644 index 0000000..fd50420 --- /dev/null +++ b/internal/domains/api/services/processors/ivyz/ivyzfo5k_processor.go @@ -0,0 +1,24 @@ +package ivyz + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessIVYZFO5KRequest IVYZN2P8 身份证实名认证政务版 API处理方法 +func ProcessIVYZFO5KRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZSQ0EReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "IVYZN2P8", params) +} diff --git a/internal/domains/api/services/processors/ivyz/ivyzgz08_processor.go b/internal/domains/api/services/processors/ivyz/ivyzgz08_processor.go deleted file mode 100644 index 97c4bd3..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyzgz08_processor.go +++ /dev/null @@ -1,51 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessIVYZGZ08Request IVYZGZ08 API处理方法 -func ProcessIVYZGZ08Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZGZ08Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "xm": encryptedName, - "gmsfzhm": encryptedIDCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G08SC02", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyzkj31_processor.go b/internal/domains/api/services/processors/ivyz/ivyzkj31_processor.go new file mode 100644 index 0000000..0e2d195 --- /dev/null +++ b/internal/domains/api/services/processors/ivyz/ivyzkj31_processor.go @@ -0,0 +1,24 @@ +package ivyz + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessIVYZKJ31Request IVYZX5Q2 活体识别步骤二API处理方法 +func ProcessIVYZKJ31Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZKJ31Req + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "IVYZX5Q2", params) +} diff --git a/internal/domains/api/services/processors/ivyz/ivyzn2p8_processor.go b/internal/domains/api/services/processors/ivyz/ivyzn2p8_processor.go deleted file mode 100644 index 83eddc4..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyzn2p8_processor.go +++ /dev/null @@ -1,121 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessIVYZN2P8Request IVYZN2P8 身份证实名认证政务版 API处理方法 -func ProcessIVYZN2P8Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZ9K7FReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idcard": paramsDto.IDCard, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/id_card/check" - - // 先尝试使用政务接口(app_id2 和 app_secret2) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqData, true) - if err != nil { - if errors.Is(err, shumai.ErrNotFound) { - // 查无记录情况 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - return respBytes, nil -} - -// respBytes, err := deps.AlicloudService.CallAPI("api-mall/api/id_card/check", reqData) -// if err != nil { -// if errors.Is(err, alicloud.ErrDatasource) { -// return nil, errors.Join(processors.ErrDatasource, err) -// } -// return nil, errors.Join(processors.ErrSystem, err) -// } - -// return respBytes, nil -// // 对齐 yysybe08test 的原始响应结构,取 data 字段映射为 ivyzn2p8 返回 -// var aliyunData struct { -// Code int `json:"code"` -// Data struct { -// Birthday string `json:"birthday"` -// Result interface{} `json:"result"` -// Address string `json:"address"` -// OrderNo string `json:"orderNo"` -// Sex string `json:"sex"` -// Desc string `json:"desc"` -// } `json:"data"` -// Result interface{} `json:"result"` -// Desc string `json:"desc"` -// } -// if err := json.Unmarshal(respBytes, &aliyunData); err != nil { -// return nil, errors.Join(processors.ErrSystem, err) -// } - -// rawResult := aliyunData.Result -// rawDesc := aliyunData.Desc -// if aliyunData.Code == 200 { -// rawResult = aliyunData.Data.Result -// rawDesc = aliyunData.Data.Desc -// } - -// response := map[string]interface{}{ -// "result": normalizeResult(rawResult), -// "order_no": aliyunData.Data.OrderNo, -// "desc": rawDesc, -// "sex": aliyunData.Data.Sex, -// "birthday": aliyunData.Data.Birthday, -// "address": aliyunData.Data.Address, -// } -// return json.Marshal(response) -// } - -// func normalizeResult(v interface{}) int { -// switch r := v.(type) { -// case float64: -// return int(r) -// case int: -// return r -// case int32: -// return int(r) -// case int64: -// return int(r) -// case json.Number: -// n, err := r.Int64() -// if err == nil { -// return int(n) -// } -// case string: -// s := strings.TrimSpace(r) -// if s == "" { -// return 1 -// } -// n, err := strconv.Atoi(s) -// if err == nil { -// return n -// } -// } -// // 默认按不一致处理 -// return 1 -// } diff --git a/internal/domains/api/services/processors/ivyz/ivyzo4rx_processor.go b/internal/domains/api/services/processors/ivyz/ivyzo4rx_processor.go new file mode 100644 index 0000000..36dd8c5 --- /dev/null +++ b/internal/domains/api/services/processors/ivyz/ivyzo4rx_processor.go @@ -0,0 +1,14 @@ +package ivyz + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessIVYZO4RXRequest IVYZ28HY 婚姻状况核验(单人)(天远中转) +func ProcessIVYZO4RXRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZO4RXReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "IVYZ28HY", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/ivyz/ivyzocr1_processor.go b/internal/domains/api/services/processors/ivyz/ivyzocr1_processor.go deleted file mode 100644 index 0827a99..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyzocr1_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessIVYZOCR1Request IVYZOCR1 身份证OCR API 处理方法(使用数据宝服务示例) -func ProcessIVYZOCR1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZOCR1Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建数据宝入参:姓名、身份证、手机号、银行卡号(sign 外的业务参数可按需 AES 加密后作为 bodyData) - reqParams := map[string]interface{}{ - "key": "8782f2a32463f75b53096323461df735", - "imageId": paramsDto.PhotoData, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/trade/user/1985" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyzocr2_processor.go b/internal/domains/api/services/processors/ivyz/ivyzocr2_processor.go deleted file mode 100644 index 4916597..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyzocr2_processor.go +++ /dev/null @@ -1,56 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessIVYZOCR2Request IVYZOCR2 OCR识别API处理方法数卖 -func ProcessIVYZOCR2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZOCR1Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - if paramsDto.PhotoData == "" && paramsDto.ImageUrl == "" { - return nil, errors.Join(processors.ErrInvalidParam, errors.New("photo_data or image_url is required")) - } - - // 2选1:有值的用对应 key,空则用另一个 - reqFormData := make(map[string]interface{}) - if paramsDto.PhotoData != "" { - reqFormData["image"] = paramsDto.PhotoData - } else { - reqFormData["url"] = paramsDto.ImageUrl - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/idcard/ocr" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrNotFound) { - // 查无记录情况 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyzv1o6_processor.go b/internal/domains/api/services/processors/ivyz/ivyzoqfb_processor.go similarity index 88% rename from internal/domains/api/services/processors/ivyz/ivyzv1o6_processor.go rename to internal/domains/api/services/processors/ivyz/ivyzoqfb_processor.go index dd86fe5..a90fc86 100644 --- a/internal/domains/api/services/processors/ivyz/ivyzv1o6_processor.go +++ b/internal/domains/api/services/processors/ivyz/ivyzoqfb_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessIVYZV1O6Request IVYZV1O6 API处理方法 -身份风险V106 -func ProcessIVYZV1O6Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZV1O6Req +// ProcessIVYZOQFBRequest IVYZV1O6 API处理方法 -身份风险V106 +func ProcessIVYZOQFBRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZOQFBReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/ivyz/ivyzp2q6_processor.go b/internal/domains/api/services/processors/ivyz/ivyzp2q6_processor.go deleted file mode 100644 index 71221ea..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyzp2q6_processor.go +++ /dev/null @@ -1,84 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessIVYZP2Q6Request IVYZP2Q6 API处理方法 - 身份认证二要素 -func ProcessIVYZP2Q6Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZP2Q6Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqFormData := map[string]interface{}{ - "idcard": paramsDto.IDCard, - "name": paramsDto.Name, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/id_card/check" // 接口路径,根据数脉文档填写(如 v4/xxx) - - // 先尝试使用政务接口(app_id2 和 app_secret2) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true) - if err != nil { - // 使用实时接口(app_id 和 app_secret)重试 - respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false) - // 如果重试后仍然失败,返回错误 - if err != nil { - if errors.Is(err, shumai.ErrNotFound) { - // 查无记录情况 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - } - - // 数据源返回 result(0-一致/1-不一致/2-无记录),映射为 state(1-匹配/2-不匹配/3-异常情况) - var dsResp struct { - Result int `json:"result"` // 0-一致 1-不一致 2-无记录(预留) - } - if err := json.Unmarshal(respBytes, &dsResp); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - state := resultToState(dsResp.Result) - - out := map[string]interface{}{ - "errMsg": "", - "state": state, - } - return json.Marshal(out) -} - -// resultToState 将数据源 result 映射为接口 state:1-匹配 2-不匹配 3-异常情况 -func resultToState(result int) int { - switch result { - case 0: // 一致 → 匹配 - return 1 - case 1: // 不一致 → 不匹配 - return 2 - case 2: // 无记录(预留) → 异常情况 - return 3 - default: - return 3 // 未知/异常 → 异常情况 - } -} diff --git a/internal/domains/api/services/processors/ivyz/ivyzpyso_processor.go b/internal/domains/api/services/processors/ivyz/ivyzpyso_processor.go new file mode 100644 index 0000000..0e4d2d8 --- /dev/null +++ b/internal/domains/api/services/processors/ivyz/ivyzpyso_processor.go @@ -0,0 +1,14 @@ +package ivyz + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessIVYZPYSORequest IVYZ5E22 双人婚姻评估查询(天远中转) +func ProcessIVYZPYSORequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZPYSOReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "IVYZ5E22", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/ivyz/ivyzrht5_processor.go b/internal/domains/api/services/processors/ivyz/ivyzrht5_processor.go new file mode 100644 index 0000000..6a10c57 --- /dev/null +++ b/internal/domains/api/services/processors/ivyz/ivyzrht5_processor.go @@ -0,0 +1,14 @@ +package ivyz + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessIVYZRHT5Request IVYZ38SR 婚姻状态核验(双人)(天远中转) +func ProcessIVYZRHT5Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZRHT5Req + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "IVYZ38SR", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/ivyz/ivyzsfel_processor.go b/internal/domains/api/services/processors/ivyz/ivyzsfel_processor.go deleted file mode 100644 index cdac2cc..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyzsfel_processor.go +++ /dev/null @@ -1,52 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessIVYZSFELRequest IVYZSFEL 全国自然人人像三要素核验_V1API处理方法 -func ProcessIVYZSFELRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZSFELReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,使用xingwei服务的正确字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "photo": paramsDto.PhotoData, - "authAuthorizeFileCode": paramsDto.AuthAuthorizeFileCode, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1068350101927161856" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - // 查空情况,返回特定的查空错误 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyzsq0e_processor.go b/internal/domains/api/services/processors/ivyz/ivyzsq0e_processor.go new file mode 100644 index 0000000..d2eb665 --- /dev/null +++ b/internal/domains/api/services/processors/ivyz/ivyzsq0e_processor.go @@ -0,0 +1,24 @@ +package ivyz + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessIVYZSQ0ERequest IVYZ9K7F 身份证实名认证即时版 API处理方法 +func ProcessIVYZSQ0ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZSQ0EReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "IVYZ9K7F", params) +} diff --git a/internal/domains/api/services/processors/ivyz/ivyzwvya_processor.go b/internal/domains/api/services/processors/ivyz/ivyzwvya_processor.go new file mode 100644 index 0000000..8278cd5 --- /dev/null +++ b/internal/domains/api/services/processors/ivyz/ivyzwvya_processor.go @@ -0,0 +1,24 @@ +package ivyz + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessIVYZx5qzRequest IVYZx5qz 活体识别API处理方法 +func ProcessIVYZWVYARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZWVYAReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "IVYZX5QZ", params) +} diff --git a/internal/domains/api/services/processors/ivyz/ivyzx5q2_processor.go b/internal/domains/api/services/processors/ivyz/ivyzx5q2_processor.go deleted file mode 100644 index c7d91b7..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyzx5q2_processor.go +++ /dev/null @@ -1,63 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" - "hyapi-server/internal/shared/logger" - - "go.uber.org/zap" -) - -// ProcessIVYZX5Q2Request IVYZX5Q2 活体识别步骤二API处理方法 -func ProcessIVYZX5Q2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZX5Q2Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqFormData := map[string]interface{}{ - "token": paramsDto.Token, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/liveness/h5/v4/result" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrNotFound) { - // 查无记录情况 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // result==2 时手动抛出错误(不通过/无记录,不返回正常响应) - var body struct { - Result int `json:"result"` - } - if err := json.Unmarshal(respBytes, &body); err == nil && body.Result == 2 { - log := logger.GetGlobalLogger() - log.Warn("IVYZX5Q2 活体检测 result=2 无记录或不通过,返回错误", - zap.Int("result", body.Result), - zap.ByteString("response", respBytes)) - return nil, errors.Join(processors.ErrNotFound, errors.New("活体检测 result=2 无记录或不通过")) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyzx5qz_processor.go b/internal/domains/api/services/processors/ivyz/ivyzx5qz_processor.go deleted file mode 100644 index 9ecea1f..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyzx5qz_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessIVYZx5qzRequest IVYZx5qz 活体识别API处理方法 -func ProcessIVYZX5QZRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZX5QZReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqFormData := map[string]interface{}{ - "returnUrl": paramsDto.ReturnURL, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/liveness/h5/v4/token" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrNotFound) { - // 查无记录情况 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/ivyz/ivyzydqm_processor.go b/internal/domains/api/services/processors/ivyz/ivyzydqm_processor.go new file mode 100644 index 0000000..0b56fc8 --- /dev/null +++ b/internal/domains/api/services/processors/ivyz/ivyzydqm_processor.go @@ -0,0 +1,14 @@ +package ivyz + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessIVYZYDQMRequest IVYZ48SR 婚姻状态核验V2(双人)(天远中转) +func ProcessIVYZYDQMRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZYDQMReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "IVYZ48SR", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/ivyz/ivyzyqkx_processor.go b/internal/domains/api/services/processors/ivyz/ivyzyqkx_processor.go new file mode 100644 index 0000000..72c27ac --- /dev/null +++ b/internal/domains/api/services/processors/ivyz/ivyzyqkx_processor.go @@ -0,0 +1,14 @@ +package ivyz + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessIVYZYQKXRequest IVYZ18HY 婚姻状况核验V2(单人)(天远中转) +func ProcessIVYZYQKXRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZYQKXReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "IVYZ18HY", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/ivyz/ivyzzqt3_processor.go b/internal/domains/api/services/processors/ivyz/ivyzzqt3_processor.go deleted file mode 100644 index 43c198b..0000000 --- a/internal/domains/api/services/processors/ivyz/ivyzzqt3_processor.go +++ /dev/null @@ -1,212 +0,0 @@ -package ivyz - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "math" - "strconv" - "strings" - "time" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessIVYZZQT3Request IVYZZQT3 人脸比对V3API处理方法 -func ProcessIVYZZQT3Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.IVYZZQT3Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 使用数脉接口进行人脸身份证比对 - reqFormData := map[string]interface{}{ - "idcard": paramsDto.IDCard, - "name": paramsDto.Name, - "image": paramsDto.PhotoData, - } - - apiPath := "/v4/face_id_card/compare" - - // 先尝试政务接口,再回退实时接口 - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true) - if err != nil { - respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false) - if err != nil { - if errors.Is(err, shumai.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, shumai.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - } - - outBytes, err := mapShumaiFaceCompareToIVYZZQT3(respBytes) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return outBytes, nil -} - -type shumaiFaceCompareResp struct { - OrderNo string `json:"order_no"` - Score interface{} `json:"score"` - Msg string `json:"msg"` - Incorrect interface{} `json:"incorrect"` -} - -type ivyzzqt3Out struct { - HandleTime string `json:"handleTime"` - ResultData ivyzzqt3OutResultData `json:"resultData"` - OrderNo string `json:"orderNo"` -} - -type ivyzzqt3OutResultData struct { - VerificationCode string `json:"verification_code"` - VerificationResult string `json:"verification_result"` - VerificationMessage string `json:"verification_message"` - Similarity string `json:"similarity"` -} - -func mapShumaiFaceCompareToIVYZZQT3(respBytes []byte) ([]byte, error) { - var r shumaiFaceCompareResp - if err := json.Unmarshal(respBytes, &r); err != nil { - return nil, err - } - - score := parseScoreToFloat64(r.Score) - similarity := strconv.Itoa(int(math.Round(mapScoreToSimilarity(score)))) - verificationResult := mapScoreToVerificationResult(score) - verificationMessage := strings.TrimSpace(r.Msg) - if verificationMessage == "" { - verificationMessage = mapScoreToVerificationMessage(score) - } - - out := ivyzzqt3Out{ - HandleTime: time.Now().Format("2006-01-02 15:04:05"), - OrderNo: strings.TrimSpace(r.OrderNo), - ResultData: ivyzzqt3OutResultData{ - VerificationCode: mapVerificationCode(verificationResult, r.Incorrect), - VerificationResult: verificationResult, - VerificationMessage: verificationMessage, - Similarity: similarity, - }, - } - - return json.Marshal(out) -} - -func mapScoreToVerificationResult(score float64) string { - if score >= 0.45 { - return "valid" - } - // 旧结构仅支持 valid/invalid,不能确定场景按 invalid 返回 - return "invalid" -} - -func mapScoreToVerificationMessage(score float64) string { - if score < 0.40 { - return "系统判断为不同人" - } - if score < 0.45 { - return "不能确定是否为同一人" - } - return "系统判断为同一人" -} - -func mapScoreToSimilarity(score float64) float64 { - // 将 score(0~1) 分段映射到 similarity(0~1000),并对齐业务阈值: - // 0.40 -> 600,0.45 -> 700 - if score <= 0 { - return 0 - } - if score >= 1 { - return 1000 - } - if score < 0.40 { - // [0, 0.40) -> [0, 600) - return (score / 0.40) * 600 - } - if score < 0.45 { - // [0.40, 0.45) -> [600, 700) - return 600 + ((score-0.40)/0.05)*100 - } - // [0.45, 1] -> [700, 1000] - return 700 + ((score-0.45)/0.55)*300 -} - -func parseScoreToFloat64(v interface{}) float64 { - switch t := v.(type) { - case float64: - return t - case float32: - return float64(t) - case int: - return float64(t) - case int32: - return float64(t) - case int64: - return float64(t) - case json.Number: - if f, err := t.Float64(); err == nil { - return f - } - case string: - s := strings.TrimSpace(t) - if s == "" { - return 0 - } - if f, err := strconv.ParseFloat(s, 64); err == nil { - return f - } - } - return 0 -} - -func valueToString(v interface{}) string { - switch t := v.(type) { - case string: - return strings.TrimSpace(t) - case json.Number: - return t.String() - case float64: - return strconv.FormatFloat(t, 'f', -1, 64) - case float32: - return strconv.FormatFloat(float64(t), 'f', -1, 64) - case int: - return strconv.Itoa(t) - case int32: - return strconv.FormatInt(int64(t), 10) - case int64: - return strconv.FormatInt(t, 10) - default: - if v == nil { - return "" - } - return strings.TrimSpace(fmt.Sprint(v)) - } -} - -func mapVerificationCode(verificationResult string, upstreamIncorrect interface{}) string { - if verificationResult == "valid" { - return "1000" - } - if verificationResult == "invalid" { - return "2006" - } - // 兜底:若后续扩展出其它结果,保持可追溯 - if s := valueToString(upstreamIncorrect); s != "" { - return s - } - return "2006" -} diff --git a/internal/domains/api/services/processors/ivyz/ivyzzscg_processor.go b/internal/domains/api/services/processors/ivyz/ivyzzscg_processor.go new file mode 100644 index 0000000..c4009a5 --- /dev/null +++ b/internal/domains/api/services/processors/ivyz/ivyzzscg_processor.go @@ -0,0 +1,28 @@ +package ivyz + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessIVYZZSCGRequest IVYZOCR2 OCR 识别 API 处理方法 +func ProcessIVYZZSCGRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.IVYZ9OHNReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + if paramsDto.PhotoData == "" && paramsDto.ImageUrl == "" { + return nil, errors.Join(processors.ErrInvalidParam, errors.New("photo_data 与 image_url 至少传一个")) + } + + return processors.CallTianyuanByProduct(ctx, deps, "IVYZOCR2", params) +} diff --git a/internal/domains/api/services/processors/jrzq/jrzq09j8_processor.go b/internal/domains/api/services/processors/jrzq/jrzq09j8_processor.go deleted file mode 100644 index 2ae3796..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq09j8_processor.go +++ /dev/null @@ -1,62 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQ09J8Request JRZQ09J8 API处理方法 -func ProcessJRZQ09J8Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ09J8Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI031", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq0a03_processor.go b/internal/domains/api/services/processors/jrzq/jrzq0a03_processor.go deleted file mode 100644 index aa8fc86..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq0a03_processor.go +++ /dev/null @@ -1,57 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessJRZQ0A03Request JRZQ0A03 API处理方法 -func ProcessJRZQ0A03Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ0A03Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "id": encryptedIDCard, - "cell": encryptedMobileNo, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G27BJ05", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq0b6y_processor.go b/internal/domains/api/services/processors/jrzq/jrzq0b6y_processor.go deleted file mode 100644 index b9759a9..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq0b6y_processor.go +++ /dev/null @@ -1,40 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/yushan" -) - -// ProcessJRZQ0B6YRequest JRZQ0B6Y 银行卡黑名单查询V1API处理方法 -func ProcessJRZQ0B6YRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ0B6YReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "cardld": paramsDto.BankCard, - "cardNo": paramsDto.IDCard, - "mobile": paramsDto.MobileNo, - } - - respBytes, err := deps.YushanService.CallAPI(ctx, "FIN019", reqData) - if err != nil { - if errors.Is(err, yushan.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq0l85_processor.go b/internal/domains/api/services/processors/jrzq/jrzq0l85_processor.go deleted file mode 100644 index d4d57c0..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq0l85_processor.go +++ /dev/null @@ -1,47 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessJRZQ0L85Request JRZQ0L85 API处理方法 - xingwei service -func ProcessJRZQ0L85Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ0L85Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "phoneNumber": paramsDto.MobileNo, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1101695364016041984" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzqv07t_processor.go b/internal/domains/api/services/processors/jrzq/jrzq1aij_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqv07t_processor.go rename to internal/domains/api/services/processors/jrzq/jrzq1aij_processor.go index 87a9265..1d6f1da 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqv07t_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzq1aij_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQV07TRequest JRZQV07T API处理方法 - 洞侦多头履约行为 -func ProcessJRZQV07TRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQV07TReq +// ProcessJRZQ1AIJRequest JRZQV07T API处理方法 - 洞侦多头履约行为 +func ProcessJRZQ1AIJRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQ1AIJReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzq1d09_processor.go b/internal/domains/api/services/processors/jrzq/jrzq1d09_processor.go deleted file mode 100644 index 07a67cb..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq1d09_processor.go +++ /dev/null @@ -1,62 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQ1D09Request JRZQ1D09 API处理方法 -func ProcessJRZQ1D09Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ1D09Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI020", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq1e7b_processor.go b/internal/domains/api/services/processors/jrzq/jrzq1e7b_processor.go deleted file mode 100644 index 5d977c6..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq1e7b_processor.go +++ /dev/null @@ -1,62 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQ1E7BRequest JRZQ1E7B API处理方法 - 消费交易特征 -func ProcessJRZQ1E7BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ1E7BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI034", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为 JSON 字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq1p5g_processor.go b/internal/domains/api/services/processors/jrzq/jrzq1p5g_processor.go deleted file mode 100644 index 012506b..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq1p5g_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessJRZQ1P5GRequest JRZQ1P5G 全国自然人借贷压力指数查询(2) - xingwei service -func ProcessJRZQ1P5GRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ1P5GReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "phoneNumber": paramsDto.MobileNo, - "authAuthorizeFileCode": paramsDto.AuthAuthorizeFileCode, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1068350101704863744" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq1w4x_processor.go b/internal/domains/api/services/processors/jrzq/jrzq1w4x_processor.go deleted file mode 100644 index d07bddb..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq1w4x_processor.go +++ /dev/null @@ -1,64 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessjrzqW4XRequest JRZQ1W4XAPI处理方法 - 全景档案 -func ProcessJRZQ1W4XRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ1W4XReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 加密姓名 - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // 加密身份证号 - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - // 加手机号 - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI022", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq2f8a_processor.go b/internal/domains/api/services/processors/jrzq/jrzq2f8a_processor.go deleted file mode 100644 index e2c49e6..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq2f8a_processor.go +++ /dev/null @@ -1,62 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQ2F8ARequest JRZQ2F8A API处理方法 - 探针A -func ProcessJRZQ2F8ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ2F8AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI009", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为 JSON 字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq3ag6_processor.go b/internal/domains/api/services/processors/jrzq/jrzq3ag6_processor.go deleted file mode 100644 index 16e7ff1..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq3ag6_processor.go +++ /dev/null @@ -1,63 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQ3AG6Request JRZQ3AG6 轻松查公积API处理方法 -func ProcessJRZQ3AG6Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ3AG6Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "return_url": paramsDto.ReturnURL, - "authorization_url": paramsDto.AuthorizationURL, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI108", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq3c7b_processor.go b/internal/domains/api/services/processors/jrzq/jrzq3c7b_processor.go deleted file mode 100644 index f64c91f..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq3c7b_processor.go +++ /dev/null @@ -1,62 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQ3C7BRequest JRZQ3C7B API处理方法 - 借贷意向验证 -func ProcessJRZQ3C7BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ3C7BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI017", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq3c9R_processor.go b/internal/domains/api/services/processors/jrzq/jrzq3c9R_processor.go deleted file mode 100644 index d700ce6..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq3c9R_processor.go +++ /dev/null @@ -1,62 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQ3c9RRequest JRZQ3c9R API处理方法 - 支付行为指数 -func ProcessJRZQ3C9RRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ3C9RReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI036", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq3p01_processor.go b/internal/domains/api/services/processors/jrzq/jrzq3p01_processor.go deleted file mode 100644 index aba0d27..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq3p01_processor.go +++ /dev/null @@ -1,56 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQ3P01Request JRZQ3P01 海宇风控决策API处理方法 -func ProcessJRZQ3P01Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ3P01Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI109", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq4aa8_processor.go b/internal/domains/api/services/processors/jrzq/jrzq4aa8_processor.go deleted file mode 100644 index 2792f44..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq4aa8_processor.go +++ /dev/null @@ -1,57 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessJRZQ4AA8Request JRZQ4AA8 API处理方法 -func ProcessJRZQ4AA8Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ4AA8Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "id": encryptedIDCard, - "cell": encryptedMobileNo, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G29BJ05", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq4b6c_processor.go b/internal/domains/api/services/processors/jrzq/jrzq4b6c_processor.go deleted file mode 100644 index b45cc9a..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq4b6c_processor.go +++ /dev/null @@ -1,61 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQ4B6CRequest JRZQ4B6C API处理方法 - 探针C -func ProcessJRZQ4B6CRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ4B6CReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI023", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq5e9f_processor.go b/internal/domains/api/services/processors/jrzq/jrzq5e9f_processor.go deleted file mode 100644 index 095f343..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq5e9f_processor.go +++ /dev/null @@ -1,62 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQ5E9FRequest JRZQ5E9F API处理方法 - 借选指数 -func ProcessJRZQ5E9FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ5E9FReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI021", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzqbhz4_processor.go b/internal/domains/api/services/processors/jrzq/jrzq65zo_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqbhz4_processor.go rename to internal/domains/api/services/processors/jrzq/jrzq65zo_processor.go index df3817b..09215e2 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqbhz4_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzq65zo_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQBHZ4Request JRZQBHZ4 API处理方法 - 支付行为指数博汇 -func ProcessJRZQBHZ4Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQBHZ4Req +// ProcessJRZQ65ZORequest JRZQBHZ4 API处理方法 - 支付行为指数博汇 +func ProcessJRZQ65ZORequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQ65ZOReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzq6f2a_processor.go b/internal/domains/api/services/processors/jrzq/jrzq6f2a_processor.go deleted file mode 100644 index 7b6acbf..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq6f2a_processor.go +++ /dev/null @@ -1,47 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessJRZQ6F2ARequest JRZQ6F2A API处理方法 - 借贷申请记录 -func ProcessJRZQ6F2ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ6F2AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "phoneNumber": paramsDto.MobileNo, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1101695369065984000" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq7f1a_processor.go b/internal/domains/api/services/processors/jrzq/jrzq7f1a_processor.go deleted file mode 100644 index 27b946a..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq7f1a_processor.go +++ /dev/null @@ -1,62 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQ7F1ARequest JRZQ7F1A API处理方法 - 全景雷达V4 -func ProcessJRZQ7F1ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ7F1AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI008", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq8203_processor.go b/internal/domains/api/services/processors/jrzq/jrzq8203_processor.go deleted file mode 100644 index 85924e2..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq8203_processor.go +++ /dev/null @@ -1,57 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessJRZQ8203Request JRZQ8203 API处理方法 -func ProcessJRZQ8203Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ8203Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "id": encryptedIDCard, - "cell": encryptedMobileNo, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G28BJ05", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq8a2d_processor.go b/internal/domains/api/services/processors/jrzq/jrzq8a2d_processor.go deleted file mode 100644 index b96e3b2..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq8a2d_processor.go +++ /dev/null @@ -1,59 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQ8A2DRequest JRZQ8A2D API处理方法 - 特殊名单验证 -func ProcessJRZQ8A2DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ8A2DReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI018", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq8b3c_processor.go b/internal/domains/api/services/processors/jrzq/jrzq8b3c_processor.go deleted file mode 100644 index 9354bfb..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq8b3c_processor.go +++ /dev/null @@ -1,47 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessJRZQ8B3CRequest JRZQ8B3C API处理方法 - 个人消费能力等级 -func ProcessJRZQ8B3CRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ8B3CReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "phoneNumber": paramsDto.MobileNo, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1101695392528920576" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq8f7c_processor.go b/internal/domains/api/services/processors/jrzq/jrzq8f7c_processor.go deleted file mode 100644 index 9ce6169..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq8f7c_processor.go +++ /dev/null @@ -1,62 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQ8F7CRequest JRZQ8F7C API处理方法 -func ProcessJRZQ8F7CRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ8F7CReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI047", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq9a1w_processor.go b/internal/domains/api/services/processors/jrzq/jrzq9a1w_processor.go deleted file mode 100644 index 746bffc..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq9a1w_processor.go +++ /dev/null @@ -1,40 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/yushan" -) - -// ProcessJRZQ9A1WRequest JRZQ9A1W 银行卡鉴权V1API处理方法 -func ProcessJRZQ9A1WRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ9A1WReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "cardId": paramsDto.BankCard, - "cardNo": paramsDto.IDCard, - "phone": paramsDto.MobileNo, - } - - respBytes, err := deps.YushanService.CallAPI(ctx, "PCB145", reqData) - if err != nil { - if errors.Is(err, yushan.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq9d4e_processor.go b/internal/domains/api/services/processors/jrzq/jrzq9d4e_processor.go deleted file mode 100644 index f3ad2cf..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq9d4e_processor.go +++ /dev/null @@ -1,47 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessJRZQ9D4ERequest JRZQ9D4E API处理方法 - 多头借贷小时级 -func ProcessJRZQ9D4ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ9D4EReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "phoneNumber": paramsDto.MobileNo, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1118085532960616448" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzq9e2a_processor.go b/internal/domains/api/services/processors/jrzq/jrzq9e2a_processor.go deleted file mode 100644 index f9dc46b..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzq9e2a_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessJRZQ9E2ARequest JRZQ9E2A API处理方法 -func ProcessJRZQ9E2ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQ9E2AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名 - reqData := map[string]interface{}{ - "phoneNumber": paramsDto.MobileNo, - "idCardNum": paramsDto.IDCard, - "name": paramsDto.Name, - "authAuthorizeFileCode": paramsDto.AuthAuthorizeFileCode, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1068350101688086528" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzqacab_processor.go b/internal/domains/api/services/processors/jrzq/jrzqacab_processor.go deleted file mode 100644 index 936f032..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzqacab_processor.go +++ /dev/null @@ -1,51 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessJRZQACABERequest JRZQACAB 银行卡四要素 API 处理方法(使用数据宝服务示例) -func ProcessJRZQACABERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQACABReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建数据宝入参:姓名、身份证、手机号、银行卡号(sign 外的业务参数可按需 AES 加密后作为 bodyData) - reqParams := map[string]interface{}{ - "key": "7eb69f73a855e41875e22f139b934c3c", - "name": paramsDto.Name, - "idcard": paramsDto.IDCard, - "mobile": paramsDto.MobileNo, - "acc_no": paramsDto.BankCard, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/9442" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzqv4tf_processor.go b/internal/domains/api/services/processors/jrzq/jrzqah34_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqv4tf_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqah34_processor.go index ade43e2..9c9e4ed 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqv4tf_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqah34_processor.go @@ -10,10 +10,10 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQV4TFRequest JRZQV4TFRequest API处理方法 - 智瞳分尊享版 +// ProcessJRZQAH34Request JRZQV4TFRequest API处理方法 - 智瞳分尊享版 -func ProcessJRZQV4TFRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQV4TFReq +func ProcessJRZQAH34Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQAH34Req if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqbqir_processor.go b/internal/domains/api/services/processors/jrzq/jrzqbqir_processor.go new file mode 100644 index 0000000..834b76b --- /dev/null +++ b/internal/domains/api/services/processors/jrzq/jrzqbqir_processor.go @@ -0,0 +1,50 @@ +package jrzq + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" + "hyapi-server/internal/infrastructure/external/nuoer" +) + +// ProcessJRZQBQIRRequest JRZQV87MReq API处理方法 - 黑名单V110_c10 +func ProcessJRZQBQIRRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQBQIRReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + body := map[string]string{ + "name": paramsDto.Name, + "idCard": paramsDto.IDCard, + "mobile": paramsDto.MobileNo, + } + + nuoerDoCheckAPIKey := "blackListV110_c10" + ApiPath := "/v1/doCheck" + + resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body) + if err != nil { + if errors.Is(err, nuoer.ErrDatasource) { + return nil, errors.Join(processors.ErrDatasource, err) + } + if errors.Is(err, nuoer.ErrNotFound) { + return nil, errors.Join(processors.ErrNotFound, err) + } + return nil, errors.Join(processors.ErrSystem, err) + } + + respBytes, err := json.Marshal(resp.Data) + if err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + return respBytes, nil +} diff --git a/internal/domains/api/services/processors/jrzq/jrzqdcbe_processor.go b/internal/domains/api/services/processors/jrzq/jrzqdcbe_processor.go deleted file mode 100644 index 2cf7f92..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzqdcbe_processor.go +++ /dev/null @@ -1,62 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessJRZQDCBERequest JRZQDCBE API处理方法 -func ProcessJRZQDCBERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQDCBEReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedBankCard, err := deps.WestDexService.Encrypt(paramsDto.BankCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "idcard": encryptedIDCard, - "mobile": encryptedMobileNo, - "acc_no": encryptedBankCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G20GZ01", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzqdmlo_processor.go b/internal/domains/api/services/processors/jrzq/jrzqdmlo_processor.go new file mode 100644 index 0000000..a0e00d4 --- /dev/null +++ b/internal/domains/api/services/processors/jrzq/jrzqdmlo_processor.go @@ -0,0 +1,14 @@ +package jrzq + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessJRZQDMLORequest JRZQOCRY 银行卡OCR(天远中转) +func ProcessJRZQDMLORequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQDMLOReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "JRZQOCRY", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/jrzq/jrzqv1o0_processor.go b/internal/domains/api/services/processors/jrzq/jrzqi079_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqv1o0_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqi079_processor.go index 376eafb..d63a1ce 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqv1o0_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqi079_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQV1O0Request JRZQV1O0 API处理方法 - 风险量级V10 -func ProcessJRZQV1O0Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQV1O0Req +// ProcessJRZQI079Request JRZQV1O0 API处理方法 - 风险量级V10 +func ProcessJRZQI079Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQI079Req if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqvztf_processor.go b/internal/domains/api/services/processors/jrzq/jrzqly6d_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqvztf_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqly6d_processor.go index 00a6220..67b4d4a 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqvztf_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqly6d_processor.go @@ -10,10 +10,10 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQVZTFRequest JRZQVZTFRequest API处理方法 - 智瞳-通用版 +// ProcessJRZQLY6DRequest JRZQVZTFRequest API处理方法 - 智瞳-通用版 -func ProcessJRZQVZTFRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQVZTFReq +func ProcessJRZQLY6DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQLY6DReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqmdq1_processor.go b/internal/domains/api/services/processors/jrzq/jrzqmdq1_processor.go new file mode 100644 index 0000000..fa60df6 --- /dev/null +++ b/internal/domains/api/services/processors/jrzq/jrzqmdq1_processor.go @@ -0,0 +1,28 @@ +package jrzq + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessJRZQMDQ1Request JRZQOCRE 银行卡 OCR API 处理方法 +func ProcessJRZQMDQ1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQMDQ1Req + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + if paramsDto.PhotoData == "" && paramsDto.ImageUrl == "" { + return nil, errors.Join(processors.ErrInvalidParam, errors.New("photo_data 与 image_url 至少传一个")) + } + + return processors.CallTianyuanByProduct(ctx, deps, "JRZQOCRE", params) +} diff --git a/internal/domains/api/services/processors/jrzq/jrzqvkk6_processor.go b/internal/domains/api/services/processors/jrzq/jrzqml9g_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqvkk6_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqml9g_processor.go index f53b238..a243e8b 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqvkk6_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqml9g_processor.go @@ -10,10 +10,10 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQVKK6Request JRZQVKK6Request API处理方法 - 坤羽模型V3-标签版 +// ProcessJRZQML9GRequest JRZQVKK6Request API处理方法 - 坤羽模型V3-标签版 -func ProcessJRZQVKK6Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQVKK6Req +func ProcessJRZQML9GRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQML9GReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqv7md_processor.go b/internal/domains/api/services/processors/jrzq/jrzqmlzx_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqv7md_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqmlzx_processor.go index 7ca89a4..e545492 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqv7md_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqmlzx_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQVZ3YRequest JRZQVZ3Y API处理方法 - 特殊名单 -func ProcessJRZQV7MDRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQV7MDReq +// ProcessJRZQZ05IRequest JRZQVZ3Y API处理方法 - 特殊名单 +func ProcessJRZQMLZXRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQMLZXReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqvzxf_processor.go b/internal/domains/api/services/processors/jrzq/jrzqnep0_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqvzxf_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqnep0_processor.go index eacf8b2..713f958 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqvzxf_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqnep0_processor.go @@ -10,10 +10,10 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQVZXFRequest JRZQVZXFRequest API处理方法 - 智享分 +// ProcessJRZQNEP0Request JRZQVZXFRequest API处理方法 - 智享分 -func ProcessJRZQVZXFRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQVZXFReq +func ProcessJRZQNEP0Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQNEP0Req if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqvz2y_processor.go b/internal/domains/api/services/processors/jrzq/jrzqnk43_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqvz2y_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqnk43_processor.go index 546145a..67139bf 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqvz2y_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqnk43_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQVZ2YRequest JRZQVZ2Y API处理方法 - 借贷申请意向V22 -func ProcessJRZQVZ2YRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQVZ2YReq +// ProcessJRZQNK43Request JRZQVZ2Y API处理方法 - 借贷申请意向V22 +func ProcessJRZQNK43Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQNK43Req if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqv8v8_processor.go b/internal/domains/api/services/processors/jrzq/jrzqnkei_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqv8v8_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqnkei_processor.go index 370206a..fadcc97 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqv8v8_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqnkei_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQV8V8Request JRZQV8V8 API处理方法 - 风险量级V8 -func ProcessJRZQV8V8Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQV8V8Req +// ProcessJRZQNKEIRequest JRZQV8V8 API处理方法 - 风险量级V8 +func ProcessJRZQNKEIRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQNKEIReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqv5f4_processor.go b/internal/domains/api/services/processors/jrzq/jrzqnvm8_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqv5f4_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqnvm8_processor.go index c30271a..91a0803 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqv5f4_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqnvm8_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQV5F4Request JRZQV5F4 API处理方法 - 风险变量V5F4 -func ProcessJRZQV5F4Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQV5F4Req +// ProcessJRZQNVM8Request JRZQV5F4 API处理方法 - 风险变量V5F4 +func ProcessJRZQNVM8Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQNVM8Req if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqo6l7_processor.go b/internal/domains/api/services/processors/jrzq/jrzqo6l7_processor.go deleted file mode 100644 index c60d862..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzqo6l7_processor.go +++ /dev/null @@ -1,64 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQO6L7Request JRZQO6L7 API处理方法 - 全国自然人经济特征评分模型v3 简版 -func ProcessJRZQO6L7Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQO6L7Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - null := "" - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - "province": null, - "city": null, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI081", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzqo7l1_processor.go b/internal/domains/api/services/processors/jrzq/jrzqo7l1_processor.go deleted file mode 100644 index 5ea818d..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzqo7l1_processor.go +++ /dev/null @@ -1,67 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQO7L1Request JRZQO7L1 API处理方法 - 全国自然人经济特征评分模型v4 详版 -func ProcessJRZQO7L1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQO7L1Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - null := "" - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - "entName": paramsDto.EntName, - "province": null, - "city": null, - } - - // 使用 WithSkipCode201Check 不跳过 201 错误检查,当 Code == "201" 时返回错误 - // ctx = zhicha.WithSkipCode201Check(ctx) - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI080", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzqocre_processor.go b/internal/domains/api/services/processors/jrzq/jrzqocre_processor.go deleted file mode 100644 index 1aa6740..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzqocre_processor.go +++ /dev/null @@ -1,52 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessJRZQOCREERequest JRZQOCRE 银行卡OCR API 数卖服务示例 -func ProcessJRZQOCREERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQOCREReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - if paramsDto.PhotoData == "" && paramsDto.ImageUrl == "" { - return nil, errors.Join(processors.ErrInvalidParam, errors.New("photo_data or image_url is required")) - } - - // 2选1:有值的用对应 key,空则用另一个 - reqFormData := make(map[string]interface{}) - if paramsDto.PhotoData != "" { - reqFormData["image"] = paramsDto.PhotoData - } else { - reqFormData["url"] = paramsDto.ImageUrl - } - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v2/bankcard/ocr" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzqocry_processor.go b/internal/domains/api/services/processors/jrzq/jrzqocry_processor.go deleted file mode 100644 index db9ead8..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzqocry_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessJRZQOCRYERequest JRZQOCRY 银行卡OCR API 处理方法(使用数据宝服务示例) -func ProcessJRZQOCRYERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQOCRYReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建数据宝入参:姓名、身份证、手机号、银行卡号(sign 外的业务参数可按需 AES 加密后作为 bodyData) - reqParams := map[string]interface{}{ - "key": "3ee8e7a7a71870db2c0bf98e7e6b8b5c", - "imageId": paramsDto.PhotoData, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/trade/user/1986" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzqoicn_processor.go b/internal/domains/api/services/processors/jrzq/jrzqoicn_processor.go new file mode 100644 index 0000000..6f11128 --- /dev/null +++ b/internal/domains/api/services/processors/jrzq/jrzqoicn_processor.go @@ -0,0 +1,14 @@ +package jrzq + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessJRZQOICNRequest JRZQACAB 银行卡四要素(天远中转) +func ProcessJRZQOICNRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQOICNReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "JRZQACAB", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/jrzq/jrzqv3hm_processor.go b/internal/domains/api/services/processors/jrzq/jrzqqd4f_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqv3hm_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqqd4f_processor.go index b095f52..5e9af1d 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqv3hm_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqqd4f_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQV3HMRequest JRZQV3HM API处理方法 - 债务逾期黑名单V3_1 -func ProcessJRZQV3HMRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQV3HMReq +// ProcessJRZQQD4FRequest JRZQV3HM API处理方法 - 债务逾期黑名单V3_1 +func ProcessJRZQQD4FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQQD4FReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqv9v9_processor.go b/internal/domains/api/services/processors/jrzq/jrzqqkec_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqv9v9_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqqkec_processor.go index 850608e..295f839 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqv9v9_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqqkec_processor.go @@ -10,9 +10,9 @@ import ( nuoerext "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQV9V9Request JRZQV9V9 API处理方法 - 风险量级V9 -func ProcessJRZQV9V9Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQV9V9Req +// ProcessJRZQQKECRequest JRZQV9V9 API处理方法 - 风险量级V9 +func ProcessJRZQQKECRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQQKECReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqs7g0_processor.go b/internal/domains/api/services/processors/jrzq/jrzqs7g0_processor.go deleted file mode 100644 index dc632bc..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzqs7g0_processor.go +++ /dev/null @@ -1,61 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessJRZQS7G0Request JRZQS7G0 API处理方法 -社保综合评分V1 -func ProcessJRZQS7G0Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQS7G0Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - // 使用 WithSkipCode201Check 不跳过 201 错误检查,当 Code == "201" 时返回错误 - // ctx = zhicha.WithSkipCode201Check(ctx) - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI082", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzqv0md_processor.go b/internal/domains/api/services/processors/jrzq/jrzqtm1v_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqv0md_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqtm1v_processor.go index 4ba7f12..947bfae 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqv0md_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqtm1v_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQV0MDRequest JRZQV0MDRequest API处理方法 - 特殊名单 -func ProcessJRZQV0MDRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQV0MDReq +// ProcessJRZQTM1VRequest JRZQV0MDRequest API处理方法 - 特殊名单 +func ProcessJRZQTM1VRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQTM1VReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqv2o1_processor.go b/internal/domains/api/services/processors/jrzq/jrzqv7yz_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqv2o1_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqv7yz_processor.go index 40a0a67..88101d8 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqv2o1_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqv7yz_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQV2O1Request JRZQV2O1 API处理方法 - 信用全景V21 -func ProcessJRZQV2O1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQV2O1Req +// ProcessJRZQV7YZRequest JRZQV2O1 API处理方法 - 信用全景V21 +func ProcessJRZQV7YZRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQV7YZReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqv87m_processor.go b/internal/domains/api/services/processors/jrzq/jrzqv87m_processor.go deleted file mode 100644 index 3a9f48c..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzqv87m_processor.go +++ /dev/null @@ -1,50 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/nuoer" -) - -// ProcessJRZQV87MReqest JRZQV87MReq API处理方法 - 黑名单V110_c10 -func ProcessJRZQV87MReqest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQV87MReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - body := map[string]string{ - "name": paramsDto.Name, - "idCard": paramsDto.IDCard, - "mobile": paramsDto.MobileNo, - } - - nuoerDoCheckAPIKey := "blackListV110_c10" - ApiPath := "/v1/doCheck" - - resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body) - if err != nil { - if errors.Is(err, nuoer.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, nuoer.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(resp.Data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzqvt43_processor.go b/internal/domains/api/services/processors/jrzq/jrzqvbhj_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqvt43_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqvbhj_processor.go index c932500..aea3024 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqvt43_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqvbhj_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQVT43Request JRZQVT43 API处理方法 - 投诉风险筛查V709 -func ProcessJRZQVT43Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQVT43Req +// ProcessJRZQVBHJRequest JRZQVT43 API处理方法 - 投诉风险筛查V709 +func ProcessJRZQVBHJRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQVBHJReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqvt72_processor.go b/internal/domains/api/services/processors/jrzq/jrzqvt72_processor.go deleted file mode 100644 index 3b1e2ca..0000000 --- a/internal/domains/api/services/processors/jrzq/jrzqvt72_processor.go +++ /dev/null @@ -1,50 +0,0 @@ -package jrzq - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/nuoer" -) - -// ProcessJRZQVT72Request JRZQVT72 API处理方法 - 团伙欺诈风险识别 -func ProcessJRZQVT72Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQVT72Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - body := map[string]string{ - "name": paramsDto.Name, - "idCard": paramsDto.IDCard, - "mobile": paramsDto.MobileNo, - } - - nuoerDoCheckAPIKey := "idRelationRisk" - ApiPath := "/v1/doCheck" - - resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body) - if err != nil { - if errors.Is(err, nuoer.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, nuoer.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(resp.Data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/jrzq/jrzqv7d1_processor.go b/internal/domains/api/services/processors/jrzq/jrzqx5dm_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqv7d1_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqx5dm_processor.go index 27d7220..17b9a35 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqv7d1_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqx5dm_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQV7D1Request JRZQV7D1 API处理方法 - 借贷意向验证 -func ProcessJRZQV7D1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQV7D1Req +// ProcessJRZQX5DMRequest JRZQV7D1 API处理方法 - 借贷意向验证 +func ProcessJRZQX5DMRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQX5DMReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/jrzq/jrzqvz3y_processor.go b/internal/domains/api/services/processors/jrzq/jrzqz05i_processor.go similarity index 88% rename from internal/domains/api/services/processors/jrzq/jrzqvz3y_processor.go rename to internal/domains/api/services/processors/jrzq/jrzqz05i_processor.go index 476e730..6cb636b 100644 --- a/internal/domains/api/services/processors/jrzq/jrzqvz3y_processor.go +++ b/internal/domains/api/services/processors/jrzq/jrzqz05i_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessJRZQVZ3YRequest JRZQVZ3Y API处理方法 - 租赁申请意向 -func ProcessJRZQVZ3YRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.JRZQVZ3YReq +// ProcessJRZQZ05IRequest JRZQVZ3Y API处理方法 - 租赁申请意向 +func ProcessJRZQZ05IRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.JRZQZ05IReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/pdfg/pdfg01gz_processor.go b/internal/domains/api/services/processors/pdfg/pdfg01gz_processor.go deleted file mode 100644 index 3cbd131..0000000 --- a/internal/domains/api/services/processors/pdfg/pdfg01gz_processor.go +++ /dev/null @@ -1,498 +0,0 @@ -package pdfg - -import ( - "context" - "crypto/rand" - "encoding/hex" - "encoding/json" - "errors" - "fmt" - "time" - - "hyapi-server/internal/config" - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/pdfgen" - "hyapi-server/internal/shared/logger" - "hyapi-server/internal/shared/pdf" - - "go.uber.org/zap" -) - -// ProcessPDFG01GZRequest PDFG01GZ 处理器 - 大数据租赁风险PDF报告 -func ProcessPDFG01GZRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.PDFG01GZReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 获取全局logger - zapLogger := logger.GetGlobalLogger() - - // Debug:记录入口参数(使用 Info 级别便于线上查看) - logger.L().Info("PDFG01GZ请求开始", - zap.String("name", paramsDto.Name), - zap.String("id_card", paramsDto.IDCard), - zap.String("mobile_no", paramsDto.MobileNo), - zap.String("authorized", paramsDto.Authorized), - ) - - // 从context获取config(如果存在) - var cacheTTL time.Duration = 24 * time.Hour - var cacheDir string - var apiDomain string - if cfg, ok := ctx.Value("config").(*config.Config); ok && cfg != nil { - cacheTTL = cfg.PDFGen.Cache.TTL - if cacheTTL == 0 { - cacheTTL = 24 * time.Hour - } - cacheDir = cfg.PDFGen.Cache.CacheDir - apiDomain = cfg.API.Domain - } - - // 获取最大缓存大小 - var maxSize int64 - if cfg, ok := ctx.Value("config").(*config.Config); ok && cfg != nil { - maxSize = cfg.PDFGen.Cache.MaxSize - - // Debug:记录PDF生成服务配置(使用 Info 级别便于线上查看) - logger.L().Info("PDFG01GZ加载配置", - zap.String("env", cfg.App.Env), - zap.String("pdfgen_production_url", cfg.PDFGen.ProductionURL), - zap.String("pdfgen_development_url", cfg.PDFGen.DevelopmentURL), - zap.String("pdfgen_api_path", cfg.PDFGen.APIPath), - zap.Duration("pdfgen_timeout", cfg.PDFGen.Timeout), - zap.String("cache_dir", cacheDir), - zap.Duration("cache_ttl", cacheTTL), - zap.Int64("cache_max_size", maxSize), - ) - } - - // 创建PDF缓存管理器 - cacheManager, err := pdf.NewPDFCacheManager(zapLogger, cacheDir, cacheTTL, maxSize) - if err != nil { - return nil, errors.Join(processors.ErrSystem, fmt.Errorf("创建PDF缓存管理器失败: %w", err)) - } - - // 从context获取config创建PDF生成服务 - var pdfGenService *pdfgen.PDFGenService - if cfg, ok := ctx.Value("config").(*config.Config); ok && cfg != nil { - pdfGenService = pdfgen.NewPDFGenService(cfg, zapLogger) - } else { - // 如果无法获取config,使用默认配置 - defaultCfg := &config.Config{ - App: config.AppConfig{Env: "development"}, - PDFGen: config.PDFGenConfig{ - DevelopmentURL: "http://pdfg.haiyudata.com", - ProductionURL: "http://localhost:15990", - APIPath: "/api/v1/generate/guangzhou", - Timeout: 120 * time.Second, - }, - } - pdfGenService = pdfgen.NewPDFGenService(defaultCfg, zapLogger) - } - - // 直接生成PDF,不检查缓存(每次都重新生成) - zapLogger.Info("开始生成PDF", - zap.String("name", paramsDto.Name), - zap.String("id_card", paramsDto.IDCard), - ) - - // 调用多个处理器获取数据(即使部分失败也继续) - apiData := collectAPIData(ctx, paramsDto, deps, zapLogger) - - // 格式化数据为PDF生成服务需要的格式(为缺失的数据提供默认值) - formattedData := formatDataForPDF(apiData, paramsDto, zapLogger) - - // 打印完整的apiData(为避免日志过大,这里直接序列化为JSON字符串) - apiDataBytes, _ := json.Marshal(apiData) - logger.L().Info("PDFG01GZ数据准备完成", - zap.Int("api_data_count", len(apiData)), - zap.Int("formatted_items", len(formattedData)), - zap.ByteString("api_data", apiDataBytes), - ) - - // 从APPLICANT_BASIC_INFO中提取报告编号(如果存在) - var reportNumber string - if len(formattedData) > 0 { - if basicInfo, ok := formattedData[0]["data"].(map[string]interface{}); ok { - if rn, ok := basicInfo["report_number"].(string); ok { - reportNumber = rn - } - } - } - // 如果没有提取到,生成新的报告编号 - if reportNumber == "" { - reportNumber = generateReportNumber() - } - - // 构建PDF生成请求 - pdfReq := &pdfgen.GeneratePDFRequest{ - Data: formattedData, - ReportNumber: reportNumber, - GenerateTime: time.Now().Format("2006-01-02 15:04:05"), - } - - // 调用PDF生成服务 - // 即使部分子处理器失败,只要有APPLICANT_BASIC_INFO就可以生成PDF - logger.L().Info("PDFG01GZ开始调用PDF生成服务", - zap.String("report_number", reportNumber), - zap.Int("data_items", len(formattedData)), - ) - pdfResp, err := pdfGenService.GenerateGuangzhouPDF(ctx, pdfReq) - if err != nil { - zapLogger.Error("生成PDF失败", - zap.Error(err), - zap.Int("data_items", len(formattedData)), - ) - return nil, errors.Join(processors.ErrSystem, fmt.Errorf("生成PDF失败: %w", err)) - } - - // 生成报告ID(每次请求都生成唯一的ID) - reportID := generateReportID() - - // 保存到缓存(基于报告ID,文件名包含时间戳确保唯一性) - if err := cacheManager.SetByReportID(reportID, pdfResp.PDFBytes); err != nil { - zapLogger.Warn("保存PDF到缓存失败", zap.Error(err)) - // 不影响返回结果,只记录警告 - } - - // 生成下载链接(基于报告ID) - downloadURL := generateDownloadURL(apiDomain, reportID) - expiresAt := time.Now().Add(cacheTTL) - - zapLogger.Info("PDF生成成功", - zap.String("name", paramsDto.Name), - zap.String("id_card", paramsDto.IDCard), - zap.String("report_id", reportID), - zap.String("report_number", reportNumber), - zap.String("download_url", downloadURL), - ) - - return json.Marshal(map[string]interface{}{ - "download_url": downloadURL, - "report_id": reportID, - "report_number": reportNumber, - "expires_at": expiresAt.Format(time.RFC3339), - "ttl_seconds": int(cacheTTL.Seconds()), - }) -} - -// collectAPIData 收集所有需要的API数据 -// 即使部分或全部子处理器失败,也会返回结果(失败的设为nil),确保流程继续 -func collectAPIData(ctx context.Context, params dto.PDFG01GZReq, deps *processors.ProcessorDependencies, logger *zap.Logger) map[string]interface{} { - apiData := make(map[string]interface{}) - - // 并发调用多个处理器 - type processorResult struct { - apiCode string - data interface{} - err error - } - - results := make(chan processorResult, 5) - - // 调用JRZQ0L85 - 需要: name, id_card, mobile_no - go func() { - defer func() { - if r := recover(); r != nil { - logger.Error("调用JRZQ0L85处理器时发生panic", - zap.Any("panic", r), - ) - results <- processorResult{"JRZQ0L85", nil, fmt.Errorf("处理器panic: %v", r)} - } - }() - jrzq0l85Params := map[string]interface{}{ - "name": params.Name, - "id_card": params.IDCard, - "mobile_no": params.MobileNo, - } - paramsBytes, err := json.Marshal(jrzq0l85Params) - if err != nil { - logger.Warn("序列化JRZQ0L85参数失败", zap.Error(err)) - results <- processorResult{"JRZQ0L85", nil, err} - return - } - data, err := callProcessor(ctx, "JRZQ0L85", paramsBytes, deps) - results <- processorResult{"JRZQ0L85", data, err} - }() - - // 调用JRZQ8A2D - 需要: name, id_card, mobile_no, authorized - go func() { - defer func() { - if r := recover(); r != nil { - logger.Error("调用JRZQ8A2D处理器时发生panic", - zap.Any("panic", r), - ) - results <- processorResult{"JRZQ8A2D", nil, fmt.Errorf("处理器panic: %v", r)} - } - }() - jrzq8a2dParams := map[string]interface{}{ - "name": params.Name, - "id_card": params.IDCard, - "mobile_no": params.MobileNo, - "authorized": params.Authorized, - } - paramsBytes, err := json.Marshal(jrzq8a2dParams) - if err != nil { - logger.Warn("序列化JRZQ8A2D参数失败", zap.Error(err)) - results <- processorResult{"JRZQ8A2D", nil, err} - return - } - data, err := callProcessor(ctx, "JRZQ8A2D", paramsBytes, deps) - results <- processorResult{"JRZQ8A2D", data, err} - }() - - // 调用FLXGDEA9 - 需要: name, id_card, authorized - go func() { - defer func() { - if r := recover(); r != nil { - logger.Error("调用FLXGDEA9处理器时发生panic", - zap.Any("panic", r), - ) - results <- processorResult{"FLXGDEA9", nil, fmt.Errorf("处理器panic: %v", r)} - } - }() - flxgParams := map[string]interface{}{ - "name": params.Name, - "id_card": params.IDCard, - "authorized": params.Authorized, - } - paramsBytes, err := json.Marshal(flxgParams) - if err != nil { - logger.Warn("序列化FLXGDEA9参数失败", zap.Error(err)) - results <- processorResult{"FLXGDEA9", nil, err} - return - } - data, err := callProcessor(ctx, "FLXGDEA9", paramsBytes, deps) - results <- processorResult{"FLXGDEA9", data, err} - }() - - // 调用JRZQ1D09 - 需要: name, id_card, mobile_no, authorized - go func() { - defer func() { - if r := recover(); r != nil { - logger.Error("调用JRZQ1D09处理器时发生panic", - zap.Any("panic", r), - ) - results <- processorResult{"JRZQ1D09", nil, fmt.Errorf("处理器panic: %v", r)} - } - }() - jrzq1d09Params := map[string]interface{}{ - "name": params.Name, - "id_card": params.IDCard, - "mobile_no": params.MobileNo, - "authorized": params.Authorized, - } - paramsBytes, err := json.Marshal(jrzq1d09Params) - if err != nil { - logger.Warn("序列化JRZQ1D09参数失败", zap.Error(err)) - results <- processorResult{"JRZQ1D09", nil, err} - return - } - data, err := callProcessor(ctx, "JRZQ1D09", paramsBytes, deps) - results <- processorResult{"JRZQ1D09", data, err} - }() - - // 调用JRZQ8B3C - 需要: name, id_card, mobile_no (不需要authorized) - go func() { - defer func() { - if r := recover(); r != nil { - logger.Error("调用JRZQ8B3C处理器时发生panic", - zap.Any("panic", r), - ) - results <- processorResult{"JRZQ8B3C", nil, fmt.Errorf("处理器panic: %v", r)} - } - }() - jrzq8b3cParams := map[string]interface{}{ - "name": params.Name, - "id_card": params.IDCard, - "mobile_no": params.MobileNo, - } - paramsBytes, err := json.Marshal(jrzq8b3cParams) - if err != nil { - logger.Warn("序列化JRZQ8B3C参数失败", zap.Error(err)) - results <- processorResult{"JRZQ8B3C", nil, err} - return - } - data, err := callProcessor(ctx, "JRZQ8B3C", paramsBytes, deps) - results <- processorResult{"JRZQ8B3C", data, err} - }() - - // 收集结果,即使所有处理器都失败也继续 - successCount := 0 - for i := 0; i < 5; i++ { - result := <-results - if result.err != nil { - // 记录错误但不中断流程,允许部分数据缺失 - logger.Warn("调用处理器失败,将使用默认值", - zap.String("api_code", result.apiCode), - zap.Error(result.err), - ) - apiData[result.apiCode] = nil - } else { - apiData[result.apiCode] = result.data - successCount++ - } - } - - logger.Info("子处理器调用完成", - zap.Int("total", 5), - zap.Int("success", successCount), - zap.Int("failed", 5-successCount), - ) - - return apiData -} - -// callProcessor 调用指定的处理器 -func callProcessor(ctx context.Context, apiCode string, params []byte, deps *processors.ProcessorDependencies) (interface{}, error) { - // 通过CombService获取处理器 - if combSvc, ok := deps.CombService.(interface { - GetProcessor(apiCode string) (processors.ProcessorFunc, bool) - }); ok { - processor, exists := combSvc.GetProcessor(apiCode) - if !exists { - return nil, fmt.Errorf("未找到处理器: %s", apiCode) - } - respBytes, err := processor(ctx, params, deps) - if err != nil { - return nil, err - } - var data interface{} - if err := json.Unmarshal(respBytes, &data); err != nil { - return nil, fmt.Errorf("解析响应失败: %w", err) - } - return data, nil - } - - // 如果无法通过CombService获取,返回错误 - return nil, fmt.Errorf("无法获取处理器: %s,CombService不支持GetProcessor方法", apiCode) -} - -// formatDataForPDF 格式化数据为PDF生成服务需要的格式 -// 为所有子处理器提供数据,即使失败也提供默认值,确保PDF生成服务能收到完整结构 -func formatDataForPDF(apiData map[string]interface{}, params dto.PDFG01GZReq, logger *zap.Logger) []map[string]interface{} { - result := make([]map[string]interface{}, 0) - - // 1. APPLICANT_BASIC_INFO - 申请人基本信息(始终存在) - result = append(result, map[string]interface{}{ - "apiID": "APPLICANT_BASIC_INFO", - "data": map[string]interface{}{ - "name": params.Name, - "id_card": params.IDCard, - "mobile": params.MobileNo, - "query_time": time.Now().Format("2006-01-02 15:04:05"), - "report_number": generateReportNumber(), - "generate_time": time.Now().Format("2006-01-02 15:04:05"), - }, - }) - - // 2. JRZQ0L85 - 自然人综合风险智能评估模型(替代原IVYZ5A9O) - if data, ok := apiData["JRZQ0L85"]; ok && data != nil { - result = append(result, map[string]interface{}{ - "apiID": "JRZQ0L85", - "data": data, - }) - } else { - // 子处理器失败或无数据时,返回空对象 {} - logger.Debug("JRZQ0L85数据缺失,使用空对象") - result = append(result, map[string]interface{}{ - "apiID": "JRZQ0L85", - "data": map[string]interface{}{}, - }) - } - - // 3. JRZQ8A2D - 特殊名单验证B - if data, ok := apiData["JRZQ8A2D"]; ok && data != nil { - result = append(result, map[string]interface{}{ - "apiID": "JRZQ8A2D", - "data": data, - }) - } else { - logger.Debug("JRZQ8A2D数据缺失,使用空对象") - result = append(result, map[string]interface{}{ - "apiID": "JRZQ8A2D", - "data": map[string]interface{}{}, - }) - } - - // 4. FLXGDEA9 - 公安不良人员名单 - if data, ok := apiData["FLXGDEA9"]; ok && data != nil { - result = append(result, map[string]interface{}{ - "apiID": "FLXGDEA9", - "data": data, - }) - } else { - logger.Debug("FLXGDEA9数据缺失,使用空对象") - result = append(result, map[string]interface{}{ - "apiID": "FLXGDEA9", - "data": map[string]interface{}{}, - }) - } - - // 5. JRZQ1D09 - 3C租赁申请意向 - if data, ok := apiData["JRZQ1D09"]; ok && data != nil { - result = append(result, map[string]interface{}{ - "apiID": "JRZQ1D09", - "data": data, - }) - } else { - logger.Debug("JRZQ1D09数据缺失,使用空对象") - result = append(result, map[string]interface{}{ - "apiID": "JRZQ1D09", - "data": map[string]interface{}{}, - }) - } - - // 6. JRZQ8B3C - 个人消费能力等级 - if data, ok := apiData["JRZQ8B3C"]; ok && data != nil { - result = append(result, map[string]interface{}{ - "apiID": "JRZQ8B3C", - "data": data, - }) - } else { - logger.Debug("JRZQ8B3C数据缺失,使用空对象") - result = append(result, map[string]interface{}{ - "apiID": "JRZQ8B3C", - "data": map[string]interface{}{}, - }) - } - - return result -} - -// generateReportNumber 生成报告编号 -func generateReportNumber() string { - return fmt.Sprintf("RPT%s", time.Now().Format("20060102150405")) -} - -// generateReportID 生成对外可见的报告ID -// 每次请求都生成唯一的ID,格式:{report_number}-{随机字符串} -// 注意:不再包含cacheKey,因为每次请求都会重新生成,不需要通过ID定位缓存文件 -func generateReportID() string { - reportNumber := generateReportNumber() - // 生成8字节随机字符串,确保每次请求ID都不同 - randomBytes := make([]byte, 8) - if _, err := rand.Read(randomBytes); err != nil { - // 如果随机数生成失败,使用纳秒时间戳作为后备 - randomBytes = []byte(fmt.Sprintf("%d", time.Now().UnixNano())) - } - randomStr := hex.EncodeToString(randomBytes) - return fmt.Sprintf("%s-%s", reportNumber, randomStr) -} - -// generateDownloadURL 生成下载链接(基于报告ID/缓存键) -// apiDomain: 外部可访问的API域名,如 api.haiyudata.com -func generateDownloadURL(apiDomain, reportID string) string { - if apiDomain == "" { - // 兜底:保留相对路径,方便本地/测试环境使用 - return fmt.Sprintf("/api/v1/pdfg/download?id=%s", reportID) - } - // 生成完整链接,例如:https://api.haiyudata.com/api/v1/pdfg/download?id=xxx - return fmt.Sprintf("https://%s/api/v1/pdfg/download?id=%s", apiDomain, reportID) -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg1h7y_processor.go b/internal/domains/api/services/processors/qcxg/qcxg1h7y_processor.go deleted file mode 100644 index ac2b080..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg1h7y_processor.go +++ /dev/null @@ -1,47 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessQCXG1H7YRequest QCXG1H7Y API处理方法 - 车辆过户简版查询 -func ProcessQCXG1H7YRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG1H7YReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "vin": paramsDto.VinCode, - "plateNumber": paramsDto.PlateNo, - } - - // 调用极光API - // apiCode: car-vin (用于请求头) - // apiPath: car/car-vin (用于URL路径) - respBytes, err := deps.JiguangService.CallAPI(ctx, "vehicle-transfer", "vehicle/transfer", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg1u4u_processor.go b/internal/domains/api/services/processors/qcxg/qcxg1u4u_processor.go deleted file mode 100644 index 610c05a..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg1u4u_processor.go +++ /dev/null @@ -1,49 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessQCXG1U4URequest QCXG1U4U API处理方法 - 车辆里程记录(混合查询) -func ProcessQCXG1U4URequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG1U4UReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "vin": paramsDto.VinCode, - "licensePlate": paramsDto.PlateNo, - "callbackUrl": paramsDto.ReturnURL, - "imageUrl": paramsDto.ImageURL, - "regUrl": paramsDto.RegURL, - "engine": paramsDto.EngineNumber, - } - - // 调用极光API - respBytes, err := deps.JiguangService.CallAPI(ctx, "car-mileage-b", "vehicle/car-mileage-b", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg2t6s_processor.go b/internal/domains/api/services/processors/qcxg/qcxg2t6s_processor.go deleted file mode 100644 index fe9417a..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg2t6s_processor.go +++ /dev/null @@ -1,47 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessQCXG2T6SRequest QCXG2T6S API处理方法 - 车辆里程记录(品牌查询) -func ProcessQCXG2T6SRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG2T6SReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "vin": paramsDto.VinCode, - "licensePlate": paramsDto.PlateNo, - "callbackUrl": paramsDto.ReturnURL, - "imageUrl": paramsDto.ImageURL, - } - - // 调用极光API - respBytes, err := deps.JiguangService.CallAPI(ctx, "car-mileage-a", "vehicle/car-mileage-a", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg3b8z_processor.go b/internal/domains/api/services/processors/qcxg/qcxg3b8z_processor.go deleted file mode 100644 index de84a2c..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg3b8z_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessQCXG3B8ZRequest QCXG3B8Z 疑似运营车辆查询(月度里程)10268 API 处理方法(使用数据宝服务示例) -func ProcessQCXG3B8ZRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG3B8ZReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建数据宝入参:姓名、身份证、手机号、银行卡号(sign 外的业务参数可按需 AES 加密后作为 bodyData) - reqParams := map[string]interface{}{ - "key": "c94605174cfe29bb2a62e2600b7d1596", - "carNo": paramsDto.PlateNo, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10268" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg3m7z_processor.go b/internal/domains/api/services/processors/qcxg/qcxg3m7z_processor.go deleted file mode 100644 index 646bcb1..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg3m7z_processor.go +++ /dev/null @@ -1,50 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessQCXG3M7ZRequest QCXG3M7Z 人车关系核验(ETC)10093 月更 API 处理方法(使用数据宝服务示例) -func ProcessQCXG3M7ZRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG3M7ZReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建数据宝入参:姓名、身份证、手机号、银行卡号(sign 外的业务参数可按需 AES 加密后作为 bodyData) - reqParams := map[string]interface{}{ - "key": "a2f32fc54b44ebc85b97a2aaff1734ec", - "carNo": paramsDto.PlateNo, - "name": paramsDto.Name, - "plateColor": paramsDto.PlateColor, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10093" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg3y6b_processor.go b/internal/domains/api/services/processors/qcxg/qcxg3y6b_processor.go deleted file mode 100644 index d12f1b3..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg3y6b_processor.go +++ /dev/null @@ -1,49 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessQCXG3Y6BRequest QCXG3Y6B API处理方法 - 车辆维保简版查询 -func ProcessQCXG3Y6BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG1U4UReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "vin": paramsDto.VinCode, - "licensePlate": paramsDto.PlateNo, - "notifyUrl": paramsDto.ReturnURL, - "imageUrl": paramsDto.ImageURL, - "regUrl": paramsDto.RegURL, - "engine": paramsDto.EngineNumber, - } - - // 调用极光API - respBytes, err := deps.JiguangService.CallAPI(ctx, "car-maintenance-info-v2", "vehicle/car-maintenance-info-v2", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg3z3l_processor.go b/internal/domains/api/services/processors/qcxg/qcxg3z3l_processor.go deleted file mode 100644 index e1d95df..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg3z3l_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessQCXG3Z3LRequest QCXG3Z3L API处理方法 - 车辆维保详细版查询 -func ProcessQCXG3Z3LRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG3Z3LReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "vin": paramsDto.VinCode, - "notifyUrl": paramsDto.ReturnURL, - "imageUrl": paramsDto.ImageURL, - "plateNo": paramsDto.PlateNo, - "engine": paramsDto.EngineNumber, - } - - // 调用极光API - respBytes, err := deps.JiguangService.CallAPI(ctx, "car-maintenance-info-v2", "vehicle/car-maintenance-info-v2", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg4896_processor.go b/internal/domains/api/services/processors/qcxg/qcxg4896_processor.go deleted file mode 100644 index b6f959c..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg4896_processor.go +++ /dev/null @@ -1,52 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - "strings" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/muzi" -) - -// ProcessQCXG4896MRequest QCXG4896 API处理方法 - 网约车风险查询 -func ProcessQCXG4896Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG4896Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - - paramSign := map[string]interface{}{ - "paramName": "licenseNo", - "paramValue": paramsDto.PlateNo, - } - - reqData := map[string]interface{}{ - "paramName": "licenseNo", - "paramValue": paramsDto.PlateNo, - "startTime": strings.Split(paramsDto.AuthDate, "-")[0], - "endTime": strings.Split(paramsDto.AuthDate, "-")[1], - } - - respData, err := deps.MuziService.CallAPI(ctx, "PC0031", "/hailingScoreBySearch", reqData,paramSign) - if err != nil { - switch { - case errors.Is(err, muzi.ErrDatasource): - return nil, errors.Join(processors.ErrDatasource, err) - case errors.Is(err, muzi.ErrSystem): - return nil, errors.Join(processors.ErrSystem, err) - default: - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respData, nil - -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg4d2e_processor.go b/internal/domains/api/services/processors/qcxg/qcxg4d2e_processor.go deleted file mode 100644 index b933840..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg4d2e_processor.go +++ /dev/null @@ -1,47 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessQCXG4D2ERequest QCXG4D2E API处理方法 - 极光名下车辆数量查询 -func ProcessQCXG4D2ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG4D2EReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "idNum": paramsDto.IDCard, - "userType": paramsDto.UserType, - } - - // 调用极光API - // apiCode: vehicle-inquiry-under-name (用于请求头) - // apiPath: vehicle/inquiry-under-name (用于URL路径) - respBytes, err := deps.JiguangService.CallAPI(ctx, "vehicle-inquiry-under-name", "vehicle/inquiry-under-name", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg4i1z_processor.go b/internal/domains/api/services/processors/qcxg/qcxg4i1z_processor.go deleted file mode 100644 index ca1bc7b..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg4i1z_processor.go +++ /dev/null @@ -1,46 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessQCXG4I1ZRequest QCXG4I1Z API处理方法 - 车辆过户详版查询 -func ProcessQCXG4I1ZRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG4I1ZReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "vin": paramsDto.VinCode, - } - - // 调用极光API - // apiCode: car-vin (用于请求头) - // apiPath: car/car-vin (用于URL路径) - respBytes, err := deps.JiguangService.CallAPI(ctx, "transfer-information", "vehicle/transfer-information", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg521l_processor.go b/internal/domains/api/services/processors/qcxg/qcxg521l_processor.go new file mode 100644 index 0000000..cf715ff --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/qcxg521l_processor.go @@ -0,0 +1,14 @@ +package qcxg + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessQCXG521LRequest QCXG5U0Z 车辆静态信息查询(天远中转) +func ProcessQCXG521LRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QCXG521LReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "QCXG5U0Z", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/qcxg/qcxg5f3a_processor.go b/internal/domains/api/services/processors/qcxg/qcxg5f3a_processor.go deleted file mode 100644 index ccbce51..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg5f3a_processor.go +++ /dev/null @@ -1,52 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessQCXG5F3ARequest QCXG5F3A API处理方法 - 极光名下车辆车牌查询 -func ProcessQCXG5F3ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG5F3AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - null := "" - // 构建请求参数 - reqData := map[string]interface{}{ - "id_card": paramsDto.IDCard, - "name": paramsDto.Name, - "userType": null, - "vehicleType": null, - "encryptionType": null, - "encryptionContent": null, - } - - // 调用极光API - // apiCode: vehicle-person-vehicles (用于请求头) - // apiPath: vehicle/person-vehicles (用于URL路径) - respBytes, err := deps.JiguangService.CallAPI(ctx, "vehicle-person-vehicles", "vehicle/person-vehicles", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg5u0z_processor.go b/internal/domains/api/services/processors/qcxg/qcxg5u0z_processor.go deleted file mode 100644 index 9e62cd1..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg5u0z_processor.go +++ /dev/null @@ -1,46 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessQCXG5U0ZRequest QCXG5U0Z 车辆静态信息查询 10479 API 处理方法(使用数据宝服务) -func ProcessQCXG5U0ZRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG5U0ZReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqParams := map[string]interface{}{ - "key": "7c8122677476dd2621f574976f1a9fde", - "vinList": paramsDto.VinCode, - } - - apiPath := "/communication/personal/10479" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg6b4e_processor.go b/internal/domains/api/services/processors/qcxg/qcxg6b4e_processor.go deleted file mode 100644 index 7a89a76..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg6b4e_processor.go +++ /dev/null @@ -1,45 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessQCXG6B4ERequest QCXG6B4E API处理方法 - 车辆出险记录查验 -func ProcessQCXG6B4ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG6B4EReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqData := map[string]interface{}{ - "vin": paramsDto.VINCode, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI049", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为 JSON 字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg76va_processor.go b/internal/domains/api/services/processors/qcxg/qcxg76va_processor.go new file mode 100644 index 0000000..67220e2 --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/qcxg76va_processor.go @@ -0,0 +1,14 @@ +package qcxg + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessQCXG76VARequest QCXG3B8Z 疑似运营车辆查询(月度里程)(天远中转) +func ProcessQCXG76VARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QCXG76VAReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "QCXG3B8Z", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/qcxg/qcxg7a2b_processor.go b/internal/domains/api/services/processors/qcxg/qcxg7a2b_processor.go deleted file mode 100644 index 83c8f55..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg7a2b_processor.go +++ /dev/null @@ -1,38 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/yushan" -) - -// ProcessQCXG7A2BRequest QCXG7A2B API处理方法 -func ProcessQCXG7A2BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG7A2BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqData := map[string]interface{}{ - "cardNo": paramsDto.PlateNo, - } - - respBytes, err := deps.YushanService.CallAPI(ctx, "CAR061", reqData) - if err != nil { - if errors.Is(err, yushan.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg8a3d_processor.go b/internal/domains/api/services/processors/qcxg/qcxg8a3d_processor.go deleted file mode 100644 index 264a1b6..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg8a3d_processor.go +++ /dev/null @@ -1,49 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessQCXG8A3DRequest QCXG8A3D API处理方法 - 车辆七项信息核验 -func ProcessQCXG8A3DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG8A3DReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqData := map[string]interface{}{ - "plate": paramsDto.PlateNo, - "authorized": paramsDto.Authorized, - } - // 如果传了车牌类型,则添加到请求数据中 - if paramsDto.PlateType != "" { - reqData["vehType"] = paramsDto.PlateType - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI048", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为 JSON 字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg9f5c_processor.go b/internal/domains/api/services/processors/qcxg/qcxg9f5c_processor.go deleted file mode 100644 index 072d19a..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg9f5c_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessQCXG9F5CERequest QCXG9F5C 疑似营运车辆注册平台数 10386 API 处理方法(使用数据宝服务示例) -func ProcessQCXG9F5CERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG9F5CReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建数据宝入参:姓名、身份证、手机号、银行卡号(sign 外的业务参数可按需 AES 加密后作为 bodyData) - reqParams := map[string]interface{}{ - "key": "27ab7048dda23d9a56178a2e5d4300ec", - "carNo": paramsDto.PlateNo, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10386" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxg9p1c_processor.go b/internal/domains/api/services/processors/qcxg/qcxg9p1c_processor.go deleted file mode 100644 index 5b88ac4..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxg9p1c_processor.go +++ /dev/null @@ -1,77 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - "strconv" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" - - "github.com/tidwall/gjson" -) - -// ProcessQCXG9P1CRequest QCXG9P1C API处理方法 兼容旧版 极光名下车牌查询数量 -func ProcessQCXG9P1CRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXG9P1CReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - null := "" - // 构建请求参数 - reqData := map[string]interface{}{ - "id_card": paramsDto.IDCard, - "name": null, - "userType": null, - "vehicleType": null, - "encryptionType": null, - "encryptionContent": null, - } - - // 调用极光API - // apiCode: vehicle-person-vehicles (用于请求头) - // apiPath: vehicle/person-vehicles (用于URL路径) - respBytes, err := deps.JiguangService.CallAPI(ctx, "vehicle-person-vehicles", "vehicle/person-vehicles", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 使用 gjson 检查并转换 vehicleCount 字段 - vehicleCountResult := gjson.GetBytes(respBytes, "vehicleCount") - if vehicleCountResult.Exists() && vehicleCountResult.Type == gjson.String { - // 如果是字符串类型,转换为整数 - vehicleCountInt, err := strconv.Atoi(vehicleCountResult.String()) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - // 解析 JSON 并修改 vehicleCount 字段 - var respData map[string]interface{} - if err := json.Unmarshal(respBytes, &respData); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - respData["vehicleCount"] = vehicleCountInt - // 重新序列化为JSON并返回 - resultBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return resultBytes, nil - } - - // 如果 vehicleCount 不存在或不是字符串,直接返回原始响应 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxgfv9w_processor.go b/internal/domains/api/services/processors/qcxg/qcxgfv9w_processor.go new file mode 100644 index 0000000..6f108de --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/qcxgfv9w_processor.go @@ -0,0 +1,14 @@ +package qcxg + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessQCXGFV9WRequest QCXG9F5C 疑似营运车辆注册平台数(天远中转) +func ProcessQCXGFV9WRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QCXGFV9WReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "QCXG9F5C", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/qcxg/qcxggb2q_processor.go b/internal/domains/api/services/processors/qcxg/qcxggb2q_processor.go deleted file mode 100644 index 6227996..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxggb2q_processor.go +++ /dev/null @@ -1,79 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// CarPlateTypeMap 号牌类型代码到名称的映射 -var CarPlateTypeMap = map[string]string{ - "01": "大型汽车", - "02": "小型汽车", - "03": "使馆汽车", - "04": "领馆汽车", - "05": "境外汽车", - "06": "外籍汽车", - "07": "普通摩托车", - "08": "轻便摩托车", - "09": "使馆摩托车", - "10": "领馆摩托车", - "11": "境外摩托车", - "12": "外籍摩托车", - "13": "低速车", - "14": "拖拉机", - "15": "挂车", - "16": "教练汽车", - "17": "教练摩托车", - "20": "临时入境汽车", - "21": "临时入境摩托车", - "22": "临时行驶车", - "23": "警用汽车", - "24": "警用摩托", - "51": "新能源大型车", - "52": "新能源小型车", -} - -// getCarPlateTypeName 根据号牌类型代码获取中文名称 -func getCarPlateTypeName(code string) string { - if name, exists := CarPlateTypeMap[code]; exists { - return name - } - return code // 如果找不到,返回原值 -} - -// ProcessQCXGGB2QRequest QCXGGB2Q API处理方法 - 车辆二要素核验V1 -func ProcessQCXGGB2QRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXGGB2QReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数,将号牌类型代码转换为中文名称 - reqData := map[string]interface{}{ - "plateNumber": paramsDto.PlateNo, - "owner": paramsDto.Name, - "plateType": getCarPlateTypeName(paramsDto.CarPlateType), - } - - respBytes, err := deps.JiguangService.CallAPI(ctx, "vehicle-factor-two-auth", "vehicle/factor-two-auth", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxggfww_processor.go b/internal/domains/api/services/processors/qcxg/qcxggfww_processor.go new file mode 100644 index 0000000..c9baa7f --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/qcxggfww_processor.go @@ -0,0 +1,14 @@ +package qcxg + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessQCXGGFWWRequest QCXGM7R9 疑似运营车辆查询(半年度里程)(天远中转) +func ProcessQCXGGFWWRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QCXGGFWWReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "QCXGM7R9", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/qcxg/qcxggj3a_processor.go b/internal/domains/api/services/processors/qcxg/qcxggj3a_processor.go deleted file mode 100644 index 1c03c52..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxggj3a_processor.go +++ /dev/null @@ -1,46 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessQCXGGJ3ARequest QCXGGJ3A API处理方法 - 车辆vin码查询号牌 -func ProcessQCXGGJ3ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXGGJ3AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "vin": paramsDto.VinCode, - } - - // 调用极光API - // apiCode: car-vin (用于请求头) - // apiPath: car/car-vin (用于URL路径) - respBytes, err := deps.JiguangService.CallAPI(ctx, "car-vin", "vehicle/car-vin", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxgm4cl_processor.go b/internal/domains/api/services/processors/qcxg/qcxgijy3_processor.go similarity index 88% rename from internal/domains/api/services/processors/qcxg/qcxgm4cl_processor.go rename to internal/domains/api/services/processors/qcxg/qcxgijy3_processor.go index e4f876d..c3fd4cf 100644 --- a/internal/domains/api/services/processors/qcxg/qcxgm4cl_processor.go +++ b/internal/domains/api/services/processors/qcxg/qcxgijy3_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessQCXGM4CLRequest QCXGM4CL API处理方法 - 名下车辆诺尔 -func ProcessQCXGM4CLRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXGM4CLReq +// ProcessQCXGIJY3Request QCXGM4CL API处理方法 - 名下车辆诺尔 +func ProcessQCXGIJY3Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QCXGIJY3Req if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/qcxg/qcxgjj2a_processor.go b/internal/domains/api/services/processors/qcxg/qcxgjj2a_processor.go deleted file mode 100644 index ca911c1..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxgjj2a_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessQCXGJJ2ARequest QCXGJJ2A API处理方法 - vin码查车辆信息(一对多) -func ProcessQCXGJJ2ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXGJJ2AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "vin": paramsDto.VinCode, - "engineNumber": paramsDto.EngineNumber, - "noticeModel": paramsDto.NoticeModel, - } - - // 调用极光API - // apiCode: carInfo-vin (用于请求头) - // apiPath: car/carInfo-vin (用于URL路径) - respBytes, err := deps.JiguangService.CallAPI(ctx, "carInfo-vin", "car/carInfo-vin", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxgm7r9_processor.go b/internal/domains/api/services/processors/qcxg/qcxgm7r9_processor.go deleted file mode 100644 index 649b570..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxgm7r9_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessQCXGM7R9Request QCXGM7R9 疑似运营车辆查询(半年度里程)10270 API 处理方法(使用数据宝服务示例) -func ProcessQCXGM7R9Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXGM7R9Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建数据宝入参:姓名、身份证、手机号、银行卡号(sign 外的业务参数可按需 AES 加密后作为 bodyData) - reqParams := map[string]interface{}{ - "key": "fc335ea4308add7454ac0858b08bef72", - "carNo": paramsDto.PlateNo, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10270" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxgp00w_processor.go b/internal/domains/api/services/processors/qcxg/qcxgp00w_processor.go deleted file mode 100644 index c85104a..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxgp00w_processor.go +++ /dev/null @@ -1,45 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessQCXGP00WRequest QCXGP00W API处理方法 - 车辆出险详版查询 -func ProcessQCXGP00WRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXGP00WReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "vin": paramsDto.VinCode, - "licenseNo": paramsDto.PlateNo, - "notifyUrl": paramsDto.ReturnURL, - "image": paramsDto.VlPhotoData, - } - - respBytes, err := deps.JiguangService.CallAPI(ctx, "car-accident-order-high", "car-accident-precision-order", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxgp1w3_processor.go b/internal/domains/api/services/processors/qcxg/qcxgp1w3_processor.go deleted file mode 100644 index 2ec8b38..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxgp1w3_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessQCXGP1W3Request QCXGP1W3 疑似运营车辆查询(季度里程)10269 API 处理方法(使用数据宝服务示例) -func ProcessQCXGP1W3Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXGP1W3Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建数据宝入参:姓名、身份证、手机号、银行卡号(sign 外的业务参数可按需 AES 加密后作为 bodyData) - reqParams := map[string]interface{}{ - "key": "ecd6f3485322b0c706fc1dce330fe26e", - "carNo": paramsDto.PlateNo, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10269" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxgu2k4_processor.go b/internal/domains/api/services/processors/qcxg/qcxgu2k4_processor.go deleted file mode 100644 index f650c9e..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxgu2k4_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessQCXGU2K4Request QCXGU2K4 疑似运营车辆查询(年度里程)10271 API 处理方法(使用数据宝服务示例) -func ProcessQCXGU2K4Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXGU2K4Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建数据宝入参:姓名、身份证、手机号、银行卡号(sign 外的业务参数可按需 AES 加密后作为 bodyData) - reqParams := map[string]interface{}{ - "key": "8c02f9c755b37b5a1bd39fc6ac9569d6", - "carNo": paramsDto.PlateNo, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10271" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxgy7f2_processor.go b/internal/domains/api/services/processors/qcxg/qcxgy7f2_processor.go deleted file mode 100644 index 15b9ac8..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxgy7f2_processor.go +++ /dev/null @@ -1,50 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessQCXGY7F2Request QCXGY7F2 二手车VIN估值 10443 API 处理方法(使用数据宝服务) -func ProcessQCXGY7F2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXGY7F2Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqParams := map[string]interface{}{ - "key": "463cea654a0a99d5d04c62f98ac882c0", - "vin": paramsDto.VinCode, - "model_name": paramsDto.VehicleName, - "Vehicle_location": paramsDto.VehicleLocation, - "firstRegistrationDate": paramsDto.FirstRegistrationdate, - "color": paramsDto.Color, - } - - apiPath := "/government/traffic/10443" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxgyqdc_processor.go b/internal/domains/api/services/processors/qcxg/qcxgyqdc_processor.go new file mode 100644 index 0000000..074c69d --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/qcxgyqdc_processor.go @@ -0,0 +1,14 @@ +package qcxg + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessQCXGYQDCRequest QCXGP1W3 疑似运营车辆查询(季度里程)(天远中转) +func ProcessQCXGYQDCRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QCXGYQDCReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "QCXGP1W3", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/qcxg/qcxgyts2_processor.go b/internal/domains/api/services/processors/qcxg/qcxgyts2_processor.go deleted file mode 100644 index 89e8411..0000000 --- a/internal/domains/api/services/processors/qcxg/qcxgyts2_processor.go +++ /dev/null @@ -1,44 +0,0 @@ -package qcxg - -import ( - "context" - "encoding/json" - "errors" - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/jiguang" -) - -// ProcessQCXGYTS2Request QCXGYTS2 API处理方法 - 车辆二要素核验v2 -func ProcessQCXGYTS2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QCXGYTS2Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求参数 - reqData := map[string]interface{}{ - "vin": paramsDto.VinCode, - "plate": paramsDto.PlateNo, - "name": paramsDto.Name, - } - - respBytes, err := deps.JiguangService.CallAPI(ctx, "vehicle-person-and-vehicle-verification-v2", "vehicle/person-and-vehicle-verification-v2", reqData) - if err != nil { - // 根据错误类型返回相应的错误 - if errors.Is(err, jiguang.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, jiguang.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 极光服务已经返回了 data 字段的 JSON,直接返回即可 - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qcxg/qcxgywsv_processor.go b/internal/domains/api/services/processors/qcxg/qcxgywsv_processor.go new file mode 100644 index 0000000..11c6004 --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/qcxgywsv_processor.go @@ -0,0 +1,14 @@ +package qcxg + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessQCXGYWSVRequest QCXGU2K4 疑似运营车辆查询(年度里程)(天远中转) +func ProcessQCXGYWSVRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QCXGYWSVReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "QCXGU2K4", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/qygl/coment01_processor.go b/internal/domains/api/services/processors/qygl/coment01_processor.go deleted file mode 100644 index b6460ab..0000000 --- a/internal/domains/api/services/processors/qygl/coment01_processor.go +++ /dev/null @@ -1,69 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "strings" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessCOMENT01Request COMENT01 API处理方法 - 企业风险报告 -func ProcessCOMENT01Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.COMENT01Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求体 - requestBody := map[string]string{ - "company_name": paramsDto.EntName, - "credit_code": paramsDto.EntCode, - } - - requestBodyBytes, err := json.Marshal(requestBody) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // 创建HTTP请求 - url := "https://api.v1.tybigdata.com/api/v1/enterprise/risk-report" - req, err := http.NewRequestWithContext(ctx, "POST", url, strings.NewReader(string(requestBodyBytes))) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // 设置请求头 - req.Header.Set("Content-Type", "application/json") - req.Header.Set("apikey", "1000000$BUsWYV5DQ3CSvPWYYegkr3$TZmMl7WZ29Zj5gcRmgieoqVs1oBjOt3BPWGq7iTSF5o") - - // 发送请求 - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - return nil, errors.Join(processors.ErrDatasource, err) - } - defer resp.Body.Close() - - // 检查HTTP状态码 - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("%s: HTTP状态码异常: %d", processors.ErrDatasource, resp.StatusCode) - } - - // 读取响应 - respBody, err := io.ReadAll(resp.Body) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBody, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl23t7_processor.go b/internal/domains/api/services/processors/qygl/qygl23t7_processor.go deleted file mode 100644 index b117a0a..0000000 --- a/internal/domains/api/services/processors/qygl/qygl23t7_processor.go +++ /dev/null @@ -1,121 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "fmt" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - - "github.com/tidwall/gjson" -) - -// ProcessQYGL23T7Request QYGL23T7 API处理方法 - 企业四要素验证 -func ProcessQYGL23T7Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL23T7Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建API调用参数 - apiParams := map[string]string{ - "code": paramsDto.EntCode, - "name": paramsDto.EntName, - "legalPersonName": paramsDto.LegalPerson, - } - - // 调用天眼查API - 使用通用的CallAPI方法 - response, err := deps.TianYanChaService.CallAPI(ctx, "VerifyThreeElements", apiParams) - if err != nil { - return nil, convertTianYanChaError(err) - } - - // 检查天眼查API调用是否成功 - if !response.Success { - // 天眼查API调用失败,返回企业信息校验不通过 - return createStatusResponse(1), nil - } - - // 解析天眼查响应数据 - if response.Data == nil { - // 天眼查响应数据为空,返回企业信息校验不通过 - return createStatusResponse(1), nil - } - - // 将response.Data转换为JSON字符串,然后使用gjson解析 - dataBytes, err := json.Marshal(response.Data) - if err != nil { - // 数据序列化失败,返回企业信息校验不通过 - return createStatusResponse(1), nil - } - - // 使用gjson解析嵌套的data.result.data字段 - result := gjson.GetBytes(dataBytes, "result") - if !result.Exists() { - // 字段不存在,返回企业信息校验不通过 - return createStatusResponse(1), nil - } - - // 检查data.result.data是否等于1 - if result.Int() != 1 { - // 不等于1,返回企业信息校验不通过 - return createStatusResponse(1), nil - } - - // 天眼查三要素验证通过,继续调用阿里云身份证二要素验证 - // 构建阿里云二要素验证请求参数 - reqData := map[string]interface{}{ - "name": paramsDto.LegalPerson, - "idcard": paramsDto.IDCard, - } - - // 调用阿里云二要素验证API - respBytes, err := deps.AlicloudService.CallAPI("api-mall/api/id_card/check", reqData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // 解析阿里云响应 - var alicloudResponse struct { - Msg string `json:"msg"` - Success bool `json:"success"` - Code int `json:"code"` - Data struct { - Birthday string `json:"birthday"` - Result int `json:"result"` - Address string `json:"address"` - OrderNo string `json:"orderNo"` - Sex string `json:"sex"` - Desc string `json:"desc"` - } `json:"data"` - } - - if err := json.Unmarshal(respBytes, &alicloudResponse); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // 检查响应状态 - if alicloudResponse.Code != 200 && alicloudResponse.Code != 400 { - return nil, fmt.Errorf("%s: %s", processors.ErrDatasource, alicloudResponse.Msg) - } - - // 根据阿里云响应结果返回状态 - if alicloudResponse.Code == 400 { - // 身份证号格式错误,返回状态2 - return createStatusResponse(2), nil - } else { - if alicloudResponse.Data.Result == 0 { - // 验证通过,返回状态0 - return createStatusResponse(0), nil - } else { - // 验证失败,返回状态2 - return createStatusResponse(2), nil - } - } -} diff --git a/internal/domains/api/services/processors/qygl/qygl2acd_processor.go b/internal/domains/api/services/processors/qygl/qygl2acd_processor.go deleted file mode 100644 index 0720308..0000000 --- a/internal/domains/api/services/processors/qygl/qygl2acd_processor.go +++ /dev/null @@ -1,57 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessQYGL2ACDRequest QYGL2ACD API处理方法 -func ProcessQYGL2ACDRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL2ACDReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedEntName, err := deps.WestDexService.Encrypt(paramsDto.EntName) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedLegalPerson, err := deps.WestDexService.Encrypt(paramsDto.LegalPerson) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedEntCode, err := deps.WestDexService.Encrypt(paramsDto.EntCode) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedEntName, - "oper_name": encryptedLegalPerson, - "keyword": encryptedEntCode, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "WEST00022", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl2b5c_processor.go b/internal/domains/api/services/processors/qygl/qygl2b5c_processor.go deleted file mode 100644 index 414545b..0000000 --- a/internal/domains/api/services/processors/qygl/qygl2b5c_processor.go +++ /dev/null @@ -1,59 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "fmt" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessQYGL2B5CRequest QYGL2B5C API处理方法 - 企业联系人实际经营地址 -func ProcessQYGL2B5CRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL2B5CReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 两选一校验:EntName 和 EntCode 至少传一个 - var keyword string - if paramsDto.EntName == "" && paramsDto.EntCode == "" { - return nil, fmt.Errorf("%s: %w", processors.ErrInvalidParam, errors.New("必须提供企业名称或企业统一信用代码中的其中一个")) - } - - // 确定使用哪个值作为 keyword - if paramsDto.EntName != "" { - keyword = paramsDto.EntName - } else { - keyword = paramsDto.EntCode - } - - reqData := map[string]interface{}{ - "keyword": keyword, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI050", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为 JSON 字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl2nao_processor.go b/internal/domains/api/services/processors/qygl/qygl2nao_processor.go deleted file mode 100644 index 84a5665..0000000 --- a/internal/domains/api/services/processors/qygl/qygl2nao_processor.go +++ /dev/null @@ -1,58 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "strconv" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessQYGL2naoRequest QYGL2NAO API处理方法 - 股权变更 -func ProcessQYGL2naoRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL2naoReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - // 设置默认值 - pageSize := paramsDto.PageSize - if pageSize == 0 { - pageSize = int64(20) - } - pageNum := paramsDto.PageNum - if pageNum == 0 { - pageNum = int64(1) - } - - // 构建API调用参数 - apiParams := map[string]string{ - "keyword": paramsDto.EntCode, - "pageSize": strconv.FormatInt(pageSize, 10), - "pageNum": strconv.FormatInt(pageNum, 10), - } - - // 调用天眼查API - 企业基本信息 - response, err := deps.TianYanChaService.CallAPI(ctx, "holderChange", apiParams) - if err != nil { - return nil, convertTianYanChaError(err) - } - - // 检查天眼查API调用是否成功 - if !response.Success { - return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message)) - } - - // 返回天眼查响应数据 - respBytes, err := json.Marshal(response.Data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl2s0w_processor.go b/internal/domains/api/services/processors/qygl/qygl2s0w_processor.go deleted file mode 100644 index 021cc5c..0000000 --- a/internal/domains/api/services/processors/qygl/qygl2s0w_processor.go +++ /dev/null @@ -1,79 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "fmt" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// Processqygl2s0wRequest QYGL2S0W API处理方法 - 失信被执行企业个人查询 -func ProcessQYGL2S0WRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL2S0WReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 验证逻辑 - var nameValue string - if paramsDto.Type == "per" { - // 个人查询:idCardNum 必填 - nameValue = paramsDto.Name - if paramsDto.IDCard == "" { - fmt.Print("个人身份证件号不能为空") - return nil, fmt.Errorf("%s: %w", processors.ErrInvalidParam, errors.New("当失信被执行人类型为个人时,身份证件号不能为空")) - } - if paramsDto.IDCard == "410482198504029333" { - return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空")) - } - } else if paramsDto.Type == "ent" { - // 企业查询:name 和 entMark 两者必填其一 - nameValue = paramsDto.EntName - if paramsDto.EntName == "" && paramsDto.EntCode == "" { - return nil, fmt.Errorf("%s: %w", processors.ErrInvalidParam, errors.New("当查询为企业时,企业名称和企业标识统一代码注册号两者必填其一")) - } // 确定使用哪个值作为 name - if paramsDto.EntName != "" { - nameValue = paramsDto.EntName - } else { - nameValue = paramsDto.EntCode - } - } - - fmt.Println("dto2s0w", paramsDto) - // 构建请求数据(不传的参数也需要添加,值为空字符串) - reqData := map[string]interface{}{ - "idCardNum": paramsDto.IDCard, - "name": nameValue, - "entMark": paramsDto.EntCode, - "type": paramsDto.Type, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1079244717102657536" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - // 查空情况,返回特定的查空错误 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl3f8e_processor.go b/internal/domains/api/services/processors/qygl/qygl3f8e_processor.go deleted file mode 100644 index 02327c4..0000000 --- a/internal/domains/api/services/processors/qygl/qygl3f8e_processor.go +++ /dev/null @@ -1,1141 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "sort" - "strconv" - "strings" - "sync" - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/shared/logger" - - "github.com/tidwall/gjson" - "go.uber.org/zap" -) - -// ProcessQYGL3F8ERequest QYGL3F8E API处理方法 - 人企关系加强版 -func ProcessQYGL3F8ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - // 使用 zap.L() 获取全局日志器 - log := logger.L() - - // 记录请求开始 - log.Info("QYGL3F8E处理器开始处理请求") - - var paramsDto dto.QYGL3F8EReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - log.Error("QYGL3F8E参数解析失败", zap.Error(err)) - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - log.Warn("QYGL3F8E参数验证失败", zap.Error(err)) - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 设置最大处理企业数量 - maxProcessCount := 3 - - // 1. 首先调用QYGL6S1B获取个人关联的企业信息 - b4c0Params := dto.QYGL6S1BReq{ - IDCard: paramsDto.IDCard, - Authorized: "1", - } - b4c0ParamsBytes, err := json.Marshal(b4c0Params) - if err != nil { - log.Error("QYGL3F8E构建QYGL6S1B参数失败", zap.Error(err)) - return nil, errors.Join(processors.ErrSystem, err) - } - - b4c0Response, err := ProcessQYGL6S1BRequest(ctx, b4c0ParamsBytes, deps) - if err != nil { - log.Error("QYGL3F8E调用QYGL6S1B失败", zap.Error(err)) - return nil, err // 错误已经是处理器标准错误,直接返回 - } - - // 2. 解析QYGL6S1B的响应,获取企业列表 - companies, err := parseCompaniesFrom6S1BResponse(b4c0Response) - if err != nil { - log.Error("QYGL3F8E解析QYGL6S1B响应失败", zap.Error(err)) - return nil, errors.Join(processors.ErrSystem, err) - } - - log.Info("QYGL3F8E解析企业列表完成", - zap.Int("total_companies", len(companies)), - ) - - if len(companies) == 0 { - // 没有关联企业,返回空的简化格式 - log.Info("QYGL3F8E未找到关联企业,返回空结果") - emptyResponse := map[string]interface{}{ - "items": []interface{}{}, - "total": 0, - } - return json.Marshal(emptyResponse) - } - - // 3. 对企业进行优先级排序 - sortedCompanies := sortCompaniesByPriority(companies) - - // 4. 限制处理数量 - processCount := len(sortedCompanies) - if processCount > maxProcessCount { - processCount = maxProcessCount - } - - // 保存用户输入的身份证号,用于后续查询 - userIDCard := paramsDto.IDCard - - // 5. 并发调用其他处理器获取企业详细信息 - enrichedCompanies, err := enrichCompaniesWithDetails(ctx, sortedCompanies[:processCount], userIDCard, deps) - if err != nil { - log.Error("QYGL3F8E并发获取企业详细信息失败", zap.Error(err)) - return nil, errors.Join(processors.ErrSystem, err) - } - - // 6. 构建最终响应 - finalResponse, err := buildFinalResponse(enrichedCompanies, sortedCompanies) - if err != nil { - log.Error("QYGL3F8E构建最终响应失败", zap.Error(err)) - return nil, errors.Join(processors.ErrSystem, err) - } - - log.Info("QYGL3F8E处理器处理完成", - zap.Int("response_size", len(finalResponse)), - zap.Int("total_companies", len(sortedCompanies)), - ) - - return finalResponse, nil -} - -// CompanyInfo 企业信息结构 -type CompanyInfo struct { - Index int - Data gjson.Result - Name string - CreditCode string - Relationship []string - RelationshipVal int // 关系权重值 - RelationCount int // 关系数量 - AdminPenalty int // 行政处罚数量 - Executed int // 被执行人数量 - Dishonest int // 失信被执行人数量 - RegCapValue float64 // 注册资本数值(用于排序,单位统一为“万”,含“亿”时换算为万) -} - -// parseCompaniesFrom6S1BResponse 从QYGL6S1B响应中解析企业列表 -func parseCompaniesFrom6S1BResponse(response []byte) ([]CompanyInfo, error) { - // 解析响应数据 - 根对象下的各个数组 - //担任法人信息 - legRepInfoList := gjson.GetBytes(response, "legRepInfoList") - //shareholderList 股东 - shareholderList := gjson.GetBytes(response, "shareholderList") - //ryPosPerList 高管 - ryPosPerList := gjson.GetBytes(response, "ryPosPerList") - //caseInfoList 行政处罚(可能为空) - caseInfoList := gjson.GetBytes(response, "caseInfoList") - //performerList 被执行人(可能为空) - performerList := gjson.GetBytes(response, "performerList") - //lossPromiseList 失信被执行人(可能为空) - lossPromiseList := gjson.GetBytes(response, "lossPromiseList") - - // 分别从三个列表获取企业信息,然后合并成一个扁平列表 - // 将三个数组格式 [{},{}],[{},{}],[{},{}] 合并成单个扁平数组 [{},{},{},{},{},{},{},{}] - // 构建企业数据列表,包含来源信息 - type CompanyWithSource struct { - json gjson.Result - source string // 标识来源:legRepInfoList, shareholderList, ryPosPerList - } - companiesWithSource := make([]CompanyWithSource, 0) - - // 从legRepInfoList获取企业并添加到合并列表 - if legRepInfoList.Exists() && legRepInfoList.IsArray() { - for _, item := range legRepInfoList.Array() { - companiesWithSource = append(companiesWithSource, CompanyWithSource{ - json: item, - source: "legRepInfoList", - }) - } - } - - // 从shareholderList获取企业并添加到合并列表 - if shareholderList.Exists() && shareholderList.IsArray() { - for _, item := range shareholderList.Array() { - companiesWithSource = append(companiesWithSource, CompanyWithSource{ - json: item, - source: "shareholderList", - }) - } - } - - // 从ryPosPerList获取企业并添加到合并列表 - if ryPosPerList.Exists() && ryPosPerList.IsArray() { - for _, item := range ryPosPerList.Array() { - companiesWithSource = append(companiesWithSource, CompanyWithSource{ - json: item, - source: "ryPosPerList", - }) - } - } - - // 如果没有找到任何企业信息 - if len(companiesWithSource) == 0 { - return nil, fmt.Errorf("响应中缺少企业信息数组") - } - - // 在循环外统一统计各种数据 - adminPenalty := 0 - executed := 0 - dishonest := 0 - - // 统计行政处罚 - if caseInfoList.Exists() && caseInfoList.IsArray() { - adminPenalty = len(caseInfoList.Array()) - } - - // 统计被执行人 - if performerList.Exists() && performerList.IsArray() { - executed = len(performerList.Array()) - } - - // 统计失信被执行人 - if lossPromiseList.Exists() && lossPromiseList.IsArray() { - dishonest = len(lossPromiseList.Array()) - } - - // 计算全局关系数量 - 统计有多少种关系类型存在 - relationCount := 0 - if legRepInfoList.Exists() && legRepInfoList.IsArray() && len(legRepInfoList.Array()) > 0 { - relationCount++ - } - if shareholderList.Exists() && shareholderList.IsArray() && len(shareholderList.Array()) > 0 { - relationCount++ - } - if ryPosPerList.Exists() && ryPosPerList.IsArray() && len(ryPosPerList.Array()) > 0 { - relationCount++ - } - - companies := make([]CompanyInfo, 0, len(companiesWithSource)) - - for i, companyWithSource := range companiesWithSource { - companyJson := companyWithSource.json - name := companyJson.Get("orgName").String() - creditCode := companyJson.Get("creditNo").String() - - if name == "" || creditCode == "" { - continue // 跳过无效企业 - } - - // 根据企业来源计算关系权重 - // legRepInfoList(法人) > shareholderList(股东) > ryPosPerList(高管) - relationshipVal := 0 - relationship := []string{} - switch companyWithSource.source { - case "legRepInfoList": - relationshipVal = 6 // 法人关系 - 权重最高 - relationship = append(relationship, "lp") - case "shareholderList": - relationshipVal = 5 // 股东关系 - 权重次高 - relationship = append(relationship, "sh") - case "ryPosPerList": - relationshipVal = 4 // 高管关系 - 权重较低 - relationship = append(relationship, "tm") - } - - // 解析 regCap 用于排序(优选注册资本最高的企业去查询详情) - regCapStr := companyJson.Get("regCap").String() - regCapValue := parseRegCapValue(regCapStr) - - companies = append(companies, CompanyInfo{ - Index: i, - Data: companyJson, - Name: name, - CreditCode: creditCode, - Relationship: relationship, - RelationshipVal: relationshipVal, - RelationCount: relationCount, - AdminPenalty: adminPenalty, - Executed: executed, - Dishonest: dishonest, - RegCapValue: regCapValue, - }) - } - - return companies, nil -} - -// sortCompaniesByPriority 按优先级对企业进行排序 -func sortCompaniesByPriority(companies []CompanyInfo) []CompanyInfo { - // 创建副本进行排序 - sorted := make([]CompanyInfo, len(companies)) - copy(sorted, companies) - - sort.Slice(sorted, func(i, j int) bool { - // 首先根据失信被执行人数量排序 - if sorted[i].Dishonest != sorted[j].Dishonest { - return sorted[i].Dishonest > sorted[j].Dishonest - } - - // 然后根据被执行人数量排序 - if sorted[i].Executed != sorted[j].Executed { - return sorted[i].Executed > sorted[j].Executed - } - - // 然后根据行政处罚数量排序 - if sorted[i].AdminPenalty != sorted[j].AdminPenalty { - return sorted[i].AdminPenalty > sorted[j].AdminPenalty - } - - // 然后按关系权重排序 - if sorted[i].RelationshipVal != sorted[j].RelationshipVal { - return sorted[i].RelationshipVal > sorted[j].RelationshipVal - } - - // 然后按关系数量排序 - if sorted[i].RelationCount != sorted[j].RelationCount { - return sorted[i].RelationCount > sorted[j].RelationCount - } - - // 最后按注册资本排序:优选 regCap 价值最高的企业去查询详情 - return sorted[i].RegCapValue > sorted[j].RegCapValue - }) - - return sorted -} - -// BasicInfo 企业基础信息,供前端 CQYGL3F8E 展示用(BACKEND_MAPPING_SPEC 2.2) -type BasicInfo struct { - RegStatus string `json:"regStatus"` - RegCapital string `json:"regCapital"` - RegCapitalCurrency string `json:"regCapitalCurrency"` - CreditCode string `json:"creditCode"` - RegNumber string `json:"regNumber"` - EntType string `json:"entType"` - Industry string `json:"industry"` - EstiblishTime string `json:"estiblishTime"` - RegInstitute string `json:"regInstitute"` - ApprovedTime string `json:"approvedTime,omitempty"` - LegalPersonName string `json:"legalPersonName,omitempty"` - Phone string `json:"phone,omitempty"` - Email string `json:"email,omitempty"` - Website string `json:"website,omitempty"` - RegAddress string `json:"regAddress,omitempty"` -} - -// EnrichedCompanyInfo 增强的企业信息 -type EnrichedCompanyInfo struct { - CompanyInfo - InvestHistory interface{} `json:"invest_history"` // 对外投资历史 - FinancingHistory interface{} `json:"financing_history"` // 融资历史 - PunishmentInfo interface{} `json:"punishment_info"` // 行政处罚 - AbnormalInfo interface{} `json:"abnormal_info"` // 经营异常 - LawsuitInfo interface{} `json:"lawsuit_info"` // 涉诉信息 - OwnTax interface{} `json:"own_tax"` // 欠税公告 - TaxContravention interface{} `json:"tax_contravention"` // 税收违法 -} - -// enrichCompaniesWithDetails 并发调用其他处理器获取企业详细信息 -func enrichCompaniesWithDetails(ctx context.Context, companies []CompanyInfo, idCard string, deps *processors.ProcessorDependencies) ([]EnrichedCompanyInfo, error) { - log := logger.L() - - var wg sync.WaitGroup - results := make(chan struct { - index int - data EnrichedCompanyInfo - err error - }, len(companies)) - - // 并发处理每个企业 - for i, company := range companies { - wg.Add(1) - go func(index int, comp CompanyInfo) { - defer wg.Done() - - enriched := EnrichedCompanyInfo{ - CompanyInfo: comp, - } - - // 并发调用多个处理器 - var detailWg sync.WaitGroup - var detailMu sync.Mutex - - // 用于跟踪每个处理器的调用结果 - type processorResult struct { - processorType string - status string // "success", "empty", "error" - err error - hasData bool - } - processorResults := make([]processorResult, 0, 7) - - // 调用QYGL5A3C - 对外投资历史 - detailWg.Add(1) - go func() { - defer detailWg.Done() - result := callProcessorSafely(ctx, "QYGL5A3C", comp.CreditCode, deps) - - enriched.InvestHistory = result - hasData := false - if resultMap, ok := result.(map[string]interface{}); ok { - hasData = len(resultMap) > 0 - } else if resultArray, ok := result.([]interface{}); ok { - hasData = len(resultArray) > 0 - } - - detailMu.Lock() - status := "success" - if !hasData { - status = "empty" - } - processorResults = append(processorResults, processorResult{ - processorType: "QYGL5A3C", - status: status, - hasData: hasData, - }) - detailMu.Unlock() - }() - - // 调用QYGL8B4D - 融资历史 - detailWg.Add(1) - go func() { - defer detailWg.Done() - result := callProcessorSafely(ctx, "QYGL8B4D", comp.CreditCode, deps) - - enriched.FinancingHistory = result - hasData := false - if resultMap, ok := result.(map[string]interface{}); ok { - hasData = len(resultMap) > 0 - } else if resultArray, ok := result.([]interface{}); ok { - hasData = len(resultArray) > 0 - } - - detailMu.Lock() - status := "success" - if !hasData { - status = "empty" - } - processorResults = append(processorResults, processorResult{ - processorType: "QYGL8B4D", - status: status, - hasData: hasData, - }) - detailMu.Unlock() - }() - - // 调用QYGL9E2F - 行政处罚 - detailWg.Add(1) - go func() { - defer detailWg.Done() - result := callProcessorSafely(ctx, "QYGL9E2F", comp.CreditCode, deps) - - enriched.PunishmentInfo = result - hasData := false - if resultMap, ok := result.(map[string]interface{}); ok { - hasData = len(resultMap) > 0 - } else if resultArray, ok := result.([]interface{}); ok { - hasData = len(resultArray) > 0 - } - - detailMu.Lock() - status := "success" - if !hasData { - status = "empty" - } - processorResults = append(processorResults, processorResult{ - processorType: "QYGL9E2F", - status: status, - hasData: hasData, - }) - detailMu.Unlock() - }() - - // 调用QYGL7C1A - 经营异常 - detailWg.Add(1) - go func() { - defer detailWg.Done() - result := callProcessorSafely(ctx, "QYGL7C1A", comp.CreditCode, deps) - - enriched.AbnormalInfo = result - hasData := false - if resultMap, ok := result.(map[string]interface{}); ok { - hasData = len(resultMap) > 0 - } else if resultArray, ok := result.([]interface{}); ok { - hasData = len(resultArray) > 0 - } - - detailMu.Lock() - status := "success" - if !hasData { - status = "empty" - } - processorResults = append(processorResults, processorResult{ - processorType: "QYGL7C1A", - status: status, - hasData: hasData, - }) - detailMu.Unlock() - }() - - // 调用QYGL5S1I- 企业涉诉信息 - detailWg.Add(1) - go func() { - defer detailWg.Done() - result := callQYGL5S1IProcessorSafely(ctx, comp.CreditCode, comp.Name, deps) - - enriched.LawsuitInfo = result - // QYGL5S1I返回的是特殊格式,需要检查是否有数据 - hasData := false - if resultMap, ok := result.(map[string]interface{}); ok { - for _, v := range resultMap { - if vMap, ok := v.(map[string]interface{}); ok { - if msg, ok := vMap["msg"].(string); ok && msg == "成功" { - hasData = true - break - } - } - } - } - - detailMu.Lock() - status := "success" - if !hasData { - status = "empty" - } - processorResults = append(processorResults, processorResult{ - processorType: "QYGL5S1I", - status: status, - hasData: hasData, - }) - detailMu.Unlock() - }() - - // 调用QYGL7D9A - 欠税公告 - detailWg.Add(1) - go func() { - defer detailWg.Done() - result := callProcessorSafely(ctx, "QYGL7D9A", comp.CreditCode, deps) - - enriched.OwnTax = result - hasData := false - if resultMap, ok := result.(map[string]interface{}); ok { - hasData = len(resultMap) > 0 - } else if resultArray, ok := result.([]interface{}); ok { - hasData = len(resultArray) > 0 - } - - detailMu.Lock() - status := "success" - if !hasData { - status = "empty" - } - processorResults = append(processorResults, processorResult{ - processorType: "QYGL7D9A", - status: status, - hasData: hasData, - }) - detailMu.Unlock() - }() - - // 调用QYGL4B2E - 税收违法 - detailWg.Add(1) - go func() { - defer detailWg.Done() - result := callProcessorSafely(ctx, "QYGL4B2E", comp.CreditCode, deps) - - enriched.TaxContravention = result - hasData := false - if resultMap, ok := result.(map[string]interface{}); ok { - hasData = len(resultMap) > 0 - } else if resultArray, ok := result.([]interface{}); ok { - hasData = len(resultArray) > 0 - } - - detailMu.Lock() - status := "success" - if !hasData { - status = "empty" - } - processorResults = append(processorResults, processorResult{ - processorType: "QYGL4B2E", - status: status, - hasData: hasData, - }) - detailMu.Unlock() - }() - - detailWg.Wait() - - results <- struct { - index int - data EnrichedCompanyInfo - err error - }{index, enriched, nil} - }(i, company) - } - - // 等待所有goroutine完成 - go func() { - wg.Wait() - close(results) - }() - - // 收集结果 - enrichedCompanies := make([]EnrichedCompanyInfo, len(companies)) - for result := range results { - if result.err != nil { - log.Error("QYGL3F8E企业处理失败", - zap.Int("index", result.index), - zap.Error(result.err), - ) - return nil, result.err - } - enrichedCompanies[result.index] = result.data - } - - return enrichedCompanies, nil -} - -// callProcessorSafely 安全调用处理器(处理可能的错误) -func callProcessorSafely(ctx context.Context, processorType, entCode string, deps *processors.ProcessorDependencies) interface{} { - log := logger.L() - - // 构建请求参数 - params := map[string]interface{}{ - "ent_code": entCode, - "page_size": 20, - "page_num": 1, - } - - paramsBytes, err := json.Marshal(params) - if err != nil { - log.Warn("QYGL3F8E构建处理器参数失败", - zap.String("processor_type", processorType), - zap.String("ent_code", entCode), - zap.Error(err), - ) - return map[string]interface{}{} - } - - var response []byte - switch processorType { - case "QYGL5A3C": - response, err = ProcessQYGL5A3CRequest(ctx, paramsBytes, deps) - case "QYGL8B4D": - response, err = ProcessQYGL8B4DRequest(ctx, paramsBytes, deps) - case "QYGL9E2F": - response, err = ProcessQYGL9E2FRequest(ctx, paramsBytes, deps) - case "QYGL7C1A": - response, err = ProcessQYGL7C1ARequest(ctx, paramsBytes, deps) - case "QYGL7D9A": - response, err = ProcessQYGL7D9ARequest(ctx, paramsBytes, deps) - case "QYGL4B2E": - response, err = ProcessQYGL4B2ERequest(ctx, paramsBytes, deps) - default: - log.Warn("QYGL3F8E未知的处理器类型", - zap.String("processor_type", processorType), - ) - return map[string]interface{}{} - } - - if err != nil { - // 如果是查询为空错误,返回空对象 - if errors.Is(err, processors.ErrNotFound) { - log.Debug("QYGL3F8E子处理器查询结果为空(正常情况)", - zap.String("processor_type", processorType), - zap.String("ent_code", entCode), - ) - return map[string]interface{}{} - } - // 其他错误也返回空对象,避免影响整体流程 - log.Warn("QYGL3F8E子处理器调用失败(已忽略错误)", - zap.String("processor_type", processorType), - zap.String("ent_code", entCode), - zap.Error(err), - ) - return map[string]interface{}{} - } - - // 解析响应 - var result interface{} - if err := json.Unmarshal(response, &result); err != nil { - log.Warn("QYGL3F8E子处理器响应解析失败", - zap.String("processor_type", processorType), - zap.String("ent_code", entCode), - zap.Error(err), - ) - return map[string]interface{}{} - } - - return result -} - -// callProcessorSafely 安全调用处理器 -func callQYGL5S1IProcessorSafely(ctx context.Context, entCode string, entName string, deps *processors.ProcessorDependencies) interface{} { - paramsBytes, err := json.Marshal(map[string]interface{}{ - "ent_code": entCode, - "ent_name": entName, - }) - if err != nil { - return map[string]interface{}{} - } - response, err := ProcessQYGL5S1IRequest(ctx, paramsBytes, deps) - if err != nil { - return map[string]interface{}{} - } - return normalizeQYGL5S1IBzxr(response) -} - -// normalizeQYGL5S1IBzxr 将 QYGL5S1I 响应中的 xgbzxr 统一为 { "data": { "xgbzxr": [...] } } 或空数组时附带 msg 结构 -func normalizeQYGL5S1IBzxr(response []byte) interface{} { - var m map[string]interface{} - if err := json.Unmarshal(response, &m); err != nil { - return map[string]interface{}{} - } - // 只规范化 xgbzxr,sxbzxr 保持原始结构(例如仅返回 { "msg": "没有找到" }) - m = normalizeQYGL5S1IOneBzxr(m, "xgbzxr") - // 规范化 entout 结构,生成 entout.data.civil / criminal 等及汇总 count 字段 - m = normalizeQYGL5S1IEntout(m) - return m -} - -// normalizeQYGL5S1IOneBzxr 将 m[key] 规范为 { "data": { key: [...] }, "msg": "..." } -func normalizeQYGL5S1IOneBzxr(m map[string]interface{}, key string) map[string]interface{} { - raw, ok := m[key] - if !ok { - return m - } - objMap, ok := raw.(map[string]interface{}) - if !ok { - return m - } - // 已有 data. 结构则不再处理 - if data, hasData := objMap["data"]; hasData { - if dataMap, ok := data.(map[string]interface{}); ok { - if _, hasKey := dataMap[key]; hasKey { - return m - } - } - } - // 从现有字段取出列表:优先 data.,否则顶层 - var list []interface{} - if data, hasData := objMap["data"]; hasData { - if dataMap, ok := data.(map[string]interface{}); ok { - if arr, ok := dataMap[key].([]interface{}); ok { - list = arr - } - } - } - if list == nil { - if arr, ok := objMap[key].([]interface{}); ok { - list = arr - } - } - if list == nil { - list = []interface{}{} - } - msg, _ := objMap["msg"].(string) - // 空结果时:只返回 msg 结构(例如 { "xgbzxr": { "msg": "没有找到" } }) - if len(list) == 0 { - if msg == "" { - msg = "没有找到" - } - m[key] = map[string]interface{}{ - "msg": msg, - } - return m - } - // 有数据时:返回带 data. 的结构,不带 msg - m[key] = map[string]interface{}{ - "data": map[string]interface{}{ - key: list, - }, - } - return m -} - -// normalizeQYGL5S1IEntout 将 QYGL5S1I 返回的 entout 映射为前端需要的结构: -// -// entout: { -// data: { -// civil: { cases: [...] }, -// criminal: { cases: [...] }, -// administrative: { cases: [...] }, -// implement: { cases: [...] }, -// bankrupt: { cases: [...] }, -// preservation: { cases: [...] }, -// jurisdict: { cases: [...] }, -// compensate: { cases: [...] }, -// count: <总案件数>, -// count_wei_total: <汇总未结案件数> -// } -// } -// -// 如果 entout 只有 msg(例如 { "msg": "没有找到" }),则保持原样。 -func normalizeQYGL5S1IEntout(m map[string]interface{}) map[string]interface{} { - raw, ok := m["entout"] - if !ok { - return m - } - entMap, ok := raw.(map[string]interface{}) - if !ok { - return m - } - - // 如果只有 msg,没有任何案件分类信息,则不做结构化转换 - hasCasesField := false - categoryKeys := []string{ - "civil", - "criminal", - "administrative", - "implement", - "bankrupt", - "preservation", - "jurisdict", - "compensate", - } - for _, key := range categoryKeys { - if v, ok := entMap[key]; ok { - if catMap, ok := v.(map[string]interface{}); ok { - if _, has := catMap["cases"]; has { - hasCasesField = true - break - } - } - } - } - if !hasCasesField { - // 例如 { "entout": { "msg": "没有找到" } },直接返回 - return m - } - - data := make(map[string]interface{}) - totalCases := 0 - totalWei := 0 - - for _, key := range categoryKeys { - var casesArr []interface{} - - if v, ok := entMap[key]; ok { - if catMap, ok := v.(map[string]interface{}); ok { - // 提取 cases - if arr, ok := catMap["cases"].([]interface{}); ok { - casesArr = arr - } - // 汇总 count_wei_total - if cntRaw, ok := catMap["count"]; ok { - if cntMap, ok := cntRaw.(map[string]interface{}); ok { - totalWei += toInt(cntMap["count_wei_total"]) - } - } - } - } - - if casesArr == nil { - casesArr = []interface{}{} - } - data[key] = map[string]interface{}{ - "cases": casesArr, - } - totalCases += len(casesArr) - } - - data["count"] = totalCases - data["count_wei_total"] = totalWei - - m["entout"] = map[string]interface{}{ - "data": data, - } - return m -} - -// toInt 尝试将任意类型转换为 int,用于解析统计字段 -func toInt(v interface{}) int { - switch val := v.(type) { - case int: - return val - case int64: - return int(val) - case float64: - return int(val) - case string: - if val == "" { - return 0 - } - if n, err := strconv.Atoi(val); err == nil { - return n - } - } - return 0 -} - -// parseRegCapValue 解析 regCap 字符串为可比较数值(单位统一为“万”)。 -// 如 "100.000000万人民币" -> 100.0,"1.5亿人民币" -> 15000.0(1亿=10000万)。用于排序时优选注册资本最高的企业。 -func parseRegCapValue(regCapStr string) float64 { - regCapStr = strings.TrimSpace(regCapStr) - if regCapStr == "" { - return 0 - } - // 先找数字部分(可能含小数点) - var numStr strings.Builder - for _, r := range regCapStr { - if (r >= '0' && r <= '9') || r == '.' { - numStr.WriteRune(r) - } else if numStr.Len() > 0 { - break - } - } - if numStr.Len() == 0 { - return 0 - } - val, err := strconv.ParseFloat(numStr.String(), 64) - if err != nil { - return 0 - } - if strings.Contains(regCapStr, "亿") { - val *= 10000 // 1亿 = 10000万 - } - return val -} - -// valueAfterColon 取冒号后的部分,若无冒号则返回原串 -func valueAfterColon(s string) string { - for i, c := range s { - if c == ':' { - return strings.TrimSpace(s[i+1:]) - } - } - return s -} - -// getStr 从 map 中安全取字符串 -func getStr(m map[string]interface{}, key string) string { - if v, ok := m[key]; ok && v != nil { - switch val := v.(type) { - case string: - return val - case float64: - return strconv.FormatFloat(val, 'f', -1, 64) - } - } - return "" -} - -// buildBasicInfo 按 BACKEND_MAPPING_SPEC 2.2 从 companyMap 推导 BasicInfo 结构 -func buildBasicInfo(companyMap map[string]interface{}) BasicInfo { - basic := BasicInfo{ - RegStatus: valueAfterColon(getStr(companyMap, "orgStatus")), - RegCapital: getStr(companyMap, "regCap"), - RegCapitalCurrency: valueAfterColon(getStr(companyMap, "regCapCur")), - CreditCode: getStr(companyMap, "creditNo"), - RegNumber: getStr(companyMap, "regNo"), - EntType: valueAfterColon(getStr(companyMap, "orgType")), - Industry: getStr(companyMap, "industry"), - EstiblishTime: getStr(companyMap, "esDate"), - RegInstitute: getStr(companyMap, "regorgProvince"), - ApprovedTime: "", - LegalPersonName: getStr(companyMap, "frName"), - Phone: getStr(companyMap, "phone"), - Email: getStr(companyMap, "email"), - Website: getStr(companyMap, "website"), - RegAddress: getStr(companyMap, "regAddress"), - } - return basic -} - -// hasRelationship 判断 relationship 是否包含任一目标 -func hasRelationship(relationship []string, targets ...string) bool { - set := make(map[string]bool) - for _, t := range targets { - set[t] = true - } - for _, r := range relationship { - if set[r] { - return true - } - } - return false -} - -// buildStockHolderItem 投资类记录且存在出资/持股信息时生成 stockHolderItem -func buildStockHolderItem(companyMap map[string]interface{}, relationship []string) (map[string]interface{}, bool) { - if !hasRelationship(relationship, "sh", "his_sh", "lp", "his_lp") { - return nil, false - } - ryName := getStr(companyMap, "ryName") - conform := getStr(companyMap, "conform") - subConAmt := getStr(companyMap, "subConAmt") - fundedRatio := getStr(companyMap, "fundedRatio") - if ryName == "" && subConAmt == "" && fundedRatio == "" { - return nil, false - } - orgHolderType := conform - if orgHolderType == "" { - orgHolderType = "其他" - } - item := map[string]interface{}{ - "orgHolderName": ryName, - "orgHolderType": orgHolderType, - "subscriptAmt": subConAmt, - "investRate": fundedRatio, - } - if investDate := getStr(companyMap, "investDate"); investDate != "" { - item["investDate"] = investDate - } - return item, true -} - -// parsePositionToTypeJoin 从 position 解析职位名,如 "410C:执行董事兼总经理" -> ["执行董事兼总经理"] -func parsePositionToTypeJoin(position string) []string { - if position == "" { - return nil - } - name := valueAfterColon(position) - if name == "" { - return []string{position} - } - return []string{name} -} - -// buildStaffList 高管类记录时从 position 解析出 staffList -func buildStaffList(companyMap map[string]interface{}, relationship []string) (map[string]interface{}, bool) { - if !hasRelationship(relationship, "tm", "his_tm") { - return nil, false - } - position := getStr(companyMap, "position") - typeJoin := parsePositionToTypeJoin(position) - if len(typeJoin) == 0 { - typeJoin = []string{} - } - return map[string]interface{}{ - "result": []map[string]interface{}{ - {"typeJoin": typeJoin}, - }, - }, true -} - -// buildFinalResponse 构建最终响应 -// enrichedCompanies: 已增强的企业信息(前3个处理过的) -// allCompanies: 所有企业信息(从legRepInfoList, shareholderList, ryPosPerList合并的扁平列表,格式为 [{},{},{},{},{},{},{},{}]) -func buildFinalResponse(enrichedCompanies []EnrichedCompanyInfo, allCompanies []CompanyInfo) ([]byte, error) { - // 如果没有企业数据,返回空列表 - if len(allCompanies) == 0 { - finalResponse := map[string]interface{}{ - "items": []interface{}{}, - "total": 0, - } - return json.Marshal(finalResponse) - } - - // 创建已处理企业的映射(使用Index作为key,方便查找) - // enrichedCompanies 中的企业是按处理顺序传入的,对应 allCompanies 中已排序的前几个 - // 注意:allCompanies 已经排序过了,enrichedCompanies 的顺序对应 allCompanies 的前几个 - processedMap := make(map[int]EnrichedCompanyInfo) - for i, enriched := range enrichedCompanies { - if i < len(allCompanies) { - // enrichedCompanies[i] 对应 allCompanies[i],使用 allCompanies[i].Index 作为key - // 这样后续遍历 allCompanies 时,可以通过 company.Index 查找对应的 enriched - processedMap[allCompanies[i].Index] = enriched - } - } - - // 构建增强后的企业列表 - enhancedDatalist := make([]interface{}, 0, len(allCompanies)) - - for _, company := range allCompanies { - // 将gjson.Result(CompanyInfo.Data)转换为map[string]interface{} - // CompanyInfo.Data 包含来自legRepInfoList/shareholderList/ryPosPerList的完整原始对象 - // 例如:{"regNo": "...", "orgName": "...", "creditNo": "...", "industry": "...", ...} - var companyMap map[string]interface{} - if err := json.Unmarshal([]byte(company.Data.Raw), &companyMap); err != nil { - // 如果转换失败,创建一个基本对象(包含orgName和creditNo) - companyMap = map[string]interface{}{ - "orgName": company.Name, - "creditNo": company.CreditCode, - } - } - - // 关系字段(必填,若无则返回空数组) - if len(company.Relationship) == 0 { - companyMap["relationship"] = []string{} - } else { - companyMap["relationship"] = company.Relationship - } - - // 辅助函数:将历史记录数据转换为前端期望的 { items, total } 格式 - emptyItemsTotal := func() map[string]interface{} { - return map[string]interface{}{ - "items": []interface{}{}, - "total": 0, - } - } - convertHistoryData := func(data interface{}) interface{} { - if data == nil { - return emptyItemsTotal() - } - if arr, ok := data.([]interface{}); ok { - return map[string]interface{}{ - "items": arr, - "total": len(arr), - } - } - if dataMap, ok := data.(map[string]interface{}); ok { - if len(dataMap) == 0 { - return emptyItemsTotal() - } - if _, hasItems := dataMap["items"]; hasItems { - return dataMap - } - return emptyItemsTotal() - } - return emptyItemsTotal() - } - - // 检查是否是已处理的企业(前3个) - if enriched, exists := processedMap[company.Index]; exists { - // 已处理的企业,添加详细信息 - companyMap["invest_history"] = convertHistoryData(enriched.InvestHistory) - companyMap["financing_history"] = convertHistoryData(enriched.FinancingHistory) - companyMap["punishment_info"] = convertHistoryData(enriched.PunishmentInfo) - companyMap["abnormal_info"] = convertHistoryData(enriched.AbnormalInfo) - companyMap["lawsuitInfo"] = enriched.LawsuitInfo - companyMap["own_tax"] = convertHistoryData(enriched.OwnTax) - companyMap["tax_contravention"] = convertHistoryData(enriched.TaxContravention) - } else { - // 未处理的企业,添加空的详细信息(符合 spec:items/total 格式) - companyMap["invest_history"] = emptyItemsTotal() - companyMap["financing_history"] = emptyItemsTotal() - companyMap["punishment_info"] = emptyItemsTotal() - companyMap["abnormal_info"] = emptyItemsTotal() - companyMap["lawsuitInfo"] = map[string]interface{}{} - companyMap["own_tax"] = emptyItemsTotal() - companyMap["tax_contravention"] = emptyItemsTotal() - } - - // 每条 item 必须包含 basicInfo(BACKEND_MAPPING_SPEC 2.2) - companyMap["basicInfo"] = buildBasicInfo(companyMap) - // 投资类记录增加 stockHolderItem(SPEC 2.4) - if stockHolderItem, ok := buildStockHolderItem(companyMap, company.Relationship); ok { - companyMap["stockHolderItem"] = stockHolderItem - } - // 高管类记录增加 staffList(SPEC 2.5) - if staffList, ok := buildStaffList(companyMap, company.Relationship); ok { - companyMap["staffList"] = staffList - } - enhancedDatalist = append(enhancedDatalist, companyMap) - } - - // 总数就是所有企业的数量(从三个列表合并后的总数) - total := len(allCompanies) - - // 构建最终的简化响应格式 - finalResponse := map[string]interface{}{ - "items": enhancedDatalist, - "total": total, - } - - // 序列化最终结果 - return json.Marshal(finalResponse) -} diff --git a/internal/domains/api/services/processors/qygl/qygl45bd_processor.go b/internal/domains/api/services/processors/qygl/qygl45bd_processor.go deleted file mode 100644 index e8c49ff..0000000 --- a/internal/domains/api/services/processors/qygl/qygl45bd_processor.go +++ /dev/null @@ -1,66 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessQYGL45BDRequest QYGL45BD API处理方法 -func ProcessQYGL45BDRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL45BDReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedEntName, err := deps.WestDexService.Encrypt(paramsDto.EntName) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedLegalPerson, err := deps.WestDexService.Encrypt(paramsDto.LegalPerson) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedEntCode, err := deps.WestDexService.Encrypt(paramsDto.EntCode) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "entname": encryptedEntName, - "realname": encryptedLegalPerson, - "entmark": encryptedEntCode, - "idcard": encryptedIDCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "WEST00021", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - if respBytes != nil { - return respBytes,nil - } - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl4b2e_processor.go b/internal/domains/api/services/processors/qygl/qygl4b2e_processor.go deleted file mode 100644 index c3ce1fe..0000000 --- a/internal/domains/api/services/processors/qygl/qygl4b2e_processor.go +++ /dev/null @@ -1,59 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "strconv" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessQYGL4B2ERequest QYGL4B2E API处理方法 - 税收违法 -func ProcessQYGL4B2ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL5A3CReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 设置默认值 - pageSize := paramsDto.PageSize - if pageSize == 0 { - pageSize = int64(20) - } - pageNum := paramsDto.PageNum - if pageNum == 0 { - pageNum = int64(1) - } - - // 构建API调用参数 - apiParams := map[string]string{ - "keyword": paramsDto.EntCode, - "pageSize": strconv.FormatInt(pageSize, 10), - "pageNum": strconv.FormatInt(pageNum, 10), - } - - // 调用天眼查API - 税收违法 - response, err := deps.TianYanChaService.CallAPI(ctx, "TaxContravention", apiParams) - if err != nil { - return nil, convertTianYanChaError(err) - } - - // 检查天眼查API调用是否成功 - if !response.Success { - return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message)) - } - - // 返回天眼查响应数据 - respBytes, err := json.Marshal(response.Data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl5a3c_processor.go b/internal/domains/api/services/processors/qygl/qygl5a3c_processor.go deleted file mode 100644 index c38bef7..0000000 --- a/internal/domains/api/services/processors/qygl/qygl5a3c_processor.go +++ /dev/null @@ -1,59 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "strconv" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessQYGL5A3CRequest QYGL5A3C API处理方法 - 对外投资历史 -func ProcessQYGL5A3CRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL5A3CReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 设置默认值 - pageSize := paramsDto.PageSize - if pageSize == 0 { - pageSize = int64(20) - } - pageNum := paramsDto.PageNum - if pageNum == 0 { - pageNum = int64(1) - } - - // 构建API调用参数 - apiParams := map[string]string{ - "keyword": paramsDto.EntCode, - "pageSize": strconv.FormatInt(pageSize, 10), - "pageNum": strconv.FormatInt(pageNum, 10), - } - - // 调用天眼查API - 对外投资历史 - response, err := deps.TianYanChaService.CallAPI(ctx, "InvestHistory", apiParams) - if err != nil { - return nil, convertTianYanChaError(err) - } - - // 检查天眼查API调用是否成功 - if !response.Success { - return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message)) - } - - // 返回天眼查响应数据 - respBytes, err := json.Marshal(response.Data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl5a9t_processor.go b/internal/domains/api/services/processors/qygl/qygl5a9t_processor.go deleted file mode 100644 index 7df82d3..0000000 --- a/internal/domains/api/services/processors/qygl/qygl5a9t_processor.go +++ /dev/null @@ -1,64 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "fmt" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// Processqygl5a9tRequest QYGL5A9T API处理方法 - 全国企业各类工商风险统计数量查询 -func ProcessQYGL5A9TRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - - var paramsDto dto.QYGL5A9TReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 两选一校验:EntName 和 EntCode 至少传一个 - var keyword string - if paramsDto.EntName == "" && paramsDto.EntCode == "" { - return nil, fmt.Errorf("%s: %w", processors.ErrInvalidParam, errors.New("必须提供企业名称或企业统一信用代码中的其中一个")) - } - - // 确定使用哪个值作为 keyword - if paramsDto.EntName != "" { - keyword = paramsDto.EntName - } else { - keyword = paramsDto.EntCode - } - - // 构建请求数据, - reqData := map[string]interface{}{ - "nameCode": keyword, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1054665422426533888" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - // 查空情况,返回特定的查空错误 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl5cmp_processor.go b/internal/domains/api/services/processors/qygl/qygl5cmp_processor.go deleted file mode 100644 index 6ec10ca..0000000 --- a/internal/domains/api/services/processors/qygl/qygl5cmp_processor.go +++ /dev/null @@ -1,128 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "fmt" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" - - "github.com/tidwall/gjson" -) - -// ProcessQYGL5CMPRequest QYGL5CMP API处理方法 - 企业五要素验证 -func ProcessQYGL5CMPRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL5CMPReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 第一步:企业信息验证 - 调用天眼查API - _, err := verifyEnterpriseInfo(ctx, paramsDto, deps) - if err != nil { - // 企业信息验证失败,只返回简单的状态码 - return createStatusResponse(1), nil - } - - // 企业信息验证通过,继续个人信息验证 - _, err = verifyPersonalInfo(ctx, paramsDto, deps) - if err != nil { - // 个人信息验证失败,只返回简单的状态码 - return createStatusResponse(1), nil - } - - // 两个验证都通过,只返回成功状态码 - return createStatusResponse(0), nil -} - -// verifyEnterpriseInfo 验证企业信息 -func verifyEnterpriseInfo(ctx context.Context, paramsDto dto.QYGL5CMPReq, deps *processors.ProcessorDependencies) (map[string]interface{}, error) { - // 构建API调用参数 - apiParams := map[string]string{ - "code": paramsDto.EntCode, - "name": paramsDto.EntName, - "legalPersonName": paramsDto.LegalPerson, - } - - // 调用天眼查API - 使用通用的CallAPI方法 - response, err := deps.TianYanChaService.CallAPI(ctx, "VerifyThreeElements", apiParams) - if err != nil { - return nil, convertTianYanChaError(err) - } - - // 检查天眼查API调用是否成功 - if !response.Success { - return nil, fmt.Errorf("天眼查API调用失败") - } - - // 解析天眼查响应数据 - if response.Data == nil { - return nil, fmt.Errorf("天眼查响应数据为空") - } - - // 将response.Data转换为JSON字符串,然后使用gjson解析 - dataBytes, err := json.Marshal(response.Data) - if err != nil { - return nil, fmt.Errorf("数据序列化失败") - } - - // 使用gjson解析嵌套的data.result.data字段 - result := gjson.GetBytes(dataBytes, "result") - if !result.Exists() { - return nil, fmt.Errorf("result字段不存在") - } - - // 检查data.result.data是否等于1 - if result.Int() != 1 { - return nil, fmt.Errorf("企业信息验证不通过") - } - - // 构建天眼查API返回的数据结构 - return map[string]interface{}{ - "success": response.Success, - "message": response.Message, - "data": response.Data, - }, nil -} - -// verifyPersonalInfo 验证个人信息并返回API数据 -func verifyPersonalInfo(ctx context.Context, paramsDto dto.QYGL5CMPReq, deps *processors.ProcessorDependencies) (map[string]interface{}, error) { - // 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名 - reqData := map[string]interface{}{ - "name": paramsDto.LegalPerson, - "idCardNum": paramsDto.IDCard, - "phoneNumber": paramsDto.MobileNo, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1100244702166183936" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - // 个人信息验证失败,返回错误状态 - if errors.Is(err, xingwei.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 解析星维API返回的数据 - var xingweiData map[string]interface{} - if err := json.Unmarshal(respBytes, &xingweiData); err != nil { - return nil, errors.Join(processors.ErrSystem, fmt.Errorf("解析星维API响应失败: %w", err)) - } - - // 返回星维API的全部数据 - return xingweiData, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl5f6a_processor.go b/internal/domains/api/services/processors/qygl/qygl5f6a_processor.go deleted file mode 100644 index e33c78e..0000000 --- a/internal/domains/api/services/processors/qygl/qygl5f6a_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "fmt" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessQYGL5F6ARequest QYGL5F6A API处理方法 - 企业相关查询 -func ProcessQYGL5F6ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL5F6AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - fmt.Println("paramsDto", paramsDto) - - // 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名 - reqData := map[string]interface{}{ - "idCardNum": paramsDto.IDCard, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1101695397213958144" - fmt.Println("reqData", reqData) - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl5s1i_processor.go b/internal/domains/api/services/processors/qygl/qygl5s1i_processor.go deleted file mode 100644 index 01cf298..0000000 --- a/internal/domains/api/services/processors/qygl/qygl5s1i_processor.go +++ /dev/null @@ -1,59 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessQYGL5S1IReq QYGL5S1I API处理方法 - 企业司法涉诉V2 -func ProcessQYGL5S1IRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - - var paramsDto dto.QYGL5S1IReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedEntName, err := deps.ZhichaService.Encrypt(paramsDto.EntName) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - encryptedEntCode, err := deps.ZhichaService.Encrypt(paramsDto.EntCode) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // 按企业名称时传 enterpriseNo(加密名),按统一信用代码时传 enterpriseName(加密代码) - reqData := map[string]interface{}{} - if paramsDto.EntName != "" { - reqData["enterpriseName"] = encryptedEntName - } - if paramsDto.EntCode != "" { - reqData["enterpriseNo"] = encryptedEntCode - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI088", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl66sl_processor.go b/internal/domains/api/services/processors/qygl/qygl66sl_processor.go deleted file mode 100644 index cb491bb..0000000 --- a/internal/domains/api/services/processors/qygl/qygl66sl_processor.go +++ /dev/null @@ -1,53 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// Processqygl66slRequest QYGL66SL API处理方法 - 全国企业司法模型服务查询_V1 -func ProcessQYGL66SLRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - - var paramsDto dto.QYGL66SLReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据, - reqData := map[string]interface{}{ - "orgName": paramsDto.EntName, - "inquiredAuth": "authed:" + paramsDto.AuthDate, - "uscc": paramsDto.EntCode, - "authAuthorizeFileCode": paramsDto.AuthAuthorizeFileCode, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1068350101956521984" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - // 查空情况,返回特定的查空错误 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl6f2d_processor.go b/internal/domains/api/services/processors/qygl/qygl6f2d_processor.go deleted file mode 100644 index 78b46af..0000000 --- a/internal/domains/api/services/processors/qygl/qygl6f2d_processor.go +++ /dev/null @@ -1,45 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessQYGL6F2DRequest QYGL6F2D API处理方法 -func ProcessQYGL6F2DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL6F2DReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "idno": encryptedIDCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G05XM02", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl6s1b_processor.go b/internal/domains/api/services/processors/qygl/qygl6s1b_processor.go deleted file mode 100644 index ccfc341..0000000 --- a/internal/domains/api/services/processors/qygl/qygl6s1b_processor.go +++ /dev/null @@ -1,128 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "strconv" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessQYGL6S1BRequest QYGL6S1B API处理方法 - 董监高司法综合信息核验(使用数据宝服务) - -func ProcessQYGL6S1BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL6S1BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建数据宝入参 - reqParams := map[string]interface{}{ - "key": "1cce582f0a6f3ca40de80f1bea9b9698", - "idcard": paramsDto.IDCard, - } - - // 调用数据宝API - apiPath := "/communication/personal/10166" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - // 解析响应中的 JSON 字符串(使用 RecursiveParse) - parsedResp, err := RecursiveParse(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // 提取 resultData 字段 - resultData, ok := parsedResp.(map[string]interface{}) - if !ok { - return nil, errors.Join(processors.ErrSystem, errors.New("invalid response format")) - } - - resultDataValue, exists := resultData["resultData"] - if !exists { - // 如果 resultData 不存在,说明查询为空,返回空的业务数据结构 - emptyResult := map[string]interface{}{ - "caseInfoList": []interface{}{}, - "legRepInfoList": []interface{}{}, - "lossPromiseList": []interface{}{}, - "performerList": []interface{}{}, - "ryPosPerList": []interface{}{}, - "shareholderList": []interface{}{}, - } - return json.Marshal(emptyResult) - } - - // 转换数据类型:将数字字段转换为字符串 - convertedData, err := convertDataTypes(resultDataValue) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(convertedData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} - -// convertDataTypes 递归转换数据类型,将数字字段转换为字符串以保持与原有格式一致 -func convertDataTypes(data interface{}) (interface{}, error) { - switch v := data.(type) { - case map[string]interface{}: - for key, val := range v { - converted, err := convertDataTypes(val) - if err != nil { - return nil, err - } - v[key] = converted - } - return v, nil - case []interface{}: - for i, item := range v { - converted, err := convertDataTypes(item) - if err != nil { - return nil, err - } - v[i] = converted - } - return v, nil - case float64: - // 将 float64 类型转换为字符串(JSON 解析后数字默认为 float64) - if v == float64(int64(v)) { - return strconv.FormatInt(int64(v), 10), nil - } - return strconv.FormatFloat(v, 'f', -1, 64), nil - case int: - return strconv.Itoa(v), nil - case int32: - return strconv.FormatInt(int64(v), 10), nil - case int64: - return strconv.FormatInt(v, 10), nil - case string: - // 尝试解析字符串中的 JSON - var parsed interface{} - if err := json.Unmarshal([]byte(v), &parsed); err == nil { - return convertDataTypes(parsed) - } - return v, nil - default: - return v, nil - } -} diff --git a/internal/domains/api/services/processors/qygl/qygl7c1a_processor.go b/internal/domains/api/services/processors/qygl/qygl7c1a_processor.go deleted file mode 100644 index 96d3123..0000000 --- a/internal/domains/api/services/processors/qygl/qygl7c1a_processor.go +++ /dev/null @@ -1,61 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "strconv" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessQYGL7C1ARequest QYGL7C1A API处理方法 - 经营异常 -func ProcessQYGL7C1ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL7C1AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - fmt.Println("paramsDto", paramsDto) - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 设置默认值 - pageSize := paramsDto.PageSize - if pageSize == 0 { - pageSize = int64(20) - } - pageNum := paramsDto.PageNum - if pageNum == 0 { - pageNum = int64(1) - } - - // 构建API调用参数 - apiParams := map[string]string{ - "keyword": paramsDto.EntCode, - "pageSize": strconv.FormatInt(pageSize, 10), - "pageNum": strconv.FormatInt(pageNum, 10), - } - - // 调用天眼查API - 经营异常 - response, err := deps.TianYanChaService.CallAPI(ctx, "AbnormalInfo", apiParams) - if err != nil { - return nil, convertTianYanChaError(err) - } - - // 检查天眼查API调用是否成功 - if !response.Success { - return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message)) - } - - // 返回天眼查响应数据 - respBytes, err := json.Marshal(response.Data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl7d9a_processor.go b/internal/domains/api/services/processors/qygl/qygl7d9a_processor.go deleted file mode 100644 index 1456afe..0000000 --- a/internal/domains/api/services/processors/qygl/qygl7d9a_processor.go +++ /dev/null @@ -1,59 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "strconv" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessQYGL7D9ARequest QYGL7D9A API处理方法 - 欠税公告 -func ProcessQYGL7D9ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL5A3CReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 设置默认值 - pageSize := paramsDto.PageSize - if pageSize == 0 { - pageSize = int64(20) - } - pageNum := paramsDto.PageNum - if pageNum == 0 { - pageNum = int64(1) - } - - // 构建API调用参数 - apiParams := map[string]string{ - "keyword": paramsDto.EntCode, - "pageSize": strconv.FormatInt(pageSize, 10), - "pageNum": strconv.FormatInt(pageNum, 10), - } - - // 调用天眼查API - 欠税公告 - response, err := deps.TianYanChaService.CallAPI(ctx, "OwnTax", apiParams) - if err != nil { - return nil, convertTianYanChaError(err) - } - - // 检查天眼查API调用是否成功 - if !response.Success { - return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message)) - } - - // 返回天眼查响应数据 - respBytes, err := json.Marshal(response.Data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qyglj1u9_processor.go b/internal/domains/api/services/processors/qygl/qygl7hbn_processor.go similarity index 53% rename from internal/domains/api/services/processors/qygl/qyglj1u9_processor.go rename to internal/domains/api/services/processors/qygl/qygl7hbn_processor.go index 84371db..8ef4110 100644 --- a/internal/domains/api/services/processors/qygl/qyglj1u9_processor.go +++ b/internal/domains/api/services/processors/qygl/qygl7hbn_processor.go @@ -2,27 +2,21 @@ package qygl import ( "context" - "crypto/rand" - "encoding/hex" "encoding/json" "errors" - "fmt" - "net/url" - "strings" "sync" - "time" "hyapi-server/internal/domains/api/dto" "hyapi-server/internal/domains/api/entities" "hyapi-server/internal/domains/api/services/processors" + "hyapi-server/internal/domains/api/services/processors/qygl/reportstore" ) -// ProcessQYGLJ1U9Request 企业全景报告处理器:并发调用企业全量(QYGLUY3S)、股权全景(QYGLJ0Q1)、司法涉诉(QYGL5S1I)、 -// 企业年报(QYGLDJ12)、税收违法(QYGL8848)、欠税公告(QYGL7D9A)。 +// ProcessQYGL7HBNRequest 企业全景报告处理器:并发经天远中转调用 QYGLUY3S、QYGLJ0Q1、QYGLDJ12、QYGL8848。 // 单路失败、查无、解析失败时该路按空数据处理并继续合并;仅当合并后的报告仍无任何可展示的企业要素时返回查询为空。 -func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { +func ProcessQYGL7HBNRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { // 复用 QYGLUY3S 的入参结构:企业名称/注册号/统一社会信用代码 - var p dto.QYGLJ1U9Req + var p dto.QYGL7HBNReq if err := json.Unmarshal(params, &p); err != nil { return nil, errors.Join(processors.ErrSystem, err) } @@ -30,16 +24,16 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors return nil, errors.Join(processors.ErrInvalidParam, err) } - // 并发调用六个子处理器;单路失败或无数据时降级为空结果,仅当合并后仍无任何企业要素时返回查询为空 + // 并发调用四个子处理器;单路失败或无数据时降级为空结果,仅当合并后仍无任何企业要素时返回查询为空 type apiResult struct { key string data map[string]interface{} err error } - resultsCh := make(chan apiResult, 6) + resultsCh := make(chan apiResult, 4) var wg sync.WaitGroup - call := func(key string, req interface{}, fn func(context.Context, []byte, *processors.ProcessorDependencies) ([]byte, error)) { + call := func(key string, productCode string, req interface{}) { wg.Add(1) go func() { defer wg.Done() @@ -48,7 +42,7 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors resultsCh <- apiResult{key: key, err: err} return } - resp, err := fn(ctx, b, deps) + resp, err := processors.CallTianyuanByProduct(ctx, deps, productCode, b) if err != nil { resultsCh <- apiResult{key: key, err: err} return @@ -57,7 +51,7 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors var uerr error // 根节点可能是数组或非对象,与欠税接口一致用宽松解析 if key == "taxArrears" || key == "annualReport" || key == "taxViolation" { - m, uerr = unmarshalToReportMap(resp) + m, uerr = reportstore.UnmarshalToReportMap(resp) } else { uerr = json.Unmarshal(resp, &m) } @@ -70,40 +64,27 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors } // 企业全量信息核验V2(QYGLUY3S) - call("jiguangFull", map[string]interface{}{ + call("jiguangFull", "QYGLUY3S", map[string]interface{}{ "ent_name": p.EntName, "ent_code": p.EntCode, - }, ProcessQYGLUY3SRequest) + }) // 企业股权结构全景(QYGLJ0Q1) - call("equityPanorama", map[string]interface{}{ + call("equityPanorama", "QYGLJ0Q1", map[string]interface{}{ "ent_name": p.EntName, - }, ProcessQYGLJ0Q1Request) - - // 企业司法涉诉V2(QYGL5S1I) - call("judicialCertFull", map[string]interface{}{ - "ent_name": p.EntName, - "ent_code": p.EntCode, - }, ProcessQYGL5S1IRequest) + }) // 企业年报信息核验(QYGLDJ12) - call("annualReport", map[string]interface{}{ + call("annualReport", "QYGLDJ12", map[string]interface{}{ "ent_name": p.EntName, "ent_code": p.EntCode, - }, ProcessQYGLDJ12Request) + }) // 企业税收违法核查(QYGL8848) - call("taxViolation", map[string]interface{}{ + call("taxViolation", "QYGL8848", map[string]interface{}{ "ent_name": p.EntName, "ent_code": p.EntCode, - }, ProcessQYGL8848Request) - - // 欠税公告(QYGL7D9A,天眼查 OwnTax,keyword 为统一社会信用代码) - call("taxArrears", map[string]interface{}{ - "ent_code": p.EntCode, - "page_size": 20, - "page_num": 1, - }, ProcessQYGL7D9ARequest) + }) wg.Wait() close(resultsCh) @@ -136,12 +117,12 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors // 复用构建逻辑生成企业报告结构(含年报 / 税收违法 / 欠税公告的转化结果) report := buildReport(jiguang, judicial, equity, annualReport, taxViolation, taxArrears) - if !qyglJ1U9ReportHasSubstantiveData(report) { + if !qygl7HBNReportHasSubstantiveData(report) { return nil, errors.Join(processors.ErrNotFound, errors.New("未查询到可用于生成报告的企业数据")) } // 为报告生成唯一编号并缓存,供后续通过编号查看 - reportID := saveQYGLReport(report) + reportID := reportstore.Save(report) report["reportId"] = reportID // 异步预生成 PDF(写入磁盘缓存),用户点击「保存为 PDF」时可直读缓存 @@ -156,7 +137,7 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors _ = deps.ReportRepo.Create(ctx, &entities.Report{ ReportID: reportID, Type: "enterprise", - ApiCode: "QYGLJ1U9", + ApiCode: "QYGL7HBN", EntName: p.EntName, EntCode: p.EntCode, RequestParams: string(reqJSON), @@ -164,7 +145,7 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors }) } // 为报告补充前端查看链接,供调用方直接跳转到企业报告页面(通过编号访问) - report["reportUrl"] = buildQYGLReportURLByID(deps.APIPublicBaseURL, reportID) + report["reportUrl"] = reportstore.BuildReportURLByID(deps.APIPublicBaseURL, reportID) out, err := json.Marshal(report) if err != nil { @@ -172,60 +153,3 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors } return out, nil } - -// unmarshalToReportMap 将 JSON 解析为报告用 map;根节点非对象时包在 data 下(兼容欠税等接口根为数组的情况)。 -func unmarshalToReportMap(b []byte) (map[string]interface{}, error) { - var raw interface{} - if err := json.Unmarshal(b, &raw); err != nil { - return nil, err - } - if m, ok := raw.(map[string]interface{}); ok { - return m, nil - } - return map[string]interface{}{"data": raw}, nil -} - -// 内存中的企业报告缓存(简单实现,进程重启后清空) -var qyglReportStore = struct { - sync.RWMutex - data map[string]map[string]interface{} -}{ - data: make(map[string]map[string]interface{}), -} - -// saveQYGLReport 保存报告并返回生成的编号 -func saveQYGLReport(report map[string]interface{}) string { - id := generateQYGLReportID() - qyglReportStore.Lock() - qyglReportStore.data[id] = report - qyglReportStore.Unlock() - return id -} - -// GetQYGLReport 根据编号获取报告(供页面渲染使用) -func GetQYGLReport(id string) (map[string]interface{}, bool) { - qyglReportStore.RLock() - defer qyglReportStore.RUnlock() - r, ok := qyglReportStore.data[id] - return r, ok -} - -// generateQYGLReportID 生成短编号 -func generateQYGLReportID() string { - b := make([]byte, 8) - if _, err := rand.Read(b); err == nil { - return hex.EncodeToString(b) - } - // 随机数失败时退化为时间戳 - return fmt.Sprintf("%d", time.Now().UnixNano()) -} - -// buildQYGLReportURLByID 构造企业报告前端查看链接(通过编号查看)。 -// publicBase 为对外 API 基址(如 https://api.example.com),空则返回站内相对路径。 -func buildQYGLReportURLByID(publicBase, id string) string { - path := "/reports/qygl/" + url.PathEscape(id) - if publicBase == "" { - return path - } - return strings.TrimRight(publicBase, "/") + path -} diff --git a/internal/domains/api/services/processors/qygl/qyglj1u9_processor_test.go b/internal/domains/api/services/processors/qygl/qygl7hbn_processor_test.go similarity index 83% rename from internal/domains/api/services/processors/qygl/qyglj1u9_processor_test.go rename to internal/domains/api/services/processors/qygl/qygl7hbn_processor_test.go index 6fdeff3..4069cf9 100644 --- a/internal/domains/api/services/processors/qygl/qyglj1u9_processor_test.go +++ b/internal/domains/api/services/processors/qygl/qygl7hbn_processor_test.go @@ -7,13 +7,13 @@ import ( sharedvalidator "hyapi-server/internal/shared/validator" ) -// TestQYGLJ1U9Req_ValidateParams 仅验证 QYGLJ1U9 入参的校验规则(特别是 validUSCI)。 -func TestQYGLJ1U9Req_ValidateParams(t *testing.T) { +// TestQYGL7HBNReq_ValidateParams 仅验证 QYGLJ1U9 入参的校验规则(特别是 validUSCI)。 +func TestQYGL7HBNReq_ValidateParams(t *testing.T) { // 使用全局业务校验器 bv := sharedvalidator.NewBusinessValidator() t.Run("invalid_usci_should_fail", func(t *testing.T) { - req := dto.QYGLJ1U9Req{ + req := dto.QYGL7HBNReq{ EntName: "测试企业有限公司", EntCode: "123", // 明显不符合 validUSCI } @@ -23,7 +23,7 @@ func TestQYGLJ1U9Req_ValidateParams(t *testing.T) { }) t.Run("valid_usci_should_pass", func(t *testing.T) { - req := dto.QYGLJ1U9Req{ + req := dto.QYGL7HBNReq{ EntName: "杭州娃哈哈集团有限公司", EntCode: "91330000142916567N", // 符合 validUSCI 正则的示例 } diff --git a/internal/domains/api/services/processors/qygl/qyglv4s6_processor.go b/internal/domains/api/services/processors/qygl/qygl7z0o_processor.go similarity index 88% rename from internal/domains/api/services/processors/qygl/qyglv4s6_processor.go rename to internal/domains/api/services/processors/qygl/qygl7z0o_processor.go index 4e6d29f..76122d6 100644 --- a/internal/domains/api/services/processors/qygl/qyglv4s6_processor.go +++ b/internal/domains/api/services/processors/qygl/qygl7z0o_processor.go @@ -10,10 +10,10 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessQYGLV4S6Request QYGLV4S6 API处理方法 -企业诉讼定制版 +// ProcessQYGL7Z0ORequest QYGLV4S6 API处理方法 -企业诉讼定制版 -func ProcessQYGLV4S6Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGLV4S6Req +func ProcessQYGL7Z0ORequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QYGL7Z0OReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/qygl/qygl8261_processor.go b/internal/domains/api/services/processors/qygl/qygl8261_processor.go deleted file mode 100644 index 13f396d..0000000 --- a/internal/domains/api/services/processors/qygl/qygl8261_processor.go +++ /dev/null @@ -1,45 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessQYGL8261Request QYGL8261 API处理方法 -func ProcessQYGL8261Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL8261Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedEntName, err := deps.WestDexService.Encrypt(paramsDto.EntName) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "ent_name": encryptedEntName, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "Q03BJ03", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl8271_processor.go b/internal/domains/api/services/processors/qygl/qygl8271_processor.go deleted file mode 100644 index e22ee65..0000000 --- a/internal/domains/api/services/processors/qygl/qygl8271_processor.go +++ /dev/null @@ -1,90 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "fmt" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" - - "github.com/tidwall/gjson" -) - -// ProcessQYGL8271Request QYGL8271 API处理方法 -func ProcessQYGL8271Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL8271Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedEntName, err := deps.WestDexService.Encrypt(paramsDto.EntName) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedEntCode, err := deps.WestDexService.Encrypt(paramsDto.EntCode) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - if deps.CallContext.ContractCode == "" { - return nil, fmt.Errorf("%s: %w", processors.ErrSystem, errors.New("合同编号不能为空")) - } - encryptedAuthAuthorizeFileCode, err := deps.WestDexService.Encrypt(deps.CallContext.ContractCode) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "org_name": encryptedEntName, - "uscc": encryptedEntCode, - "auth_authorizeFileCode": encryptedAuthAuthorizeFileCode, - "inquired_auth": fmt.Sprintf("authed:%s", paramsDto.AuthDate), - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "Q03SC01", reqData) - if err != nil { - // 数据源错误 - if errors.Is(err, westdex.ErrDatasource) { - // 如果有返回内容,优先解析返回内容 - if respBytes != nil { - parsed, parseErr := ParseJsonResponse(respBytes) - if parseErr == nil { - // 通过gjson获取指定路径的数据 - contentResult := gjson.GetBytes(parsed, "Q03SC0101.Q03SC0102.content") - if contentResult.Exists() { - return []byte(contentResult.Raw), errors.Join(processors.ErrDatasource, err) - } - return parsed, errors.Join(processors.ErrDatasource, err) - } - // 解析失败,返回原始内容和系统错误 - return respBytes, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr) - } - // 没有返回内容,直接返回数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } - // 其他系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } - - // 正常返回 - 不管有没有deps.Options.Json都进行ParseJsonResponse - parsed, parseErr := ParseJsonResponse(respBytes) - if parseErr != nil { - return nil, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr) - } - - // 通过gjson获取指定路径的数据 - contentResult := gjson.GetBytes(parsed, "Q03SC0101.Q03SC0102.content") - if contentResult.Exists() { - return []byte(contentResult.Raw), nil - } else { - return nil, errors.Join(processors.ErrDatasource, err) - } -} diff --git a/internal/domains/api/services/processors/qygl/qygl8848_processor.go b/internal/domains/api/services/processors/qygl/qygl8848_processor.go deleted file mode 100644 index 82b4b6b..0000000 --- a/internal/domains/api/services/processors/qygl/qygl8848_processor.go +++ /dev/null @@ -1,68 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessQYGL8848Request QYGL8848 企业税收违法核查 API 处理方法(使用数据宝服务示例) -func ProcessQYGL8848Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGLDJ12Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 企业名称(entName)、统一社会信用代码(creditCode)、企业注册号(entRegNo) 至少传其一;多填时优先用 creditCode 传参 - hasEntName := paramsDto.EntName != "" - hasEntCode := paramsDto.EntCode != "" - hasEntRegNo := paramsDto.EntRegNo != "" - if !hasEntName && !hasEntCode && !hasEntRegNo { // 三个都未填才报错 - return nil, errors.Join(processors.ErrInvalidParam, errors.New("ent_name、ent_code、ent_reg_no 至少需要传其中一个")) - } - - // 构建数据宝入参(多填时优先取 creditCode) - reqParams := map[string]interface{}{ - "key": "c67673dd2e92deb2d2ec91b87bb0a81c", - } - if hasEntCode { - reqParams["creditCode"] = paramsDto.EntCode - } else if hasEntName { - reqParams["entName"] = paramsDto.EntName - } else if hasEntRegNo { - reqParams["regCode"] = paramsDto.EntRegNo - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10233" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - // 解析响应中的 JSON 字符串(使用 qyglb4c0 中的 RecursiveParse) - parsedResp, err := RecursiveParse(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(parsedResp) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl8b4d_processor.go b/internal/domains/api/services/processors/qygl/qygl8b4d_processor.go deleted file mode 100644 index 088f566..0000000 --- a/internal/domains/api/services/processors/qygl/qygl8b4d_processor.go +++ /dev/null @@ -1,59 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "strconv" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessQYGL8B4DRequest QYGL8B4D API处理方法 - 融资历史 -func ProcessQYGL8B4DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL8B4DReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 设置默认值 - pageSize := paramsDto.PageSize - if pageSize == 0 { - pageSize = int64(20) - } - pageNum := paramsDto.PageNum - if pageNum == 0 { - pageNum = int64(1) - } - - // 构建API调用参数 - apiParams := map[string]string{ - "keyword": paramsDto.EntCode, - "pageSize": strconv.FormatInt(pageSize, 10), - "pageNum": strconv.FormatInt(pageNum, 10), - } - - // 调用天眼查API - 融资历史 - response, err := deps.TianYanChaService.CallAPI(ctx, "FinancingHistory", apiParams) - if err != nil { - return nil, convertTianYanChaError(err) - } - - // 检查天眼查API调用是否成功 - if !response.Success { - return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message)) - } - - // 返回天眼查响应数据 - respBytes, err := json.Marshal(response.Data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl9e2f_processor.go b/internal/domains/api/services/processors/qygl/qygl9e2f_processor.go deleted file mode 100644 index 9541e0c..0000000 --- a/internal/domains/api/services/processors/qygl/qygl9e2f_processor.go +++ /dev/null @@ -1,59 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - "strconv" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessQYGL9E2FRequest QYGL9E2F API处理方法 - 行政处罚 -func ProcessQYGL9E2FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL9E2FReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 设置默认值 - pageSize := paramsDto.PageSize - if pageSize == 0 { - pageSize = int64(20) - } - pageNum := paramsDto.PageNum - if pageNum == 0 { - pageNum = int64(1) - } - - // 构建API调用参数 - apiParams := map[string]string{ - "keyword": paramsDto.EntCode, - "pageSize": strconv.FormatInt(pageSize, 10), - "pageNum": strconv.FormatInt(pageNum, 10), - } - - // 调用天眼查API - 行政处罚 - response, err := deps.TianYanChaService.CallAPI(ctx, "PunishmentInfo", apiParams) - if err != nil { - return nil, convertTianYanChaError(err) - } - - // 检查天眼查API调用是否成功 - if !response.Success { - return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message)) - } - - // 返回天眼查响应数据 - respBytes, err := json.Marshal(response.Data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygl9myb_processor.go b/internal/domains/api/services/processors/qygl/qygl9myb_processor.go new file mode 100644 index 0000000..a4e6d86 --- /dev/null +++ b/internal/domains/api/services/processors/qygl/qygl9myb_processor.go @@ -0,0 +1,27 @@ +package qygl + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessQYGL9MYBRequest QYGLJ0Q1 企业股权结构全景查询(天远中转) +func ProcessQYGL9MYBRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QYGL9MYBReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + hasEntName := paramsDto.EntName != "" + hasEntCode := paramsDto.EntCode != "" + if hasEntName == hasEntCode { + return nil, errors.Join(processors.ErrInvalidParam, errors.New("ent_name 与 ent_code 二选一,必须且仅能传其中一个")) + } + return processors.CallTianyuanByProduct(ctx, deps, "QYGLJ0Q1", params) +} diff --git a/internal/domains/api/services/processors/qygl/qygl9t1q_processor.go b/internal/domains/api/services/processors/qygl/qygl9t1q_processor.go deleted file mode 100644 index c51a4a9..0000000 --- a/internal/domains/api/services/processors/qygl/qygl9t1q_processor.go +++ /dev/null @@ -1,55 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// Processqygl9t1qRequest QYGL9T1Q API处理方法 - 全国企业借贷意向验证查询_V1 -func ProcessQYGL9T1QRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - - var paramsDto dto.QYGL9T1QReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,直接传递姓名、身份证、手机号等 - reqData := map[string]interface{}{ - "ownerType": paramsDto.OwnerType, - "phoneNumber": paramsDto.MobileNo, - "idCardNum": paramsDto.IDCard, - "name": paramsDto.Name, - "searchKey": paramsDto.EntCode, // 企业统一信用代码和注册号两者必填其一 - "authAuthorizeFileCode": paramsDto.Authorized, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1078965351139438592" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - // 查空情况,返回特定的查空错误 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qyglalpk_processor.go b/internal/domains/api/services/processors/qygl/qyglalpk_processor.go new file mode 100644 index 0000000..114341a --- /dev/null +++ b/internal/domains/api/services/processors/qygl/qyglalpk_processor.go @@ -0,0 +1,14 @@ +package qygl + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessQYGLALPKRequest QYGLUY3S 企业全量信息核验V2(天远中转) +func ProcessQYGLALPKRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QYGLALPKReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "QYGLUY3S", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/qygl/qyglb4c0_processor.go b/internal/domains/api/services/processors/qygl/qyglb4c0_processor.go deleted file mode 100644 index cf16e35..0000000 --- a/internal/domains/api/services/processors/qygl/qyglb4c0_processor.go +++ /dev/null @@ -1,105 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" - - "github.com/tidwall/gjson" -) - -// ProcessQYGLB4C0Request QYGLB4C0 API处理方法 -func ProcessQYGLB4C0Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGLB4C0Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedIDCard := deps.WestDexService.Md5Encrypt(paramsDto.IDCard) - - reqData := map[string]interface{}{ - "pid": encryptedIDCard, - } - - respBytes, err := deps.WestDexService.G05HZ01CallAPI(ctx, "G05HZ01", reqData) - if err != nil { - // 数据源错误 - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, westdex.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } - // 其他系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} - -// ParseWestResponse 解析西部返回的响应数据(获取data字段后解析) -// westResp: 西部返回的原始响应 -// Returns: 解析后的数据字节数组 -func ParseWestResponse(westResp []byte) ([]byte, error) { - dataResult := gjson.GetBytes(westResp, "data") - if !dataResult.Exists() { - return nil, errors.New("data not found") - } - return ParseJsonResponse([]byte(dataResult.Raw)) -} - -// ParseJsonResponse 直接解析JSON响应数据 -// jsonResp: JSON响应数据 -// Returns: 解析后的数据字节数组 -func ParseJsonResponse(jsonResp []byte) ([]byte, error) { - parseResult, err := RecursiveParse(string(jsonResp)) - if err != nil { - return nil, err - } - - resultResp, marshalErr := json.Marshal(parseResult) - if marshalErr != nil { - return nil, err - } - - return resultResp, nil -} - -// RecursiveParse 递归解析JSON数据 -func RecursiveParse(data interface{}) (interface{}, error) { - switch v := data.(type) { - case string: - var parsed interface{} - if err := json.Unmarshal([]byte(v), &parsed); err == nil { - return RecursiveParse(parsed) - } - return v, nil - case map[string]interface{}: - for key, val := range v { - parsed, err := RecursiveParse(val) - if err != nil { - return nil, err - } - v[key] = parsed - } - return v, nil - case []interface{}: - for i, item := range v { - parsed, err := RecursiveParse(item) - if err != nil { - return nil, err - } - v[i] = parsed - } - return v, nil - default: - return v, nil - } -} diff --git a/internal/domains/api/services/processors/qygl/qygldj12_processor.go b/internal/domains/api/services/processors/qygl/qygldj12_processor.go deleted file mode 100644 index 8970fc6..0000000 --- a/internal/domains/api/services/processors/qygl/qygldj12_processor.go +++ /dev/null @@ -1,67 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessQYGLDJ12Request QYGLDJ12 企业年报信息核验 API 处理方法(使用数据宝服务示例) -func ProcessQYGLDJ12Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGLDJ12Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 企业名称(entName)、统一社会信用代码(creditCode)、企业注册号(entRegNo) 至少传其一;多填时优先用 creditCode 传参 - hasEntName := paramsDto.EntName != "" - hasEntCode := paramsDto.EntCode != "" - hasEntRegNo := paramsDto.EntRegNo != "" - if !hasEntName && !hasEntCode && !hasEntRegNo { // 三个都未填才报错 - return nil, errors.Join(processors.ErrInvalidParam, errors.New("ent_name、ent_code、ent_reg_no 至少需要传其中一个")) - } - - // 构建数据宝入参(sign 外的业务参数可按需 AES 加密后作为 bodyData) - reqParams := map[string]interface{}{ - "key": "112813815e2cc281ad8f552deb7a3c7f", - } - if hasEntCode { - reqParams["creditCode"] = paramsDto.EntCode - } else if hasEntName { - reqParams["entName"] = paramsDto.EntName - } else if hasEntRegNo { - reqParams["regCode"] = paramsDto.EntRegNo - } - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10192" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - // 解析响应中的 JSON 字符串(使用 qyglb4c0 中的 RecursiveParse) - parsedResp, err := RecursiveParse(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(parsedResp) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qyglj0q1_processor.go b/internal/domains/api/services/processors/qygl/qyglj0q1_processor.go deleted file mode 100644 index 6ff44a0..0000000 --- a/internal/domains/api/services/processors/qygl/qyglj0q1_processor.go +++ /dev/null @@ -1,65 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessQYGLJ0Q1Request QYGLJ0Q1 企业股权结构全景查询 API 处理方法(使用数据宝服务示例) -func ProcessQYGLJ0Q1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGLJ0Q1Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 二选一:企业名称(entName) 与 统一社会信用代码(creditCode) 必须且仅能传其一 - hasEntName := paramsDto.EntName != "" - hasEntCode := paramsDto.EntCode != "" - if hasEntName == hasEntCode { // 两个都填或两个都未填 - return nil, errors.Join(processors.ErrInvalidParam, errors.New("ent_name 与 ent_code 二选一,必须且仅能传其中一个")) - } - - // 构建数据宝入参(sign 外的业务参数可按需 AES 加密后作为 bodyData) - reqParams := map[string]interface{}{ - "key": "adac456f7b4ced764b606c8b07fed4d3", - } - if hasEntName { - reqParams["entName"] = paramsDto.EntName - } else { - reqParams["creditCode"] = paramsDto.EntCode - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10216" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - // 解析响应中的 JSON 字符串(使用 qyglb4c0 中的 RecursiveParse) - parsedResp, err := RecursiveParse(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(parsedResp) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qyglj1u9_processor_build.go b/internal/domains/api/services/processors/qygl/qyglj1u9_processor_build.go index 3c71d67..2f6373c 100644 --- a/internal/domains/api/services/processors/qygl/qyglj1u9_processor_build.go +++ b/internal/domains/api/services/processors/qygl/qyglj1u9_processor_build.go @@ -58,12 +58,12 @@ func buildReport(jiguang, judicial, equity, annualRaw, taxViolationRaw, taxArrea report["annualReports"] = annualReports report["taxViolations"] = mapTaxViolations(taxViolationRaw) report["ownTaxNotices"] = mapOwnTaxNotices(taxArrearsRaw) - applyQYGLJ1U9ReportFieldDefaults(report) + applyQYGL7HBNReportFieldDefaults(report) return report } -// applyQYGLJ1U9ReportFieldDefaults 在子数据源缺失时仍保证报告字段齐全:字符串 ""、数值 0、数组 []、对象按约定填空结构(不向客户暴露「缺键」)。 -func applyQYGLJ1U9ReportFieldDefaults(report map[string]interface{}) { +// applyQYGL7HBNReportFieldDefaults 在子数据源缺失时仍保证报告字段齐全:字符串 ""、数值 0、数组 []、对象按约定填空结构(不向客户暴露「缺键」)。 +func applyQYGL7HBNReportFieldDefaults(report map[string]interface{}) { if report == nil { return } @@ -615,9 +615,9 @@ func ensureStrKeys(m map[string]interface{}, keys []string) { } } -// qyglJ1U9ReportHasSubstantiveData 判断合并后的报告是否至少含一项可展示的企业要素。 +// qygl7HBNReportHasSubstantiveData 判断合并后的报告是否至少含一项可展示的企业要素。 // 当所有子数据源均失败或等价于无数据时返回 false,用于 QYGLJ1U9 整体返回「查询为空」。 -func qyglJ1U9ReportHasSubstantiveData(report map[string]interface{}) bool { +func qygl7HBNReportHasSubstantiveData(report map[string]interface{}) bool { if report == nil { return false } diff --git a/internal/domains/api/services/processors/qygl/qyglbh7y_processor.go b/internal/domains/api/services/processors/qygl/qygllucm_processor.go similarity index 76% rename from internal/domains/api/services/processors/qygl/qyglbh7y_processor.go rename to internal/domains/api/services/processors/qygl/qygllucm_processor.go index 9fff24c..1ad45cb 100644 --- a/internal/domains/api/services/processors/qygl/qyglbh7y_processor.go +++ b/internal/domains/api/services/processors/qygl/qygllucm_processor.go @@ -9,9 +9,9 @@ import ( "hyapi-server/internal/domains/api/services/processors" ) -// ProcessQYGLBH7YRequest QYGLBH7Y API处理方法 - 企业案件查询汇博 -func ProcessQYGLBH7YRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGLBH7YReq +// ProcessQYGLLUCMRequest QYGLBH7Y API处理方法 - 企业案件查询汇博 +func ProcessQYGLLUCMRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QYGLLUCMReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } @@ -24,7 +24,7 @@ func ProcessQYGLBH7YRequest(ctx context.Context, params []byte, deps *processors return nil, errors.Join(processors.ErrInvalidParam, err) } - if _, err := deps.HuiboService.SaveAuthPDFLocally(ctx, "QYGLBH7Y", paramsDto.AuthPDFBase64, paramsDto.EntName); err != nil { + if _, err := deps.HuiboService.SaveAuthPDFLocally(ctx, "QYGLLUCM", paramsDto.AuthPDFBase64, paramsDto.EntName); err != nil { return nil, errors.Join(processors.ErrInvalidParam, err) } diff --git a/internal/domains/api/services/processors/qygl/qyglnio8_processor.go b/internal/domains/api/services/processors/qygl/qyglnio8_processor.go deleted file mode 100644 index 6113046..0000000 --- a/internal/domains/api/services/processors/qygl/qyglnio8_processor.go +++ /dev/null @@ -1,46 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessQYGLNIO8Request QYGLNIO8 API处理方法 - 企业基本信息 -func ProcessQYGLNIO8Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGLNIO8Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建API调用参数 - apiParams := map[string]string{ - "keyword": paramsDto.EntCode, - } - - // 调用天眼查API - 企业基本信息 - response, err := deps.TianYanChaService.CallAPI(ctx, "baseinfo", apiParams) - if err != nil { - return nil, convertTianYanChaError(err) - } - - // 检查天眼查API调用是否成功 - if !response.Success { - return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message)) - } - - // 返回天眼查响应数据 - respBytes, err := json.Marshal(response.Data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qyglp0ht_processor.go b/internal/domains/api/services/processors/qygl/qyglp0ht_processor.go deleted file mode 100644 index 9992fd0..0000000 --- a/internal/domains/api/services/processors/qygl/qyglp0ht_processor.go +++ /dev/null @@ -1,68 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessQYGLP0HTRequest QYGLP0HT API处理方法 - 股权穿透 -func ProcessQYGLP0HTRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGLP0HTReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 设置默认值 - flag := paramsDto.Flag - if flag == "" { - flag = "4" - } - dir := paramsDto.Dir - if dir == "" { - dir = "down" - } - minPercent := paramsDto.MinPercent - if minPercent == "" { - minPercent = "0" - } - maxPercent := paramsDto.MaxPercent - if maxPercent == "" { - maxPercent = "1" - } - - // 构建API调用参数 - apiParams := map[string]string{ - "keyword": paramsDto.EntCode, - "flag": flag, - "dir": dir, - "minPercent": minPercent, - "maxPercent": maxPercent, - } - - // 调用天眼查API - 企股权穿透 - response, err := deps.TianYanChaService.CallAPI(ctx, "investtree", apiParams) - if err != nil { - return nil, convertTianYanChaError(err) - } - - // 检查天眼查API调用是否成功 - if !response.Success { - return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message)) - } - - // 返回天眼查响应数据 - respBytes, err := json.Marshal(response.Data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qygludjg_processor.go b/internal/domains/api/services/processors/qygl/qygludjg_processor.go new file mode 100644 index 0000000..8ca1771 --- /dev/null +++ b/internal/domains/api/services/processors/qygl/qygludjg_processor.go @@ -0,0 +1,28 @@ +package qygl + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessQYGLUDJGRequest QYGLDJ12 企业年报信息核验(天远中转) +func ProcessQYGLUDJGRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QYGLUDJGReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + hasEntName := paramsDto.EntName != "" + hasEntCode := paramsDto.EntCode != "" + hasEntRegNo := paramsDto.EntRegNo != "" + if !hasEntName && !hasEntCode && !hasEntRegNo { + return nil, errors.Join(processors.ErrInvalidParam, errors.New("ent_name、ent_code、ent_reg_no 至少需要传其中一个")) + } + return processors.CallTianyuanByProduct(ctx, deps, "QYGLDJ12", params) +} diff --git a/internal/domains/api/services/processors/qygl/qygluy3s_processor.go b/internal/domains/api/services/processors/qygl/qygluy3s_processor.go deleted file mode 100644 index efc097b..0000000 --- a/internal/domains/api/services/processors/qygl/qygluy3s_processor.go +++ /dev/null @@ -1,56 +0,0 @@ -package qygl - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessQYGLUY3SRequest QYGLUY3S 企业全量信息核验V2 可用 API 处理方法(使用数据宝服务示例) -func ProcessQYGLUY3SRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGLUY3SReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建数据宝入参:姓名、身份证、手机号、银行卡号(sign 外的业务参数可按需 AES 加密后作为 bodyData) - reqParams := map[string]interface{}{ - "key": "5131227a847c06c111f624a22ebacc06", - "entName": paramsDto.EntName, - "regno": paramsDto.EntRegno, - "creditcode": paramsDto.EntCode, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/10195" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - // 解析响应中的 JSON 字符串(使用 qyglb4c0 中的 RecursiveParse) - parsedResp, err := RecursiveParse(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(parsedResp) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/qygl/qyglvr76_processor.go b/internal/domains/api/services/processors/qygl/qyglwv7u_processor.go similarity index 87% rename from internal/domains/api/services/processors/qygl/qyglvr76_processor.go rename to internal/domains/api/services/processors/qygl/qyglwv7u_processor.go index fa243b1..6c12db7 100644 --- a/internal/domains/api/services/processors/qygl/qyglvr76_processor.go +++ b/internal/domains/api/services/processors/qygl/qyglwv7u_processor.go @@ -10,9 +10,9 @@ import ( "hyapi-server/internal/infrastructure/external/nuoer" ) -// ProcessQYGLVR76Request QYGLVR76 API处理方法 -人企关联 -func ProcessQYGLVR76Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGLVR76Req +// ProcessQYGLWV7URequest QYGLVR76 API处理方法 -人企关联 +func ProcessQYGLWV7URequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QYGLWV7UReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } diff --git a/internal/domains/api/services/processors/qygl/qyglwyek_processor.go b/internal/domains/api/services/processors/qygl/qyglwyek_processor.go new file mode 100644 index 0000000..f1f6a5c --- /dev/null +++ b/internal/domains/api/services/processors/qygl/qyglwyek_processor.go @@ -0,0 +1,28 @@ +package qygl + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessQYGLWYEKRequest QYGL8848 企业税收违法核查(天远中转) +func ProcessQYGLWYEKRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QYGLWYEKReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + hasEntName := paramsDto.EntName != "" + hasEntCode := paramsDto.EntCode != "" + hasEntRegNo := paramsDto.EntRegNo != "" + if !hasEntName && !hasEntCode && !hasEntRegNo { + return nil, errors.Join(processors.ErrInvalidParam, errors.New("ent_name、ent_code、ent_reg_no 至少需要传其中一个")) + } + return processors.CallTianyuanByProduct(ctx, deps, "QYGL8848", params) +} diff --git a/internal/domains/api/services/processors/qygl/reportstore/store.go b/internal/domains/api/services/processors/qygl/reportstore/store.go new file mode 100644 index 0000000..c05f50a --- /dev/null +++ b/internal/domains/api/services/processors/qygl/reportstore/store.go @@ -0,0 +1,70 @@ +package reportstore + +import ( + "crypto/rand" + "encoding/hex" + "encoding/json" + "fmt" + "net/url" + "strings" + "sync" + "time" +) + +// UnmarshalToReportMap 将 JSON 解析为报告用 map;根节点非对象时包在 data 下。 +func UnmarshalToReportMap(b []byte) (map[string]interface{}, error) { + var raw interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return nil, err + } + if m, ok := raw.(map[string]interface{}); ok { + return m, nil + } + return map[string]interface{}{"data": raw}, nil +} + +var reportStore = struct { + sync.RWMutex + data map[string]map[string]interface{} +}{ + data: make(map[string]map[string]interface{}), +} + +// Save 保存报告并返回生成的编号 +func Save(report map[string]interface{}) string { + id := newReportID() + reportStore.Lock() + reportStore.data[id] = report + reportStore.Unlock() + return id +} + +// Get 根据编号获取报告 +func Get(id string) (map[string]interface{}, bool) { + reportStore.RLock() + defer reportStore.RUnlock() + r, ok := reportStore.data[id] + return r, ok +} + +// GetQYGLReport 根据编号获取企业全景报告(HTTP 页面渲染使用) +func GetQYGLReport(id string) (map[string]interface{}, bool) { + return Get(id) +} + +func newReportID() string { + b := make([]byte, 8) + if _, err := rand.Read(b); err == nil { + return hex.EncodeToString(b) + } + return fmt.Sprintf("%d", time.Now().UnixNano()) +} + +// BuildReportURLByID 构造企业报告前端查看链接 +func BuildReportURLByID(publicBase, id string) string { + path := "/reports/qygl/" + url.PathEscape(id) + if publicBase == "" { + return path + } + return strings.TrimRight(publicBase, "/") + path +} diff --git a/internal/domains/api/services/processors/shujubao_recursive_parse.go b/internal/domains/api/services/processors/shujubao_recursive_parse.go new file mode 100644 index 0000000..fda027b --- /dev/null +++ b/internal/domains/api/services/processors/shujubao_recursive_parse.go @@ -0,0 +1,58 @@ +package processors + +import ( + "encoding/json" + "fmt" +) + +// RecursiveParse 将数据宝等返回中嵌套的 JSON 字符串递归解析为结构化数据。 +func RecursiveParse(data interface{}) (interface{}, error) { + switch v := data.(type) { + case string: + trimmed := trimSpace(v) + if trimmed == "" { + return v, nil + } + if !json.Valid([]byte(trimmed)) { + return v, nil + } + var inner interface{} + if err := json.Unmarshal([]byte(trimmed), &inner); err != nil { + return v, nil + } + return RecursiveParse(inner) + case map[string]interface{}: + out := make(map[string]interface{}, len(v)) + for k, val := range v { + parsed, err := RecursiveParse(val) + if err != nil { + return nil, fmt.Errorf("解析字段 %s 失败: %w", k, err) + } + out[k] = parsed + } + return out, nil + case []interface{}: + out := make([]interface{}, len(v)) + for i, val := range v { + parsed, err := RecursiveParse(val) + if err != nil { + return nil, fmt.Errorf("解析数组下标 %d 失败: %w", i, err) + } + out[i] = parsed + } + return out, nil + default: + return data, nil + } +} + +func trimSpace(s string) string { + start, end := 0, len(s) + for start < end && (s[start] == ' ' || s[start] == '\n' || s[start] == '\r' || s[start] == '\t') { + start++ + } + for end > start && (s[end-1] == ' ' || s[end-1] == '\n' || s[end-1] == '\r' || s[end-1] == '\t') { + end-- + } + return s[start:end] +} diff --git a/internal/domains/api/services/processors/test/README.md b/internal/domains/api/services/processors/test/README.md deleted file mode 100644 index b6abffc..0000000 --- a/internal/domains/api/services/processors/test/README.md +++ /dev/null @@ -1,94 +0,0 @@ -# 测试处理器使用说明 - -这个目录包含了用于测试的处理器,可以模拟各种API请求场景,帮助开发和测试人员验证系统功能。 - -## 处理器列表 - -### 1. ProcessTestRequest - 基础测试处理器 -- **功能**: 模拟正常的API请求处理 -- **用途**: 测试基本的请求处理流程、参数验证、响应生成等 - -#### 请求参数 -```json -{ - "test_param": "测试参数值", - "delay": 1000 -} -``` - -#### 响应示例 -```json -{ - "message": "测试请求处理成功", - "timestamp": "2024-01-01T12:00:00Z", - "request_id": "test_20240101120000_000000000", - "test_param": "测试参数值", - "process_time_ms": 1005, - "status": "success" -} -``` - -### 2. ProcessTestErrorRequest - 错误测试处理器 -- **功能**: 模拟各种错误情况 -- **用途**: 测试错误处理机制、异常响应等 - -#### 支持的错误类型 -- `system_error`: 系统错误 -- `datasource_error`: 数据源错误 -- `not_found`: 资源未找到 -- `invalid_param`: 参数无效 - -#### 请求示例 -```json -{ - "test_param": "system_error" -} -``` - -### 3. ProcessTestTimeoutRequest - 超时测试处理器 -- **功能**: 模拟长时间处理导致的超时 -- **用途**: 测试超时处理、上下文取消等 - -## 使用场景 - -### 开发阶段 -- 验证处理器框架是否正常工作 -- 测试参数验证逻辑 -- 验证错误处理机制 - -### 测试阶段 -- 性能测试(通过delay参数) -- 超时测试 -- 错误场景测试 -- 集成测试 - -### 调试阶段 -- 快速验证API调用流程 -- 测试中间件功能 -- 验证日志记录 - -## 注意事项 - -1. **延迟参数**: `delay` 参数最大值为5000毫秒(5秒),避免测试时等待时间过长 -2. **上下文处理**: 所有处理器都正确处理上下文取消,支持超时控制 -3. **错误处理**: 遵循项目的错误处理规范,使用预定义的错误类型 -4. **参数验证**: 使用标准的参数验证机制,确保测试的真实性 - -## 集成到路由 - -要将测试处理器集成到API路由中,需要在相应的路由配置中添加: - -```go -// 在路由配置中添加测试端点 -router.POST("/api/test/basic", handlers.WrapProcessor(processors.ProcessTestRequest)) -router.POST("/api/test/error", handlers.WrapProcessor(processors.ProcessTestErrorRequest)) -router.POST("/api/test/timeout", handlers.WrapProcessor(processors.ProcessTestTimeoutRequest)) -``` - -## 测试建议 - -1. **基础功能测试**: 先使用 `ProcessTestRequest` 验证基本流程 -2. **错误场景测试**: 使用 `ProcessTestErrorRequest` 测试各种错误情况 -3. **性能测试**: 通过调整 `delay` 参数测试不同响应时间 -4. **超时测试**: 使用 `ProcessTestTimeoutRequest` 验证超时处理 -5. **压力测试**: 并发调用测试处理器的稳定性 diff --git a/internal/domains/api/services/processors/test/test_processor.go b/internal/domains/api/services/processors/test/test_processor.go deleted file mode 100644 index 259454b..0000000 --- a/internal/domains/api/services/processors/test/test_processor.go +++ /dev/null @@ -1,120 +0,0 @@ -package test - -import ( - "context" - "encoding/json" - "errors" - "time" - - "hyapi-server/internal/domains/api/services/processors" -) - -// TestRequest 测试请求参数 -type TestRequest struct { - TestParam string `json:"test_param" validate:"required"` - Delay int `json:"delay" validate:"min=0,max=5000"` // 延迟毫秒数,最大5秒 -} - -// TestResponse 测试响应数据 -type TestResponse struct { - Message string `json:"message"` - Timestamp time.Time `json:"timestamp"` - RequestID string `json:"request_id"` - TestParam string `json:"test_param"` - ProcessTime int64 `json:"process_time_ms"` - Status string `json:"status"` -} - -// ProcessTestRequest 测试处理器,用于模拟API请求 -func ProcessTestRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - startTime := time.Now() - - // 解析请求参数 - var req TestRequest - if err := json.Unmarshal(params, &req); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 参数验证 - if err := deps.Validator.ValidateStruct(req); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 模拟处理延迟 - if req.Delay > 0 { - select { - case <-ctx.Done(): - return nil, errors.Join(processors.ErrSystem, ctx.Err()) - case <-time.After(time.Duration(req.Delay) * time.Millisecond): - // 延迟完成 - } - } - - // 检查上下文是否已取消 - if ctx.Err() != nil { - return nil, errors.Join(processors.ErrSystem, ctx.Err()) - } - - // 生成响应数据 - response := TestResponse{ - Message: "测试请求处理成功", - Timestamp: time.Now(), - RequestID: generateTestRequestID(), - TestParam: req.TestParam, - ProcessTime: time.Since(startTime).Milliseconds(), - Status: "success", - } - - // 序列化响应 - result, err := json.Marshal(response) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return result, nil -} - -// ProcessTestErrorRequest 测试错误处理的处理器 -func ProcessTestErrorRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var req TestRequest - if err := json.Unmarshal(params, &req); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 模拟不同类型的错误 - switch req.TestParam { - case "system_error": - return nil, processors.ErrSystem - case "datasource_error": - return nil, processors.ErrDatasource - case "not_found": - return nil, processors.ErrNotFound - case "invalid_param": - return nil, processors.ErrInvalidParam - default: - return nil, errors.Join(processors.ErrSystem, errors.New("未知错误类型")) - } -} - -// ProcessTestTimeoutRequest 测试超时处理的处理器 -func ProcessTestTimeoutRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var req TestRequest - if err := json.Unmarshal(params, &req); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 模拟长时间处理 - select { - case <-ctx.Done(): - return nil, errors.Join(processors.ErrSystem, ctx.Err()) - case <-time.After(10 * time.Second): // 10秒超时 - // 这里通常不会执行到,因为上下文会先超时 - } - - return nil, processors.ErrSystem -} - -// generateTestRequestID 生成测试用的请求ID -func generateTestRequestID() string { - return "test_" + time.Now().Format("20060102150405") + "_" + time.Now().Format("000000000") -} diff --git a/internal/domains/api/services/processors/tianyuan_proxy.go b/internal/domains/api/services/processors/tianyuan_proxy.go new file mode 100644 index 0000000..e09a97b --- /dev/null +++ b/internal/domains/api/services/processors/tianyuan_proxy.go @@ -0,0 +1,53 @@ +package processors + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/infrastructure/external/tianyuanapi" +) + +// CallTianyuanByProduct 将处理器入参 JSON 转发至天远平台对应产品(使用天远侧产品编号) +func CallTianyuanByProduct(ctx context.Context, deps *ProcessorDependencies, productCode string, params []byte) ([]byte, error) { + if deps == nil || deps.TianyuanapiService == nil { + return nil, errors.Join(ErrSystem, errors.New("天远 API 服务未配置")) + } + + var paramsMap map[string]interface{} + if err := json.Unmarshal(params, ¶msMap); err != nil { + return nil, errors.Join(ErrSystem, err) + } + + respBytes, err := deps.TianyuanapiService.CallAPI(ctx, productCode, paramsMap) + if err != nil { + if errors.Is(err, tianyuanapi.ErrNotFound) { + return nil, errors.Join(ErrNotFound, err) + } + if errors.Is(err, tianyuanapi.ErrDatasource) { + return nil, errors.Join(ErrDatasource, err) + } + if errors.Is(err, tianyuanapi.ErrSystem) { + return nil, errors.Join(ErrSystem, err) + } + return nil, errors.Join(ErrSystem, err) + } + return respBytes, nil +} + +// MapTianyuanError 将天远服务错误映射为处理器层错误(直接调用 CallAPI 时使用) +func MapTianyuanError(err error) error { + if err == nil { + return nil + } + if errors.Is(err, tianyuanapi.ErrNotFound) { + return errors.Join(ErrNotFound, err) + } + if errors.Is(err, tianyuanapi.ErrDatasource) { + return errors.Join(ErrDatasource, err) + } + if errors.Is(err, tianyuanapi.ErrSystem) { + return errors.Join(ErrSystem, err) + } + return errors.Join(ErrSystem, err) +} diff --git a/internal/domains/api/services/processors/validate_tianyuan.go b/internal/domains/api/services/processors/validate_tianyuan.go new file mode 100644 index 0000000..d85d373 --- /dev/null +++ b/internal/domains/api/services/processors/validate_tianyuan.go @@ -0,0 +1,18 @@ +package processors + +import ( + "context" + "encoding/json" + "errors" +) + +// ValidateParamsAndCallTianyuan 校验入参后按天远产品编号转发 +func ValidateParamsAndCallTianyuan(ctx context.Context, deps *ProcessorDependencies, tianyuanProductCode string, params []byte, dest interface{}) ([]byte, error) { + if err := json.Unmarshal(params, dest); err != nil { + return nil, errors.Join(ErrSystem, err) + } + if err := deps.Validator.ValidateStruct(dest); err != nil { + return nil, errors.Join(ErrInvalidParam, err) + } + return CallTianyuanByProduct(ctx, deps, tianyuanProductCode, params) +} diff --git a/internal/domains/api/services/processors/yysy/yysy09cd_processor.go b/internal/domains/api/services/processors/yysy/yysy09cd_processor.go deleted file mode 100644 index dee47c4..0000000 --- a/internal/domains/api/services/processors/yysy/yysy09cd_processor.go +++ /dev/null @@ -1,111 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - "strings" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// YYSY09CDResponse 最终返回结构 -// code: 1000一致 1001不一致 1002查无 -type YYSY09CDResponse struct { - Code string `json:"code"` - Data YYSY09CDResponseData `json:"data"` -} - -type YYSY09CDResponseData struct { - Msg string `json:"msg"` // 一致/不一致/查无 - PhoneType string `json:"phoneType"` // CMCC/CUCC/CTCC/CBN - Code int `json:"code"` // 1000/1001/1002 - EncryptType string `json:"encryptType"` // MD5 -} - -// ProcessYYSY09CDRequest YYSY09CD API处理方法 - 运营商三要素查询 -func ProcessYYSY09CDRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY09CDReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqParams := map[string]interface{}{ - "key": "c115708d915451da8f34a23e144dda6b", - "name": paramsDto.Name, - "idcard": paramsDto.IDCard, - "mobile": paramsDto.MobileNo, - } - - apiPath := "/communication/personal/1979" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - out, err := mapYYSYK9R4ToYYSY09CD(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return json.Marshal(out) -} - -// yysyk9r4Resp 数据宝 YYSYK9R4 接口 data 结构 -// state: 1-验证一致 2-验证不一致 3-异常情况 -type yysyk9r4Resp struct { - State string `json:"state"` -} - -// mapYYSYK9R4ToYYSY09CD 数据宝 YYSYK9R4 的 data -> YYSY09CD 最终格式 -// state: 1->1000一致 2->1001不一致 其它->1002查无 -func mapYYSYK9R4ToYYSY09CD(data interface{}) (*YYSY09CDResponse, error) { - var r yysyk9r4Resp - - b, err := json.Marshal(data) - if err != nil { - return nil, err - } - if err := json.Unmarshal(b, &r); err != nil { - return nil, err - } - - // code/msg: 1000一致 1001不一致 1002查无 - var codeStr string - var codeInt int - var msg string - switch strings.TrimSpace(r.State) { - case "1": - codeStr = "1000" - codeInt = 1000 - msg = "一致" - case "2": - codeStr = "1001" - codeInt = 1001 - msg = "不一致" - default: - codeStr = "1002" - codeInt = 1002 - msg = "查无" - } - - return &YYSY09CDResponse{ - Code: codeStr, - Data: YYSY09CDResponseData{ - Msg: msg, - PhoneType: "", - Code: codeInt, - EncryptType: "MD5", - }, - }, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysy0yyv_processor.go b/internal/domains/api/services/processors/yysy/yysy0yyv_processor.go new file mode 100644 index 0000000..f96af0a --- /dev/null +++ b/internal/domains/api/services/processors/yysy/yysy0yyv_processor.go @@ -0,0 +1,24 @@ +package yysy + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessYYSY0YYVRequest YYSY3M8S 运营商二要素 API处理方法 +func ProcessYYSY0YYVRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.YYSY0YYVReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "YYSY3M8S", params) +} diff --git a/internal/domains/api/services/processors/yysy/yysy35ta_processor.go b/internal/domains/api/services/processors/yysy/yysy35ta_processor.go deleted file mode 100644 index db991bf..0000000 --- a/internal/domains/api/services/processors/yysy/yysy35ta_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessYYSY35TARequest YYSY35TA API 运营商归属地数卖处理方法数脉 -func ProcessYYSY35TARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY35TAReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqFormData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/phone/number" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrNotFound) { - // 查无记录情况 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysy3e7f_processor.go b/internal/domains/api/services/processors/yysy/yysy3e7f_processor.go deleted file mode 100644 index 908c7aa..0000000 --- a/internal/domains/api/services/processors/yysy/yysy3e7f_processor.go +++ /dev/null @@ -1,44 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessYYSY3E7FRequest YYSY3E7F API处理方法 - 空号检测 -func ProcessYYSY3E7FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY3E7FReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/mobile_empty/check" // 接口路径,根据数脉文档填写( - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysy3m8s_processor.go b/internal/domains/api/services/processors/yysy/yysy3m8s_processor.go deleted file mode 100644 index 97fe077..0000000 --- a/internal/domains/api/services/processors/yysy/yysy3m8s_processor.go +++ /dev/null @@ -1,45 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessYYSY3M8SRequest YYSY3M8S 运营商二要素 API处理方法 -func ProcessYYSY3M8SRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY3M8SReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - "name": paramsDto.Name, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/mobile_two/check" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysy4b21_processor.go b/internal/domains/api/services/processors/yysy/yysy4b21_processor.go deleted file mode 100644 index a04e573..0000000 --- a/internal/domains/api/services/processors/yysy/yysy4b21_processor.go +++ /dev/null @@ -1,45 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessYYSY4B21Request YYSY4B21 API处理方法 -func ProcessYYSY4B21Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY4B21Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "phone": encryptedMobileNo, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G25BJ02", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysy4b37_processor.go b/internal/domains/api/services/processors/yysy/yysy4b37_processor.go deleted file mode 100644 index c0fddda..0000000 --- a/internal/domains/api/services/processors/yysy/yysy4b37_processor.go +++ /dev/null @@ -1,45 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessYYSY4B37Request YYSY4B37 API处理方法 -func ProcessYYSY4B37Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY4B37Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "phone": encryptedMobileNo, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G02BJ02", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysy4f2e_processor.go b/internal/domains/api/services/processors/yysy/yysy4f2e_processor.go deleted file mode 100644 index 877f63f..0000000 --- a/internal/domains/api/services/processors/yysy/yysy4f2e_processor.go +++ /dev/null @@ -1,62 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessYYSY4F2ERequest YYSY4F2E API处理方法 - 运营商三要素验证(详版) -func ProcessYYSY4F2ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY4F2EReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "name": encryptedName, - "idCard": encryptedIDCard, - "phone": encryptedMobileNo, - "authorized": paramsDto.Authorized, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI002", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysy6d9a_processor.go b/internal/domains/api/services/processors/yysy/yysy6d9a_processor.go deleted file mode 100644 index a2ef6bc..0000000 --- a/internal/domains/api/services/processors/yysy/yysy6d9a_processor.go +++ /dev/null @@ -1,101 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - "strings" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// shumaiMobileTransferResp 数脉 /v4/mobile-transfer/query 返回结构 -type shumaiMobileTransferResp struct { - OrderNo string `json:"order_no"` - Channel string `json:"channel"` // 移动/电信/联通 - Status int `json:"status"` // 0-在网 1-不在网 - Desc string `json:"desc"` // 不在网原因(status=1时有效) -} - -// ProcessYYSY6D9ARequest YYSY6D9A API处理方法 - 全网手机号状态验证A -func ProcessYYSY6D9ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY6D9AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqFormData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/mobile-transfer/query" - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - mapped, err := mapShumaiToYYSY6D9A(respBytes) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return json.Marshal(mapped) -} - -// mapShumaiToYYSY6D9A 将数脉 mobile-transfer 响应映射为最终 state/operators 格式 -// state: 1-正常 2-不在网(空号) 3-无短信能力 4-欠费 5-长时间关机 6-关机 7-通话中 -1-查询失败 -// operators: 1-移动 2-联通 3-电信 -func mapShumaiToYYSY6D9A(dataBytes []byte) (map[string]string, error) { - var r shumaiMobileTransferResp - if err := json.Unmarshal(dataBytes, &r); err != nil { - return map[string]string{"state": "-1", "operators": ""}, nil // 解析失败视为查询失败 - } - - operators := ispNameToCode(strings.TrimSpace(r.Channel)) - state := statusDescToState(r.Status, r.Desc) - - return map[string]string{ - "state": state, - "operators": operators, - }, nil -} - -// statusDescToState status: 0-在网 1-不在网;desc 为不在网原因 -func statusDescToState(status int, desc string) string { - if status == 0 { - return "1" // 正常 - } - // status == 1 不在网,根据 desc 推断 state - d := strings.TrimSpace(desc) - if strings.Contains(d, "销号") || strings.Contains(d, "空号") { - return "2" // 不在网(空号) - } - if strings.Contains(d, "无短信") || strings.Contains(d, "在网不可用") { - return "3" // 无短信能力 - } - if strings.Contains(d, "欠费") { - return "4" // 欠费 - } - if strings.Contains(d, "长时间关机") { - return "5" // 长时间关机 - } - if strings.Contains(d, "关机") { - return "6" // 关机 - } - if strings.Contains(d, "通话中") { - return "7" // 通话中 - } - return "2" // 不在网但未明确原因,默认空号 -} diff --git a/internal/domains/api/services/processors/yysy/yysy6f2b_processor.go b/internal/domains/api/services/processors/yysy/yysy6f2b_processor.go deleted file mode 100644 index 97849b1..0000000 --- a/internal/domains/api/services/processors/yysy/yysy6f2b_processor.go +++ /dev/null @@ -1,49 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessYYSY6F2BRequestYYSY 6F2B API处理方法 - 手机消费区间验证 -func ProcessYYSY6F2BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY6F2BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "phone": encryptedMobileNo, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI041", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysy6f2e_processor.go b/internal/domains/api/services/processors/yysy/yysy6f2e_processor.go deleted file mode 100644 index 78d1556..0000000 --- a/internal/domains/api/services/processors/yysy/yysy6f2e_processor.go +++ /dev/null @@ -1,58 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessYYSY6F2ERequest YYSY6F2E API处理方法 -func ProcessYYSY6F2ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY6F2EReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "name": encryptedName, - "idNo": encryptedIDCard, - "phone": encryptedMobileNo, - "phoneType": paramsDto.MobileType, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G15BJ02", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysy7d3e_processor.go b/internal/domains/api/services/processors/yysy/yysy7d3e_processor.go deleted file mode 100644 index 5851337..0000000 --- a/internal/domains/api/services/processors/yysy/yysy7d3e_processor.go +++ /dev/null @@ -1,113 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - "strings" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// shumaiMobileTransferResp 数脉 /v4/mobile-transfer/query 携号转网返回结构 -type shumaiMobileTransfer7d3eResp struct { - OrderNo string `json:"order_no"` - Mobile string `json:"mobile"` - Area *string `json:"area"` - IspType string `json:"ispType"` // 转网前运营商 - NewIspType string `json:"newIspType"` // 转网后运营商 -} - -// yysy7d3eResp 携号转网查询对外响应结构 -type yysy7d3eResp struct { - BatchNo string `json:"batchNo"` - QueryResult []yysy7d3eQueryItem `json:"queryResult"` -} - -type yysy7d3eQueryItem struct { - Mobile string `json:"mobile"` - Result string `json:"result"` // 0:否 1:是 - After string `json:"after"` // 转网后:-1未知 1移动 2联通 3电信 4广电 - Before string `json:"before"` // 转网前:同上 -} - -// ProcessYYSY7D3ERequest YYSY7D3E API处理方法 - 携号转网查询 -func ProcessYYSY7D3ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY7D3EReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqFormData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/mobile-transfer/query" - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - mapped, err := mapShumaiToYYSY7D3E(respBytes) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return json.Marshal(mapped) -} - -// mapShumaiToYYSY7D3E 将数脉携号转网响应映射为 batchNo + queryResult 格式 -func mapShumaiToYYSY7D3E(dataBytes []byte) (*yysy7d3eResp, error) { - var r shumaiMobileTransfer7d3eResp - if err := json.Unmarshal(dataBytes, &r); err != nil { - return nil, err - } - - before := ispNameToCodeTransfer(strings.TrimSpace(r.IspType)) - after := ispNameToCodeTransfer(strings.TrimSpace(r.NewIspType)) - result := "0" - if r.IspType != "" && r.NewIspType != "" && strings.TrimSpace(r.IspType) != strings.TrimSpace(r.NewIspType) { - result = "1" // 转网前与转网后不同即为携号转网 - } - - out := &yysy7d3eResp{ - BatchNo: r.OrderNo, - QueryResult: []yysy7d3eQueryItem{ - { - Mobile: r.Mobile, - Result: result, - After: after, - Before: before, - }, - }, - } - return out, nil -} - -// ispNameToCodeTransfer 运营商名称转编码:-1未知 1移动 2联通 3电信 4广电 -func ispNameToCodeTransfer(name string) string { - switch name { - case "移动": - return "1" - case "联通": - return "2" - case "电信": - return "3" - case "广电": - return "4" - default: - return "-1" - } -} diff --git a/internal/domains/api/services/processors/yysy/yysy8b1c_processor.go b/internal/domains/api/services/processors/yysy/yysy8b1c_processor.go deleted file mode 100644 index ce8b0d9..0000000 --- a/internal/domains/api/services/processors/yysy/yysy8b1c_processor.go +++ /dev/null @@ -1,100 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessYYSY8B1CRequest YYSY8B1C API处理方法 - 手机在网时长 -func ProcessYYSY8B1CRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY8B1CReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v2/mobile_online/check" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - var shumaiResp struct { - OrderNo string `json:"order_no"` - Channel string `json:"channel"` // cmcc/cucc/ctcc/gdcc - Time string `json:"time"` // [0,3),[3,6),[6,12),[12,24),[24,-1) - } - if err := json.Unmarshal(respBytes, &shumaiResp); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // 映射 channel -> operators - operators := channelToOperators(shumaiResp.Channel) - // 映射 time 区间 -> inTime - inTime := timeIntervalToInTime(shumaiResp.Time) - - out := map[string]string{ - "inTime": inTime, - "operators": operators, - } - return json.Marshal(out) -} - -// channelToOperators 运营商编码转名称:cmcc-移动 cucc-联通 ctcc-电信 gdcc-广电 -func channelToOperators(channel string) string { - switch channel { - case "cmcc": - return "移动" - case "cucc": - return "联通" - case "ctcc": - return "电信" - case "gdcc": - return "广电" - default: - return "" - } -} - -// timeIntervalToInTime 在网时间区间转 inTime 值 -// [0,3)->0, [3,6)->3, [6,12)->6, [12,24)->12, [24,-1)->24 -// 空或异常->99, 查无记录->-1(此处按空/未知处理为99) -func timeIntervalToInTime(timeInterval string) string { - switch timeInterval { - case "[0,3)": - return "0" - case "[3,6)": - return "3" - case "[6,12)": - return "6" - case "[12,24)": - return "12" - case "[24,-1)": - return "24" - case "": - return "-1" - default: - return "99" - } -} diff --git a/internal/domains/api/services/processors/yysy/yysy8c2d_processor.go b/internal/domains/api/services/processors/yysy/yysy8c2d_processor.go deleted file mode 100644 index 15a988f..0000000 --- a/internal/domains/api/services/processors/yysy/yysy8c2d_processor.go +++ /dev/null @@ -1,47 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessYYSY8C2DRequest YYSY8C2D API处理方法 - 运营商三要素查询 -func ProcessYYSY8C2DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY8C2DReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "phoneNumber": paramsDto.MobileNo, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1100244702166183936" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysy8f3a_processor.go b/internal/domains/api/services/processors/yysy/yysy8f3a_processor.go deleted file mode 100644 index 4ab33b5..0000000 --- a/internal/domains/api/services/processors/yysy/yysy8f3a_processor.go +++ /dev/null @@ -1,51 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/xingwei" -) - -// ProcessYYSY8F3ARequest YYSY8F3A API处理方法 - 行为数据查询 -func ProcessYYSY8F3ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY8F3AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 构建请求数据,直接传递姓名、身份证、手机号 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "phoneNumber": paramsDto.MobileNo, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1100244697766359040" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) - if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - // 查空情况,返回特定的查空错误 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysy9a1b_processor.go b/internal/domains/api/services/processors/yysy/yysy9a1b_processor.go deleted file mode 100644 index b9454a2..0000000 --- a/internal/domains/api/services/processors/yysy/yysy9a1b_processor.go +++ /dev/null @@ -1,158 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - "strconv" - "strings" - "time" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// shumaiMobileThreeResp 数脉 /v4/mobile_three/check 返回的 data 结构 -// result: 0-一致 1-不一致 2-无记录;channel: cmcc/cucc/ctcc/gdcc -type shumaiMobileThreeResp struct { - OrderNo string `json:"order_no"` - Result string `json:"result"` - Desc string `json:"desc"` - Channel string `json:"channel"` - Sex string `json:"sex"` - Birthday string `json:"birthday"` - Address string `json:"address"` -} - -// yysy9a1bOut 最终返回格式 -// result: 01一致 02不一致 03不确定 04失败/虚拟号;type: 1移动 2联通 3电信 4广电 -type yysy9a1bOut struct { - OrderNo string `json:"orderNo"` - HandleTime string `json:"handleTime"` - Type string `json:"type"` // 1:移动 2:联通 3:电信 4:广电 - Result string `json:"result"` - Gender string `json:"gender"` - Age string `json:"age"` - Remark string `json:"remark"` -} - -// ProcessYYSY9A1BRequest YYSY9A1B API处理方法 - 运营商三要素查询 -func ProcessYYSY9A1BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY9A1BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "idcard": paramsDto.IDCard, - "name": paramsDto.Name, - "mobile": paramsDto.MobileNo, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/mobile_three/check" - - // 先尝试使用政务接口(app_id2 和 app_secret2) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true) - if err != nil { - // 使用实时接口(app_id 和 app_secret)重试 - respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false) - // 如果重试后仍然失败,返回错误 - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - } - - // 将数脉 data 映射为最终返回格式 - out, err := mapShumaiMobileThreeToYYSY9A1B(respBytes) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return json.Marshal(out) -} - -// mapShumaiMobileThreeToYYSY9A1B 数脉 mobile_three/check 的 data -> 最终格式 -// result: 0->01 1->02 2->04 其它->04;remark: 认证一致/认证不一致/无记录/虚拟号;gender: 男->1 女->2;type: cmcc->1 cucc->2 ctcc->3 gdcc->4 -func mapShumaiMobileThreeToYYSY9A1B(dataBytes []byte) (*yysy9a1bOut, error) { - var r shumaiMobileThreeResp - if err := json.Unmarshal(dataBytes, &r); err != nil { - return nil, err - } - - // result: 01一致 02不一致 03不确定 04失败/虚拟号;原 2-无记录 及 其它 均映射为 04 - // remark: 认证一致;认证不一致;无记录;虚拟号 - var res, remark string - switch strings.TrimSpace(r.Result) { - case "0": - res = "01" - remark = "认证一致" - case "1": - res = "02" - remark = "认证不一致" - case "2": - res = "04" - remark = "无记录" - default: - res = "04" - remark = "虚拟号" - } - - // type: 运营商 channel -> 1移动 2联通 3电信 4广电(cmcc/cucc/ctcc/gdcc),未知为空 - ch := strings.ToLower(strings.TrimSpace(r.Channel)) - var chType string - switch ch { - case "cmcc": - chType = "1" - case "cucc": - chType = "2" - case "ctcc": - chType = "3" - case "gdcc": - chType = "4" - } - - // gender: 男->1 女->2 - sex := strings.TrimSpace(r.Sex) - var gender string - if sex == "男" { - gender = "1" - } else if sex == "女" { - gender = "2" - } - - return &yysy9a1bOut{ - OrderNo: r.OrderNo, - HandleTime: time.Now().Format("2006-01-02 15:04:05"), - Type: chType, - Result: res, - Gender: gender, - Age: ageFromBirthday(r.Birthday), - Remark: remark, - }, nil -} - -func ageFromBirthday(s string) string { - s = strings.TrimSpace(s) - if len(s) < 4 { - return "" - } - y, err := strconv.Atoi(s[0:4]) - if err != nil || y <= 0 { - return "" - } - age := time.Now().Year() - y - if age < 0 { - age = 0 - } - return strconv.Itoa(age) -} diff --git a/internal/domains/api/services/processors/yysy/yysy9e4a_processor.go b/internal/domains/api/services/processors/yysy/yysy9e4a_processor.go deleted file mode 100644 index 3ecf265..0000000 --- a/internal/domains/api/services/processors/yysy/yysy9e4a_processor.go +++ /dev/null @@ -1,57 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/zhicha" -) - -// ProcessYYSY9E4ARequest YYSY9E4A API处理方法 - 手机号归属地查询 -func ProcessYYSY9E4ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY9E4AReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "phone": encryptedMobileNo, - } - - respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI026", reqData) - if err != nil { - if errors.Is(err, zhicha.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // 兼容上游有时返回 JSON 字符串的情况:如果是字符串则尝试再反序列化一次 - if str, ok := respData.(string); ok && str != "" { - var parsed interface{} - if err := json.Unmarshal([]byte(str), &parsed); err == nil { - respData = parsed - } - } - - // 将响应数据转换为JSON字节 - respBytes, err := json.Marshal(respData) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysy9f1b_processor.go b/internal/domains/api/services/processors/yysy/yysy9f1b_processor.go deleted file mode 100644 index 421e14d..0000000 --- a/internal/domains/api/services/processors/yysy/yysy9f1b_processor.go +++ /dev/null @@ -1,114 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessYYSY9F1BYequest YYSY9F1B API处理方法 - 手机二要素验证 - -func ProcessYYSY9F1BYequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSY9F1BReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - "name": paramsDto.Name, - } - - // 3m8s 运营商二要素:order_no, fee, result(0-一致 1-不一致)。失败则直接返回,不再调携号转网接口。 - apiPath := "/v4/mobile_two/check" - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - // s9w1 手机携号转网(仅在上方二要素成功后再调) - apiPath2 := "/v4/mobile-transfer/query" - respBytes2, err := deps.ShumaiService.CallAPIForm(ctx, apiPath2, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - return nil, errors.Join(processors.ErrSystem, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - var twoFactorResp struct { - OrderNo string `json:"order_no"` - Fee int `json:"fee"` - Result int `json:"result"` // 0-一致 1-不一致 - } - if err := json.Unmarshal(respBytes, &twoFactorResp); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - var transferResp struct { - OrderNo string `json:"order_no"` - Mobile string `json:"mobile"` - Area *string `json:"area"` - IspType string `json:"ispType"` // 转网前运营商 - NewIspType string `json:"newIspType"` // 转网后运营商 - } - if err := json.Unmarshal(respBytes2, &transferResp); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - // state: 1-一致 2-不一致 3-异常 - state := "3" - switch twoFactorResp.Result { - case 0: - state = "1" - case 1: - state = "2" - } - - operator := ispNameToCode(transferResp.IspType) - operatorReal := ispNameToCode(transferResp.NewIspType) - - // is_xhzw: 0-否 1-是(转网前与转网后运营商不同即为携号转网) - isXhzw := "0" - if transferResp.IspType != "" && transferResp.NewIspType != "" && transferResp.IspType != transferResp.NewIspType { - isXhzw = "1" - } - - out := map[string]string{ - "operator_real": operatorReal, - "state": state, - "is_xhzw": isXhzw, - "operator": operator, - } - return json.Marshal(out) -} - -// ispNameToCode 运营商名称转编码:1-移动 2-联通 3-电信 -func ispNameToCode(name string) string { - switch name { - case "移动": - return "1" - case "联通": - return "2" - case "电信": - return "3" - default: - return "" - } -} diff --git a/internal/domains/api/services/processors/yysy/yysybe08_processor.go b/internal/domains/api/services/processors/yysy/yysybe08_processor.go deleted file mode 100644 index 920883e..0000000 --- a/internal/domains/api/services/processors/yysy/yysybe08_processor.go +++ /dev/null @@ -1,134 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - "strconv" - "strings" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" -) - -// ProcessYYSYBE08Request YYSYBE08 API处理方法 - 使用数脉二要素验证 -func ProcessYYSYBE08Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSYBE08Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqFormData := map[string]interface{}{ - "idcard": paramsDto.IDCard, - "name": paramsDto.Name, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/id_card/check" - - // 先尝试使用政务接口(app_id2 和 app_secret2) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true) - if err != nil { - // 使用实时接口(app_id 和 app_secret)重试 - respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false) - // 重试仍失败:阿里云身份证二要素兜底,并直接返回统一映射响应 - if err != nil { - return callAliyunIDCardCheckRaw(ctx, deps, paramsDto.Name, paramsDto.IDCard) - } - } - - // 解析数脉 /v4/id_card/check 的 data 内容(CallAPIForm 返回的即 data 对象) - // 数卖响应: result 0-一致 1-不一致 2-无记录(预留); desc 如 "一致"/"不一致" - var shumaiData struct { - Result interface{} `json:"result"` - OrderNo string `json:"order_no"` - Desc string `json:"desc"` - Sex string `json:"sex"` - Birthday string `json:"birthday"` - Address string `json:"address"` - } - - if err := json.Unmarshal(respBytes, &shumaiData); err != nil { - // 解析失败,返回系统错误 - 转换为目标格式 - errorResponse := map[string]interface{}{ - "ctidRequest": map[string]interface{}{ - "ctidAuth": map[string]interface{}{ - "idCard": paramsDto.IDCard, - "name": paramsDto.Name, - "resultCode": "500", - "resultMsg": "响应解析失败", - "verifyResult": "", - }, - }, - } - return json.Marshal(errorResponse) - } - - // 按数卖 result 验证结果处理: 0-一致 1-不一致 2-无记录(预留) - // resultCode: 0XXX=一致, 5XXX=不一致/无记录 - resultCode, verifyResult, resultMsg := mapIDCardCheckResult(shumaiData.Result, shumaiData.Desc) - - // 构建目标格式的响应 - response := map[string]interface{}{ - "ctidRequest": map[string]interface{}{ - "ctidAuth": map[string]interface{}{ - "idCard": paramsDto.IDCard, - "name": paramsDto.Name, - "resultCode": resultCode, - "resultMsg": resultMsg, - "verifyResult": verifyResult, - }, - }, - } - - return json.Marshal(response) -} - -func mapIDCardCheckResult(rawResult interface{}, desc string) (resultCode, verifyResult, resultMsg string) { - if isResultZero(rawResult) { - resultCode = "0XXX" - verifyResult = "一致" - resultMsg = desc - if resultMsg == "" { - resultMsg = "成功" - } - return - } - - resultCode = "5XXX" - verifyResult = "不一致" - resultMsg = desc - if resultMsg == "" { - resultMsg = "不一致" - } - return -} - -func isResultZero(v interface{}) bool { - switch r := v.(type) { - case float64: - return r == 0 - case int: - return r == 0 - case int32: - return r == 0 - case int64: - return r == 0 - case json.Number: - n, err := r.Int64() - return err == nil && n == 0 - case string: - s := strings.TrimSpace(r) - if s == "" { - return false - } - n, err := strconv.ParseFloat(s, 64) - return err == nil && n == 0 - default: - return false - } -} diff --git a/internal/domains/api/services/processors/yysy/yysybe08test_processor.go b/internal/domains/api/services/processors/yysy/yysybe08test_processor.go deleted file mode 100644 index c18d2e0..0000000 --- a/internal/domains/api/services/processors/yysy/yysybe08test_processor.go +++ /dev/null @@ -1,82 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/alicloud" -) - -// ProcessYYSYBE08testRequest 与 YYSYBE08 相同入参,底层使用阿里云市场身份证二要素校验;响应映射为 ctidRequest.ctidAuth 格式 -func ProcessYYSYBE08testRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSYBE08Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - return callAliyunIDCardCheckRaw(ctx, deps, paramsDto.Name, paramsDto.IDCard) -} - -// callAliyunIDCardCheckRaw POST api-mall/api/id_card/check(form: name、idcard),并映射为 ctidRequest.ctidAuth 响应 -func callAliyunIDCardCheckRaw(ctx context.Context, deps *processors.ProcessorDependencies, name, idCard string) ([]byte, error) { - _ = ctx - reqData := map[string]interface{}{ - "name": name, - "idcard": idCard, - } - respBytes, err := deps.AlicloudService.CallAPI("api-mall/api/id_card/check", reqData) - if err != nil { - if errors.Is(err, alicloud.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - var aliyunData struct { - Msg string `json:"msg"` - Success bool `json:"success"` - Code int `json:"code"` - Data struct { - Birthday string `json:"birthday"` - Result interface{} `json:"result"` - Address string `json:"address"` - OrderNo string `json:"orderNo"` - Sex string `json:"sex"` - Desc string `json:"desc"` - } `json:"data"` - Result interface{} `json:"result"` - Desc string `json:"desc"` - } - if err := json.Unmarshal(respBytes, &aliyunData); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - rawResult := aliyunData.Result - rawDesc := aliyunData.Desc - // 优先使用 code=200 时 data 内的字段;兼容旧格式直接返回 result/desc - if aliyunData.Code == 200 { - rawResult = aliyunData.Data.Result - rawDesc = aliyunData.Data.Desc - } - - resultCode, verifyResult, resultMsg := mapIDCardCheckResult(rawResult, rawDesc) - response := map[string]interface{}{ - "ctidRequest": map[string]interface{}{ - "ctidAuth": map[string]interface{}{ - "idCard": idCard, - "name": name, - "resultCode": resultCode, - "resultMsg": resultMsg, - "verifyResult": verifyResult, - }, - }, - } - return json.Marshal(response) -} diff --git a/internal/domains/api/services/processors/yysy/yysyc4r9_processor.go b/internal/domains/api/services/processors/yysy/yysyc4r9_processor.go deleted file mode 100644 index d01f985..0000000 --- a/internal/domains/api/services/processors/yysy/yysyc4r9_processor.go +++ /dev/null @@ -1,46 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessYYSYC4R9Request YYSYC4R9 运营商三要素详版API处理方法 -func ProcessYYSYC4R9Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSYC4R9Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "idcard": paramsDto.IDCard, - "name": paramsDto.Name, - "mobile": paramsDto.MobileNo, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v2/mobile_three/check/detail" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysyd50f_processor.go b/internal/domains/api/services/processors/yysy/yysyd50f_processor.go deleted file mode 100644 index 30c84bf..0000000 --- a/internal/domains/api/services/processors/yysy/yysyd50f_processor.go +++ /dev/null @@ -1,51 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/westdex" -) - -// ProcessYYSYD50FRequest YYSYD50F API处理方法 -func ProcessYYSYD50FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSYD50FReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "phone": encryptedMobileNo, - "idNo": encryptedIDCard, - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G18BJ02", reqData) - if err != nil { - if errors.Is(err, westdex.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } else { - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysye7v5_processor.go b/internal/domains/api/services/processors/yysy/yysye7v5_processor.go deleted file mode 100644 index b148018..0000000 --- a/internal/domains/api/services/processors/yysy/yysye7v5_processor.go +++ /dev/null @@ -1,44 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessYYSYE7V5Request YYSYE7V5 手机在网状态查询API处理方法 -func ProcessYYSYE7V5Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSYE7V5Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v1/mobile_status/check" // 接口路径,根据数脉文档填写( - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysyf2t7_processor.go b/internal/domains/api/services/processors/yysy/yysyf2t7_processor.go deleted file mode 100644 index 3723c08..0000000 --- a/internal/domains/api/services/processors/yysy/yysyf2t7_processor.go +++ /dev/null @@ -1,49 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - "strings" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessYYSYF2T7Request YYSYF2T7 手机二次放号检测查询API处理方法 -func ProcessYYSYF2T7Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSYF2T7Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - // 从入参 date_range(YYYYMMDD-YYYYMMDD)提取右区间作为 date - parts := strings.SplitN(paramsDto.DateRange, "-", 2) - dateEnd := strings.TrimSpace(parts[1]) // 校验已保证格式正确,取结束日期 - reqFormData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - "date": dateEnd, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/mobile_twice/check" // 接口路径,根据数脉文档填写( - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysyf7db_processor.go b/internal/domains/api/services/processors/yysy/yysyf7db_processor.go deleted file mode 100644 index 9ae56e7..0000000 --- a/internal/domains/api/services/processors/yysy/yysyf7db_processor.go +++ /dev/null @@ -1,133 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - "strings" - "time" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// westdexG19BJ02Resp 上游 G19BJ02 实际返回结构:order_no->guid, result->code, channel->phoneType, desc->msg -type westdexG19BJ02Resp struct { - Result int `json:"result"` // 0-是二次卡 1-不是二次卡 2-数据库中无信息(预留) - OrderNo string `json:"orderNo"` - Channel string `json:"channel"` // cmcc/cucc/ctcc - Desc string `json:"desc"` -} - -// YYSYF7DBResponse 手机二次卡查询成功响应(最终返回结构) -type YYSYF7DBResponse struct { - Code string `json:"code"` - Data YYSYF7DBResponseData `json:"data"` -} - -// YYSYF7DBResponseData 手机二次卡 data 结构 -type YYSYF7DBResponseData struct { - Code int `json:"code"` - EncryptType string `json:"encryptType"` - Guid string `json:"guid"` // 来自 order_no - Msg string `json:"msg"` // 来自 desc,按 result:0-是二次卡 1-不是二次卡 - PhoneType string `json:"phoneType"` // 来自 channel:cmcc->CMCC 等 -} - -// ProcessYYSYF7DBRequest YYSYF7DB API处理方法 -func ProcessYYSYF7DBRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSYF7DBReq - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - // 组装日期:开始日期 + 当前日期(YYYYMMDD-YYYYMMDD) - today := time.Now().Format("20060102") - // dateRange := startDateYyyymmdd + "-" + today - - reqFormData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - "date": today, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/mobile_twice/check" // 接口路径,根据数脉文档填写( - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - mapped, err := mapWestdexG19BJ02ToYYSYF7DB(respBytes) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return json.Marshal(mapped) -} - -// mapWestdexG19BJ02ToYYSYF7DB 将上游 result/orderNo/channel/desc 映射为最终 code/data 结构 -// result: 0->1025(是二次卡) 1->1026(不是二次卡) 2->1027(数据库中无信息);channel: cmcc->CMCC cucc->CUCC ctcc->CTCC -func mapWestdexG19BJ02ToYYSYF7DB(dataBytes []byte) (*YYSYF7DBResponse, error) { - var r westdexG19BJ02Resp - if err := json.Unmarshal(dataBytes, &r); err != nil { - return nil, err - } - - var codeStr string - var codeInt int - var msg string - switch r.Result { - case 0: - codeStr = "1025" - codeInt = 1025 - msg = "二次卡" - case 1: - codeStr = "1026" - codeInt = 1026 - msg = "不是二次卡" - default: - codeStr = "1027" - codeInt = 1027 - msg = "不是二次卡" - } - if r.Desc != "" { - msg = strings.TrimSpace(r.Desc) - } - - ch := strings.ToLower(strings.TrimSpace(r.Channel)) - var phoneType string - switch ch { - case "cmcc": - phoneType = "CMCC" - case "cucc": - phoneType = "CUCC" - case "ctcc": - phoneType = "CTCC" - default: - phoneType = "UNKNOWN" - } - - return &YYSYF7DBResponse{ - Code: codeStr, - Data: YYSYF7DBResponseData{ - Code: codeInt, - EncryptType: "MD5", - Guid: r.OrderNo, - Msg: msg, - PhoneType: phoneType, - }, - }, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysyglsf_processor.go b/internal/domains/api/services/processors/yysy/yysyglsf_processor.go new file mode 100644 index 0000000..6fb3cfe --- /dev/null +++ b/internal/domains/api/services/processors/yysy/yysyglsf_processor.go @@ -0,0 +1,14 @@ +package yysy + +import ( + "context" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessYYSYGLSFRequest YYSYK9R4 全网手机三要素验证(天远中转) +func ProcessYYSYGLSFRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.YYSYGLSFReq + return processors.ValidateParamsAndCallTianyuan(ctx, deps, "YYSYK9R4", params, ¶msDto) +} diff --git a/internal/domains/api/services/processors/yysy/yysyh6d2_processor.go b/internal/domains/api/services/processors/yysy/yysyh6d2_processor.go deleted file mode 100644 index 09e31ee..0000000 --- a/internal/domains/api/services/processors/yysy/yysyh6d2_processor.go +++ /dev/null @@ -1,52 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessYYSYH6D2Request YYSYH6D2 运营商三要素简版API处理方法 -func ProcessYYSYH6D2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSYH6D2Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "idcard": paramsDto.IDCard, - "name": paramsDto.Name, - "mobile": paramsDto.MobileNo, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/mobile_three/check" // 接口路径,根据数脉文档填写(如 v4/xxx) - - // 先尝试使用政务接口(app_id2 和 app_secret2) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true) - if err != nil { - // 使用实时接口(app_id 和 app_secret)重试 - respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false) - // 如果重试后仍然失败,返回错误 - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysyh6f3_processor.go b/internal/domains/api/services/processors/yysy/yysyh6f3_processor.go deleted file mode 100644 index 98c4536..0000000 --- a/internal/domains/api/services/processors/yysy/yysyh6f3_processor.go +++ /dev/null @@ -1,48 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessYYSYH6F3Request YYSYH6F3 运营商三要素即时版API处理方法 -func ProcessYYSYH6F3Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSYH6F3Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "idcard": paramsDto.IDCard, - "name": paramsDto.Name, - "mobile": paramsDto.MobileNo, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - // 走政务接口使用这个 - - apiPath := "/v4/mobile_three/check" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysyjxzf_processor.go b/internal/domains/api/services/processors/yysy/yysyjxzf_processor.go new file mode 100644 index 0000000..f4066b3 --- /dev/null +++ b/internal/domains/api/services/processors/yysy/yysyjxzf_processor.go @@ -0,0 +1,24 @@ +package yysy + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessYYSYJXZFRequest YYSYK8R3 手机空号检测查询API处理方法 +func ProcessYYSYJXZFRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.YYSYJXZFReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "YYSYK8R3", params) +} diff --git a/internal/domains/api/services/processors/yysy/yysyk8r3_processor.go b/internal/domains/api/services/processors/yysy/yysyk8r3_processor.go deleted file mode 100644 index de7c1e3..0000000 --- a/internal/domains/api/services/processors/yysy/yysyk8r3_processor.go +++ /dev/null @@ -1,44 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessYYSYK8R3Request YYSYK8R3 手机空号检测查询API处理方法 -func ProcessYYSYK8R3Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSYK8R3Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/mobile_empty/check" // 接口路径,根据数脉文档填写( - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysyk9r4_processor.go b/internal/domains/api/services/processors/yysy/yysyk9r4_processor.go deleted file mode 100644 index 851e500..0000000 --- a/internal/domains/api/services/processors/yysy/yysyk9r4_processor.go +++ /dev/null @@ -1,49 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shujubao" -) - -// ProcessYYSYK9R4Request JRZQACAB 全网手机三要素验证1979周更新版 API 处理方法(使用数据宝服务示例) -func ProcessYYSYK9R4Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSYK9R4Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - - reqParams := map[string]interface{}{ - "key": "c115708d915451da8f34a23e144dda6b", - "name": paramsDto.Name, - "idcard": paramsDto.IDCard, - "mobile": paramsDto.MobileNo, - } - - // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197 - apiPath := "/communication/personal/1979" - data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams) - if err != nil { - if errors.Is(err, shujubao.ErrDatasource) { - return nil, errors.Join(processors.ErrDatasource, err) - } - if errors.Is(err, shujubao.ErrQueryEmpty) { - return nil, errors.Join(processors.ErrNotFound, err) - } - return nil, errors.Join(processors.ErrSystem, err) - } - - respBytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysyktqo_processor.go b/internal/domains/api/services/processors/yysy/yysyktqo_processor.go new file mode 100644 index 0000000..8b1a301 --- /dev/null +++ b/internal/domains/api/services/processors/yysy/yysyktqo_processor.go @@ -0,0 +1,24 @@ +package yysy + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessYYSYKTQORequest YYSYE7V5 手机在网状态查询API处理方法 +func ProcessYYSYKTQORequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.YYSYKTQOReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "YYSYE7V5", params) +} diff --git a/internal/domains/api/services/processors/yysy/yysyn8di_processor.go b/internal/domains/api/services/processors/yysy/yysyn8di_processor.go new file mode 100644 index 0000000..3e234f3 --- /dev/null +++ b/internal/domains/api/services/processors/yysy/yysyn8di_processor.go @@ -0,0 +1,24 @@ +package yysy + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessYYSYN8DIRequest YYSYH6D2 运营商三要素简版API处理方法 +func ProcessYYSYN8DIRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.YYSYN8DIReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "YYSYH6D2", params) +} diff --git a/internal/domains/api/services/processors/yysy/yysyp0t4_processor.go b/internal/domains/api/services/processors/yysy/yysyp0t4_processor.go deleted file mode 100644 index e7e554a..0000000 --- a/internal/domains/api/services/processors/yysy/yysyp0t4_processor.go +++ /dev/null @@ -1,44 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessYYSYP0T4Request YYSYP0T4 在网时长API处理方法 -func ProcessYYSYP0T4Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSYP0T4Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v2/mobile_online/check" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysyp7pl_processor.go b/internal/domains/api/services/processors/yysy/yysyp7pl_processor.go new file mode 100644 index 0000000..bfad358 --- /dev/null +++ b/internal/domains/api/services/processors/yysy/yysyp7pl_processor.go @@ -0,0 +1,24 @@ +package yysy + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessYYSYP7PLRequest YYSYF2T7 手机二次放号检测查询API处理方法 +func ProcessYYSYP7PLRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.YYSYP7PLReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "YYSYF2T7", params) +} diff --git a/internal/domains/api/services/processors/yysy/yysys66t_processor.go b/internal/domains/api/services/processors/yysy/yysys66t_processor.go new file mode 100644 index 0000000..572728c --- /dev/null +++ b/internal/domains/api/services/processors/yysy/yysys66t_processor.go @@ -0,0 +1,24 @@ +package yysy + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessYYSYS66TRequest YYSYC4R9 运营商三要素详版API处理方法 +func ProcessYYSYS66TRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.YYSYS66TReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "YYSYC4R9", params) +} diff --git a/internal/domains/api/services/processors/yysy/yysys9w1_processor.go b/internal/domains/api/services/processors/yysy/yysys9w1_processor.go deleted file mode 100644 index 5012fa0..0000000 --- a/internal/domains/api/services/processors/yysy/yysys9w1_processor.go +++ /dev/null @@ -1,44 +0,0 @@ -package yysy - -import ( - "context" - "encoding/json" - "errors" - - "hyapi-server/internal/domains/api/dto" - "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/infrastructure/external/shumai" -) - -// ProcessYYSYS9W1Request YYSYS9W1 手机携号转网查询API处理方法 -func ProcessYYSYS9W1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.YYSYS9W1Req - if err := json.Unmarshal(params, ¶msDto); err != nil { - return nil, errors.Join(processors.ErrSystem, err) - } - - if err := deps.Validator.ValidateStruct(paramsDto); err != nil { - return nil, errors.Join(processors.ErrInvalidParam, err) - } - reqFormData := map[string]interface{}{ - "mobile": paramsDto.MobileNo, - } - - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - apiPath := "/v4/mobile-transfer/query" // 接口路径,根据数脉文档填写( - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) - if err != nil { - if errors.Is(err, shumai.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, shumai.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } - } - - return respBytes, nil -} diff --git a/internal/domains/api/services/processors/yysy/yysyuo7e_processor.go b/internal/domains/api/services/processors/yysy/yysyuo7e_processor.go new file mode 100644 index 0000000..e2b97db --- /dev/null +++ b/internal/domains/api/services/processors/yysy/yysyuo7e_processor.go @@ -0,0 +1,24 @@ +package yysy + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessYYSYUO7ERequest YYSYP0T4 在网时长API处理方法 +func ProcessYYSYUO7ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.YYSYUO7EReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "YYSYP0T4", params) +} diff --git a/internal/domains/api/services/processors/yysy/yysyxaes_processor.go b/internal/domains/api/services/processors/yysy/yysyxaes_processor.go new file mode 100644 index 0000000..a8c9bfb --- /dev/null +++ b/internal/domains/api/services/processors/yysy/yysyxaes_processor.go @@ -0,0 +1,24 @@ +package yysy + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessYYSYXAESRequest YYSYS9W1 手机携号转网查询API处理方法 +func ProcessYYSYXAESRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.YYSYXAESReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "YYSYS9W1", params) +} diff --git a/internal/domains/api/services/processors/yysy/yysyxhho_processor.go b/internal/domains/api/services/processors/yysy/yysyxhho_processor.go new file mode 100644 index 0000000..849a354 --- /dev/null +++ b/internal/domains/api/services/processors/yysy/yysyxhho_processor.go @@ -0,0 +1,24 @@ +package yysy + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessYYSYXHHORequest YYSYH6F3 运营商三要素即时版API处理方法 +func ProcessYYSYXHHORequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.YYSYXHHOReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + return processors.CallTianyuanByProduct(ctx, deps, "YYSYH6F3", params) +} diff --git a/internal/domains/certification/services/enterprise_info_submit_record_service.go b/internal/domains/certification/services/enterprise_info_submit_record_service.go index 45f2fe4..2beb0bb 100644 --- a/internal/domains/certification/services/enterprise_info_submit_record_service.go +++ b/internal/domains/certification/services/enterprise_info_submit_record_service.go @@ -2,13 +2,12 @@ package services import ( "context" - "encoding/json" "errors" "fmt" + "strings" + "hyapi-server/internal/config" - "hyapi-server/internal/domains/api/dto" "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/domains/api/services/processors/qygl" "hyapi-server/internal/domains/certification/entities" "hyapi-server/internal/domains/certification/entities/value_objects" "hyapi-server/internal/domains/certification/repositories" @@ -71,85 +70,72 @@ func (s *EnterpriseInfoSubmitRecordService) Save(ctx context.Context, enterprise return s.repositories.Create(ctx, enterpriseInfoSubmitRecord) } -// ValidateWithWestdex 调用QYGL5CMP处理器验证企业信息 +// ValidateWithWestdex 通过天眼查企业基本信息核对企业名称、统一社会信用代码与法人姓名(原 QYGL23T7 产品已下线)。 func (s *EnterpriseInfoSubmitRecordService) ValidateWithWestdex(ctx context.Context, info *value_objects.EnterpriseInfo) error { if info == nil { return errors.New("企业信息不能为空") } - // 先做本地校验 if err := info.Validate(); err != nil { return err } - - // 开发环境下跳过外部验证 - // if s.appConfig.IsDevelopment() { - // s.logger.Info("开发环境:跳过企业信息外部验证", - // zap.String("company_name", info.CompanyName), - // zap.String("legal_person", info.LegalPersonName)) - // return nil - // } - - // 构建QYGL5CMP请求参数 - reqDto := dto.QYGL5CMPReq{ - EntName: info.CompanyName, - LegalPerson: info.LegalPersonName, - EntCode: info.UnifiedSocialCode, - IDCard: info.LegalPersonID, - MobileNo: info.LegalPersonPhone, + if s.tianYanChaService == nil { + return errors.New("企业信息验证服务未配置") } - // 序列化请求参数 - paramsBytes, err := json.Marshal(reqDto) + resp, err := s.tianYanChaService.CallAPI(ctx, "baseinfo", map[string]string{ + "keyword": info.UnifiedSocialCode, + }) if err != nil { - return fmt.Errorf("序列化请求参数失败: %w", err) - } - - // 创建处理器依赖 - deps := &processors.ProcessorDependencies{ - WestDexService: s.westdexService, - TianYanChaService: s.tianYanChaService, - AlicloudService: s.alicloudService, - YushanService: s.yushanService, - Validator: s.validator, - } - - // 调用QYGL23T7处理器进行验证 - responseBytes, err := qygl.ProcessQYGL23T7Request(ctx, paramsBytes, deps) - if err != nil { - // 检查是否是数据源错误企业信息不一致 - if errors.Is(err, processors.ErrDatasource) { - return fmt.Errorf("数据源异常: %w", err) + if errors.Is(err, tianyancha.ErrNotFound) { + return fmt.Errorf("企业信息不一致") + } + if errors.Is(err, tianyancha.ErrDatasource) { + return fmt.Errorf("数据源异常: %w", errors.Join(processors.ErrDatasource, err)) } return fmt.Errorf("企业信息验证失败: %w", err) } - - // 解析响应结果 - var response map[string]interface{} - if err := json.Unmarshal(responseBytes, &response); err != nil { - return fmt.Errorf("解析响应结果失败: %w", err) + if resp == nil || !resp.Success { + return fmt.Errorf("企业信息验证失败") } - // 检查验证状态 - status, ok := response["status"].(float64) + data, ok := resp.Data.(map[string]interface{}) if !ok { return fmt.Errorf("响应格式错误") } - // 根据状态码判断验证结果 - switch int(status) { - case 0: - // 验证通过 - s.logger.Info("企业信息验证通过", - zap.String("company_name", info.CompanyName), - zap.String("legal_person", info.LegalPersonName)) - return nil - case 1: - // 企业信息不一致 - return fmt.Errorf("企业信息不一致") - case 2: - // 身份证信息不一致 - return fmt.Errorf("身份证信息不一致") - default: - return fmt.Errorf("未知的验证状态: %d", int(status)) + entName := strings.TrimSpace(fmt.Sprint(data["name"])) + entCode := strings.TrimSpace(fmt.Sprint(data["creditCode"])) + if entCode == "" { + entCode = strings.TrimSpace(fmt.Sprint(data["regNumber"])) } + legalPerson := strings.TrimSpace(fmt.Sprint(data["legalPersonName"])) + + if !enterpriseNamesMatch(entName, info.CompanyName) || !strings.EqualFold(entCode, strings.TrimSpace(info.UnifiedSocialCode)) { + return fmt.Errorf("企业信息不一致") + } + if legalPerson != "" && !namesMatch(legalPerson, info.LegalPersonName) { + return fmt.Errorf("身份证信息不一致") + } + + s.logger.Info("企业信息验证通过", + zap.String("company_name", info.CompanyName), + zap.String("legal_person", info.LegalPersonName)) + return nil +} + +func enterpriseNamesMatch(a, b string) bool { + a = normalizeEnterpriseName(a) + b = normalizeEnterpriseName(b) + return a == b || strings.Contains(a, b) || strings.Contains(b, a) +} + +func namesMatch(a, b string) bool { + return strings.TrimSpace(a) == strings.TrimSpace(b) +} + +func normalizeEnterpriseName(s string) string { + s = strings.TrimSpace(s) + s = strings.ReplaceAll(s, "(", "(") + s = strings.ReplaceAll(s, ")", ")") + return s } diff --git a/internal/infrastructure/external/tianyuanapi/tianyuanapi_factory.go b/internal/infrastructure/external/tianyuanapi/tianyuanapi_factory.go new file mode 100644 index 0000000..10e5237 --- /dev/null +++ b/internal/infrastructure/external/tianyuanapi/tianyuanapi_factory.go @@ -0,0 +1,51 @@ +package tianyuanapi + +import ( + "time" + + "hyapi-server/internal/config" + "hyapi-server/internal/shared/external_logger" +) + +// NewTianyuanapiServiceWithConfig 使用配置创建天远 API 服务 +func NewTianyuanapiServiceWithConfig(cfg *config.Config) (*TianyuanapiService, error) { + loggingConfig := external_logger.ExternalServiceLoggingConfig{ + Enabled: cfg.Tianyuanapi.Logging.Enabled, + LogDir: cfg.Tianyuanapi.Logging.LogDir, + ServiceName: "tianyuanapi", + UseDaily: cfg.Tianyuanapi.Logging.UseDaily, + EnableLevelSeparation: cfg.Tianyuanapi.Logging.EnableLevelSeparation, + LevelConfigs: make(map[string]external_logger.ExternalServiceLevelFileConfig), + } + for k, v := range cfg.Tianyuanapi.Logging.LevelConfigs { + loggingConfig.LevelConfigs[k] = external_logger.ExternalServiceLevelFileConfig{ + MaxSize: v.MaxSize, + MaxBackups: v.MaxBackups, + MaxAge: v.MaxAge, + Compress: v.Compress, + } + } + + var logger *external_logger.ExternalServiceLogger + var err error + if loggingConfig.Enabled { + logger, err = external_logger.NewExternalServiceLogger(loggingConfig) + if err != nil { + return nil, err + } + } + + timeout := 30 * time.Second + if cfg.Tianyuanapi.Timeout > 0 { + timeout = cfg.Tianyuanapi.Timeout + } + + serviceCfg := TianyuanapiConfig{ + BaseURL: cfg.Tianyuanapi.BaseURL, + AccessID: cfg.Tianyuanapi.AccessID, + EncryptionKey: cfg.Tianyuanapi.EncryptionKey, + Timeout: timeout, + } + + return NewTianyuanapiService(serviceCfg, logger), nil +} diff --git a/internal/infrastructure/external/tianyuanapi/tianyuanapi_service.go b/internal/infrastructure/external/tianyuanapi/tianyuanapi_service.go new file mode 100644 index 0000000..0a077e3 --- /dev/null +++ b/internal/infrastructure/external/tianyuanapi/tianyuanapi_service.go @@ -0,0 +1,285 @@ +package tianyuanapi + +import ( + "bytes" + "context" + "crypto/md5" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "strconv" + "strings" + "time" + + "hyapi-server/internal/shared/crypto" + "hyapi-server/internal/shared/external_logger" +) + +const ( + maxLogParamValueLen = 300 + maxLogResponseBodyLen = 500 +) + +var ( + ErrDatasource = errors.New("数据源异常") + ErrSystem = errors.New("系统异常") + ErrNotFound = errors.New("查询为空") +) + +// TianyuanapiConfig 天远 API 服务配置 +type TianyuanapiConfig struct { + BaseURL string + AccessID string + EncryptionKey string + Timeout time.Duration +} + +// apiResponse 天远平台 HTTP 外层响应 +type apiResponse struct { + Code int `json:"code"` + Message string `json:"message"` + Data string `json:"data"` +} + +// requestPayload 请求体 +type requestPayload struct { + Data string `json:"data"` +} + +// TianyuanapiService 天远平台中转服务 +type TianyuanapiService struct { + config TianyuanapiConfig + logger *external_logger.ExternalServiceLogger +} + +// NewTianyuanapiService 创建天远 API 服务实例 +func NewTianyuanapiService(cfg TianyuanapiConfig, logger *external_logger.ExternalServiceLogger) *TianyuanapiService { + if cfg.Timeout == 0 { + cfg.Timeout = 30 * time.Second + } + return &TianyuanapiService{ + config: cfg, + logger: logger, + } +} + +func (s *TianyuanapiService) generateRequestID() string { + timestamp := time.Now().UnixNano() + hash := md5.Sum([]byte(fmt.Sprintf("%d_%s", timestamp, s.config.AccessID))) + return fmt.Sprintf("tianyuanapi_%x", hash[:8]) +} + +func truncateForLog(str string, maxLen int) string { + if maxLen <= 0 || len(str) <= maxLen { + return str + } + return str[:maxLen] + "...[truncated, total " + strconv.Itoa(len(str)) + " chars]" +} + +func requestParamsForLog(params map[string]interface{}) map[string]interface{} { + if params == nil { + return nil + } + out := make(map[string]interface{}, len(params)) + for k, v := range params { + if v == nil { + out[k] = nil + continue + } + switch val := v.(type) { + case string: + out[k] = truncateForLog(val, maxLogParamValueLen) + default: + out[k] = truncateForLog(fmt.Sprint(v), maxLogParamValueLen) + } + } + return out +} + +// CallAPI 调用天远平台指定产品(产品编号与处理器 ApiCode 一致) +func (s *TianyuanapiService) CallAPI(ctx context.Context, productCode string, params map[string]interface{}) ([]byte, error) { + startTime := time.Now() + requestID := s.generateRequestID() + + var transactionID string + if id, ok := ctx.Value("transaction_id").(string); ok { + transactionID = id + } + + baseURL := strings.TrimSuffix(s.config.BaseURL, "/") + reqURL := fmt.Sprintf("%s/api/v1/%s", baseURL, productCode) + + if s.logger != nil { + s.logger.LogRequest(requestID, transactionID, productCode, reqURL) + } + + jsonData, err := json.Marshal(params) + if err != nil { + err = errors.Join(ErrSystem, err) + if s.logger != nil { + s.logger.LogError(requestID, transactionID, productCode, err, map[string]interface{}{"request_params": requestParamsForLog(params)}) + } + return nil, err + } + + encryptedData, err := crypto.AesEncrypt(jsonData, s.config.EncryptionKey) + if err != nil { + err = errors.Join(ErrSystem, fmt.Errorf("加密请求失败: %w", err)) + if s.logger != nil { + s.logger.LogError(requestID, transactionID, productCode, err, map[string]interface{}{"request_params": requestParamsForLog(params)}) + } + return nil, err + } + + bodyBytes, err := json.Marshal(requestPayload{Data: encryptedData}) + if err != nil { + err = errors.Join(ErrSystem, err) + if s.logger != nil { + s.logger.LogError(requestID, transactionID, productCode, err, map[string]interface{}{"request_params": requestParamsForLog(params)}) + } + return nil, err + } + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, reqURL, bytes.NewReader(bodyBytes)) + if err != nil { + err = errors.Join(ErrSystem, err) + if s.logger != nil { + s.logger.LogError(requestID, transactionID, productCode, err, map[string]interface{}{"request_params": requestParamsForLog(params)}) + } + return nil, err + } + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Access-Id", s.config.AccessID) + + client := &http.Client{Timeout: s.config.Timeout} + resp, err := client.Do(req) + if err != nil { + isTimeout := ctx.Err() == context.DeadlineExceeded + if !isTimeout { + if te, ok := err.(interface{ Timeout() bool }); ok && te.Timeout() { + isTimeout = true + } + } + if !isTimeout { + es := err.Error() + if strings.Contains(es, "deadline exceeded") || strings.Contains(es, "timeout") || strings.Contains(es, "canceled") { + isTimeout = true + } + } + if isTimeout { + err = errors.Join(ErrDatasource, fmt.Errorf("API请求超时: %v", err)) + } else { + err = errors.Join(ErrSystem, err) + } + if s.logger != nil { + s.logger.LogError(requestID, transactionID, productCode, err, map[string]interface{}{"request_params": requestParamsForLog(params)}) + } + return nil, err + } + defer resp.Body.Close() + + duration := time.Since(startTime) + raw, err := io.ReadAll(resp.Body) + if err != nil { + err = errors.Join(ErrSystem, err) + if s.logger != nil { + s.logger.LogError(requestID, transactionID, productCode, err, map[string]interface{}{"request_params": requestParamsForLog(params)}) + } + return nil, err + } + + if resp.StatusCode != http.StatusOK { + err = errors.Join(ErrDatasource, fmt.Errorf("HTTP %d", resp.StatusCode)) + if s.logger != nil { + s.logger.LogError(requestID, transactionID, productCode, err, map[string]interface{}{ + "request_params": requestParamsForLog(params), + "response_body": truncateForLog(string(raw), maxLogResponseBodyLen), + }) + } + return nil, err + } + + if s.logger != nil { + s.logger.LogResponse(requestID, transactionID, productCode, resp.StatusCode, duration) + } + + var outer apiResponse + if err := json.Unmarshal(raw, &outer); err != nil { + parseErr := errors.Join(ErrSystem, fmt.Errorf("响应解析失败: %w", err)) + if s.logger != nil { + s.logger.LogError(requestID, transactionID, productCode, parseErr, map[string]interface{}{ + "request_params": requestParamsForLog(params), + "response_body": truncateForLog(string(raw), maxLogResponseBodyLen), + }) + } + return nil, parseErr + } + + if outer.Code != 0 { + mappedErr := mapBusinessError(outer.Code, outer.Message) + if s.logger != nil { + s.logger.LogError(requestID, transactionID, productCode, mappedErr, map[string]interface{}{ + "request_params": requestParamsForLog(params), + "response_body": truncateForLog(string(raw), maxLogResponseBodyLen), + "api_code": outer.Code, + }) + } + if errors.Is(mappedErr, ErrNotFound) { + return nil, mappedErr + } + return nil, mappedErr + } + + if outer.Data == "" { + return []byte("{}"), nil + } + + plain, err := crypto.AesDecrypt(outer.Data, s.config.EncryptionKey) + if err != nil { + decErr := errors.Join(ErrSystem, fmt.Errorf("解密响应失败: %w", err)) + if s.logger != nil { + s.logger.LogError(requestID, transactionID, productCode, decErr, map[string]interface{}{ + "request_params": requestParamsForLog(params), + "response_body": truncateForLog(string(raw), maxLogResponseBodyLen), + }) + } + return nil, decErr + } + + if len(plain) == 0 { + return []byte("{}"), nil + } + if !json.Valid(plain) { + return plain, nil + } + return plain, nil +} + +func mapBusinessError(code int, message string) error { + switch code { + case 0: + return nil + case 1000: + if message != "" { + return errors.Join(ErrNotFound, errors.New(message)) + } + return ErrNotFound + case 1003: + if message != "" { + return fmt.Errorf("%s", message) + } + return errors.New("请求参数结构不正确") + case 2001: + if message != "" { + return errors.Join(ErrDatasource, errors.New(message)) + } + return ErrDatasource + default: + if message != "" { + return errors.Join(ErrDatasource, errors.New(message)) + } + return ErrDatasource + } +} diff --git a/internal/infrastructure/external/tianyuanapi/tianyuanapi_service_test.go b/internal/infrastructure/external/tianyuanapi/tianyuanapi_service_test.go new file mode 100644 index 0000000..3974a67 --- /dev/null +++ b/internal/infrastructure/external/tianyuanapi/tianyuanapi_service_test.go @@ -0,0 +1,18 @@ +package tianyuanapi + +import ( + "errors" + "testing" +) + +func TestMapBusinessError(t *testing.T) { + if err := mapBusinessError(0, ""); err != nil { + t.Fatalf("code 0 should be nil, got %v", err) + } + if !errors.Is(mapBusinessError(1000, "查无"), ErrNotFound) { + t.Fatal("expected ErrNotFound for 1000") + } + if !errors.Is(mapBusinessError(2001, "业务失败"), ErrDatasource) { + t.Fatal("expected ErrDatasource for 2001") + } +} diff --git a/internal/infrastructure/http/handlers/qygl_report_handler.go b/internal/infrastructure/http/handlers/qygl_report_handler.go index 69e3a68..af29d73 100644 --- a/internal/infrastructure/http/handlers/qygl_report_handler.go +++ b/internal/infrastructure/http/handlers/qygl_report_handler.go @@ -17,7 +17,7 @@ import ( api_repositories "hyapi-server/internal/domains/api/repositories" api_services "hyapi-server/internal/domains/api/services" "hyapi-server/internal/domains/api/services/processors" - "hyapi-server/internal/domains/api/services/processors/qygl" + "hyapi-server/internal/domains/api/services/processors/qygl/reportstore" "hyapi-server/internal/shared/pdf" ) @@ -55,13 +55,11 @@ func (h *QYGLReportHandler) GetQYGLReportPage(c *gin.Context) { // 读取查询参数 entCode := c.Query("ent_code") entName := c.Query("ent_name") - entRegNo := c.Query("ent_reg_no") - // 组装 QYGLUY3S 入参 - req := dto.QYGLUY3SReq{ - EntName: entName, - EntRegno: entRegNo, - EntCode: entCode, + // 组装企业全景(QYGL7HBN)入参 + req := dto.QYGL7HBNReq{ + EntName: entName, + EntCode: entCode, } params, err := json.Marshal(req) @@ -71,12 +69,12 @@ func (h *QYGLReportHandler) GetQYGLReportPage(c *gin.Context) { return } - // 通过 ApiRequestService 调用 QYGLJ1U9 聚合处理器 + // 通过 ApiRequestService 调用 QYGL7HBN 聚合处理器 options := &commands.ApiCallOptions{} callCtx := &processors.CallContext{} ctx := c.Request.Context() - respBytes, err := h.apiRequestService.PreprocessRequestApi(ctx, "QYGLJ1U9", params, options, callCtx) + respBytes, err := h.apiRequestService.PreprocessRequestApi(ctx, "QYGL7HBN", params, options, callCtx) if err != nil { h.logger.Error("调用企业全景报告处理器失败", zap.Error(err)) c.String(http.StatusInternalServerError, "生成企业报告失败,请稍后重试") @@ -127,7 +125,7 @@ func (h *QYGLReportHandler) GetQYGLReportPageByID(c *gin.Context) { } // 回退到进程内存缓存(兼容老的访问方式) - report, ok := qygl.GetQYGLReport(id) + report, ok := reportstore.GetQYGLReport(id) if !ok { c.String(http.StatusNotFound, "报告不存在或已过期") return @@ -156,7 +154,7 @@ func (h *QYGLReportHandler) qyglReportExists(ctx context.Context, id string) boo return true } } - _, ok := qygl.GetQYGLReport(id) + _, ok := reportstore.GetQYGLReport(id) return ok }