[
  {
    "path": ".gitignore",
    "content": "# Compiled class file\n*.class\n\n# Log file\n*.log\n\n# BlueJ files\n*.ctxt\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.jar\n*.war\n*.nar\n*.ear\n*.zip\n*.tar.gz\n*.rar\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n"
  },
  {
    "path": "LICENSE",
    "content": "Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n\"License\" shall mean the terms and conditions for use, reproduction, and\ndistribution as defined by Sections 1 through 9 of this document.\n\n\"Licensor\" shall mean the copyright owner or entity authorized by the copyright\nowner that is granting the License.\n\n\"Legal Entity\" shall mean the union of the acting entity and all other entities\nthat control, are controlled by, or are under common control with that entity.\nFor the purposes of this definition, \"control\" means (i) the power, direct or\nindirect, to cause the direction or management of such entity, whether by\ncontract or otherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising\npermissions granted by this License.\n\n\"Source\" form shall mean the preferred form for making modifications, including\nbut not limited to software source code, documentation source, and configuration\nfiles.\n\n\"Object\" form shall mean any form resulting from mechanical transformation or\ntranslation of a Source form, including but not limited to compiled object code,\ngenerated documentation, and conversions to other media types.\n\n\"Work\" shall mean the work of authorship, whether in Source or Object form, made\navailable under the License, as indicated by a copyright notice that is included\nin or attached to the work (an example is provided in the Appendix below).\n\n\"Derivative Works\" shall mean any work, whether in Source or Object form, that\nis based on (or derived from) the Work and for which the editorial revisions,\nannotations, elaborations, or other modifications represent, as a whole, an\noriginal work of authorship. For the purposes of this License, Derivative Works\nshall not include works that remain separable from, or merely link (or bind by\nname) to the interfaces of, the Work and Derivative Works thereof.\n\n\"Contribution\" shall mean any work of authorship, including the original version\nof the Work and any modifications or additions to that Work or Derivative Works\nthereof, that is intentionally submitted to Licensor for inclusion in the Work\nby the copyright owner or by an individual or Legal Entity authorized to submit\non behalf of the copyright owner. For the purposes of this definition,\n\"submitted\" means any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems, and\nissue tracking systems that are managed by, or on behalf of, the Licensor for\nthe purpose of discussing and improving the Work, but excluding communication\nthat is conspicuously marked or otherwise designated in writing by the copyright\nowner as \"Not a Contribution.\"\n\n\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf\nof whom a Contribution has been received by Licensor and subsequently\nincorporated within the Work.\n\n2. Grant of Copyright License.\n\nSubject to the terms and conditions of this License, each Contributor hereby\ngrants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,\nirrevocable copyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the Work and such\nDerivative Works in Source or Object form.\n\n3. Grant of Patent License.\n\nSubject to the terms and conditions of this License, each Contributor hereby\ngrants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,\nirrevocable (except as stated in this section) patent license to make, have\nmade, use, offer to sell, sell, import, and otherwise transfer the Work, where\nsuch license applies only to those patent claims licensable by such Contributor\nthat are necessarily infringed by their Contribution(s) alone or by combination\nof their Contribution(s) with the Work to which such Contribution(s) was\nsubmitted. If You institute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work or a\nContribution incorporated within the Work constitutes direct or contributory\npatent infringement, then any patent licenses granted to You under this License\nfor that Work shall terminate as of the date such litigation is filed.\n\n4. Redistribution.\n\nYou may reproduce and distribute copies of the Work or Derivative Works thereof\nin any medium, with or without modifications, and in Source or Object form,\nprovided that You meet the following conditions:\n\nYou must give any other recipients of the Work or Derivative Works a copy of\nthis License; and\nYou must cause any modified files to carry prominent notices stating that You\nchanged the files; and\nYou must retain, in the Source form of any Derivative Works that You distribute,\nall copyright, patent, trademark, and attribution notices from the Source form\nof the Work, excluding those notices that do not pertain to any part of the\nDerivative Works; and\nIf the Work includes a \"NOTICE\" text file as part of its distribution, then any\nDerivative Works that You distribute must include a readable copy of the\nattribution notices contained within such NOTICE file, excluding those notices\nthat do not pertain to any part of the Derivative Works, in at least one of the\nfollowing places: within a NOTICE text file distributed as part of the\nDerivative Works; within the Source form or documentation, if provided along\nwith the Derivative Works; or, within a display generated by the Derivative\nWorks, if and wherever such third-party notices normally appear. The contents of\nthe NOTICE file are for informational purposes only and do not modify the\nLicense. You may add Your own attribution notices within Derivative Works that\nYou distribute, alongside or as an addendum to the NOTICE text from the Work,\nprovided that such additional attribution notices cannot be construed as\nmodifying the License.\nYou may add Your own copyright statement to Your modifications and may provide\nadditional or different license terms and conditions for use, reproduction, or\ndistribution of Your modifications, or for any such Derivative Works as a whole,\nprovided Your use, reproduction, and distribution of the Work otherwise complies\nwith the conditions stated in this License.\n\n5. Submission of Contributions.\n\nUnless You explicitly state otherwise, any Contribution intentionally submitted\nfor inclusion in the Work by You to the Licensor shall be under the terms and\nconditions of this License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify the terms of\nany separate license agreement you may have executed with Licensor regarding\nsuch Contributions.\n\n6. Trademarks.\n\nThis License does not grant permission to use the trade names, trademarks,\nservice marks, or product names of the Licensor, except as required for\nreasonable and customary use in describing the origin of the Work and\nreproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty.\n\nUnless required by applicable law or agreed to in writing, Licensor provides the\nWork (and each Contributor provides its Contributions) on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,\nincluding, without limitation, any warranties or conditions of TITLE,\nNON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are\nsolely responsible for determining the appropriateness of using or\nredistributing the Work and assume any risks associated with Your exercise of\npermissions under this License.\n\n8. Limitation of Liability.\n\nIn no event and under no legal theory, whether in tort (including negligence),\ncontract, or otherwise, unless required by applicable law (such as deliberate\nand grossly negligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special, incidental,\nor consequential damages of any character arising as a result of this License or\nout of the use or inability to use the Work (including but not limited to\ndamages for loss of goodwill, work stoppage, computer failure or malfunction, or\nany and all other commercial damages or losses), even if such Contributor has\nbeen advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability.\n\nWhile redistributing the Work or Derivative Works thereof, You may choose to\noffer, and charge a fee for, acceptance of support, warranty, indemnity, or\nother liability obligations and/or rights consistent with this License. However,\nin accepting such obligations, You may act only on Your own behalf and on Your\nsole responsibility, not on behalf of any other Contributor, and only if You\nagree to indemnify, defend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason of your\naccepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work\n\nTo apply the Apache License to your work, attach the following boilerplate\nnotice, with the fields enclosed by brackets \"{}\" replaced with your own\nidentifying information. (Don't include the brackets!) The text should be\nenclosed in the appropriate comment syntax for the file format. We also\nrecommend that a file or class name and description of purpose be included on\nthe same \"printed page\" as the copyright notice for easier identification within\nthird-party archives.\n\n   Copyright 2018 egan\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License."
  },
  {
    "path": "README.md",
    "content": " # 支付聚合spring boot组件\npay-spring-boot-starter 是一个基于spring-boot实现自动化配置的支付对接， **让你真正做到一行代码实现支付聚合**， 让你可以不用理解支付怎么对接，只需要专注你的业务 \n\n\n ### 特性\n      1. 项目第三方依赖极少，依托于spring boot与pay-java，项目精简，不用担心项目迁移问题\n      2. 一行代码解决配置，一行代码发起支付，一行代码处理回调并且业务与支付完全隔离\n      3. 项目扩展性极强极灵活，组件中暴露大量接口，实现对应接口重写加入spring容器即可覆盖全部功能\n      4. 引入pay-java具体支付组件即可激活某一支付功能，代码可以不用任何修改即可使用\n\n---\n全能第三方支付对接pay-spring-boot-starter开发工具包.优雅的轻量级支付模块集成支付对接支付整合（微信,支付宝,银联,友店,富友,跨境支付paypal,payoneer(P卡派安盈)易极付）app,扫码,网页支付刷卡付条码付刷脸付转账服务商模式、支持多种支付类型多支付账户，支付与业务完全剥离，简单几行代码即可实现支付，简单快速完成支付模块的开发\n \n\n\n#### 本项目在以下代码托管网站\n* 码云：https://gitee.com/egzosn/pay-spring-boot-starter-parent\n* GitHub：https://github.com/egzosn/pay-spring-boot-starter-parent\n\n#### 软件架构\nspring-boot  pay-java-parent\n\n#### 本项目基础实现 pay-java-parent 全能第三方支付对接Java开发工具包.优雅的轻量级支付模块集成支付对接支付整合（微信,支付宝,银联,友店,富友,跨境支付paypal,payoneer(P卡派安盈)易极付）app,扫码,网页支付刷卡付条码付刷脸付转账服务商模式、支持多种支付类型多支付账户，支付与业务完全剥离，简单几行代码即可实现支付，简单快速完成支付模块的开发，可轻松嵌入到任何系统里 目前仅是一个开发工具包（即SDK）\n* 码云：https://gitee.com/egzosn/pay-java-parent\n* GitHub：https://github.com/egzosn/pay-java-parent\n\n\n#### 使用教程\n\n1. 引入 pay-spring-boot-starter\n```xml\n    <dependency>\n        <groupId>com.egzosn</groupId>\n        <artifactId>pay-spring-boot-starter</artifactId>\n        <version>1.0.5</version>\n    </dependency>\n```\n2. 引入 你需要对接的基于`pay-java-parent`支付开发包,具体支付模块 \"{module-name}\" 为具体的支付渠道的模块名 pay-java-ali，pay-java-wx等\n\n```xml\n    <dependency>\n        <groupId>com.egzosn</groupId>\n        <artifactId>{module-name}</artifactId>\n        <version>2.14.9</version>\n    </dependency>\n\n```\n3. 编写一个基于com.egzosn.pay.spring.boot.core.PayServiceConfigurer的子类 \n```\n    3.1.  并将其加入spring容器中\n    3.2.  对PayServiceConfigurer的子类所实现的方法进行配置数据来源，目前提供两种方式`jdbc`与`inMemory`\n\n```\n\n    \n4. 使用： 在你需要用到的类中注入 `com.egzosn.pay.spring.boot.core.MerchantPayServiceManager`  这个类是一个支付相关的操作类，拿到该类的引用即可对任意支付进行操作\n\n#### 使用案例详情查看[pay-spring-boot-starter-demo](pay-spring-boot-starter-demo?dir=1&filepath=pay-spring-boot-starter-demo)\n\n\n###### 支付教程 \n\n * [基础模块支付宝微信讲解](https://gitee.com/egzosn/pay-java-parent/wikis/Home)\n * [微信V3，查看demo/WxV3PayController](https://gitee.com/egzosn/pay-java-parent/blob/develop/pay-java-demo/)\n * [微信合并支付，查看demo/WxV3CombinePayController](https://gitee.com/egzosn/pay-java-parent/blob/develop/pay-java-demo/)\n * [微信分账，查看demo/WxV3ProfitSharingController](https://gitee.com/egzosn/pay-java-parent/blob/develop/pay-java-demo/)\n * [银联](https://gitee.com/egzosn/pay-java-parent/blob/develop/pay-java-union?dir=1&filepath=pay-java-union)\n * [payoneer](https://gitee.com/egzosn/pay-java-parent/blob/develop/pay-java-payoneer?dir=1&filepath=pay-java-payoneer)\n * [paypal,查看demo/PayPalV2PayController](https://gitee.com/egzosn/pay-java-parent/blob/develop/pay-java-demo/)\n * [友店微信](https://gitee.com/egzosn/pay-java-parent/blob/develop/pay-java-wx-youdian?dir=1&filepath=pay-java-youdian)\n * [富友](https://gitee.com/egzosn/pay-java-parent/blob/develop/pay-java-fuiou?dir=1&filepath=pay-java-fuiou)\n * [自定义支付宝商户/MyAliPaymentPlatform](pay-spring-boot-starter-demo?dir=1&filepath=pay-spring-boot-starter-demo)\n \n\n作者公众号\n![公众号](https://gitee.com/egzosn/pay-java-parent/raw/develop/pay-java-demo/src/main/webapp/gzh.png \"gzh.png\")\n\nE-Mail：egan@egzosn.com\n\n **QQ群：** \n\n\n1. pay-java(1群): 542193977(已满)\n2. pay-java(2群)：766275051\n\n\n微信群: 加我前拜托伸个小手关注公众号\n\n![微信群](https://egzosn.gitee.io/pay-java-parent/wx.jpg \"wx.jpg\")\n\n\n\n\n#### 参与贡献\n\n1. Fork 本项目\n2. 新建 Feat_xxx 分支\n3. 提交代码\n4. 新建 Pull Request\n\n\n也感谢各大友友同学帮忙进行接口测试\n\n非常欢迎和感谢对本项目发起Pull Request的同学，不过本项目基于git flow开发流程，因此在发起Pull Request的时候请选择develop分支。\n\n"
  },
  {
    "path": "doc/sql/merchant_pay.sql",
    "content": "\r\nCREATE DATABASE merchant_pay;\r\n\r\nUSE `merchant_pay`;\r\n\r\n\r\nDROP TABLE IF EXISTS `merchant_details`;\r\n\r\nCREATE TABLE `merchant_details` (\r\n  `details_id` char(32) NOT NULL COMMENT '列表id',\r\n  `pay_type` varchar(16) NOT NULL COMMENT '支付类型(支付渠道) 详情查看com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform对应子类，aliPay 支付宝， wxPay微信..等等',\r\n  `appid` varchar(32) DEFAULT NULL COMMENT '应用id',\r\n  `mch_id` varchar(32) DEFAULT NULL COMMENT '商户id，商户号，合作伙伴id等等',\r\n  `cert_store_type` varchar(16) DEFAULT NULL COMMENT '当前面私钥公钥为证书类型的时候，这里必填，可选值:PATH,STR,INPUT_STREAM,CLASS_PATH,URL',\r\n  `key_private` mediumtext COMMENT '私钥或私钥证书',\r\n  `key_public` mediumtext COMMENT '公钥或公钥证书',\r\n  `key_cert` varchar(20480) DEFAULT NULL COMMENT 'key证书,附加证书使用，如SSL证书，或者银联根级证书方面',\r\n  `key_cert_pwd` varchar(32) DEFAULT NULL COMMENT '私钥证书或key证书的密码',\r\n  `notify_url` varchar(256) DEFAULT NULL COMMENT '异步回调',\r\n  `return_url` varchar(256) DEFAULT NULL COMMENT '同步回调地址，大部分用于付款成功后页面转跳',\r\n  `sign_type` varchar(16) NOT NULL COMMENT '签名方式,目前已实现多种签名方式详情查看com.egzosn.pay.common.util.sign.encrypt。MD5,RSA等等',\r\n  `seller` varchar(32) DEFAULT NULL COMMENT '收款账号，暂时只有支付宝部分使用，可根据开发者自行使用',\r\n  `sub_app_id` varchar(32) DEFAULT NULL COMMENT '子appid',\r\n  `sub_mch_id` varchar(32) DEFAULT NULL COMMENT '子商户id',\r\n  `input_charset` varchar(16) NOT NULL COMMENT '编码类型，大部分为utf-8',\r\n  `is_test` tinyint(1) NOT NULL COMMENT '是否为测试环境: 0 否，1 测试环境',\r\n  PRIMARY KEY (`details_id`)\r\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\r\n\r\n\r\n\r\n\r\ninsert  into `merchant_details`(`details_id`,`pay_type`,`appid`,`mch_id`,`cert_store_type`,`key_private`,`key_public`,`key_cert`,`key_cert_pwd`,`notify_url`,`return_url`,`sign_type`,`seller`,`sub_app_id`,`sub_mch_id`,`input_charset`,`is_test`) values\r\n ('1','aliPay','2016080400165436','2088102169916436',NULL ,'MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKroe/8h5vC4L6T+B2WdXiVwGsMvUKgb2XsKix6VY3m2wcf6tyzpNRDCNykbIwGtaeo7FshN+qZxdXHLiIam9goYncBit/8ojfLGy2gLxO/PXfzGxYGs0KsDZ+ryVPPmE34ZZ8jiJpR0ygzCFl8pN3QJPJRGTJn5+FTT9EF/9zyZAgMBAAECgYAktngcYC35u7cQXDk+jMVyiVhWYU2ULxdSpPspgLGzrZyG1saOcTIi/XVX8Spd6+B6nmLQeF/FbU3rOeuD8U2clzul2Z2YMbJ0FYay9oVZFfp5gTEFpFRTVfzqUaZQBIjJe/xHL9kQVqc5xHlE/LVA27/Kx3dbC35Y7B4EVBDYAQJBAOhsX8ZreWLKPhXiXHTyLmNKhOHJc+0tFH7Ktise/0rNspojU7o9prOatKpNylp9v6kux7migcMRdVUWWiVe+4ECQQC8PqsuEz7B0yqirQchRg1DbHjh64bw9Kj82EN1/NzOUd53tP9tg+SO97EzsibK1F7tOcuwqsa7n2aY48mQ+y0ZAkBndA2xcRcnvOOjtAz5VO8G7R12rse181HjGfG6AeMadbKg30aeaGCyIxN1loiSfNR5xsPJwibGIBg81mUrqzqBAkB+K6rkaPXJR9XtzvdWb/N3235yPkDlw7Z4MiOVM3RzvR/VMDV7m8lXoeDde2zQyeMOMYy6ztwA6WgE1bhGOnQRAkEAouUBv1sVdSBlsexX15qphOmAevzYrpufKgJIRLFWQxroXMS7FTesj+f+FmGrpPCxIde1dqJ8lqYLTyJmbzMPYw==','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIgHnOn7LLILlKETd6BFRJ0GqgS2Y3mn1wMQmyh9zEyWlz5p1zrahRahbXAfCfSqshSNfqOmAQzSHRVjCqjsAw1jyqrXaPdKBmr90DIpIxmIyKXv4GGAkPyJ/6FTFY99uhpiq0qadD/uSzQsefWo0aTvP/65zi3eof7TcZ32oWpwIDAQAB',NULL,NULL,'http://pay.egzosn.com/payBack1.json','http://pay.egzosn.com/payBack1.json','RSA','2088102169916436',NULL,NULL,'UTF-8',1)\r\n -- 这里支付证书加载方式，需要配合定制化的代码 详情pay-spring-boot-starter-demo\\src\\main\\java\\com\\egzosn\\pay\\spring\\boot\\demo\\config\\MyAliPaymentPlatform.java\r\n ('11','aliPay','2016080400165436','2088102169916436','CLASS_PATH','MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCw7MD2Cwv/jnXssFjXnGx3JlGF57gJa2aYbJRV8MnNiPVpX4Ha+8ZjnQDhvkrWH4hHmzcujOr213HqloMpUSYBzCPiXGVRUUvdimejcHHTod7nI4g6nztzzfey/TXNDHmp7vY3pOIcjB0Zn0pkNAz2tKAFkqb4raHOqTB0QA0zD24Cn+26J2UJyYRcgeH0GtSQuUrm7yaGsuKakh+qtgWF6R71n5PMGOTQ5LH3i0WVHfCBkNGgJC6yC96HR4D7cosoyKD0+lp8UB/NVUWl7Tt/KLOgFUwh0GKSYFfv56O/VBV2+xqCGE4PlZESfVuOqz5vjjxzw3xDAUJrV8hSX/AJAgMBAAECggEBAKE0d3U4B4yo/2XUIH8EdgfykCFUSum6RFbpyBauORHfksyaSzV+ZvtomN8XhhSn0oJ8OMFfgM+86nz2+zdwSxMkMCYWTfLUAi4v59KRqAVO3kz4oS3Y3FDeAK3D7XuRvGFL7GgzAhtEx1cLPrsiehVn6s5pG15GxsIIgq/JlL1J88wn1zENLrVHmD6z/JpXvfb/RS1yR+5lyoohp4g0Ph9jJ3bCyUbRpK0QkPEzgAuWL0K2ITCL7PYHNAplI8d2xHHOLF9Qdjyx+ZrQ/RxtqzfyWzhqjsmp2qlgNCxWlt3woS9UhDB+nRvjEoWTJmIOszAMYuj8wGlX+3Ui3ALOdQECgYEA25EqnFPFinUnzgNvB6NYmh5STmZun6s4bUOLqwefKtEvrOtRwTu7sB7NIf37fizG3/MJUWHxiLy2/3ub4d2JxdDNBtJoEqnp6QB12qglCNa4CajdjtJa1dR81F9QvytsqEkmPYXFPPyviB0FcSIDAGMb3IbwvIfzBPY9WY8dJnECgYEAzkg3yKEFBZ8BU0WQ+3hyfKUoAhBEnxouxRSTBcXxwstJRiqaGTVe5aoJGQI+0xS7Z6q07XDtN2t97s6DnRLWbljsX6B64itzNhXRyzjdD3iZDU/KSw7khjhXf8XOZaj9eXmACDiUnkEn1xsM8bLiRGqB8y5f3aMY/RpuACGXnxkCgYEAx/zwT9Vpr1RIfjfYcJ+Su0X0994K0roUukj0tUJK8qf4gcsQ+y1aJe/YLib1ZBaKyj7G9O5+HmqtUAUZld/AdoJZzOXmz2EeYhD+R7wxh1xz4rCBpW3qOKvDS3jJxmZaIOoHv6/RWFxb0WGFrGcrTrX3EaWDLmWxr4pNlP5qsbECgYATllntrBR8/ycyEAX/SuWcHlaZM5BAh0zvm8+GGdCmDYWMqxjs0duL9URd4o+ynWJaKqR5c2KjA4r2tRdcP+Cqo7j2L5fbiAKtnQ7JvEGJaYsm72+nBuf+MrVkRZUepBhFg5r7rNu31zoAO+pTvQetNWvXeozRz93ckrjlPEtYaQKBgQDFwbV92rlRMLjZzlY+o0knoeJBjPQmPdiBTpGNimdy9L4c2Ure7affjcUiYhkKqrK5k5SScJTATgyQ7JF346FdtUtZ/6Kkj1RwJmmprPrDa9CATLoTle7g9OVd4sHT2ITHZMzPaF3ILvzcwJ70AD1xcxCQb+/7sDPmw7Mc8gOA7Q==','ali/alipayCertPublicKey_RSA2.crt','ali/appCertPublicKey_2016080400165436.crt,ali/alipayRootCert.crt',NULL,'http://pay.egzosn.com/payBack1.json','http://pay.egzosn.com/payBack1.json','RSA2','2088102169916436',NULL,NULL,'UTF-8',1)\r\n,('2','unionPay',NULL,'700000000000001','PATH','D:/certs/acp_test_sign.pfx','D:/certs/acp_test_middle.cer','D:/certs/acp_test_root.cer','000000','http://pay.egzosn.com/payBack3.json','http://pay.egzosn.com/payBack3.json','RSA2',NULL,NULL,NULL,'UTF-8',1)\r\n,( '3','wxPay','公众账号ID','合作者id（商户号）','URL','密钥','转账公钥，转账时必填','http://www.egzosn.com/certs/apiclient_cert.p12','默认为商户号','http://www.pay.egzosn.com/payBack3.json','http://www.pay.egzosn.com/payBack3.json','MD5',NULL,NULL,NULL,'UTF-8','1')\r\n,( '4','wxV3Pay','公众账号ID','合作者id（商户号）','URL','密钥','转账公钥，转账时必填','http://www.egzosn.com/certs/apiclient_cert.p12','默认为商户号','http://www.pay.egzosn.com/payBack3.json','http://www.pay.egzosn.com/payBack3.json','MD5',NULL,NULL,NULL,'UTF-8','1')\r\n,( '5','wxV3ProfitSharing','公众账号ID','合作者id（商户号）','URL','V3密钥','转账公钥，转账时必填','http://www.egzosn.com/certs/apiclient_cert.p12','默认为商户号','http://www.pay.egzosn.com/payBack3.json','http://www.pay.egzosn.com/payBack3.json','MD5',NULL,NULL,NULL,'UTF-8','1')\r\n,( '6','wxV3ProfitSharing','公众账号ID','合作者id（商户号）','URL','V3密钥','转账公钥，转账时必填','http://www.egzosn.com/certs/apiclient_cert.p12','默认为商户号','http://www.pay.egzosn.com/payBack3.json','http://www.pay.egzosn.com/payBack3.json','MD5',NULL,NULL,NULL,'UTF-8','1')\r\n,( '7','wxV3CombinePay','公众账号ID','合作者id（商户号）','URL','V3密钥','转账公钥，转账时必填','http://www.egzosn.com/certs/apiclient_cert.p12','默认为商户号','http://www.pay.egzosn.com/payBack3.json','http://www.pay.egzosn.com/payBack3.json','MD5',NULL,NULL,NULL,'UTF-8','1')\r\n;\r\n"
  },
  {
    "path": "pay-spring-boot/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <groupId>com.egzosn</groupId>\n        <artifactId>pay-spring-boot-starter-parent</artifactId>\n      <version>1.0.5</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.egzosn</groupId>\n    <artifactId>pay-spring-boot</artifactId>\n    <name>pay-spring-boot</name>\n\n\n</project>"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/MerchantPayServiceManager.java",
    "content": "package com.egzosn.pay.spring.boot.core;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.Map;\n\nimport javax.imageio.ImageIO;\n\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport com.egzosn.pay.common.api.DefaultPayMessageHandler;\nimport com.egzosn.pay.common.api.PayMessageHandler;\nimport com.egzosn.pay.common.api.PayMessageInterceptor;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.api.TransferService;\nimport com.egzosn.pay.common.bean.AssistOrder;\nimport com.egzosn.pay.common.bean.DefaultNoticeRequest;\nimport com.egzosn.pay.common.bean.MethodType;\nimport com.egzosn.pay.common.bean.NoticeParams;\nimport com.egzosn.pay.common.bean.NoticeRequest;\nimport com.egzosn.pay.common.bean.PayMessage;\nimport com.egzosn.pay.common.bean.RefundOrder;\nimport com.egzosn.pay.common.bean.RefundResult;\nimport com.egzosn.pay.common.bean.TransferOrder;\nimport com.egzosn.pay.spring.boot.core.bean.MerchantPayOrder;\nimport com.egzosn.pay.spring.boot.core.bean.MerchantQueryOrder;\nimport com.egzosn.pay.spring.boot.core.merchant.MerchantDetailsService;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\n\n/**\n * 商户支付服务\n *\n * @author egan\n * <pre>\n * email egzosn@gmail.com\n *\n * date 2019/5/8 19:43.\n * </pre>\n */\npublic class MerchantPayServiceManager implements PayServiceManager {\n\n    @Autowired\n    private MerchantDetailsService<PaymentPlatformMerchantDetails> detailsService;\n\n    /**\n     * 回调校验\n     *\n     * @param detailsId 商户列表id\n     * @param params    回调回来的参数集\n     * @return 签名校验 true通过\n     */\n    @Override\n    public boolean verify(String detailsId, Map<String, Object> params) {\n\n        return this.verify(detailsId, new NoticeParams(params));\n    }\n\n    /**\n     * 回调校验\n     *\n     * @param detailsId 商户列表id\n     * @param params    回调回来的参数集\n     * @return 签名校验 true通过\n     */\n    @Override\n    public boolean verify(String detailsId, NoticeParams params) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(detailsId);\n        return details.getPayService().verify(params);\n    }\n\n    /**\n     * 将请求参数或者请求流转化为 Map\n     *\n     * @param detailsId    商户列表id\n     * @param parameterMap 请求参数\n     * @param is           请求流\n     * @return 获得回调的请求参数\n     * @see #getNoticeParams(String, NoticeRequest)\n     */\n    @Deprecated\n    @Override\n    public Map<String, Object> getParameter2Map(String detailsId, Map<String, String[]> parameterMap, InputStream is) {\n        return getNoticeParams(detailsId, new DefaultNoticeRequest(parameterMap, is)).getBody();\n    }\n\n    /**\n     * 将请求参数或者请求流转化为 Map\n     *\n     * @param detailsId 商户列表id\n     * @param request   通知请求\n     * @return 获得回调的请求参数\n     */\n    @Override\n    public NoticeParams getNoticeParams(String detailsId, NoticeRequest request) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(detailsId);\n        return details.getPayService().getNoticeParams(request);\n    }\n\n    /**\n     * 跳到支付页面\n     * 针对实时支付,即时付款\n     *\n     * @param payOrder 商户支付订单信息\n     * @return 跳到支付页面\n     */\n    @Override\n    public String toPay(MerchantPayOrder payOrder) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(payOrder.getDetailsId());\n        payOrder.setTransactionType(details.getPaymentPlatform().getTransactionType(payOrder.getWayTrade()));\n        PayService payService = details.getPayService();\n        Map<String, Object> orderInfo = payService.orderInfo(payOrder);\n        return payService.buildRequest(orderInfo, MethodType.POST);\n    }\n\n    /**\n     * 获取支付预订单信息\n     *\n     * @param payOrder 商户支付订单信息\n     * @return 支付预订单信息\n     */\n    @Override\n    public Map<String, Object> app(MerchantPayOrder payOrder) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(payOrder.getDetailsId());\n        payOrder.setTransactionType(details.getPaymentPlatform().getTransactionType(payOrder.getWayTrade()));\n        PayService payService = details.getPayService();\n        return payService.app(payOrder);\n    }\n\n    /**\n     * 获取支付预订单信息\n     *\n     * @param payOrder 商户支付订单信息\n     * @return 支付预订单信息\n     */\n    @Override\n    public Map<String, Object> getOrderInfo(MerchantPayOrder payOrder) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(payOrder.getDetailsId());\n        payOrder.setTransactionType(details.getPaymentPlatform().getTransactionType(payOrder.getWayTrade()));\n        PayService payService = details.getPayService();\n        return payService.orderInfo(payOrder);\n    }\n\n    /**\n     * 刷卡付,pos主动扫码付款(条码付)\n     * 刷脸付\n     *\n     * @param payOrder 商户支付订单信息\n     * @return 支付结果\n     */\n    @Override\n    public Map<String, Object> microPay(MerchantPayOrder payOrder) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(payOrder.getDetailsId());\n        payOrder.setTransactionType(details.getPaymentPlatform().getTransactionType(payOrder.getWayTrade()));\n        //支付结果\n        return details.getPayService().microPay(payOrder);\n    }\n\n    /**\n     * 获取二维码图像\n     * 二维码支付\n     *\n     * @param payOrder 商户支付订单信息\n     * @return 二维码图像\n     * @throws IOException IOException\n     */\n    @Override\n    public byte[] toQrPay(MerchantPayOrder payOrder) throws IOException {\n        //获取对应的支付账户操作工具（可根据账户id）\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(payOrder.getDetailsId());\n        payOrder.setTransactionType(details.getPaymentPlatform().getTransactionType(payOrder.getWayTrade()));\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n\n        ImageIO.write(details.getPayService().genQrPay(payOrder), \"JPEG\", baos);\n        return baos.toByteArray();\n    }\n\n    /**\n     * 获取二维码信息\n     * 二维码支付\n     *\n     * @param payOrder 商户支付订单信息\n     * @return 二维码信息\n     */\n    @Override\n    public String getQrPay(MerchantPayOrder payOrder) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(payOrder.getDetailsId());\n        payOrder.setTransactionType(details.getPaymentPlatform().getTransactionType(payOrder.getWayTrade()));\n        return details.getPayService().getQrPay(payOrder);\n    }\n\n    /**\n     * 支付回调地址\n     * 方式二\n     *\n     * @param detailsId    商户列表id\n     * @param parameterMap 请求参数\n     * @param is           请求流\n     * @return 支付是否成功\n     * @throws IOException IOException\n     *                     拦截器相关增加， 详情查看{@link com.egzosn.pay.common.api.PayService#addPayMessageInterceptor(PayMessageInterceptor)}\n     *                     <p>\n     *                     业务处理在对应的PayMessageHandler里面处理，在哪里设置PayMessageHandler，详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)}\n     *                     </p>\n     *                     如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler}\n     *                     方法过时，替代方法{@link #payBack(String, NoticeRequest)}\n     */\n    @Deprecated\n    @Override\n    public String payBack(String detailsId, Map<String, String[]> parameterMap, InputStream is) throws IOException {\n        return this.payBack(detailsId, new DefaultNoticeRequest(parameterMap, is));\n    }\n\n    /**\n     * 支付回调地址\n     * 方式二\n     *\n     * @param detailsId 商户列表id\n     * @param request   请求参数\n     * @return 支付是否成功\n     * 拦截器相关增加， 详情查看{@link PayService#addPayMessageInterceptor(PayMessageInterceptor)}\n     * <p>\n     * 业务处理在对应的PayMessageHandler里面处理，在哪里设置PayMessageHandler，详情查看{@link PayService#setPayMessageHandler(PayMessageHandler)}\n     * </p>\n     * 如果未设置 {@link PayMessageHandler} 那么会使用默认的 {@link DefaultPayMessageHandler}\n     */\n    @Override\n    public String payBack(String detailsId, NoticeRequest request) {\n        //业务处理在对应的PayMessageHandler里面处理，在哪里设置PayMessageHandler，详情查看com.egzosn.pay.common.api.PayService.setPayMessageHandler()\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(detailsId);\n        PayService payService = details.getPayService();\n        return payService.payBack(request).toMessage();\n    }\n\n\n    /**\n     * 查询\n     *\n     * @param order 订单的请求体\n     * @return 返回查询回来的结果集，支付方原值返回\n     */\n    @Override\n    public Map<String, Object> query(MerchantQueryOrder order) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(order.getDetailsId());\n        order.setTransactionType(details.getPaymentPlatform().getTransactionType(order.getWayTrade()));\n        return details.getPayService().query(order);\n    }\n\n    /**\n     * 交易关闭接口\n     *\n     * @param order 订单的请求体\n     * @return 返回支付方交易关闭后的结果\n     */\n    @Override\n    public Map<String, Object> close(MerchantQueryOrder order) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(order.getDetailsId());\n        order.setTransactionType(details.getPaymentPlatform().getTransactionType(order.getWayTrade()));\n        return details.getPayService().close(order);\n    }\n\n\n    /**\n     * 申请退款接口\n     *\n     * @param detailsId 列表id\n     * @param order     订单的请求体\n     * @return 返回支付方申请退款后的结果\n     */\n    @Override\n    public RefundResult refund(String detailsId, RefundOrder order) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(detailsId);\n\n        return details.getPayService().refund(order);\n    }\n\n    /**\n     * 查询退款\n     *\n     * @param detailsId 列表id\n     * @param order     订单的请求体\n     * @return 返回支付方查询退款后的结果\n     */\n    @Override\n    public Map<String, Object> refundQuery(String detailsId, RefundOrder order) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(detailsId);\n        return details.getPayService().refundquery(order);\n    }\n\n    /**\n     * 下载对账单\n     *\n     * @param order 订单的请求体\n     * @return 返回支付方下载对账单的结果\n     */\n    @Override\n    public Map<String, Object> downloadBill(MerchantQueryOrder order) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(order.getDetailsId());\n\n        return details.getPayService().downloadBill(order.getBillDate(), order.getBillType());\n    }\n\n\n    /**\n     * 转账\n     *\n     * @param detailsId 列表id\n     * @param order     转账订单\n     * @return 对应的转账结果\n     */\n    @Override\n    public Map<String, Object> transfer(String detailsId, TransferOrder order) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(detailsId);\n\n        return details.getPayService().transfer(order);\n    }\n\n    /**\n     * 转账查询\n     *\n     * @param detailsId 列表id\n     * @param outNo     商户转账订单号\n     * @param tradeNo   支付平台转账订单号\n     * @return 对应的转账订单\n     */\n    @Override\n    public Map<String, Object> transferQuery(String detailsId, String outNo, String tradeNo) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(detailsId);\n        return details.getPayService().transferQuery(outNo, tradeNo);\n    }\n\n    /**\n     * 转账查询\n     *\n     * @param detailsId   列表id\n     * @param assistOrder 辅助交易订单\n     * @return 对应的转账订单\n     */\n    @Override\n    public Map<String, Object> transferQuery(String detailsId, AssistOrder assistOrder) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(detailsId);\n        PayService payService = details.getPayService();\n        if (payService instanceof TransferService) {\n            return ((TransferService) payService).transferQuery(assistOrder);\n        }\n        //todo: 暂时兼容旧版本\n        return details.getPayService().transferQuery(assistOrder.getOutTradeNo(), assistOrder.getTradeNo());\n    }\n\n    /**\n     * 创建消息\n     *\n     * @param detailsId 列表id\n     * @param message   支付平台返回的消息\n     * @return 支付消息对象\n     */\n    @Override\n    public PayMessage createMessage(String detailsId, Map<String, Object> message) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(detailsId);\n        return details.getPayService().createMessage(message);\n    }\n\n    /**\n     * 获取payService具体调用类引用\n     *\n     * @param detailsId       列表id\n     * @param payServiceClass payService类\n     * @return 具体调用类引用\n     */\n    @Override\n    public <T extends PayService> T cast(String detailsId, Class<T> payServiceClass) {\n        PaymentPlatformMerchantDetails details = detailsService.loadMerchantByMerchantId(detailsId);\n        return (T) details.getPayService();\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/PayBuilder.java",
    "content": "package com.egzosn.pay.spring.boot.core;\n\n/**\n * 用于构建对象的接口\n *\n * @param <O> 正在构建的对象的类型\n\n * @author egan\n *         <pre>\n *              email egzosn@gmail.com\n *\n *              date 2019/05/06 19:27.\n *         </pre>\n */\npublic interface PayBuilder<O> {\n\n\n    /**\n     * 构建对象并返回它或null。\n     *\n     * @return 如果实现允许，则要构建的对象或null。\n     */\n    O build();\n}"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/PayConfigurerAdapter.java",
    "content": "package com.egzosn.pay.spring.boot.core;\n\n/**\n * 支付配置适配，主要用于外部调用者链式的方式创建对象\n * @author egan\n *         <pre>\n *              email egzosn@gmail.com\n *\n *              date 2019/5/6 19:43.\n *         </pre>\n * @param <B> 返回对应的服务构建器\n */\npublic interface PayConfigurerAdapter<B> {\n\n    /**\n     * 外部调用者使用，链式的做法\n     *\n     * @return 返回对应外部调用者\n     */\n    B and();\n\n    /**\n     * 获取构建器\n     * @return 构建器\n     */\n    B getBuilder();\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/PayServiceConfigurer.java",
    "content": "package com.egzosn.pay.spring.boot.core;\n\nimport com.egzosn.pay.spring.boot.core.configurers.MerchantDetailsServiceConfigurer;\nimport com.egzosn.pay.spring.boot.core.configurers.PayMessageConfigurer;\n\n/**\n * 支付服务配置，用于支付服务相关的配置，暂时主要为商户相关的配置，后期在进行添加别的配置\n * @author egan\n *         <pre>\n *              email egzosn@gmail.com\n *\n *              date 2019/5/8 19:06.\n *         </pre>\n */\npublic interface PayServiceConfigurer {\n\n    /**\n     * 商户配置\n     * @param configurer 商户配置\n     */\n    void configure(MerchantDetailsServiceConfigurer configurer);\n    /**\n     * 商户配置\n     * @param configurer 支付消息配置\n     */\n    void configure(PayMessageConfigurer configurer) ;\n\n\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/PayServiceManager.java",
    "content": "package com.egzosn.pay.spring.boot.core;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.Map;\n\nimport com.egzosn.pay.common.api.PayMessageInterceptor;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.AssistOrder;\nimport com.egzosn.pay.common.bean.NoticeParams;\nimport com.egzosn.pay.common.bean.NoticeRequest;\nimport com.egzosn.pay.common.bean.PayMessage;\nimport com.egzosn.pay.common.bean.RefundOrder;\nimport com.egzosn.pay.common.bean.RefundResult;\nimport com.egzosn.pay.common.bean.TransferOrder;\nimport com.egzosn.pay.spring.boot.core.bean.MerchantPayOrder;\nimport com.egzosn.pay.spring.boot.core.bean.MerchantQueryOrder;\n\n\n/**\n * 商户支付服务\n *\n * @author egan\n * <pre>\n * email egzosn@gmail.com\n *\n * date 020/1/2 15:03\n * </pre>\n */\npublic interface PayServiceManager {\n\n    /**\n     * 回调校验\n     *\n     * @param detailsId 商户列表id\n     * @param params    回调回来的参数集\n     * @return 签名校验 true通过\n     */\n\n    @Deprecated\n    boolean verify(String detailsId, Map<String, Object> params);\n\n    /**\n     * 回调校验\n     *\n     * @param detailsId 商户列表id\n     * @param params    回调回来的参数集\n     * @return 签名校验 true通过\n     */\n    boolean verify(String detailsId, NoticeParams params);\n\n    /**\n     * 将请求参数或者请求流转化为 Map\n     *\n     * @param detailsId    商户列表id\n     * @param parameterMap 请求参数\n     * @param is           请求流\n     * @return 获得回调的请求参数\n     * @see #getNoticeParams(String, NoticeRequest)\n     */\n    @Deprecated\n    Map<String, Object> getParameter2Map(String detailsId, Map<String, String[]> parameterMap, InputStream is);\n\n    /**\n     * 将请求参数或者请求流转化为 Map\n     *\n     * @param detailsId 商户列表id\n     * @param request   通知请求\n     * @return 获得回调的请求参数\n     */\n    NoticeParams getNoticeParams(String detailsId, NoticeRequest request);\n\n    /**\n     * 跳到支付页面\n     * 针对实时支付,即时付款\n     *\n     * @param payOrder 商户支付订单信息\n     * @return 跳到支付页面\n     */\n    String toPay(MerchantPayOrder payOrder);\n\n    /**\n     * 获取支付预订单信息\n     *\n     * @param payOrder 商户支付订单信息\n     * @return 支付预订单信息\n     */\n    Map<String, Object> app(MerchantPayOrder payOrder);\n\n    /**\n     * 获取支付预订单信息\n     *\n     * @param payOrder 商户支付订单信息\n     * @return 支付预订单信息\n     */\n    Map<String, Object> getOrderInfo(MerchantPayOrder payOrder);\n\n    /**\n     * 刷卡付,pos主动扫码付款(条码付)\n     * 刷脸付\n     *\n     * @param payOrder 商户支付订单信息\n     * @return 支付结果\n     */\n    Map<String, Object> microPay(MerchantPayOrder payOrder);\n\n    /**\n     * 获取二维码图像\n     * 二维码支付\n     *\n     * @param payOrder 商户支付订单信息\n     * @return 二维码图像\n     * @throws IOException IOException\n     */\n    byte[] toQrPay(MerchantPayOrder payOrder) throws IOException;\n\n    /**\n     * 获取二维码信息\n     * 二维码支付\n     *\n     * @param payOrder 商户支付订单信息\n     * @return 二维码信息\n     */\n    String getQrPay(MerchantPayOrder payOrder);\n\n    /**\n     * 支付回调地址\n     * 方式二\n     *\n     * @param detailsId    商户列表id\n     * @param parameterMap 请求参数\n     * @param is           请求流\n     * @return 支付是否成功\n     * @throws IOException IOException\n     *                     拦截器相关增加， 详情查看{@link com.egzosn.pay.common.api.PayService#addPayMessageInterceptor(PayMessageInterceptor)}\n     *                     <p>\n     *                     业务处理在对应的PayMessageHandler里面处理，在哪里设置PayMessageHandler，详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)}\n     *                     </p>\n     *                     如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler}\n     */\n    @Deprecated\n    String payBack(String detailsId, Map<String, String[]> parameterMap, InputStream is) throws IOException;\n\n    /**\n     * 支付回调地址\n     * 方式二\n     *\n     * @param detailsId 商户列表id\n     * @param request   请求参数\n     * @return 支付是否成功\n     * 拦截器相关增加， 详情查看{@link com.egzosn.pay.common.api.PayService#addPayMessageInterceptor(PayMessageInterceptor)}\n     * <p>\n     * 业务处理在对应的PayMessageHandler里面处理，在哪里设置PayMessageHandler，详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)}\n     * </p>\n     * 如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler}\n     */\n    String payBack(String detailsId, NoticeRequest request);\n\n    /**\n     * 查询\n     *\n     * @param order 订单的请求体\n     * @return 返回查询回来的结果集，支付方原值返回\n     */\n    Map<String, Object> query(MerchantQueryOrder order);\n\n    /**\n     * 交易关闭接口\n     *\n     * @param order 订单的请求体\n     * @return 返回支付方交易关闭后的结果\n     */\n    Map<String, Object> close(MerchantQueryOrder order);\n\n    /**\n     * 申请退款接口\n     *\n     * @param detailsId 列表id\n     * @param order     订单的请求体\n     * @return 返回支付方申请退款后的结果\n     */\n\n    RefundResult refund(String detailsId, RefundOrder order);\n\n    /**\n     * 查询退款\n     *\n     * @param detailsId 列表id\n     * @param order     订单的请求体\n     * @return 返回支付方查询退款后的结果\n     */\n    Map<String, Object> refundQuery(String detailsId, RefundOrder order);\n\n    /**\n     * 下载对账单\n     *\n     * @param order 订单的请求体\n     * @return 返回支付方下载对账单的结果\n     */\n    Map<String, Object> downloadBill(MerchantQueryOrder order);\n\n\n    /**\n     * 转账\n     *\n     * @param detailsId 列表id\n     * @param order     转账订单\n     * @return 对应的转账结果\n     */\n    Map<String, Object> transfer(String detailsId, TransferOrder order);\n\n    /**\n     * 转账查询\n     *\n     * @param detailsId 列表id\n     * @param outNo     商户转账订单号\n     * @param tradeNo   支付平台转账订单号\n     * @return 对应的转账订单\n     * @deprecated {@link #transferQuery(String, AssistOrder)}\n     */\n    @Deprecated\n    Map<String, Object> transferQuery(String detailsId, String outNo, String tradeNo);\n\n\n    /**\n     * 转账查询\n     *\n     * @param detailsId   列表id\n     * @param assistOrder 辅助交易订单\n     * @return 对应的转账订单\n     */\n    Map<String, Object> transferQuery(String detailsId, AssistOrder assistOrder);\n\n    /**\n     * 创建消息\n     *\n     * @param detailsId 列表id\n     * @param message   支付平台返回的消息\n     * @return 支付消息对象\n     */\n    PayMessage createMessage(String detailsId, Map<String, Object> message);\n\n\n    /**\n     * 获取payService具体调用类引用\n     *\n     * @param detailsId       列表id\n     * @param payServiceClass payService类\n     * @param <T>             支付服务类引用\n     * @return 具体调用类引用\n     */\n    <T extends PayService> T cast(String detailsId, Class<T> payServiceClass);\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/bean/MerchantPayOrder.java",
    "content": "package com.egzosn.pay.spring.boot.core.bean;\n\nimport com.egzosn.pay.common.bean.PayOrder;\nimport com.egzosn.pay.common.bean.TransactionType;\n\nimport java.math.BigDecimal;\n\n/**\n * 商户支付订单\n * @author egan\n *         <pre>\n *                 email egzosn@gmail.com\n *\n *                 date 2019/5/9 19:43.\n *                 </pre>\n */\npublic class MerchantPayOrder extends PayOrder {\n\n    /**\n     * 列表id\n     */\n    private String  detailsId;\n    /**\n     * 交易类型，交易方式，\n     * 本字段与{@link com.egzosn.pay.common.bean.PayOrder#getTransactionType()}相同。\n     *\n     *  例如，网页支付，扫码付等等\n     */\n    private String wayTrade;\n\n    public MerchantPayOrder() {\n    }\n\n    public MerchantPayOrder(String detailsId, String wayTrade) {\n        this.detailsId = detailsId;\n        this.wayTrade = wayTrade;\n    }\n\n\n\n    public MerchantPayOrder(String detailsId, String wayTrade, String subject, String body, BigDecimal price, String outTradeNo) {\n        super(subject, body, price, outTradeNo);\n        this.detailsId = detailsId;\n        this.wayTrade = wayTrade;\n    }\n\n    public String getDetailsId() {\n        return detailsId;\n    }\n\n    public void setDetailsId(String detailsId) {\n        this.detailsId = detailsId;\n    }\n\n    public String getWayTrade() {\n        return wayTrade;\n    }\n\n    public void setWayTrade(String wayTrade) {\n        this.wayTrade = wayTrade;\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/bean/MerchantQueryOrder.java",
    "content": "package com.egzosn.pay.spring.boot.core.bean;\n\nimport com.egzosn.pay.common.bean.AssistOrder;\nimport com.egzosn.pay.common.bean.BillType;\n\nimport java.math.BigDecimal;\nimport java.util.Date;\n\n/**\n * 订单辅助接口\n *\n * @author egan\n * email egzosn@gmail.com\n * date 2017/3/12 14:50\n */\npublic class MerchantQueryOrder extends AssistOrder {\n    /**\n     * 列表id\n     */\n    private String detailsId;\n    /**\n     * 退款金额\n     */\n    private BigDecimal refundAmount;\n    /**\n     * 总金额\n     */\n    private BigDecimal totalAmount;\n    /**\n     * 账单时间：具体请查看对应支付平台\n     */\n    private Date billDate;\n    /**\n     * 账单类型：具体请查看对应支付平台\n     * 详情实现查看各个平台组件对应实现类\n     */\n    private BillType billType;\n    /**\n     * 支付平台订单号或者账单日期\n     */\n    private Object tradeNoOrBillDate;\n    /**\n     * 商户单号或者 账单类型\n     */\n    private String outTradeNoBillType;\n    /**\n     * 交易类型，交易方式，\n     * 本字段与{@link com.egzosn.pay.common.bean.PayOrder#getTransactionType}相同。\n     * <p>\n     * 例如，网页支付，扫码付等等\n     */\n    private String wayTrade;\n\n    public String getDetailsId() {\n        return detailsId;\n    }\n\n    public void setDetailsId(String detailsId) {\n        this.detailsId = detailsId;\n    }\n\n    public BigDecimal getRefundAmount() {\n        return refundAmount;\n    }\n\n    public void setRefundAmount(BigDecimal refundAmount) {\n        this.refundAmount = refundAmount;\n    }\n\n    public BigDecimal getTotalAmount() {\n        return totalAmount;\n    }\n\n    public void setTotalAmount(BigDecimal totalAmount) {\n        this.totalAmount = totalAmount;\n    }\n\n    public Date getBillDate() {\n        return billDate;\n    }\n\n    public void setBillDate(Date billDate) {\n        this.billDate = billDate;\n    }\n\n    public BillType getBillType() {\n        return billType;\n    }\n\n    public void setBillType(BillType billType) {\n        this.billType = billType;\n    }\n\n    public Object getTradeNoOrBillDate() {\n        return tradeNoOrBillDate;\n    }\n\n    public void setTradeNoOrBillDate(Object tradeNoOrBillDate) {\n        this.tradeNoOrBillDate = tradeNoOrBillDate;\n    }\n\n    public String getOutTradeNoBillType() {\n        return outTradeNoBillType;\n    }\n\n    public void setOutTradeNoBillType(String outTradeNoBillType) {\n        this.outTradeNoBillType = outTradeNoBillType;\n    }\n\n    public String getWayTrade() {\n        return wayTrade;\n    }\n\n    public void setWayTrade(String wayTrade) {\n        this.wayTrade = wayTrade;\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/builders/InMemoryMerchantDetailsServiceBuilder.java",
    "content": "package com.egzosn.pay.spring.boot.core.builders;\n\nimport com.egzosn.pay.spring.boot.core.configurers.PayMessageConfigurer;\nimport com.egzosn.pay.spring.boot.core.merchant.MerchantDetailsService;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.merchant.bean.*;\nimport com.egzosn.pay.spring.boot.core.provider.InMemoryMerchantDetailsManager;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 内存型商户列表服务构建器\n * @author egan\n *         <pre>\n *         email egzosn@gmail.com\n *         date  2019/5/6 19:36.\n *         </pre>\n */\npublic class InMemoryMerchantDetailsServiceBuilder extends MerchantDetailsServiceBuilder {\n\n    private List<PaymentPlatformMerchantDetails> merchantDetails = new ArrayList<PaymentPlatformMerchantDetails>();\n\n\n\n    public void addMerchantDetails(PaymentPlatformMerchantDetails merchantDetail) {\n\n        this.merchantDetails.add(merchantDetail);\n    }\n\n    public AliMerchantDetails ali(){\n        AliMerchantDetails details = new AliMerchantDetails(this);\n        addMerchantDetails(details);\n        return details;\n    }\n\n    public FuiouMerchantDetails fuiou(){\n        FuiouMerchantDetails details = new FuiouMerchantDetails(this);\n        addMerchantDetails(details);\n        return details;\n    }\n    public PayoneerMerchantDetails payoneer(){\n        PayoneerMerchantDetails details = new PayoneerMerchantDetails(this);\n        addMerchantDetails(details);\n        return details;\n    }\n    public PaypalMerchantDetails payPal(){\n        PaypalMerchantDetails details = new PaypalMerchantDetails(this);\n        addMerchantDetails(details);\n        return details;\n    }\n    public UnionMerchantDetails union(){\n        UnionMerchantDetails details = new UnionMerchantDetails(this);\n        addMerchantDetails(details);\n        return details;\n    }\n    public WxMerchantDetails wx(){\n        WxMerchantDetails details = new WxMerchantDetails(this);\n        addMerchantDetails(details);\n        return details;\n    }\n\n    public WxV3MerchantDetails wxV3(){\n        WxV3MerchantDetails details = new WxV3MerchantDetails(this);\n        addMerchantDetails(details);\n        return details;\n    }\n\n\n    /**\n     * 开始构建\n     *\n     * @return 商户列表服务\n     */\n    @Override\n    protected MerchantDetailsService performBuild() {\n        InMemoryMerchantDetailsManager merchantDetailsManager = new InMemoryMerchantDetailsManager();\n        merchantDetailsManager.setPayMessageConfigurer(configurer);\n        merchantDetailsManager.createMerchant(merchantDetails);\n        return merchantDetailsManager;\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/builders/JdbcMerchantDetailsServiceBuilder.java",
    "content": "package com.egzosn.pay.spring.boot.core.builders;\n\nimport javax.sql.DataSource;\n\nimport org.springframework.jdbc.core.JdbcTemplate;\n\nimport com.egzosn.pay.spring.boot.core.merchant.MerchantDetailsService;\nimport com.egzosn.pay.spring.boot.core.provider.CacheMerchantDetailsManager;\nimport com.egzosn.pay.spring.boot.core.provider.JdbcMerchantDetailsManager;\nimport com.egzosn.pay.spring.boot.core.provider.MerchantDetailsManager;\n\n/**\n * 内存型商户列表服务构建器\n *\n * @author egan\n * <pre>\n *         email egzosn@gmail.com\n *         date  2019/5/6 19:36.\n *         </pre>\n */\npublic class JdbcMerchantDetailsServiceBuilder extends MerchantDetailsServiceBuilder {\n\n    private JdbcTemplate jdbcTemplate;\n\n    private boolean cache = false;\n\n\n    public JdbcMerchantDetailsServiceBuilder(DataSource source) {\n        setJdbcTemplate(new JdbcTemplate(source));\n    }\n\n    public JdbcMerchantDetailsServiceBuilder(JdbcTemplate jdbcTemplate) {\n        this.jdbcTemplate = jdbcTemplate;\n    }\n\n    public JdbcMerchantDetailsServiceBuilder(boolean cache) {\n        this.cache = cache;\n    }\n\n    public JdbcMerchantDetailsServiceBuilder() {\n    }\n\n\n    /**\n     * 设置缓存\n     *\n     * @param cache 缓存\n     * @return 当前\n     */\n    public JdbcMerchantDetailsServiceBuilder cache(boolean cache) {\n        setCache(cache);\n        return this;\n    }\n\n    /**\n     * 设置jdbc 模版\n     *\n     * @param jdbcTemplate jdbcTemplate\n     * @return 当前\n     */\n    public JdbcMerchantDetailsServiceBuilder template(JdbcTemplate jdbcTemplate) {\n        setJdbcTemplate(jdbcTemplate);\n        return this;\n    }\n\n\n    /**\n     * 设置数据源\n     *\n     * @param source 数据源\n     * @return 当前\n     */\n    public JdbcMerchantDetailsServiceBuilder dataSource(DataSource source) {\n        setJdbcTemplate(new JdbcTemplate(source));\n        return this;\n    }\n\n    public JdbcTemplate getJdbcTemplate() {\n        return jdbcTemplate;\n    }\n\n    private void setJdbcTemplate(JdbcTemplate jdbcTemplate) {\n        if (null != this.jdbcTemplate) {\n            return;\n        }\n        this.jdbcTemplate = jdbcTemplate;\n    }\n\n    public boolean isCache() {\n        return cache;\n    }\n\n    public void setCache(boolean cache) {\n        this.cache = cache;\n    }\n\n    /**\n     * 开始构建\n     *\n     * @return 商户列表服务·\n     */\n    @Override\n    protected MerchantDetailsService performBuild() {\n\n        MerchantDetailsManager manager = new JdbcMerchantDetailsManager(jdbcTemplate);\n        if (cache) {\n            manager = new CacheMerchantDetailsManager(manager);\n        }\n        manager.setPayMessageConfigurer(configurer);\n\n        return manager;\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/builders/MerchantDetailsServiceBuilder.java",
    "content": "package com.egzosn.pay.spring.boot.core.builders;\n\nimport javax.sql.DataSource;\n\nimport org.springframework.jdbc.core.JdbcTemplate;\n\nimport com.egzosn.pay.spring.boot.core.PayBuilder;\nimport com.egzosn.pay.spring.boot.core.configurers.PayMessageConfigurer;\nimport com.egzosn.pay.spring.boot.core.merchant.MerchantDetailsService;\n\n/**\n * @author egan\n * <pre>\n *         email egzosn@gmail.com\n *         date  2019/5/6 19:36.\n *         </pre>\n */\npublic class MerchantDetailsServiceBuilder implements PayBuilder<MerchantDetailsService> {\n    protected PayMessageConfigurer configurer;\n\n    public static InMemoryMerchantDetailsServiceBuilder inMemory() {\n        return new InMemoryMerchantDetailsServiceBuilder();\n    }\n\n    public static JdbcMerchantDetailsServiceBuilder jdbc() {\n        return new JdbcMerchantDetailsServiceBuilder();\n    }\n\n    public static JdbcMerchantDetailsServiceBuilder jdbc(boolean cache) {\n        return new JdbcMerchantDetailsServiceBuilder();\n    }\n\n    public static JdbcMerchantDetailsServiceBuilder jdbc(DataSource source) {\n        return new JdbcMerchantDetailsServiceBuilder(source);\n    }\n\n    public static JdbcMerchantDetailsServiceBuilder jdbc(JdbcTemplate jdbcTemplate) {\n        return new JdbcMerchantDetailsServiceBuilder(jdbcTemplate);\n    }\n\n    /**\n     * 构建对象并返回它或null。\n     *\n     * @return 如果实现允许，则要构建的对象或null。\n     */\n    @Override\n    public MerchantDetailsService build() {\n        return performBuild();\n    }\n\n    /**\n     * 开始构建\n     *\n     * @return 商户列表服务\n     */\n    protected MerchantDetailsService performBuild() {\n        throw new UnsupportedOperationException(\"无法构建商家服务(需要使用inMemory()或jdbc())\");\n    }\n\n    public void setConfigurer(PayMessageConfigurer configurer) {\n        this.configurer = configurer;\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/configurers/DefalutPayMessageConfigurer.java",
    "content": "package com.egzosn.pay.spring.boot.core.configurers;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.egzosn.pay.common.api.PayMessageHandler;\nimport com.egzosn.pay.common.api.PayMessageInterceptor;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.PayMessage;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\n\n/**\n * 支付回调配置中心\n * @author egan\n * <pre>\n *         email egzosn@gmail.com\n *         date 2019/9/7.22:08\n *</pre>\n */\npublic class DefalutPayMessageConfigurer implements PayMessageConfigurer {\n\n    /**\n     * 消息处理器集\n     *\n     * key 为商户平台\n     * value 为对应得处理器\n     */\n    private Map<PaymentPlatform, PayMessageHandler<PayMessage, PayService>> handlers = new HashMap<PaymentPlatform, PayMessageHandler<PayMessage, PayService>>();\n\n    /**\n     * 消息拦截器集\n     *\n     * key 为商户平台\n     * value 为对应得拦截器\n     */\n    private Map<PaymentPlatform, List<PayMessageInterceptor<PayMessage, PayService>>> interceptors = new HashMap<PaymentPlatform, List<PayMessageInterceptor<PayMessage, PayService>>>();\n\n    /**\n     * 添加处理器\n     *\n     * @param platform 商户平台，渠道\n     * @param handler  处理器\n     */\n    @Override\n    public void addHandler(PaymentPlatform platform, PayMessageHandler handler) {\n        if (handlers.containsKey(platform)){\n            throw new IllegalArgumentException(platform.getPlatform() + \"已存在，请勿重复设置\");\n        }\n        this.handlers.put(platform, handler);\n    }\n\n    /**\n     * 获取处理器\n     *\n     * @param platform 商户平台，渠道\n     * @return 处理器\n     */\n    @Override\n    public PayMessageHandler<PayMessage, PayService> getHandler(PaymentPlatform platform) {\n        return handlers.get(platform);\n    }\n    /**\n     * 添加拦截器\n     *\n     * @param platform    商户平台，渠道\n     * @param interceptor 拦截器\n     */\n    @Override\n    public void addInterceptor(PaymentPlatform platform, PayMessageInterceptor interceptor) {\n        List<PayMessageInterceptor<PayMessage, PayService>> interceptors = this.interceptors.get(platform);\n        if (null == interceptors){\n            interceptors = new ArrayList<>();\n            this.interceptors.put(platform, interceptors);\n        }\n        interceptors.add(interceptor);\n    }\n\n    /**\n     * 获取拦截器\n     *\n     * @param platform 商户平台，渠道\n     * @return 拦截器\n     */\n    @Override\n    public List<PayMessageInterceptor<PayMessage, PayService>> getInterceptor(PaymentPlatform platform) {\n        return interceptors.get(platform);\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/configurers/MerchantDetailsServiceConfigurer.java",
    "content": "package com.egzosn.pay.spring.boot.core.configurers;\n\n\nimport com.egzosn.pay.spring.boot.core.PayConfigurerAdapter;\nimport com.egzosn.pay.spring.boot.core.builders.InMemoryMerchantDetailsServiceBuilder;\nimport com.egzosn.pay.spring.boot.core.builders.JdbcMerchantDetailsServiceBuilder;\nimport com.egzosn.pay.spring.boot.core.builders.MerchantDetailsServiceBuilder;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\nimport javax.sql.DataSource;\n\n/**\n * 商户列表服务配置\n *\n * @author egan\n * <pre>\n *      email egzosn@gmail.com\n *\n *      date 2019/5/8 19:54.\n * </pre>\n */\npublic class MerchantDetailsServiceConfigurer implements PayConfigurerAdapter<MerchantDetailsServiceBuilder> {\n\n    private MerchantDetailsServiceBuilder builder;\n\n    @Autowired\n    private PayMessageConfigurer configurer;\n\n    public void setBuilder(MerchantDetailsServiceBuilder builder) {\n        this.builder = builder;\n    }\n\n    public InMemoryMerchantDetailsServiceBuilder inMemory() {\n        InMemoryMerchantDetailsServiceBuilder builder = MerchantDetailsServiceBuilder.inMemory();\n        initBuilder(builder);\n        return builder;\n    }\n    public MerchantDetailsServiceBuilder initBuilder(MerchantDetailsServiceBuilder builder) {\n        builder.setConfigurer(this.configurer);\n        setBuilder(builder);\n        return builder;\n    }\n\n\n    public JdbcMerchantDetailsServiceBuilder jdbc() {\n        JdbcMerchantDetailsServiceBuilder builder = MerchantDetailsServiceBuilder.jdbc();\n        initBuilder(builder);\n        return builder;\n    }\n\n    public JdbcMerchantDetailsServiceBuilder jdbc(DataSource source) {\n        JdbcMerchantDetailsServiceBuilder builder = MerchantDetailsServiceBuilder.jdbc(source);\n        initBuilder(builder);\n        return builder;\n    }\n\n    /**\n     *\n     * 将在未来可能进行移除，避免项目不用JdbcTemplate最为数据源操作并且不需要引入JdbcTemplate包时导致的不必要报错\n     *\n     *  替代方式{@link #jdbc()}与{@link #jdbc(DataSource)}进行替代\n     *  <code>\n     *      jdbc().template(JdbcTemplate);\n     *  </code>\n     * @param jdbcTemplate jdbc模版\n     * @return jdbc商户列表服务构建器\n     */\n    @Deprecated\n    public JdbcMerchantDetailsServiceBuilder jdbc(JdbcTemplate jdbcTemplate) {\n        JdbcMerchantDetailsServiceBuilder builder = MerchantDetailsServiceBuilder.jdbc(jdbcTemplate);\n        initBuilder(builder);\n        return builder;\n    }\n\n\n    /**\n     * 外部调用者使用，链式的做法\n     *\n     * @return 返回对应外部调用者\n     */\n    @Override\n    public MerchantDetailsServiceBuilder and() {\n        return getBuilder();\n    }\n\n    /**\n     * 获取构建器\n     *\n     * @return 构建器\n     */\n    @Override\n    public MerchantDetailsServiceBuilder getBuilder() {\n        return builder;\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/configurers/PayMessageConfigurer.java",
    "content": "package com.egzosn.pay.spring.boot.core.configurers;\n\nimport com.egzosn.pay.common.api.PayMessageHandler;\nimport com.egzosn.pay.common.api.PayMessageInterceptor;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.PayMessage;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\n\nimport java.util.List;\n\n/**\n * @author egan\n * <pre>\n *         email egzosn@gmail.com\n *         date 2019/9/7.23:54\n * </pre>\n */\npublic interface PayMessageConfigurer {\n\n    /**\n     * 添加处理器\n     *\n     * @param platform 商户平台，渠道\n     * @param handler  处理器\n     */\n    void addHandler(PaymentPlatform platform, PayMessageHandler handler);\n\n    /**\n     * 获取处理器\n     *\n     * @param platform 商户平台，渠道\n     * @return 处理器\n     */\n    PayMessageHandler<PayMessage, PayService> getHandler(PaymentPlatform platform);\n\n    /**\n     * 添加拦截器\n     *\n     * @param platform    商户平台，渠道\n     * @param interceptor 拦截器\n     */\n    void addInterceptor(PaymentPlatform platform, PayMessageInterceptor interceptor);\n\n    /**\n     * 获取拦截器\n     *\n     * @param platform 商户平台，渠道\n     * @return 拦截器\n     */\n    List<PayMessageInterceptor<PayMessage, PayService>> getInterceptor(PaymentPlatform platform);\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/MerchantDetails.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant;\n\nimport com.egzosn.pay.common.api.PayConfigStorage;\n\nimport java.io.Serializable;\n\n/**\n * 商户信息列表\n *\n * @author egan\n *         <pre>\n *                 email egzosn@gmail.com\n *                 date 2018/12/29 11:03.\n *                 </pre>\n */\npublic interface MerchantDetails extends PayConfigStorage, Serializable {\n\n\n    /**\n     * 获取支付商户详细信息id\n     *\n     * @return 支付商户详细信息id\n     */\n    String getDetailsId();\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/MerchantDetailsService.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant;\n\n/**\n *  提供给客户端获取商户列表信息的服务\n *\n * @author egan\n *         <pre>\n *         email egzosn@gmail.com\n *         date 2018-12-29 10:53:08\n *         </pre>\n */\npublic interface MerchantDetailsService<T extends MerchantDetails> {\n\n    /**\n     *  通过支付商户id加载对应的商户信息列表\n     * @param merchantId  支付商户id\n     * @return 商户信息列表\n     */\n    T loadMerchantByMerchantId(String merchantId);\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/MerchantNotFoundException.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant;\n\n/**\n * 商户不存在异常\n * @author egan\n *         <pre>\n *         email egzosn@gmail.com\n *         date  2019/4/6 16:43.\n *         </pre>\n */\n\npublic class MerchantNotFoundException extends RuntimeException {\n\n    /**\n     * 商户列表id\n     */\n    private String detailsId;\n    private static final String MESSAGE = \"不存在的商户列表id：\";\n\n    /**\n     *\n     * @param detailsId 商户列表id\n     */\n    public MerchantNotFoundException(String detailsId) {\n        this(MESSAGE + detailsId, null);\n    }\n\n    /**\n     * @param detailsId 商户列表id\n     * @param cause 异常\n     */\n    public MerchantNotFoundException(String detailsId, Throwable cause) {\n        super(MESSAGE + detailsId, cause);\n        this.detailsId = detailsId;\n    }\n\n    /**\n     * 获取商户id\n     * @return 商户id\n     */\n    public String getMerchantId(){\n        return detailsId;\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/PaymentPlatform.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant;\n\nimport com.egzosn.pay.common.api.PayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.BasePayType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\n\n/**\n * 支付平台\n * @author egan\n *         <pre>\n *         email egzosn@gmail.com\n *         date  2019/4/6 17:20.\n *         </pre>\n */\npublic interface PaymentPlatform<S extends PayService> extends BasePayType {\n\n    /**\n     * 获取商户平台\n     * @return 商户平台\n     */\n    String getPlatform();\n\n    /**\n     * 获取支付平台对应的支付服务\n     * @param payConfigStorage 支付配置\n     * @return 支付服务\n     */\n    S getPayService(PayConfigStorage payConfigStorage);\n    /**\n     * 获取支付平台对应的支付服务\n     * @param payConfigStorage 支付配置\n     * @param httpConfigStorage 网络配置\n     * @return 支付服务\n     */\n    S getPayService(PayConfigStorage payConfigStorage, HttpConfigStorage httpConfigStorage);\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/PaymentPlatformMerchantDetails.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant;\n\nimport com.egzosn.pay.common.api.PayService;\n\n/**\n * 支付平台商户列表\n * @author egan\n *         <pre>\n *         email egzosn@gmail.com\n *         date 2019/4/6 17:28.\n *         </pre>\n */\npublic interface PaymentPlatformMerchantDetails<S extends PayService>  extends MerchantDetails{\n\n    /**\n     * 获取支付平台对应的支付服务\n     * @return 支付服务\n     */\n    S getPayService();\n    /**\n     * 获取支付平台\n     * @return 支付平台\n     */\n    PaymentPlatform getPaymentPlatform();\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/PaymentPlatformServiceAdapter.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant;\n\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\n\n/**\n * 支付商户服务适配器\n * @author egan\n *         <pre>\n *                 email egzosn@gmail.com\n *\n *                 date 2019/5/9 19:28.\n *                 </pre>\n */\npublic interface PaymentPlatformServiceAdapter<S extends PayService> {\n\n    /**\n     * 初始化服务\n     * @return 支付商户服务适配器\n     */\n    PaymentPlatformServiceAdapter initService();\n\n    /**\n     * 获取支付平台对应的支付服务\n     * @return 支付服务\n     */\n    S getPayService();\n\n\n\n    /**\n     * 获取HTTP请求配置\n     * @return HTTP请求配置\n     */\n    HttpConfigStorage getHttpConfigStorage();\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/bean/AliMerchantDetails.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant.bean;\n\nimport com.egzosn.pay.ali.api.AliPayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.spring.boot.core.PayConfigurerAdapter;\nimport com.egzosn.pay.spring.boot.core.builders.InMemoryMerchantDetailsServiceBuilder;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformServiceAdapter;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.AliPaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaymentPlatforms;\n\n/**\n * 支付宝商户信息列表\n *\n * @author egan\n * <pre>\n *                         email egzosn@gmail.com\n *                         date   2019/4/6 14:30.\n *                         </pre>\n */\npublic class AliMerchantDetails extends AliPayConfigStorage implements PaymentPlatformMerchantDetails, PaymentPlatformServiceAdapter, PayConfigurerAdapter<InMemoryMerchantDetailsServiceBuilder> {\n\n\n    private String detailsId;\n\n    /**\n     * 商户对应的支付服务\n     */\n    private volatile PayService payService;\n\n    /**\n     * 商户平台\n     */\n    private PaymentPlatform platform;\n\n    private InMemoryMerchantDetailsServiceBuilder builder;\n    /**\n     * HTTP请求配置\n     */\n    private HttpConfigStorage httpConfigStorage;\n\n\n    /**\n     * 外部调用者使用，链式的做法\n     *\n     * @return 返回对应外部调用者\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder and() {\n        initService();\n        return getBuilder();\n    }\n\n    /**\n     * 获取构建器\n     *\n     * @return 构建器\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder getBuilder() {\n        return builder;\n    }\n\n    public AliMerchantDetails(InMemoryMerchantDetailsServiceBuilder builder) {\n        this();\n        this.builder = builder;\n    }\n\n    public AliMerchantDetails() {\n        init();\n    }\n\n    public void init() {\n        if (null != platform){\n            return;\n        }\n        String platformName = AliPaymentPlatform.platformName;\n        setPayType(platformName);\n        platform = PaymentPlatforms.getPaymentPlatform(platformName);\n    }\n\n    /**\n     * 获取支付平台\n     *\n     * @return 支付平台\n     */\n    @Override\n    public PaymentPlatform getPaymentPlatform() {\n\n        return platform;\n    }\n\n    /**\n     * 初始化服务\n     *\n     * @return 支付商户服务适配器\n     */\n    @Override\n    public PaymentPlatformServiceAdapter initService() {\n        init();\n        if (null == payService) {\n            payService = platform.getPayService(this, getHttpConfigStorage());\n        }\n        return this;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService() {\n        initService();\n        return payService;\n    }\n\n    /**\n     * 获取HTTP请求配置\n     *\n     * @return HTTP请求配置\n     */\n    @Override\n    public HttpConfigStorage getHttpConfigStorage() {\n        return httpConfigStorage;\n    }\n\n    public AliMerchantDetails httpConfigStorage(HttpConfigStorage httpConfigStorage) {\n        this.httpConfigStorage = httpConfigStorage;\n        return this;\n    }\n\n    public void setDetailsId(String detailsId) {\n        this.detailsId = detailsId;\n    }\n\n    /**\n     * 获取支付商户id\n     *\n     * @return 支付商户id\n     */\n    @Override\n    public String getDetailsId() {\n        return detailsId;\n    }\n\n    public AliMerchantDetails detailsId(String detailsId) {\n        this.detailsId = detailsId;\n        return this;\n    }\n\n    public AliMerchantDetails notifyUrl(String notifyUrl) {\n        setNotifyUrl(notifyUrl);\n        return this;\n    }\n\n    public AliMerchantDetails returnUrl(String returnUrl) {\n        setReturnUrl(returnUrl);\n        return this;\n    }\n\n    public AliMerchantDetails signType(String signType) {\n        setSignType(signType);\n        return this;\n    }\n\n    public AliMerchantDetails inputCharset(String inputCharset) {\n        setInputCharset(inputCharset);\n        return this;\n    }\n\n    public AliMerchantDetails test(boolean test) {\n        setTest(test);\n        return this;\n    }\n\n    public AliMerchantDetails pid(String pid) {\n        setPid(pid);\n        return this;\n    }\n\n    public AliMerchantDetails appid(String appid) {\n        setAppid(appid);\n        return this;\n    }\n\n    public AliMerchantDetails keyPrivate(String keyPrivate) {\n        setKeyPrivate(keyPrivate);\n        return this;\n    }\n\n    public AliMerchantDetails keyPublic(String keyPublic) {\n        setKeyPublic(keyPublic);\n        return this;\n    }\n\n    public AliMerchantDetails seller(String seller) {\n        setSeller(seller);\n        return this;\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/bean/CommonPaymentPlatformMerchantDetails.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant.bean;\n\nimport com.egzosn.pay.common.api.BasePayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.CertStoreType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.spring.boot.core.PayConfigurerAdapter;\nimport com.egzosn.pay.spring.boot.core.builders.MerchantDetailsServiceBuilder;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformServiceAdapter;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaymentPlatforms;\n\nimport java.io.IOException;\nimport java.io.InputStream;\n\n/**\n * 公共的支付商户信息列表\n *\n * @author egan\n * <pre>\n * email egzosn@gmail.com\n * date   2019/4/9 19:39.\n * </pre>\n */\npublic class CommonPaymentPlatformMerchantDetails extends BasePayConfigStorage implements PaymentPlatformMerchantDetails, PaymentPlatformServiceAdapter, PayConfigurerAdapter<MerchantDetailsServiceBuilder> {\n\n    private String detailsId;\n    private String appId;\n    private String mchId;\n    private String seller;\n    private String subAppId;\n    private String subMchId;\n    /**\n     * 证书（PKCS12）\n     */\n    private Object keystore;\n\n\n    /**\n     * 公钥证书\n     */\n    private Object keyPublicCert;\n    /**\n     * 证书，这里针对双证书校验， 银联的根级证书\n     */\n    private Object keyCert;\n    /**\n     * 应用私钥证书，rsa_private pkcs8格式 生成签名时使用\n     */\n    private String keyPrivateCertPwd;\n\n    /**\n     * 证书存储类型\n     */\n    private CertStoreType certStoreType;\n    /**\n     * 商户对应的支付服务\n     */\n    private volatile PayService payService;\n    /**\n     * 商户平台\n     */\n    private volatile PaymentPlatform platform;\n\n    private MerchantDetailsServiceBuilder builder;\n    /**\n     * HTTP请求配置\n     */\n    private HttpConfigStorage httpConfigStorage;\n\n\n    /**\n     * 外部调用者使用，链式的做法\n     *\n     * @return 返回对应外部调用者\n     */\n    @Override\n    public MerchantDetailsServiceBuilder and() {\n        return getBuilder();\n    }\n\n    /**\n     * 获取构建器\n     *\n     * @return 构建器\n     */\n    @Override\n    public MerchantDetailsServiceBuilder getBuilder() {\n        return builder;\n    }\n\n    public CommonPaymentPlatformMerchantDetails(MerchantDetailsServiceBuilder builder) {\n        this();\n        this.builder = builder;\n    }\n\n    public CommonPaymentPlatformMerchantDetails() {\n\n    }\n\n    /**\n     * 获取支付平台\n     *\n     * @return 支付平台\n     */\n    @Override\n    public PaymentPlatform getPaymentPlatform() {\n        if (null == platform){\n            platform = PaymentPlatforms.getPaymentPlatform(getPayType());\n        }\n        return platform;\n    }\n\n    /**\n     * 初始化服务\n     *\n     * @return 支付商户服务适配器\n     */\n    @Override\n    public PaymentPlatformServiceAdapter initService() {\n        getPaymentPlatform();\n        if (null == payService){\n            payService = platform.getPayService(this, getHttpConfigStorage());\n        }\n        return this;\n    }\n\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService() {\n        initService();\n        return payService;\n    }\n\n    /**\n     * 获取HTTP请求配置\n     *\n     * @return HTTP请求配置\n     */\n    @Override\n    public HttpConfigStorage getHttpConfigStorage() {\n        return httpConfigStorage;\n    }\n\n    public void setHttpConfigStorage(HttpConfigStorage httpConfigStorage) {\n        this.httpConfigStorage = httpConfigStorage;\n    }\n\n    public void setDetailsId(String detailsId) {\n        this.detailsId = detailsId;\n    }\n\n    /**\n     * 获取支付商户id\n     *\n     * @return 支付商户id\n     */\n    @Override\n    public String getDetailsId() {\n        return detailsId;\n    }\n\n\n    public void setAppId(String appId) {\n        this.appId = appId;\n    }\n\n    public String getMchId() {\n        return mchId;\n    }\n\n    public void setMchId(String mchId) {\n        this.mchId = mchId;\n    }\n\n    @Override\n    @Deprecated\n    public String getAppid() {\n        return appId;\n    }\n\n    /**\n     * 应用id\n     * 纠正名称\n     *\n     * @return 应用id\n     */\n    @Override\n    public String getAppId() {\n        return appId;\n    }\n\n    @Override\n    public String getPid() {\n        return mchId;\n    }\n\n    @Override\n    public String getSeller() {\n        return seller;\n    }\n\n    public void setSeller(String seller) {\n        this.seller = seller;\n    }\n\n    public String getSubAppId() {\n        return subAppId;\n    }\n\n    public void setSubAppId(String subAppId) {\n        this.subAppId = subAppId;\n    }\n\n    public String getSubMchId() {\n        return subMchId;\n    }\n\n    public void setSubMchId(String subMchId) {\n        this.subMchId = subMchId;\n    }\n\n\n    /**\n     * 设置私钥证书\n     *\n     * @param keystore 私钥证书地址 或者证书内容字符串\n     *                 私钥证书密码 {@link #setKeyPrivateCertPwd(String)}\n     */\n    public void setKeystore(String keystore) {\n        super.setKeyPrivate(keystore);\n        this.keystore = keystore;\n    }\n\n    /**\n     * 设置私钥证书\n     *\n     * @param keystore 私钥证书信息流\n     *                 私钥证书密码 {@link #setKeyPrivateCertPwd(String)}\n     */\n    public void setKeystore(InputStream keystore) {\n        this.keystore = keystore;\n    }\n\n    public InputStream getKeystoreInputStream() throws IOException {\n        return certStoreType.getInputStream(keystore);\n    }\n\n    public Object getKeystore() {\n        return keystore;\n    }\n\n    public String getKeystorePwd() {\n        return getKeyPrivateCertPwd();\n    }\n\n    public void setKeystorePwd(String keystorePwd) {\n       setKeyPrivateCertPwd(keystorePwd);\n    }\n\n    /**\n     * 获取私钥证书密码\n     * @return 私钥证书密码\n     */\n    public String getKeyPrivateCertPwd() {\n        return keyPrivateCertPwd;\n    }\n\n    public void setKeyPrivateCertPwd(String keyPrivateCertPwd) {\n        this.keyPrivateCertPwd = keyPrivateCertPwd;\n    }\n\n\n\n    public String getKeyPublicCert() {\n        return (String) keyPublicCert;\n    }\n\n    /**\n     * 设置公钥证书\n     *\n     * @param keyPublicCert 证书信息或者证书路径\n     */\n    public void setKeyPublicCert(String keyPublicCert) {\n        setKeyPublic(keyPublicCert);\n        this.keyPublicCert = keyPublicCert;\n    }\n\n    /**\n     * 设置公钥证书\n     *\n     * @param keyPublicCert 证书文件\n     */\n    public void setKeyPublicCert(InputStream keyPublicCert) {\n        this.keyPublicCert = keyPublicCert;\n    }\n\n    public Object getKeyCert() {\n        return keyCert;\n    }\n\n\n    /**\n     * 公钥证书，这里针对双证书校验， 银联的根级证书\n     *\n     * @param keyCert 证书信息或者证书路径\n     */\n    public void setKeyCert(String keyCert) {\n        this.keyCert = keyCert;\n    }\n\n    /**\n     * 公钥证书，这里针对双证书校验， 银联的根级证书\n     *\n     * @param keyCert 证书文件\n     */\n    public void setKeyCert(InputStream keyCert) {\n        this.keyCert = keyCert;\n    }\n\n    public InputStream getKeyPublicCertInputStream() throws IOException {\n        return certStoreType.getInputStream(keyPublicCert);\n    }\n\n    public InputStream getKeyCertInputStream() throws IOException {\n        return certStoreType.getInputStream(keyCert);\n    }\n\n    /**\n     * 证书存储类型\n     *\n     * @return 证书存储类型\n     */\n    public CertStoreType getCertStoreType() {\n        return certStoreType;\n    }\n\n    public void setCertStoreType(CertStoreType certStoreType) {\n        this.certStoreType = certStoreType;\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/bean/FuiouMerchantDetails.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant.bean;\n\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.fuiou.api.FuiouPayConfigStorage;\nimport com.egzosn.pay.spring.boot.core.PayConfigurerAdapter;\nimport com.egzosn.pay.spring.boot.core.builders.InMemoryMerchantDetailsServiceBuilder;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformServiceAdapter;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.FuiouPaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaymentPlatforms;\n\n/**\n * 富友商户信息列表\n *\n * @author egan\n * <pre>\n *                         email egzosn@gmail.com\n *                         date   2019/4/6 14:30.\n *                         </pre>\n */\npublic class FuiouMerchantDetails extends FuiouPayConfigStorage implements PaymentPlatformMerchantDetails, PaymentPlatformServiceAdapter, PayConfigurerAdapter<InMemoryMerchantDetailsServiceBuilder> {\n\n    private String detailsId;\n    /**\n     * 商户对应的支付服务\n     */\n    private volatile PayService payService;\n    /**\n     * 商户平台\n     */\n    private PaymentPlatform platform;\n\n    private InMemoryMerchantDetailsServiceBuilder builder;\n    /**\n     * HTTP请求配置\n     */\n    private HttpConfigStorage httpConfigStorage;\n\n    /**\n     * 外部调用者使用，链式的做法\n     *\n     * @return 返回对应外部调用者\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder and() {\n        initService();\n        return getBuilder();\n    }\n\n    /**\n     * 获取构建器\n     *\n     * @return 构建器\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder getBuilder() {\n        return builder;\n    }\n\n    public FuiouMerchantDetails(InMemoryMerchantDetailsServiceBuilder builder) {\n        this();\n        this.builder = builder;\n    }\n\n    public FuiouMerchantDetails() {\n        init();\n    }\n\n    public void init() {\n        if (null != platform) {\n            return;\n        }\n        String platformName = FuiouPaymentPlatform.platformName;\n        setPayType(platformName);\n        platform = PaymentPlatforms.getPaymentPlatform(platformName);\n    }\n\n    /**\n     * 获取支付平台\n     *\n     * @return 支付平台\n     */\n    @Override\n    public PaymentPlatform getPaymentPlatform() {\n        return platform;\n    }\n\n\n    /**\n     * 初始化服务\n     *\n     * @return 支付商户服务适配器\n     */\n    @Override\n    public PaymentPlatformServiceAdapter initService() {\n        init();\n        if (null == payService) {\n            payService = platform.getPayService(this, getHttpConfigStorage());\n        }\n        return this;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService() {\n        initService();\n        return payService;\n    }\n\n    /**\n     * 获取HTTP请求配置\n     *\n     * @return HTTP请求配置\n     */\n    @Override\n    public HttpConfigStorage getHttpConfigStorage() {\n        return httpConfigStorage;\n    }\n\n    public FuiouMerchantDetails httpConfigStorage(HttpConfigStorage httpConfigStorage) {\n        this.httpConfigStorage = httpConfigStorage;\n        return this;\n    }\n\n    public void setDetailsId(String detailsId) {\n        this.detailsId = detailsId;\n    }\n\n    /**\n     * 获取支付商户id\n     *\n     * @return 支付商户id\n     */\n    @Override\n    public String getDetailsId() {\n        return detailsId;\n    }\n\n\n    public FuiouMerchantDetails detailsId(String detailsId) {\n        this.detailsId = detailsId;\n        return this;\n    }\n\n    public FuiouMerchantDetails notifyUrl(String notifyUrl) {\n        setNotifyUrl(notifyUrl);\n        return this;\n    }\n\n    public FuiouMerchantDetails returnUrl(String returnUrl) {\n        setReturnUrl(returnUrl);\n        return this;\n    }\n\n    public FuiouMerchantDetails signType(String signType) {\n        setSignType(signType);\n        return this;\n    }\n\n    public FuiouMerchantDetails inputCharset(String inputCharset) {\n        setInputCharset(inputCharset);\n        return this;\n    }\n\n    public FuiouMerchantDetails test(boolean test) {\n        setTest(test);\n        return this;\n    }\n\n    public FuiouMerchantDetails mchntCd(String mchntCd) {\n        setMchntCd(mchntCd);\n        return this;\n    }\n\n    public FuiouMerchantDetails keyPrivate(String keyPrivate) {\n        setKeyPrivate(keyPrivate);\n        return this;\n    }\n\n    public FuiouMerchantDetails keyPublic(String keyPublic) {\n        setKeyPublic(keyPublic);\n        return this;\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/bean/PayPalV2MerchantDetails.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant.bean;\n\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.paypal.api.PayPalConfigStorage;\nimport com.egzosn.pay.spring.boot.core.PayConfigurerAdapter;\nimport com.egzosn.pay.spring.boot.core.builders.InMemoryMerchantDetailsServiceBuilder;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformServiceAdapter;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaymentPlatforms;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaypalV2PaymentPlatform;\n\n/**\n * 贝宝商户信息列表\n *\n * @author egan\n * <pre>\n *                 email egzosn@gmail.com\n *                 date   2019/4/6 14:30.\n *                 </pre>\n */\npublic class PayPalV2MerchantDetails extends PayPalConfigStorage implements PaymentPlatformMerchantDetails, PaymentPlatformServiceAdapter, PayConfigurerAdapter<InMemoryMerchantDetailsServiceBuilder> {\n\n    private String detailsId;\n\n    /**\n     * 商户对应的支付服务\n     */\n    private volatile PayService payService;\n    /**\n     * 商户平台\n     */\n    private PaymentPlatform platform;\n\n    private InMemoryMerchantDetailsServiceBuilder builder;\n    /**\n     * HTTP请求配置\n     */\n    private HttpConfigStorage httpConfigStorage;\n\n    /**\n     * 外部调用者使用，链式的做法\n     *\n     * @return 返回对应外部调用者\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder and() {\n        initService();\n        return getBuilder();\n    }\n\n    /**\n     * 获取构建器\n     *\n     * @return 构建器\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder getBuilder() {\n        return builder;\n    }\n\n    public PayPalV2MerchantDetails(InMemoryMerchantDetailsServiceBuilder builder) {\n        this();\n        this.builder = builder;\n    }\n\n    public PayPalV2MerchantDetails() {\n        init();\n    }\n\n    public void init() {\n        if (null != platform) {\n            return;\n        }\n        String platformName = PaypalV2PaymentPlatform.platformName;\n        setPayType(platformName);\n        platform = PaymentPlatforms.getPaymentPlatform(platformName);\n    }\n\n    /**\n     * 获取支付平台\n     *\n     * @return 支付平台\n     */\n    @Override\n    public PaymentPlatform getPaymentPlatform() {\n        return platform;\n    }\n\n    /**\n     * 初始化服务\n     *\n     * @return 支付商户服务适配器\n     */\n    @Override\n    public PaymentPlatformServiceAdapter initService() {\n\n        init();\n\n        if (null == payService) {\n            payService = platform.getPayService(this, getHttpConfigStorage());\n        }\n        return this;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService() {\n        initService();\n        return payService;\n    }\n\n    /**\n     * 获取HTTP请求配置\n     *\n     * @return HTTP请求配置\n     */\n    @Override\n    public HttpConfigStorage getHttpConfigStorage() {\n        return httpConfigStorage;\n    }\n\n    public PayPalV2MerchantDetails httpConfigStorage(HttpConfigStorage httpConfigStorage) {\n        this.httpConfigStorage = httpConfigStorage;\n        return this;\n    }\n\n    /**\n     * 获取支付商户id\n     *\n     * @return 支付商户id\n     */\n    @Override\n    public String getDetailsId() {\n        return detailsId;\n    }\n\n    public PayPalV2MerchantDetails detailsId(String detailsId) {\n        this.detailsId = detailsId;\n        return this;\n    }\n\n    public PayPalV2MerchantDetails signType(String signType) {\n        setSignType(signType);\n        return this;\n    }\n\n    public PayPalV2MerchantDetails inputCharset(String inputCharset) {\n        setInputCharset(inputCharset);\n        return this;\n    }\n\n    public PayPalV2MerchantDetails test(boolean test) {\n        setTest(test);\n        return this;\n    }\n\n    public PayPalV2MerchantDetails clientID(String clientID) {\n        setClientID(clientID);\n        return this;\n    }\n\n    public PayPalV2MerchantDetails clientSecret(String clientSecret) {\n        setClientSecret(clientSecret);\n        return this;\n    }\n\n    public PayPalV2MerchantDetails cancelUrl(String cancelUrl) {\n        setNotifyUrl(cancelUrl);\n        return this;\n    }\n\n    public PayPalV2MerchantDetails returnUrl(String returnUrl) {\n        setReturnUrl(returnUrl);\n        return this;\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/bean/PayoneerMerchantDetails.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant.bean;\n\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.payoneer.api.PayoneerConfigStorage;\nimport com.egzosn.pay.spring.boot.core.PayConfigurerAdapter;\nimport com.egzosn.pay.spring.boot.core.builders.InMemoryMerchantDetailsServiceBuilder;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformServiceAdapter;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaymentPlatforms;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PayoneerPaymentPlatform;\n\n/**\n * P卡(派安盈)商户信息列表\n *\n * @author egan\n *         <pre>\n *                         email egzosn@gmail.com\n *                         date   2019/4/6 14:30.\n *                         </pre>\n */\npublic class PayoneerMerchantDetails extends PayoneerConfigStorage implements PaymentPlatformMerchantDetails, PaymentPlatformServiceAdapter, PayConfigurerAdapter<InMemoryMerchantDetailsServiceBuilder> {\n\n    private String detailsId;\n\n    /**\n     * 商户对应的支付服务\n     */\n    private volatile PayService payService;\n    /**\n     * 商户平台\n     */\n    private PaymentPlatform platform ;\n\n    private InMemoryMerchantDetailsServiceBuilder builder;\n    /**\n     * HTTP请求配置\n     */\n    private HttpConfigStorage httpConfigStorage;\n\n\n    /**\n     * 外部调用者使用，链式的做法\n     *\n     * @return 返回对应外部调用者\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder and() {\n        initService();\n        return getBuilder();\n    }\n\n    /**\n     * 获取构建器\n     *\n     * @return 构建器\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder getBuilder() {\n        return builder;\n    }\n    public PayoneerMerchantDetails(InMemoryMerchantDetailsServiceBuilder builder) {\n        this();\n        this.builder = builder;\n    }\n\n    public PayoneerMerchantDetails() {\n       init();\n    }\n    public void init() {\n        if (null != platform){\n            return;\n        }\n        String platformName = PayoneerPaymentPlatform.platformName;\n        setPayType(platformName);\n        platform = PaymentPlatforms.getPaymentPlatform(platformName);\n    }\n    /**\n     * 获取支付平台\n     *\n     * @return 支付平台\n     */\n    @Override\n    public PaymentPlatform getPaymentPlatform() {\n        return platform;\n    }\n\n\n    /**\n     * 初始化服务\n     *\n     * @return 支付商户服务适配器\n     */\n    @Override\n    public PaymentPlatformServiceAdapter initService() {\n        init();\n        if (null == payService){\n            payService = platform.getPayService(this, getHttpConfigStorage());\n        }\n        return this;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService() {\n        initService();\n        return payService;\n    }\n\n    /**\n     * 获取HTTP请求配置\n     *\n     * @return HTTP请求配置\n     */\n    @Override\n    public HttpConfigStorage getHttpConfigStorage() {\n        return httpConfigStorage;\n    }\n    public PayoneerMerchantDetails httpConfigStorage(HttpConfigStorage httpConfigStorage) {\n        this.httpConfigStorage = httpConfigStorage;\n        return this;\n    }\n    /**\n     * 获取支付商户id\n     *\n     * @return 支付商户id\n     */\n    @Override\n    public String getDetailsId() {\n        return detailsId;\n    }\n\n    public PayoneerMerchantDetails detailsId(String detailsId) {\n        this.detailsId = detailsId;\n        return this;\n    }\n\n    public PayoneerMerchantDetails programId(String programId) {\n        setProgramId(programId);\n        return this;\n    }\n    public PayoneerMerchantDetails userName(String userName) {\n        setUserName(userName);\n        return this;\n    }\n    public PayoneerMerchantDetails apiPassword(String apiPassword) {\n        setApiPassword(apiPassword);\n        return this;\n    }\n\n    public PayoneerMerchantDetails signType(String signType) {\n        setSignType(signType);\n        return this;\n    }\n\n    public PayoneerMerchantDetails inputCharset(String inputCharset) {\n        setInputCharset(inputCharset);\n        return this;\n    }\n\n    public PayoneerMerchantDetails test(boolean test) {\n        setTest(test);\n        return this;\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/bean/PaypalMerchantDetails.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant.bean;\n\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.paypal.api.PayPalConfigStorage;\nimport com.egzosn.pay.spring.boot.core.PayConfigurerAdapter;\nimport com.egzosn.pay.spring.boot.core.builders.InMemoryMerchantDetailsServiceBuilder;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformServiceAdapter;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaymentPlatforms;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaypalPaymentPlatform;\n\n/**\n * 贝宝商户信息列表\n *\n * @author egan\n *         <pre>\n *                 email egzosn@gmail.com\n *                 date   2019/4/6 14:30.\n *                 </pre>\n */\npublic class PaypalMerchantDetails extends PayPalConfigStorage implements PaymentPlatformMerchantDetails, PaymentPlatformServiceAdapter, PayConfigurerAdapter<InMemoryMerchantDetailsServiceBuilder> {\n\n    private String detailsId;\n\n    /**\n     * 商户对应的支付服务\n     */\n    private volatile PayService payService;\n    /**\n     * 商户平台\n     */\n    private PaymentPlatform platform ;\n\n    private InMemoryMerchantDetailsServiceBuilder builder;\n    /**\n     * HTTP请求配置\n     */\n    private HttpConfigStorage httpConfigStorage;\n\n    /**\n     * 外部调用者使用，链式的做法\n     *\n     * @return 返回对应外部调用者\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder and() {\n        initService();\n        return getBuilder();\n    }\n\n    /**\n     * 获取构建器\n     *\n     * @return 构建器\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder getBuilder() {\n        return builder;\n    }\n    public PaypalMerchantDetails(InMemoryMerchantDetailsServiceBuilder builder) {\n        this();\n        this.builder = builder;\n    }\n\n    public PaypalMerchantDetails() {\n      init();\n    }\n    public void init() {\n        String platformName = PaypalPaymentPlatform.platformName;\n        setPayType(platformName);\n        platform = PaymentPlatforms.getPaymentPlatform(platformName);\n    }\n\n    /**\n     * 获取支付平台\n     *\n     * @return 支付平台\n     */\n    @Override\n    public PaymentPlatform getPaymentPlatform() {\n        return platform;\n    }\n\n    /**\n     * 初始化服务\n     *\n     * @return 支付商户服务适配器\n     */\n    @Override\n    public PaymentPlatformServiceAdapter initService() {\n        init();\n        if (null == payService){\n            payService = platform.getPayService(this, getHttpConfigStorage());\n        }\n        return this;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService() {\n        return payService;\n    }\n\n    /**\n     * 获取HTTP请求配置\n     *\n     * @return HTTP请求配置\n     */\n    @Override\n    public HttpConfigStorage getHttpConfigStorage() {\n        return httpConfigStorage;\n    }\n    public PaypalMerchantDetails httpConfigStorage(HttpConfigStorage httpConfigStorage) {\n        this.httpConfigStorage = httpConfigStorage;\n        return this;\n    }\n    /**\n     * 获取支付商户id\n     *\n     * @return 支付商户id\n     */\n    @Override\n    public String getDetailsId() {\n        return detailsId;\n    }\n\n    public PaypalMerchantDetails detailsId(String detailsId) {\n        this.detailsId = detailsId;\n        return this;\n    }\n    public PaypalMerchantDetails signType(String signType) {\n        setSignType(signType);\n        return this;\n    }\n\n    public PaypalMerchantDetails inputCharset(String inputCharset) {\n        setInputCharset(inputCharset);\n        return this;\n    }\n\n    public PaypalMerchantDetails test(boolean test) {\n        setTest(test);\n        return this;\n    }\n    public PaypalMerchantDetails clientID(String clientID) {\n        setClientID(clientID);\n        return this;\n    }\n    public PaypalMerchantDetails clientSecret(String clientSecret) {\n        setClientSecret(clientSecret);\n        return this;\n    }\n\n    public PaypalMerchantDetails cancelUrl(String cancelUrl) {\n        setNotifyUrl(cancelUrl);\n        return this;\n    }\n\n    public PaypalMerchantDetails returnUrl(String returnUrl) {\n        setReturnUrl(returnUrl);\n        return this;\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/bean/UnionMerchantDetails.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant.bean;\n\nimport java.io.InputStream;\n\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.CertStoreType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.spring.boot.core.PayConfigurerAdapter;\nimport com.egzosn.pay.spring.boot.core.builders.InMemoryMerchantDetailsServiceBuilder;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformServiceAdapter;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaymentPlatforms;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.UnionPaymentPlatform;\nimport com.egzosn.pay.union.api.UnionPayConfigStorage;\n\n/**\n * 银联商户信息列表\n *\n * @author egan\n *         <pre>\n *                         email egzosn@gmail.com\n *                         date   2019/4/6 14:30.\n *                         </pre>\n */\npublic class UnionMerchantDetails extends UnionPayConfigStorage implements PaymentPlatformMerchantDetails, PaymentPlatformServiceAdapter, PayConfigurerAdapter<InMemoryMerchantDetailsServiceBuilder> {\n\n    private String detailsId;\n    /**\n     * 商户对应的支付服务\n     */\n    private volatile PayService payService;\n    /**\n     * 商户平台\n     */\n    private PaymentPlatform platform;\n\n    private InMemoryMerchantDetailsServiceBuilder builder;\n    /**\n     * HTTP请求配置\n     */\n    private HttpConfigStorage httpConfigStorage;\n\n    /**\n     * 外部调用者使用，链式的做法\n     *\n     * @return 返回对应外部调用者\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder and() {\n        initService();\n        return getBuilder();\n    }\n\n    /**\n     * 获取构建器\n     *\n     * @return 构建器\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder getBuilder() {\n        return builder;\n    }\n\n    public UnionMerchantDetails(InMemoryMerchantDetailsServiceBuilder builder) {\n        this();\n        this.builder = builder;\n    }\n\n    public UnionMerchantDetails() {\n        init();\n    }\n    public void init() {\n        if (null != platform){\n            return;\n        }\n        String platformName = UnionPaymentPlatform.platformName;\n        setPayType(platformName);\n        platform = PaymentPlatforms.getPaymentPlatform(platformName);\n    }\n\n    /**\n     * 获取支付平台\n     *\n     * @return 支付平台\n     */\n    @Override\n    public PaymentPlatform getPaymentPlatform() {\n        return platform;\n    }\n\n    /**\n     * 初始化服务\n     *\n     * @return 支付商户服务适配器\n     */\n    @Override\n    public PaymentPlatformServiceAdapter initService() {\n        init();\n        if (null == payService){\n            payService = platform.getPayService(this, getHttpConfigStorage());\n        }\n        return this;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService() {\n        initService();\n        return payService;\n    }\n\n    /**\n     * 获取HTTP请求配置\n     *\n     * @return HTTP请求配置\n     */\n    @Override\n    public HttpConfigStorage getHttpConfigStorage() {\n        return httpConfigStorage;\n    }\n\n    public UnionMerchantDetails httpConfigStorage(HttpConfigStorage httpConfigStorage) {\n        this.httpConfigStorage = httpConfigStorage;\n        return this;\n    }\n\n    /**\n     * 获取支付商户id\n     *\n     * @return 支付商户id\n     */\n    @Override\n    public String getDetailsId() {\n        return detailsId;\n    }\n\n\n    public UnionMerchantDetails detailsId(String detailsId) {\n        this.detailsId = detailsId;\n        return this;\n    }\n\n    public UnionMerchantDetails notifyUrl(String notifyUrl) {\n        setNotifyUrl(notifyUrl);\n        return this;\n    }\n\n    public UnionMerchantDetails returnUrl(String returnUrl) {\n        setReturnUrl(returnUrl);\n        return this;\n    }\n\n    public UnionMerchantDetails signType(String signType) {\n        setSignType(signType);\n        return this;\n    }\n\n    public UnionMerchantDetails inputCharset(String inputCharset) {\n        setInputCharset(inputCharset);\n        return this;\n    }\n\n    public UnionMerchantDetails test(boolean test) {\n        setTest(test);\n        return this;\n    }\n\n    public UnionMerchantDetails acpMiddleCert(String acpMiddleCert) {\n        setAcpMiddleCert(acpMiddleCert);\n        return this;\n    }\n\n    public UnionMerchantDetails acpMiddleCert(InputStream acpMiddleCert) {\n        setAcpMiddleCert(acpMiddleCert);\n        return this;\n    }\n\n    public UnionMerchantDetails acpRootCert(String acpRootCert) {\n        setAcpRootCert(acpRootCert);\n        return this;\n    }\n\n    public UnionMerchantDetails acpRootCert(InputStream acpRootCert) {\n        setAcpRootCert(acpRootCert);\n        return this;\n    }\n\n    public UnionMerchantDetails keyPrivateCert(String keyPrivateCert) {\n        setKeyPrivateCert(keyPrivateCert);\n        return this;\n    }\n\n    public UnionMerchantDetails keyPrivateCert(InputStream keyPrivateCert) {\n        setKeyPrivateCert(keyPrivateCert);\n        return this;\n\n    }\n\n    public UnionMerchantDetails keyPrivateCertPwd(String keyPrivateCertPwd) {\n        setKeyPrivateCertPwd(keyPrivateCertPwd);\n        return this;\n    }\n    public UnionMerchantDetails certStoreType(CertStoreType certStoreType) {\n        setCertStoreType(certStoreType);\n        return this;\n    }\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/bean/WxMerchantDetails.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant.bean;\n\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.spring.boot.core.PayConfigurerAdapter;\nimport com.egzosn.pay.spring.boot.core.builders.InMemoryMerchantDetailsServiceBuilder;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformServiceAdapter;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaymentPlatforms;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.WxPaymentPlatform;\nimport com.egzosn.pay.wx.api.WxPayConfigStorage;\n\n/**\n * 支付宝商户信息列表\n *\n * @author egan\n * <pre>\n *                 email egzosn@gmail.com\n *                 date   2019/4/6 20:10.\n *                 </pre>\n */\npublic class WxMerchantDetails extends WxPayConfigStorage implements PaymentPlatformMerchantDetails, PaymentPlatformServiceAdapter, PayConfigurerAdapter<InMemoryMerchantDetailsServiceBuilder> {\n\n\n    private String detailsId;\n\n    /**\n     * 商户对应的支付服务\n     */\n    private volatile PayService payService;\n    /**\n     * 商户平台\n     */\n    private PaymentPlatform platform;\n\n    private InMemoryMerchantDetailsServiceBuilder builder;\n    /**\n     * HTTP请求配置\n     */\n    private HttpConfigStorage httpConfigStorage;\n\n    /**\n     * 外部调用者使用，链式的做法\n     *\n     * @return 返回对应外部调用者\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder and() {\n        initService();\n        return getBuilder();\n    }\n\n    /**\n     * 获取构建器\n     *\n     * @return 构建器\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder getBuilder() {\n        return builder;\n    }\n\n    public WxMerchantDetails(InMemoryMerchantDetailsServiceBuilder builder) {\n        this();\n        this.builder = builder;\n    }\n\n    public WxMerchantDetails() {\n        init();\n    }\n\n    public void init() {\n        if (null != platform) {\n            return;\n        }\n        String platformName = WxPaymentPlatform.platformName;\n        setPayType(platformName);\n        platform = PaymentPlatforms.getPaymentPlatform(platformName);\n    }\n\n    /**\n     * 获取支付平台\n     *\n     * @return 支付平台\n     */\n    @Override\n    public PaymentPlatform getPaymentPlatform() {\n        return platform;\n    }\n\n    /**\n     * 初始化服务\n     *\n     * @return 支付商户服务适配器\n     */\n    @Override\n    public PaymentPlatformServiceAdapter initService() {\n        init();\n        if (null == payService) {\n            payService = platform.getPayService(this, getHttpConfigStorage());\n        }\n        return this;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService() {\n        initService();\n        return payService;\n    }\n\n    /**\n     * 获取HTTP请求配置\n     *\n     * @return HTTP请求配置\n     */\n    @Override\n    public HttpConfigStorage getHttpConfigStorage() {\n        return httpConfigStorage;\n    }\n\n    public WxMerchantDetails httpConfigStorage(HttpConfigStorage httpConfigStorage) {\n        this.httpConfigStorage = httpConfigStorage;\n        return this;\n    }\n\n    /**\n     * 获取支付商户id\n     *\n     * @return 支付商户id\n     */\n    @Override\n    public String getDetailsId() {\n        return detailsId;\n    }\n\n    public WxMerchantDetails detailsId(String detailsId) {\n        this.detailsId = detailsId;\n        return this;\n    }\n\n    public WxMerchantDetails notifyUrl(String notifyUrl) {\n        setNotifyUrl(notifyUrl);\n        return this;\n    }\n\n    public WxMerchantDetails returnUrl(String returnUrl) {\n        setReturnUrl(returnUrl);\n        return this;\n    }\n\n    public WxMerchantDetails signType(String signType) {\n        setSignType(signType);\n        return this;\n    }\n\n    public WxMerchantDetails inputCharset(String inputCharset) {\n        setInputCharset(inputCharset);\n        return this;\n    }\n\n    public WxMerchantDetails test(boolean test) {\n        setTest(test);\n        return this;\n    }\n\n\n    public WxMerchantDetails appid(String appid) {\n        setAppid(appid);\n        return this;\n    }\n\n    public WxMerchantDetails secretKey(String secretKey) {\n        setSecretKey(secretKey);\n        return this;\n    }\n\n    public WxMerchantDetails keyPublic(String keyPublic) {\n        setKeyPublic(keyPublic);\n        return this;\n    }\n\n    public WxMerchantDetails mchId(String mchId) {\n        setMchId(mchId);\n        return this;\n    }\n\n    public WxMerchantDetails subAppid(String subAppid) {\n        setSubAppid(subAppid);\n        return this;\n    }\n\n    public WxMerchantDetails subMchId(String subMchId) {\n        setSubMchId(subMchId);\n        return this;\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/bean/WxV3MerchantDetails.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant.bean;\n\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.CertStoreType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.spring.boot.core.PayConfigurerAdapter;\nimport com.egzosn.pay.spring.boot.core.builders.InMemoryMerchantDetailsServiceBuilder;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformServiceAdapter;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaymentPlatforms;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.WxV3PaymentPlatform;\nimport com.egzosn.pay.wx.v3.api.WxPayConfigStorage;\n\n/**\n * 支付宝商户信息列表\n *\n * @author egan\n * <pre>\n *                 email egzosn@gmail.com\n *                 date   2019/4/6 20:10.\n *                 </pre>\n */\npublic class WxV3MerchantDetails extends WxPayConfigStorage implements PaymentPlatformMerchantDetails, PaymentPlatformServiceAdapter, PayConfigurerAdapter<InMemoryMerchantDetailsServiceBuilder> {\n\n\n    private String detailsId;\n\n    /**\n     * 商户对应的支付服务\n     */\n    private volatile PayService payService;\n    /**\n     * 商户平台\n     */\n    private PaymentPlatform platform;\n\n    private InMemoryMerchantDetailsServiceBuilder builder;\n    /**\n     * HTTP请求配置\n     */\n    private HttpConfigStorage httpConfigStorage;\n\n    /**\n     * 外部调用者使用，链式的做法\n     *\n     * @return 返回对应外部调用者\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder and() {\n        initService();\n        return getBuilder();\n    }\n\n    /**\n     * 获取构建器\n     *\n     * @return 构建器\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder getBuilder() {\n        return builder;\n    }\n\n    public WxV3MerchantDetails(InMemoryMerchantDetailsServiceBuilder builder) {\n        this();\n        this.builder = builder;\n    }\n\n    public WxV3MerchantDetails() {\n        init();\n    }\n\n\n    public WxV3MerchantDetails init() {\n        if (null != platform) {\n            return this;\n        }\n        String platformName = WxV3PaymentPlatform.platformName;\n        setPayType(platformName);\n        platform = PaymentPlatforms.getPaymentPlatform(platformName);\n        return this;\n    }\n\n    /**\n     * 获取支付平台\n     *\n     * @return 支付平台\n     */\n    @Override\n    public PaymentPlatform getPaymentPlatform() {\n\n        return platform;\n    }\n\n    /**\n     * 初始化服务\n     *\n     * @return 支付商户服务适配器\n     */\n    @Override\n    public PaymentPlatformServiceAdapter initService() {\n        init();\n        if (null == payService) {\n            payService = platform.getPayService(this, getHttpConfigStorage());\n        }\n        return this;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService() {\n        initService();\n        return payService;\n    }\n\n    /**\n     * 获取HTTP请求配置\n     *\n     * @return HTTP请求配置\n     */\n    @Override\n    public HttpConfigStorage getHttpConfigStorage() {\n        return httpConfigStorage;\n    }\n\n    public WxV3MerchantDetails httpConfigStorage(HttpConfigStorage httpConfigStorage) {\n        this.httpConfigStorage = httpConfigStorage;\n        return this;\n    }\n\n    /**\n     * 获取支付商户id\n     *\n     * @return 支付商户id\n     */\n    @Override\n    public String getDetailsId() {\n        return detailsId;\n    }\n\n    public void setDetailsId(String detailsId) {\n        this.detailsId = detailsId;\n    }\n\n    public WxV3MerchantDetails detailsId(String detailsId) {\n        this.detailsId = detailsId;\n        return this;\n    }\n\n    public WxV3MerchantDetails notifyUrl(String notifyUrl) {\n        setNotifyUrl(notifyUrl);\n        return this;\n    }\n\n    public WxV3MerchantDetails returnUrl(String returnUrl) {\n        setReturnUrl(returnUrl);\n        return this;\n    }\n\n    public WxV3MerchantDetails signType(String signType) {\n        setSignType(signType);\n        return this;\n    }\n\n    public WxV3MerchantDetails inputCharset(String inputCharset) {\n        setInputCharset(inputCharset);\n        return this;\n    }\n\n    public WxV3MerchantDetails test(boolean test) {\n        setTest(test);\n        return this;\n    }\n\n\n    public WxV3MerchantDetails appId(String appId) {\n        setAppId(appId);\n        return this;\n    }\n\n    public WxV3MerchantDetails keyPrivate(String keyPrivate) {\n        setKeyPrivate(keyPrivate);\n        return this;\n    }\n\n    public WxV3MerchantDetails v3ApiKey(String v3ApiKey) {\n        setV3ApiKey(v3ApiKey);\n        return this;\n    }\n\n    public WxV3MerchantDetails apiKey(String apiKey) {\n        setApiKey(apiKey);\n        return this;\n    }\n\n    public WxV3MerchantDetails keyPublic(String keyPublic) {\n        setKeyPublic(keyPublic);\n        return this;\n    }\n\n    public WxV3MerchantDetails keyPublicId(String keyPublicId) {\n        setKeyPublicId(keyPublicId);\n        return this;\n    }\n\n    public WxV3MerchantDetails merchantSerialNumber(String merchantSerialNumber) {\n        setMerchantSerialNumber(merchantSerialNumber);\n        return this;\n    }\n\n    public WxV3MerchantDetails mchId(String mchId) {\n        setMchId(mchId);\n        return this;\n    }\n\n    public WxV3MerchantDetails subAppId(String subAppId) {\n        setSubAppId(subAppId);\n        return this;\n    }\n\n    public WxV3MerchantDetails subMchId(String subMchId) {\n        setSubMchId(subMchId);\n        return this;\n    }\n\n\n    public WxV3MerchantDetails apiClientKeyP12(Object apiClientKeyP12) {\n        setApiClientKeyP12(apiClientKeyP12);\n        return this;\n    }\n\n    public WxV3MerchantDetails certStoreType(CertStoreType certStoreType) {\n        setCertStoreType(certStoreType);\n        return this;\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/merchant/bean/WxYouDianMerchantDetails.java",
    "content": "package com.egzosn.pay.spring.boot.core.merchant.bean;\n\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.spring.boot.core.PayConfigurerAdapter;\nimport com.egzosn.pay.spring.boot.core.builders.InMemoryMerchantDetailsServiceBuilder;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformServiceAdapter;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaymentPlatforms;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PayoneerPaymentPlatform;\nimport com.egzosn.pay.wx.youdian.api.WxYouDianPayConfigStorage;\n\n/**\n * P卡(派安盈)商户信息列表\n *\n * @author egan\n *         <pre>\n *                         email egzosn@gmail.com\n *                         date   2019/4/6 14:30.\n *                         </pre>\n */\npublic class WxYouDianMerchantDetails extends WxYouDianPayConfigStorage implements PaymentPlatformMerchantDetails, PaymentPlatformServiceAdapter, PayConfigurerAdapter<InMemoryMerchantDetailsServiceBuilder> {\n\n    private String detailsId;\n\n    /**\n     * 商户对应的支付服务\n     */\n    private volatile PayService payService;\n    /**\n     * 商户平台\n     */\n    private PaymentPlatform platform ;\n\n    private InMemoryMerchantDetailsServiceBuilder builder;\n    /**\n     * HTTP请求配置\n     */\n    private HttpConfigStorage httpConfigStorage;\n\n\n    /**\n     * 外部调用者使用，链式的做法\n     *\n     * @return 返回对应外部调用者\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder and() {\n        initService();\n        return getBuilder();\n    }\n\n    /**\n     * 获取构建器\n     *\n     * @return 构建器\n     */\n    @Override\n    public InMemoryMerchantDetailsServiceBuilder getBuilder() {\n        return builder;\n    }\n    public WxYouDianMerchantDetails(InMemoryMerchantDetailsServiceBuilder builder) {\n        this();\n        this.builder = builder;\n    }\n\n    public WxYouDianMerchantDetails() {\n       init();\n    }\n    public void init() {\n        String platformName = PayoneerPaymentPlatform.platformName;\n        setPayType(platformName);\n        platform = PaymentPlatforms.getPaymentPlatform(platformName);\n    }\n    /**\n     * 获取支付平台\n     *\n     * @return 支付平台\n     */\n    @Override\n    public PaymentPlatform getPaymentPlatform() {\n        return platform;\n    }\n\n\n    /**\n     * 初始化服务\n     *\n     * @return 支付商户服务适配器\n     */\n    @Override\n    public PaymentPlatformServiceAdapter initService() {\n        init();\n        if (null == payService){\n            payService = platform.getPayService(this, getHttpConfigStorage());\n        }\n        return this;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService() {\n        return payService;\n    }\n\n    /**\n     * 获取HTTP请求配置\n     *\n     * @return HTTP请求配置\n     */\n    @Override\n    public HttpConfigStorage getHttpConfigStorage() {\n        return httpConfigStorage;\n    }\n    public WxYouDianMerchantDetails httpConfigStorage(HttpConfigStorage httpConfigStorage) {\n        this.httpConfigStorage = httpConfigStorage;\n        return this;\n    }\n    /**\n     * 获取支付商户id\n     *\n     * @return 支付商户id\n     */\n    @Override\n    public String getDetailsId() {\n        return detailsId;\n    }\n\n    public WxYouDianMerchantDetails detailsId(String detailsId) {\n        this.detailsId = detailsId;\n        return this;\n    }\n\n\n    public WxYouDianMerchantDetails keyPrivate(String keyPrivate) {\n        setKeyPrivate(keyPrivate);\n        return this;\n    }\n\n    public WxYouDianMerchantDetails keyPublic(String keyPublic) {\n        setKeyPublic(keyPublic);\n        return this;\n    }\n\n    public WxYouDianMerchantDetails seller(String seller) {\n        setSeller(seller);\n        return this;\n    }\n\n\n    public WxYouDianMerchantDetails signType(String signType) {\n        setSignType(signType);\n        return this;\n    }\n\n    public WxYouDianMerchantDetails inputCharset(String inputCharset) {\n        setInputCharset(inputCharset);\n        return this;\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/CacheMerchantDetailsManager.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.springframework.util.Assert;\n\nimport com.egzosn.pay.spring.boot.core.configurers.PayMessageConfigurer;\nimport com.egzosn.pay.spring.boot.core.merchant.MerchantNotFoundException;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\n\n/**\n * 缓存支付账户(商户)存储器\n *\n * @author egan\n *         <pre>\n * email egzosn@gmail.com\n * date 2021/1/7\n * </pre>\n */\npublic class CacheMerchantDetailsManager implements MerchantDetailsManager<PaymentPlatformMerchantDetails> {\n\n    private Map<String, PaymentPlatformMerchantDetails> merchantDetails = new HashMap<String, PaymentPlatformMerchantDetails>();\n\n    private MerchantDetailsManager<PaymentPlatformMerchantDetails> delegate;\n\n    public CacheMerchantDetailsManager(MerchantDetailsManager<PaymentPlatformMerchantDetails> delegate) {\n        this.delegate = delegate;\n    }\n\n    /**\n     * 创建商户\n     *\n     * @param merchant 商户信息\n     */\n    @Override\n    public void createMerchant(PaymentPlatformMerchantDetails merchant) {\n        Assert.isTrue(!merchantExists(merchant.getDetailsId()), \"商户信息已存在\");\n        merchantDetails.put(merchant.getDetailsId(), merchant);\n        delegate.createMerchant(merchant);\n    }\n\n    /**\n     * 创建商户\n     *\n     * @param merchants 商户信息\n     */\n    @Override\n    public void createMerchant(Collection<PaymentPlatformMerchantDetails> merchants) {\n        for (PaymentPlatformMerchantDetails merchant : merchants) {\n            this.createMerchant(merchant);\n        }\n    }\n\n    /**\n     * 更新商户\n     *\n     * @param merchant 商户信息\n     */\n    @Override\n    public void updateMerchant(PaymentPlatformMerchantDetails merchant) {\n        Assert.isTrue(merchantExists(merchant.getDetailsId()), \"商户信息不存在\");\n        merchantDetails.put(merchant.getDetailsId(), merchant);\n        delegate.updateMerchant(merchant);\n\n\n    }\n\n    /**\n     * 删除商户\n     *\n     * @param id 商户id\n     */\n    @Override\n    public void deleteMerchant(String id) {\n        merchantDetails.remove(id);\n        delegate.deleteMerchant(id);\n    }\n\n    /**\n     * 检查商户是否存在\n     *\n     * @param id 商户id\n     * @return 检查商户是否存在\n     */\n    @Override\n    public boolean merchantExists(String id) {\n        boolean exist = merchantDetails.containsKey(id);\n        if (exist) {\n            return exist;\n        }\n        return delegate.merchantExists(id);\n\n    }\n\n    /**\n     * 设置支付消息配置中心\n     *\n     * @param configurer 配置\n     */\n    @Override\n    public void setPayMessageConfigurer(PayMessageConfigurer configurer) {\n        delegate.setPayMessageConfigurer(configurer);\n    }\n\n    /**\n     * 通过支付商户id加载对应的商户信息列表\n     *\n     * @param merchantId 支付商户id\n     * @return 商户信息列表\n     */\n    @Override\n    public PaymentPlatformMerchantDetails loadMerchantByMerchantId(String merchantId) {\n        PaymentPlatformMerchantDetails details = merchantDetails.get(merchantId);\n        if (null != details) {\n            return details;\n        }\n        details = delegate.loadMerchantByMerchantId(merchantId);\n        if (null == details){\n            throw new MerchantNotFoundException(merchantId);\n        }\n        merchantDetails.put(details.getDetailsId(), details);\n        return details;\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/InMemoryMerchantDetailsManager.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider;\n\nimport com.egzosn.pay.common.api.PayMessageHandler;\nimport com.egzosn.pay.common.api.PayMessageInterceptor;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.PayMessage;\nimport com.egzosn.pay.spring.boot.core.configurers.PayMessageConfigurer;\nimport com.egzosn.pay.spring.boot.core.merchant.MerchantNotFoundException;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\nimport org.springframework.util.Assert;\n\nimport java.util.*;\n\n\n/**\n * 内存型支付账户(商户)存储器\n *\n * @author egan\n *         <pre>\n *                 email egzosn@gmail.com\n *                 date 2018-11-22 17:18:03\n *           </pre>\n */\npublic class InMemoryMerchantDetailsManager implements MerchantDetailsManager<PaymentPlatformMerchantDetails> {\n\n    private Map<String, PaymentPlatformMerchantDetails> merchantDetails = new HashMap<String, PaymentPlatformMerchantDetails>();\n    private PayMessageConfigurer configurer;\n\n    public InMemoryMerchantDetailsManager() {\n    }\n\n    public InMemoryMerchantDetailsManager(Collection<PaymentPlatformMerchantDetails> merchantDetails) {\n        createMerchant(merchantDetails);\n    }\n\n    public InMemoryMerchantDetailsManager(Map<String, PaymentPlatformMerchantDetails> merchantDetails) {\n        this.merchantDetails = merchantDetails;\n    }\n\n    /**\n     * 这个暂时还未定义，后期版本进行\n     * @param merchants 属性配置\n     */\n    public InMemoryMerchantDetailsManager(Properties merchants) {\n\n    }\n\n\n    /**\n     * 创建商户\n     *\n     * @param merchants 商户信息\n     */\n    @Override\n    public void createMerchant(Collection<PaymentPlatformMerchantDetails> merchants) {\n        for (PaymentPlatformMerchantDetails merchant : merchants) {\n            this.createMerchant(merchant);\n        }\n    }\n    /**\n     * 创建商户\n     *\n     * @param merchant 商户信息\n     */\n    @Override\n    public void createMerchant(PaymentPlatformMerchantDetails merchant) {\n\n        Assert.isTrue(!merchantExists(merchant.getDetailsId()), \"商户信息已存在\");\n        InMemoryMerchantDetailsManager.setPayMessageConfigurer(merchant.getPayService(), merchant, configurer);\n        merchantDetails.put(merchant.getDetailsId(), merchant);\n\n    }\n    protected static void setPayMessageConfigurer(PayService payService, PaymentPlatformMerchantDetails details, PayMessageConfigurer configurer){\n        PayMessageHandler<PayMessage, PayService> handler = configurer.getHandler(details.getPaymentPlatform());\n        if (null != handler){\n            payService.setPayMessageHandler(handler);\n        }\n\n        List<PayMessageInterceptor<PayMessage, PayService>> interceptors = configurer.getInterceptor(details.getPaymentPlatform());\n        if (null == interceptors || interceptors.isEmpty()){\n            return;\n        }\n        for (PayMessageInterceptor<PayMessage, PayService> interceptor : interceptors){\n            payService.addPayMessageInterceptor(interceptor);\n        }\n    }\n    /**\n     * 更新商户\n     *\n     * @param merchant 商户信息\n     */\n    @Override\n    public void updateMerchant(PaymentPlatformMerchantDetails merchant) {\n        Assert.isTrue(merchantExists(merchant.getDetailsId()), \"商户信息不存在\");\n        merchantDetails.put(merchant.getDetailsId(), merchant);\n    }\n\n    /**\n     * 删除商户\n     *\n     * @param id 商户id\n     */\n    @Override\n    public void deleteMerchant(String id) {\n        merchantDetails.remove(id);\n    }\n\n    /**\n     * 检查商户是否存在\n     *\n     * @param id 商户id\n     * @return 检查商户是否存在\n     */\n    @Override\n    public boolean merchantExists(String id) {\n        return merchantDetails.containsKey(id);\n    }\n\n    /**\n     * 设置支付消息配置中心\n     *\n     * @param configurer 配置\n     */\n    @Override\n    public void setPayMessageConfigurer(PayMessageConfigurer configurer) {\n        this.configurer = configurer;\n    }\n\n    /**\n     * 通过支付商户id加载对应的商户信息列表\n     *\n     * @param merchantId 支付商户id\n     * @return 商户信息列表\n     */\n    @Override\n    public PaymentPlatformMerchantDetails loadMerchantByMerchantId(String merchantId) {\n\n        PaymentPlatformMerchantDetails details = merchantDetails.get(merchantId);\n        if (null == details) {\n            throw new MerchantNotFoundException(merchantId);\n        }\n        return details;\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/JdbcMerchantDetailsManager.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider;\n\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.CertStoreType;\nimport com.egzosn.pay.common.util.str.StringUtils;\nimport com.egzosn.pay.spring.boot.core.configurers.PayMessageConfigurer;\nimport com.egzosn.pay.spring.boot.core.merchant.MerchantNotFoundException;\nimport com.egzosn.pay.spring.boot.core.merchant.bean.CommonPaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.UnionPaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.utils.SqlTools;\nimport org.springframework.dao.IncorrectResultSizeDataAccessException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.core.RowMapper;\nimport org.springframework.util.Assert;\nimport javax.sql.DataSource;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.List;\nimport static com.egzosn.pay.spring.boot.core.utils.SqlTools.SEPARATED;\n\n\n/**\n * JDBC支付账户(商户)存储器\n *\n * @author egan\n *         <pre>\n *                 email egzosn@gmail.com\n *                 date 2018-11-22 17:18:03\n *                 </pre>\n */\npublic class JdbcMerchantDetailsManager implements MerchantDetailsManager<CommonPaymentPlatformMerchantDetails> {\n\n\n    private static final String TABLE = \"merchant_details\";\n    private static final List<String> FIELDS = Arrays.asList(\"appid\", \"pay_type\", \"mch_id\", \"cert_store_type\", \"key_private\", \"key_cert_pwd\", \"key_public\", \"key_cert\", \"notify_url\", \"return_url\", \"sign_type\", \"seller\", \"sub_app_id\", \"sub_mch_id\", \"input_charset\", \"is_test\");\n    private static final String SELECT_FIELDS = SqlTools.join(FIELDS, SEPARATED);\n    private static final String ID = \"details_id\";\n\n    private static final String DEFAULT_BASE_QUERY_SQL = SqlTools.getSelectSQL(ID + SEPARATED + SELECT_FIELDS, TABLE);\n    private static final String DEFAULT_FIND_BY_ID_SQL = DEFAULT_BASE_QUERY_SQL + \" where \" + ID + \"=?\";\n    private static final String DEFAULT_INSERT_SQL = \"insert into \" + TABLE + \" (\" + ID + SEPARATED + SELECT_FIELDS + \") values (\" + SqlTools.forQuestionMarkSQL(FIELDS.size() + 1) + \")\";\n    private static final String DEFAULT_UPDATE_SQL = SqlTools.generateUpdateByRowIdString(TABLE, FIELDS, ID).toString();\n    private static final String DEFAULT_DELETE_SQL = \"delete from \" + TABLE + \" where \" + ID + \"=?\";\n    public static final String DEFAULT_EXISTS_SQL = \"select \" + ID + \" from \" + TABLE + \" where \" + ID + \" = ?\";\n\n    private JdbcTemplate jdbcTemplate;\n\n    private String findByIdSql = DEFAULT_FIND_BY_ID_SQL;\n    private String insertSql = DEFAULT_INSERT_SQL;\n    private String updateSql = DEFAULT_UPDATE_SQL;\n    private String deleteSql = DEFAULT_DELETE_SQL;\n    private String existsSql = DEFAULT_EXISTS_SQL;\n\n    private PayMessageConfigurer configurer;\n\n    public JdbcMerchantDetailsManager(DataSource dataSource) {\n        this.jdbcTemplate = new JdbcTemplate(dataSource);\n    }\n\n    public JdbcMerchantDetailsManager(JdbcTemplate jdbcTemplate) {\n        this.jdbcTemplate = jdbcTemplate;\n    }\n\n\n    /**\n     * 创建商户\n     *\n     * @param merchants 商户信息\n     */\n    @Override\n    public void createMerchant(Collection<CommonPaymentPlatformMerchantDetails> merchants) {\n        for (CommonPaymentPlatformMerchantDetails merchant : merchants) {\n            this.createMerchant(merchant);\n        }\n    }\n    /**\n     * 创建商户\n     *\n     * @param merchant 商户信息\n     */\n    @Override\n    public void createMerchant(CommonPaymentPlatformMerchantDetails merchant) {\n\n        Assert.isTrue(!merchantExists(merchant.getDetailsId()), \"商户信息已存在\");\n        Object[] args = new Object[]{merchant.getDetailsId(), merchant.getAppId(), merchant.getPayType(), merchant.getMchId(), merchant.getCertStoreType(), merchant.getKeyPrivate(), merchant.getKeyPrivateCertPwd(), merchant.getKeyPublic(), merchant.getKeyCert(), merchant.getNotifyUrl(), merchant.getReturnUrl(), merchant.getSignType(), merchant.getSeller(), merchant.getSubAppId(), merchant.getSubMchId(), merchant.getInputCharset(), merchant.isTest()};\n        jdbcTemplate.update(insertSql, args);\n\n\n    }\n\n    /**\n     * 更新商户\n     *\n     * @param merchant 商户信息\n     */\n    @Override\n    public void updateMerchant(CommonPaymentPlatformMerchantDetails merchant) {\n        Assert.isTrue(merchantExists(merchant.getDetailsId()), \"商户信息不存在\");\n        Object[] args = new Object[]{merchant.getAppId(), merchant.getPayType(), merchant.getMchId(), merchant.getCertStoreType(), merchant.getKeyPrivate(), merchant.getKeyPrivateCertPwd(), merchant.getKeyPublic(), merchant.getKeyCert(), merchant.getNotifyUrl(), merchant.getReturnUrl(), merchant.getSignType(), merchant.getSeller(), merchant.getSubAppId(), merchant.getSubMchId(), merchant.getInputCharset(), merchant.isTest(), merchant.getDetailsId()};\n        jdbcTemplate.update(updateSql, args);\n    }\n\n    /**\n     * 删除商户\n     *\n     * @param id 商户id\n     */\n    @Override\n    public void deleteMerchant(String id) {\n        jdbcTemplate.update(deleteSql, id);\n    }\n\n    /**\n     * 检查商户是否存在\n     *\n     * @param merchantId 商户id\n     * @return 检查商户是否存在\n     */\n    @Override\n    public boolean merchantExists(String merchantId) {\n        List<String> ids = jdbcTemplate.queryForList(existsSql, String.class, merchantId);\n        if (ids.size() > 1) {\n            throw new IncorrectResultSizeDataAccessException(\"出现重复的支付商户id\", 1);\n        }\n\n        return !ids.isEmpty();\n    }\n\n    /**\n     * 通过支付商户id加载对应的商户信息列表\n     *\n     * @param merchantId 支付商户id\n     * @return 商户信息列表\n     */\n    @Override\n    public CommonPaymentPlatformMerchantDetails loadMerchantByMerchantId(String merchantId) {\n        List<CommonPaymentPlatformMerchantDetails> detailss = jdbcTemplate.query(findByIdSql, (ResultSet rs, int i)->{\n                CommonPaymentPlatformMerchantDetails details = new CommonPaymentPlatformMerchantDetails();\n                details.setDetailsId(rs.getString(1));\n                details.setAppId(rs.getString(2));\n                details.setPayType(rs.getString(3));\n                details.setMchId(rs.getString(4));\n                String certStoreType = rs.getString(5);\n                if (StringUtils.isNotEmpty(certStoreType)) {\n                    details.setCertStoreType(CertStoreType.valueOf(certStoreType));\n                }\n                if (details.getCertStoreType() == CertStoreType.INPUT_STREAM) {\n                    setKeyPrivate(details, rs);\n                    details.setKeyCert(rs.getAsciiStream(9));\n                }\n                else {\n                    details.setKeystore(rs.getString(6));\n                    details.setKeyPublicCert(rs.getString(8));\n                    details.setKeyCert(rs.getString(9));\n                }\n                details.setKeystorePwd(rs.getString(7));\n                details.setNotifyUrl(rs.getString(10));\n                details.setReturnUrl(rs.getString(11));\n                details.setSignType(rs.getString(12));\n                details.setSeller(rs.getString(13));\n                details.setSubAppId(rs.getString(14));\n                details.setSubMchId(rs.getString(15));\n                details.setInputCharset(rs.getString(16));\n                details.setTest(rs.getBoolean(17));\n                PayService payService = details.initService().getPayService();\n                InMemoryMerchantDetailsManager.setPayMessageConfigurer(payService, details, configurer);\n                return details;\n        }, merchantId);\n        int size = detailss != null ? detailss.size() : 0;\n        if (size == 0) {\n            throw new MerchantNotFoundException(merchantId);\n        }\n        else if (size > 1) {\n            throw new IncorrectResultSizeDataAccessException(1, size);\n        }\n        else {\n            return detailss.get(0);\n        }\n    }\n\n\n    public void setKeyPrivate(CommonPaymentPlatformMerchantDetails details, ResultSet rs) throws SQLException {\n        if (UnionPaymentPlatform.platformName.equals(details.getPayType())) {\n            details.setKeystore(rs.getAsciiStream(6));\n            details.setKeyPublicCert(rs.getAsciiStream(8));\n        }\n        else {\n            details.setKeyPrivate(rs.getString(6));\n            details.setKeyPublic(rs.getString(8));\n        }\n\n    }\n\n    public String getFindByIdSql() {\n        return findByIdSql;\n    }\n\n    public void setFindByIdSql(String findByIdSql) {\n        this.findByIdSql = findByIdSql;\n    }\n\n    public String getInsertSql() {\n        return insertSql;\n    }\n\n    public void setInsertSql(String insertSql) {\n        this.insertSql = insertSql;\n    }\n\n    public String getUpdateSql() {\n        return updateSql;\n    }\n\n    public void setUpdateSql(String updateSql) {\n        this.updateSql = updateSql;\n    }\n\n    public String getDeleteSql() {\n        return deleteSql;\n    }\n\n    public void setDeleteSql(String deleteSql) {\n        this.deleteSql = deleteSql;\n    }\n\n    public String getExistsSql() {\n        return existsSql;\n    }\n\n    public void setExistsSql(String existsSql) {\n        this.existsSql = existsSql;\n    }\n\n\n    /**\n     * 设置支付消息配置中心\n     *\n     * @param configurer 配置\n     */\n    @Override\n    public void setPayMessageConfigurer(PayMessageConfigurer configurer) {\n        this.configurer = configurer;\n    }\n\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/MerchantDetailsManager.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider;\n\nimport com.egzosn.pay.spring.boot.core.configurers.PayMessageConfigurer;\nimport com.egzosn.pay.spring.boot.core.merchant.MerchantDetails;\nimport com.egzosn.pay.spring.boot.core.merchant.MerchantDetailsService;\n\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * 商户列表管理器\n * @author egan\n *         <pre>\n *         email egzosn@gmail.com\n *         date  2019/4/2 14:44.\n *         </pre>\n */\npublic interface MerchantDetailsManager<T extends MerchantDetails> extends MerchantDetailsService<T> {\n\n    /**\n     *  创建商户\n     * @param merchant 商户信息\n     */\n    void createMerchant(T merchant);\n    /**\n     *  创建商户\n     * @param merchants 商户信息\n     */\n    void createMerchant(Collection<T> merchants);\n\n    /**\n     *  更新商户\n     * @param merchant 商户信息\n     */\n    void updateMerchant(T merchant);\n    /**\n     *  删除商户\n     * @param id 商户id\n     */\n    void deleteMerchant(String id);\n\n    /**\n     * 检查商户是否存在\n     * @param id 商户id\n     * @return 检查商户是否存在\n     */\n    boolean merchantExists(String id);\n\n    /**\n     * 设置支付消息配置中心\n     * @param configurer 配置\n     */\n    void setPayMessageConfigurer(PayMessageConfigurer configurer);\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/merchant/platform/AliPaymentPlatform.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider.merchant.platform;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Configuration;\n\nimport com.egzosn.pay.ali.api.AliPayConfigStorage;\nimport com.egzosn.pay.ali.api.AliPayService;\nimport com.egzosn.pay.ali.bean.AliTransactionType;\nimport com.egzosn.pay.common.api.PayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.TransactionType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.common.util.str.StringUtils;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.bean.CommonPaymentPlatformMerchantDetails;\n\n/**\n * 支付宝支付平台\n *\n * @author egan\n * <pre>\n *                 email egzosn@gmail.com\n *                 date  2019/4/4 14:35.\n *                 </pre>\n */\n@Configuration(AliPaymentPlatform.PLATFORM_NAME)\n@ConditionalOnMissingBean(AliPaymentPlatform.class)\n@ConditionalOnClass(name = \"com.egzosn.pay.ali.api.AliPayConfigStorage\")\npublic class AliPaymentPlatform implements PaymentPlatform {\n\n    public static final String PLATFORM_NAME = \"aliPay\";\n    @Deprecated\n    public static final String platformName = PLATFORM_NAME;\n\n\n    /**\n     * 获取商户平台\n     *\n     * @return 商户平台\n     */\n    @Override\n    public String getPlatform() {\n        return PLATFORM_NAME;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage 支付配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage) {\n        if (payConfigStorage instanceof AliPayConfigStorage) {\n            return new AliPayService((AliPayConfigStorage) payConfigStorage);\n        }\n        AliPayConfigStorage configStorage = new AliPayConfigStorage();\n        configStorage.setInputCharset(payConfigStorage.getInputCharset());\n        configStorage.setAppId(payConfigStorage.getAppId());\n        configStorage.setPid(payConfigStorage.getPid());\n        configStorage.setAttach(payConfigStorage.getAttach());\n        configStorage.setSeller(payConfigStorage.getSeller());\n        configStorage.setKeyPrivate(payConfigStorage.getKeyPrivate());\n        configStorage.setKeyPublic(payConfigStorage.getKeyPublic());\n        configStorage.setNotifyUrl(payConfigStorage.getNotifyUrl());\n        configStorage.setReturnUrl(payConfigStorage.getReturnUrl());\n        configStorage.setPayType(payConfigStorage.getPayType());\n        configStorage.setTest(payConfigStorage.isTest());\n        configStorage.setSignType(payConfigStorage.getSignType());\n        if (payConfigStorage instanceof CommonPaymentPlatformMerchantDetails) {\n            final CommonPaymentPlatformMerchantDetails commonPaymentPlatformMerchantDetails = (CommonPaymentPlatformMerchantDetails) payConfigStorage;\n            configStorage.setAppAuthToken(commonPaymentPlatformMerchantDetails.getSubAppId());\n            certKeyPublic(configStorage, commonPaymentPlatformMerchantDetails);\n        }\n\n        return new AliPayService(configStorage);\n    }\n\n    private static void certKeyPublic(AliPayConfigStorage aliPayConfigStorage, CommonPaymentPlatformMerchantDetails payConfigStorage) {\n        final String keyPublicCert = payConfigStorage.getKeyPublic();\n        //这里通过兼容的方式去处理，匹配尾缀如果为证书文件的话就当证书处理\n        if (!keyPublicCert.endsWith(\".crt\")) {\n            return;\n        }\n        //设置为证书方式\n        aliPayConfigStorage.setCertSign(true);\n        //设置证书存储方式，这里为路径\n        aliPayConfigStorage.setCertStoreType(payConfigStorage.getCertStoreType());\n        String[] keyCert = payConfigStorage.getKeyCert().toString().split(\",\");\n        aliPayConfigStorage.setMerchantCert(keyCert[0]);\n        aliPayConfigStorage.setAliPayRootCert(keyCert[1]);\n        aliPayConfigStorage.setAliPayCert(payConfigStorage.getKeyPublic());\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage  支付配置\n     * @param httpConfigStorage 网络配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage, HttpConfigStorage httpConfigStorage) {\n        PayService payService = getPayService(payConfigStorage);\n        payService.setRequestTemplateConfigStorage(httpConfigStorage);\n        return payService;\n    }\n\n    @Override\n    public TransactionType getTransactionType(String name) {\n        if (StringUtils.isEmpty(name)) {\n            return null;\n        }\n        return AliTransactionType.valueOf(name);\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/merchant/platform/FuiouPaymentPlatform.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider.merchant.platform;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Configuration;\n\nimport com.egzosn.pay.common.api.PayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.TransactionType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.common.util.str.StringUtils;\nimport com.egzosn.pay.fuiou.api.FuiouPayConfigStorage;\nimport com.egzosn.pay.fuiou.api.FuiouPayService;\nimport com.egzosn.pay.fuiou.bean.FuiouTransactionType;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\n\n/**\n * 富友支付平台\n *\n * @author egan\n * <pre>\n *                 email egzosn@gmail.com\n *                 date  2019/4/4 14:35.\n *                 </pre>\n */\n@Configuration(FuiouPaymentPlatform.PLATFORM_NAME)\n@ConditionalOnMissingBean(FuiouPaymentPlatform.class)\n@ConditionalOnClass(name = \"com.egzosn.pay.fuiou.api.FuiouPayConfigStorage\")\npublic class FuiouPaymentPlatform implements PaymentPlatform {\n\n    public static final String PLATFORM_NAME = \"fuiouPay\";\n    @Deprecated\n    public static final String platformName = PLATFORM_NAME;\n\n\n    /**\n     * 获取商户平台\n     *\n     * @return 商户平台\n     */\n    @Override\n    public String getPlatform() {\n        return PLATFORM_NAME;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage 支付配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage) {\n        if (payConfigStorage instanceof FuiouPayConfigStorage) {\n            return new FuiouPayService((FuiouPayConfigStorage) payConfigStorage);\n        }\n        FuiouPayConfigStorage configStorage = new FuiouPayConfigStorage();\n        configStorage.setMchntCd(payConfigStorage.getPid());\n        configStorage.setNotifyUrl(payConfigStorage.getNotifyUrl());\n        configStorage.setReturnUrl(payConfigStorage.getReturnUrl());\n        configStorage.setSignType(payConfigStorage.getSignType());\n        configStorage.setPayType(payConfigStorage.getPayType());\n        configStorage.setInputCharset(payConfigStorage.getInputCharset());\n        configStorage.setTest(payConfigStorage.isTest());\n        return new FuiouPayService(configStorage);\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage  支付配置\n     * @param httpConfigStorage 网络配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage, HttpConfigStorage httpConfigStorage) {\n        PayService payService = getPayService(payConfigStorage);\n        payService.setRequestTemplateConfigStorage(httpConfigStorage);\n        return payService;\n    }\n\n    @Override\n    public TransactionType getTransactionType(String name) {\n        if (StringUtils.isEmpty(name)) {\n            return null;\n        }\n        return FuiouTransactionType.valueOf(name);\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/merchant/platform/PaymentPlatforms.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider.merchant.platform;\n\nimport com.egzosn.pay.common.bean.TransactionType;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 支付平台集\n *\n * @author egan\n *         <pre>\n * email egzosn@gmail.com\n * date  2019/4/9 15:57.\n * </pre>\n */\npublic final class PaymentPlatforms {\n\n    private static final Map<String, PaymentPlatform> PAYMENT_PLATFORMS = new HashMap<String, PaymentPlatform>();\n\n\n    /**\n     * 加载支付平台\n     *\n     * @param platform 支付平台\n     */\n    public static void loadPaymentPlatform(PaymentPlatform platform) {\n        PAYMENT_PLATFORMS.put(platform.getPlatform(), platform);\n    }\n\n    /**\n     * 获取所有的支付平台\n     *\n     * @return 所有的支付平台\n     */\n    public static Map<String, PaymentPlatform> getPaymentPlatforms() {\n        return PAYMENT_PLATFORMS;\n    }\n\n    /**\n     * 通过支付平台名称与交易类型(支付类型)名称或者交易类型\n     *\n     * @param platformName        支付平台名称\n     * @param transactionTypeName 交易类型名称\n     * @return 交易类型\n     */\n    public static TransactionType getTransactionType(String platformName, String transactionTypeName) {\n        PaymentPlatform platform = getPaymentPlatform(platformName);\n        return platform.getTransactionType(transactionTypeName);\n    }\n\n    /**\n     * 通过支付平台名称与交易类型(支付类型)名称或者交易类型\n     *\n     * @param platformName 支付平台名称\n     * @return 交易类型\n     */\n    public static PaymentPlatform getPaymentPlatform(String platformName) {\n        PaymentPlatform platform = PAYMENT_PLATFORMS.get(platformName);\n        return platform;\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/merchant/platform/PayoneerPaymentPlatform.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider.merchant.platform;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Configuration;\n\nimport com.egzosn.pay.common.api.PayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.TransactionType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.common.util.str.StringUtils;\nimport com.egzosn.pay.payoneer.api.PayoneerConfigStorage;\nimport com.egzosn.pay.payoneer.api.PayoneerPayService;\nimport com.egzosn.pay.payoneer.bean.PayoneerTransactionType;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\n\n/**\n * P卡(派安盈)支付平台\n *\n * @author egan\n * <pre>\n *                 email egzosn@gmail.com\n *                 date  2019/4/4 14:35.\n *                 </pre>\n */\n@Configuration(PayoneerPaymentPlatform.PLATFORM_NAME)\n@ConditionalOnMissingBean(PayoneerPaymentPlatform.class)\n@ConditionalOnClass(name = \"com.egzosn.pay.payoneer.api.PayoneerConfigStorage\")\npublic class PayoneerPaymentPlatform implements PaymentPlatform {\n\n\n    public static final String PLATFORM_NAME = \"payoneerPay\";\n    @Deprecated\n    public static final String platformName = PLATFORM_NAME;\n\n    /**\n     * 获取商户平台\n     *\n     * @return 商户平台\n     */\n    @Override\n    public String getPlatform() {\n        return PLATFORM_NAME;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage 支付配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage) {\n        if (payConfigStorage instanceof PayoneerConfigStorage) {\n            return new PayoneerPayService((PayoneerConfigStorage) payConfigStorage);\n        }\n        PayoneerConfigStorage configStorage = new PayoneerConfigStorage();\n        configStorage.setProgramId(payConfigStorage.getPid());\n        configStorage.setUserName(payConfigStorage.getSeller());\n        configStorage.setApiPassword(payConfigStorage.getKeyPrivate());\n        configStorage.setNotifyUrl(payConfigStorage.getNotifyUrl());\n        configStorage.setReturnUrl(payConfigStorage.getReturnUrl());\n        configStorage.setSignType(payConfigStorage.getSignType());\n        configStorage.setPayType(payConfigStorage.getPayType());\n        configStorage.setInputCharset(payConfigStorage.getInputCharset());\n        configStorage.setTest(payConfigStorage.isTest());\n        return new PayoneerPayService(configStorage);\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage  支付配置\n     * @param httpConfigStorage 网络配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage, HttpConfigStorage httpConfigStorage) {\n        PayService payService = getPayService(payConfigStorage);\n        payService.setRequestTemplateConfigStorage(httpConfigStorage);\n        return payService;\n    }\n\n    @Override\n    public TransactionType getTransactionType(String name) {\n        if (StringUtils.isEmpty(name)) {\n            return null;\n        }\n        return PayoneerTransactionType.valueOf(name);\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/merchant/platform/PaypalPaymentPlatform.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider.merchant.platform;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Configuration;\n\nimport com.egzosn.pay.common.api.PayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.TransactionType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.common.util.str.StringUtils;\nimport com.egzosn.pay.paypal.api.PayPalConfigStorage;\nimport com.egzosn.pay.paypal.api.PayPalPayService;\nimport com.egzosn.pay.paypal.bean.PayPalTransactionType;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\n\n/**\n * 贝宝支付平台\n *\n * @author egan\n * <pre>\n *                 email egzosn@gmail.com\n *                 date  2019/4/4 14:35.\n *                 </pre>\n */\n\n@Configuration(PaypalPaymentPlatform.PLATFORM_NAME)\n@ConditionalOnMissingBean(PaypalPaymentPlatform.class)\n@ConditionalOnClass(name = \"com.egzosn.pay.paypal.api.PayPalConfigStorage\")\npublic class PaypalPaymentPlatform implements PaymentPlatform {\n    public static final String PLATFORM_NAME = \"paypalPay\";\n    @Deprecated\n    public static final String platformName = PLATFORM_NAME;\n\n\n    /**\n     * 获取商户平台\n     *\n     * @return 商户平台\n     */\n    @Override\n    public String getPlatform() {\n        return PLATFORM_NAME;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage 支付配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage) {\n        if (payConfigStorage instanceof PayPalConfigStorage) {\n            return new PayPalPayService((PayPalConfigStorage) payConfigStorage);\n        }\n        PayPalConfigStorage configStorage = new PayPalConfigStorage();\n        configStorage.setClientID(payConfigStorage.getPid());\n        configStorage.setClientSecret(payConfigStorage.getKeyPrivate());\n        configStorage.setReturnUrl(payConfigStorage.getReturnUrl());\n        //取消按钮转跳地址,这里用异步通知地址的兼容的做法\n        configStorage.setNotifyUrl(payConfigStorage.getNotifyUrl());\n        configStorage.setSignType(payConfigStorage.getSignType());\n        configStorage.setPayType(payConfigStorage.getPayType());\n        configStorage.setInputCharset(payConfigStorage.getInputCharset());\n        configStorage.setTest(payConfigStorage.isTest());\n        return new PayPalPayService(configStorage);\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage  支付配置\n     * @param httpConfigStorage 网络配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage, HttpConfigStorage httpConfigStorage) {\n        PayService payService = getPayService(payConfigStorage);\n        payService.setRequestTemplateConfigStorage(httpConfigStorage);\n        return payService;\n    }\n\n    @Override\n    public TransactionType getTransactionType(String name) {\n        if (StringUtils.isEmpty(name)) {\n            return null;\n        }\n        return PayPalTransactionType.valueOf(name);\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/merchant/platform/PaypalV2PaymentPlatform.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider.merchant.platform;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Configuration;\n\nimport com.egzosn.pay.common.api.PayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.TransactionType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.common.util.str.StringUtils;\nimport com.egzosn.pay.paypal.api.PayPalConfigStorage;\nimport com.egzosn.pay.paypal.v2.api.PayPalPayService;\nimport com.egzosn.pay.paypal.v2.bean.PayPalTransactionType;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\n\n/**\n * 贝宝支付平台\n *\n * @author egan\n * <pre>\n * email egan@egzosn.com\n * date  2021/10/7.\n * </pre>\n */\n\n@Configuration(PaypalV2PaymentPlatform.PLATFORM_NAME)\n@ConditionalOnMissingBean(PaypalV2PaymentPlatform.class)\n@ConditionalOnClass(name = \"com.egzosn.pay.paypal.api.PayPalConfigStorage\")\npublic class PaypalV2PaymentPlatform implements PaymentPlatform {\n    public static final String PLATFORM_NAME = \"paypalV2Pay\";\n    @Deprecated\n    public static final String platformName = PLATFORM_NAME;\n\n\n    /**\n     * 获取商户平台\n     *\n     * @return 商户平台\n     */\n    @Override\n    public String getPlatform() {\n        return PLATFORM_NAME;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage 支付配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage) {\n        if (payConfigStorage instanceof PayPalConfigStorage) {\n            return new PayPalPayService((PayPalConfigStorage) payConfigStorage);\n        }\n        PayPalConfigStorage configStorage = new PayPalConfigStorage();\n        configStorage.setClientID(payConfigStorage.getPid());\n        configStorage.setClientSecret(payConfigStorage.getKeyPrivate());\n        configStorage.setReturnUrl(payConfigStorage.getReturnUrl());\n        //取消按钮转跳地址,这里用异步通知地址的兼容的做法\n        configStorage.setNotifyUrl(payConfigStorage.getNotifyUrl());\n        configStorage.setSignType(payConfigStorage.getSignType());\n        configStorage.setPayType(payConfigStorage.getPayType());\n        configStorage.setInputCharset(payConfigStorage.getInputCharset());\n        configStorage.setTest(payConfigStorage.isTest());\n        return new PayPalPayService(configStorage);\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage  支付配置\n     * @param httpConfigStorage 网络配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage, HttpConfigStorage httpConfigStorage) {\n        PayService payService = getPayService(payConfigStorage);\n        payService.setRequestTemplateConfigStorage(httpConfigStorage);\n        return payService;\n    }\n\n    @Override\n    public TransactionType getTransactionType(String name) {\n        if (StringUtils.isEmpty(name)) {\n            return null;\n        }\n        return PayPalTransactionType.valueOf(name);\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/merchant/platform/UnionPaymentPlatform.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider.merchant.platform;\n\nimport java.io.IOException;\n\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Configuration;\n\nimport com.egzosn.pay.common.api.PayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.CertStoreType;\nimport com.egzosn.pay.common.bean.TransactionType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.common.util.str.StringUtils;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.bean.CommonPaymentPlatformMerchantDetails;\nimport com.egzosn.pay.union.api.UnionPayConfigStorage;\nimport com.egzosn.pay.union.api.UnionPayService;\nimport com.egzosn.pay.union.bean.UnionTransactionType;\n\n/**\n * 银联支付平台\n *\n * @author egan\n * <pre>\n *                 email egzosn@gmail.com\n *                 date  2019/4/4 14:35.\n *                 </pre>\n */\n@Configuration(UnionPaymentPlatform.PLATFORM_NAME)\n@ConditionalOnMissingBean(UnionPaymentPlatform.class)\n@ConditionalOnClass(name = \"com.egzosn.pay.union.api.UnionPayConfigStorage\")\npublic class UnionPaymentPlatform implements PaymentPlatform {\n    protected final Log LOG = LogFactory.getLog(UnionPaymentPlatform.class);\n    public static final String PLATFORM_NAME = \"unionPay\";\n    @Deprecated\n    public static final String platformName = PLATFORM_NAME;\n\n\n    /**\n     * 获取商户平台\n     *\n     * @return 商户平台\n     */\n    @Override\n    public String getPlatform() {\n        return PLATFORM_NAME;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage 支付配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage) {\n        if (payConfigStorage instanceof UnionPayConfigStorage) {\n            return new UnionPayService((UnionPayConfigStorage) payConfigStorage);\n        }\n        UnionPayConfigStorage configStorage = new UnionPayConfigStorage();\n        configStorage.setMerId(payConfigStorage.getPid());\n        //是否为证书签名\n        configStorage.setCertSign(true);\n        configStorage.setPid(payConfigStorage.getPid());\n        configStorage.setNotifyUrl(payConfigStorage.getNotifyUrl());\n        configStorage.setReturnUrl(payConfigStorage.getReturnUrl());\n        configStorage.setSignType(payConfigStorage.getSignType());\n        configStorage.setPayType(payConfigStorage.getPayType());\n        configStorage.setInputCharset(payConfigStorage.getInputCharset());\n        configStorage.setTest(payConfigStorage.isTest());\n        if (payConfigStorage instanceof CommonPaymentPlatformMerchantDetails) {\n            CommonPaymentPlatformMerchantDetails merchantDetails = (CommonPaymentPlatformMerchantDetails) payConfigStorage;\n            //设置证书对应的存储方式\n            configStorage.setCertStoreType(merchantDetails.getCertStoreType());\n            try {\n                //中级证书路径\n                configStorage.setAcpMiddleCert(merchantDetails.getKeyPublicCertInputStream());\n                //根证书路径\n                configStorage.setAcpRootCert(merchantDetails.getKeyCertInputStream());\n                // 私钥证书路径\n                configStorage.setKeyPrivateCert(merchantDetails.getKeystoreInputStream());\n                //这里转变为流的方式\n                configStorage.setCertStoreType(CertStoreType.INPUT_STREAM);\n            }\n            catch (IOException e) {\n                LOG.error(e);\n            }\n            //私钥证书对应的密码\n            configStorage.setKeyPrivateCertPwd(merchantDetails.getKeystorePwd());\n\n        }\n\n        return new UnionPayService(configStorage);\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage  支付配置\n     * @param httpConfigStorage 网络配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage, HttpConfigStorage httpConfigStorage) {\n        PayService payService = getPayService(payConfigStorage);\n        payService.setRequestTemplateConfigStorage(httpConfigStorage);\n        return payService;\n    }\n\n    @Override\n    public TransactionType getTransactionType(String name) {\n        if (StringUtils.isEmpty(name)) {\n            return null;\n        }\n        return UnionTransactionType.valueOf(name);\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/merchant/platform/WxPaymentPlatform.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider.merchant.platform;\n\nimport java.io.IOException;\n\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Configuration;\n\nimport com.egzosn.pay.common.api.PayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.CertStoreType;\nimport com.egzosn.pay.common.bean.TransactionType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.common.util.str.StringUtils;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.bean.CommonPaymentPlatformMerchantDetails;\nimport com.egzosn.pay.wx.api.WxPayConfigStorage;\nimport com.egzosn.pay.wx.api.WxPayService;\nimport com.egzosn.pay.wx.bean.WxTransactionType;\n\n/**\n * 微信支付平台\n *\n * @author egan\n * <pre>\n *                 email egzosn@gmail.com\n *                 date  2019/4/4 14:35.\n *                 </pre>\n */\n@Configuration(WxPaymentPlatform.PLATFORM_NAME)\n@ConditionalOnMissingBean(WxPaymentPlatform.class)\n@ConditionalOnClass(name = \"com.egzosn.pay.wx.api.WxPayConfigStorage\")\npublic class WxPaymentPlatform extends WxPayConfigStorage implements PaymentPlatform {\n\n    protected final Log LOG = LogFactory.getLog(WxPaymentPlatform.class);\n\n    public static final String PLATFORM_NAME = \"wxPay\";\n    @Deprecated\n    public static final String platformName = PLATFORM_NAME;\n\n\n    /**\n     * 获取商户平台\n     *\n     * @return 商户平台\n     */\n    @Override\n    public String getPlatform() {\n        return PLATFORM_NAME;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage 支付配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage) {\n        return getPayService(payConfigStorage, null);\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage  支付配置\n     * @param httpConfigStorage 网络配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage, HttpConfigStorage httpConfigStorage) {\n        if (payConfigStorage instanceof WxPayConfigStorage) {\n            WxPayService wxPayService = new WxPayService((WxPayConfigStorage) payConfigStorage);\n            wxPayService.setRequestTemplateConfigStorage(httpConfigStorage);\n            return wxPayService;\n        }\n        WxPayConfigStorage configStorage = new WxPayConfigStorage();\n        configStorage.setInputCharset(payConfigStorage.getInputCharset());\n        configStorage.setAppId(payConfigStorage.getAppId());\n        configStorage.setMchId(payConfigStorage.getPid());\n        configStorage.setAttach(payConfigStorage.getAttach());\n        configStorage.setKeyPrivate(payConfigStorage.getKeyPrivate());\n        configStorage.setKeyPublic(payConfigStorage.getKeyPublic());\n        configStorage.setNotifyUrl(payConfigStorage.getNotifyUrl());\n        configStorage.setReturnUrl(payConfigStorage.getReturnUrl());\n        configStorage.setPayType(payConfigStorage.getPayType());\n        configStorage.setTest(payConfigStorage.isTest());\n        configStorage.setSignType(payConfigStorage.getSignType());\n\n        if (payConfigStorage instanceof CommonPaymentPlatformMerchantDetails) {\n            CommonPaymentPlatformMerchantDetails merchantDetails = (CommonPaymentPlatformMerchantDetails) payConfigStorage;\n            configStorage.setSubAppId(merchantDetails.getSubAppId());\n            configStorage.setSubMchId(merchantDetails.getSubMchId());\n            if (null != merchantDetails.getKeyCert()) {\n                if (null == httpConfigStorage) {\n                    httpConfigStorage = new HttpConfigStorage();\n                }\n                httpConfigStorage.setCertStoreType(merchantDetails.getCertStoreType());\n                try {\n                    httpConfigStorage.setKeystore(merchantDetails.getKeyCertInputStream());\n                }\n                catch (IOException e) {\n                    LOG.error(e);\n                }\n\n                httpConfigStorage.setCertStoreType(CertStoreType.INPUT_STREAM);\n                httpConfigStorage.setStorePassword(merchantDetails.getKeystorePwd());\n\n            }\n        }\n\n\n        WxPayService wxPayService = new WxPayService(configStorage);\n        wxPayService.setRequestTemplateConfigStorage(httpConfigStorage);\n        return wxPayService;\n    }\n\n    @Override\n    public TransactionType getTransactionType(String name) {\n        if (StringUtils.isEmpty(name)) {\n            return null;\n        }\n        return WxTransactionType.valueOf(name);\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/merchant/platform/WxV3CombinePaymentPlatform.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider.merchant.platform;\n\nimport java.io.IOException;\n\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Configuration;\n\nimport com.egzosn.pay.common.api.PayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.CertStoreType;\nimport com.egzosn.pay.common.bean.TransactionType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.common.util.str.StringUtils;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.bean.CommonPaymentPlatformMerchantDetails;\nimport com.egzosn.pay.wx.v3.api.WxCombinePayService;\nimport com.egzosn.pay.wx.v3.api.WxPayConfigStorage;\nimport com.egzosn.pay.wx.v3.bean.WxTransactionType;\n\n/**\n * 微信V3合单支付平台\n *\n * @author egan\n * <pre>\n * email egan@egzosn.com\n * date  2021/10/7.\n * </pre>\n */\n@Configuration(WxV3CombinePaymentPlatform.PLATFORM_NAME)\n@ConditionalOnMissingBean(WxV3CombinePaymentPlatform.class)\n@ConditionalOnClass(name = \"com.egzosn.pay.wx.v3.api.WxPayConfigStorage\")\npublic class WxV3CombinePaymentPlatform extends WxPayConfigStorage implements PaymentPlatform {\n\n    private final Log LOG = LogFactory.getLog(WxV3CombinePaymentPlatform.class);\n\n    public static final String PLATFORM_NAME = \"wxV3CombinePay\";\n    @Deprecated\n    public static final String platformName = PLATFORM_NAME;\n\n\n    /**\n     * 获取商户平台\n     *\n     * @return 商户平台\n     */\n    @Override\n    public String getPlatform() {\n        return PLATFORM_NAME;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage 支付配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage) {\n        return getPayService(payConfigStorage, null);\n    }\n\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage  支付配置\n     * @param httpConfigStorage 网络配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage, HttpConfigStorage httpConfigStorage) {\n        if (payConfigStorage instanceof WxPayConfigStorage) {\n            WxCombinePayService wxPayService = new WxCombinePayService((WxPayConfigStorage) payConfigStorage);\n            wxPayService.setRequestTemplateConfigStorage(httpConfigStorage);\n            return wxPayService;\n        }\n        WxPayConfigStorage configStorage = new WxPayConfigStorage();\n        configStorage.setInputCharset(payConfigStorage.getInputCharset());\n        configStorage.setAppId(payConfigStorage.getAppId());\n        configStorage.setMchId(payConfigStorage.getPid());\n        configStorage.setAttach(payConfigStorage.getAttach());\n        configStorage.setV3ApiKey(payConfigStorage.getKeyPrivate());\n        configStorage.setKeyPublic(payConfigStorage.getKeyPublic());\n        configStorage.setNotifyUrl(payConfigStorage.getNotifyUrl());\n        configStorage.setReturnUrl(payConfigStorage.getReturnUrl());\n        configStorage.setPayType(payConfigStorage.getPayType());\n        configStorage.setTest(payConfigStorage.isTest());\n        configStorage.setSignType(payConfigStorage.getSignType());\n        //是否为证书签名\n        configStorage.setCertSign(true);\n        if (payConfigStorage instanceof CommonPaymentPlatformMerchantDetails) {\n            CommonPaymentPlatformMerchantDetails merchantDetails = (CommonPaymentPlatformMerchantDetails) payConfigStorage;\n            configStorage.setSubAppId(merchantDetails.getSubAppId());\n            configStorage.setSubMchId(merchantDetails.getSubMchId());\n            if (null != merchantDetails.getKeyCert()) {\n                configStorage.setCertStoreType(merchantDetails.getCertStoreType());\n                try {\n                    configStorage.setApiClientKeyP12(merchantDetails.getKeyCertInputStream());\n                }\n                catch (IOException e) {\n                    LOG.error(e);\n                }\n                configStorage.setCertStoreType(CertStoreType.INPUT_STREAM);\n\n            }\n        }\n\n\n        WxCombinePayService wxPayService = new WxCombinePayService(configStorage);\n        wxPayService.setRequestTemplateConfigStorage(httpConfigStorage);\n        return wxPayService;\n    }\n\n    @Override\n    public TransactionType getTransactionType(String name) {\n        if (StringUtils.isEmpty(name)) {\n            return null;\n        }\n        return WxTransactionType.valueOf(name);\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/merchant/platform/WxV3PaymentPlatform.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider.merchant.platform;\n\nimport java.io.IOException;\n\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Configuration;\n\nimport com.egzosn.pay.common.api.PayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.CertStoreType;\nimport com.egzosn.pay.common.bean.TransactionType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.common.util.str.StringUtils;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.bean.CommonPaymentPlatformMerchantDetails;\nimport com.egzosn.pay.wx.v3.api.WxPayConfigStorage;\nimport com.egzosn.pay.wx.v3.api.WxPayService;\nimport com.egzosn.pay.wx.v3.bean.WxTransactionType;\n\n/**\n * 微信V3支付平台\n *\n * @author egan\n * <pre>\n * email egan@egzosn.com\n * date  2021/10/7.\n * </pre>\n */\n@Configuration(WxV3PaymentPlatform.PLATFORM_NAME)\n@ConditionalOnMissingBean(WxV3PaymentPlatform.class)\n@ConditionalOnClass(name = \"com.egzosn.pay.wx.v3.api.WxPayConfigStorage\")\npublic class WxV3PaymentPlatform extends WxPayConfigStorage implements PaymentPlatform {\n\n    private final Log LOG = LogFactory.getLog(WxV3PaymentPlatform.class);\n\n    public static final String PLATFORM_NAME = \"wxV3Pay\";\n    @Deprecated\n    public static final String platformName = PLATFORM_NAME;\n\n\n    /**\n     * 获取商户平台\n     *\n     * @return 商户平台\n     */\n    @Override\n    public String getPlatform() {\n        return PLATFORM_NAME;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage 支付配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage) {\n        return getPayService(payConfigStorage, null);\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage  支付配置\n     * @param httpConfigStorage 网络配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage, HttpConfigStorage httpConfigStorage) {\n        if (payConfigStorage instanceof WxPayConfigStorage) {\n            WxPayService wxPayService = new WxPayService((WxPayConfigStorage) payConfigStorage);\n            wxPayService.setRequestTemplateConfigStorage(httpConfigStorage);\n            return wxPayService;\n        }\n        WxPayConfigStorage configStorage = new WxPayConfigStorage();\n        configStorage.setInputCharset(payConfigStorage.getInputCharset());\n        configStorage.setAppId(payConfigStorage.getAppId());\n        configStorage.setMchId(payConfigStorage.getPid());\n        configStorage.setAttach(payConfigStorage.getAttach());\n        configStorage.setV3ApiKey(payConfigStorage.getKeyPrivate());\n        configStorage.setKeyPublic(payConfigStorage.getKeyPublic());\n        configStorage.setNotifyUrl(payConfigStorage.getNotifyUrl());\n        configStorage.setReturnUrl(payConfigStorage.getReturnUrl());\n        configStorage.setPayType(payConfigStorage.getPayType());\n        configStorage.setTest(payConfigStorage.isTest());\n        configStorage.setSignType(payConfigStorage.getSignType());\n        if (payConfigStorage instanceof CommonPaymentPlatformMerchantDetails) {\n            CommonPaymentPlatformMerchantDetails merchantDetails = (CommonPaymentPlatformMerchantDetails) payConfigStorage;\n            configStorage.setSubAppId(merchantDetails.getSubAppId());\n            configStorage.setSubMchId(merchantDetails.getSubMchId());\n            if (null != merchantDetails.getKeyCert()) {\n                configStorage.setCertStoreType(merchantDetails.getCertStoreType());\n                try {\n                    configStorage.setApiClientKeyP12(merchantDetails.getKeyCertInputStream());\n                }\n                catch (IOException e) {\n                    LOG.error(e);\n                }\n                configStorage.setCertStoreType(CertStoreType.INPUT_STREAM);\n\n            }\n        }\n\n\n        WxPayService wxPayService = new WxPayService(configStorage);\n        wxPayService.setRequestTemplateConfigStorage(httpConfigStorage);\n        return wxPayService;\n    }\n\n    @Override\n    public TransactionType getTransactionType(String name) {\n        if (StringUtils.isEmpty(name)) {\n            return null;\n        }\n        return WxTransactionType.valueOf(name);\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/merchant/platform/WxV3ProfitSharingPlatform.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider.merchant.platform;\n\nimport java.io.IOException;\n\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Configuration;\n\nimport com.egzosn.pay.common.api.PayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.CertStoreType;\nimport com.egzosn.pay.common.bean.TransactionType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.common.util.str.StringUtils;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.merchant.bean.CommonPaymentPlatformMerchantDetails;\nimport com.egzosn.pay.wx.v3.api.WxPayConfigStorage;\nimport com.egzosn.pay.wx.v3.api.WxProfitSharingService;\nimport com.egzosn.pay.wx.v3.bean.WxTransactionType;\n\n/**\n * 微信V3分账平台\n *\n * @author egan\n * <pre>\n * email egan@egzosn.com\n * date  2021/10/7.\n * </pre>\n */\n@Configuration(WxV3ProfitSharingPlatform.PLATFORM_NAME)\n@ConditionalOnMissingBean(WxV3ProfitSharingPlatform.class)\n@ConditionalOnClass(name = \"com.egzosn.pay.wx.v3.api.WxPayConfigStorage\")\npublic class WxV3ProfitSharingPlatform extends WxPayConfigStorage implements PaymentPlatform {\n\n    private final Log LOG = LogFactory.getLog(WxV3ProfitSharingPlatform.class);\n\n    public static final String PLATFORM_NAME = \"wxV3ProfitSharing\";\n    @Deprecated\n    public static final String platformName = PLATFORM_NAME;\n\n    /**\n     * 获取商户平台\n     *\n     * @return 商户平台\n     */\n    @Override\n    public String getPlatform() {\n        return PLATFORM_NAME;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage 支付配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage) {\n        return getPayService(payConfigStorage, null);\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage  支付配置\n     * @param httpConfigStorage 网络配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage, HttpConfigStorage httpConfigStorage) {\n        if (payConfigStorage instanceof WxPayConfigStorage) {\n            WxProfitSharingService wxPayService = new WxProfitSharingService((WxPayConfigStorage) payConfigStorage);\n            wxPayService.setRequestTemplateConfigStorage(httpConfigStorage);\n            return wxPayService;\n        }\n        WxPayConfigStorage configStorage = new WxPayConfigStorage();\n        configStorage.setInputCharset(payConfigStorage.getInputCharset());\n        configStorage.setAppId(payConfigStorage.getAppId());\n        configStorage.setMchId(payConfigStorage.getPid());\n        configStorage.setAttach(payConfigStorage.getAttach());\n        configStorage.setV3ApiKey(payConfigStorage.getKeyPrivate());\n        configStorage.setKeyPublic(payConfigStorage.getKeyPublic());\n        configStorage.setNotifyUrl(payConfigStorage.getNotifyUrl());\n        configStorage.setReturnUrl(payConfigStorage.getReturnUrl());\n        configStorage.setPayType(payConfigStorage.getPayType());\n        configStorage.setTest(payConfigStorage.isTest());\n        configStorage.setSignType(payConfigStorage.getSignType());\n        //是否为证书签名\n        if (payConfigStorage instanceof CommonPaymentPlatformMerchantDetails) {\n            CommonPaymentPlatformMerchantDetails merchantDetails = (CommonPaymentPlatformMerchantDetails) payConfigStorage;\n            configStorage.setSubAppId(merchantDetails.getSubAppId());\n            configStorage.setSubMchId(merchantDetails.getSubMchId());\n            if (null != merchantDetails.getKeyCert()) {\n                configStorage.setCertStoreType(merchantDetails.getCertStoreType());\n                try {\n                    configStorage.setApiClientKeyP12(merchantDetails.getKeyCertInputStream());\n                }\n                catch (IOException e) {\n                    LOG.error(e);\n                }\n                configStorage.setCertStoreType(CertStoreType.INPUT_STREAM);\n\n            }\n        }\n\n\n        WxProfitSharingService wxPayService = new WxProfitSharingService(configStorage);\n        wxPayService.setRequestTemplateConfigStorage(httpConfigStorage);\n        return wxPayService;\n    }\n\n    @Override\n    public TransactionType getTransactionType(String name) {\n        if (StringUtils.isEmpty(name)) {\n            return null;\n        }\n        return WxTransactionType.valueOf(name);\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/provider/merchant/platform/YoudianPaymentPlatform.java",
    "content": "package com.egzosn.pay.spring.boot.core.provider.merchant.platform;\n\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Configuration;\n\nimport com.egzosn.pay.common.api.PayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.TransactionType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.common.util.str.StringUtils;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.wx.youdian.api.WxYouDianPayConfigStorage;\nimport com.egzosn.pay.wx.youdian.api.WxYouDianPayService;\nimport com.egzosn.pay.wx.youdian.bean.YoudianTransactionType;\n\n/**\n * 友店支付平台\n *\n * @author egan\n * <pre>\n *         email egzosn@gmail.com\n *         date  2019/4/4 14:35.\n *         </pre>\n */\n@Configuration(YoudianPaymentPlatform.PLATFORM_NAME)\n@ConditionalOnMissingBean(YoudianPaymentPlatform.class)\n@ConditionalOnClass(name = \"com.egzosn.pay.wx.youdian.api.WxYouDianPayConfigStorage\")\npublic class YoudianPaymentPlatform implements PaymentPlatform {\n\n    public static final String PLATFORM_NAME = \"youdianPay\";\n    @Deprecated\n    public static final String platformName = PLATFORM_NAME;\n\n\n    /**\n     * 获取商户平台\n     *\n     * @return 商户平台\n     */\n    @Override\n    public String getPlatform() {\n        return PLATFORM_NAME;\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage 支付配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage) {\n        if (payConfigStorage instanceof WxYouDianPayConfigStorage) {\n            return new WxYouDianPayService((WxYouDianPayConfigStorage) payConfigStorage);\n        }\n        WxYouDianPayConfigStorage configStorage = new WxYouDianPayConfigStorage();\n        configStorage.setKeyPrivate(payConfigStorage.getKeyPrivate());\n        configStorage.setKeyPublic(payConfigStorage.getKeyPublic());\n        configStorage.setSignType(payConfigStorage.getSignType());\n        configStorage.setPayType(payConfigStorage.getPayType());\n        configStorage.setSeller(payConfigStorage.getSeller());\n        configStorage.setInputCharset(payConfigStorage.getInputCharset());\n        configStorage.setTest(payConfigStorage.isTest());\n        return new WxYouDianPayService(configStorage);\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage  支付配置\n     * @param httpConfigStorage 网络配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage, HttpConfigStorage httpConfigStorage) {\n        PayService payService = getPayService(payConfigStorage);\n        payService.setRequestTemplateConfigStorage(httpConfigStorage);\n        return payService;\n    }\n\n    @Override\n    public TransactionType getTransactionType(String name) {\n        if (StringUtils.isEmpty(name)) {\n            return null;\n        }\n        return YoudianTransactionType.valueOf(name);\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot/src/main/java/com/egzosn/pay/spring/boot/core/utils/SqlTools.java",
    "content": "package com.egzosn.pay.spring.boot.core.utils;\n\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Types;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n\n/**\n * jdbc sql生成语句生产\n *\n * @author ZaoSheng\n * Wed Nov 162 17:31:32 CST 2015\n */\npublic class SqlTools {\n    public static final String SEPARATED = \", \";\n    private static final Pattern PATTERN = Pattern.compile(\":([0-9A-Za-z_]+)[\" + SEPARATED + \"]?\");\n\n    /**\n     * 获取统计的sql\n     *\n     * @param sql 原始sql\n     * @return 转化后的sql\n     */\n    public static String getCountSQL(final String sql) {\n        return getCountSQL(sql, null);\n    }\n\n    /**\n     * 获取统计的sql\n     *\n     * @param sql 原始sql\n     * @return 转化后的sql\n     */\n    public static String getCountOracleSQL(final String sql) {\n        return getCountOracleSQL(sql, null);\n\n    }\n\n    /**\n     * 获取统计的sql\n     *\n     * @param sql        原始sql\n     * @param countField 需要统计的字段\n     * @return 转化后的sql\n     */\n    public static String getCountSQL(final String sql, String countField) {\n\n        String countSql = String.format(\"SELECT  COUNT(%s) \", null == countField ? \"*\" : countField);\n        String upperSql = sql.toUpperCase();\n        int start = upperSql.indexOf(\"FROM \");\n        int end = upperSql.lastIndexOf(\"ORDER BY \");\n        countSql += sql.substring(start, end == -1 ? sql.length() : end);\n        return countSql;\n    }\n\n    /**\n     * 获取统计的sql\n     *\n     * @param sql        原始sql\n     * @param countField 需要统计的字段\n     * @return 转化后的sql\n     */\n    public static String getCountOracleSQL(final String sql, String countField) {\n\n        String countSql = String.format(\"SELECT  COUNT(%s) \", null == countField ? \"*\" : countField);\n        String upperSql = sql.toUpperCase().replace(\"SELECT * FROM ( \", \"\").replace(\" ) WHERE ROWNUM BETWEEN %s AND %s\", \"\");\n        int start = upperSql.indexOf(\"FROM \");\n        int end = upperSql.lastIndexOf(\"ORDER BY \");\n        countSql += sql.substring(start, end == -1 ? sql.length() : end);\n        return countSql;\n    }\n\n    /**\n     * 移除sql的group部分\n     *\n     * @param sql 原始sql\n     * @return 转化后的sql\n     */\n    public static String removeGROUP(final String sql) {\n\n        String upperSql = sql.toUpperCase();\n        int end = upperSql.indexOf(\" GROUP \");\n        return -1 == end ? sql : sql.substring(0, end);\n    }\n\n    /**\n     * 获取sql\n     *\n     * @param select 需要查询的字段\n     * @param tableName 表名\n     * @return sql\n     */\n    public static String getSelectSQL(String select, String tableName) {\n        if (null == select || \"\".equals(select)) {\n            select = \"*\";\n        }\n        return String.format(\"select %s from %s \", select, tableName);\n\n    }\n\n\n    /**\n     * 获取sql\n     *\n     * @param select    需要查询的字段\n     * @param tableName 表名\n     * @param alias     别名\n     * @param where     条件开始的语句\n     * @return 拼装好的sql\n     */\n    public static String getSQL(String select, String tableName, String alias, String where) {\n        return String.format(\"%s %s %s\", getSelectSQL(select, tableName), alias, where);\n    }\n\n\n    /**\n     * 拼接分页部分\n     *\n     * @param pageNumber 页号\n     * @param pageSize   每页大小\n     * @return 拼装 分页sql\n     */\n    public static String forPaginate(int pageNumber, int pageSize) {\n        int offset = pageSize * (pageNumber - 1);\n        return String.format(\" limit %s,%s\", offset, pageSize);\n    }\n\n\n    /**\n     * 拼接分页部分\n     *\n     * @param sql sql\n     * @param pageNumber 页号\n     * @param pageSize   每页大小\n     * @return 拼装 分页sql\n     */\n    public static String forPaginate(String sql, int pageNumber, int pageSize) {\n        int offset = pageSize * (pageNumber - 1);\n        String sqltmp = String.format(\"SELECT *  FROM (SELECT ROWNUM  RN,a.* FROM (  %s  ) a  WHERE ROWNUM <= %s) WHERE RN >%s\", sql, offset + pageSize, offset);\n        return sqltmp;\n    }\n\n\n    /**\n     * 设置 参数\n     *\n     * @param ps     代替对象\n     * @param params 参数\n     * @throws SQLException 设置参数异常\n     */\n    public static void fillStatement(PreparedStatement ps, List<Object> params) throws SQLException {\n        if (null == params || params.isEmpty()) {\n            return;\n        }\n\n        int i = 0;\n        for (Object param : params) {\n            if (param instanceof List) {\n                fillStatement(ps, (List) param);\n                ps.addBatch();\n                continue;\n            }\n\n            if (param instanceof Object[]) {\n                fillStatement(ps, (Object[]) param);\n                ps.addBatch();\n                continue;\n            }\n\n            if (null == param) {\n                ps.setNull(++i, Types.OTHER);\n                continue;\n            }\n            ps.setObject(++i, param);\n\n        }\n\n    }\n\n    /**\n     * 设置 参数\n     *\n     * @param ps     代替对象\n     * @param params 参数\n     * @throws SQLException 设置参数异常\n     */\n    public static void fillStatement(PreparedStatement ps, Object... params) throws SQLException {\n\n\n        if (null == params) {\n            return;\n        }\n        if (params instanceof Object[][]) {\n            for (Object[] v : (Object[][]) params) {\n                fillStatement(ps, v);\n                ps.addBatch();\n            }\n        }\n        else {\n            int i = 0;\n            for (Object param : params) {\n                if (null == param) {\n                    ps.setNull(++i, Types.OTHER);\n                    continue;\n                }\n                ps.setObject(++i, param);\n            }\n        }\n\n\n    }\n\n\n    /**\n     * 生成插入语句\n     *\n     * @param tableName      表名\n     * @param keyColumnNames 数据库列集\n     * @return 插入语句\n     */\n    public static StringBuilder generateInsertString(String tableName, List<String> keyColumnNames) {\n        StringBuilder sql = new StringBuilder();\n        sql.append(\"insert into \").append(tableName).append(\"(\");\n        StringBuilder temp = new StringBuilder(\") values(\");\n        boolean flag = false;\n        for (String colName : keyColumnNames) {\n            if (flag) {\n                sql.append(\", \");\n                temp.append(\", \");\n            }\n            sql.append(\"\").append(colName).append(\"\");\n            temp.append(\"?\");\n            flag = true;\n        }\n        return sql.append(temp.toString()).append(\")\");\n\n    }\n\n    /**\n     * 生成更新语句\n     *\n     * @param tableName      表名\n     * @param keyColumnNames 数据库列集\n     * @param idColumn       主键列\n     * @return 更新语句\n     */\n    public static StringBuilder generateUpdateByRowIdString(String tableName, List<String> keyColumnNames, String idColumn) {\n        StringBuilder sql = new StringBuilder();\n        sql.append(\"update \").append(tableName).append(\" set \");\n        int i = 0;\n        for (String colName : keyColumnNames) {\n            if (i != 0) {\n                sql.append(\", \");\n            }\n            sql.append(\"\").append(colName).append(\" = ? \");\n            i++;\n        }\n//\t\tkeyColumnNames.add(idColumn);\n        sql.append(\" where \").append(idColumn).append(\" = ?\");\n        return sql;\n    }\n\n    /**\n     * 通过 Map 获取保存的sql\n     *\n     * @param table 表名\n     * @param attrs Map属性集\n     * @param paras 参数集\n     * @return 生成sql\n     */\n    public static StringBuilder forMapSave(String table, Map<String, Object> attrs, List<Object> paras) {\n        StringBuilder sql = new StringBuilder();\n        sql.append(\"insert into \").append(table).append(\"(\");\n        StringBuilder temp = new StringBuilder(\") values(\");\n        for (Map.Entry<String, Object> entry : attrs.entrySet()) {\n            if (null == entry.getValue()) {\n                continue;\n            }\n            if (paras.size() > 0) {\n                sql.append(\", \");\n                temp.append(\", \");\n            }\n            sql.append(' ').append(entry.getKey()).append(' ');\n            temp.append(\"?\");\n            paras.add(entry.getValue());\n        }\n        sql.append(temp).append(\")\");\n        return sql;\n    }\n\n\n    /**\n     * 生成更新的sql\n     *\n     * @param table    表名\n     * @param attrs    更新的属性\n     * @param where    条件部分\n     * @param whereVal 条件对应的值\n     * @param paras    参数集\n     * @return 更新的sql\n     */\n    public static StringBuilder forMapUpdate(String table, Map<String, Object> attrs, String where, List<Object> whereVal, List<Object> paras) {\n\n        StringBuilder sql = new StringBuilder();\n        sql.append(\"update \").append(table).append(\" set \");\n        for (Map.Entry<String, Object> entry : attrs.entrySet()) {\n            if (!paras.isEmpty()) {\n                sql.append(\", \");\n            }\n            sql.append(' ').append(entry.getKey()).append(\" = ? \");\n            paras.add(entry.getValue());\n        }\n\n        sql.append(where);\n        paras.addAll(whereVal);\n\n        return sql;\n    }\n\n    /**\n     * 生成更新的sql\n     *\n     * @param table 表名\n     * @param attrs 更新的属性\n     * @param where 条件部分 and eq 级别\n     * @param paras 参数集\n     * @return 更新的sql\n     */\n    public static StringBuilder forMapUpdate(String table, Map<String, Object> attrs, Map<String, Object> where, List<Object> paras) {\n        boolean flag = false;\n        StringBuilder sql = new StringBuilder();\n        sql.append(\"update \").append(table).append(\" set \");\n        for (Map.Entry<String, Object> entry : attrs.entrySet()) {\n            if (flag) {\n                sql.append(\", \");\n            }\n            sql.append(' ').append(entry.getKey()).append(\" = ? \");\n            paras.add(entry.getValue());\n            flag = true;\n        }\n        sql.append(\" where \");\n        for (Map.Entry<String, Object> entry : where.entrySet()) {\n            if (!flag) {\n                sql.append(\" and \");\n            }\n            sql.append(' ').append(entry.getKey()).append(\" = ? \");\n            paras.add(entry.getValue());\n            flag = false;\n        }\n        return sql;\n    }\n\n\n    /**\n     * 冒号形式的sql转化为问号形式\n     *\n     * @param sql    原始sql\n     * @param attrs  属性\n     * @param values 转化后的属性集\n     * @return 转化后的sql\n     */\n    public static String forConverSQL(String sql, Map<String, Object> attrs, List<Object> values) {\n        Matcher matcher = PATTERN.matcher(sql);\n        String rexp = null;\n        while (matcher.find()) {\n            String group = matcher.group(1);\n            Object ov = attrs.get(group);\n            if (ov instanceof Collection) {\n                StringBuilder sb = new StringBuilder();\n                Collection vs = (Collection) ov;\n                for (Object v : vs) {\n                    sb.append(\"?,\");\n                    values.add(v);\n                }\n                sb.deleteCharAt(sb.length() - 1);\n                rexp = sb.toString();\n            }\n            else {\n                values.add(ov);\n                rexp = \"?\";\n            }\n            sql = sql.replace(String.format(\":%s\", group), rexp);\n        }\n        return sql;\n    }\n\n    /**\n     * 根据数组对象生成对应的in部分\n     *\n     * @param num 生成\"?\"的数量\n     *\n     *            <code> forQuestionMarkSQL(3)  = ?,?,? </code>\n     * @return 问号，逗号隔开\n     */\n    public static String forQuestionMarkSQL(int num) {\n\n        StringBuilder sb = new StringBuilder();\n        for (int i = 0; i < num; i++) {\n            sb.append(\"?,\");\n        }\n        sb.deleteCharAt(sb.length() - 1);\n\n        return sb.toString();\n    }\n\n    /**\n     * 将集合以分隔符的形式进行连接成对应字符串\n     *\n     * @param list      集合\n     * @param separated 分隔符\n     * @return 连接字符串\n     */\n    public static String join(List<String> list, String separated) {\n        StringBuilder sb = new StringBuilder();\n        for (int i = 0; i < list.size(); i++) {\n            if (sb.length() != 0) {\n                sb.append(separated);\n            }\n            sb.append(list.get(i));\n\n        }\n        return sb.toString();\n\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot-autoconfigue/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>pay-spring-boot-starter-parent</artifactId>\n        <groupId>com.egzosn</groupId>\n      <version>1.0.5</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>pay-spring-boot-autoconfigue</artifactId>\n    <name>pay-spring-boot-autoconfigue</name>\n    <dependencies>\n    <dependency>\n        <groupId>com.egzosn</groupId>\n        <artifactId>pay-spring-boot</artifactId>\n        <version>${project.version}</version>\n    </dependency>\n    </dependencies>\n\n</project>"
  },
  {
    "path": "pay-spring-boot-autoconfigue/src/main/java/com/egzosn/pay/spring/boot/autoconfigue/PayAutoConfiguration.java",
    "content": "package com.egzosn.pay.spring.boot.autoconfigue;\n\nimport java.util.List;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.ImportAutoConfiguration;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnBean;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.annotation.Order;\n\nimport com.egzosn.pay.spring.boot.core.MerchantPayServiceManager;\nimport com.egzosn.pay.spring.boot.core.PayServiceConfigurer;\nimport com.egzosn.pay.spring.boot.core.PayServiceManager;\nimport com.egzosn.pay.spring.boot.core.configurers.DefalutPayMessageConfigurer;\nimport com.egzosn.pay.spring.boot.core.configurers.MerchantDetailsServiceConfigurer;\nimport com.egzosn.pay.spring.boot.core.configurers.PayMessageConfigurer;\nimport com.egzosn.pay.spring.boot.core.merchant.MerchantDetailsService;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.AliPaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.FuiouPaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaymentPlatforms;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PayoneerPaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaypalPaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaypalV2PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.UnionPaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.WxPaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.WxV3CombinePaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.WxV3PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.WxV3ProfitSharingPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.YoudianPaymentPlatform;\n\n/**\n * 支付转载配置\n *\n * @author egan\n * <pre>\n *  email egzosn@gmail.com\n *  date  2018/11/21.\n *  </pre>\n */\n@Configuration\n@ImportAutoConfiguration({AliPaymentPlatform.class, FuiouPaymentPlatform.class, PayoneerPaymentPlatform.class, PaypalPaymentPlatform.class, UnionPaymentPlatform.class, WxPaymentPlatform.class, WxV3PaymentPlatform.class, WxV3ProfitSharingPlatform.class, WxV3CombinePaymentPlatform.class, PaypalV2PaymentPlatform.class, YoudianPaymentPlatform.class})\npublic class PayAutoConfiguration {\n\n\n    @Autowired(required = false)\n    @Order\n    public void loadPaymentPlatforms(List<PaymentPlatform> platforms) {\n        for (PaymentPlatform platform : platforms) {\n            PaymentPlatforms.loadPaymentPlatform(platform);\n        }\n    }\n\n\n    @Bean\n    @ConditionalOnMissingBean(MerchantDetailsServiceConfigurer.class)\n    @ConditionalOnBean(PayServiceConfigurer.class)\n    public MerchantDetailsServiceConfigurer detailsServiceConfigurer() {\n        return new MerchantDetailsServiceConfigurer();\n    }\n\n    @Bean\n    @ConditionalOnMissingBean(MerchantDetailsService.class)\n    @ConditionalOnBean(PayServiceConfigurer.class)\n    protected MerchantDetailsService configure(PayServiceConfigurer configurer, MerchantDetailsServiceConfigurer merchantDetails, PayMessageConfigurer payMessageConfigurer) {\n        configurer.configure(merchantDetails);\n        configurer.configure(payMessageConfigurer);\n        MerchantDetailsService detailsService = merchantDetails.getBuilder().build();\n        return detailsService;\n    }\n\n    @Bean\n    @Order\n    @ConditionalOnBean(MerchantDetailsService.class)\n    @ConditionalOnMissingBean(PayServiceManager.class)\n    public PayServiceManager payServiceManager() {\n        return new MerchantPayServiceManager();\n    }\n\n\n    @Bean\n    @ConditionalOnMissingBean(PayMessageConfigurer.class)\n    public PayMessageConfigurer messageHandlerConfigurer() {\n        return new DefalutPayMessageConfigurer();\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot-autoconfigue/src/main/resources/META-INF/spring.factories",
    "content": "org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\\ncom.egzosn.pay.spring.boot.autoconfigue.PayAutoConfiguration"
  },
  {
    "path": "pay-spring-boot-starter/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>pay-spring-boot-starter-parent</artifactId>\n        <groupId>com.egzosn</groupId>\n      <version>1.0.5</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>pay-spring-boot-starter</artifactId>\n    <name>pay-spring-boot-starter</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-spring-boot-autoconfigue</artifactId>\n            <version>${project.version}</version>\n        </dependency>\n    </dependencies>\n</project>"
  },
  {
    "path": "pay-spring-boot-starter/src/main/resources/META-INF/spring.providers",
    "content": "provides: pay-spring-boot-autoconfigue"
  },
  {
    "path": "pay-spring-boot-starter-demo/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>pay-spring-boot-starter-parent</artifactId>\n        <groupId>com.egzosn</groupId>\n        <version>1.0.5</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.egzosn</groupId>\n    <artifactId>pay-spring-boot-starter-demo</artifactId>\n    <name>pay-spring-boot-starter-demo</name>\n    <packaging>jar</packaging>\n    <properties>\n        <java.version>17</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-spring-boot-starter</artifactId>\n            <version>${project.version}</version>\n        </dependency>\n        <!--web应用基本环境配置 -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <!--db-->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-jdbc</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>mysql</groupId>\n            <artifactId>mysql-connector-java</artifactId>\n        </dependency>\n        <!--db-->\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-web-support</artifactId>\n            <version>${pay.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-ali</artifactId>\n        </dependency>\n        <!-- 这里测试不引入是否报错或者触发-->\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-wx</artifactId>\n            <version>${pay.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-union</artifactId>\n            <version>${pay.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-payoneer</artifactId>\n            <version>${pay.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-paypal</artifactId>\n            <version>${pay.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-wx-youdian</artifactId>\n            <version>${pay.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-fuiou</artifactId>\n            <version>${pay.version}</version>\n        </dependency>\n        <!-- 热部署 -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-devtools</artifactId>\n            <optional>true</optional>\n        </dependency>\n\n\n    </dependencies>\n\n\n    <!--<build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n                <configuration>\n                    <mainClass>com.egzosn.pay.spring.boot.demo.PayApplication</mainClass>\n                    <fork>false</fork>\n                </configuration>\n                <dependencies>\n                    &lt;!&ndash; 热部署 &ndash;&gt;\n                    <dependency>\n                        <groupId>org.springframework</groupId>\n                        <artifactId>springloaded</artifactId>\n                        <version>1.2.6.RELEASE</version>\n                    </dependency>\n                </dependencies>\n            </plugin>\n        </plugins>\n    </build>-->\n\n</project>"
  },
  {
    "path": "pay-spring-boot-starter-demo/src/main/java/com/egzosn/pay/spring/boot/demo/PayApplication.java",
    "content": "package com.egzosn.pay.spring.boot.demo;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * 应用\n * @author egan\n *         email egzosn@gmail.com\n *         date 2019/5/27.20:51\n */\n@SpringBootApplication\npublic class PayApplication {\n    public static void main(String[] args) {\n        SpringApplication.run(PayApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot-starter-demo/src/main/java/com/egzosn/pay/spring/boot/demo/config/MerchantPayServiceConfigurer.java",
    "content": "package com.egzosn.pay.spring.boot.demo.config;\n\nimport com.egzosn.pay.common.bean.CertStoreType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.spring.boot.core.PayServiceConfigurer;\nimport com.egzosn.pay.spring.boot.core.configurers.MerchantDetailsServiceConfigurer;\nimport com.egzosn.pay.spring.boot.core.merchant.bean.UnionMerchantDetails;\n\nimport com.egzosn.pay.spring.boot.core.configurers.PayMessageConfigurer;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.AliPaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaymentPlatforms;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.WxPaymentPlatform;\nimport com.egzosn.pay.spring.boot.demo.config.handlers.AliPayMessageHandler;\nimport com.egzosn.pay.spring.boot.demo.config.handlers.WxPayMessageHandler;\nimport com.egzosn.pay.spring.boot.demo.config.interceptor.AliPayMessageInterceptor;\nimport com.egzosn.pay.spring.boot.core.configurers.PayMessageConfigurer;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.AliPaymentPlatform;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.PaymentPlatforms;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.WxPaymentPlatform;\nimport com.egzosn.pay.spring.boot.demo.config.handlers.WxPayMessageHandler;\nimport com.egzosn.pay.spring.boot.demo.config.interceptor.AliPayMessageInterceptor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.config.AutowireCapableBeanFactory;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\nimport java.security.KeyFactory;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.PublicKey;\nimport java.security.spec.InvalidKeySpecException;\nimport java.security.spec.X509EncodedKeySpec;\nimport java.util.Base64;\n\n/**\n * 支付服务配置\n *\n * @author egan\n *         email egzosn@gmail.com\n *         date 2019/5/26.19:25\n */\n@Configuration\npublic class MerchantPayServiceConfigurer implements PayServiceConfigurer {\n\n//    @Autowired\n//    private JdbcTemplate jdbcTemplate;\n    @Autowired\n    private AutowireCapableBeanFactory spring;\n    @Autowired\n    private AliPayMessageHandler aliPayMessageHandler;\n    public static PublicKey loadPublicKeyFromString(String keyString) {\n        try {\n            keyString = keyString.replace(\"-----BEGIN PUBLIC KEY-----\", \"\").replace(\"-----END PUBLIC KEY-----\", \"\").replaceAll(\"\\\\s+\", \"\");\n            return KeyFactory.getInstance(\"RSA\").generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(keyString)));\n        } catch (NoSuchAlgorithmException e) {\n            throw new UnsupportedOperationException(e);\n        } catch (InvalidKeySpecException e) {\n            throw new IllegalArgumentException(e);\n        }\n    }\n\n    /**\n     * 商户配置\n     *\n     * @param merchants 商户配置\n     */\n    @Override\n    public void configure(MerchantDetailsServiceConfigurer merchants)  {\n\n//        数据库文件存放 /doc/sql目录下\n//        merchants.jdbc()\n//                //是否开启缓存，默认不开启,这里开启缓存\n//                .cache(true)\n//                .template(jdbcTemplate);\n        //微信请求配置，详情参考https://gitee.com/egzosn/pay-java-parent项目中的使用\n//        PublicKey publicKey = loadPublicKeyFromString(\"MIIEFDCCAvygAwIBAgIUcsLvDuUJXG2Cb/kJvjPWI6xi3kYwDQYJKoZIhvcNAQEL\\n\" +\n//                \"BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\\n\" +\n//                \"FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\\n\" +\n//                \"Q0EwHhcNMjUwMTA2MDY0MjI3WhcNMzAwMTA1MDY0MjI3WjBuMRgwFgYDVQQDDA9U\\n\" +\n//                \"ZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl\\n\" +\n//                \"bnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGEwJDTjERMA8GA1UEBwwIU2hlblpo\\n\" +\n//                \"ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCejehpOA5Q4yen2mjx\\n\" +\n//                \"imNGIwiQThXnt9NPm8ut+A9YON+sBS5bwApy1WZyClUnc0OdGKu0Ygw9jp0qTodN\\n\" +\n//                \"lfLJsR5yLnm4vQY43uYVIHl9dCTOD+ZqYLc+Ld/B+gtYMJbIhgUU142Y7lUIOsmI\\n\" +\n//                \"DbMLPchbxPuajqdav8tL2cnz9MtF5Gw+ZusJ9GBYBeu8/xyQFaq3jD/zWnbGHZ4K\\n\" +\n//                \"hS1LOXmcyTPwZNy9k4ckqcf1x/yy7eH92EsXnXAqhfH+dQcSgYZcK6JLXi2bWyqF\\n\" +\n//                \"UpQZ2DzmhJwQ09bN0a9g4Py1AOYSdj0ZBuaNvHRJVVQK1LLg6vUtfbMPGDwhbyp/\\n\" +\n//                \"S207AgMBAAGjgbkwgbYwCQYDVR0TBAIwADALBgNVHQ8EBAMCA/gwgZsGA1UdHwSB\\n\" +\n//                \"kzCBkDCBjaCBiqCBh4aBhGh0dHA6Ly9ldmNhLml0cnVzLmNvbS5jbi9wdWJsaWMv\\n\" +\n//                \"aXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1NDk4NDZDMDFDM0U4\\n\" +\n//                \"RUJEMiZzZz1IQUNDNDcxQjY1NDIyRTEyQjI3QTlEMzNBODdBRDFDREY1OTI2RTE0\\n\" +\n//                \"MDM3MTANBgkqhkiG9w0BAQsFAAOCAQEAk82I3ThSpikhHbtG8pTtJay8gJyIUf+n\\n\" +\n//                \"rn9G8AruSpDvlCxRMJ6QHXLABLx5ko/yG+gGv7P02M3AQbDskxMN430vHRsJ8tyY\\n\" +\n//                \"B8C2QE8AbVHzJ2/K6CirxDxGbclSwJCvdq++uebfnKbM7U5GnfyHprpjT9MLIx0G\\n\" +\n//                \"r+i1CXQ4SCWYt0am84kLwpjDIkPuzqWbIdmNVV9+3lbQilaB6/EQzQxsGeA0FxPV\\n\" +\n//                \"mGJC02hmaPgORKGLZM91Z3xnS/trLU3yF/VxMX5g7QGW9DlHOW2I8Ko/wiZuU3MM\\n\" +\n//                \"WKM0Vp8BB+817Vn8HZ52b53bc85Ffm8tOLlX5kMutV2k8QH7SR/8xg==\");\n        //内存Builder方式\n        merchants.inMemory()\n//                .ali()\n//                .detailsId(\"1\")\n//                .appid(\"2016080400165436\")\n//                .keyPrivate(\"MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKroe/8h5vC4L6T+B2WdXiVwGsMvUKgb2XsKix6VY3m2wcf6tyzpNRDCNykbIwGtaeo7FshN+qZxdXHLiIam9goYncBit/8ojfLGy2gLxO/PXfzGxYGs0KsDZ+ryVPPmE34ZZ8jiJpR0ygzCFl8pN3QJPJRGTJn5+FTT9EF/9zyZAgMBAAECgYAktngcYC35u7cQXDk+jMVyiVhWYU2ULxdSpPspgLGzrZyG1saOcTIi/XVX8Spd6+B6nmLQeF/FbU3rOeuD8U2clzul2Z2YMbJ0FYay9oVZFfp5gTEFpFRTVfzqUaZQBIjJe/xHL9kQVqc5xHlE/LVA27/Kx3dbC35Y7B4EVBDYAQJBAOhsX8ZreWLKPhXiXHTyLmNKhOHJc+0tFH7Ktise/0rNspojU7o9prOatKpNylp9v6kux7migcMRdVUWWiVe+4ECQQC8PqsuEz7B0yqirQchRg1DbHjh64bw9Kj82EN1/NzOUd53tP9tg+SO97EzsibK1F7tOcuwqsa7n2aY48mQ+y0ZAkBndA2xcRcnvOOjtAz5VO8G7R12rse181HjGfG6AeMadbKg30aeaGCyIxN1loiSfNR5xsPJwibGIBg81mUrqzqBAkB+K6rkaPXJR9XtzvdWb/N3235yPkDlw7Z4MiOVM3RzvR/VMDV7m8lXoeDde2zQyeMOMYy6ztwA6WgE1bhGOnQRAkEAouUBv1sVdSBlsexX15qphOmAevzYrpufKgJIRLFWQxroXMS7FTesj+f+FmGrpPCxIde1dqJ8lqYLTyJmbzMPYw==\")\n//                .keyPublic(\"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIgHnOn7LLILlKETd6BFRJ0GqgS2Y3mn1wMQmyh9zEyWlz5p1zrahRahbXAfCfSqshSNfqOmAQzSHRVjCqjsAw1jyqrXaPdKBmr90DIpIxmIyKXv4GGAkPyJ/6FTFY99uhpiq0qadD/uSzQsefWo0aTvP/65zi3eof7TcZ32oWpwIDAQAB\")\n//                .inputCharset(\"utf-8\")\n//                .notifyUrl(\"http://pay.egzosn.com/payBack1.json\")\n//                .returnUrl(\"http://pay.egzosn.com/payBack1.json\")\n//                .pid(\"2088102169916436\")\n//                .seller(\"2088102169916436\")\n//                .signType(\"RSA\")\n//                .test(true)\n//                .and()\n                .wxV3()\n                .detailsId(\"2\")\n                .appId(\"wx5ce9f1a204c49979\")\n                .mchId(\"1703302548\")\n                .v3ApiKey(\"KDBX2tbrKi9eWFEZW4s3bxGpP30AtXtW\")\n                .keyPrivate(\"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCltaNjUKUcXEQe\\n\" +\n                        \"31O3ljZswpRgNMVNVdR2vQt0ymVKZwFcTNrOE28Tmn4UuWkb6HzCTtlOM2mOuX9T\\n\" +\n                        \"uE8rkkc+gqrZtTjchotsGu35YO3L2VvADxvd0SUw9rZIqh+/5MybBEpmOwR9p1pr\\n\" +\n                        \"bYSwxSWlwx4qt1fNX/uOrjYplcvEp00otlHv3SJh2CyK+vkWP30F18FVTpTf1mdY\\n\" +\n                        \"ehMF8aDr9Zlnsdm25Kig14Zly25dsuxiuoagLWIz0031v3byO0iuAxxUhl9ofUHh\\n\" +\n                        \"zt2ajshy/DS910N0PE/FCYKbMQEz951ZnAojWI97hXRYnigAEo1VJyB9GBxxPRIT\\n\" +\n                        \"fr4KUJGvAgMBAAECggEAVw5L3hs6AuI+L3HoS2SxBwZaaQiQNwbGbfL3F85U1He0\\n\" +\n                        \"8Ua3FNiE3Gmnnz+hBrZnBLXj1/+OjxrI17TWcu+QWjjPhTx9uO0+RfcH2qGfjB6O\\n\" +\n                        \"4yGM5EXCIi0aqqYls+yByVbBt19+Bn1rNVD+Ctgn5SPSr2JO0GiCgfzoG4TE3nSl\\n\" +\n                        \"v9YWhfzbWjrNgQR4npY5UQbL4D86ubZ6I81YnN+MGmxuTxS06fwjQyVH3AQbUp70\\n\" +\n                        \"LRmdjQUhsRS2uSmsMmfavLtfyq14ZV2I0KWNADzvGfcTNOtg+XCCohQyJUhEDhtH\\n\" +\n                        \"Si8bvsL+Blauu0o8tpFMA1hEIsxdwdvjWAie45yW4QKBgQDUyQTYc/oyJn7HfGLN\\n\" +\n                        \"EcUF9qCL0ymH1UepstrnIDiNTZ4n4rFCORlM5wpZe6kZzZqMRMnHEaipk4WWryAN\\n\" +\n                        \"z0UjXA+n3j/uoIybvpMjljMHvxzP+IfZwt/XK437bFeiNSNigk8zU7sEw0RD+y77\\n\" +\n                        \"Jn6ucmnFxBwpsN4zuFKY+ObhBwKBgQDHXReTD6HLZ12Pf91469D/qvD7jJ7R/1I7\\n\" +\n                        \"maPHQB7+VrSHZeZnhy9TOZyONEt3vd2GpYxhdvkUXL4j6FqjYn0tt72PNs/xQhL0\\n\" +\n                        \"V3EZsm+YYZ8GOPh24Ij6jPhWLEIvYGLYSBtR7Uq8VWN84A1AUxnw538I8L7qH+7D\\n\" +\n                        \"j0PTuSioGQKBgEeqoLgqb7UeZAraKQi6mGpGw5H0gANg4S8Vr0azAnkNEFyMrHkK\\n\" +\n                        \"dCwDkOfMj4rCRfBCZtdmajEbH549w4UDL10Wb6txXoUHi/QUvsf4mZ1dT9337gF4\\n\" +\n                        \"8h0tbTemKOnYDd/q1bQK2m1jOwXOfudV8srcfCWAxJ+CE4TF6wPcqR5XAoGAYAFs\\n\" +\n                        \"gN1eRN2aKKiitsCY/QYM1pZ5RRd3OkxamnE+e6y1cx6XPfPTznhH9BMq5JcCPv0q\\n\" +\n                        \"BSWN/UhMKG6Ud2nObl21Y2o56SywhAo35PAQ3YjlU9HLlTO7wyxvys+1b6sy7oSK\\n\" +\n                        \"44EqJFfaeSBMQVXDgEd63YtR5N1L1dEAEM1xzsECgYEAxMV8DnXRUpY2tTF0GHLL\\n\" +\n                        \"RJBz0OQNbQbpOsUQuMyAN+MGISdbjJISpVOBE1ngUwS1CNGIUaBKUZu5g53ZqF/M\\n\" +\n                        \"K3a0qjFJwzzkCaTo802CBcoATYKhQv+xP25s7UU+gS1Qhsa57+j/g0yoSNle02gE\\n\" +\n                        \"vOBgNU/g1THHdIVOY4uO64g=\")\n                .merchantSerialNumber(\"72C2EF0EE5095C6D826FF909BE33D623AC62DE46\")\n//                .keyPublic(\"MIIEFDCCAvygAwIBAgIUcsLvDuUJXG2Cb/kJvjPWI6xi3kYwDQYJKoZIhvcNAQEL\\n\" +\n//                        \"BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\\n\" +\n//                        \"FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\\n\" +\n//                        \"Q0EwHhcNMjUwMTA2MDY0MjI3WhcNMzAwMTA1MDY0MjI3WjBuMRgwFgYDVQQDDA9U\\n\" +\n//                        \"ZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl\\n\" +\n//                        \"bnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGEwJDTjERMA8GA1UEBwwIU2hlblpo\\n\" +\n//                        \"ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCejehpOA5Q4yen2mjx\\n\" +\n//                        \"imNGIwiQThXnt9NPm8ut+A9YON+sBS5bwApy1WZyClUnc0OdGKu0Ygw9jp0qTodN\\n\" +\n//                        \"lfLJsR5yLnm4vQY43uYVIHl9dCTOD+ZqYLc+Ld/B+gtYMJbIhgUU142Y7lUIOsmI\\n\" +\n//                        \"DbMLPchbxPuajqdav8tL2cnz9MtF5Gw+ZusJ9GBYBeu8/xyQFaq3jD/zWnbGHZ4K\\n\" +\n//                        \"hS1LOXmcyTPwZNy9k4ckqcf1x/yy7eH92EsXnXAqhfH+dQcSgYZcK6JLXi2bWyqF\\n\" +\n//                        \"UpQZ2DzmhJwQ09bN0a9g4Py1AOYSdj0ZBuaNvHRJVVQK1LLg6vUtfbMPGDwhbyp/\\n\" +\n//                        \"S207AgMBAAGjgbkwgbYwCQYDVR0TBAIwADALBgNVHQ8EBAMCA/gwgZsGA1UdHwSB\\n\" +\n//                        \"kzCBkDCBjaCBiqCBh4aBhGh0dHA6Ly9ldmNhLml0cnVzLmNvbS5jbi9wdWJsaWMv\\n\" +\n//                        \"aXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1NDk4NDZDMDFDM0U4\\n\" +\n//                        \"RUJEMiZzZz1IQUNDNDcxQjY1NDIyRTEyQjI3QTlEMzNBODdBRDFDREY1OTI2RTE0\\n\" +\n//                        \"MDM3MTANBgkqhkiG9w0BAQsFAAOCAQEAk82I3ThSpikhHbtG8pTtJay8gJyIUf+n\\n\" +\n//                        \"rn9G8AruSpDvlCxRMJ6QHXLABLx5ko/yG+gGv7P02M3AQbDskxMN430vHRsJ8tyY\\n\" +\n//                        \"B8C2QE8AbVHzJ2/K6CirxDxGbclSwJCvdq++uebfnKbM7U5GnfyHprpjT9MLIx0G\\n\" +\n//                        \"r+i1CXQ4SCWYt0am84kLwpjDIkPuzqWbIdmNVV9+3lbQilaB6/EQzQxsGeA0FxPV\\n\" +\n//                        \"mGJC02hmaPgORKGLZM91Z3xnS/trLU3yF/VxMX5g7QGW9DlHOW2I8Ko/wiZuU3MM\\n\" +\n//                        \"WKM0Vp8BB+817Vn8HZ52b53bc85Ffm8tOLlX5kMutV2k8QH7SR/8xg==\")\n//                .keyPublicId(\"72C2EF0EE5095C6D826FF909BE33D623AC62DE46\")\n                .notifyUrl(\"http://pay.egzosn.com/payBack2.json\")\n                .returnUrl(\"http://pay.egzosn.com/payBack2.json\")\n                .inputCharset(\"utf-8\")\n                .and()\n        ;\n\n      /*  //------------内存手动方式------------------\n        UnionMerchantDetails unionMerchantDetails = new UnionMerchantDetails();\n        unionMerchantDetails.detailsId(\"3\");\n        //内存方式的时候这个必须设置\n        unionMerchantDetails.setCertSign(true);\n        unionMerchantDetails.setMerId(\"700000000000001\");\n        //公钥，验签证书链格式： 中级证书路径;\n        unionMerchantDetails.setAcpMiddleCert(\"D:/certs/acp_test_middle.cer\");\n        //公钥，根证书路径\n        unionMerchantDetails.setAcpRootCert(\"D:/certs/acp_test_root.cer\");\n        //私钥, 私钥证书格式： 私钥证书路径\n        unionMerchantDetails.setKeyPrivateCert(\"D:/certs/acp_test_sign.pfx\");\n        //私钥证书对应的密码\n        unionMerchantDetails.setKeyPrivateCertPwd(\"000000\");\n        //证书的存储方式\n        unionMerchantDetails.setCertStoreType(CertStoreType.PATH);\n        unionMerchantDetails.setNotifyUrl(\"http://127.0.0.1/payBack4.json\");\n        // 无需同步回调可不填  app填这个就可以\n        unionMerchantDetails.setReturnUrl(\"http://127.0.0.1/payBack4.json\");\n        unionMerchantDetails.setInputCharset(\"UTF-8\");\n        unionMerchantDetails.setSignType(\"RSA2\");\n        unionMerchantDetails.setTest(true);\n        //手动加入商户容器中\n        merchants.inMemory().addMerchantDetails(unionMerchantDetails);*/\n    }\n    /**\n     * 商户配置\n     *\n     * @param configurer 支付消息配置\n     */\n    @Override\n    public void configure(PayMessageConfigurer configurer) {\n        PaymentPlatform aliPaymentPlatform = PaymentPlatforms.getPaymentPlatform(AliPaymentPlatform.PLATFORM_NAME);\n        configurer.addHandler(aliPaymentPlatform, aliPayMessageHandler);\n        configurer.addInterceptor(aliPaymentPlatform, spring.getBean(AliPayMessageInterceptor.class));\n        configurer.addHandler(PaymentPlatforms.getPaymentPlatform(WxPaymentPlatform.PLATFORM_NAME), new WxPayMessageHandler());\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot-starter-demo/src/main/java/com/egzosn/pay/spring/boot/demo/config/MyAliPaymentPlatform.java",
    "content": "package com.egzosn.pay.spring.boot.demo.config;\n\nimport com.egzosn.pay.ali.api.AliPayConfigStorage;\nimport com.egzosn.pay.ali.api.AliPayService;\nimport com.egzosn.pay.ali.bean.AliTransactionType;\nimport com.egzosn.pay.common.api.PayConfigStorage;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.TransactionType;\nimport com.egzosn.pay.common.http.HttpConfigStorage;\nimport com.egzosn.pay.spring.boot.core.merchant.bean.CommonPaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.provider.merchant.platform.AliPaymentPlatform;\n\n/**\n * 支付宝支付平台,自定义支付宝平台支持证书方式\n * 所有支付平台都可以使用这种定制的方式进行覆盖\n * 使用案例\n * @author egan\n * <pre>\n *                 email egzosn@gmail.com\n *                 date  2019/4/4 14:35.\n *                 </pre>\n */\n//@Component(AliPaymentPlatform.PLATFORM_NAME)\npublic class MyAliPaymentPlatform extends AliPaymentPlatform {\n\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage 支付配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage) {\n        if (payConfigStorage instanceof AliPayConfigStorage) {\n            return new AliPayService((AliPayConfigStorage) payConfigStorage);\n        }\n        AliPayConfigStorage configStorage = new AliPayConfigStorage();\n        configStorage.setInputCharset(payConfigStorage.getInputCharset());\n        configStorage.setAppId(payConfigStorage.getAppId());\n        configStorage.setPid(payConfigStorage.getPid());\n        configStorage.setAttach(payConfigStorage.getAttach());\n        configStorage.setSeller(payConfigStorage.getSeller());\n        configStorage.setKeyPrivate(payConfigStorage.getKeyPrivate());\n        configStorage.setKeyPublic(payConfigStorage.getKeyPublic());\n        configStorage.setNotifyUrl(payConfigStorage.getNotifyUrl());\n        configStorage.setReturnUrl(payConfigStorage.getReturnUrl());\n        configStorage.setPayType(payConfigStorage.getPayType());\n        configStorage.setTest(payConfigStorage.isTest());\n        configStorage.setSignType(payConfigStorage.getSignType());\n        if (payConfigStorage instanceof CommonPaymentPlatformMerchantDetails) {\n            final CommonPaymentPlatformMerchantDetails commonPaymentPlatformMerchantDetails = (CommonPaymentPlatformMerchantDetails) payConfigStorage;\n            configStorage.setAppAuthToken(commonPaymentPlatformMerchantDetails.getSubAppId());\n            certKeyPublic(configStorage, commonPaymentPlatformMerchantDetails);\n        }\n\n        return new AliPayService(configStorage);\n    }\n\n    /**\n     * 设置证书公钥信息\n     * 普通公钥方式与证书公钥方式为两者取其一的方式\n     *\n     * @param aliPayConfigStorage 支付宝配置信息\n     * @param payConfigStorage    配置信息\n     */\n    private static void certKeyPublic(AliPayConfigStorage aliPayConfigStorage, CommonPaymentPlatformMerchantDetails payConfigStorage) {\n        final String keyPublicCert = payConfigStorage.getKeyPublic();\n        //这里通过兼容的方式去处理，匹配尾缀如果为证书文件的话就当证书处理\n        if (!keyPublicCert.endsWith(\".crt\")) {\n            return;\n        }\n        //设置为证书方式\n        aliPayConfigStorage.setCertSign(true);\n        //设置证书存储方式，这里为路径\n        aliPayConfigStorage.setCertStoreType(payConfigStorage.getCertStoreType());\n        String[] keyCert = payConfigStorage.getKeyCert().toString().split(\",\");\n        aliPayConfigStorage.setMerchantCert(keyCert[0]);\n        aliPayConfigStorage.setAliPayRootCert(keyCert[1]);\n        aliPayConfigStorage.setAliPayCert(payConfigStorage.getKeyPublic());\n    }\n\n    /**\n     * 获取支付平台对应的支付服务\n     *\n     * @param payConfigStorage  支付配置\n     * @param httpConfigStorage 网络配置\n     * @return 支付服务\n     */\n    @Override\n    public PayService getPayService(PayConfigStorage payConfigStorage, HttpConfigStorage httpConfigStorage) {\n        PayService payService = getPayService(payConfigStorage);\n        payService.setRequestTemplateConfigStorage(httpConfigStorage);\n        return payService;\n    }\n\n    @Override\n    public TransactionType getTransactionType(String name) {\n        return AliTransactionType.valueOf(name);\n    }\n\n\n}\n"
  },
  {
    "path": "pay-spring-boot-starter-demo/src/main/java/com/egzosn/pay/spring/boot/demo/config/handlers/AliPayMessageHandler.java",
    "content": "package com.egzosn.pay.spring.boot.demo.config.handlers;\n\nimport com.egzosn.pay.ali.api.AliPayService;\nimport com.egzosn.pay.ali.bean.AliPayMessage;\nimport com.egzosn.pay.common.api.PayMessageHandler;\nimport com.egzosn.pay.common.bean.PayOutMessage;\nimport com.egzosn.pay.common.exception.PayErrorException;\nimport org.springframework.stereotype.Component;\n\nimport java.math.BigDecimal;\nimport java.util.Map;\n\n/**\n * 支付宝支付回调处理器\n * Created by ZaoSheng on 2016/6/1.\n *\n */\n@Component\npublic class AliPayMessageHandler implements PayMessageHandler<AliPayMessage, AliPayService> {\n\n\n    /**\n     * 处理支付回调消息的处理器接口\n     *\n     * @param payMessage 支付消息\n     * @param context    上下文，如果handler或interceptor之间有信息要传递，可以用这个\n     * @param payService 支付服务\n     * @return xml, text格式的消息，如果在异步规则里处理的话，可以返回null\n     * @throws PayErrorException 支付错误异常\n     */\n    @Override\n    public PayOutMessage handle(AliPayMessage payMessage, Map<String, Object> context, AliPayService payService) throws PayErrorException {\n        //com.egzosn.pay.demo.entity.PayType.getPayService()#48\n        Object payId = payService.getPayConfigStorage().getAttach();\n\n        Map<String, Object> message = payMessage.getPayMessage();\n        //交易状态\n        String trade_status = (String) message.get(\"trade_status\");\n\n        //上下文对象中获取账单\n//        AmtApply amtApply = (AmtApply)context.get(\"amtApply\");\n        //日志存储\n//        amtPaylogService.createAmtPaylogByCallBack(amtApply,  message.toString());\n        //交易完成\n        if (\"TRADE_SUCCESS\".equals(trade_status) || \"TRADE_FINISHED\".equals(trade_status)) {\n\n            BigDecimal payAmount = new BigDecimal((String) message.get(\"total_fee\"));\n\n            return payService.successPayOutMessage(payMessage);\n\n        }/* else if (\"WAIT_BUYER_PAY\".equals(trade_status) || \"TRADE_CLOSED\".equals(trade_status)) {\n\n        }*/\n\n        return payService.getPayOutMessage(\"fail\", \"失败\");\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot-starter-demo/src/main/java/com/egzosn/pay/spring/boot/demo/config/handlers/WxPayMessageHandler.java",
    "content": "package com.egzosn.pay.spring.boot.demo.config.handlers;\n\nimport com.egzosn.pay.common.api.PayMessageHandler;\nimport com.egzosn.pay.common.api.PayService;\nimport com.egzosn.pay.common.bean.PayOutMessage;\nimport com.egzosn.pay.common.exception.PayErrorException;\nimport com.egzosn.pay.wx.bean.WxPayMessage;\n\nimport java.util.Map;\n\n/**\n * 微信支付回调处理器\n * Created by ZaoSheng on 2016/6/1.\n */\npublic class WxPayMessageHandler implements PayMessageHandler<WxPayMessage, PayService> {\n\n\n\n\n    @Override\n    public PayOutMessage handle(WxPayMessage payMessage, Map<String, Object> context, PayService payService) throws PayErrorException {\n        //交易状态\n        if (\"SUCCESS\".equals(payMessage.getPayMessage().get(\"result_code\"))){\n            /////这里进行成功的处理\n\n            return  payService.getPayOutMessage(\"SUCCESS\", \"OK\");\n        }\n\n        return  payService.getPayOutMessage(\"FAIL\", \"失败\");\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot-starter-demo/src/main/java/com/egzosn/pay/spring/boot/demo/config/interceptor/AliPayMessageInterceptor.java",
    "content": "\npackage com.egzosn.pay.spring.boot.demo.config.interceptor;\n\nimport com.egzosn.pay.ali.api.AliPayService;\nimport com.egzosn.pay.ali.bean.AliPayMessage;\nimport com.egzosn.pay.common.api.PayMessageHandler;\nimport com.egzosn.pay.common.api.PayMessageInterceptor;\nimport com.egzosn.pay.common.exception.PayErrorException;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Map;\n\n/**\n * 支付宝回调信息拦截器\n * @author: egan\n * email egzosn@gmail.com\n * date 2017/1/18 19:28\n */\n@Component\npublic class AliPayMessageInterceptor implements PayMessageInterceptor<AliPayMessage, AliPayService> {\n\n    /**\n     * 拦截支付消息\n     *\n     * @param payMessage     支付回调消息\n     * @param context        上下文，如果handler或interceptor之间有信息要传递，可以用这个\n     * @param payService 支付服务\n     * @return true代表OK，false代表不OK并直接中断对应的支付处理器\n     * @see PayMessageHandler 支付处理器\n     * @throws PayErrorException PayErrorException*\n     */\n    @Override\n    public boolean intercept(AliPayMessage payMessage, Map<String, Object> context, AliPayService payService) throws PayErrorException {\n\n        //这里进行拦截器处理，自行实现\n        String outTradeNo = payMessage.getOutTradeNo();\n        // 设置外部单号\n//        amtApplyService.fillApplyoutId(outTradeNo, (String) payMessage.getPayMessage().get(\"trade_no\"));\n\n\n        //获取账单\n//        AmtApply amtApply = amtApplyService.getAmtApplyByApplyId(outTradeNo);\n//        if (null == amtApply){\n//            Log4jUtil.info(\"app 阿里pay：\" + outTradeNo);\n//            return false;\n//        }\n//\n//        重复回调不进行处理\n//        if(amtApply.getApplyState().shortValue()== ApplyStateEnum.success.getCode()){\n//            return false;\n//        }\n        //将账单存储至上下文对象中\n//        context.put(\"amtApply\", amtApply);\n\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "pay-spring-boot-starter-demo/src/main/java/com/egzosn/pay/spring/boot/demo/controller/PayMerchantController.java",
    "content": "package com.egzosn.pay.spring.boot.demo.controller;\n\nimport java.io.IOException;\nimport java.math.BigDecimal;\nimport java.util.Map;\nimport java.util.UUID;\n\nimport javax.servlet.http.HttpServletRequest;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport com.egzosn.pay.common.api.PayMessageInterceptor;\nimport com.egzosn.pay.common.bean.AssistOrder;\nimport com.egzosn.pay.common.bean.RefundOrder;\nimport com.egzosn.pay.common.bean.RefundResult;\nimport com.egzosn.pay.common.bean.TransferOrder;\nimport com.egzosn.pay.common.util.MapGen;\nimport com.egzosn.pay.spring.boot.core.PayServiceManager;\nimport com.egzosn.pay.spring.boot.core.bean.MerchantPayOrder;\nimport com.egzosn.pay.spring.boot.core.bean.MerchantQueryOrder;\nimport com.egzosn.pay.spring.boot.core.merchant.PaymentPlatformMerchantDetails;\nimport com.egzosn.pay.spring.boot.core.provider.MerchantDetailsManager;\nimport com.egzosn.pay.web.support.HttpRequestNoticeParams;\n\n/**\n * @author egan\n * email egzosn@gmail.com\n * date 2019/5/26.20:10\n */\n\n@RequestMapping(\"pay\")\n@Controller\npublic class PayMerchantController {\n\n    @Autowired\n    private PayServiceManager manager;\n    @Autowired\n    private MerchantDetailsManager<PaymentPlatformMerchantDetails> merchantDetailsManager;\n\n\n    @GetMapping(\"merchantExists\")\n    public Map<String, Object> merchantExists() {\n        return new MapGen<String, Object>(\"exist\", merchantDetailsManager.merchantExists(\"1\")).getAttr();\n    }\n\n    /**\n     * 网页支付\n     *\n     * @param detailsId 列表id\n     * @param wayTrade  交易方式\n     * @return 网页\n     */\n    @ResponseBody\n    @RequestMapping(value = \"toPay.html\", produces = \"text/html;charset=UTF-8\")\n    public String toPay(String detailsId, String wayTrade, BigDecimal price) {\n        MerchantPayOrder payOrder = new MerchantPayOrder(detailsId, wayTrade, \"订单title\", \"摘要\", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace(\"-\", \"\"));\n        return manager.toPay(payOrder);\n    }\n\n\n    /**\n     * 公众号支付\n     *\n     * @param detailsId 账户id\n     * @param openid    openid\n     * @param price     金额\n     * @return 返回jsapi所需参数\n     */\n    @RequestMapping(value = \"jsapi\")\n    public Map<String, Object> jsapi(String detailsId, String openid, BigDecimal price) {\n        //获取对应的支付账户操作工具（可根据账户id）\n        MerchantPayOrder payOrder = new MerchantPayOrder(detailsId, \"JSAPI\", \"订单title\", \"摘要\", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace(\"-\", \"\"));\n        payOrder.setOpenid(openid);\n        return manager.getOrderInfo(payOrder);\n    }\n\n    /**\n     * 获取支付预订单信息\n     *\n     * @param detailsId 支付账户id\n     * @param price     金额\n     * @return 支付预订单信息\n     */\n    @RequestMapping(\"app\")\n    public Map<String, Object> getOrderInfo(String detailsId, BigDecimal price) {\n        //获取对应的支付账户操作工具（可根据账户id）\n        MerchantPayOrder payOrder = new MerchantPayOrder(detailsId, \"APP\", \"订单title\", \"摘要\", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace(\"-\", \"\"));\n        return manager.app(payOrder);\n    }\n\n\n    /**\n     * 二维码\n     *\n     * @param detailsId 列表id\n     * @param wayTrade  交易方式\n     * @return 二维码\n     */\n    @ResponseBody\n    @RequestMapping(value = \"toQrPay.jpg\", produces = \"image/jpeg;charset=UTF-8\")\n    public byte[] toQrPay(String detailsId, String wayTrade, BigDecimal price) throws IOException {\n        MerchantPayOrder payOrder = new MerchantPayOrder(detailsId, wayTrade, \"订单title\", \"摘要\", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace(\"-\", \"\"));\n        return manager.toQrPay(payOrder);\n    }\n\n    /**\n     * 二维码信息\n     *\n     * @param detailsId 列表id\n     * @param wayTrade  交易方式\n     * @return 二维码信息\n     */\n    @ResponseBody\n    @RequestMapping(value = \"getQrPay.json\")\n    public String getQrPay(String detailsId, String wayTrade, BigDecimal price) {\n        MerchantPayOrder payOrder = new MerchantPayOrder(detailsId, wayTrade, \"订单title\", \"摘要\", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace(\"-\", \"\"));\n        return manager.getQrPay(payOrder);\n    }\n\n\n    /**\n     * 刷卡付,pos主动扫码付款(条码付)\n     *\n     * @param detailsId       账户id\n     * @param transactionType 交易类型， 这个针对于每一个 支付类型的对应的几种交易方式\n     * @param authCode        授权码，条码等\n     * @param price           金额\n     * @return 支付结果\n     */\n    @RequestMapping(value = \"microPay\")\n    public Map<String, Object> microPay(String detailsId, String transactionType, BigDecimal price, String authCode) {\n        //获取对应的支付账户操作工具（可根据账户id）\n        MerchantPayOrder payOrder = new MerchantPayOrder(detailsId, transactionType, \"订单title\", \"摘要\", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace(\"-\", \"\"));\n        //设置授权码，条码等\n        payOrder.setAuthCode(authCode);\n        return manager.microPay(payOrder);\n    }\n\n    /**\n     * 支付回调地址\n     *\n     * @param request   请求\n     * @param detailsId 列表id\n     * @return 支付是否成功\n     * 拦截器相关增加， 详情查看{@link com.egzosn.pay.common.api.PayService#addPayMessageInterceptor(PayMessageInterceptor)}\n     * <p>\n     * 业务处理在对应的PayMessageHandler里面处理，在哪里设置PayMessageHandler，详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)}\n     * </p>\n     * 如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler}\n     */\n    @RequestMapping(value = \"payBack/{deatilsId}.json\")\n    public String payBack(HttpServletRequest request, @PathVariable String detailsId) {\n        //业务处理在对应的PayMessageHandler里面处理，在哪里设置PayMessageHandler，详情查看com.egzosn.pay.common.api.PayService.setPayMessageHandler()\n        return manager.payBack(detailsId, new HttpRequestNoticeParams(request));\n    }\n\n    /**\n     * 支付回调地址\n     *\n     * @param request   请求\n     * @param detailsId 列表id\n     * @return 支付是否成功\n     * @throws IOException IOException\n     *                     拦截器相关增加， 详情查看{@link com.egzosn.pay.common.api.PayService#addPayMessageInterceptor(PayMessageInterceptor)}\n     *                     <p>\n     *                     业务处理在对应的PayMessageHandler里面处理，在哪里设置PayMessageHandler，详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)}\n     *                     </p>\n     *                     如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler}\n     */\n    @Deprecated\n    @RequestMapping(value = \"payBackOld{detailsId}.json\")\n    public String payBackOld(HttpServletRequest request, @PathVariable String detailsId) throws IOException {\n        //业务处理在对应的PayMessageHandler里面处理，在哪里设置PayMessageHandler，详情查看com.egzosn.pay.common.api.PayService.setPayMessageHandler()\n        return manager.payBack(detailsId, request.getParameterMap(), request.getInputStream());\n    }\n\n    /**\n     * 查询\n     * 入参根据实际情况来填写，\n     * 必填参数 detailsId\n     * 普通查询 tradeNo,outTradeNo\n     * <b>具体详情查看pay-java-demo内对应demo</b>\n     *\n     * @param order 订单的请求体\n     * @return 返回查询回来的结果集，支付方原值返回\n     */\n    @RequestMapping(\"query\")\n    public Map<String, Object> query(MerchantQueryOrder order) {\n\n        return manager.query(order);\n    }\n\n\n    /**\n     * 交易关闭接口\n     *\n     * @param detailsId  id\n     * @param tradeNo    tradeNo\n     * @param outTradeNo outTradeNo\n     * @return 返回支付方交易关闭后的结果\n     */\n    @RequestMapping(\"close\")\n    public Map<String, Object> close(String detailsId, String tradeNo, String outTradeNo) {\n        final MerchantQueryOrder order = new MerchantQueryOrder();\n        order.setDetailsId(detailsId);\n        order.setTradeNo(tradeNo);\n        order.setOutTradeNo(outTradeNo);\n        return manager.close(order);\n    }\n\n    /**\n     * 申请退款接口\n     *\n     * @param detailsId 账户id\n     * @param order     订单的请求体\n     * @return 返回支付方申请退款后的结果\n     */\n    @RequestMapping(\"refund\")\n    public RefundResult refund(String detailsId, RefundOrder order) {\n\n        return manager.refund(detailsId, order);\n    }\n\n    /**\n     * 查询退款\n     *\n     * @param order 订单的请求体\n     * @return 返回支付方查询退款后的结果\n     */\n    @RequestMapping(\"refundquery\")\n    public Map<String, Object> refundQuery(String detailsId, RefundOrder order) {\n        return manager.refundQuery(detailsId, order);\n    }\n\n    /**\n     * 下载对账单\n     * 必填参数 detailsId\n     * 普通查询 billDate, billType\n     * <b>具体详情查看pay-java-demo内对应demo</b>\n     *\n     * @param order 订单的请求体\n     * @return 返回支付方下载对账单的结果\n     */\n    @RequestMapping(\"downloadBill\")\n    public Object downloadBill(MerchantQueryOrder order) {\n        return manager.downloadBill(order);\n\n    }\n\n\n    /**\n     * 转账\n     *\n     * @param order 转账订单\n     * @return 对应的转账结果\n     * 具体参数看具体支付平台，案例pay-java-parent/pay-java-demo/com.egzosn.pay.demo.controller\n     */\n    @RequestMapping(\"transfer/{detailsId}\")\n    public Map<String, Object> transfer(@PathVariable String detailsId, TransferOrder order) {\n        return manager.transfer(detailsId, order);\n    }\n    /**\n     * 转账\n     *\n     * @param order 转账订单\n     * @return 对应的转账结果\n     * 具体参数看具体支付平台，\n     */\n    @RequestMapping(\"transferQuery/{detailsId}\")\n    public Map<String, Object> transferQuery(@PathVariable String detailsId, AssistOrder order) {\n        return manager.transferQuery(detailsId, order);\n    }\n\n}\n"
  },
  {
    "path": "pay-spring-boot-starter-demo/src/main/resources/ali/alipayCertPublicKey_RSA2.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDqDCCApCgAwIBAgIQIBkQFQ/dyVOPUjiooDnPNjANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UE\nBhMCQ04xGzAZBgNVBAoMEkFudCBGaW5hbmNpYWwgdGVzdDElMCMGA1UECwwcQ2VydGlmaWNhdGlv\nbiBBdXRob3JpdHkgdGVzdDE+MDwGA1UEAww1QW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1\ndGhvcml0eSBDbGFzcyAyIFIxIHRlc3QwHhcNMTkxMDE1MTMzMjEzWhcNMjIxMDEzMTMzMjEzWjB6\nMQswCQYDVQQGEwJDTjEVMBMGA1UECgwM5rKZ566x546v5aKDMQ8wDQYDVQQLDAZBbGlwYXkxQzBB\nBgNVBAMMOuaUr+S7mOWunSjkuK3lm70p572R57uc5oqA5pyv5pyJ6ZmQ5YWs5Y+4LTIwODgxMDIx\nNjk5MTY0MzYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0iWE/WO7qDt8whynlxH6/\ntuTtFQj6KtHcdSbR6ff0r9ScYHIC6UYUtlT3/8jAi7fEJN8aREdZXy/2IwmE2bFapvHB6FuVMKXh\n/i4QPP2cQJzVDM56wY/HqcyxsDHz7eP9nanU4KT4azOz+dQESNVj+Xw05CgTmQQ3JaXRYFMU8841\nabxXTZg7x03HS7b16CHR2TXs55L6LkbQX45jvFad+NKs6o9gC2ij1xwRBQhuGJbPlfdOqaTOM0vc\nmiOy+vKYvKb3vPQI5h+XVGU/y2piE0oszQWZWd1F9w70eBPHWY7i2PaGwNk38CcBve9QtoyURLEi\nD6LrJQGkQ6LCP7MtAgMBAAGjEjAQMA4GA1UdDwEB/wQEAwIE8DANBgkqhkiG9w0BAQsFAAOCAQEA\nj6xIDkX/GbcQoeMTrJIP2sI4AsStxwG5QjYh021hA74agx0XGQyWrRhXtKpIyEfNxwSZaWgoJqZ3\nuBGTMfiVxjoI1xvHrv5kLQAU8lAt3thdwMYkwP56u51jT15V56OzwvWycGplEwGBw/ln6nc6lwcA\nFTPnBR82Wv0J3+B6iSyw/bqXAiWM9ftIv9ex10YIjBRGC0kK0OFS2h1Cq/lEuFSW59cbo5h901Jx\nyPVVa6qPYdkLatI/Cxexan+oKJG1BpUoRsKx95wPPV/jxtjP/b8i4qvq71V/h35LaX0uMkgVMJj0\n7SFBl8ciLbSrWZfmMt/sXQszNIhXU/hZwslNQA==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIE4jCCAsqgAwIBAgIIddq/0OOwJzIwDQYJKoZIhvcNAQELBQAwejELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMyMjE0MzAzMVoXDTM3MTEyNjE0MzAzMVowgYIxCzAJBgNVBAYTAkNOMRYwFAYDVQQKDA1BbnQgRmluYW5jaWFsMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE5MDcGA1UEAwwwQW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDbGFzcyAxIFIxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3OruCD7d4evJiEKxzJQYmwp5ziF7lT4fMpBb+WLme42Ulrkh4cJCDEOTUL29Yb8NyQ6cRe9UHLupI2HbByDZoSJl7nkxyi5NGJLaADC7wnFBJq39WMaVBzouFo0yQkkYNbbkJm+MsV4obu3l2xFGQx72bz6ThDJLpfYJbnGXqC4Bcyn8ubj1ddrJ0VsGdj/3Knmuo7XWLYqqN/qomK3LJIpfhVozi0b2FWQl+lE9urch+FVhXSg0AlRGn8FTOVNlKrY+hAKZGZhqC+J+BD4GL3hQZzVeNl0tMmSGz474lnt7DExNq33WfyJkn5UIoCfg8Tno7XTnocmBzbNYPq1aSQIDAQABo2MwYTAfBgNVHSMEGDAWgBRfdLQEwE8HWurlsdsio4dBspzhATAdBgNVHQ4EFgQUcQfiBGEW5OXyZesxD8ng9Dya1ZEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAGkc6bDB4YQCa5D6IbgRtLfiqTQb5DeCp38uVKKrUl8ZCE5U+wXSu/fFhOkIs+Aq9tEOdPWgi7TAxPMMbfJRTAF20qK1qF/X6lwRYGSi7LBbEhmI7dYFKj7i7z6fupBMVaI4C4O8KJGfovp3qD/FkXyb13Lo8vL85Ll0BFk89Qbim0qYhW2JRsf9G46vBeIZaoMm8iMv9vvlVgMs30R96W+gZBgvlIE4ah+oOEUd+G/V74vTbaXtWI8gkmwCzs/yUGW2g2ERHqZ3ksq4xwL+mNmqRNzq3aC9iA4p0uoHp/els89vWHCUaPjHmEnhx+M843/WVjN8LWpoeQ+wc7Wz1jfYy0e+JXidqWkPn7qorlEQTfzcFBZh+YHnV6oVtcG5iYatRKVTAPA+RrjJnEEzn6hAIPsiYsLmdA18f6ruuUUuKRukAEbCQ9q9L1gyOkaz2LxZj5kOFyemDa3pjqESuHuazztnOvs6u4YrH03CPyK3G/6MhCNEJTxGDYy+8bRtNsTGRUbdmhZm/u8tjYIreNEy55f4WYlb72R6PODBLXmf4HWWPpyX1Zy9TEhmFsuPfelhBrdmBVM1iTwVFLW7gLqoEwzYhMt5KRPjmfCc2P2pcbpLnYNcbSYiykFsCa7jHG0137Jv8Z/QH2N9r4+xdER7SW40ndmD59ynmGvrWUMj\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "pay-spring-boot-starter-demo/src/main/resources/ali/alipayRootCert.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG\nEwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw\nMzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO\nUkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE\nMPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT\nV7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti\nW/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ\nMxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b\n53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI\npDoiVhsLwg==\n-----END CERTIFICATE-----\n\n-----BEGIN CERTIFICATE-----\nMIIF0zCCA7ugAwIBAgIIH8+hjWpIDREwDQYJKoZIhvcNAQELBQAwejELMAkGA1UE\nBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmlj\nYXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmlj\nYXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMyMTEzNDg0MFoXDTM4MDIyODEzNDg0\nMFowejELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNV\nBAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5j\naWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMIICIjANBgkqhkiG9w0BAQEF\nAAOCAg8AMIICCgKCAgEAtytTRcBNuur5h8xuxnlKJetT65cHGemGi8oD+beHFPTk\nrUTlFt9Xn7fAVGo6QSsPb9uGLpUFGEdGmbsQ2q9cV4P89qkH04VzIPwT7AywJdt2\nxAvMs+MgHFJzOYfL1QkdOOVO7NwKxH8IvlQgFabWomWk2Ei9WfUyxFjVO1LVh0Bp\ndRBeWLMkdudx0tl3+21t1apnReFNQ5nfX29xeSxIhesaMHDZFViO/DXDNW2BcTs6\nvSWKyJ4YIIIzStumD8K1xMsoaZBMDxg4itjWFaKRgNuPiIn4kjDY3kC66Sl/6yTl\nYUz8AybbEsICZzssdZh7jcNb1VRfk79lgAprm/Ktl+mgrU1gaMGP1OE25JCbqli1\nPbw/BpPynyP9+XulE+2mxFwTYhKAwpDIDKuYsFUXuo8t261pCovI1CXFzAQM2w7H\nDtA2nOXSW6q0jGDJ5+WauH+K8ZSvA6x4sFo4u0KNCx0ROTBpLif6GTngqo3sj+98\nSZiMNLFMQoQkjkdN5Q5g9N6CFZPVZ6QpO0JcIc7S1le/g9z5iBKnifrKxy0TQjtG\nPsDwc8ubPnRm/F82RReCoyNyx63indpgFfhN7+KxUIQ9cOwwTvemmor0A+ZQamRe\n9LMuiEfEaWUDK+6O0Gl8lO571uI5onYdN1VIgOmwFbe+D8TcuzVjIZ/zvHrAGUcC\nAwEAAaNdMFswCwYDVR0PBAQDAgEGMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFF90\ntATATwda6uWx2yKjh0GynOEBMB8GA1UdIwQYMBaAFF90tATATwda6uWx2yKjh0Gy\nnOEBMA0GCSqGSIb3DQEBCwUAA4ICAQCVYaOtqOLIpsrEikE5lb+UARNSFJg6tpkf\ntJ2U8QF/DejemEHx5IClQu6ajxjtu0Aie4/3UnIXop8nH/Q57l+Wyt9T7N2WPiNq\nJSlYKYbJpPF8LXbuKYG3BTFTdOVFIeRe2NUyYh/xs6bXGr4WKTXb3qBmzR02FSy3\nIODQw5Q6zpXj8prYqFHYsOvGCEc1CwJaSaYwRhTkFedJUxiyhyB5GQwoFfExCVHW\n05ZFCAVYFldCJvUzfzrWubN6wX0DD2dwultgmldOn/W/n8at52mpPNvIdbZb2F41\nT0YZeoWnCJrYXjq/32oc1cmifIHqySnyMnavi75DxPCdZsCOpSAT4j4lAQRGsfgI\nkkLPGQieMfNNkMCKh7qjwdXAVtdqhf0RVtFILH3OyEodlk1HYXqX5iE5wlaKzDop\nPKwf2Q3BErq1xChYGGVS+dEvyXc/2nIBlt7uLWKp4XFjqekKbaGaLJdjYP5b2s7N\n1dM0MXQ/f8XoXKBkJNzEiM3hfsU6DOREgMc1DIsFKxfuMwX3EkVQM1If8ghb6x5Y\njXayv+NLbidOSzk4vl5QwngO/JYFMkoc6i9LNwEaEtR9PhnrdubxmrtM+RjfBm02\n77q3dSWFESFQ4QxYWew4pHE0DpWbWy/iMIKQ6UZ5RLvB8GEcgt8ON7BBJeMc+Dyi\nkT9qhqn+lw==\n-----END CERTIFICATE-----\n\n-----BEGIN CERTIFICATE-----\nMIICiDCCAgygAwIBAgIIQX76UsB/30owDAYIKoZIzj0EAwMFADB6MQswCQYDVQQG\nEwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UECwwXQ2VydGlmaWNh\ndGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNpYWwgQ2VydGlmaWNh\ndGlvbiBBdXRob3JpdHkgRTEwHhcNMTkwNDI4MTYyMDQ0WhcNNDkwNDIwMTYyMDQ0\nWjB6MQswCQYDVQQGEwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UE\nCwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNp\nYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRTEwdjAQBgcqhkjOPQIBBgUrgQQA\nIgNiAASCCRa94QI0vR5Up9Yr9HEupz6hSoyjySYqo7v837KnmjveUIUNiuC9pWAU\nWP3jwLX3HkzeiNdeg22a0IZPoSUCpasufiLAnfXh6NInLiWBrjLJXDSGaY7vaokt\nrpZvAdmjXTBbMAsGA1UdDwQEAwIBBjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRZ\n4ZTgDpksHL2qcpkFkxD2zVd16TAfBgNVHSMEGDAWgBRZ4ZTgDpksHL2qcpkFkxD2\nzVd16TAMBggqhkjOPQQDAwUAA2gAMGUCMQD4IoqT2hTUn0jt7oXLdMJ8q4vLp6sg\nwHfPiOr9gxreb+e6Oidwd2LDnC4OUqCWiF8CMAzwKs4SnDJYcMLf2vpkbuVE4dTH\nRglz+HGcTLWsFs4KxLsq7MuU+vJTBUeDJeDjdA==\n-----END CERTIFICATE-----\n\n-----BEGIN CERTIFICATE-----\nMIIDxTCCAq2gAwIBAgIUEMdk6dVgOEIS2cCP0Q43P90Ps5YwDQYJKoZIhvcNAQEF\nBQAwajELMAkGA1UEBhMCQ04xEzARBgNVBAoMCmlUcnVzQ2hpbmExHDAaBgNVBAsM\nE0NoaW5hIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMMH2lUcnVzQ2hpbmEgQ2xhc3Mg\nMiBSb290IENBIC0gRzMwHhcNMTMwNDE4MDkzNjU2WhcNMzMwNDE4MDkzNjU2WjBq\nMQswCQYDVQQGEwJDTjETMBEGA1UECgwKaVRydXNDaGluYTEcMBoGA1UECwwTQ2hp\nbmEgVHJ1c3QgTmV0d29yazEoMCYGA1UEAwwfaVRydXNDaGluYSBDbGFzcyAyIFJv\nb3QgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOPPShpV\nnJbMqqCw6Bz1kehnoPst9pkr0V9idOwU2oyS47/HjJXk9Rd5a9xfwkPO88trUpz5\n4GmmwspDXjVFu9L0eFaRuH3KMha1Ak01citbF7cQLJlS7XI+tpkTGHEY5pt3EsQg\nwykfZl/A1jrnSkspMS997r2Gim54cwz+mTMgDRhZsKK/lbOeBPpWtcFizjXYCqhw\nWktvQfZBYi6o4sHCshnOswi4yV1p+LuFcQ2ciYdWvULh1eZhLxHbGXyznYHi0dGN\nz+I9H8aXxqAQfHVhbdHNzi77hCxFjOy+hHrGsyzjrd2swVQ2iUWP8BfEQqGLqM1g\nKgWKYfcTGdbPB1MCAwEAAaNjMGEwHQYDVR0OBBYEFG/oAMxTVe7y0+408CTAK8hA\nuTyRMB8GA1UdIwQYMBaAFG/oAMxTVe7y0+408CTAK8hAuTyRMA8GA1UdEwEB/wQF\nMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBLnUTfW7hp\nemMbuUGCk7RBswzOT83bDM6824EkUnf+X0iKS95SUNGeeSWK2o/3ALJo5hi7GZr3\nU8eLaWAcYizfO99UXMRBPw5PRR+gXGEronGUugLpxsjuynoLQu8GQAeysSXKbN1I\nUugDo9u8igJORYA+5ms0s5sCUySqbQ2R5z/GoceyI9LdxIVa1RjVX8pYOj8JFwtn\nDJN3ftSFvNMYwRuILKuqUYSHc2GPYiHVflDh5nDymCMOQFcFG3WsEuB+EYQPFgIU\n1DHmdZcz7Llx8UOZXX2JupWCYzK1XhJb+r4hK5ncf/w8qGtYlmyJpxk3hr1TfUJX\nYf4Zr0fJsGuv\n-----END CERTIFICATE-----"
  },
  {
    "path": "pay-spring-boot-starter-demo/src/main/resources/ali/appCertPublicKey_2016080400165436.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDjzCCAnegAwIBAgIQICARMFLSkg9etOjTIGp0hjANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UE\nBhMCQ04xGzAZBgNVBAoMEkFudCBGaW5hbmNpYWwgdGVzdDElMCMGA1UECwwcQ2VydGlmaWNhdGlv\nbiBBdXRob3JpdHkgdGVzdDE+MDwGA1UEAww1QW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1\ndGhvcml0eSBDbGFzcyAyIFIxIHRlc3QwHhcNMjAxMTMwMDMwMzAyWhcNMjMxMTI5MDMwMzAyWjBh\nMQswCQYDVQQGEwJDTjEVMBMGA1UECgwM5rKZ566x546v5aKDMQ8wDQYDVQQLDAZBbGlwYXkxKjAo\nBgNVBAMMITIwODgxMDIxNjk5MTY0MzYtMjAxNjA4MDQwMDE2NTQzNjCCASIwDQYJKoZIhvcNAQEB\nBQADggEPADCCAQoCggEBALDswPYLC/+OdeywWNecbHcmUYXnuAlrZphslFXwyc2I9Wlfgdr7xmOd\nAOG+StYfiEebNy6M6vbXceqWgylRJgHMI+JcZVFRS92KZ6NwcdOh3ucjiDqfO3PN97L9Nc0Meanu\n9jek4hyMHRmfSmQ0DPa0oAWSpvitoc6pMHRADTMPbgKf7bonZQnJhFyB4fQa1JC5SubvJoay4pqS\nH6q2BYXpHvWfk8wY5NDksfeLRZUd8IGQ0aAkLrIL3odHgPtyiyjIoPT6WnxQH81VRaXtO38os6AV\nTCHQYpJgV+/no79UFXb7GoIYTg+VkRJ9W46rPm+OPHPDfEMBQmtXyFJf8AkCAwEAAaMSMBAwDgYD\nVR0PAQH/BAQDAgTwMA0GCSqGSIb3DQEBCwUAA4IBAQChVg6GZf8LcjlMlIt7RhQZjbycGlRB5pp2\nbckojulTEoHbmjvjL9LRJAtjuHQ1Teuy3meK6iT/J+O8PWXEigLtX+K+5Xne3JpRcztAciRmWhLe\ndAEvh1aPPmiG11ZDPC2dDOtTQVIleLpbFtYkqn9IVsU2n+2lmM7aMbw1969wADE4mov2X3m6bnuI\nCzrPGpWiI0MwLp00e0sNHnHXpzENxtabBqabYvL/AH7QZgAmX0JTxYwx0zW7r1JiAc+42Eh/qwqE\nTJa+tOY+Iig5GcFkc6fE7guTNGxz2OhKr2whNq6uRnLbA+Xwx11NhE1K3NHNrZZpSf3QW1//xJoC\nzlBJ\n-----END CERTIFICATE-----"
  },
  {
    "path": "pay-spring-boot-starter-demo/src/main/resources/ali/www.egzosn.com_私钥.txt",
    "content": "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCw7MD2Cwv/jnXssFjXnGx3JlGF57gJa2aYbJRV8MnNiPVpX4Ha+8ZjnQDhvkrWH4hHmzcujOr213HqloMpUSYBzCPiXGVRUUvdimejcHHTod7nI4g6nztzzfey/TXNDHmp7vY3pOIcjB0Zn0pkNAz2tKAFkqb4raHOqTB0QA0zD24Cn+26J2UJyYRcgeH0GtSQuUrm7yaGsuKakh+qtgWF6R71n5PMGOTQ5LH3i0WVHfCBkNGgJC6yC96HR4D7cosoyKD0+lp8UB/NVUWl7Tt/KLOgFUwh0GKSYFfv56O/VBV2+xqCGE4PlZESfVuOqz5vjjxzw3xDAUJrV8hSX/AJAgMBAAECggEBAKE0d3U4B4yo/2XUIH8EdgfykCFUSum6RFbpyBauORHfksyaSzV+ZvtomN8XhhSn0oJ8OMFfgM+86nz2+zdwSxMkMCYWTfLUAi4v59KRqAVO3kz4oS3Y3FDeAK3D7XuRvGFL7GgzAhtEx1cLPrsiehVn6s5pG15GxsIIgq/JlL1J88wn1zENLrVHmD6z/JpXvfb/RS1yR+5lyoohp4g0Ph9jJ3bCyUbRpK0QkPEzgAuWL0K2ITCL7PYHNAplI8d2xHHOLF9Qdjyx+ZrQ/RxtqzfyWzhqjsmp2qlgNCxWlt3woS9UhDB+nRvjEoWTJmIOszAMYuj8wGlX+3Ui3ALOdQECgYEA25EqnFPFinUnzgNvB6NYmh5STmZun6s4bUOLqwefKtEvrOtRwTu7sB7NIf37fizG3/MJUWHxiLy2/3ub4d2JxdDNBtJoEqnp6QB12qglCNa4CajdjtJa1dR81F9QvytsqEkmPYXFPPyviB0FcSIDAGMb3IbwvIfzBPY9WY8dJnECgYEAzkg3yKEFBZ8BU0WQ+3hyfKUoAhBEnxouxRSTBcXxwstJRiqaGTVe5aoJGQI+0xS7Z6q07XDtN2t97s6DnRLWbljsX6B64itzNhXRyzjdD3iZDU/KSw7khjhXf8XOZaj9eXmACDiUnkEn1xsM8bLiRGqB8y5f3aMY/RpuACGXnxkCgYEAx/zwT9Vpr1RIfjfYcJ+Su0X0994K0roUukj0tUJK8qf4gcsQ+y1aJe/YLib1ZBaKyj7G9O5+HmqtUAUZld/AdoJZzOXmz2EeYhD+R7wxh1xz4rCBpW3qOKvDS3jJxmZaIOoHv6/RWFxb0WGFrGcrTrX3EaWDLmWxr4pNlP5qsbECgYATllntrBR8/ycyEAX/SuWcHlaZM5BAh0zvm8+GGdCmDYWMqxjs0duL9URd4o+ynWJaKqR5c2KjA4r2tRdcP+Cqo7j2L5fbiAKtnQ7JvEGJaYsm72+nBuf+MrVkRZUepBhFg5r7rNu31zoAO+pTvQetNWvXeozRz93ckrjlPEtYaQKBgQDFwbV92rlRMLjZzlY+o0knoeJBjPQmPdiBTpGNimdy9L4c2Ure7affjcUiYhkKqrK5k5SScJTATgyQ7JF346FdtUtZ/6Kkj1RwJmmprPrDa9CATLoTle7g9OVd4sHT2ITHZMzPaF3ILvzcwJ70AD1xcxCQb+/7sDPmw7Mc8gOA7Q=="
  },
  {
    "path": "pay-spring-boot-starter-demo/src/main/resources/application.yml",
    "content": "server:\n  port: 8080\n#  context-path: /dock\n\n\n\nlogging:\n  level:\n#    root: debug\n      com:\n        egzosn: debug\n  file: examples.log\n\n\n\n\nspring:\n  datasource:\n    #数据库文件存放 /doc/sql目录下\n    url: jdbc:mysql://localhost:3306/merchant_pay?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&useOldAliasMetadataBehavior=true&serverTimezone=UTC\n    username: root\n    password: root\n    max-active: 20\n    max-idle: 8\n    min-idle: 8\n    initial-size: 10\n    #指定连接多久没被使用时，被设置为空闲，默认为10ms\n    idle-timeout: 10\n    driver-class-name: com.mysql.cj.jdbc.Driver\n    #验证连接的有效性\n    test-while-idle: true\n    validation-query: select 1 from dual\n    #空闲连接回收的时间间隔，与test-while-idle一起使用，设置5分钟\n    time-between-eviction-runs-millis: 300000\n    #连接池空闲连接的有效时间 ，设置30分钟\n    min-evictable-idle-time-millis: 1800000\n"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>pay-java-parent</artifactId>\n        <groupId>com.egzosn</groupId>\n        <version>2.14.9</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>pay-spring-boot-starter-parent</artifactId>\n    <name>pay-spring-boot-starter-parent</name>\n    <packaging>pom</packaging>\n    <version>1.0.5</version>\n    <modules>\n        <module>pay-spring-boot</module>\n        <module>pay-spring-boot-starter</module>\n        <module>pay-spring-boot-autoconfigue</module>\n        <module>pay-spring-boot-starter-demo</module>\n    </modules>\n\n    <properties>\n        <java.version>17</java.version>\n        <pay.version>2.14.9</pay.version>\n    </properties>\n    <licenses>\n        <license>\n            <name>The Apache License, Version 2.0</name>\n            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>\n        </license>\n    </licenses>\n    <developers>\n        <developer>\n            <name>Egan</name>\n            <email>egzosn@gmail.com</email>\n            <url>https://github.com/egzosn</url>\n        </developer>\n    </developers>\n    <scm>\n        <connection>scm:git:https://github.com/egzosn/pay-java-parent.git</connection>\n        <developerConnection>scm:git:git@github.com:egzosn/pay-java-parent.git</developerConnection>\n        <url>https://github.com/egzosn/pay-java-parent</url>\n    </scm>\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-autoconfigure</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-common</artifactId>\n            <optional>true</optional>\n        </dependency>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-ali</artifactId>\n            <optional>true</optional>\n        </dependency>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-wx</artifactId>\n            <optional>true</optional>\n        </dependency>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-wx-youdian</artifactId>\n            <optional>true</optional>\n        </dependency>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-union</artifactId>\n            <optional>true</optional>\n        </dependency>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-payoneer</artifactId>\n            <optional>true</optional>\n        </dependency>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-paypal</artifactId>\n            <optional>true</optional>\n        </dependency>\n        <dependency>\n            <groupId>com.egzosn</groupId>\n            <artifactId>pay-java-fuiou</artifactId>\n            <optional>true</optional>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-jdbc</artifactId>\n            <optional>true</optional>\n        </dependency>\n    </dependencies>\n    <dependencyManagement>\n        <dependencies>\n            <dependency> <!-- Import dependency management from Spring Boot -->\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-dependencies</artifactId>\n                <version>2.4.0</version>\n                <type>pom</type>\n                <scope>import</scope>\n            </dependency>\n            <dependency>\n                <groupId>com.egzosn</groupId>\n                <artifactId>pay-java-common</artifactId>\n                <version>${pay.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.egzosn</groupId>\n                <artifactId>pay-java-ali</artifactId>\n                <version>${pay.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.egzosn</groupId>\n                <artifactId>pay-java-wx</artifactId>\n                <version>${pay.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.egzosn</groupId>\n                <artifactId>pay-java-web-support</artifactId>\n                <version>${pay.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.egzosn</groupId>\n                <artifactId>pay-java-wx-youdian</artifactId>\n                <version>${pay.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.egzosn</groupId>\n                <artifactId>pay-java-union</artifactId>\n                <version>${pay.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.egzosn</groupId>\n                <artifactId>pay-java-payoneer</artifactId>\n                <version>${pay.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.egzosn</groupId>\n                <artifactId>pay-java-paypal</artifactId>\n                <version>${pay.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.egzosn</groupId>\n                <artifactId>pay-java-fuiou</artifactId>\n                <version>${pay.version}</version>\n            </dependency>\n        </dependencies>\n    </dependencyManagement>\n    <build>\n        <plugins>\n\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n                <configuration>\n                    <!--                        <fork>true</fork>-->\n                    <compilerArgs>\n                        <arg>-parameters</arg>\n                    </compilerArgs>\n                    <source>${maven.compiler.source}</source>\n                    <target>${maven.compiler.target}</target>\n                    <encoding>${project.build.sourceEncoding}</encoding>\n                </configuration>\n            </plugin>\n            <plugin>\n                <groupId>org.codehaus.mojo</groupId>\n                <artifactId>flatten-maven-plugin</artifactId>\n                <version>${flatten-maven-plugin.version}</version>\n                <configuration>\n                    <updatePomFile>true</updatePomFile>\n                    <flattenMode>resolveCiFriendliesOnly</flattenMode>\n                </configuration>\n                <executions>\n                    <execution>\n                        <id>flatten</id>\n                        <phase>process-resources</phase>\n                        <goals>\n                            <goal>flatten</goal>\n                        </goals>\n                    </execution>\n                    <execution>\n                        <id>flatten.clean</id>\n                        <phase>clean</phase>\n                        <goals>\n                            <goal>clean</goal>\n                        </goals>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n\n    </build>\n    <profiles>\n        <profile>\n            <id>local</id>\n            <activation>\n                <activeByDefault>true</activeByDefault>\n            </activation>\n        </profile>\n        <profile>\n            <id>proc</id>\n            <build>\n                <plugins>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-source-plugin</artifactId>\n                        <version>3.3.0</version>\n                        <executions>\n                            <execution>\n                                <id>attach-sources</id>\n                                <goals>\n                                    <goal>jar-no-fork</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-javadoc-plugin</artifactId>\n                        <version>3.6.0</version>\n                        <executions>\n                            <execution>\n                                <id>attach-javadocs</id>\n                                <goals>\n                                    <goal>jar</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-gpg-plugin</artifactId>\n                        <version>1.6</version>\n                        <executions>\n                            <execution>\n                                <id>sign-artifacts</id>\n                                <phase>verify</phase>\n                                <goals>\n                                    <goal>sign</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.sonatype.central</groupId>\n                        <artifactId>central-publishing-maven-plugin</artifactId>\n                        <version>0.5.0</version>\n                        <extensions>true</extensions>\n                        <configuration>\n                            <publishingServerId>central</publishingServerId>\n                        </configuration>\n                    </plugin>\n                </plugins>\n            </build>\n        </profile>\n    </profiles>\n</project>"
  }
]