From 1bb16e600ca1807380b6e3707da98b53f0864e76 Mon Sep 17 00:00:00 2001 From: Francesco Panico Date: Tue, 15 Apr 2025 16:20:09 +0000 Subject: [PATCH 1/8] Initial commit --- README.md | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..0e863755 --- /dev/null +++ b/README.md @@ -0,0 +1,93 @@ +# swagger-diff + + + +## Getting started + +To make it easy for you to get started with GitLab, here's a list of recommended next steps. + +Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! + +## Add your files + +- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files +- [ ] [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command: + +``` +cd existing_repo +git remote add origin https://git.imolinfo.it/bancoBPM/swagger-diff.git +git branch -M develop +git push -uf origin develop +``` + +## Integrate with your tools + +- [ ] [Set up project integrations](https://git.imolinfo.it/bancoBPM/swagger-diff/-/settings/integrations) + +## Collaborate with your team + +- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) +- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) +- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) +- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) +- [ ] [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/) + +## Test and Deploy + +Use the built-in continuous integration in GitLab. + +- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/) +- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) +- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) +- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) +- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) + +*** + +# Editing this README + +When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template. + +## Suggestions for a good README + +Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. + +## Name +Choose a self-explaining name for your project. + +## Description +Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. + +## Badges +On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. + +## Visuals +Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. + +## Installation +Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. + +## Usage +Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. + +## Support +Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. + +## Roadmap +If you have ideas for releases in the future, it is a good idea to list them in the README. + +## Contributing +State if you are open to contributions and what your requirements are for accepting them. + +For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. + +You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. + +## Authors and acknowledgment +Show your appreciation to those who have contributed to the project. + +## License +For open source projects, say how it is licensed. + +## Project status +If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. From a48d266fe90c64b94cdc827608409df87da5eb3e Mon Sep 17 00:00:00 2001 From: Francesco Panico Date: Thu, 11 Sep 2025 11:12:00 +0000 Subject: [PATCH 2/8] aggiunto utilizzo --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0e863755..e2389566 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # swagger-diff - +## Utilizzo +``` +java -jar swagger-diff-1.2.2.jar -old File.yaml -new fileNuovo.yaml -v 2.0 -output-mode html > diff.md +``` ## Getting started From a31eb0cca76ff9d6715068cbecf73e6b9ea3d03f Mon Sep 17 00:00:00 2001 From: Francesco Panico Date: Thu, 11 Sep 2025 15:34:26 +0200 Subject: [PATCH 3/8] Sistemazione main class --- README.md | 3 ++- pom.xml | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e2389566..9bfd6261 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ ## Utilizzo ``` -java -jar swagger-diff-1.2.2.jar -old File.yaml -new fileNuovo.yaml -v 2.0 -output-mode html > diff.md + mvn clean compile assembly:single + java -jar swagger-diff-1.2.2-jar-with-dependencies.jar -old File.yaml -new fileNuovo.yaml -v 2.0 -output-mode html > diff.md ``` ## Getting started diff --git a/pom.xml b/pom.xml index 27fc64c4..43ee70eb 100644 --- a/pom.xml +++ b/pom.xml @@ -93,6 +93,11 @@ 4.8.2 test + + org.slf4j + slf4j-simple + 1.7.36 + @@ -199,6 +204,32 @@ coveralls-maven-plugin 4.3.0 + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + com.deepoove.swagger.diff.cli.CLI + + + + + + maven-assembly-plugin + + + + com.deepoove.swagger.diff.cli.CLI + + + + jar-with-dependencies + + + + From f4a45a41c757388ebbbc1d92fb7e71793c18b1ff Mon Sep 17 00:00:00 2001 From: Francesco Panico Date: Mon, 29 Jun 2026 18:24:04 +0200 Subject: [PATCH 4/8] Aggiunto supporto per OpenApi 3.0.0 --- .gitignore | 4 + pom.xml | 33 +- src/.DS_Store | Bin 0 -> 8196 bytes .../deepoove/swagger/diff/SwaggerDiff.java | 149 +++----- .../com/deepoove/swagger/diff/cli/CLI.java | 62 ++-- .../swagger/diff/compare/ModelDiff.java | 248 +++++++------ .../swagger/diff/compare/ParameterDiff.java | 114 ++---- .../swagger/diff/compare/PropertyDiff.java | 59 ++- .../diff/compare/SpecificationDiff.java | 332 ++++++++++++----- .../swagger/diff/model/ChangedEndpoint.java | 25 +- .../swagger/diff/model/ChangedOperation.java | 89 ++++- .../swagger/diff/model/ChangedParameter.java | 3 +- .../swagger/diff/model/ChangedResponse.java | 109 ++++++ .../swagger/diff/model/ElProperty.java | 10 +- .../deepoove/swagger/diff/model/Endpoint.java | 17 +- .../swagger/diff/output/HtmlRender.java | 224 ++++++------ .../swagger/diff/output/MarkdownRender.java | 335 ++++++++---------- src/test/.DS_Store | Bin 0 -> 6148 bytes .../com/deepoove/swagger/test/CLITest.java | 56 ++- .../swagger/test/SwaggerDiffTest.java | 182 +++++++++- src/test/resources/petstore_v3_diff1.json | 38 ++ src/test/resources/petstore_v3_diff2.json | 81 +++++ src/test/resources/petstore_v3_empty.json | 53 +++ 23 files changed, 1424 insertions(+), 799 deletions(-) create mode 100644 src/.DS_Store create mode 100644 src/main/java/com/deepoove/swagger/diff/model/ChangedResponse.java create mode 100644 src/test/.DS_Store create mode 100644 src/test/resources/petstore_v3_diff1.json create mode 100644 src/test/resources/petstore_v3_diff2.json create mode 100644 src/test/resources/petstore_v3_empty.json diff --git a/.gitignore b/.gitignore index 618c6c87..6da7e20b 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,7 @@ testDiff.md testDeprecatedApi.html testNewApi.html + +.vscode/ + +.DS_Store diff --git a/pom.xml b/pom.xml index 43ee70eb..b1075187 100644 --- a/pom.xml +++ b/pom.xml @@ -57,14 +57,14 @@ - io.swagger + io.swagger.parser.v3 swagger-parser - 1.0.31 + 2.1.22 - io.swagger - swagger-compat-spec-parser - 1.0.31 + org.apache.commons + commons-lang3 + 3.12.0 com.j2html @@ -229,7 +229,28 @@ - + + org.jacoco + jacoco-maven-plugin + 0.8.12 + + + + prepare-agent + + prepare-agent + + + + + report + test + + report + + + + diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f8524ee5dc6319b92d730c2100befb729e919821 GIT binary patch literal 8196 zcmeHMU2GIp6u#fIzzh>$s09i#c58)VSwpEUQc+m8ZRDrrZ(I7qPo3Qv=!EG^*_qu^ zn`(X1fSUNC@&Ape52#TTeKPSsF+LC^N=(F<_{57w@WI4*?%dg?E%2a;26S#R_q*rZ zbMDMJ`<=PHQ^pw51#>N9Rg5v2E{>W?-8CAY=hszDiZrtcLH;Z|;tyvXFH7>7tE^*1 zoPjt4aR%ZH#2JV)a3f@Z_H5qd>+JhtHtypL#2NTsW`MsR5_EA)MK~cae05M49svl; zNgXyCYkWYMh%go5gg~012H{F5ToD~HAlylxi0o1kP6!n44AJ2O(VY>UP!Qgo)=z}y z3@L$eA7>!Wz||SxXZLb8#0+LLck1~)JM7qg(9m!mQd#+|*>k9=a}Hz%y^%~{1O-2B z4To+SbT`R@v&gfnmE=K6J26i%j zZaf*J;}=`SM~bpcDaZ>^kg_sYRp;qFy?y=r_77-U!MFBUjuF^JtIY^3e?VK{Q_Nd) zp1Uh=6)D!9oaYpVT$)*!Gn`z3jIGU%ld&HX*15drIJ-RG4s6fu>kX`90iWXwO`GcN z_q}}38ZOpr)B3`yg5P83Fn9L%T6v#PQBKWYQhmp&yBhDgFV()abN9Ig+QJI8QeE6r zw0%44SluJG84UIre$H}D+dbS*X?6qqkZt9ag-9x0t}$ettEgJK?AGPFKGV9iN^c=+ zA1&Cys8%b>;vO}6t)iWl_nQ=Cr)TmN&2UDq(d%S+AJ@0$E$W3@t=E%^X2@MWg)Ej> zqpnpnU+FqRToA5J>N;67m2St#T8>b)s2gN$yV6q>5esFdx=B`gbKcMp1>*}{T5prJ z&*g*s#vO(q>>Re-(j%qyEwbG24;p!E=Lj*eI1bc?P!ro!0*}Lo$_7ywNzGFYJpV=?$GP}ZlM>*!A63ejy zby$Tv(TKazjCE*52Rg9>{m8+@AsmK-0*W|>Q9O*t@Hmd+1fIt8cmXfrWt_wtcoT2o z1AK&!@hLvTd3=wH_yL!28CUR|q(~Lga!HqNlj@{ZQoXcV+9++3wn)3BerZ4&6fsDp z`a3WgQ#g=D38t1>^gU2Ib?s8CeqhViZQDC;*i!p;J}<6YDipH?Ly-$PE!zdouYHb#kj1X7WkvN;m zMTo1D)zz9rRVu`WwbiOtMm4B}zRgJz5eY5#s;X8_)hOmR>LjvANVn25ytd?jisfIh zv+NsokzFE||A8{dSb_vrB1x>?h!ioq4eiA2UD$&Rx^MskFpwplJ8&_KqsU_n<9GxU zc$8TF1fIlGcoxqQ(_bX6pTw(p4X@*EoW^@NgZD$ue~GVg0YA=Qap!avDFhHz6=|p)Nd*6Nble!pVOa(l|k;+$R;`gh0|z``14NxPRqO?Rfu> K_y7Oq{{JVgm4U1P literal 0 HcmV?d00001 diff --git a/src/main/java/com/deepoove/swagger/diff/SwaggerDiff.java b/src/main/java/com/deepoove/swagger/diff/SwaggerDiff.java index dfb3ebed..98bf550f 100644 --- a/src/main/java/com/deepoove/swagger/diff/SwaggerDiff.java +++ b/src/main/java/com/deepoove/swagger/diff/SwaggerDiff.java @@ -1,6 +1,5 @@ package com.deepoove.swagger.diff; -import java.io.IOException; import java.util.List; import org.slf4j.Logger; @@ -9,129 +8,99 @@ import com.deepoove.swagger.diff.compare.SpecificationDiff; import com.deepoove.swagger.diff.model.ChangedEndpoint; import com.deepoove.swagger.diff.model.Endpoint; -import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.models.Swagger; -import io.swagger.models.auth.AuthorizationValue; -import io.swagger.parser.SwaggerCompatConverter; -import io.swagger.parser.SwaggerParser; +import io.swagger.parser.OpenAPIParser; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.parser.core.models.ParseOptions; +import io.swagger.v3.parser.core.models.SwaggerParseResult; public class SwaggerDiff { public static final String SWAGGER_VERSION_V2 = "2.0"; + public static final String OPENAPI_VERSION_V3 = "3.0"; private static Logger logger = LoggerFactory.getLogger(SwaggerDiff.class); - private Swagger oldSpecSwagger; - private Swagger newSpecSwagger; + private OpenAPI oldSpecSwagger; + private OpenAPI newSpecSwagger; private List newEndpoints; private List missingEndpoints; private List changedEndpoints; /** - * compare two swagger 1.x doc - * - * @param oldSpec - * old api-doc location:Json or Http - * @param newSpec - * new api-doc location:Json or Http - */ - public static SwaggerDiff compareV1(String oldSpec, String newSpec) { - return compare(oldSpec, newSpec, null, null); - } - - /** - * compare two swagger v2.0 doc - * - * @param oldSpec - * old api-doc location:Json or Http - * @param newSpec - * new api-doc location:Json or Http + * Compare two OpenAPI/Swagger documents (supports both Swagger 2.0 and OpenAPI 3.x). + * + * @param oldSpec old api-doc location: file path or HTTP URL + * @param newSpec new api-doc location: file path or HTTP URL */ public static SwaggerDiff compareV2(String oldSpec, String newSpec) { - return compare(oldSpec, newSpec, null, SWAGGER_VERSION_V2); + return compare(oldSpec, newSpec); } - /** - * compare two swagger v2.0 Sring + * Compare two OpenAPI 3.x documents. * - * @param oldSpec old api-doc json as string - * @param newSpec new api-doc json as string + * @param oldSpec old api-doc location: file path or HTTP URL + * @param newSpec new api-doc location: file path or HTTP URL */ - public static SwaggerDiff compareV2Raw(String oldSpec, String newSpec) { - return new SwaggerDiff(oldSpec, newSpec).compare(); + public static SwaggerDiff compareV3(String oldSpec, String newSpec) { + return compare(oldSpec, newSpec); } - + /** - * Compare two swagger v2.0 docs by JsonNode - * - * @param oldSpec - * old Swagger specification document in v2.0 format as a JsonNode - * @param newSpec - * new Swagger specification document in v2.0 format as a JsonNode + * Compare two OpenAPI/Swagger documents from raw JSON/YAML strings. */ - public static SwaggerDiff compareV2(JsonNode oldSpec, JsonNode newSpec) { - return new SwaggerDiff(oldSpec, newSpec).compare(); + public static SwaggerDiff compareRaw(String oldSpec, String newSpec) { + return new SwaggerDiff(oldSpec, newSpec, true).compare(); } - public static SwaggerDiff compare(String oldSpec, String newSpec, - List auths, String version) { - return new SwaggerDiff(oldSpec, newSpec, auths, version).compare(); + /** @deprecated Use compareV2 or compareV3 */ + @Deprecated + public static SwaggerDiff compareV2Raw(String oldSpec, String newSpec) { + return compareRaw(oldSpec, newSpec); } + public static SwaggerDiff compare(String oldSpec, String newSpec) { + return new SwaggerDiff(oldSpec, newSpec, false).compare(); + } - /** - * @param rawOldSpec - * @param rawNewSpec - */ - private SwaggerDiff(String rawOldSpec, String rawNewSpec) { - SwaggerParser swaggerParser = new SwaggerParser(); - oldSpecSwagger = swaggerParser.parse(rawOldSpec); - newSpecSwagger = swaggerParser.parse(rawNewSpec); + // ---- Constructors ---- - if (null == oldSpecSwagger || null == newSpecSwagger) { - throw new RuntimeException("cannot read api-doc from spec."); - } - } + /** Constructor for file path / URL */ + private SwaggerDiff(String oldSpec, String newSpec, boolean isRawContent) { + ParseOptions options = new ParseOptions(); + options.setResolve(true); + options.setResolveFully(true); - /** - * @param oldSpec - * @param newSpec - * @param auths - * @param version - */ - private SwaggerDiff(String oldSpec, String newSpec, List auths, - String version) { - if (SWAGGER_VERSION_V2.equals(version)) { - SwaggerParser swaggerParser = new SwaggerParser(); - oldSpecSwagger = swaggerParser.read(oldSpec, auths, true); - newSpecSwagger = swaggerParser.read(newSpec, auths, true); - } else { - SwaggerCompatConverter swaggerCompatConverter = new SwaggerCompatConverter(); - try { - oldSpecSwagger = swaggerCompatConverter.read(oldSpec, auths); - newSpecSwagger = swaggerCompatConverter.read(newSpec, auths); - } catch (IOException e) { - logger.error("cannot read api-doc from spec[version_v1.x]", e); - return; - } + OpenAPIParser parser = new OpenAPIParser(); + + SwaggerParseResult oldResult = isRawContent + ? parser.readContents(oldSpec, null, options) + : parser.readLocation(oldSpec, null, options); + SwaggerParseResult newResult = isRawContent + ? parser.readContents(newSpec, null, options) + : parser.readLocation(newSpec, null, options); + + oldSpecSwagger = oldResult.getOpenAPI(); + newSpecSwagger = newResult.getOpenAPI(); + + if (oldResult.getMessages() != null && !oldResult.getMessages().isEmpty()) { + logger.warn("Warnings parsing old spec: {}", oldResult.getMessages()); + } + if (newResult.getMessages() != null && !newResult.getMessages().isEmpty()) { + logger.warn("Warnings parsing new spec: {}", newResult.getMessages()); } - if (null == oldSpecSwagger || null == newSpecSwagger) { throw new RuntimeException( - "cannot read api-doc from spec."); } - } - private SwaggerDiff(JsonNode oldSpec, JsonNode newSpec) { - SwaggerParser swaggerParser = new SwaggerParser(); - oldSpecSwagger = swaggerParser.read(oldSpec, true); - newSpecSwagger = swaggerParser.read(newSpec, true); - if (null == oldSpecSwagger || null == newSpecSwagger) { throw new RuntimeException( - "cannot read api-doc from spec."); } + if (null == oldSpecSwagger || null == newSpecSwagger) { + throw new RuntimeException("Cannot read api-doc from spec. " + + "Old: " + oldResult.getMessages() + + " New: " + newResult.getMessages()); + } } private SwaggerDiff compare() { - SpecificationDiff diff = SpecificationDiff.diff(oldSpecSwagger, newSpecSwagger); + SpecificationDiff diff = SpecificationDiff.diff(oldSpecSwagger, newSpecSwagger); this.newEndpoints = diff.getNewEndpoints(); this.missingEndpoints = diff.getMissingEndpoints(); this.changedEndpoints = diff.getChangedEndpoints(); @@ -151,10 +120,10 @@ public List getChangedEndpoints() { } public String getOldVersion() { - return oldSpecSwagger.getInfo().getVersion(); + return oldSpecSwagger.getInfo() != null ? oldSpecSwagger.getInfo().getVersion() : "unknown"; } public String getNewVersion() { - return newSpecSwagger.getInfo().getVersion(); + return newSpecSwagger.getInfo() != null ? newSpecSwagger.getInfo().getVersion() : "unknown"; } } diff --git a/src/main/java/com/deepoove/swagger/diff/cli/CLI.java b/src/main/java/com/deepoove/swagger/diff/cli/CLI.java index 98c195ba..c1857009 100644 --- a/src/main/java/com/deepoove/swagger/diff/cli/CLI.java +++ b/src/main/java/com/deepoove/swagger/diff/cli/CLI.java @@ -9,30 +9,33 @@ import com.deepoove.swagger.diff.output.Render; /** - * $java -jar swagger-diff.jar -old http://www.petstore.com/swagger.json \n - * -new http://www.petstore.com/swagger_new.json \n - * -v 2.0 \n - * -output-mode markdown \n + * $java -jar swagger-diff.jar -old http://www.petstore.com/swagger.json + * -new http://www.petstore.com/swagger_new.json + * -v 2.0 + * -output-mode markdown + * + * Supports both Swagger 2.0 (-v 2.0) and OpenAPI 3.x (-v 3.0). * * @author Sayi - * @version */ public class CLI { private static final String OUTPUT_MODE_MARKDOWN = "markdown"; private static final String OUTPUT_MODE_JSON = "json"; - @Parameter(names = "-old", description = "old api-doc location:Json file path or Http url", required = true, order = 0) + @Parameter(names = "-old", description = "old api-doc location: file path or HTTP URL", required = true, order = 0) private String oldSpec; - @Parameter(names = "-new", description = "new api-doc location:Json file path or Http url", required = true, order = 1) + @Parameter(names = "-new", description = "new api-doc location: file path or HTTP URL", required = true, order = 1) private String newSpec; - @Parameter(names = "-v", description = "swagger version:1.0 or 2.0", validateWith= RegexValidator.class, order = 2) - @Regex("(2\\.0|1\\.0)") + @Parameter(names = "-v", description = "swagger/openapi version: 2.0 or 3.0", + validateWith = RegexValidator.class, order = 2) + @Regex("(2\\.0|1\\.0|3\\.0)") private String version = SwaggerDiff.SWAGGER_VERSION_V2; - @Parameter(names = "-output-mode", description = "render mode: markdown, html or json", validateWith = RegexValidator.class, order = 3) + @Parameter(names = "-output-mode", description = "render mode: markdown, html or json", + validateWith = RegexValidator.class, order = 3) @Regex("(markdown|html|json)") private String outputMode = OUTPUT_MODE_MARKDOWN; @@ -52,47 +55,32 @@ public static void main(String[] args) { } public void run(JCommander jCommander) { - if (help){ + if (help) { jCommander.setProgramName("java -jar swagger-diff.jar"); jCommander.usage(); return; } - if (v){ - JCommander.getConsole().println("1.2.2"); + if (v) { + JCommander.getConsole().println("1.2.2-oas3"); return; } - SwaggerDiff diff = SwaggerDiff.SWAGGER_VERSION_V2.equals(version) - ? SwaggerDiff.compareV2(oldSpec, newSpec) : SwaggerDiff.compareV1(oldSpec, newSpec); + SwaggerDiff diff = SwaggerDiff.OPENAPI_VERSION_V3.equals(version) + ? SwaggerDiff.compareV3(oldSpec, newSpec) + : SwaggerDiff.compareV2(oldSpec, newSpec); String render = getRender(outputMode).render(diff); JCommander.getConsole().println(render); } private Render getRender(String outputMode) { - if (OUTPUT_MODE_MARKDOWN.equals(outputMode)) { - return new MarkdownRender(); - } else if (OUTPUT_MODE_JSON.equals(outputMode)) { - return new JsonRender(); - } + if (OUTPUT_MODE_MARKDOWN.equals(outputMode)) return new MarkdownRender(); + if (OUTPUT_MODE_JSON.equals(outputMode)) return new JsonRender(); return new HtmlRender("Changelog", "http://deepoove.com/swagger-diff/stylesheets/demo.css"); } - public String getOldSpec() { - return oldSpec; - } - - public String getNewSpec() { - return newSpec; - } - - public String getVersion() { - return version; - } - - public String getOutputMode() { - return outputMode; - } - - + public String getOldSpec() { return oldSpec; } + public String getNewSpec() { return newSpec; } + public String getVersion() { return version; } + public String getOutputMode() { return outputMode; } } diff --git a/src/main/java/com/deepoove/swagger/diff/compare/ModelDiff.java b/src/main/java/com/deepoove/swagger/diff/compare/ModelDiff.java index 600132f5..543471ad 100644 --- a/src/main/java/com/deepoove/swagger/diff/compare/ModelDiff.java +++ b/src/main/java/com/deepoove/swagger/diff/compare/ModelDiff.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -11,100 +12,148 @@ import com.deepoove.swagger.diff.model.ElProperty; -import io.swagger.models.ArrayModel; -import io.swagger.models.Model; -import io.swagger.models.RefModel; -import io.swagger.models.properties.ArrayProperty; -import io.swagger.models.properties.Property; -import io.swagger.models.properties.RefProperty; -import io.swagger.models.properties.StringProperty; +import io.swagger.v3.oas.models.media.Schema; /** - * compare two model - * - * @author Sayi - * @version + * compare two OAS3 Schema (replaces Model + Property from Swagger 2.0) + * + * @author Sayi (adapted for OAS3) */ +@SuppressWarnings({"rawtypes", "unchecked"}) public class ModelDiff { private List increased; private List missing; private List changed; - Map oldDedinitions; - Map newDedinitions; + Map oldDefinitions; + Map newDefinitions; private ModelDiff() { - increased = new ArrayList(); - missing = new ArrayList(); - changed = new ArrayList(); + increased = new ArrayList<>(); + missing = new ArrayList<>(); + changed = new ArrayList<>(); } - public static ModelDiff buildWithDefinition(Map left, Map right) { + public static ModelDiff buildWithDefinition(Map left, Map right) { ModelDiff diff = new ModelDiff(); - diff.oldDedinitions = left; - diff.newDedinitions = right; + diff.oldDefinitions = left != null ? left : new HashMap<>(); + diff.newDefinitions = right != null ? right : new HashMap<>(); return diff; } - public ModelDiff diff(Model leftModel, Model rightModel) { - return this.diff(leftModel, rightModel, null, new HashSet()); + public ModelDiff diff(Schema leftModel, Schema rightModel) { + return this.diff(leftModel, rightModel, null, new HashSet<>()); } - public ModelDiff diff(Model leftModel, Model rightModel, String parentEl) { - return this.diff(leftModel, rightModel, parentEl, new HashSet()); + public ModelDiff diff(Schema leftModel, Schema rightModel, String parentEl) { + return this.diff(leftModel, rightModel, parentEl, new HashSet<>()); } - public ModelDiff diff(Property leftProperty, Property rightProperty) { - return this.diff(findModel(leftProperty, oldDedinitions), findModel(rightProperty, newDedinitions)); + /** Entry point when comparing two property-level schemas (resolves $ref before diffing) */ + public ModelDiff diffSchema(Schema leftProperty, Schema rightProperty) { + return this.diff(resolveRef(leftProperty, oldDefinitions), + resolveRef(rightProperty, newDefinitions)); } - private ModelDiff diff(Model leftInputModel, Model rightInputModel, String parentEl, Set visited) { - // Stop recursing if both models are null - // OR either model is already contained in the visiting history - if ((null == leftInputModel && null == rightInputModel) || visited.contains(leftInputModel) + private ModelDiff diff(Schema leftInputModel, Schema rightInputModel, + String parentEl, Set visited) { + if ((null == leftInputModel && null == rightInputModel) + || visited.contains(leftInputModel) || visited.contains(rightInputModel)) { return this; } - Model leftModel = isModelReference(leftInputModel) ? findReferenceModel(leftInputModel, oldDedinitions) - : leftInputModel; - Model rightModel = isModelReference(rightInputModel) ? findReferenceModel(rightInputModel, newDedinitions) - : rightInputModel; - Map leftProperties = null == leftModel ? null : leftModel.getProperties(); - Map rightProperties = null == rightModel ? null : rightModel.getProperties(); - // Diff the properties - MapKeyDiff propertyDiff = MapKeyDiff.diff(leftProperties, rightProperties); + Schema leftModel = resolveRef(leftInputModel, oldDefinitions); + Schema rightModel = resolveRef(rightInputModel, newDefinitions); - increased.addAll(convert2ElPropertys(propertyDiff.getIncreased(), parentEl)); - missing.addAll(convert2ElPropertys(propertyDiff.getMissing(), parentEl)); + while (leftModel != null && leftModel.getItems() != null && rightModel != null && rightModel.getItems() != null) { + leftModel = resolveRef(leftModel.getItems(), oldDefinitions); + rightModel = resolveRef(rightModel.getItems(), newDefinitions); + } + + Map leftProperties = leftModel == null ? null : leftModel.getProperties(); + Map rightProperties = rightModel == null ? null : rightModel.getProperties(); + + MapKeyDiff propertyDiff = MapKeyDiff.diff(leftProperties, rightProperties); + + increased.addAll(convert2ElProperties(propertyDiff.getIncreased(), parentEl)); + missing.addAll(convert2ElProperties(propertyDiff.getMissing(), parentEl)); + + Set newVisited = copyAndAdd(visited, leftModel, rightModel); - // Recursively find the diff between properties List sharedKey = propertyDiff.getSharedKey(); - sharedKey.stream().forEach((key) -> { - Property left = leftProperties.get(key); - Property right = rightProperties.get(key); - Model leftSubModel = findModel(left, oldDedinitions); - Model rightSubModel = findModel(left, newDedinitions); - if (leftSubModel != null || rightSubModel != null) { - diff(leftSubModel, rightSubModel, buildElString(parentEl, key), - copyAndAdd(visited, leftModel, rightModel)); - } else if (left != null && right != null && !left.equals(right)) { - // Add a changed ElProperty if not a Reference - // Useless - changed.add(addChangeMetadata(convert2ElProperty(key, parentEl, left), left, right)); + sharedKey.forEach(key -> { + Schema left = leftProperties.get(key); + Schema right = rightProperties.get(key); + + // Try to resolve as sub-model (ref or object with properties) + Schema leftSub = resolveToSubModel(left, oldDefinitions); + Schema rightSub = resolveToSubModel(right, newDefinitions); + + if (leftSub != null || rightSub != null) { + diff(leftSub, rightSub, buildElString(parentEl, key), newVisited); + } else if (left != null && right != null) { + ElProperty diffProp = convert2ElProperty(key, parentEl, left); + addChangeMetadata(diffProp, left, right); + if (diffProp.isTypeChange() || diffProp.isNewEnums() || diffProp.isRemovedEnums()) { + changed.add(diffProp); + } } }); + return this; } - private Collection convert2ElPropertys(Map propMap, String parentEl) { + /** Returns the resolved object schema if schema is a $ref or has properties; null otherwise */ + private Schema resolveToSubModel(Schema schema, Map definitions) { + if (schema == null) return null; + if (schema.get$ref() != null) { + return definitions.get(getSimpleRef(schema.get$ref())); + } + // Array: try to resolve items + if (schema.getItems() != null) { + String itemRef = schema.getItems().get$ref(); + if (itemRef != null) { + return definitions.get(getSimpleRef(itemRef)); + } + if (schema.getItems().getProperties() != null && !schema.getItems().getProperties().isEmpty()) { + return schema.getItems(); + } + } + // Object inline with properties + if (schema.getProperties() != null && !schema.getProperties().isEmpty()) { + return schema; + } + return null; + } + + /** Resolve a $ref schema to the referenced schema in definitions */ + private Schema resolveRef(Schema schema, Map definitions) { + if (schema == null) return null; + if (schema.get$ref() != null) { + String name = getSimpleRef(schema.get$ref()); + Schema resolved = definitions.get(name); + return resolved != null ? resolved : schema; + } + return schema; + } - List result = new ArrayList(); - if (null == propMap) return result; + private boolean schemasCompatible(Schema left, Schema right) { + String lt = left.getType(); + String rt = right.getType(); + if (lt != null && !lt.equals(rt)) return false; + String lr = left.get$ref(); + String rr = right.get$ref(); + if (lr != null && !lr.equals(rr)) return false; + return true; + } - for (Entry entry : propMap.entrySet()) { - // TODO Recursively get the properties + private Collection convert2ElProperties( + Map propMap, String parentEl) { + List result = new ArrayList<>(); + if (propMap == null) return result; + for (Entry entry : propMap.entrySet()) { result.add(convert2ElProperty(entry.getKey(), parentEl, entry.getValue())); } return result; @@ -114,21 +163,25 @@ private String buildElString(String parentEl, String propName) { return null == parentEl ? propName : (parentEl + "." + propName); } - private ElProperty convert2ElProperty(String propName, String parentEl, Property property) { + private ElProperty convert2ElProperty(String propName, String parentEl, Schema schema) { ElProperty pWithPath = new ElProperty(); - pWithPath.setProperty(property); + pWithPath.setProperty(schema); pWithPath.setEl(buildElString(parentEl, propName)); return pWithPath; } - private ElProperty addChangeMetadata(ElProperty diffProperty, Property left, Property right) { - diffProperty.setTypeChange(!left.getType().equalsIgnoreCase(right.getType())); + private ElProperty addChangeMetadata(ElProperty diffProperty, Schema left, Schema right) { + String leftType = left.getType(); + String rightType = right.getType(); + diffProperty.setTypeChange(leftType != null && !leftType.equalsIgnoreCase( + rightType != null ? rightType : "")); + List leftEnums = enumValues(left); List rightEnums = enumValues(right); if (!leftEnums.isEmpty() && !rightEnums.isEmpty()) { ListDiff enumDiff = ListDiff.diff(leftEnums, rightEnums, (t, enumVal) -> { for (String value : t) { - if (enumVal.equalsIgnoreCase(value)) { return value; } + if (enumVal.equalsIgnoreCase(value)) return value; } return null; }); @@ -140,70 +193,33 @@ private ElProperty addChangeMetadata(ElProperty diffProperty, Property left, Pro @SuppressWarnings("unchecked") private Set copyAndAdd(Set set, T... add) { - Set newSet = new HashSet(set); + Set newSet = new HashSet<>(set); newSet.addAll(Arrays.asList(add)); return newSet; } - private List enumValues(Property prop) { - if (prop instanceof StringProperty && ((StringProperty) prop).getEnum() != null) { - return ((StringProperty) prop).getEnum(); - } else { - return new ArrayList<>(); - } - } - - private Model findModel(Property property, Map modelMap) { - String modelName = null; - if (property instanceof RefProperty) { - modelName = ((RefProperty) property).getSimpleRef(); - } else if (property instanceof ArrayProperty) { - Property arrayType = ((ArrayProperty) property).getItems(); - if (arrayType instanceof RefProperty) { - modelName = ((RefProperty) arrayType).getSimpleRef(); - } - } - return modelName == null ? null : modelMap.get(modelName); - } - - private boolean isModelReference(Model model) { - return model instanceof RefModel || model instanceof ArrayModel; - } - - private Model findReferenceModel(Model model, Map modelMap) { - String modelName = null; - if (model instanceof RefModel) { - modelName = ((RefModel) model).getSimpleRef(); - } else if (model instanceof ArrayModel) { - Property arrayType = ((ArrayModel) model).getItems(); - if (arrayType instanceof RefProperty) { - modelName = ((RefProperty) arrayType).getSimpleRef(); + private List enumValues(Schema schema) { + List result = new ArrayList<>(); + if (schema.getEnum() != null) { + for (Object val : schema.getEnum()) { + if (val != null) result.add(val.toString()); } } - return modelName == null ? null : modelMap.get(modelName); - } - - public List getIncreased() { - return increased; - } - - public void setIncreased(List increased) { - this.increased = increased; + return result; } - public List getMissing() { - return missing; + private String getSimpleRef(String ref) { + if (ref == null) return null; + int lastSlash = ref.lastIndexOf('/'); + return lastSlash >= 0 ? ref.substring(lastSlash + 1) : ref; } - public void setMissing(List missing) { - this.missing = missing; - } + public List getIncreased() { return increased; } + public void setIncreased(List increased) { this.increased = increased; } - public List getChanged() { - return changed; - } + public List getMissing() { return missing; } + public void setMissing(List missing) { this.missing = missing; } - public void setChanged(List changed) { - this.changed = changed; - } + public List getChanged() { return changed; } + public void setChanged(List changed) { this.changed = changed; } } diff --git a/src/main/java/com/deepoove/swagger/diff/compare/ParameterDiff.java b/src/main/java/com/deepoove/swagger/diff/compare/ParameterDiff.java index 30e8f3ba..b45a126e 100644 --- a/src/main/java/com/deepoove/swagger/diff/compare/ParameterDiff.java +++ b/src/main/java/com/deepoove/swagger/diff/compare/ParameterDiff.java @@ -1,6 +1,7 @@ package com.deepoove.swagger.diff.compare; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -10,38 +11,35 @@ import com.deepoove.swagger.diff.model.ElProperty; import com.google.common.collect.Lists; -import io.swagger.models.Model; -import io.swagger.models.parameters.AbstractSerializableParameter; -import io.swagger.models.parameters.BodyParameter; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.properties.Property; -import io.swagger.models.properties.StringProperty; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; /** - * compare two parameter + * Compare two lists of OAS3 parameters (path/query/header/cookie only; + * request body is handled separately in SpecificationDiff). * - * @author Sayi - * @version + * @author Sayi (adapted for OAS3) */ +@SuppressWarnings({"rawtypes"}) public class ParameterDiff { private List increased; private List missing; private List changed; - Map oldDedinitions; - Map newDedinitions; + Map oldDefinitions; + Map newDefinitions; private ParameterDiff() { - this.increased = new ArrayList(); - this.missing = new ArrayList(); - this.changed = new ArrayList(); + this.increased = new ArrayList<>(); + this.missing = new ArrayList<>(); + this.changed = new ArrayList<>(); } - public static ParameterDiff buildWithDefinition(Map left, Map right) { + public static ParameterDiff buildWithDefinition(Map left, Map right) { ParameterDiff diff = new ParameterDiff(); - diff.oldDedinitions = left; - diff.newDedinitions = right; + diff.oldDefinitions = left != null ? left : new HashMap<>(); + diff.newDefinitions = right != null ? right : new HashMap<>(); return diff; } @@ -51,97 +49,59 @@ public ParameterDiff diff(List left, List right) { ListDiff paramDiff = ListDiff.diff(left, right, (t, param) -> { for (Parameter para : t) { - if (param.getName().equals(para.getName())) { return para; } + if (param.getName() != null && param.getName().equals(para.getName())) return para; } return null; }); this.increased.addAll(paramDiff.getIncreased()); this.missing.addAll(paramDiff.getMissing()); + Map shared = paramDiff.getShared(); shared.forEach((leftPara, rightPara) -> { ChangedParameter changedParameter = new ChangedParameter(); changedParameter.setLeftParameter(leftPara); changedParameter.setRightParameter(rightPara); - if (leftPara instanceof BodyParameter && rightPara instanceof BodyParameter) { - BodyParameter leftBodyPara = (BodyParameter) leftPara; - Model leftSchema = leftBodyPara.getSchema(); - BodyParameter rightBodyPara = (BodyParameter) rightPara; - Model rightSchema = rightBodyPara.getSchema(); - - ModelDiff diff = ModelDiff.buildWithDefinition(oldDedinitions, newDedinitions).diff(leftSchema, - rightSchema, leftPara.getName()); - changedParameter.setIncreased(diff.getIncreased()); - changedParameter.setMissing(diff.getMissing()); - changedParameter.setChanged(diff.getChanged()); - - } - // Let's handle the case where the new API has fx changed the type - // of PathParameter from being of type String to type integer - if (leftPara instanceof AbstractSerializableParameter - && rightPara instanceof AbstractSerializableParameter) { - if (!leftPara.equals(rightPara)) { + // Compare schema type changes (replaces AbstractSerializableParameter check) + Schema leftSchema = leftPara.getSchema(); + Schema rightSchema = rightPara.getSchema(); + if (leftSchema != null && rightSchema != null) { + String leftType = leftSchema.getType(); + String rightType = rightSchema.getType(); + if (leftType != null && !leftType.equals(rightType)) { ElProperty elProperty = new ElProperty(); elProperty.setEl(rightPara.getName()); - elProperty.setProperty(mapToProperty(rightPara)); + elProperty.setProperty(rightSchema); changedParameter.setChanged(Lists.newArrayList(elProperty)); } } - // is requried - boolean rightRequired = rightPara.getRequired(); - boolean leftRequired = leftPara.getRequired(); + // required + boolean rightRequired = Boolean.TRUE.equals(rightPara.getRequired()); + boolean leftRequired = Boolean.TRUE.equals(leftPara.getRequired()); changedParameter.setChangeRequired(leftRequired != rightRequired); // description String description = rightPara.getDescription(); - String oldPescription = leftPara.getDescription(); + String oldDescription = leftPara.getDescription(); if (StringUtils.isBlank(description)) description = ""; - if (StringUtils.isBlank(oldPescription)) oldPescription = ""; - changedParameter.setChangeDescription(!description.equals(oldPescription)); + if (StringUtils.isBlank(oldDescription)) oldDescription = ""; + changedParameter.setChangeDescription(!description.equals(oldDescription)); if (changedParameter.isDiff()) { this.changed.add(changedParameter); } - }); return this; } - private Property mapToProperty(Parameter rightPara) { - Property prop = new StringProperty(); - prop.setAccess(rightPara.getAccess()); - prop.setAllowEmptyValue(rightPara.getAllowEmptyValue()); - prop.setDescription(rightPara.getDescription()); - prop.setName(rightPara.getName()); - prop.setReadOnly(rightPara.isReadOnly()); - prop.setRequired(rightPara.getRequired()); - return prop; - } - - public List getIncreased() { - return increased; - } - - public void setIncreased(List increased) { - this.increased = increased; - } - - public List getMissing() { - return missing; - } - - public void setMissing(List missing) { - this.missing = missing; - } - - public List getChanged() { - return changed; - } + public List getIncreased() { return increased; } + public void setIncreased(List increased) { this.increased = increased; } - public void setChanged(List changed) { - this.changed = changed; - } + public List getMissing() { return missing; } + public void setMissing(List missing) { this.missing = missing; } + public List getChanged() { return changed; } + public void setChanged(List changed) { this.changed = changed; } } diff --git a/src/main/java/com/deepoove/swagger/diff/compare/PropertyDiff.java b/src/main/java/com/deepoove/swagger/diff/compare/PropertyDiff.java index 97817501..ae9df385 100644 --- a/src/main/java/com/deepoove/swagger/diff/compare/PropertyDiff.java +++ b/src/main/java/com/deepoove/swagger/diff/compare/PropertyDiff.java @@ -1,65 +1,52 @@ package com.deepoove.swagger.diff.compare; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import com.deepoove.swagger.diff.model.ElProperty; -import io.swagger.models.Model; -import io.swagger.models.properties.Property; +import io.swagger.v3.oas.models.media.Schema; +@SuppressWarnings({"rawtypes"}) public class PropertyDiff { private List increased; private List missing; private List changed; - Map oldDedinitions; - Map newDedinitions; + Map oldDefinitions; + Map newDefinitions; private PropertyDiff() { - increased = new ArrayList(); - missing = new ArrayList(); - changed = new ArrayList(); + increased = new ArrayList<>(); + missing = new ArrayList<>(); + changed = new ArrayList<>(); } - public static PropertyDiff buildWithDefinition(Map left, Map right) { + public static PropertyDiff buildWithDefinition(Map left, Map right) { PropertyDiff diff = new PropertyDiff(); - diff.oldDedinitions = left; - diff.newDedinitions = right; + diff.oldDefinitions = left != null ? left : new HashMap<>(); + diff.newDefinitions = right != null ? right : new HashMap<>(); return diff; } - public PropertyDiff diff(Property left, Property right) { - ModelDiff diff = ModelDiff.buildWithDefinition(oldDedinitions, newDedinitions).diff(left, right); - increased.addAll(diff.getIncreased()); - missing.addAll(diff.getMissing()); - changed.addAll(diff.getChanged()); + public PropertyDiff diff(Schema left, Schema right) { + ModelDiff modelDiff = ModelDiff.buildWithDefinition(oldDefinitions, newDefinitions) + .diffSchema(left, right); + increased.addAll(modelDiff.getIncreased()); + missing.addAll(modelDiff.getMissing()); + changed.addAll(modelDiff.getChanged()); return this; } - public List getIncreased() { - return increased; - } + public List getIncreased() { return increased; } + public void setIncreased(List increased) { this.increased = increased; } - public void setIncreased(List increased) { - this.increased = increased; - } + public List getMissing() { return missing; } + public void setMissing(List missing) { this.missing = missing; } - public List getMissing() { - return missing; - } - - public void setMissing(List missing) { - this.missing = missing; - } - - public List getChanged() { - return changed; - } - - public void setChanged(List changed) { - this.changed = changed; - } + public List getChanged() { return changed; } + public void setChanged(List changed) { this.changed = changed; } } diff --git a/src/main/java/com/deepoove/swagger/diff/compare/SpecificationDiff.java b/src/main/java/com/deepoove/swagger/diff/compare/SpecificationDiff.java index 2e0e6d66..0bc1441a 100644 --- a/src/main/java/com/deepoove/swagger/diff/compare/SpecificationDiff.java +++ b/src/main/java/com/deepoove/swagger/diff/compare/SpecificationDiff.java @@ -8,22 +8,28 @@ import com.deepoove.swagger.diff.model.ChangedEndpoint; import com.deepoove.swagger.diff.model.ChangedOperation; +import com.deepoove.swagger.diff.model.ChangedResponse; import com.deepoove.swagger.diff.model.Endpoint; -import io.swagger.models.HttpMethod; -import io.swagger.models.Operation; -import io.swagger.models.Path; -import io.swagger.models.Response; -import io.swagger.models.Swagger; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.properties.Property; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.media.Content; +import io.swagger.v3.oas.models.media.MediaType; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.RequestBody; +import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.oas.models.responses.ApiResponses; +import io.swagger.v3.oas.models.headers.Header; + /** - * compare two Swagger - * - * @author Sayi + * Compare two OpenAPI 3.x specifications. * + * @author Sayi (adapted for OAS3) */ +@SuppressWarnings({"rawtypes"}) public class SpecificationDiff { private List newEndpoints; @@ -32,70 +38,152 @@ public class SpecificationDiff { private SpecificationDiff() {} - public static SpecificationDiff diff(Swagger oldSpec, Swagger newSpec) { - if (null == oldSpec || null == newSpec) { throw new IllegalArgumentException("cannot diff null spec."); } + public static SpecificationDiff diff(OpenAPI oldSpec, OpenAPI newSpec) { + if (null == oldSpec || null == newSpec) { + throw new IllegalArgumentException("cannot diff null spec."); + } SpecificationDiff instance = new SpecificationDiff(); - Map oldPaths = oldSpec.getPaths(); - Map newPaths = newSpec.getPaths(); - // Diff path - MapKeyDiff pathDiff = MapKeyDiff.diff(oldPaths, newPaths); + Map oldDefs = getSchemas(oldSpec); + Map newDefs = getSchemas(newSpec); + + Map oldPaths = oldSpec.getPaths() != null ? oldSpec.getPaths() : new HashMap<>(); + Map newPaths = newSpec.getPaths() != null ? newSpec.getPaths() : new HashMap<>(); + + // Diff paths + MapKeyDiff pathDiff = MapKeyDiff.diff(oldPaths, newPaths); instance.newEndpoints = convert2EndpointList(pathDiff.getIncreased()); instance.missingEndpoints = convert2EndpointList(pathDiff.getMissing()); instance.changedEndpoints = new ArrayList<>(); List sharedKey = pathDiff.getSharedKey(); - sharedKey.stream().forEach((pathUrl) -> { + sharedKey.forEach(pathUrl -> { ChangedEndpoint changedEndpoint = new ChangedEndpoint(); changedEndpoint.setPathUrl(pathUrl); - Path oldPath = oldPaths.get(pathUrl); - Path newPath = newPaths.get(pathUrl); - - // Diff Operation - Map oldOperationMap = oldPath.getOperationMap(); - Map newOperationMap = newPath.getOperationMap(); - MapKeyDiff operationDiff = MapKeyDiff.diff(oldOperationMap, newOperationMap); - Map increasedOperation = operationDiff.getIncreased(); - Map missingOperation = operationDiff.getMissing(); - changedEndpoint.setNewOperations(increasedOperation); - changedEndpoint.setMissingOperations(missingOperation); - - List sharedMethods = operationDiff.getSharedKey(); - Map operas = new HashMap<>(); - sharedMethods.stream().forEach((method) -> { + PathItem oldPath = oldPaths.get(pathUrl); + PathItem newPath = newPaths.get(pathUrl); + + // Diff operations + Map oldOpMap = oldPath.readOperationsMap() != null + ? oldPath.readOperationsMap() : new HashMap<>(); + Map newOpMap = newPath.readOperationsMap() != null + ? newPath.readOperationsMap() : new HashMap<>(); + + MapKeyDiff operationDiff = + MapKeyDiff.diff(oldOpMap, newOpMap); + + changedEndpoint.setNewOperations(operationDiff.getIncreased()); + changedEndpoint.setMissingOperations(operationDiff.getMissing()); + + Map operas = new HashMap<>(); + operationDiff.getSharedKey().forEach(method -> { ChangedOperation changedOperation = new ChangedOperation(); - Operation oldOperation = oldOperationMap.get(method); - Operation newOperation = newOperationMap.get(method); - changedOperation.setSummary(newOperation.getSummary()); - - // Diff Parameter - List oldParameters = oldOperation.getParameters(); - List newParameters = newOperation.getParameters(); - ParameterDiff parameterDiff = ParameterDiff - .buildWithDefinition(oldSpec.getDefinitions(), newSpec.getDefinitions()) - .diff(oldParameters, newParameters); - changedOperation.setAddParameters(parameterDiff.getIncreased()); - changedOperation.setMissingParameters(parameterDiff.getMissing()); - changedOperation.setChangedParameter(parameterDiff.getChanged()); - - // Diff response - Property oldResponseProperty = getResponseProperty(oldOperation); - Property newResponseProperty = getResponseProperty(newOperation); - PropertyDiff propertyDiff = PropertyDiff.buildWithDefinition(oldSpec.getDefinitions(), - newSpec.getDefinitions()); - propertyDiff.diff(oldResponseProperty, newResponseProperty); + Operation oldOp = oldOpMap.get(method); + Operation newOp = newOpMap.get(method); + changedOperation.setSummary(newOp.getSummary()); + + // Diff parameters (path/query/header/cookie — NOT body) + List oldParams = oldOp.getParameters() != null + ? oldOp.getParameters() : new ArrayList<>(); + List newParams = newOp.getParameters() != null + ? newOp.getParameters() : new ArrayList<>(); + ParameterDiff paramDiff = ParameterDiff.buildWithDefinition(oldDefs, newDefs) + .diff(oldParams, newParams); + changedOperation.setAddParameters(paramDiff.getIncreased()); + changedOperation.setMissingParameters(paramDiff.getMissing()); + changedOperation.setChangedParameter(paramDiff.getChanged()); + + // Diff request body schema + Schema oldRequestSchema = getRequestSchema(oldOp); + Schema newRequestSchema = getRequestSchema(newOp); + PropertyDiff requestPropertyDiff = PropertyDiff.buildWithDefinition(oldDefs, newDefs); + requestPropertyDiff.diff(oldRequestSchema, newRequestSchema); + changedOperation.setAddRequestProps(requestPropertyDiff.getIncreased()); + changedOperation.setMissingRequestProps(requestPropertyDiff.getMissing()); + changedOperation.setChangedRequestProps(requestPropertyDiff.getChanged()); + + // --- LEGACY: diff schema del 200 sui campi addProps/missingProps/changedProps + // (mantenuto per retrocompatibilità con i test/render esistenti) --- + Schema oldResponseSchema = getResponseSchema(oldOp); // il vecchio helper che prende il 200 + Schema newResponseSchema = getResponseSchema(newOp); + PropertyDiff propertyDiff = PropertyDiff.buildWithDefinition(oldDefs, newDefs); + propertyDiff.diff(oldResponseSchema, newResponseSchema); changedOperation.setAddProps(propertyDiff.getIncreased()); changedOperation.setMissingProps(propertyDiff.getMissing()); changedOperation.setChangedProps(propertyDiff.getChanged()); + // Diff RESPONSES per status code + ApiResponses oldResponses = oldOp.getResponses() != null + ? oldOp.getResponses() : new ApiResponses(); + ApiResponses newResponses = newOp.getResponses() != null + ? newOp.getResponses() : new ApiResponses(); + + MapKeyDiff responseDiff = MapKeyDiff.diff(oldResponses, newResponses); + + // status aggiunti (es. nuovo 201) e rimossi (es. 404 tolto) + changedOperation.setAddResponses(responseDiff.getIncreased()); + changedOperation.setMissingResponses(responseDiff.getMissing()); + + // status presenti in entrambi: diff dello schema per ciascuno + List changedResponseList = new ArrayList<>(); + + responseDiff.getSharedKey().forEach(statusCode -> { + ApiResponse oldResp = oldResponses.get(statusCode); + ApiResponse newResp = newResponses.get(statusCode); + + ChangedResponse cr = new ChangedResponse(); + cr.setStatusCode(statusCode); + + // --- description --- + cr.setOldDescription(oldResp != null ? oldResp.getDescription() : null); + cr.setNewDescription(newResp != null ? newResp.getDescription() : null); + + // --- schema (application/json, come prima) --- + Schema oldRespSchema = getResponseSchema(oldResp); + Schema newRespSchema = getResponseSchema(newResp); + PropertyDiff respPropDiff = PropertyDiff.buildWithDefinition(oldDefs, newDefs); + respPropDiff.diff(oldRespSchema, newRespSchema); + cr.setAddProps(respPropDiff.getIncreased()); + cr.setMissingProps(respPropDiff.getMissing()); + cr.setChangedProps(respPropDiff.getChanged()); + + // --- content-type --- + ListDiff ctDiff = getMediaTypeDiff( + getContentTypes(oldResp), getContentTypes(newResp)); + cr.setAddContentTypes(ctDiff.getIncreased()); + cr.setMissingContentTypes(ctDiff.getMissing()); + + // --- headers --- + Map oldHeaders = getHeaders(oldResp); + Map newHeaders = getHeaders(newResp); + MapKeyDiff headerDiff = MapKeyDiff.diff(oldHeaders, newHeaders); + cr.setAddHeaders(headerDiff.getIncreased()); + cr.setMissingHeaders(headerDiff.getMissing()); + // header presenti in entrambi ma cambiati (per tipo/descrizione) + List changedHeaderNames = new ArrayList<>(); + headerDiff.getSharedKey().forEach(headerName -> { + Header oh = oldHeaders.get(headerName); + Header nh = newHeaders.get(headerName); + if (isHeaderChanged(oh, nh)) { + changedHeaderNames.add(headerName); + } + }); + cr.setChangedHeaders(changedHeaderNames); - // Diff Consumes - ListDiff consumeDiff = getMediaTypeDiff(oldOperation.getConsumes(), newOperation.getConsumes()); + if (cr.isDiff()) { + changedResponseList.add(cr); + } + }); + changedOperation.setChangedResponses(changedResponseList); + + // Diff consumes (request body content types) + ListDiff consumeDiff = getMediaTypeDiff( + getRequestContentTypes(oldOp), getRequestContentTypes(newOp)); changedOperation.setAddConsumes(consumeDiff.getIncreased()); changedOperation.setMissingConsumes(consumeDiff.getMissing()); - // Diff Produces - ListDiff producesDiff = getMediaTypeDiff(oldOperation.getProduces(), - newOperation.getProduces()); + // Diff produces (response content types) + ListDiff producesDiff = getMediaTypeDiff( + getResponseContentTypes(oldOp), getResponseContentTypes(newOp)); changedOperation.setAddProduces(producesDiff.getIncreased()); changedOperation.setMissingProduces(producesDiff.getMissing()); @@ -103,12 +191,13 @@ public static SpecificationDiff diff(Swagger oldSpec, Swagger newSpec) { operas.put(method, changedOperation); } }); + changedEndpoint.setChangedOperations(operas); - instance.newEndpoints - .addAll(convert2EndpointList(changedEndpoint.getPathUrl(), changedEndpoint.getNewOperations())); - instance.missingEndpoints - .addAll(convert2EndpointList(changedEndpoint.getPathUrl(), changedEndpoint.getMissingOperations())); + instance.newEndpoints.addAll( + convert2EndpointList(changedEndpoint.getPathUrl(), changedEndpoint.getNewOperations())); + instance.missingEndpoints.addAll( + convert2EndpointList(changedEndpoint.getPathUrl(), changedEndpoint.getMissingOperations())); if (changedEndpoint.isDiff()) { instance.changedEndpoints.add(changedEndpoint); @@ -116,28 +205,86 @@ public static SpecificationDiff diff(Swagger oldSpec, Swagger newSpec) { }); return instance; + } + // ---- Helpers ---- + + @SuppressWarnings("unchecked") + private static Map getSchemas(OpenAPI api) { + if (api.getComponents() == null) return new HashMap<>(); + Map schemas = api.getComponents().getSchemas(); + return schemas != null ? schemas : new HashMap<>(); } - private static Property getResponseProperty(Operation operation) { - Map responses = operation.getResponses(); - // temporary workaround for missing response messages + // TODO: remove this old method that only manage 200 response + private static Schema getResponseSchema(Operation operation) { + ApiResponses responses = operation.getResponses(); if (responses == null) return null; - Response response = responses.get("200"); - return null == response ? null : response.getSchema(); + ApiResponse response = responses.get("200"); + if (response == null && !responses.isEmpty()) { + response = responses.values().iterator().next(); + } + if (response == null) return null; + Content content = response.getContent(); + if (content == null || content.isEmpty()) return null; + MediaType mediaType = content.get("application/json"); + if (mediaType == null) mediaType = content.values().iterator().next(); + return mediaType != null ? mediaType.getSchema() : null; + } + +private static Schema getResponseSchema(ApiResponse response) { + if (response == null) { System.out.println(">>> response NULL"); return null; } + Content content = response.getContent(); + //System.out.println(">>> response content keys = " + (content != null ? content.keySet() : "NULL")); + if (content == null || content.isEmpty()) return null; + MediaType mediaType = content.get("application/json"); + if (mediaType == null) mediaType = content.values().iterator().next(); + Schema s = mediaType != null ? mediaType.getSchema() : null; + //System.out.println(">>> response schema = " + (s != null ? s.getType() + " ref=" + s.get$ref() : "NULL")); + return s; +} + + private static List getResponseContentTypes(Operation operation) { + ApiResponses responses = operation.getResponses(); + if (responses == null) return new ArrayList<>(); + ApiResponse response = responses.get("200"); + if (response == null && !responses.isEmpty()) { + response = responses.values().iterator().next(); + } + if (response == null) return new ArrayList<>(); + Content content = response.getContent(); + return content != null ? new ArrayList<>(content.keySet()) : new ArrayList<>(); + } + + private static List getRequestContentTypes(Operation operation) { + RequestBody requestBody = operation.getRequestBody(); + if (requestBody == null) return new ArrayList<>(); + Content content = requestBody.getContent(); + return content != null ? new ArrayList<>(content.keySet()) : new ArrayList<>(); + } + + private static Schema getRequestSchema(Operation operation) { + RequestBody requestBody = operation.getRequestBody(); + if (requestBody == null) return null; + Content content = requestBody.getContent(); + if (content == null || content.isEmpty()) return null; + MediaType mediaType = content.get("application/json"); + if (mediaType == null) mediaType = content.values().iterator().next(); + return mediaType != null ? mediaType.getSchema() : null; } - private static List convert2EndpointList(Map map) { - List endpoints = new ArrayList(); + private static List convert2EndpointList(Map map) { + List endpoints = new ArrayList<>(); if (null == map) return endpoints; - map.forEach((url, path) -> { - Map operationMap = path.getOperationMap(); - operationMap.forEach((httpMethod, operation) -> { + map.forEach((url, pathItem) -> { + Map opMap = pathItem.readOperationsMap(); + if (opMap == null) return; + opMap.forEach((httpMethod, operation) -> { Endpoint endpoint = new Endpoint(); endpoint.setPathUrl(url); endpoint.setMethod(httpMethod); endpoint.setSummary(operation.getSummary()); - endpoint.setPath(path); + endpoint.setPath(pathItem); endpoint.setOperation(operation); endpoints.add(endpoint); }); @@ -145,8 +292,9 @@ private static List convert2EndpointList(Map map) { return endpoints; } - private static Collection convert2EndpointList(String pathUrl, Map map) { - List endpoints = new ArrayList(); + private static Collection convert2EndpointList( + String pathUrl, Map map) { + List endpoints = new ArrayList<>(); if (null == map) return endpoints; map.forEach((httpMethod, operation) -> { Endpoint endpoint = new Endpoint(); @@ -162,22 +310,42 @@ private static Collection convert2EndpointList(String pathUr private static ListDiff getMediaTypeDiff(List oldTypes, List newTypes) { return ListDiff.diff(oldTypes, newTypes, (t, sample) -> { for (String mediaType : t) { - if (sample.equalsIgnoreCase(mediaType)) { return mediaType; } + if (sample.equalsIgnoreCase(mediaType)) return mediaType; } return null; }); } - public List getNewEndpoints() { - return newEndpoints; - } + public List getNewEndpoints() { return newEndpoints; } + public List getMissingEndpoints() { return missingEndpoints; } + public List getChangedEndpoints() { return changedEndpoints; } + - public List getMissingEndpoints() { - return missingEndpoints; + private static List getContentTypes(ApiResponse response) { + if (response == null) return new ArrayList<>(); + Content content = response.getContent(); + return content != null ? new ArrayList<>(content.keySet()) : new ArrayList<>(); } - public List getChangedEndpoints() { - return changedEndpoints; + private static Map getHeaders(ApiResponse response) { + if (response == null || response.getHeaders() == null) return new HashMap<>(); + return response.getHeaders(); } + /** + * Confronto "leggero" di due header: cambio di descrizione, deprecated o tipo schema. + */ + private static boolean isHeaderChanged(Header oldHeader, Header newHeader) { + if (oldHeader == null || newHeader == null) return oldHeader != newHeader; + + if (!java.util.Objects.equals(oldHeader.getDescription(), newHeader.getDescription())) return true; + if (!java.util.Objects.equals(oldHeader.getDeprecated(), newHeader.getDeprecated())) return true; + if (!java.util.Objects.equals(oldHeader.getRequired(), newHeader.getRequired())) return true; + + String oldType = oldHeader.getSchema() != null ? oldHeader.getSchema().getType() : null; + String newType = newHeader.getSchema() != null ? newHeader.getSchema().getType() : null; + if (!java.util.Objects.equals(oldType, newType)) return true; + + return false; + } } diff --git a/src/main/java/com/deepoove/swagger/diff/model/ChangedEndpoint.java b/src/main/java/com/deepoove/swagger/diff/model/ChangedEndpoint.java index 270972b2..77f07cfb 100644 --- a/src/main/java/com/deepoove/swagger/diff/model/ChangedEndpoint.java +++ b/src/main/java/com/deepoove/swagger/diff/model/ChangedEndpoint.java @@ -2,39 +2,39 @@ import java.util.Map; -import io.swagger.models.HttpMethod; -import io.swagger.models.Operation; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; public class ChangedEndpoint implements Changed { private String pathUrl; - private Map newOperations; - private Map missingOperations; + private Map newOperations; + private Map missingOperations; - private Map changedOperations; + private Map changedOperations; - public Map getNewOperations() { + public Map getNewOperations() { return newOperations; } - public void setNewOperations(Map newOperations) { + public void setNewOperations(Map newOperations) { this.newOperations = newOperations; } - public Map getMissingOperations() { + public Map getMissingOperations() { return missingOperations; } - public void setMissingOperations(Map missingOperations) { + public void setMissingOperations(Map missingOperations) { this.missingOperations = missingOperations; } - public Map getChangedOperations() { + public Map getChangedOperations() { return changedOperations; } - public void setChangedOperations(Map changedOperations) { + public void setChangedOperations(Map changedOperations) { this.changedOperations = changedOperations; } @@ -47,9 +47,6 @@ public void setPathUrl(String pathUrl) { } public boolean isDiff() { - // newOperations.isEmpty() - // || !missingOperations.isEmpty() - // || return !changedOperations.isEmpty(); } diff --git a/src/main/java/com/deepoove/swagger/diff/model/ChangedOperation.java b/src/main/java/com/deepoove/swagger/diff/model/ChangedOperation.java index 8703cf5c..6e5a2175 100644 --- a/src/main/java/com/deepoove/swagger/diff/model/ChangedOperation.java +++ b/src/main/java/com/deepoove/swagger/diff/model/ChangedOperation.java @@ -1,40 +1,50 @@ package com.deepoove.swagger.diff.model; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; -import io.swagger.models.parameters.Parameter; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.Operation; + +import io.swagger.v3.oas.models.responses.ApiResponse; public class ChangedOperation implements Changed { private String summary; - private List addParameters = new ArrayList(); - private List missingParameters = new ArrayList(); + private List addParameters = new ArrayList<>(); + private List missingParameters = new ArrayList<>(); + + private List changedParameter = new ArrayList<>(); - private List changedParameter = new ArrayList(); + private List addProps = new ArrayList<>(); + private List missingProps = new ArrayList<>(); + private List changedProps = new ArrayList<>(); + + private List addRequestProps = new ArrayList<>(); + private List missingRequestProps = new ArrayList<>(); + private List changedRequestProps = new ArrayList<>(); - private List addProps = new ArrayList(); - private List missingProps = new ArrayList(); - private List changedProps = new ArrayList(); private List addConsumes = new ArrayList<>(); private List missingConsumes = new ArrayList<>(); private List addProduces = new ArrayList<>(); private List missingProduces = new ArrayList<>(); - public List getAddParameters() { + public List getAddParameters() { return addParameters; } - public void setAddParameters(List addParameters) { + public void setAddParameters(List addParameters) { this.addParameters = addParameters; } - public List getMissingParameters() { + public List getMissingParameters() { return missingParameters; } - public void setMissingParameters(List missingParameters) { + public void setMissingParameters(List missingParameters) { this.missingParameters = missingParameters; } @@ -79,14 +89,20 @@ public void setSummary(String summary) { } public boolean isDiff() { - return !addParameters.isEmpty() || !missingParameters.isEmpty() || !changedParameter.isEmpty() || isDiffProp() - || isDiffConsumes() || isDiffProduces(); + return !addParameters.isEmpty() || !missingParameters.isEmpty() || !changedParameter.isEmpty() + || isDiffProp() || isDiffRequestProp() || isDiffConsumes() || isDiffProduces()|| !addResponses.isEmpty() + || !missingResponses.isEmpty() || !changedResponses.isEmpty(); } + public boolean isDiffProp() { return !addProps.isEmpty() || !missingProps.isEmpty() || !changedProps.isEmpty(); } + public boolean isDiffRequestProp() { + return !addRequestProps.isEmpty() || !missingRequestProps.isEmpty() || !changedRequestProps.isEmpty(); + } + public boolean isDiffParam() { return !addParameters.isEmpty() || !missingParameters.isEmpty() || !changedParameter.isEmpty(); } @@ -130,4 +146,49 @@ public List getMissingProduces() { public void setMissingProduces(List missing) { this.missingProduces = missing == null ? new ArrayList<>() : missing; } -} + + public List getAddRequestProps() { + return addRequestProps; + } + + public void setAddRequestProps(List addRequestProps) { + this.addRequestProps = addRequestProps; + } + + public List getMissingRequestProps() { + return missingRequestProps; + } + + public void setMissingRequestProps(List missingRequestProps) { + this.missingRequestProps = missingRequestProps; + } + + public List getChangedRequestProps() { + return changedRequestProps; + } + + public void setChangedRequestProps(List changedRequestProps) { + this.changedRequestProps = changedRequestProps; + } + + // --- Response diffs per status code --- + private Map addResponses = new LinkedHashMap<>(); + private Map missingResponses = new LinkedHashMap<>(); + // status presenti in entrambi ma con schema cambiato + private List changedResponses = new ArrayList<>(); + + public Map getAddResponses() { return addResponses; } + public void setAddResponses(Map addResponses) { + this.addResponses = addResponses != null ? addResponses : new LinkedHashMap<>(); + } + + public Map getMissingResponses() { return missingResponses; } + public void setMissingResponses(Map missingResponses) { + this.missingResponses = missingResponses != null ? missingResponses : new LinkedHashMap<>(); + } + + public List getChangedResponses() { return changedResponses; } + public void setChangedResponses(List changedResponses) { + this.changedResponses = changedResponses != null ? changedResponses : new ArrayList<>(); + } +} \ No newline at end of file diff --git a/src/main/java/com/deepoove/swagger/diff/model/ChangedParameter.java b/src/main/java/com/deepoove/swagger/diff/model/ChangedParameter.java index 05d24b71..158ced32 100644 --- a/src/main/java/com/deepoove/swagger/diff/model/ChangedParameter.java +++ b/src/main/java/com/deepoove/swagger/diff/model/ChangedParameter.java @@ -3,7 +3,7 @@ import java.util.ArrayList; import java.util.List; -import io.swagger.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.Parameter; public class ChangedParameter implements Changed { @@ -15,7 +15,6 @@ public class ChangedParameter implements Changed { private Parameter rightParameter; private boolean isChangeRequired; - // private boolean isChangeType; private boolean isChangeDescription; public boolean isChangeRequired() { diff --git a/src/main/java/com/deepoove/swagger/diff/model/ChangedResponse.java b/src/main/java/com/deepoove/swagger/diff/model/ChangedResponse.java new file mode 100644 index 00000000..012197e1 --- /dev/null +++ b/src/main/java/com/deepoove/swagger/diff/model/ChangedResponse.java @@ -0,0 +1,109 @@ +package com.deepoove.swagger.diff.model; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import io.swagger.v3.oas.models.headers.Header; + +public class ChangedResponse { + + private String statusCode; + + // --- description --- + private String oldDescription; + private String newDescription; + + // --- schema (proprietà del body) --- + private List addProps = new ArrayList<>(); + private List missingProps = new ArrayList<>(); + private List changedProps = new ArrayList<>(); + + // --- content-type (media types) --- + private List addContentTypes = new ArrayList<>(); + private List missingContentTypes = new ArrayList<>(); + + // --- headers --- + private Map addHeaders = new LinkedHashMap<>(); + private Map missingHeaders = new LinkedHashMap<>(); + private List changedHeaders = new ArrayList<>(); // nomi degli header cambiati + + public String getStatusCode() { return statusCode; } + public void setStatusCode(String statusCode) { this.statusCode = statusCode; } + + // --- description --- + public String getOldDescription() { return oldDescription; } + public void setOldDescription(String oldDescription) { this.oldDescription = oldDescription; } + + public String getNewDescription() { return newDescription; } + public void setNewDescription(String newDescription) { this.newDescription = newDescription; } + + public boolean isDescriptionChanged() { + return !Objects.equals(oldDescription, newDescription); + } + + // --- schema --- + public List getAddProps() { return addProps; } + public void setAddProps(List addProps) { + this.addProps = addProps != null ? addProps : new ArrayList<>(); + } + + public List getMissingProps() { return missingProps; } + public void setMissingProps(List missingProps) { + this.missingProps = missingProps != null ? missingProps : new ArrayList<>(); + } + + public List getChangedProps() { return changedProps; } + public void setChangedProps(List changedProps) { + this.changedProps = changedProps != null ? changedProps : new ArrayList<>(); + } + + public boolean isSchemaChanged() { + return !addProps.isEmpty() || !missingProps.isEmpty() || !changedProps.isEmpty(); + } + + // --- content-type --- + public List getAddContentTypes() { return addContentTypes; } + public void setAddContentTypes(List addContentTypes) { + this.addContentTypes = addContentTypes != null ? addContentTypes : new ArrayList<>(); + } + + public List getMissingContentTypes() { return missingContentTypes; } + public void setMissingContentTypes(List missingContentTypes) { + this.missingContentTypes = missingContentTypes != null ? missingContentTypes : new ArrayList<>(); + } + + public boolean isContentTypeChanged() { + return !addContentTypes.isEmpty() || !missingContentTypes.isEmpty(); + } + + // --- headers --- + public Map getAddHeaders() { return addHeaders; } + public void setAddHeaders(Map addHeaders) { + this.addHeaders = addHeaders != null ? addHeaders : new LinkedHashMap<>(); + } + + public Map getMissingHeaders() { return missingHeaders; } + public void setMissingHeaders(Map missingHeaders) { + this.missingHeaders = missingHeaders != null ? missingHeaders : new LinkedHashMap<>(); + } + + public List getChangedHeaders() { return changedHeaders; } + public void setChangedHeaders(List changedHeaders) { + this.changedHeaders = changedHeaders != null ? changedHeaders : new ArrayList<>(); + } + + public boolean isHeadersChanged() { + return !addHeaders.isEmpty() || !missingHeaders.isEmpty() || !changedHeaders.isEmpty(); + } + + // --- diff globale --- + public boolean isDiff() { + return isDescriptionChanged() + || isSchemaChanged() + || isContentTypeChanged() + || isHeadersChanged(); + } +} \ No newline at end of file diff --git a/src/main/java/com/deepoove/swagger/diff/model/ElProperty.java b/src/main/java/com/deepoove/swagger/diff/model/ElProperty.java index cb2bf282..c736f58f 100644 --- a/src/main/java/com/deepoove/swagger/diff/model/ElProperty.java +++ b/src/main/java/com/deepoove/swagger/diff/model/ElProperty.java @@ -1,10 +1,10 @@ package com.deepoove.swagger.diff.model; -import io.swagger.models.properties.Property; +import io.swagger.v3.oas.models.media.Schema; /** * property with expression Language grammar - * + * * @author Sayi * @version */ @@ -12,18 +12,18 @@ public class ElProperty { private String el; - private Property property; + private Schema property; // optional change metadata private boolean isTypeChange; private boolean newEnums; private boolean removedEnums; - public Property getProperty() { + public Schema getProperty() { return property; } - public void setProperty(Property property) { + public void setProperty(Schema property) { this.property = property; } diff --git a/src/main/java/com/deepoove/swagger/diff/model/Endpoint.java b/src/main/java/com/deepoove/swagger/diff/model/Endpoint.java index 6ea5f205..bd5d90a7 100644 --- a/src/main/java/com/deepoove/swagger/diff/model/Endpoint.java +++ b/src/main/java/com/deepoove/swagger/diff/model/Endpoint.java @@ -1,16 +1,15 @@ package com.deepoove.swagger.diff.model; -import io.swagger.models.HttpMethod; -import io.swagger.models.Operation; -import io.swagger.models.Path; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; public class Endpoint { private String pathUrl; - private HttpMethod method; + private PathItem.HttpMethod method; private String summary; - private Path path; + private PathItem path; private Operation operation; public String getPathUrl() { @@ -21,11 +20,11 @@ public void setPathUrl(String pathUrl) { this.pathUrl = pathUrl; } - public HttpMethod getMethod() { + public PathItem.HttpMethod getMethod() { return method; } - public void setMethod(HttpMethod method) { + public void setMethod(PathItem.HttpMethod method) { this.method = method; } @@ -37,11 +36,11 @@ public void setSummary(String summary) { this.summary = summary; } - public Path getPath() { + public PathItem getPath() { return path; } - public void setPath(Path path) { + public void setPath(PathItem path) { this.path = path; } diff --git a/src/main/java/com/deepoove/swagger/diff/output/HtmlRender.java b/src/main/java/com/deepoove/swagger/diff/output/HtmlRender.java index d7cb699c..8aa04bc8 100644 --- a/src/main/java/com/deepoove/swagger/diff/output/HtmlRender.java +++ b/src/main/java/com/deepoove/swagger/diff/output/HtmlRender.java @@ -2,9 +2,9 @@ import com.deepoove.swagger.diff.SwaggerDiff; import com.deepoove.swagger.diff.model.*; -import io.swagger.models.HttpMethod; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.properties.Property; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; import j2html.tags.ContainerTag; import java.util.ArrayList; @@ -28,7 +28,6 @@ public HtmlRender(String title, String linkCss) { this.linkCss = linkCss; } - public String render(SwaggerDiff diff) { List newEndpoints = diff.getNewEndpoints(); ContainerTag ol_newEndpoint = ol_newEndpoint(newEndpoints); @@ -44,12 +43,13 @@ public String render(SwaggerDiff diff) { return renderHtml(ol_newEndpoint, ol_missingEndpoint, ol_changed, p_versions); } - public String renderHtml(ContainerTag ol_new, ContainerTag ol_miss, ContainerTag ol_changed, ContainerTag p_versions) { + public String renderHtml(ContainerTag ol_new, ContainerTag ol_miss, ContainerTag ol_changed, + ContainerTag p_versions) { ContainerTag html = html().attr("lang", "en").with( head().with( meta().withCharset("utf-8"), title(title), - script(rawHtml("function showHide(id){if(document.getElementById(id).style.display==\'none\'){document.getElementById(id).style.display=\'block\';document.getElementById(\'btn_\'+id).innerHTML=\'⇑\';}else{document.getElementById(id).style.display=\'none\';document.getElementById(\'btn_\'+id).innerHTML=\'⇓\';}return true;}")).withType("text/javascript"), + script(rawHtml("function showHide(id){if(document.getElementById(id).style.display=='none'){document.getElementById(id).style.display='block';document.getElementById('btn_'+id).innerHTML='⇑';}else{document.getElementById(id).style.display='none';document.getElementById('btn_'+id).innerHTML='⇓';}return true;}")).withType("text/javascript"), link().withRel("stylesheet").withHref(linkCss) ), body().with( @@ -62,50 +62,45 @@ public String renderHtml(ContainerTag ol_new, ContainerTag ol_miss, ContainerTag ) ) ); - return document().render() + html.render(); } private ContainerTag div_headArticle(final String title, final String type, final ContainerTag ol) { - return div().with(h2(title).with(a(rawHtml("⇑")).withId("btn_" + type).withClass("showhide").withHref("#").attr("onClick", "javascript:showHide('" + type + "');")), hr(), ol); + return div().with(h2(title).with(a(rawHtml("⇑")).withId("btn_" + type) + .withClass("showhide").withHref("#").attr("onClick", "javascript:showHide('" + type + "')")), + hr(), ol); } private ContainerTag p_versions(String oldVersion, String newVersion) { - ContainerTag p = p().withId("versions"); - p.withText("Changes from " + oldVersion + " to " + newVersion + "."); - return p; + return p().withId("versions").withText("Changes from " + oldVersion + " to " + newVersion + "."); } private ContainerTag ol_newEndpoint(List endpoints) { if (null == endpoints) return ol().withId("new"); ContainerTag ol = ol().withId("new"); for (Endpoint endpoint : endpoints) { - ol.with(li_newEndpoint(endpoint.getMethod().toString(), - endpoint.getPathUrl(), endpoint.getSummary())); + ol.with(li_newEndpoint(endpoint.getMethod().name(), endpoint.getPathUrl(), endpoint.getSummary())); } return ol; } - private ContainerTag li_newEndpoint(String method, String path, - String desc) { - return li().with(span(method).withClass(method)).withText(path + " ") - .with(span(null == desc ? "" : desc)); + private ContainerTag li_newEndpoint(String method, String path, String desc) { + return li().with(span(method).withClass(method.toLowerCase())) + .withText(path + " ").with(span(null == desc ? "" : desc)); } private ContainerTag ol_missingEndpoint(List endpoints) { if (null == endpoints) return ol().withId("deprecated"); ContainerTag ol = ol().withId("deprecated"); for (Endpoint endpoint : endpoints) { - ol.with(li_missingEndpoint(endpoint.getMethod().toString(), - endpoint.getPathUrl(), endpoint.getSummary())); + ol.with(li_missingEndpoint(endpoint.getMethod().name(), endpoint.getPathUrl(), endpoint.getSummary())); } return ol; } - private ContainerTag li_missingEndpoint(String method, String path, - String desc) { - return li().with(span(method).withClass(method), - del().withText(path)).with(span(null == desc ? "" : " " + desc)); + private ContainerTag li_missingEndpoint(String method, String path, String desc) { + return li().with(span(method).withClass(method.toLowerCase()), del().withText(path)) + .with(span(null == desc ? "" : " " + desc)); } private ContainerTag ol_changed(List changedEndpoints) { @@ -113,9 +108,9 @@ private ContainerTag ol_changed(List changedEndpoints) { ContainerTag ol = ol().withId("changed"); for (ChangedEndpoint changedEndpoint : changedEndpoints) { String pathUrl = changedEndpoint.getPathUrl(); - Map changedOperations = changedEndpoint.getChangedOperations(); - for (Entry entry : changedOperations.entrySet()) { - String method = entry.getKey().toString(); + Map changedOperations = changedEndpoint.getChangedOperations(); + for (Entry entry : changedOperations.entrySet()) { + String method = entry.getKey().name(); ChangedOperation changedOperation = entry.getValue(); String desc = changedOperation.getSummary(); @@ -132,56 +127,52 @@ private ContainerTag ol_changed(List changedEndpoints) { if (changedOperation.isDiffConsumes()) { ul_detail.with(li().with(h3("Consumes")).with(ul_consume(changedOperation))); } - ol.with(li().with(span(method).withClass(method)).withText(pathUrl + " ").with(span(null == desc ? "" : desc)) - .with(ul_detail)); + if (isDiffResponses(changedOperation)) { + ul_detail.with(li().with(h3("Responses")).with(ul_responses(changedOperation))); + } + ol.with(li().with(span(method).withClass(method.toLowerCase())) + .withText(pathUrl + " ").with(span(null == desc ? "" : desc)) + .with(ul_detail)); } } return ol; } + @SuppressWarnings("rawtypes") private ContainerTag ul_response(ChangedOperation changedOperation) { List addProps = changedOperation.getAddProps(); List delProps = changedOperation.getMissingProps(); List chgProps = changedOperation.getChangedProps(); ContainerTag ul = ul().withClass("change response"); - for (ElProperty prop : addProps) { - ul.with(li_addProp(prop)); - } - for (ElProperty prop : delProps) { - ul.with(li_missingProp(prop)); - } - for (ElProperty prop : chgProps) { - ul.with(li_changedProp(prop)); - } + for (ElProperty prop : addProps) ul.with(li_addProp(prop)); + for (ElProperty prop : delProps) ul.with(li_missingProp(prop)); + for (ElProperty prop : chgProps) ul.with(li_changedProp(prop)); return ul; } + @SuppressWarnings("rawtypes") private ContainerTag li_missingProp(ElProperty prop) { - Property property = prop.getProperty(); - return li().withClass("missing").withText("Delete").with(del(prop.getEl())).with(span(null == property.getDescription() ? "" : ("//" + property.getDescription())).withClass("comment")); + Schema property = prop.getProperty(); + String desc = property != null ? property.getDescription() : null; + return li().withClass("missing").withText("Delete").with(del(prop.getEl())) + .with(span(null == desc ? "" : ("//" + desc)).withClass("comment")); } + @SuppressWarnings("rawtypes") private ContainerTag li_addProp(ElProperty prop) { - Property property = prop.getProperty(); - return li().withText("Add " + prop.getEl()).with(span(null == property.getDescription() ? "" : ("//" + property.getDescription())).withClass("comment")); + Schema property = prop.getProperty(); + String desc = property != null ? property.getDescription() : null; + return li().withText("Add " + prop.getEl()) + .with(span(null == desc ? "" : ("//" + desc)).withClass("comment")); } private ContainerTag li_changedProp(ElProperty prop) { List changeDetails = new ArrayList<>(); - String changeDetailsHeading = ""; - if (prop.isTypeChange()) { - changeDetails.add("Data Type"); - } - if (prop.isNewEnums()) { - changeDetails.add("Added Enum"); - } - if (prop.isRemovedEnums()) { - changeDetails.add("Removed Enum"); - } - if (! changeDetails.isEmpty()) { - changeDetailsHeading = " (" + String.join(", ", changeDetails) + ")"; - } - return li().withText("Change " + prop.getEl()).with(span(changeDetailsHeading).withClass("comment")); + if (prop.isTypeChange()) changeDetails.add("Data Type"); + if (prop.isNewEnums()) changeDetails.add("Added Enum"); + if (prop.isRemovedEnums()) changeDetails.add("Removed Enum"); + String heading = changeDetails.isEmpty() ? "" : " (" + String.join(", ", changeDetails) + ")"; + return li().withText("Change " + prop.getEl()).with(span(heading).withClass("comment")); } private ContainerTag ul_param(ChangedOperation changedOperation) { @@ -189,85 +180,59 @@ private ContainerTag ul_param(ChangedOperation changedOperation) { List delParameters = changedOperation.getMissingParameters(); List changedParameters = changedOperation.getChangedParameter(); ContainerTag ul = ul().withClass("change param"); - for (Parameter param : addParameters) { - ul.with(li_addParam(param)); - } + for (Parameter param : addParameters) ul.with(li_addParam(param)); for (ChangedParameter param : changedParameters) { - List increased = param.getIncreased(); - for (ElProperty prop : increased) { - ul.with(li_addProp(prop)); - } + for (ElProperty prop : param.getIncreased()) ul.with(li_addProp(prop)); } for (ChangedParameter param : changedParameters) { - boolean changeRequired = param.isChangeRequired(); - boolean changeDescription = param.isChangeDescription(); - if (changeRequired || changeDescription) - ul.with(li_changedParam(param)); + if (param.isChangeRequired() || param.isChangeDescription()) ul.with(li_changedParam(param)); } for (ChangedParameter param : changedParameters) { - List missing = param.getMissing(); - for (ElProperty prop : missing) { - ul.with(li_missingProp(prop)); - } - } - for (ChangedParameter param : changedParameters) { - List changed = param.getChanged(); - for (ElProperty prop : changed) { - ul.with(li_changedProp(prop)); - } - } - for (Parameter param : delParameters) { - ul.with(li_missingParam(param)); + for (ElProperty prop : param.getMissing()) ul.with(li_missingProp(prop)); + for (ElProperty prop : param.getChanged()) ul.with(li_changedProp(prop)); } + for (Parameter param : delParameters) ul.with(li_missingParam(param)); return ul; } private ContainerTag li_addParam(Parameter param) { - return li().withText("Add " + param.getName()).with(span(null == param.getDescription() ? "" : ("//" + param.getDescription())).withClass("comment")); + return li().withText("Add " + param.getName()) + .with(span(null == param.getDescription() ? "" : ("//" + param.getDescription())).withClass("comment")); } private ContainerTag li_missingParam(Parameter param) { - return li().withClass("missing").with(span("Delete")).with(del(param.getName())).with(span(null == param.getDescription() ? "" : ("//" + param.getDescription())).withClass("comment")); + return li().withClass("missing").with(span("Delete")).with(del(param.getName())) + .with(span(null == param.getDescription() ? "" : ("//" + param.getDescription())).withClass("comment")); } private ContainerTag li_changedParam(ChangedParameter changeParam) { - boolean changeRequired = changeParam.isChangeRequired(); - boolean changeDescription = changeParam.isChangeDescription(); Parameter rightParam = changeParam.getRightParameter(); Parameter leftParam = changeParam.getLeftParameter(); ContainerTag li = li().withText(rightParam.getName()); - if (changeRequired) { - li.withText(" change into " + (rightParam.getRequired() ? "required" : "not required")); + if (changeParam.isChangeRequired()) { + boolean required = Boolean.TRUE.equals(rightParam.getRequired()); + li.withText(" change into " + (required ? "required" : "not required")); } - if (changeDescription) { - li.withText(" Notes ").with(del(leftParam.getDescription()).withClass("comment")).withText(" change into ").with(span(span(null == rightParam.getDescription() ? "" : rightParam.getDescription()).withClass("comment"))); + if (changeParam.isChangeDescription()) { + li.withText(" Notes ") + .with(del(leftParam.getDescription()).withClass("comment")) + .withText(" change into ") + .with(span(span(null == rightParam.getDescription() ? "" : rightParam.getDescription()).withClass("comment"))); } return li; } private ContainerTag ul_produce(ChangedOperation changedOperation) { - List addProduce = changedOperation.getAddProduces(); - List delProduce = changedOperation.getMissingProduces(); ContainerTag ul = ul().withClass("change produces"); - for (String mt : addProduce) { - ul.with(li_addMediaType(mt)); - } - for (String mt : delProduce) { - ul.with(li_missingMediaType(mt)); - } + for (String mt : changedOperation.getAddProduces()) ul.with(li_addMediaType(mt)); + for (String mt : changedOperation.getMissingProduces()) ul.with(li_missingMediaType(mt)); return ul; } private ContainerTag ul_consume(ChangedOperation changedOperation) { - List addConsume = changedOperation.getAddConsumes(); - List delConsume = changedOperation.getMissingConsumes(); ContainerTag ul = ul().withClass("change consumes"); - for (String mt : addConsume) { - ul.with(li_addMediaType(mt)); - } - for (String mt : delConsume) { - ul.with(li_missingMediaType(mt)); - } + for (String mt : changedOperation.getAddConsumes()) ul.with(li_addMediaType(mt)); + for (String mt : changedOperation.getMissingConsumes()) ul.with(li_missingMediaType(mt)); return ul; } @@ -278,4 +243,57 @@ private ContainerTag li_missingMediaType(String type) { private ContainerTag li_addMediaType(String type) { return li().withText("Add " + type).with(span("")); } + + private boolean isDiffResponses(ChangedOperation op) { + return !op.getAddResponses().isEmpty() + || !op.getMissingResponses().isEmpty() + || !op.getChangedResponses().isEmpty(); +} + + @SuppressWarnings("rawtypes") + private ContainerTag ul_responses(ChangedOperation op) { + ContainerTag ul = ul().withClass("change responses"); + + // status aggiunti + for (Map.Entry e : op.getAddResponses().entrySet()) { + String desc = e.getValue() != null ? e.getValue().getDescription() : null; + ul.with(li().withText("Add response " + e.getKey()) + .with(span(null == desc ? "" : "//" + desc).withClass("comment"))); + } + + // status rimossi + for (Map.Entry e : op.getMissingResponses().entrySet()) { + String desc = e.getValue() != null ? e.getValue().getDescription() : null; + ul.with(li().withClass("missing").withText("Delete response ").with(del(e.getKey())) + .with(span(null == desc ? "" : "//" + desc).withClass("comment"))); + } + + // status modificati + for (ChangedResponse cr : op.getChangedResponses()) { + ContainerTag sub = ul().withClass("change response-detail"); + + if (cr.isDescriptionChanged()) { + sub.with(li().withText("Description ") + .with(del(cr.getOldDescription() == null ? "" : cr.getOldDescription()).withClass("comment")) + .withText(" change into ") + .with(span(cr.getNewDescription() == null ? "" : cr.getNewDescription()).withClass("comment"))); + } + for (ElProperty p : cr.getAddProps()) sub.with(li_addProp(p)); + for (ElProperty p : cr.getMissingProps()) sub.with(li_missingProp(p)); + for (ElProperty p : cr.getChangedProps()) sub.with(li_changedProp(p)); + + for (String ct : cr.getAddContentTypes()) sub.with(li().withText("Add content-type " + ct)); + for (String ct : cr.getMissingContentTypes()) + sub.with(li().withClass("missing").withText("Delete content-type ").with(del(ct))); + + for (String h : cr.getAddHeaders().keySet()) sub.with(li().withText("Add header " + h)); + for (String h : cr.getMissingHeaders().keySet()) + sub.with(li().withClass("missing").withText("Delete header ").with(del(h))); + for (String h : cr.getChangedHeaders()) sub.with(li().withText("Change header " + h)); + + ul.with(li().withText("Response " + cr.getStatusCode()).with(sub)); + } + + return ul; + } } diff --git a/src/main/java/com/deepoove/swagger/diff/output/MarkdownRender.java b/src/main/java/com/deepoove/swagger/diff/output/MarkdownRender.java index 975e3bea..d1208a3f 100644 --- a/src/main/java/com/deepoove/swagger/diff/output/MarkdownRender.java +++ b/src/main/java/com/deepoove/swagger/diff/output/MarkdownRender.java @@ -7,9 +7,9 @@ import com.deepoove.swagger.diff.SwaggerDiff; import com.deepoove.swagger.diff.model.*; -import io.swagger.models.HttpMethod; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.properties.Property; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; public class MarkdownRender implements Render { @@ -25,259 +25,216 @@ public class MarkdownRender implements Render { public MarkdownRender() {} public String render(SwaggerDiff diff) { - List newEndpoints = diff.getNewEndpoints(); - String ol_newEndpoint = ol_newEndpoint(newEndpoints); - - List missingEndpoints = diff.getMissingEndpoints(); - String ol_missingEndpoint = ol_missingEndpoint(missingEndpoints); - - List changedEndpoints = diff.getChangedEndpoints(); - String ol_changed = ol_changed(changedEndpoints); - - return renderHtml(diff.getOldVersion(), diff.getNewVersion(), ol_newEndpoint, ol_missingEndpoint, ol_changed); + String ol_new = ol_newEndpoint(diff.getNewEndpoints()); + String ol_miss = ol_missingEndpoint(diff.getMissingEndpoints()); + String ol_changed = ol_changed(diff.getChangedEndpoints()); + return renderHtml(diff.getOldVersion(), diff.getNewVersion(), ol_new, ol_miss, ol_changed); } - public String renderHtml(String oldVersion, String newVersion, String ol_new, String ol_miss, - String ol_changed) { - StringBuffer sb = new StringBuffer(); - sb.append(H2).append("Version " + oldVersion + " to " + newVersion).append("\n").append(HR); - sb.append(H3).append("What's New").append("\n").append(HR) - .append(ol_new).append("\n").append(H3) - .append("What's Deprecated").append("\n").append(HR) - .append(ol_miss).append("\n").append(H3) - .append("What's Changed").append("\n").append(HR) - .append(ol_changed); - return sb.toString(); + public String renderHtml(String oldVersion, String newVersion, String ol_new, + String ol_miss, String ol_changed) { + return new StringBuilder() + .append(H2).append("Version ").append(oldVersion).append(" to ").append(newVersion).append("\n").append(HR) + .append(H3).append("What's New").append("\n").append(HR).append(ol_new).append("\n") + .append(H3).append("What's Deprecated").append("\n").append(HR).append(ol_miss).append("\n") + .append(H3).append("What's Changed").append("\n").append(HR).append(ol_changed) + .toString(); } private String ol_newEndpoint(List endpoints) { if (null == endpoints) return ""; - StringBuffer sb = new StringBuffer(); - for (Endpoint endpoint : endpoints) { - sb.append(li_newEndpoint(endpoint.getMethod().toString(), - endpoint.getPathUrl(), endpoint.getSummary())); + StringBuilder sb = new StringBuilder(); + for (Endpoint e : endpoints) { + sb.append(li_newEndpoint(e.getMethod().name(), e.getPathUrl(), e.getSummary())); } return sb.toString(); } private String li_newEndpoint(String method, String path, String desc) { - StringBuffer sb = new StringBuffer(); - sb.append(LI).append(CODE).append(method).append(CODE) - .append(" " + path).append(" " + desc + "\n"); - return sb.toString(); + return LI + CODE + method + CODE + " " + path + " " + (desc != null ? desc : "") + "\n"; } private String ol_missingEndpoint(List endpoints) { if (null == endpoints) return ""; - StringBuffer sb = new StringBuffer(); - for (Endpoint endpoint : endpoints) { - sb.append(li_newEndpoint(endpoint.getMethod().toString(), - endpoint.getPathUrl(), endpoint.getSummary())); + StringBuilder sb = new StringBuilder(); + for (Endpoint e : endpoints) { + sb.append(li_newEndpoint(e.getMethod().name(), e.getPathUrl(), e.getSummary())); } return sb.toString(); } private String ol_changed(List changedEndpoints) { if (null == changedEndpoints) return ""; - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); for (ChangedEndpoint changedEndpoint : changedEndpoints) { String pathUrl = changedEndpoint.getPathUrl(); - Map changedOperations = changedEndpoint - .getChangedOperations(); - for (Entry entry : changedOperations - .entrySet()) { - String method = entry.getKey().toString(); - ChangedOperation changedOperation = entry.getValue(); - String desc = changedOperation.getSummary(); - - StringBuffer ul_detail = new StringBuffer(); - if (changedOperation.isDiffParam()) { - ul_detail.append(PRE_LI).append("Parameters") - .append(ul_param(changedOperation)); - } - if (changedOperation.isDiffProp()) { - ul_detail.append(PRE_LI).append("Return Type") - .append(ul_response(changedOperation)); - } - if (changedOperation.isDiffProduces()) { - ul_detail.append(PRE_LI).append("Produces") - .append(ul_produce(changedOperation)); - } - if (changedOperation.isDiffConsumes()) { - ul_detail.append(PRE_LI).append("Consumes") - .append(ul_consume(changedOperation)); - } - sb.append(CODE).append(method).append(CODE) - .append(" " + pathUrl).append(" " + desc + " \n") - .append(ul_detail); + Map changedOps = changedEndpoint.getChangedOperations(); + for (Entry entry : changedOps.entrySet()) { + String method = entry.getKey().name(); + ChangedOperation op = entry.getValue(); + StringBuilder detail = new StringBuilder(); + if (op.isDiffParam()) detail.append(PRE_LI).append("Parameters").append(ul_param(op)); + if (op.isDiffProp()) detail.append(PRE_LI).append("Return Type").append(ul_response(op)); + if (op.isDiffProduces()) detail.append(PRE_LI).append("Produces").append(ul_produce(op)); + if (op.isDiffConsumes()) detail.append(PRE_LI).append("Consumes").append(ul_consume(op)); + if (isDiffResponses(op)) detail.append(PRE_LI).append("Responses").append(ul_responses(op)); + sb.append(CODE).append(method).append(CODE).append(" ").append(pathUrl) + .append(" ").append(op.getSummary() != null ? op.getSummary() : "").append(" \n") + .append(detail); } } return sb.toString(); } - private String ul_response(ChangedOperation changedOperation) { - List addProps = changedOperation.getAddProps(); - List delProps = changedOperation.getMissingProps(); - List changedProps = changedOperation.getChangedProps(); - StringBuffer sb = new StringBuffer("\n\n"); - - String prefix = PRE_LI + PRE_CODE; - for (ElProperty prop : addProps) { - sb.append(PRE_LI).append(PRE_CODE).append(li_addProp(prop) + "\n"); - } - for (ElProperty prop : delProps) { - sb.append(prefix).append(li_missingProp(prop) + "\n"); - } - for (ElProperty prop : changedProps) { - sb.append(prefix).append(li_changedProp(prop) + "\n"); - } + @SuppressWarnings("rawtypes") + private String ul_response(ChangedOperation op) { + StringBuilder sb = new StringBuilder("\n\n"); + for (ElProperty p : op.getAddProps()) sb.append(PRE_LI).append(PRE_CODE).append(li_addProp(p)).append("\n"); + for (ElProperty p : op.getMissingProps()) sb.append(PRE_LI).append(PRE_CODE).append(li_missingProp(p)).append("\n"); + for (ElProperty p : op.getChangedProps()) sb.append(PRE_LI).append(PRE_CODE).append(li_changedProp(p)).append("\n"); return sb.toString(); } + @SuppressWarnings("rawtypes") private String li_missingProp(ElProperty prop) { - Property property = prop.getProperty(); - StringBuffer sb = new StringBuffer(""); - sb.append("Delete ").append(prop.getEl()) - .append(null == property.getDescription() ? "" - : (" //" + property.getDescription())); - return sb.toString(); + Schema schema = prop.getProperty(); + String desc = schema != null ? schema.getDescription() : null; + return "Delete " + prop.getEl() + (null == desc ? "" : " //" + desc); } + @SuppressWarnings("rawtypes") private String li_addProp(ElProperty prop) { - Property property = prop.getProperty(); - StringBuffer sb = new StringBuffer(""); - sb.append("Insert ").append(prop.getEl()) - .append(null == property.getDescription() ? "" - : (" //" + property.getDescription())); - return sb.toString(); + Schema schema = prop.getProperty(); + String desc = schema != null ? schema.getDescription() : null; + return "Insert " + prop.getEl() + (null == desc ? "" : " //" + desc); } + @SuppressWarnings("rawtypes") private String li_changedProp(ElProperty prop) { - Property property = prop.getProperty(); - String prefix = "Modify "; - String desc = " //" + property.getDescription(); - String postfix = (null == property.getDescription() ? "" : desc); - - StringBuffer sb = new StringBuffer(""); - sb.append(prefix).append(prop.getEl()) - .append(postfix); - return sb.toString(); + Schema schema = prop.getProperty(); + String desc = schema != null ? schema.getDescription() : null; + return "Modify " + prop.getEl() + (null == desc ? "" : " //" + desc); } - private String ul_param(ChangedOperation changedOperation) { - List addParameters = changedOperation.getAddParameters(); - List delParameters = changedOperation.getMissingParameters(); - List changedParameters = changedOperation - .getChangedParameter(); - StringBuffer sb = new StringBuffer("\n\n"); - for (Parameter param : addParameters) { - sb.append(PRE_LI).append(PRE_CODE) - .append(li_addParam(param) + "\n"); + private String ul_param(ChangedOperation op) { + StringBuilder sb = new StringBuilder("\n\n"); + for (Parameter p : op.getAddParameters()) sb.append(PRE_LI).append(PRE_CODE).append(li_addParam(p)).append("\n"); + for (ChangedParameter cp : op.getChangedParameter()) { + for (ElProperty prop : cp.getIncreased()) sb.append(PRE_LI).append(PRE_CODE).append(li_addProp(prop)).append("\n"); } - for (ChangedParameter param : changedParameters) { - List increased = param.getIncreased(); - for (ElProperty prop : increased) { - sb.append(PRE_LI).append(PRE_CODE) - .append(li_addProp(prop) + "\n"); + for (ChangedParameter cp : op.getChangedParameter()) { + if (cp.isChangeRequired() || cp.isChangeDescription()) { + sb.append(PRE_LI).append(PRE_CODE).append(li_changedParam(cp)).append("\n"); } } - for (ChangedParameter param : changedParameters) { - boolean changeRequired = param.isChangeRequired(); - boolean changeDescription = param.isChangeDescription(); - if (changeRequired || changeDescription) sb.append(PRE_LI) - .append(PRE_CODE).append(li_changedParam(param) + "\n"); - } - for (ChangedParameter param : changedParameters) { - List missing = param.getMissing(); - List changed = param.getChanged(); - for (ElProperty prop : missing) { - sb.append(PRE_LI).append(PRE_CODE) - .append(li_missingProp(prop) + "\n"); - } - for (ElProperty prop : changed) { - sb.append(PRE_LI).append(PRE_CODE) - .append(li_changedProp(prop) + "\n"); - } - } - for (Parameter param : delParameters) { - sb.append(PRE_LI).append(PRE_CODE) - .append(li_missingParam(param) + "\n"); + for (ChangedParameter cp : op.getChangedParameter()) { + for (ElProperty prop : cp.getMissing()) sb.append(PRE_LI).append(PRE_CODE).append(li_missingProp(prop)).append("\n"); + for (ElProperty prop : cp.getChanged()) sb.append(PRE_LI).append(PRE_CODE).append(li_changedProp(prop)).append("\n"); } + for (Parameter p : op.getMissingParameters()) sb.append(PRE_LI).append(PRE_CODE).append(li_missingParam(p)).append("\n"); return sb.toString(); } private String li_addParam(Parameter param) { - StringBuffer sb = new StringBuffer(""); - sb.append("Add ").append(param.getName()) - .append(null == param.getDescription() ? "" - : (" //" + param.getDescription())); - return sb.toString(); + return "Add " + param.getName() + (null == param.getDescription() ? "" : " //" + param.getDescription()); } private String li_missingParam(Parameter param) { - StringBuffer sb = new StringBuffer(""); - sb.append("Delete ").append(param.getName()) - .append(null == param.getDescription() ? "" - : (" //" + param.getDescription())); - return sb.toString(); + return "Delete " + param.getName() + (null == param.getDescription() ? "" : " //" + param.getDescription()); } - private String li_changedParam(ChangedParameter changeParam) { - boolean changeRequired = changeParam.isChangeRequired(); - boolean changeDescription = changeParam.isChangeDescription(); - Parameter rightParam = changeParam.getRightParameter(); - Parameter leftParam = changeParam.getLeftParameter(); - StringBuffer sb = new StringBuffer(""); - sb.append(rightParam.getName()); - if (changeRequired) { - sb.append(" change into " + (rightParam.getRequired() ? "required" : "not required")); + private String li_changedParam(ChangedParameter cp) { + Parameter right = cp.getRightParameter(); + Parameter left = cp.getLeftParameter(); + StringBuilder sb = new StringBuilder(right.getName()); + if (cp.isChangeRequired()) { + sb.append(" change into ").append(Boolean.TRUE.equals(right.getRequired()) ? "required" : "not required"); } - if (changeDescription) { - sb.append(" Notes ").append(leftParam.getDescription()).append(" change into ") - .append(rightParam.getDescription()); + if (cp.isChangeDescription()) { + sb.append(" Notes ").append(left.getDescription()).append(" change into ").append(right.getDescription()); } return sb.toString(); } - private String ul_produce(ChangedOperation changedOperation) { - List addProduce = changedOperation.getAddProduces(); - List delProduce = changedOperation.getMissingProduces(); - StringBuffer sb = new StringBuffer("\n\n"); + private String ul_produce(ChangedOperation op) { + StringBuilder sb = new StringBuilder("\n\n"); + for (String mt : op.getAddProduces()) sb.append(PRE_LI).append(PRE_CODE).append("Insert ").append(mt).append("\n"); + for (String mt : op.getMissingProduces()) sb.append(PRE_LI).append(PRE_CODE).append("Delete ").append(mt).append("\n"); + return sb.toString(); + } - String prefix = PRE_LI + PRE_CODE; - for (String mt : addProduce) { - sb.append(PRE_LI).append(PRE_CODE).append(li_addMediaType(mt) + "\n"); - } - for (String mt : delProduce) { - sb.append(prefix).append(li_missingMediaType(mt) + "\n"); - } + private String ul_consume(ChangedOperation op) { + StringBuilder sb = new StringBuilder("\n\n"); + for (String mt : op.getAddConsumes()) sb.append(PRE_LI).append(PRE_CODE).append("Insert ").append(mt).append("\n"); + for (String mt : op.getMissingConsumes()) sb.append(PRE_LI).append(PRE_CODE).append("Delete ").append(mt).append("\n"); return sb.toString(); } - private String ul_consume(ChangedOperation changedOperation) { - List addConsume = changedOperation.getAddConsumes(); - List delConsume = changedOperation.getMissingConsumes(); - StringBuffer sb = new StringBuffer("\n\n"); + private boolean isDiffResponses(ChangedOperation op) { + return !op.getAddResponses().isEmpty() + || !op.getMissingResponses().isEmpty() + || !op.getChangedResponses().isEmpty(); + } + + private String ul_responses(ChangedOperation op) { + StringBuilder sb = new StringBuilder("\n\n"); - String prefix = PRE_LI + PRE_CODE; - for (String mt : addConsume) { - sb.append(PRE_LI).append(PRE_CODE).append(li_addMediaType(mt) + "\n"); + // status aggiunti + for (Map.Entry e : op.getAddResponses().entrySet()) { + String desc = e.getValue() != null ? e.getValue().getDescription() : null; + sb.append(PRE_LI).append(PRE_CODE) + .append("Insert response ").append(e.getKey()) + .append(null == desc ? "" : " //" + desc) + .append("\n"); } - for (String mt : delConsume) { - sb.append(prefix).append(li_missingMediaType(mt) + "\n"); + + // status rimossi + for (Map.Entry e : op.getMissingResponses().entrySet()) { + String desc = e.getValue() != null ? e.getValue().getDescription() : null; + sb.append(PRE_LI).append(PRE_CODE) + .append("Delete response ").append(e.getKey()) + .append(null == desc ? "" : " //" + desc) + .append("\n"); } - return sb.toString(); - } - private String li_missingMediaType(String type) { - StringBuffer sb = new StringBuffer(""); - sb.append("Delete ").append(type); - return sb.toString(); - } + // status modificati + for (ChangedResponse cr : op.getChangedResponses()) { + sb.append(PRE_LI).append(PRE_CODE) + .append("Modify response ").append(cr.getStatusCode()).append("\n"); + + // description + if (cr.isDescriptionChanged()) { + sb.append(PRE_LI).append(PRE_CODE).append(PRE_CODE) + .append("Description ") + .append(cr.getOldDescription() != null ? cr.getOldDescription() : "") + .append(" change into ") + .append(cr.getNewDescription() != null ? cr.getNewDescription() : "") + .append("\n"); + } + + // schema (proprietà) + for (ElProperty p : cr.getAddProps()) + sb.append(PRE_LI).append(PRE_CODE).append(PRE_CODE).append(li_addProp(p)).append("\n"); + for (ElProperty p : cr.getMissingProps()) + sb.append(PRE_LI).append(PRE_CODE).append(PRE_CODE).append(li_missingProp(p)).append("\n"); + for (ElProperty p : cr.getChangedProps()) + sb.append(PRE_LI).append(PRE_CODE).append(PRE_CODE).append(li_changedProp(p)).append("\n"); + + // content-type + for (String ct : cr.getAddContentTypes()) + sb.append(PRE_LI).append(PRE_CODE).append(PRE_CODE).append("Insert content-type ").append(ct).append("\n"); + for (String ct : cr.getMissingContentTypes()) + sb.append(PRE_LI).append(PRE_CODE).append(PRE_CODE).append("Delete content-type ").append(ct).append("\n"); + + // headers + for (String h : cr.getAddHeaders().keySet()) + sb.append(PRE_LI).append(PRE_CODE).append(PRE_CODE).append("Insert header ").append(h).append("\n"); + for (String h : cr.getMissingHeaders().keySet()) + sb.append(PRE_LI).append(PRE_CODE).append(PRE_CODE).append("Delete header ").append(h).append("\n"); + for (String h : cr.getChangedHeaders()) + sb.append(PRE_LI).append(PRE_CODE).append(PRE_CODE).append("Modify header ").append(h).append("\n"); + } - private String li_addMediaType(String type) { - StringBuffer sb = new StringBuffer(""); - sb.append("Insert ").append(type); return sb.toString(); } } diff --git a/src/test/.DS_Store b/src/test/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..53fb051541bba9bee2ee9b7c7c1e1cf7111a9512 GIT binary patch literal 6148 zcmeHKI}XAy47Gs)#KOp!D{zAd!3nqkg0dl10Responses")); + + // status aggiunti (201 e 400 nei tuoi dati) + Assert.assertTrue("manca 201 aggiunto", html.contains("Add response 201")); + Assert.assertTrue("manca 400 aggiunto", html.contains("Add response 400")); + + // status rimosso (404) + Assert.assertTrue("manca 404 rimosso", + html.contains("Delete response") && html.contains("404")); + + // status 200 modificato (description cambiata ok -> update Success) + Assert.assertTrue("manca riferimento al Response 200", html.contains("Response 200")); + } + } diff --git a/src/test/java/com/deepoove/swagger/test/SwaggerDiffTest.java b/src/test/java/com/deepoove/swagger/test/SwaggerDiffTest.java index 6405ab59..59f956a0 100644 --- a/src/test/java/com/deepoove/swagger/test/SwaggerDiffTest.java +++ b/src/test/java/com/deepoove/swagger/test/SwaggerDiffTest.java @@ -8,14 +8,17 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Lists; -import io.swagger.models.HttpMethod; -import io.swagger.models.parameters.BodyParameter; +import io.swagger.v3.oas.models.PathItem.HttpMethod; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.parameters.Parameter; import org.junit.Assert; import org.junit.Test; import java.io.*; +import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -27,6 +30,14 @@ public class SwaggerDiffTest { final String SWAGGER_V2_EMPTY_DOC = "petstore_v2_empty.json"; final String SWAGGER_V2_HTTP = "http://petstore.swagger.io/v2/swagger.json"; + final String SWAGGER_V3_EMPTY_DOC = "petstore_v3_empty.json"; + + @Test + public void testEqualV3() { + SwaggerDiff diff = SwaggerDiff.compareV3(SWAGGER_V3_EMPTY_DOC, SWAGGER_V3_EMPTY_DOC); + assertEqual(diff); + } + @Test public void testEqual() { SwaggerDiff diff = SwaggerDiff.compareV2(SWAGGER_V2_DOC2, SWAGGER_V2_DOC2); @@ -160,7 +171,7 @@ public void testEqualJson() { try { InputStream inputStream = getClass().getClassLoader().getResourceAsStream(SWAGGER_V2_DOC1); JsonNode json = new ObjectMapper().readTree(inputStream); - SwaggerDiff diff = SwaggerDiff.compareV2(json, json); + SwaggerDiff diff = SwaggerDiff.compareRaw(json.toString(), json.toString()); assertEqual(diff); } catch (IOException e) { e.printStackTrace(); @@ -205,20 +216,18 @@ public void testInputBodyArray() { Assert.assertTrue("Expecting POST method change", endpoint.getChangedOperations().containsKey(HttpMethod.POST)); Assert.assertEquals(0, endpoint.getChangedOperations().get(HttpMethod.POST).getMissingParameters().size()); Assert.assertEquals(0, endpoint.getChangedOperations().get(HttpMethod.POST).getAddParameters().size()); - Assert.assertEquals(1, endpoint.getChangedOperations().get(HttpMethod.POST).getChangedParameter().size()); + Assert.assertEquals(0, endpoint.getChangedOperations().get(io.swagger.v3.oas.models.PathItem.HttpMethod.POST).getChangedParameter().size()); // assert changed property counts - ChangedParameter changedInput = endpoint.getChangedOperations().get(HttpMethod.POST).getChangedParameter().get(0); - Assert.assertTrue(changedInput.getLeftParameter() instanceof BodyParameter); - Assert.assertTrue(changedInput.getRightParameter() instanceof BodyParameter); - Assert.assertEquals(3, changedInput.getIncreased().size()); - Assert.assertEquals(3, changedInput.getMissing().size()); - Assert.assertEquals(1, changedInput.getChanged().size()); + ChangedOperation changedOp = endpoint.getChangedOperations().get(io.swagger.v3.oas.models.PathItem.HttpMethod.POST); + Assert.assertEquals(3, changedOp.getAddRequestProps().size()); + Assert.assertEquals(3, changedOp.getMissingRequestProps().size()); + Assert.assertEquals(0, changedOp.getChangedRequestProps().size()); // assert embedded array change is one of the missing properties - List missingProperties = changedInput.getMissing(); + List missingProperties = changedOp.getMissingRequestProps(); Set elementPaths = missingProperties.stream().map(ElProperty::getEl).collect(Collectors.toSet()); - Assert.assertTrue(elementPaths.contains("body.favorite.tags.removedField")); + Assert.assertTrue(elementPaths.contains("favorite.tags.removedField") || elementPaths.contains("body.favorite.tags.removedField")); }); } @@ -236,7 +245,7 @@ public void testResponseBodyArray() { ChangedOperation changedOutput = endpoint.getChangedOperations().get(HttpMethod.GET); Assert.assertEquals(3, changedOutput.getAddProps().size()); Assert.assertEquals(3, changedOutput.getMissingProps().size()); - Assert.assertEquals(1, changedOutput.getChangedProps().size()); + Assert.assertEquals(0, changedOutput.getChangedProps().size()); // assert embedded array change is one of the missing properties List missingProperties =changedOutput.getMissingProps(); @@ -269,17 +278,15 @@ public void testChangedPropertyMetadata() { Assert.assertTrue("Expecting changed endpoint " + postOrder, changedEndpointMap.containsKey(postOrder)); ChangedEndpoint postOrderChg = changedEndpointMap.get(postOrder); ChangedOperation postOrderChgOp = postOrderChg.getChangedOperations().get(HttpMethod.POST); - Assert.assertEquals(1, postOrderChgOp.getChangedParameter().size()); - - List postChgProps = postOrderChgOp.getChangedParameter().get(0).getChanged(); + List postChgProps = postOrderChgOp.getChangedRequestProps(); Assert.assertEquals(2, postChgProps.size()); ElProperty orderIdProp = postChgProps.stream().filter(cp -> { - return cp.getEl().equalsIgnoreCase("body.id");}).findFirst().get(); + return cp.getEl().equalsIgnoreCase("body.id") || cp.getEl().equalsIgnoreCase("id");}).findFirst().get(); Assert.assertTrue(orderIdProp.isTypeChange()); Assert.assertFalse(orderIdProp.isNewEnums()); Assert.assertFalse(orderIdProp.isRemovedEnums()); ElProperty statusProp = postChgProps.stream().filter(cp -> { - return cp.getEl().equalsIgnoreCase("body.status");}).findFirst().get(); + return cp.getEl().equalsIgnoreCase("body.status") || cp.getEl().equalsIgnoreCase("status");}).findFirst().get(); Assert.assertFalse(statusProp.isTypeChange()); Assert.assertTrue(statusProp.isNewEnums()); Assert.assertTrue(statusProp.isRemovedEnums()); @@ -312,5 +319,144 @@ private void assertEqual(SwaggerDiff diff) { Assert.assertTrue(changedEndPoints.isEmpty()); } + @Test + public void x() { + SwaggerDiff diff = SwaggerDiff.compareV3( + "src/test/resources/petstore_v3_diff1.json", + "src/test/resources/petstore_v3_diff2.json" + ); + + List changedEndpoints = diff.getChangedEndpoints(); + for(int i=0;i age = changedPostOp.getAddRequestProps().stream() + .filter(p -> "age".equals(p.getEl())).findFirst(); + + Assert.assertTrue("age property should be added", age.isPresent()); + Assert.assertTrue("age property should be added", age.get().getProperty().getDescription().equals("age of item")); + Assert.assertTrue("age property should be added", age.get().getProperty().getType().equals("integer")); + + // an old property oldName is removed + Assert.assertEquals(1, changedPostOp.getMissingRequestProps().size()); + Optional oldName = changedPostOp.getMissingRequestProps().stream() + .filter(p -> "oldName".equals(p.getEl())).findFirst(); + Assert.assertTrue("oldName property should be removed", oldName.isPresent()); + Assert.assertTrue("oldName property should be removed as deprecated", oldName.get().getProperty().getDeprecated()); + Assert.assertTrue("oldName property should be removed as type integer", oldName.get().getProperty().getType().equals("string")); + + + // GET: + // a new query parameter "type" is added + Operation getOp = + ce.getNewOperations().get(HttpMethod.GET); + + Assert.assertEquals(2, getOp.getParameters().size()); + + //check type parameter + Optional parameter = getOp.getParameters().stream() + .filter(p -> "type".equals(p.getName())).findFirst(); + + Assert.assertTrue("type query parameter should be added", parameter.isPresent()); + Assert.assertTrue("type query parameter should be added", parameter.get().getName().equals("type")); + Assert.assertTrue("type query parameter should be added", parameter.get().getIn().equals("query")); + Assert.assertTrue("type query parameter should be added", parameter.get().getSchema().getType().equals("string")); + Assert.assertTrue("type query parameter should be added", parameter.get().getSchema().getDescription().equals("the type of the item")); + + //check size parameter + Optional parameter2 = getOp.getParameters().stream() + .filter(p -> "size".equals(p.getName())).findFirst(); + + Assert.assertTrue("size query parameter should be added", parameter2.isPresent()); + Assert.assertTrue("size query parameter should be added", parameter2.get().getName().equals("size")); + Assert.assertTrue("size query parameter should be added", parameter2.get().getIn().equals("query")); + Assert.assertTrue("size query parameter should be added", parameter2.get().getSchema().getType().equals("integer")); + Assert.assertTrue("size query parameter should be added", parameter2.get().getDescription().equals("the size of the item")); + Assert.assertTrue("size query parameter should be added", parameter2.get().getRequired()); + + + + } + + @Test + public void testResponseStatusDiff() { + SwaggerDiff diff = SwaggerDiff.compareV3( + "src/test/resources/petstore_v3_diff1.json", + "src/test/resources/petstore_v3_diff2.json" + ); + + List changed = diff.getChangedEndpoints(); + Assert.assertFalse("Atteso almeno un endpoint cambiato", changed.isEmpty()); + + ChangedOperation op = changed.get(0).getChangedOperations() + .values().iterator().next(); + + // 201 aggiunto + Assert.assertTrue("Atteso status 201 aggiunto", + op.getAddResponses().containsKey("201")); + // 404 rimosso + Assert.assertTrue("Atteso status 404 rimosso", + op.getMissingResponses().containsKey("404")); + // 200 con schema cambiato (se hai modificato lo schema del 200) + boolean has200Changed = op.getChangedResponses().stream() + .anyMatch(cr -> "200".equals(cr.getStatusCode()) && cr.isDiff()); + Assert.assertTrue("Atteso schema del 200 cambiato", has200Changed); + } + + @Test + public void testResponseFullDiff() { + SwaggerDiff diff = SwaggerDiff.compareV3( + "src/test/resources/petstore_v3_diff1.json", + "src/test/resources/petstore_v3_diff2.json" + ); + + ChangedOperation op = diff.getChangedEndpoints().get(0) + .getChangedOperations().values().iterator().next(); + + ChangedResponse r200 = op.getChangedResponses().stream() + .filter(cr -> "200".equals(cr.getStatusCode())) + .findFirst().orElse(null); + + Assert.assertNotNull(r200); + + // description + Assert.assertTrue(r200.isDescriptionChanged()); + Assert.assertEquals("ok", r200.getOldDescription()); + Assert.assertEquals("update Success", r200.getNewDescription()); + } + + } diff --git a/src/test/resources/petstore_v3_diff1.json b/src/test/resources/petstore_v3_diff1.json new file mode 100644 index 00000000..cfaf2dc2 --- /dev/null +++ b/src/test/resources/petstore_v3_diff1.json @@ -0,0 +1,38 @@ +{ + "openapi": "3.0.1", + "info": { "title": "API", "version": "1.0" }, + "paths": { + "/item": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["name", "oldName", "size"], + "properties": { + "name": { "type": "string" }, + "oldName": { "type": "string", "deprecated": true }, + "size": { "type": "integer", "deprecated": true } + } + } + } + } + }, + "responses": { + "200": { + "description": "ok", + "headers": { + "X-Rate-Limit": { "description": "calls per hour", "schema": { "type": "integer" } }, + "X-Deprecated-Header": { "schema": { "type": "string" } } + }, + "content": { + "application/json": { "schema": { "type": "object", "properties": { "id": { "type": "integer" } } } } + } + }, + "404": { "description": "bad request" } + } + } + } + } +} diff --git a/src/test/resources/petstore_v3_diff2.json b/src/test/resources/petstore_v3_diff2.json new file mode 100644 index 00000000..285e284c --- /dev/null +++ b/src/test/resources/petstore_v3_diff2.json @@ -0,0 +1,81 @@ +{ + "openapi": "3.0.1", + "info": { "title": "API", "version": "1.1" }, + "paths": { + "/item": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["name", "age", "size"], + "properties": { + "name": { "type": "string", "description": "name of item" }, + "age": { "type": "integer", "description": "age of item" }, + "size": { "type": "integer", "deprecated": true } + } + } + } + } + }, + "responses": { + "200": { + "description": "update Success", + "headers": { + "X-Rate-Limit": { "description": "max calls per hour", "schema": { "type": "string" } }, + "X-New-Header": { "schema": { "type": "string" } } + }, + "content": { + "application/json": { "schema": { "type": "object", "properties": { "id": { "type": "string" } } } }, + "application/xml": { "schema": { "type": "object" } } + } +}, + "201": { "description": "created" }, + "400": { "description": "bad request", "content": { "application/json": { "schema": { "type": "string", "deprecated": true } } } } + } + }, + "get": { + "parameters": [ + { "name": "type", "in": "query", "schema": { "type": "string", "description": "the type of the item" } }, + { "name": "size", "in": "query", "required": true, "description": "the size of the item", "schema": { "type": "integer"} } + ], + "responses": { + "200": { "description": "ok" } + } + } + }, + "/admin/item": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { "type": "string", "description": "name of item" }, + "age": { "type": "integer", "description": "age of item" }, + "size": { "type": "integer", "deprecated": true } + } + } + } + } + }, + "responses": { + "200": { "description": "ok" }, + "201": { "description": "created" }, + "400": { "description": "bad request", "content": { "application/json": { "schema": { "type": "string", "deprecated": true } } } } + } + }, + "get": { + "parameters": [ + { "name": "type", "in": "query", "schema": { "type": "string", "description": "the type of the item" } }, + { "name": "size", "in": "query", "required": true, "description": "the size of the item", "schema": { "type": "integer"} } + ], + "responses": { + "200": { "description": "ok" } + } + } + } + } +} diff --git a/src/test/resources/petstore_v3_empty.json b/src/test/resources/petstore_v3_empty.json new file mode 100644 index 00000000..edd1b837 --- /dev/null +++ b/src/test/resources/petstore_v3_empty.json @@ -0,0 +1,53 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Swagger Petstore", + "description": "A sample API", + "version": "1.0.0" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "summary": "List all pets", + "operationId": "listPets", + "responses": { + "200": { + "description": "A paged array of pets", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + } + } + } +} From c7b370db3c975f806def6384e754eddc13ba42c7 Mon Sep 17 00:00:00 2001 From: Francesco Panico Date: Tue, 30 Jun 2026 09:42:35 +0200 Subject: [PATCH 5/8] commit esempi generati da test e altri casi --- Example/paymentServices/diff.html | 1 + .../paymentServices/paymentServicesNew.json | 1924 +++++++++++++++++ .../paymentServices/paymentServicesOld.json | 1922 ++++++++++++++++ Example/petstore_v3_testResponseRender.html | 1 + Example/testDiff.json | 1 + 5 files changed, 3849 insertions(+) create mode 100644 Example/paymentServices/diff.html create mode 100644 Example/paymentServices/paymentServicesNew.json create mode 100644 Example/paymentServices/paymentServicesOld.json create mode 100644 Example/petstore_v3_testResponseRender.html create mode 100644 Example/testDiff.json diff --git a/Example/paymentServices/diff.html b/Example/paymentServices/diff.html new file mode 100644 index 00000000..b60f5a9e --- /dev/null +++ b/Example/paymentServices/diff.html @@ -0,0 +1 @@ +Changelog

Changelog

Versions


Changes from 5.0.0 to 5.0.0.

What's New


    What's Deprecated


      What's Changed


      1. POST/fraud/bulk-payments/{payment-product}/{payment-id} This API allows to confirm or overwrite the SCA exception result performed by PSD2 Gateway.
        • Return Type

          • Add currencyConversionFees//Might be used by the ASPSP to transport specific currency conversion fees related to the initiated credit transfer.
          • Add debtorName//This field must contain the “owner name” info of the debited account. The “owner name” is the name of the legal account owner. If there is more than one owner, then e.g. two names might be noted here.For a corporate account, the corporate name is used for this attribute. This enables the ASPSP to transport the account owner name to the PISP in case where the regulatory need is provided and if not provided by other means like the List of Available Accounts Service.
          • Add estimatedInterbankSettlementAmount//The estimated amount to be transferred to the payee.
          • Add estimatedTotalAmount//The amount which is estimated to be debted from the debtor account.Note: This amount includes fees.
          • Add psuMessage//If the consumer is fraudster, the filed will be populated the specific error message
          • Add transactionFeeIndicator//If equals “true”, the transaction will involve specific transaction cost as shown by the ASPSP in their public price list or as agreed between ASPSP and PSU. If equals 'false', the transaction will not involve additional specific transaction costs to the PSU.
          • Add transactionFees//Can be used by the ASPSP to returns transaction fees relevant for the underlying payments.
          • DeletetransactionDecisionData.currencyConversionFees//Might be used by the ASPSP to transport specific currency conversion fees related to the initiated credit transfer.
          • DeletetransactionDecisionData.debtorName//This field must contain the “owner name” info of the debited account. The “owner name” is the name of the legal account owner. If there is more than one owner, then e.g. two names might be noted here.For a corporate account, the corporate name is used for this attribute. This enables the ASPSP to transport the account owner name to the PISP in case where the regulatory need is provided and if not provided by other means like the List of Available Accounts Service.
          • DeletetransactionDecisionData.estimatedInterbankSettlementAmount//The estimated amount to be transferred to the payee.
          • DeletetransactionDecisionData.estimatedTotalAmount//The amount which is estimated to be debted from the debtor account.Note: This amount includes fees.
          • DeletetransactionDecisionData.psuMessage//If the consumer is fraudster, the filed will be populated the specific error message
          • DeletetransactionDecisionData.transactionFeeIndicator//If equals “true”, the transaction will involve specific transaction cost as shown by the ASPSP in their public price list or as agreed between ASPSP and PSU. If equals 'false', the transaction will not involve additional specific transaction costs to the PSU.
          • DeletetransactionDecisionData.transactionFees//Can be used by the ASPSP to returns transaction fees relevant for the underlying payments.
        • Responses

          • Response 200
            • Add currencyConversionFees//Might be used by the ASPSP to transport specific currency conversion fees related to the initiated credit transfer.
            • Add debtorName//This field must contain the “owner name” info of the debited account. The “owner name” is the name of the legal account owner. If there is more than one owner, then e.g. two names might be noted here.For a corporate account, the corporate name is used for this attribute. This enables the ASPSP to transport the account owner name to the PISP in case where the regulatory need is provided and if not provided by other means like the List of Available Accounts Service.
            • Add estimatedInterbankSettlementAmount//The estimated amount to be transferred to the payee.
            • Add estimatedTotalAmount//The amount which is estimated to be debted from the debtor account.Note: This amount includes fees.
            • Add psuMessage//If the consumer is fraudster, the filed will be populated the specific error message
            • Add transactionFeeIndicator//If equals “true”, the transaction will involve specific transaction cost as shown by the ASPSP in their public price list or as agreed between ASPSP and PSU. If equals 'false', the transaction will not involve additional specific transaction costs to the PSU.
            • Add transactionFees//Can be used by the ASPSP to returns transaction fees relevant for the underlying payments.
            • DeletetransactionDecisionData.currencyConversionFees//Might be used by the ASPSP to transport specific currency conversion fees related to the initiated credit transfer.
            • DeletetransactionDecisionData.debtorName//This field must contain the “owner name” info of the debited account. The “owner name” is the name of the legal account owner. If there is more than one owner, then e.g. two names might be noted here.For a corporate account, the corporate name is used for this attribute. This enables the ASPSP to transport the account owner name to the PISP in case where the regulatory need is provided and if not provided by other means like the List of Available Accounts Service.
            • DeletetransactionDecisionData.estimatedInterbankSettlementAmount//The estimated amount to be transferred to the payee.
            • DeletetransactionDecisionData.estimatedTotalAmount//The amount which is estimated to be debted from the debtor account.Note: This amount includes fees.
            • DeletetransactionDecisionData.psuMessage//If the consumer is fraudster, the filed will be populated the specific error message
            • DeletetransactionDecisionData.transactionFeeIndicator//If equals “true”, the transaction will involve specific transaction cost as shown by the ASPSP in their public price list or as agreed between ASPSP and PSU. If equals 'false', the transaction will not involve additional specific transaction costs to the PSU.
            • DeletetransactionDecisionData.transactionFees//Can be used by the ASPSP to returns transaction fees relevant for the underlying payments.
      diff --git a/Example/paymentServices/paymentServicesNew.json b/Example/paymentServices/paymentServicesNew.json new file mode 100644 index 00000000..bddab59e --- /dev/null +++ b/Example/paymentServices/paymentServicesNew.json @@ -0,0 +1,1924 @@ +{ + "swagger": "2.0", + "info": { + "description": "In this section are described the interfaces exposed by ASPSP to manage bulk payment and subresource transactions", + "title": "paymentServices", + "version": "5.0.0" + }, + "paths": { + "/auth/sca/{payment-id}/authorisations/{authorisation-id}": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "description": "This field indicates the authorization purpose.The allowed values are:AUTHCANC", + "in": "header", + "name": "authorization-purpose", + "required": true, + "type": "string" + }, + { + "description": "The identification of the PSU in the ASPSP client interface.", + "in": "header", + "name": "psu-id", + "type": "string" + }, + { + "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", + "in": "header", + "name": "psu-id-type", + "type": "string" + }, + { + "description": "Identification of a Corporate, only used in a corporate context", + "in": "header", + "name": "psu-corporate-id", + "type": "string" + }, + { + "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", + "in": "header", + "name": "psu-corporate-id-type", + "type": "string" + }, + { + "description": "A unique registration number for TPP identification", + "in": "header", + "name": "tpp-registration-number", + "required": true, + "type": "string" + }, + { + "description": "The TPP name", + "in": "header", + "name": "tpp-name", + "required": true, + "type": "string" + }, + { + "description": "URI of the TPP, where the transaction flow shall be redirected to after a Redirect. Mandatory for redirect or OAuth SCA Approach ", + "in": "header", + "name": "tpp-redirect-uri", + "type": "string" + }, + { + "description": "If this URI is contained, the TPP is asking to redirect the transaction flow to this address instead of the TPP-Redirect-URI in case of a negative result of the redirect SCA method. This might be ignored by the ASPSP. ", + "in": "header", + "name": "tpp-nok-redirect-uri", + "type": "string" + }, + { + "description": "The identification of the ASPSP (for example ABI)", + "in": "header", + "name": "aspsp-code", + "required": true, + "type": "string" + }, + { + "description": "Identifier of the product in ASPSP scope.", + "in": "header", + "name": "aspsp-product-code", + "required": true, + "type": "string" + }, + { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "in": "header", + "name": "request-id", + "required": true, + "type": "string" + }, + { + "description": "The value list of products supported is:- sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-cross-border-credit-transfers", + "in": "header", + "name": "payment-product", + "type": "string" + }, + { + "description": "A session token generated by the ASPSP to ensure that an authentication session is maintained, in order to avoid re-entering client username and password (SFA) during the execution of the SCA", + "in": "header", + "name": "aspsp-authentication-session-id", + "type": "string" + }, + { + "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", + "in": "header", + "name": "Date", + "required": true, + "type": "string" + }, + { + "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", + "in": "path", + "name": "payment-id", + "required": true, + "type": "string" + }, + { + "description": "Resource identification of the related Payment Cancellation authorisation sub-resource or bulk authorisation sub-resource assigned to the created resource.", + "in": "path", + "name": "authorisation-id", + "required": true, + "type": "string" + }, + { + "description": "PaymentAuthorizationResourceScaInitiationRestRequest", + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/PaymentAuthorizationResourceScaInitiationRestRequest" + } + } + ], + "responses": { + "200": { + "description": "Service executed successfully", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/PaymentAuthorizationResourceScaInitiationRestResponse" + } + }, + "400": { + "description": "

      AUTH.0003

      Invalid parameter: {field name}

      AUTH.0004

      Missing parameter: {field name}

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "401": { + "description": "

      AUTH.0009

      PSU suspended or blocked

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "403": { + "description": "

      AUTH.0029

      ASPSP Default Error (Note: Error Description will be fill by ASPSP)

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "404": { + "description": "

      AUTH.0007

      Unknown PSU

      AUTH.0008

      Unknown ASPSP code

      PAY.0012

      Unknown Payment Identifier

      AUTH.0019

      Unsupported SCA approach

      AUTH.0027

      Unknown SCA method

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "409": { + "description": "

      AUTH.0002

      Operation not allowed

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "500": { + "description": "

      AUTH.0001

      Generic error

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + } + }, + "security": [ + { + "psd2_auth": [] + } + ], + "tags": [ + "paymentAuthorizationResourceScaInitiation" + ], + "operationId": "paymentAuthorizationResourceScaInitiation", + "summary": "This API allows to start a SCA process at ASPSP side." + }, + "put": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "description": "This field indicates the authorization purpose.The allowed values are:AUTHCANC", + "in": "header", + "name": "authorization-purpose", + "required": true, + "type": "string" + }, + { + "description": "A unique registration number for TPP identification", + "in": "header", + "name": "tpp-registration-number", + "required": true, + "type": "string" + }, + { + "description": "The TPP name", + "in": "header", + "name": "tpp-name", + "required": true, + "type": "string" + }, + { + "description": "The identification of the ASPSP (for example ABI)", + "in": "header", + "name": "aspsp-code", + "required": true, + "type": "string" + }, + { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "in": "header", + "name": "request-id", + "required": true, + "type": "string" + }, + { + "description": "The value list of products supported is: - sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-cross-border-credit-transfers", + "in": "header", + "name": "payment-product", + "type": "string" + }, + { + "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", + "in": "header", + "name": "Date", + "required": true, + "type": "string" + }, + { + "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", + "in": "path", + "name": "payment-id", + "required": true, + "type": "string" + }, + { + "description": "Resource identification of the related Payment Cancellation authorisation sub-resource or bulk authorisation sub-resource assigned to the created resource.", + "in": "path", + "name": "authorisation-id", + "required": true, + "type": "string" + }, + { + "description": "PaymentAuthorizationScaValidationRequestRestRequest", + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/PaymentAuthorizationScaValidationRequestRestRequest" + } + } + ], + "responses": { + "200": { + "description": "Service executed successfully", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/PaymentAuthorizationScaValidationRequestRestResponse" + } + }, + "400": { + "description": "

      AUTH.0003

      Invalid parameter: {field name}

      AUTH.0004

      Missing parameter: {field name}

      AUTH.0030

      Invalid SCA Authentication Data

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "401": { + "description": "

      AUTH.0028

      SCA validation failed

      PAY.0018

      Insufficient funds on the account

      PAY.0021

      Status Account doesn’t allow the operation

      PAY.0022

      Account type doesn’t allow the operation.

      PAY.0023

      Transaction amount exceeds the maximum authorized amount for specific payment product

      PAY.0024

      Duplicate payment

      PAY.0025

      Transaction amount exceeds transaction limit (daily, weekly, monthly)

      PAY.0026

      Transaction amount exceeds the single transaction limit

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "403": { + "description": "

      AUTH.0029

      ASPSP Default Error (Note: Error Description will be fill by ASPSP)

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "404": { + "description": "

      AUTH.0008

      Unknown ASPSP code

      PAY.0012

      Unknown Payment Identifier

      CNS.0006

      Unknown Consent

      PAY.0020

      Unknown Debtor Account

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "409": { + "description": "

      AUTH.0002

      Operation not allowed

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "500": { + "description": "

      AUTH.0001

      Generic error

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + } + }, + "security": [ + { + "psd2_auth": [] + } + ], + "tags": [ + "paymentAuthorizationScaValidationRequest" + ], + "operationId": "paymentAuthorizationScaValidationRequest", + "summary": "This API allows to validate the authentication data generated by PSU device during SCA phase. The service is used only in the case “Embedded” SCA approach." + } + }, + "/auth/sfa/{payment-id}/authorisations/{authorisation-id}": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "description": "This field indicates the authorization purpose.The allowed values are:AUTHCANC", + "in": "header", + "name": "authorization-purpose", + "required": true, + "type": "string" + }, + { + "description": "The identification of the PSU in the ASPSP client interface.", + "in": "header", + "name": "psu-id", + "type": "string" + }, + { + "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", + "in": "header", + "name": "psu-id-type", + "type": "string" + }, + { + "description": "Identification of a Corporate, only used in a corporate context", + "in": "header", + "name": "psu-corporate-id", + "type": "string" + }, + { + "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", + "in": "header", + "name": "psu-corporate-id-type", + "type": "string" + }, + { + "description": "A unique registration number for TPP identification", + "in": "header", + "name": "tpp-registration-number", + "required": true, + "type": "string" + }, + { + "description": "The TPP name", + "in": "header", + "name": "tpp-name", + "required": true, + "type": "string" + }, + { + "description": "The identification of the ASPSP (for example ABI)", + "in": "header", + "name": "aspsp-code", + "required": true, + "type": "string" + }, + { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "in": "header", + "name": "request-id", + "required": true, + "type": "string" + }, + { + "description": "The value list of products supported is:- sepa-credit-transfers- instant-sepa-credit-transfers- target-2-payments- cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-", + "in": "header", + "name": "payment-product", + "type": "string" + }, + { + "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", + "in": "header", + "name": "Date", + "required": true, + "type": "string" + }, + { + "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", + "in": "path", + "name": "payment-id", + "required": true, + "type": "string" + }, + { + "description": "Resource identification of the related Payment Cancellation authorisation sub-resource or bulk authorisation sub-resource assigned to the created resource.", + "in": "path", + "name": "authorisation-id", + "required": true, + "type": "string" + }, + { + "description": "PaymentAuthorizationPsuAuthenticationRestRequest", + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/PaymentAuthorizationPsuAuthenticationRestRequest" + } + } + ], + "responses": { + "200": { + "description": "Service executed successfully", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/PaymentAuthorizationPsuAuthenticationRestResponse" + } + }, + "400": { + "description": "

      AUTH.0003

      Invalid parameter: {field name}

      AUTH.0004

      Missing parameter: {field name}

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "401": { + "description": "

      AUTH.0009

      PSU suspended or blocked

      AUTH.0016

      PSU credentials invalid

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "403": { + "description": "

      AUTH.0029

      ASPSP Default Error (Note: Error Description will be fill by ASPSP)

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "404": { + "description": "

      AUTH.0007

      Unknown PSU

      AUTH.0008

      Unknown ASPSP code

      PAY.0013

      The addressed payment product is not available for the PSU.

      PAY.0014

      Unknown payment product

      PAY.0012

      Unknown Payment Identifier

      CNS.0006

      Unknown consent

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "409": { + "description": "

      AUTH.0002

      Operation not allowed

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "500": { + "description": "

      AUTH.0001

      Generic error

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + } + }, + "security": [ + { + "psd2_auth": [] + } + ], + "tags": [ + "paymentAuthorizationPsuAuthentication" + ], + "operationId": "paymentAuthorizationPsuAuthentication", + "summary": "This API manage the PSU authentication in an “embedded” way for bulk payments and cancellation requests." + } + }, + "/bulk-payments/{payment-id}/status": { + "get": { + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "description": "A unique registration number for TPP identification", + "in": "header", + "name": "tpp-registration-number", + "required": true, + "type": "string" + }, + { + "description": "The TPP name", + "in": "header", + "name": "tpp-name", + "required": true, + "type": "string" + }, + { + "description": "The identification of the ASPSP (for example ABI)", + "in": "header", + "name": "aspsp-code", + "required": true, + "type": "string" + }, + { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "in": "header", + "name": "request-id", + "required": true, + "type": "string" + }, + { + "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", + "in": "header", + "name": "Date", + "required": true, + "type": "string" + }, + { + "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", + "in": "path", + "name": "payment-id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "Service executed successfully ", + "headers": { + "content-type": { + "description": "application/json", + "type": "string" + }, + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/GetBulkPaymentStatusRequestRestResponse" + } + }, + "400": { + "description": "

      PAY.0003

      Invalid parameter: {field name}

      PAY.0004

      Missing parameter: {field name}

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "403": { + "description": "

      PAY.0029

      ASPSP Default Error (Note: Error Description will be fill by ASPSP)

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "404": { + "description": "

      PAY.0008

      Unknown ASPSP code

      PAY.0012

      Unknown Payment Identifier

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "409": { + "description": "

      PAY.0002

      Operation not allowed

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "500": { + "description": "

      PAY.0001

      Generic error

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + } + }, + "security": [ + { + "psd2_auth": [] + } + ], + "tags": [ + "getBulkPaymentStatusRequest" + ], + "operationId": "getBulkPaymentStatusRequest", + "summary": "This API retrieve the status of a Bulk payment initiation." + } + }, + "/fraud/bulk-payments/{payment-product}/{payment-id}": { + "post": { + "consumes": [ + "application/xml" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "description": "The Identification of the PSU in the ASPSP client interface.", + "in": "header", + "name": "psu-id", + "required": true, + "type": "string" + }, + { + "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", + "in": "header", + "name": "psu-id-type", + "type": "string" + }, + { + "description": "Identification of a Corporate, only used in a corporate context", + "in": "header", + "name": "psu-corporate-id", + "type": "string" + }, + { + "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", + "in": "header", + "name": "psu-corporate-id-type", + "type": "string" + }, + { + "description": "The forwarded Agent header field of the http request between PSU and TPP. The User-Agent request header contains a characteristic string that allows the network protocol peers to identify the application type, operating system, software vendor or software version of the requesting software user agent.", + "in": "header", + "name": "psu-user-agent", + "type": "string" + }, + { + "description": "The forwarded IP Address header field consists of the corresponding http request IP Address field between PSU and TPP.", + "in": "header", + "name": "psu-ip-address", + "required": true, + "type": "string" + }, + { + "description": "The forwarded IP Port header field consists of the corresponding HTTP request IP Port field between PSU and TPP, if available.", + "in": "header", + "name": "psu-ip-port", + "type": "string" + }, + { + "description": "The Accept request-header field can be used to specify certain media types which are acceptable for the response", + "in": "header", + "name": "psu-accept", + "type": "string" + }, + { + "description": "The charset information sent by the PSU. The Accept-Charset request-header field can be used to indicate what character sets are acceptable for the response. ", + "in": "header", + "name": "psu-accept-charset", + "type": "string" + }, + { + "description": "The encoding information sent by the PSU. The Accept-Encoding request-header field is similar to Accept but restricts the content-codings that are acceptable in the response.", + "in": "header", + "name": "psu-accept-encoding", + "type": "string" + }, + { + "description": "The language information sent by the PSU. The Accept-Language request-header field is similar to Accept, but restricts the set of natural languages that are preferred as a response to the request", + "in": "header", + "name": "psu-accept-language", + "type": "string" + }, + { + "description": "HTTP method used at the PSU – TPP interface, if available. Valid values are: - GET - POST - PUT - PATCH - DELETE", + "in": "header", + "name": "psu-http-method", + "type": "string" + }, + { + "description": "UUID (Universally Unique Identifier) for a device, which is used by the PSU, if available.UUID identifies either a device or a device dependant application installation. In case of an installation identification this ID need to be unaltered until removal from device.", + "in": "header", + "name": "psu-device-id", + "type": "string" + }, + { + "description": "The forwarded Geo Location of the corresponding http request between PSU and TPP if available.Format using [RFC 2426], i.e. GEO:,< longitude >.", + "in": "header", + "name": "psu-geo-location", + "type": "string" + }, + { + "description": "A unique registration number for TPP identification", + "in": "header", + "name": "tpp-registration-number", + "required": true, + "type": "string" + }, + { + "description": "The TPP name", + "in": "header", + "name": "tpp-name", + "required": true, + "type": "string" + }, + { + "description": "The identification of the ASPSP (for example ABI)", + "in": "header", + "name": "aspsp-code", + "required": true, + "type": "string" + }, + { + "description": "Identifier of the product in ASPSP scope.", + "in": "header", + "name": "aspsp-product-code", + "required": true, + "type": "string" + }, + { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "in": "header", + "name": "request-id", + "required": true, + "type": "string" + }, + { + "description": "The number of bits used to display one color.The possible values are: 32, 24, 16, or 8", + "in": "header", + "name": "screen-color-depth", + "type": "string" + }, + { + "description": "Width of the user's screen Note For iOS, the resolution measurement is in points. For other operating systems, the resolution measurement is in pixels.", + "in": "header", + "name": "screen-width", + "type": "string" + }, + { + "description": "Height of the user’s screen Note For iOS, the resolution measurement is in points. For other operating systems, the resolution measurement is in pixels.", + "in": "header", + "name": "screen-height", + "type": "string" + }, + { + "description": "Vertical space of the user’s screen. Note For iOS, the resolution measurement is in points. For other operating systems, the resolution measurement is in pixels.", + "in": "header", + "name": "screen-vertical-space", + "type": "string" + }, + { + "description": "The software plug-ins installed in the user’s browser.", + "in": "header", + "name": "software-plug-ins", + "type": "string" + }, + { + "description": "The user’s current time zone, related to UTC (for example UTC+01:00)", + "in": "header", + "name": "time-zone", + "type": "string" + }, + { + "description": "The language that the user has set in the browser ", + "in": "header", + "name": "browser-language", + "type": "string" + }, + { + "description": "A Boolean value that indicates whether Java is enabled in the browserOnly “true” or “false” value is accepted.", + "in": "header", + "name": "java-support", + "type": "string" + }, + { + "description": "A Boolean value that indicates whether cookies are enabled in the user’s browserOnly “true” or “false” value is accepted.", + "in": "header", + "name": "psu-cookie-support", + "type": "string" + }, + { + "description": "The operating system installed. ", + "in": "header", + "name": "device-os", + "type": "string" + }, + { + "description": "The operating system version installed", + "in": "header", + "name": "device-os-version", + "type": "string" + }, + { + "description": "The major version of the browser.", + "in": "header", + "name": "major-version", + "type": "string" + }, + { + "description": "The browser being used. Possible values are: Netscape, Mozilla, Explorer, Camino, Firefox, Konqueror, iCab, Opera, Safari, OmniWeb, Chrome.", + "in": "header", + "name": "browser-type", + "type": "string" + }, + { + "description": "Different identifiers are retrieved for each of the operating systems: -iOS 4.x-6.x The Wi-Fi MAC address. -iOS 7.x and later The identifierFor Vendor property of the UIDevice class. -Android The Internationa l Mobile Equipment Identity (IMEI) for GSM.", + "in": "header", + "name": "hardware-id", + "type": "string" + }, + { + "description": "A positive value indicates that the device is rooted or jailbroken.Only “true” or “false” value is accepted.", + "in": "header", + "name": "device-rooted", + "type": "string" + }, + { + "description": "A positive value indicates that the client device is an emulator.Only “true” or “false” value is accepted.", + "in": "header", + "name": "emulator", + "type": "string" + }, + { + "description": "The client application creates and saves a random unique identifier, which the client application can read. This enables verification that the application is genuine and not malicious malware. Note: For iOS system, the value is permanently stored in the keychain. For Android system the value is stored in the private storage of the application. This value is only stored until the application is uninstalled.", + "in": "header", + "name": "rsa-application-key", + "type": "string" + }, + { + "description": "The currently installed RSA Adaptive Authentication Mobile SDK Modules version and build number.", + "in": "header", + "name": "sdk-version", + "type": "string" + }, + { + "description": "The Date general-header field represents the date and time at which the message was originated.  Format: EEE, dd MMM yyyy hh:mm:ss z", + "in": "header", + "name": "Date", + "type": "string" + }, + { + "description": "The model of the mobile device.", + "in": "header", + "name": "device-model", + "type": "string" + }, + { + "description": "The mobile device name defined by the end user. Note In Android, this device element is returned based on the name defined in the Bluetooth settings.", + "in": "header", + "name": "device-name", + "type": "string" + }, + { + "description": "The language displayed in the mobile device.", + "in": "header", + "name": "languages", + "type": "string" + }, + { + "description": "Indicates whether or not the mobile device supports multitasking.Only “true” or “false” value is accepted.", + "in": "header", + "name": "multitasking-supported", + "type": "string" + }, + { + "description": "A GSM Cell ID (CID) is a unique number used to identify each base transceiver station (BTS) or sector of a BTS within a location area code (LAC) or GSM network. Note This device element is not supported by iOS. ", + "in": "header", + "name": "cell-tower-id", + "type": "string" + }, + { + "description": "The height of the mobile device above the ellipsoid. This device element is measured in meters.", + "in": "header", + "name": "geolocation-altitude", + "type": "string" + }, + { + "description": "The accuracy of the mobile device’s altitude. This device element is returned in meters.", + "in": "header", + "name": "geolocation-altitude-accuracy", + "type": "string" + }, + { + "description": "The direction of travel of the mobile device. This device element is returned in degrees.", + "in": "header", + "name": "geolocation-heading", + "type": "string" + }, + { + "description": "The radius of uncertainty for the geo-location of the mobile device. This device element is measured in meters. A negative value indicates that the geo-location latitude or longitude of the mobile device is invalid.", + "in": "header", + "name": "geolocation-horizontal-accuracy", + "type": "string" + }, + { + "description": "The current ground speed of the mobile device. This device element is returned in meters per second.", + "in": "header", + "name": "geolocation-speed", + "type": "string" + }, + { + "description": "There are five possible status codes:0=success The geolocation is successfully retrieved. 1=deny The end user denies location collection. 2=location status not available. The geolocation position is unavailable. 3=location status timeout The geolocation is timed out. 4=location status not supported The geolocation collection is not supported.", + "in": "header", + "name": "geolocation-status", + "type": "string" + }, + { + "description": "The time that the geo-location was created. This device element is returned in milliseconds.", + "in": "header", + "name": "geolocation-timestamp", + "type": "string" + }, + { + "description": "The local area code. Note For Android, this device element is only available for GSM devices and does not support CDMA devices. Note This device element is not supported by iOS.", + "in": "header", + "name": "location-area-code", + "type": "string" + }, + { + "description": "The Wi-Fi card MAC address. Note This device element is mandatory for iOS versions 4.x– 6.x.", + "in": "header", + "name": "wifi-mac-address", + "type": "string" + }, + { + "description": "The country code of the mobile device.", + "in": "header", + "name": "MCC", + "type": "string" + }, + { + "description": "The mobile carrier code.", + "in": "header", + "name": "MNC", + "type": "string" + }, + { + "description": "The basic service set identification (BSSID) for each basic service set. ", + "in": "header", + "name": "wifi-networks-data-bssid", + "type": "string" + }, + { + "description": "The wireless signal strength in the database management system expressed in decibel/meters For example -40 dBmNote This device element is not supported by iOS.", + "in": "header", + "name": "wifi-networks-data-signal-strength", + "type": "string" + }, + { + "description": "The Service Set Identifier (SSID). (the network name)", + "in": "header", + "name": "wifi-networks-data-ssid", + "type": "string" + }, + { + "description": "Define the channel used from PSU in order to send the request to TPP (WEB or APP) ", + "in": "header", + "name": "channel", + "type": "string" + }, + { + "description": "The operating system identification:- iOS: Universally Unique Identifier (UUID) (in this case it is length 36 characters)-Android: The client application creates a random unique identifier that permanently persists in the keychain (Android_ID) (in this case it is length 16 characters)", + "in": "header", + "name": "os-id", + "type": "string" + }, + { + "description": "Mobile Station International Subscriber Directory Number (MSISDN).", + "in": "header", + "name": "phone-number", + "type": "string" + }, + { + "description": "The International Mobile Subscriber Identity (IMSI)", + "in": "header", + "name": "sim-id", + "type": "string" + }, + { + "description": "The addressed payment product endpoint.The value list of products supported is: - sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers ", + "in": "path", + "name": "payment-product", + "required": true, + "type": "string" + }, + { + "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", + "in": "path", + "name": "payment-id", + "required": true, + "type": "string" + }, + { + "description": "TransactionDecisionDelegationForBulkRestRequest", + "in": "body", + "name": "body", + "schema": { + "format": "binary", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Service executed successfully", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TransactionDecisionDelegationForBulkRestResponse" + } + }, + "400": { + "description": "

      PAY.0003

      Invalid parameter: {field name}

      PAY.0004

      Missing parameter: {field name}

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "401": { + "description": "

      PAY.0009

      PSU suspended or blocked

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "403": { + "description": "

      PAY.0029

      ASPSP Default Error (Note: Error Description will be fill by ASPSP)

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "404": { + "description": "

      PAY.0007

      Unknown PSU

      PAY.0008

      Unknown ASPSP code

      PAY.0013

      The addressed payment product is not available for the PSU.

      PAY.0014

      Unknown Payment Product

      PAY.0012

      Unknown Payment Identifier

      PAY.0020

      Unknown Debtor Account

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "409": { + "description": "

      PAY.0002

      Operation not allowed

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "500": { + "description": "

      PAY.0001

      Generic error

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + } + }, + "security": [ + { + "psd2_auth": [] + } + ], + "tags": [ + "transactionDecisionDelegationForBulk" + ], + "operationId": "transactionDecisionDelegationForBulk", + "summary": "This API allows to confirm or overwrite the SCA exception result performed by PSD2 Gateway." + } + }, + "/{payment-service}/{payment-product}/{payment-id}": { + "delete": { + "produces": [ + "application/json" + ], + "parameters": [ + { + "description": "The identification of the PSU in the ASPSP client interface.", + "in": "header", + "name": "psu-id", + "required": true, + "type": "string" + }, + { + "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", + "in": "header", + "name": "psu-id-type", + "type": "string" + }, + { + "description": "Identification of a Corporate, only used in a corporate context", + "in": "header", + "name": "psu-corporate-id", + "type": "string" + }, + { + "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", + "in": "header", + "name": "psu-corporate-id-type", + "type": "string" + }, + { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "in": "header", + "name": "request-id", + "required": true, + "type": "string" + }, + { + "description": "The identification of the ASPSP (for example ABI)", + "in": "header", + "name": "aspsp-code", + "required": true, + "type": "string" + }, + { + "description": "Identifier of the product in ASPSP scope.", + "in": "header", + "name": "aspsp-product-code", + "required": true, + "type": "string" + }, + { + "description": "A unique registration number for TPP identification", + "in": "header", + "name": "tpp-registration-number", + "required": true, + "type": "string" + }, + { + "description": "The TPP name", + "in": "header", + "name": "tpp-name", + "required": true, + "type": "string" + }, + { + "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", + "in": "header", + "name": "Date", + "required": true, + "type": "string" + }, + { + "description": "The addressed payment service.The supported values are:paymentsperiodic-paymentsbulk-payments", + "in": "path", + "name": "payment-service", + "required": true, + "type": "string" + }, + { + "description": "The addressed payment product endpoint.The value list of products supported is: - sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-cross-border-credit-transfers ", + "in": "path", + "name": "payment-product", + "required": true, + "type": "string" + }, + { + "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", + "in": "path", + "name": "payment-id", + "required": true, + "type": "string" + } + ], + "responses": { + "202": { + "description": "ASPSP requests PSU authorization to cancel the payment", + "headers": { + "Date": { + "description": "The date provided used for the signature. Format: EEE, dd MMM yyyy hh:mm:ss z", + "type": "string" + }, + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponse202" + } + }, + "204": { + "description": "Payment successfully cancelled", + "headers": { + "Date": { + "description": "The date provided used for the signature. Format: EEE, dd MMM yyyy hh:mm:ss z", + "type": "string" + }, + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponse" + } + }, + "400": { + "description": "

      PAY.0003

      Invalid parameter: {field name}

      PAY.0004

      Missing parameter: {field name}

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + }, + "401": { + "description": "

      PAY.0009

      PSU suspended or blocked

      PAY.0021

      Status Account doesn’t allow the operation

      PAY.0022

      Account type doesn’t allow the operation.

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + }, + "403": { + "description": "

      PAY.0029

      ASPSP Default Error (Note: Error Description will be fill by ASPSP)

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + }, + "404": { + "description": "

      PAY.0008

      Unknown ASPSP code

      PAY.0013

      The addressed payment product is not available for the PSU.

      PAY.0014

      Unknown Payment Product

      PAY.0012

      Unknown Payment Identifier

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + }, + "405": { + "description": "

      PAY.0005

      The addressed payment is not cancellable e.g. due to cut off time passed or legal constraints

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + }, + "409": { + "description": "

      PAY.0002

      Operation not allowed

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + }, + "500": { + "description": "

      PAY.0001

      Generic error

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + } + }, + "security": [ + { + "psd2_auth": [] + } + ], + "tags": [ + "deletePayment" + ], + "operationId": "deletePayment", + "summary": "This API allows to execute a payment cancellation requesto towards ASPSP." + } + } + }, + "definitions": { + "ChallengeData": { + "description": "Data to generate OTP. The parameter is valorized only in the case of “EMBEDDED” SCA Approach.Object Type: Challenge Data", + "properties": { + "additionalInformation": { + "description": "Additional explanation for the PSU to explain e.g. fallback mechanism for the chosen SCA method. The TPP is obliged to show this to the PSU. ", + "type": "string" + }, + "data": { + "description": "String challenge data ", + "type": "string" + }, + "image": { + "description": "PNG data (max. 512 kilobyte) to be displayed to the PSU, Base64 encoding , cp. [RFC 4648]. This attribute is used only, when PHOTO_OTP or CHIP_OTP is the selected SCA method ", + "type": "string" + }, + "imageLink": { + "description": "A link where the ASPSP will provides the challenge image for the TPP. ", + "type": "string" + }, + "otpFormat": { + "description": "The format type of the OTP to be typed in. The admitted values are:charactersinteger.", + "type": "string" + }, + "otpMaxLength": { + "description": "The maximal length for the OTP to be typed in by the PSU. ", + "format": "int32", + "type": "integer" + } + }, + "type": "object" + }, + "CredentialsDetail": { + "description": "Credentials Details", + "properties": { + "credentialDetailId": { + "description": "Credential Detail Identification", + "type": "string" + }, + "credentialValue": { + "description": "Credential Value", + "type": "string" + } + }, + "required": [ + "credentialDetailId", + "credentialValue" + ], + "type": "object" + }, + "DeletePaymentRestResponse": { + "description": "PSD2 - delete payment rest response", + "properties": { + "paymentTransactionStatus": { + "description": "Status of the payment transaction on the bank systems. See Transaction Status", + "type": "string" + }, + "signatureData": { + "$ref": "#/definitions/SignatureData" + } + }, + "required": [ + "paymentTransactionStatus" + ], + "type": "object" + }, + "DeletePaymentRestResponseKO": { + "description": "PSD2 - delete payment rest response", + "properties": { + "errorManagement": { + "$ref": "#/definitions/ErrorManagement" + } + }, + "type": "object" + }, + "DeletePaymentRestResponse202": { + "type": "object", + "description": "PSD2 - delete payment rest response in case of http status 202", + "properties": { + "paymentTransactionStatus": { + "type": "string", + "description": "Status of the payment transaction on the bank systems. See Transaction Status" + } + }, + "required": [ + "paymentTransactionStatus" + ] + }, + "ErrorManagement": { + "properties": { + "errorCode": { + "description": "Code that identifies the error occurred", + "type": "string" + }, + "errorDescription": { + "description": "Error description", + "type": "string" + } + }, + "required": [ + "errorCode", + "errorDescription" + ], + "type": "object" + }, + "FraudScoreLevel": { + "description": "Define for each rule level the related score (this is valorized in case the fraudResult is different to 000)", + "properties": { + "levelId": { + "description": "Rule level identification", + "type": "string" + }, + "score": { + "description": "Score calculated to forehead of a violation of the rule level ", + "type": "string" + } + }, + "required": [ + "levelId", + "score" + ], + "type": "object" + }, + "GetBulkPaymentStatusRequestRestResponse": { + "description": "PSD2 Bulk - get bulk payment status request rest response", + "properties": { + "paymentTransactionStatus": { + "description": "Status of the payment transaction on the bank systems. See Transaction Status", + "type": "string" + }, + "psuMessage": { + "description": "Message to be shown to the PSU. This parameter should be used in case of multi SCA authorization. The bank will provide here the information needed to the TPP and PSU to complete the authorization of the payment.", + "type": "string" + } + }, + "type": "object" + }, + "PaymentAuthorizationPsuAuthenticationRestRequest": { + "description": "PSD2 - payment authorization psu authentication rest request", + "properties": { + "psuCredentials": { + "$ref": "#/definitions/PsuCredential" + } + }, + "required": [ + "psuCredentials" + ], + "type": "object" + }, + "PaymentAuthorizationPsuAuthenticationRestResponse": { + "description": "PSD2 - payment authorization psu authentication rest response", + "properties": { + "endUserIdentification": { + "description": "End user identification cross bank. The value is derived through function of SHA512 of the concatenation of PSU fiscal code and the following string: 57Z08PPmOedjjl4YLuRauc2nMoAckyQdZG5iSfmskX2jnO8LLO0jCOUCEVl5k5V19DD8xTwgg522trK3cx02, An example:enduserIdentification=SHA512(C.F.+ 57Z08PPmOedjjl4YLuRauc2nMoAckyQdZG5iSfmskX2jnO8LLO0jCOUCEVl5k5V19DD8xTwgg522trK3cx02If it is a corporate user the concatenation is the VAT number with the following string: njMqlpKSrwS6pObSRZgMcDVV6O2YyBujTckN1Z4gXB8FPvBQE6pYXpVZYxrckZsw4B1wCWAy7IgAi1sCtQWhzBBG7An example:enduserIdentification=SHA512(P.I. + njMqlpKSrwS6pObSRZgMcDVV6O2YyBujTckN1Z4gXB8FPvBQE6pYXpVZYxrckZsw4B1wCWAy7IgAi1sCtQWhzBBG7)", + "type": "string" + }, + "psuCorporateId": { + "description": "Identification of a Corporate, only used in a corporate context", + "type": "string" + }, + "psuCorporateIdType": { + "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", + "type": "string" + }, + "psuId": { + "description": "The identification of the PSU in the ASPSP client interface.", + "type": "string" + }, + "psuIdType": { + "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", + "type": "string" + }, + "psuMessage": { + "description": "Text to be displayed to the PSU.", + "type": "string" + }, + "psuName": { + "description": "Name of the PSU.In case of a corporate account, this might be the person acting on behalf of the corporate.", + "type": "string" + } + }, + "required": [ + "endUserIdentification", + "psuId" + ], + "type": "object" + }, + "PaymentAuthorizationResourceScaInitiationRestRequest": { + "description": "PSD2 - payment authorization resource sca initiation rest request", + "properties": { + "authorisationCallbackUrl": { + "description": "Callback partial URL (without IP and PORT) of the PSD2, where the bank notifies the SCA result. The parameter will be valorized only in the case “Redirect” or “Decoupled” approach. ", + "type": "string" + }, + "psuAlreadyAuthenticated": { + "description": "'true', if the psu has been already authenticated through the platform; 'false', otherwise.", + "type": "string" + }, + "selectedScaApproach": { + "description": "The SCA approach selected. Possible values are: EMBEDDED DECOUPLED REDIRECT OAUTH", + "type": "string" + }, + "selectedScaMethod": { + "$ref": "#/definitions/ScaMethod" + } + }, + "required": [ + "psuAlreadyAuthenticated", + "selectedScaApproach", + "selectedScaMethod" + ], + "type": "object" + }, + "PaymentAuthorizationResourceScaInitiationRestResponse": { + "description": "PSD2 - payment authorization resource sca initiation rest response", + "properties": { + "aspspScaUrl": { + "description": "URL to which the TPP must redirect the PSU to perform the SCA (it is valorized only in the case oAuth or Redirect SCA).", + "type": "string" + }, + "challengeData": { + "$ref": "#/definitions/ChallengeData" + }, + "psuMessage": { + "description": "Text to be displayed to the PSU.In the case of the Decoupled SCA approach this field will be valorized with PSU Instructions to execute.", + "type": "string" + } + }, + "type": "object" + }, + "PaymentAuthorizationScaValidationRequestRestRequest": { + "description": "PSD2 - payment authorization sca validation request rest request ", + "properties": { + "scaAuthenticationData": { + "description": "SCA authentication data, depending on the chosen authentication method. If the data is binary, then it is base64 encoded. ", + "type": "string" + } + }, + "required": [ + "scaAuthenticationData" + ], + "type": "object" + }, + "PaymentAuthorizationScaValidationRequestRestResponse": { + "description": "PSD2 - payment authorization sca validation request rest response ", + "properties": { + "paymentTransactionStatus": { + "description": "Status of the payment transaction. See Transaction Status", + "type": "string" + }, + "psuMessage": { + "description": "Text to be displayed to the PSU", + "type": "string" + }, + "signatureData": { + "$ref": "#/definitions/SignatureData" + } + }, + "type": "object" + }, + "PsuCredential": { + "description": "PSU Credentials on the Bank systemObject Type: PSU Credential", + "properties": { + "credentialsDetails": { + "description": "Credentials Details", + "items": { + "$ref": "#/definitions/CredentialsDetail" + }, + "type": "array" + }, + "productCode": { + "description": "Bank Product to which the user must authenticate. ", + "type": "string" + } + }, + "required": [ + "productCode" + ], + "type": "object" + }, + "RestHref": { + "description": "The link to the authorisation end-point, where the cancellation-authorisation sub-resource has to be generated while selecting the authentication method. This link is contained under exactly the same conditions as the data element 'scaMethods”.This link can be used in the following scenarios:The PSU ID provided during the cancellation isn’t the same that authorized the payment. The platform identifys more SCA methods applicable, so the PSU has to choise one of them to starts an explicit authorisationThe payment was SCA exempt and there are more SCA methods applicable, so the PSU has to choise one of them", + "properties": { + "href": { + "type": "string" + } + }, + "type": "object" + }, + "ScaMethod": { + "description": "The SCA Method selectedObject Type: Sca Method", + "properties": { + "authenticationMethodId": { + "description": "An identification provided by the ASPSP for the later identification of the authentication method selection.", + "type": "string" + }, + "authenticationType": { + "description": "The field describes the type of the authentication method.Example values are:SMS_OTPCHIP_OTPPHOTO_OTPPUSH_OTP", + "type": "string" + }, + "authenticationVersion": { + "description": "Depending on the “authenticationType”. This version can be used by differentiating authentication tools used within performing OTP generation in the same authentication type. This version can be referred to in the ASPSP’s documentation.", + "type": "string" + }, + "explanation": { + "description": "This is a description about the authentication method.", + "type": "string" + }, + "name": { + "description": "This could be a description provided by the ASPSP like “SMS OTP on phone +49160 xxxxx 28”.This name shall be used by the TPP when presenting a list of authentication methods to the PSU, if available.", + "type": "string" + } + }, + "required": [ + "authenticationMethodId", + "authenticationType" + ], + "type": "object" + }, + "SignatureData": { + "description": "ASPSP signature. Object Type: Signature Data", + "properties": { + "aspspCertificate": { + "description": "The APSPS certificate used to verify the signature", + "type": "string" + }, + "digest": { + "description": "The field is hash concatenation of the parameters which represents the payment. It could include the following parameters (to be defined with banks) paymentIdpaymentTransactionStatusDate (one received in input header)All fields are separated by pipe eg:SHA512(paymentId|paymentTransactionStatus|Date)", + "type": "string" + }, + "digitalSignature": { + "description": "The signature of the HASH by the ASPSP through its own encryption key", + "type": "string" + } + }, + "required": [ + "aspspCertificate", + "digest", + "digitalSignature" + ], + "type": "object" + }, + "ErrorManagementWrapper": { + "description": "", + "properties": { + "errorManagement": { + "$ref": "#/definitions/ErrorManagement" + } + } + }, + "TransactionDecisionData": { + "description": "Details on analysis performed from ASPSP systemObject Type: Transaction Decision Data", + "properties": { + + "fraudResult": { + "description": "Overall outcome assigned by the ASPSP system.The transaction is granted if the value is between 000 – 099 while will be denied (and consequently the flow interrupted) if the value is >= 100 (100 included)", + "type": "string" + }, + "fraudScoreLevel": { + "description": "Define for each rule level the related score (this is valorized in case the fraudResult is different to 000)", + "items": { + "$ref": "#/definitions/FraudScoreLevel" + }, + "type": "array" + } + }, + "required": [ + "fraudResult" + ], + "type": "object" + }, + "TransactionDecisionDelegationForBulkRestResponse": { + "description": "PSD2 - transaction decision delegation for bulk rest response", + "properties": { + "transactionDecisionData": { + "$ref": "#/definitions/TransactionDecisionData" + }, + "currencyConversionFees": { + "description": "Might be used by the ASPSP to transport specific currency conversion fees related to the initiated credit transfer.", + "type": "string" + }, + "debtorName": { + "description": "This field must contain the “owner name” info of the debited account. The “owner name” is the name of the legal account owner. If there is more than one owner, then e.g. two names might be noted here.For a corporate account, the corporate name is used for this attribute. This enables the ASPSP to transport the account owner name to the PISP in case where the regulatory need is provided and if not provided by other means like the List of Available Accounts Service.", + "type": "string" + }, + "estimatedInterbankSettlementAmount": { + "description": "The estimated amount to be transferred to the payee.", + "type": "string" + }, + "estimatedTotalAmount": { + "description": "The amount which is estimated to be debted from the debtor account.Note: This amount includes fees.", + "type": "string" + }, + "psuMessage": { + "description": "If the consumer is fraudster, the filed will be populated the specific error message", + "type": "string" + }, + "transactionFeeIndicator": { + "description": "If equals “true”, the transaction will involve specific transaction cost as shown by the ASPSP in their public price list or as agreed between ASPSP and PSU. If equals 'false', the transaction will not involve additional specific transaction costs to the PSU. ", + "type": "string" + }, + "transactionFees": { + "$ref": "#/definitions/TransactionFee" + } + + }, + "required": [ + "transactionDecisionData" + ], + "type": "object" + }, + "TransactionFee": { + "description": "Can be used by the ASPSP to returns transaction fees relevant for the underlying payments. ", + "properties": { + "amount": { + "description": "The amount given with fractional digits, where fractions must be compliant to the currency definition. Up to 14 significant figures. Negative amounts are signed by minus. The decimal separator is a dot. Example: Valid representations for EUR with up to two decimals are: • 1056 • 5768.2 • -1.50• 5877.78", + "type": "string" + }, + "currency": { + "description": "Define the code of a currency, three letters for the country. (CurrencyCode ISO 20022)", + "type": "string" + } + }, + "required": [ + "currency","amount" + ], + "type": "object" + } + }, + "securityDefinitions": { + "psd2_auth": { + "flow": "application", + "scopes": { + "production": "manage psd2 orchestrator authorization flow" + }, + "tokenUrl": "https://cbiglobeopenbankingapigateway.nexi.it/auth/oauth/v2/token", + "type": "oauth2" + } + }, + "x-components": {} +} \ No newline at end of file diff --git a/Example/paymentServices/paymentServicesOld.json b/Example/paymentServices/paymentServicesOld.json new file mode 100644 index 00000000..730cbf9c --- /dev/null +++ b/Example/paymentServices/paymentServicesOld.json @@ -0,0 +1,1922 @@ +{ + "swagger": "2.0", + "info": { + "description": "In this section are described the interfaces exposed by ASPSP to manage bulk payment and subresource transactions", + "title": "paymentServices", + "version": "5.0.0" + }, + "paths": { + "/auth/sca/{payment-id}/authorisations/{authorisation-id}": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "description": "This field indicates the authorization purpose.The allowed values are:AUTHCANC", + "in": "header", + "name": "authorization-purpose", + "required": true, + "type": "string" + }, + { + "description": "The identification of the PSU in the ASPSP client interface.", + "in": "header", + "name": "psu-id", + "type": "string" + }, + { + "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", + "in": "header", + "name": "psu-id-type", + "type": "string" + }, + { + "description": "Identification of a Corporate, only used in a corporate context", + "in": "header", + "name": "psu-corporate-id", + "type": "string" + }, + { + "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", + "in": "header", + "name": "psu-corporate-id-type", + "type": "string" + }, + { + "description": "A unique registration number for TPP identification", + "in": "header", + "name": "tpp-registration-number", + "required": true, + "type": "string" + }, + { + "description": "The TPP name", + "in": "header", + "name": "tpp-name", + "required": true, + "type": "string" + }, + { + "description": "URI of the TPP, where the transaction flow shall be redirected to after a Redirect. Mandatory for redirect or OAuth SCA Approach ", + "in": "header", + "name": "tpp-redirect-uri", + "type": "string" + }, + { + "description": "If this URI is contained, the TPP is asking to redirect the transaction flow to this address instead of the TPP-Redirect-URI in case of a negative result of the redirect SCA method. This might be ignored by the ASPSP. ", + "in": "header", + "name": "tpp-nok-redirect-uri", + "type": "string" + }, + { + "description": "The identification of the ASPSP (for example ABI)", + "in": "header", + "name": "aspsp-code", + "required": true, + "type": "string" + }, + { + "description": "Identifier of the product in ASPSP scope.", + "in": "header", + "name": "aspsp-product-code", + "required": true, + "type": "string" + }, + { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "in": "header", + "name": "request-id", + "required": true, + "type": "string" + }, + { + "description": "The value list of products supported is:- sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-cross-border-credit-transfers", + "in": "header", + "name": "payment-product", + "type": "string" + }, + { + "description": "A session token generated by the ASPSP to ensure that an authentication session is maintained, in order to avoid re-entering client username and password (SFA) during the execution of the SCA", + "in": "header", + "name": "aspsp-authentication-session-id", + "type": "string" + }, + { + "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", + "in": "header", + "name": "Date", + "required": true, + "type": "string" + }, + { + "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", + "in": "path", + "name": "payment-id", + "required": true, + "type": "string" + }, + { + "description": "Resource identification of the related Payment Cancellation authorisation sub-resource or bulk authorisation sub-resource assigned to the created resource.", + "in": "path", + "name": "authorisation-id", + "required": true, + "type": "string" + }, + { + "description": "PaymentAuthorizationResourceScaInitiationRestRequest", + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/PaymentAuthorizationResourceScaInitiationRestRequest" + } + } + ], + "responses": { + "200": { + "description": "Service executed successfully", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/PaymentAuthorizationResourceScaInitiationRestResponse" + } + }, + "400": { + "description": "

      AUTH.0003

      Invalid parameter: {field name}

      AUTH.0004

      Missing parameter: {field name}

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "401": { + "description": "

      AUTH.0009

      PSU suspended or blocked

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "403": { + "description": "

      AUTH.0029

      ASPSP Default Error (Note: Error Description will be fill by ASPSP)

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "404": { + "description": "

      AUTH.0007

      Unknown PSU

      AUTH.0008

      Unknown ASPSP code

      PAY.0012

      Unknown Payment Identifier

      AUTH.0019

      Unsupported SCA approach

      AUTH.0027

      Unknown SCA method

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "409": { + "description": "

      AUTH.0002

      Operation not allowed

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "500": { + "description": "

      AUTH.0001

      Generic error

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + } + }, + "security": [ + { + "psd2_auth": [] + } + ], + "tags": [ + "paymentAuthorizationResourceScaInitiation" + ], + "operationId": "paymentAuthorizationResourceScaInitiation", + "summary": "This API allows to start a SCA process at ASPSP side." + }, + "put": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "description": "This field indicates the authorization purpose.The allowed values are:AUTHCANC", + "in": "header", + "name": "authorization-purpose", + "required": true, + "type": "string" + }, + { + "description": "A unique registration number for TPP identification", + "in": "header", + "name": "tpp-registration-number", + "required": true, + "type": "string" + }, + { + "description": "The TPP name", + "in": "header", + "name": "tpp-name", + "required": true, + "type": "string" + }, + { + "description": "The identification of the ASPSP (for example ABI)", + "in": "header", + "name": "aspsp-code", + "required": true, + "type": "string" + }, + { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "in": "header", + "name": "request-id", + "required": true, + "type": "string" + }, + { + "description": "The value list of products supported is: - sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-cross-border-credit-transfers", + "in": "header", + "name": "payment-product", + "type": "string" + }, + { + "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", + "in": "header", + "name": "Date", + "required": true, + "type": "string" + }, + { + "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", + "in": "path", + "name": "payment-id", + "required": true, + "type": "string" + }, + { + "description": "Resource identification of the related Payment Cancellation authorisation sub-resource or bulk authorisation sub-resource assigned to the created resource.", + "in": "path", + "name": "authorisation-id", + "required": true, + "type": "string" + }, + { + "description": "PaymentAuthorizationScaValidationRequestRestRequest", + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/PaymentAuthorizationScaValidationRequestRestRequest" + } + } + ], + "responses": { + "200": { + "description": "Service executed successfully", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/PaymentAuthorizationScaValidationRequestRestResponse" + } + }, + "400": { + "description": "

      AUTH.0003

      Invalid parameter: {field name}

      AUTH.0004

      Missing parameter: {field name}

      AUTH.0030

      Invalid SCA Authentication Data

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "401": { + "description": "

      AUTH.0028

      SCA validation failed

      PAY.0018

      Insufficient funds on the account

      PAY.0021

      Status Account doesn’t allow the operation

      PAY.0022

      Account type doesn’t allow the operation.

      PAY.0023

      Transaction amount exceeds the maximum authorized amount for specific payment product

      PAY.0024

      Duplicate payment

      PAY.0025

      Transaction amount exceeds transaction limit (daily, weekly, monthly)

      PAY.0026

      Transaction amount exceeds the single transaction limit

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "403": { + "description": "

      AUTH.0029

      ASPSP Default Error (Note: Error Description will be fill by ASPSP)

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "404": { + "description": "

      AUTH.0008

      Unknown ASPSP code

      PAY.0012

      Unknown Payment Identifier

      CNS.0006

      Unknown Consent

      PAY.0020

      Unknown Debtor Account

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "409": { + "description": "

      AUTH.0002

      Operation not allowed

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "500": { + "description": "

      AUTH.0001

      Generic error

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + } + }, + "security": [ + { + "psd2_auth": [] + } + ], + "tags": [ + "paymentAuthorizationScaValidationRequest" + ], + "operationId": "paymentAuthorizationScaValidationRequest", + "summary": "This API allows to validate the authentication data generated by PSU device during SCA phase. The service is used only in the case “Embedded” SCA approach." + } + }, + "/auth/sfa/{payment-id}/authorisations/{authorisation-id}": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "description": "This field indicates the authorization purpose.The allowed values are:AUTHCANC", + "in": "header", + "name": "authorization-purpose", + "required": true, + "type": "string" + }, + { + "description": "The identification of the PSU in the ASPSP client interface.", + "in": "header", + "name": "psu-id", + "type": "string" + }, + { + "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", + "in": "header", + "name": "psu-id-type", + "type": "string" + }, + { + "description": "Identification of a Corporate, only used in a corporate context", + "in": "header", + "name": "psu-corporate-id", + "type": "string" + }, + { + "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", + "in": "header", + "name": "psu-corporate-id-type", + "type": "string" + }, + { + "description": "A unique registration number for TPP identification", + "in": "header", + "name": "tpp-registration-number", + "required": true, + "type": "string" + }, + { + "description": "The TPP name", + "in": "header", + "name": "tpp-name", + "required": true, + "type": "string" + }, + { + "description": "The identification of the ASPSP (for example ABI)", + "in": "header", + "name": "aspsp-code", + "required": true, + "type": "string" + }, + { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "in": "header", + "name": "request-id", + "required": true, + "type": "string" + }, + { + "description": "The value list of products supported is:- sepa-credit-transfers- instant-sepa-credit-transfers- target-2-payments- cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-", + "in": "header", + "name": "payment-product", + "type": "string" + }, + { + "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", + "in": "header", + "name": "Date", + "required": true, + "type": "string" + }, + { + "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", + "in": "path", + "name": "payment-id", + "required": true, + "type": "string" + }, + { + "description": "Resource identification of the related Payment Cancellation authorisation sub-resource or bulk authorisation sub-resource assigned to the created resource.", + "in": "path", + "name": "authorisation-id", + "required": true, + "type": "string" + }, + { + "description": "PaymentAuthorizationPsuAuthenticationRestRequest", + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/PaymentAuthorizationPsuAuthenticationRestRequest" + } + } + ], + "responses": { + "200": { + "description": "Service executed successfully", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/PaymentAuthorizationPsuAuthenticationRestResponse" + } + }, + "400": { + "description": "

      AUTH.0003

      Invalid parameter: {field name}

      AUTH.0004

      Missing parameter: {field name}

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "401": { + "description": "

      AUTH.0009

      PSU suspended or blocked

      AUTH.0016

      PSU credentials invalid

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "403": { + "description": "

      AUTH.0029

      ASPSP Default Error (Note: Error Description will be fill by ASPSP)

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "404": { + "description": "

      AUTH.0007

      Unknown PSU

      AUTH.0008

      Unknown ASPSP code

      PAY.0013

      The addressed payment product is not available for the PSU.

      PAY.0014

      Unknown payment product

      PAY.0012

      Unknown Payment Identifier

      CNS.0006

      Unknown consent

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "409": { + "description": "

      AUTH.0002

      Operation not allowed

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "500": { + "description": "

      AUTH.0001

      Generic error

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + } + }, + "security": [ + { + "psd2_auth": [] + } + ], + "tags": [ + "paymentAuthorizationPsuAuthentication" + ], + "operationId": "paymentAuthorizationPsuAuthentication", + "summary": "This API manage the PSU authentication in an “embedded” way for bulk payments and cancellation requests." + } + }, + "/bulk-payments/{payment-id}/status": { + "get": { + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "description": "A unique registration number for TPP identification", + "in": "header", + "name": "tpp-registration-number", + "required": true, + "type": "string" + }, + { + "description": "The TPP name", + "in": "header", + "name": "tpp-name", + "required": true, + "type": "string" + }, + { + "description": "The identification of the ASPSP (for example ABI)", + "in": "header", + "name": "aspsp-code", + "required": true, + "type": "string" + }, + { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "in": "header", + "name": "request-id", + "required": true, + "type": "string" + }, + { + "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", + "in": "header", + "name": "Date", + "required": true, + "type": "string" + }, + { + "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", + "in": "path", + "name": "payment-id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "Service executed successfully ", + "headers": { + "content-type": { + "description": "application/json", + "type": "string" + }, + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/GetBulkPaymentStatusRequestRestResponse" + } + }, + "400": { + "description": "

      PAY.0003

      Invalid parameter: {field name}

      PAY.0004

      Missing parameter: {field name}

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "403": { + "description": "

      PAY.0029

      ASPSP Default Error (Note: Error Description will be fill by ASPSP)

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "404": { + "description": "

      PAY.0008

      Unknown ASPSP code

      PAY.0012

      Unknown Payment Identifier

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "409": { + "description": "

      PAY.0002

      Operation not allowed

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "500": { + "description": "

      PAY.0001

      Generic error

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + } + }, + "security": [ + { + "psd2_auth": [] + } + ], + "tags": [ + "getBulkPaymentStatusRequest" + ], + "operationId": "getBulkPaymentStatusRequest", + "summary": "This API retrieve the status of a Bulk payment initiation." + } + }, + "/fraud/bulk-payments/{payment-product}/{payment-id}": { + "post": { + "consumes": [ + "application/xml" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "description": "The Identification of the PSU in the ASPSP client interface.", + "in": "header", + "name": "psu-id", + "required": true, + "type": "string" + }, + { + "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", + "in": "header", + "name": "psu-id-type", + "type": "string" + }, + { + "description": "Identification of a Corporate, only used in a corporate context", + "in": "header", + "name": "psu-corporate-id", + "type": "string" + }, + { + "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", + "in": "header", + "name": "psu-corporate-id-type", + "type": "string" + }, + { + "description": "The forwarded Agent header field of the http request between PSU and TPP. The User-Agent request header contains a characteristic string that allows the network protocol peers to identify the application type, operating system, software vendor or software version of the requesting software user agent.", + "in": "header", + "name": "psu-user-agent", + "type": "string" + }, + { + "description": "The forwarded IP Address header field consists of the corresponding http request IP Address field between PSU and TPP.", + "in": "header", + "name": "psu-ip-address", + "required": true, + "type": "string" + }, + { + "description": "The forwarded IP Port header field consists of the corresponding HTTP request IP Port field between PSU and TPP, if available.", + "in": "header", + "name": "psu-ip-port", + "type": "string" + }, + { + "description": "The Accept request-header field can be used to specify certain media types which are acceptable for the response", + "in": "header", + "name": "psu-accept", + "type": "string" + }, + { + "description": "The charset information sent by the PSU. The Accept-Charset request-header field can be used to indicate what character sets are acceptable for the response. ", + "in": "header", + "name": "psu-accept-charset", + "type": "string" + }, + { + "description": "The encoding information sent by the PSU. The Accept-Encoding request-header field is similar to Accept but restricts the content-codings that are acceptable in the response.", + "in": "header", + "name": "psu-accept-encoding", + "type": "string" + }, + { + "description": "The language information sent by the PSU. The Accept-Language request-header field is similar to Accept, but restricts the set of natural languages that are preferred as a response to the request", + "in": "header", + "name": "psu-accept-language", + "type": "string" + }, + { + "description": "HTTP method used at the PSU – TPP interface, if available. Valid values are: - GET - POST - PUT - PATCH - DELETE", + "in": "header", + "name": "psu-http-method", + "type": "string" + }, + { + "description": "UUID (Universally Unique Identifier) for a device, which is used by the PSU, if available.UUID identifies either a device or a device dependant application installation. In case of an installation identification this ID need to be unaltered until removal from device.", + "in": "header", + "name": "psu-device-id", + "type": "string" + }, + { + "description": "The forwarded Geo Location of the corresponding http request between PSU and TPP if available.Format using [RFC 2426], i.e. GEO:,< longitude >.", + "in": "header", + "name": "psu-geo-location", + "type": "string" + }, + { + "description": "A unique registration number for TPP identification", + "in": "header", + "name": "tpp-registration-number", + "required": true, + "type": "string" + }, + { + "description": "The TPP name", + "in": "header", + "name": "tpp-name", + "required": true, + "type": "string" + }, + { + "description": "The identification of the ASPSP (for example ABI)", + "in": "header", + "name": "aspsp-code", + "required": true, + "type": "string" + }, + { + "description": "Identifier of the product in ASPSP scope.", + "in": "header", + "name": "aspsp-product-code", + "required": true, + "type": "string" + }, + { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "in": "header", + "name": "request-id", + "required": true, + "type": "string" + }, + { + "description": "The number of bits used to display one color.The possible values are: 32, 24, 16, or 8", + "in": "header", + "name": "screen-color-depth", + "type": "string" + }, + { + "description": "Width of the user's screen Note For iOS, the resolution measurement is in points. For other operating systems, the resolution measurement is in pixels.", + "in": "header", + "name": "screen-width", + "type": "string" + }, + { + "description": "Height of the user’s screen Note For iOS, the resolution measurement is in points. For other operating systems, the resolution measurement is in pixels.", + "in": "header", + "name": "screen-height", + "type": "string" + }, + { + "description": "Vertical space of the user’s screen. Note For iOS, the resolution measurement is in points. For other operating systems, the resolution measurement is in pixels.", + "in": "header", + "name": "screen-vertical-space", + "type": "string" + }, + { + "description": "The software plug-ins installed in the user’s browser.", + "in": "header", + "name": "software-plug-ins", + "type": "string" + }, + { + "description": "The user’s current time zone, related to UTC (for example UTC+01:00)", + "in": "header", + "name": "time-zone", + "type": "string" + }, + { + "description": "The language that the user has set in the browser ", + "in": "header", + "name": "browser-language", + "type": "string" + }, + { + "description": "A Boolean value that indicates whether Java is enabled in the browserOnly “true” or “false” value is accepted.", + "in": "header", + "name": "java-support", + "type": "string" + }, + { + "description": "A Boolean value that indicates whether cookies are enabled in the user’s browserOnly “true” or “false” value is accepted.", + "in": "header", + "name": "psu-cookie-support", + "type": "string" + }, + { + "description": "The operating system installed. ", + "in": "header", + "name": "device-os", + "type": "string" + }, + { + "description": "The operating system version installed", + "in": "header", + "name": "device-os-version", + "type": "string" + }, + { + "description": "The major version of the browser.", + "in": "header", + "name": "major-version", + "type": "string" + }, + { + "description": "The browser being used. Possible values are: Netscape, Mozilla, Explorer, Camino, Firefox, Konqueror, iCab, Opera, Safari, OmniWeb, Chrome.", + "in": "header", + "name": "browser-type", + "type": "string" + }, + { + "description": "Different identifiers are retrieved for each of the operating systems: -iOS 4.x-6.x The Wi-Fi MAC address. -iOS 7.x and later The identifierFor Vendor property of the UIDevice class. -Android The Internationa l Mobile Equipment Identity (IMEI) for GSM.", + "in": "header", + "name": "hardware-id", + "type": "string" + }, + { + "description": "A positive value indicates that the device is rooted or jailbroken.Only “true” or “false” value is accepted.", + "in": "header", + "name": "device-rooted", + "type": "string" + }, + { + "description": "A positive value indicates that the client device is an emulator.Only “true” or “false” value is accepted.", + "in": "header", + "name": "emulator", + "type": "string" + }, + { + "description": "The client application creates and saves a random unique identifier, which the client application can read. This enables verification that the application is genuine and not malicious malware. Note: For iOS system, the value is permanently stored in the keychain. For Android system the value is stored in the private storage of the application. This value is only stored until the application is uninstalled.", + "in": "header", + "name": "rsa-application-key", + "type": "string" + }, + { + "description": "The currently installed RSA Adaptive Authentication Mobile SDK Modules version and build number.", + "in": "header", + "name": "sdk-version", + "type": "string" + }, + { + "description": "The Date general-header field represents the date and time at which the message was originated.  Format: EEE, dd MMM yyyy hh:mm:ss z", + "in": "header", + "name": "Date", + "type": "string" + }, + { + "description": "The model of the mobile device.", + "in": "header", + "name": "device-model", + "type": "string" + }, + { + "description": "The mobile device name defined by the end user. Note In Android, this device element is returned based on the name defined in the Bluetooth settings.", + "in": "header", + "name": "device-name", + "type": "string" + }, + { + "description": "The language displayed in the mobile device.", + "in": "header", + "name": "languages", + "type": "string" + }, + { + "description": "Indicates whether or not the mobile device supports multitasking.Only “true” or “false” value is accepted.", + "in": "header", + "name": "multitasking-supported", + "type": "string" + }, + { + "description": "A GSM Cell ID (CID) is a unique number used to identify each base transceiver station (BTS) or sector of a BTS within a location area code (LAC) or GSM network. Note This device element is not supported by iOS. ", + "in": "header", + "name": "cell-tower-id", + "type": "string" + }, + { + "description": "The height of the mobile device above the ellipsoid. This device element is measured in meters.", + "in": "header", + "name": "geolocation-altitude", + "type": "string" + }, + { + "description": "The accuracy of the mobile device’s altitude. This device element is returned in meters.", + "in": "header", + "name": "geolocation-altitude-accuracy", + "type": "string" + }, + { + "description": "The direction of travel of the mobile device. This device element is returned in degrees.", + "in": "header", + "name": "geolocation-heading", + "type": "string" + }, + { + "description": "The radius of uncertainty for the geo-location of the mobile device. This device element is measured in meters. A negative value indicates that the geo-location latitude or longitude of the mobile device is invalid.", + "in": "header", + "name": "geolocation-horizontal-accuracy", + "type": "string" + }, + { + "description": "The current ground speed of the mobile device. This device element is returned in meters per second.", + "in": "header", + "name": "geolocation-speed", + "type": "string" + }, + { + "description": "There are five possible status codes:0=success The geolocation is successfully retrieved. 1=deny The end user denies location collection. 2=location status not available. The geolocation position is unavailable. 3=location status timeout The geolocation is timed out. 4=location status not supported The geolocation collection is not supported.", + "in": "header", + "name": "geolocation-status", + "type": "string" + }, + { + "description": "The time that the geo-location was created. This device element is returned in milliseconds.", + "in": "header", + "name": "geolocation-timestamp", + "type": "string" + }, + { + "description": "The local area code. Note For Android, this device element is only available for GSM devices and does not support CDMA devices. Note This device element is not supported by iOS.", + "in": "header", + "name": "location-area-code", + "type": "string" + }, + { + "description": "The Wi-Fi card MAC address. Note This device element is mandatory for iOS versions 4.x– 6.x.", + "in": "header", + "name": "wifi-mac-address", + "type": "string" + }, + { + "description": "The country code of the mobile device.", + "in": "header", + "name": "MCC", + "type": "string" + }, + { + "description": "The mobile carrier code.", + "in": "header", + "name": "MNC", + "type": "string" + }, + { + "description": "The basic service set identification (BSSID) for each basic service set. ", + "in": "header", + "name": "wifi-networks-data-bssid", + "type": "string" + }, + { + "description": "The wireless signal strength in the database management system expressed in decibel/meters For example -40 dBmNote This device element is not supported by iOS.", + "in": "header", + "name": "wifi-networks-data-signal-strength", + "type": "string" + }, + { + "description": "The Service Set Identifier (SSID). (the network name)", + "in": "header", + "name": "wifi-networks-data-ssid", + "type": "string" + }, + { + "description": "Define the channel used from PSU in order to send the request to TPP (WEB or APP) ", + "in": "header", + "name": "channel", + "type": "string" + }, + { + "description": "The operating system identification:- iOS: Universally Unique Identifier (UUID) (in this case it is length 36 characters)-Android: The client application creates a random unique identifier that permanently persists in the keychain (Android_ID) (in this case it is length 16 characters)", + "in": "header", + "name": "os-id", + "type": "string" + }, + { + "description": "Mobile Station International Subscriber Directory Number (MSISDN).", + "in": "header", + "name": "phone-number", + "type": "string" + }, + { + "description": "The International Mobile Subscriber Identity (IMSI)", + "in": "header", + "name": "sim-id", + "type": "string" + }, + { + "description": "The addressed payment product endpoint.The value list of products supported is: - sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers ", + "in": "path", + "name": "payment-product", + "required": true, + "type": "string" + }, + { + "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", + "in": "path", + "name": "payment-id", + "required": true, + "type": "string" + }, + { + "description": "TransactionDecisionDelegationForBulkRestRequest", + "in": "body", + "name": "body", + "schema": { + "format": "binary", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Service executed successfully", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TransactionDecisionDelegationForBulkRestResponse" + } + }, + "400": { + "description": "

      PAY.0003

      Invalid parameter: {field name}

      PAY.0004

      Missing parameter: {field name}

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "401": { + "description": "

      PAY.0009

      PSU suspended or blocked

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "403": { + "description": "

      PAY.0029

      ASPSP Default Error (Note: Error Description will be fill by ASPSP)

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "404": { + "description": "

      PAY.0007

      Unknown PSU

      PAY.0008

      Unknown ASPSP code

      PAY.0013

      The addressed payment product is not available for the PSU.

      PAY.0014

      Unknown Payment Product

      PAY.0012

      Unknown Payment Identifier

      PAY.0020

      Unknown Debtor Account

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "409": { + "description": "

      PAY.0002

      Operation not allowed

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + }, + "500": { + "description": "

      PAY.0001

      Generic error

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/ErrorManagementWrapper" + } + } + }, + "security": [ + { + "psd2_auth": [] + } + ], + "tags": [ + "transactionDecisionDelegationForBulk" + ], + "operationId": "transactionDecisionDelegationForBulk", + "summary": "This API allows to confirm or overwrite the SCA exception result performed by PSD2 Gateway." + } + }, + "/{payment-service}/{payment-product}/{payment-id}": { + "delete": { + "produces": [ + "application/json" + ], + "parameters": [ + { + "description": "The identification of the PSU in the ASPSP client interface.", + "in": "header", + "name": "psu-id", + "required": true, + "type": "string" + }, + { + "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", + "in": "header", + "name": "psu-id-type", + "type": "string" + }, + { + "description": "Identification of a Corporate, only used in a corporate context", + "in": "header", + "name": "psu-corporate-id", + "type": "string" + }, + { + "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", + "in": "header", + "name": "psu-corporate-id-type", + "type": "string" + }, + { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "in": "header", + "name": "request-id", + "required": true, + "type": "string" + }, + { + "description": "The identification of the ASPSP (for example ABI)", + "in": "header", + "name": "aspsp-code", + "required": true, + "type": "string" + }, + { + "description": "Identifier of the product in ASPSP scope.", + "in": "header", + "name": "aspsp-product-code", + "required": true, + "type": "string" + }, + { + "description": "A unique registration number for TPP identification", + "in": "header", + "name": "tpp-registration-number", + "required": true, + "type": "string" + }, + { + "description": "The TPP name", + "in": "header", + "name": "tpp-name", + "required": true, + "type": "string" + }, + { + "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", + "in": "header", + "name": "Date", + "required": true, + "type": "string" + }, + { + "description": "The addressed payment service.The supported values are:paymentsperiodic-paymentsbulk-payments", + "in": "path", + "name": "payment-service", + "required": true, + "type": "string" + }, + { + "description": "The addressed payment product endpoint.The value list of products supported is: - sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-cross-border-credit-transfers ", + "in": "path", + "name": "payment-product", + "required": true, + "type": "string" + }, + { + "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", + "in": "path", + "name": "payment-id", + "required": true, + "type": "string" + } + ], + "responses": { + "202": { + "description": "ASPSP requests PSU authorization to cancel the payment", + "headers": { + "Date": { + "description": "The date provided used for the signature. Format: EEE, dd MMM yyyy hh:mm:ss z", + "type": "string" + }, + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponse202" + } + }, + "204": { + "description": "Payment successfully cancelled", + "headers": { + "Date": { + "description": "The date provided used for the signature. Format: EEE, dd MMM yyyy hh:mm:ss z", + "type": "string" + }, + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponse" + } + }, + "400": { + "description": "

      PAY.0003

      Invalid parameter: {field name}

      PAY.0004

      Missing parameter: {field name}

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + }, + "401": { + "description": "

      PAY.0009

      PSU suspended or blocked

      PAY.0021

      Status Account doesn’t allow the operation

      PAY.0022

      Account type doesn’t allow the operation.

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + }, + "403": { + "description": "

      PAY.0029

      ASPSP Default Error (Note: Error Description will be fill by ASPSP)

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + }, + "404": { + "description": "

      PAY.0008

      Unknown ASPSP code

      PAY.0013

      The addressed payment product is not available for the PSU.

      PAY.0014

      Unknown Payment Product

      PAY.0012

      Unknown Payment Identifier

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + }, + "405": { + "description": "

      PAY.0005

      The addressed payment is not cancellable e.g. due to cut off time passed or legal constraints

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + }, + "409": { + "description": "

      PAY.0002

      Operation not allowed

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + }, + "500": { + "description": "

      PAY.0001

      Generic error

      ", + "headers": { + "request-id": { + "description": "UUID of the request, unique to the call, as determined by the initiating party.", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/DeletePaymentRestResponseKO" + } + } + }, + "security": [ + { + "psd2_auth": [] + } + ], + "tags": [ + "deletePayment" + ], + "operationId": "deletePayment", + "summary": "This API allows to execute a payment cancellation requesto towards ASPSP." + } + } + }, + "definitions": { + "ChallengeData": { + "description": "Data to generate OTP. The parameter is valorized only in the case of “EMBEDDED” SCA Approach.Object Type: Challenge Data", + "properties": { + "additionalInformation": { + "description": "Additional explanation for the PSU to explain e.g. fallback mechanism for the chosen SCA method. The TPP is obliged to show this to the PSU. ", + "type": "string" + }, + "data": { + "description": "String challenge data ", + "type": "string" + }, + "image": { + "description": "PNG data (max. 512 kilobyte) to be displayed to the PSU, Base64 encoding , cp. [RFC 4648]. This attribute is used only, when PHOTO_OTP or CHIP_OTP is the selected SCA method ", + "type": "string" + }, + "imageLink": { + "description": "A link where the ASPSP will provides the challenge image for the TPP. ", + "type": "string" + }, + "otpFormat": { + "description": "The format type of the OTP to be typed in. The admitted values are:charactersinteger.", + "type": "string" + }, + "otpMaxLength": { + "description": "The maximal length for the OTP to be typed in by the PSU. ", + "format": "int32", + "type": "integer" + } + }, + "type": "object" + }, + "CredentialsDetail": { + "description": "Credentials Details", + "properties": { + "credentialDetailId": { + "description": "Credential Detail Identification", + "type": "string" + }, + "credentialValue": { + "description": "Credential Value", + "type": "string" + } + }, + "required": [ + "credentialDetailId", + "credentialValue" + ], + "type": "object" + }, + "DeletePaymentRestResponse": { + "description": "PSD2 - delete payment rest response", + "properties": { + "paymentTransactionStatus": { + "description": "Status of the payment transaction on the bank systems. See Transaction Status", + "type": "string" + }, + "signatureData": { + "$ref": "#/definitions/SignatureData" + } + }, + "required": [ + "paymentTransactionStatus" + ], + "type": "object" + }, + "DeletePaymentRestResponseKO": { + "description": "PSD2 - delete payment rest response", + "properties": { + "errorManagement": { + "$ref": "#/definitions/ErrorManagement" + } + }, + "type": "object" + }, + "DeletePaymentRestResponse202": { + "type": "object", + "description": "PSD2 - delete payment rest response in case of http status 202", + "properties": { + "paymentTransactionStatus": { + "type": "string", + "description": "Status of the payment transaction on the bank systems. See Transaction Status" + } + }, + "required": [ + "paymentTransactionStatus" + ] + }, + "ErrorManagement": { + "properties": { + "errorCode": { + "description": "Code that identifies the error occurred", + "type": "string" + }, + "errorDescription": { + "description": "Error description", + "type": "string" + } + }, + "required": [ + "errorCode", + "errorDescription" + ], + "type": "object" + }, + "FraudScoreLevel": { + "description": "Define for each rule level the related score (this is valorized in case the fraudResult is different to 000)", + "properties": { + "levelId": { + "description": "Rule level identification", + "type": "string" + }, + "score": { + "description": "Score calculated to forehead of a violation of the rule level ", + "type": "string" + } + }, + "required": [ + "levelId", + "score" + ], + "type": "object" + }, + "GetBulkPaymentStatusRequestRestResponse": { + "description": "PSD2 Bulk - get bulk payment status request rest response", + "properties": { + "paymentTransactionStatus": { + "description": "Status of the payment transaction on the bank systems. See Transaction Status", + "type": "string" + }, + "psuMessage": { + "description": "Message to be shown to the PSU. This parameter should be used in case of multi SCA authorization. The bank will provide here the information needed to the TPP and PSU to complete the authorization of the payment.", + "type": "string" + } + }, + "type": "object" + }, + "PaymentAuthorizationPsuAuthenticationRestRequest": { + "description": "PSD2 - payment authorization psu authentication rest request", + "properties": { + "psuCredentials": { + "$ref": "#/definitions/PsuCredential" + } + }, + "required": [ + "psuCredentials" + ], + "type": "object" + }, + "PaymentAuthorizationPsuAuthenticationRestResponse": { + "description": "PSD2 - payment authorization psu authentication rest response", + "properties": { + "endUserIdentification": { + "description": "End user identification cross bank. The value is derived through function of SHA512 of the concatenation of PSU fiscal code and the following string: 57Z08PPmOedjjl4YLuRauc2nMoAckyQdZG5iSfmskX2jnO8LLO0jCOUCEVl5k5V19DD8xTwgg522trK3cx02, An example:enduserIdentification=SHA512(C.F.+ 57Z08PPmOedjjl4YLuRauc2nMoAckyQdZG5iSfmskX2jnO8LLO0jCOUCEVl5k5V19DD8xTwgg522trK3cx02If it is a corporate user the concatenation is the VAT number with the following string: njMqlpKSrwS6pObSRZgMcDVV6O2YyBujTckN1Z4gXB8FPvBQE6pYXpVZYxrckZsw4B1wCWAy7IgAi1sCtQWhzBBG7An example:enduserIdentification=SHA512(P.I. + njMqlpKSrwS6pObSRZgMcDVV6O2YyBujTckN1Z4gXB8FPvBQE6pYXpVZYxrckZsw4B1wCWAy7IgAi1sCtQWhzBBG7)", + "type": "string" + }, + "psuCorporateId": { + "description": "Identification of a Corporate, only used in a corporate context", + "type": "string" + }, + "psuCorporateIdType": { + "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", + "type": "string" + }, + "psuId": { + "description": "The identification of the PSU in the ASPSP client interface.", + "type": "string" + }, + "psuIdType": { + "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", + "type": "string" + }, + "psuMessage": { + "description": "Text to be displayed to the PSU.", + "type": "string" + }, + "psuName": { + "description": "Name of the PSU.In case of a corporate account, this might be the person acting on behalf of the corporate.", + "type": "string" + } + }, + "required": [ + "endUserIdentification", + "psuId" + ], + "type": "object" + }, + "PaymentAuthorizationResourceScaInitiationRestRequest": { + "description": "PSD2 - payment authorization resource sca initiation rest request", + "properties": { + "authorisationCallbackUrl": { + "description": "Callback partial URL (without IP and PORT) of the PSD2, where the bank notifies the SCA result. The parameter will be valorized only in the case “Redirect” or “Decoupled” approach. ", + "type": "string" + }, + "psuAlreadyAuthenticated": { + "description": "'true', if the psu has been already authenticated through the platform; 'false', otherwise.", + "type": "string" + }, + "selectedScaApproach": { + "description": "The SCA approach selected. Possible values are: EMBEDDED DECOUPLED REDIRECT OAUTH", + "type": "string" + }, + "selectedScaMethod": { + "$ref": "#/definitions/ScaMethod" + } + }, + "required": [ + "psuAlreadyAuthenticated", + "selectedScaApproach", + "selectedScaMethod" + ], + "type": "object" + }, + "PaymentAuthorizationResourceScaInitiationRestResponse": { + "description": "PSD2 - payment authorization resource sca initiation rest response", + "properties": { + "aspspScaUrl": { + "description": "URL to which the TPP must redirect the PSU to perform the SCA (it is valorized only in the case oAuth or Redirect SCA).", + "type": "string" + }, + "challengeData": { + "$ref": "#/definitions/ChallengeData" + }, + "psuMessage": { + "description": "Text to be displayed to the PSU.In the case of the Decoupled SCA approach this field will be valorized with PSU Instructions to execute.", + "type": "string" + } + }, + "type": "object" + }, + "PaymentAuthorizationScaValidationRequestRestRequest": { + "description": "PSD2 - payment authorization sca validation request rest request ", + "properties": { + "scaAuthenticationData": { + "description": "SCA authentication data, depending on the chosen authentication method. If the data is binary, then it is base64 encoded. ", + "type": "string" + } + }, + "required": [ + "scaAuthenticationData" + ], + "type": "object" + }, + "PaymentAuthorizationScaValidationRequestRestResponse": { + "description": "PSD2 - payment authorization sca validation request rest response ", + "properties": { + "paymentTransactionStatus": { + "description": "Status of the payment transaction. See Transaction Status", + "type": "string" + }, + "psuMessage": { + "description": "Text to be displayed to the PSU", + "type": "string" + }, + "signatureData": { + "$ref": "#/definitions/SignatureData" + } + }, + "type": "object" + }, + "PsuCredential": { + "description": "PSU Credentials on the Bank systemObject Type: PSU Credential", + "properties": { + "credentialsDetails": { + "description": "Credentials Details", + "items": { + "$ref": "#/definitions/CredentialsDetail" + }, + "type": "array" + }, + "productCode": { + "description": "Bank Product to which the user must authenticate. ", + "type": "string" + } + }, + "required": [ + "productCode" + ], + "type": "object" + }, + "RestHref": { + "description": "The link to the authorisation end-point, where the cancellation-authorisation sub-resource has to be generated while selecting the authentication method. This link is contained under exactly the same conditions as the data element 'scaMethods”.This link can be used in the following scenarios:The PSU ID provided during the cancellation isn’t the same that authorized the payment. The platform identifys more SCA methods applicable, so the PSU has to choise one of them to starts an explicit authorisationThe payment was SCA exempt and there are more SCA methods applicable, so the PSU has to choise one of them", + "properties": { + "href": { + "type": "string" + } + }, + "type": "object" + }, + "ScaMethod": { + "description": "The SCA Method selectedObject Type: Sca Method", + "properties": { + "authenticationMethodId": { + "description": "An identification provided by the ASPSP for the later identification of the authentication method selection.", + "type": "string" + }, + "authenticationType": { + "description": "The field describes the type of the authentication method.Example values are:SMS_OTPCHIP_OTPPHOTO_OTPPUSH_OTP", + "type": "string" + }, + "authenticationVersion": { + "description": "Depending on the “authenticationType”. This version can be used by differentiating authentication tools used within performing OTP generation in the same authentication type. This version can be referred to in the ASPSP’s documentation.", + "type": "string" + }, + "explanation": { + "description": "This is a description about the authentication method.", + "type": "string" + }, + "name": { + "description": "This could be a description provided by the ASPSP like “SMS OTP on phone +49160 xxxxx 28”.This name shall be used by the TPP when presenting a list of authentication methods to the PSU, if available.", + "type": "string" + } + }, + "required": [ + "authenticationMethodId", + "authenticationType" + ], + "type": "object" + }, + "SignatureData": { + "description": "ASPSP signature. Object Type: Signature Data", + "properties": { + "aspspCertificate": { + "description": "The APSPS certificate used to verify the signature", + "type": "string" + }, + "digest": { + "description": "The field is hash concatenation of the parameters which represents the payment. It could include the following parameters (to be defined with banks) paymentIdpaymentTransactionStatusDate (one received in input header)All fields are separated by pipe eg:SHA512(paymentId|paymentTransactionStatus|Date)", + "type": "string" + }, + "digitalSignature": { + "description": "The signature of the HASH by the ASPSP through its own encryption key", + "type": "string" + } + }, + "required": [ + "aspspCertificate", + "digest", + "digitalSignature" + ], + "type": "object" + }, + "ErrorManagementWrapper": { + "description": "", + "properties": { + "errorManagement": { + "$ref": "#/definitions/ErrorManagement" + } + } + }, + "TransactionDecisionData": { + "description": "Details on analysis performed from ASPSP systemObject Type: Transaction Decision Data", + "properties": { + "currencyConversionFees": { + "description": "Might be used by the ASPSP to transport specific currency conversion fees related to the initiated credit transfer.", + "type": "string" + }, + "debtorName": { + "description": "This field must contain the “owner name” info of the debited account. The “owner name” is the name of the legal account owner. If there is more than one owner, then e.g. two names might be noted here.For a corporate account, the corporate name is used for this attribute. This enables the ASPSP to transport the account owner name to the PISP in case where the regulatory need is provided and if not provided by other means like the List of Available Accounts Service.", + "type": "string" + }, + "estimatedInterbankSettlementAmount": { + "description": "The estimated amount to be transferred to the payee.", + "type": "string" + }, + "estimatedTotalAmount": { + "description": "The amount which is estimated to be debted from the debtor account.Note: This amount includes fees.", + "type": "string" + }, + "fraudResult": { + "description": "Overall outcome assigned by the ASPSP system.The transaction is granted if the value is between 000 – 099 while will be denied (and consequently the flow interrupted) if the value is >= 100 (100 included)", + "type": "string" + }, + "fraudScoreLevel": { + "description": "Define for each rule level the related score (this is valorized in case the fraudResult is different to 000)", + "items": { + "$ref": "#/definitions/FraudScoreLevel" + }, + "type": "array" + }, + "psuMessage": { + "description": "If the consumer is fraudster, the filed will be populated the specific error message", + "type": "string" + }, + "transactionFeeIndicator": { + "description": "If equals “true”, the transaction will involve specific transaction cost as shown by the ASPSP in their public price list or as agreed between ASPSP and PSU. If equals 'false', the transaction will not involve additional specific transaction costs to the PSU. ", + "type": "string" + }, + "transactionFees": { + "$ref": "#/definitions/TransactionFee" + } + }, + "required": [ + "fraudResult" + ], + "type": "object" + }, + "TransactionDecisionDelegationForBulkRestResponse": { + "description": "PSD2 - transaction decision delegation for bulk rest response", + "properties": { + "transactionDecisionData": { + "$ref": "#/definitions/TransactionDecisionData" + } + }, + "required": [ + "transactionDecisionData" + ], + "type": "object" + }, + "TransactionFee": { + "description": "Can be used by the ASPSP to returns transaction fees relevant for the underlying payments. ", + "properties": { + "amount": { + "description": "The amount given with fractional digits, where fractions must be compliant to the currency definition. Up to 14 significant figures. Negative amounts are signed by minus. The decimal separator is a dot. Example: Valid representations for EUR with up to two decimals are: • 1056 • 5768.2 • -1.50• 5877.78", + "type": "string" + }, + "currency": { + "description": "Define the code of a currency, three letters for the country. (CurrencyCode ISO 20022)", + "type": "string" + } + }, + "required": [ + "currency","amount" + ], + "type": "object" + } + }, + "securityDefinitions": { + "psd2_auth": { + "flow": "application", + "scopes": { + "production": "manage psd2 orchestrator authorization flow" + }, + "tokenUrl": "https://cbiglobeopenbankingapigateway.nexi.it/auth/oauth/v2/token", + "type": "oauth2" + } + }, + "x-components": {} +} \ No newline at end of file diff --git a/Example/petstore_v3_testResponseRender.html b/Example/petstore_v3_testResponseRender.html new file mode 100644 index 00000000..021d6e31 --- /dev/null +++ b/Example/petstore_v3_testResponseRender.html @@ -0,0 +1 @@ +Changelog

      Changelog

      Versions


      Changes from 1.0 to 1.1.

      What's New


      1. GET/admin/item
      2. POST/admin/item
      3. GET/item

      What's Deprecated


        What's Changed


        1. POST/item
          • Return Type

            • Change id (Data Type)
          • Produces

            • Add application/xml
          • Responses

            • Add response 201//created
            • Add response 400//bad request
            • Delete response 404//bad request
            • Response 200
              • Description ok change into update Success
              • Change id (Data Type)
              • Add content-type application/xml
              • Add header X-New-Header
              • Delete header X-Deprecated-Header
              • Change header X-Rate-Limit
        \ No newline at end of file diff --git a/Example/testDiff.json b/Example/testDiff.json new file mode 100644 index 00000000..50933396 --- /dev/null +++ b/Example/testDiff.json @@ -0,0 +1 @@ +{"changedEndpoints":[{"changedOperations":{"PUT":{"addConsumes":[],"addParameters":[],"addProduces":[],"addProps":[],"addRequestProps":[{"el":"newFeild","newEnums":false,"property":{"description":"a feild demo by sayi","example":"a feild demo by sayi","exampleSetFlag":true,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"removedEnums":false,"typeChange":false},{"el":"category.newCatFeild","newEnums":false,"property":{"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"removedEnums":false,"typeChange":false},{"el":"owner.newUserFeild","newEnums":false,"property":{"description":"a new user feild demo","exampleSetFlag":false,"extensions":{},"format":"int32","specVersion":"V30","type":"integer","types":["integer"]},"removedEnums":false,"typeChange":false}],"addResponses":{},"changedParameter":[],"changedProps":[],"changedRequestProps":[],"changedResponses":[],"diff":true,"diffConsumes":false,"diffParam":false,"diffProduces":false,"diffProp":false,"diffRequestProp":true,"missingConsumes":[],"missingParameters":[],"missingProduces":[],"missingProps":[],"missingRequestProps":[{"el":"category.name","newEnums":false,"property":{"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"removedEnums":false,"typeChange":false},{"el":"owner.phone","newEnums":false,"property":{"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"removedEnums":false,"typeChange":false},{"el":"tags.removedField","newEnums":false,"property":{"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"removedEnums":false,"typeChange":false}],"missingResponses":{},"summary":"Update an existing pet"},"POST":{"addConsumes":[],"addParameters":[{"description":"add new query param demo","explode":true,"extensions":{},"in":"query","name":"tags","required":true,"schema":{"exampleSetFlag":false,"extensions":{"$ref":"$.changedEndpoints[0].changedOperations.POST.addParameters[0].extensions"},"items":{"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"specVersion":"V30","type":"array","types":["array"]},"style":"FORM"}],"addProduces":[],"addProps":[],"addRequestProps":[{"el":"newFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"category.newCatFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"owner.newUserFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"addResponses":{},"changedParameter":[],"changedProps":[],"changedRequestProps":[],"changedResponses":[],"diff":true,"diffConsumes":false,"diffParam":true,"diffProduces":false,"diffProp":false,"diffRequestProp":true,"missingConsumes":[],"missingParameters":[],"missingProduces":[],"missingProps":[],"missingRequestProps":[{"el":"category.name","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"owner.phone","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"tags.removedField","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"missingResponses":{},"summary":"Add a new pet to the store"}},"diff":true,"missingOperations":{},"newOperations":{},"pathUrl":"/pet"},{"changedOperations":{"GET":{"addConsumes":[],"addParameters":[],"addProduces":[],"addProps":[{"el":"newFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"category.newCatFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"owner.newUserFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"addRequestProps":[],"addResponses":{},"changedParameter":[],"changedProps":[],"changedRequestProps":[],"changedResponses":[{"addContentTypes":[],"addHeaders":{},"addProps":[{"el":"newFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"category.newCatFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"owner.newUserFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"changedHeaders":[],"changedProps":[],"contentTypeChanged":false,"descriptionChanged":false,"diff":true,"headersChanged":false,"missingContentTypes":[],"missingHeaders":{},"missingProps":[{"el":"category.name","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"owner.phone","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"tags.removedField","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"newDescription":"successful operation","oldDescription":"successful operation","schemaChanged":true,"statusCode":"200"}],"diff":true,"diffConsumes":false,"diffParam":false,"diffProduces":false,"diffProp":true,"diffRequestProp":false,"missingConsumes":[],"missingParameters":[],"missingProduces":[],"missingProps":[{"el":"category.name","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"owner.phone","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"tags.removedField","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"missingRequestProps":[],"missingResponses":{},"summary":"Finds Pets by status"}},"diff":true,"missingOperations":{},"newOperations":{},"pathUrl":"/pet/findByStatus"},{"changedOperations":{"GET":{"addConsumes":[],"addParameters":[],"addProduces":[],"addProps":[{"el":"newFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"category.newCatFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"owner.newUserFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"addRequestProps":[],"addResponses":{},"changedParameter":[],"changedProps":[],"changedRequestProps":[],"changedResponses":[{"addContentTypes":[],"addHeaders":{},"addProps":[{"el":"newFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"category.newCatFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"owner.newUserFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"changedHeaders":[],"changedProps":[],"contentTypeChanged":false,"descriptionChanged":false,"diff":true,"headersChanged":false,"missingContentTypes":[],"missingHeaders":{},"missingProps":[{"el":"category.name","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"owner.phone","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"tags.removedField","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"newDescription":"successful operation","oldDescription":"successful operation","schemaChanged":true,"statusCode":"200"}],"diff":true,"diffConsumes":false,"diffParam":false,"diffProduces":false,"diffProp":true,"diffRequestProp":false,"missingConsumes":[],"missingParameters":[],"missingProduces":[],"missingProps":[{"el":"category.name","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"owner.phone","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"tags.removedField","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"missingRequestProps":[],"missingResponses":{},"summary":"Finds Pets by tags"}},"diff":true,"missingOperations":{},"newOperations":{},"pathUrl":"/pet/findByTags"},{"changedOperations":{"DELETE":{"addConsumes":[],"addParameters":[{"extensions":{},"in":"header","name":"newHeaderParam","schema":{"exampleSetFlag":false,"extensions":{"$ref":"$.changedEndpoints[3].changedOperations.DELETE.addParameters[0].extensions"},"specVersion":"V30","type":"string","types":["string"]}}],"addProduces":[],"addProps":[],"addRequestProps":[],"addResponses":{},"changedParameter":[],"changedProps":[],"changedRequestProps":[],"changedResponses":[],"diff":true,"diffConsumes":false,"diffParam":true,"diffProduces":false,"diffProp":false,"diffRequestProp":false,"missingConsumes":[],"missingParameters":[],"missingProduces":[],"missingProps":[],"missingRequestProps":[],"missingResponses":{},"summary":"Deletes a pet"}},"diff":true,"missingOperations":{"POST":{"extensions":{},"operationId":"updatePetWithForm","parameters":[{"description":"ID of pet that needs to be updated","extensions":{},"in":"path","name":"petId","required":true,"schema":{"exampleSetFlag":false,"extensions":{"$ref":"$.changedEndpoints[3].missingOperations.POST.parameters[0].extensions"},"format":"int64","specVersion":"V30","type":"integer","types":["integer"]}}],"requestBody":{"content":{"application/x-www-form-urlencoded":{"exampleSetFlag":false,"schema":{"exampleSetFlag":false,"properties":{"name":{"description":"Updated name of the pet","exampleSetFlag":false,"extensions":{},"name":"name","specVersion":"V30","type":"string","types":["string"]},"status":{"description":"Updated status of the pet","exampleSetFlag":false,"extensions":{},"name":"status","specVersion":"V30","type":"string","types":["string"]}},"specVersion":"V30","type":"object","types":["object"]}}}},"responses":{"405":{"content":{},"description":"Invalid input","extensions":{}}},"security":[{"petstore_auth":["write:pets","read:pets"]}],"summary":"Updates a pet in the store with form data","tags":["pet"]}},"newOperations":{"GET":{"description":"Returns a single pet","extensions":{},"operationId":"getPetById","parameters":[{"description":"ID of pet to return","extensions":{},"in":"path","name":"petId","required":true,"schema":{"exampleSetFlag":false,"extensions":{"$ref":"$.changedEndpoints[3].newOperations.GET.parameters[0].extensions"},"format":"int64","specVersion":"V30","type":"integer","types":["integer"]}}],"responses":{"200":{"content":{"application/xml":{"exampleSetFlag":false,"schema":{"exampleSetFlag":false,"jsonSchema":{"type":"object","required":["name","photoUrls"],"properties":{"id":{"type":"integer","format":"int64"},"category":{"$ref":"#/components/schemas/Category","originalRef":"#/components/schemas/Category"},"name":{"type":"string","example":"doggies"},"newFeild":{"type":"string","example":"a feild demo by sayi","description":"a feild demo by sayi"},"owner":{"$ref":"#/components/schemas/User","originalRef":"#/components/schemas/User"},"parent":{"$ref":"#/components/schemas/Pet","originalRef":"#/components/schemas/Pet"},"photoUrls":{"type":"array","xml":{"name":"photoUrl","wrapped":true},"items":{"type":"string"}},"tags":{"type":"array","xml":{"name":"tag","wrapped":true},"items":{"$ref":"#/components/schemas/Tag","originalRef":"#/components/schemas/Tag"}},"status":{"type":"string","description":"pet status in the store","enum":["available","pending","sold"]}},"xml":{"name":"Pet"}},"properties":{"id":{"exampleSetFlag":false,"extensions":{},"format":"int64","specVersion":"V30","type":"integer","types":["integer"]},"category":{"exampleSetFlag":false,"jsonSchema":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"newCatFeild":{"type":"string"}},"xml":{"name":"Category"}},"properties":{"id":{"exampleSetFlag":false,"extensions":{},"format":"int64","specVersion":"V30","type":"integer","types":["integer"]},"newCatFeild":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[1].property"}},"specVersion":"V30","type":"object","types":["object"],"xml":{"name":"Category"}},"name":{"example":"doggies","exampleSetFlag":true,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"newFeild":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[0].property"},"owner":{"exampleSetFlag":false,"jsonSchema":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"username":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"password":{"type":"string"},"favorite":{"$ref":"#/components/schemas/Pet","originalRef":"#/components/schemas/Pet"},"userStatus":{"type":"integer","format":"int32","description":"User Status"},"newUserFeild":{"type":"integer","format":"int32","description":"a new user feild demo"}},"xml":{"name":"User"}},"properties":{"id":{"exampleSetFlag":false,"extensions":{},"format":"int64","specVersion":"V30","type":"integer","types":["integer"]},"username":{"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"firstName":{"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"lastName":{"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"email":{"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"password":{"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"favorite":{"exampleSetFlag":false,"specVersion":"V30"},"userStatus":{"description":"User Status","exampleSetFlag":false,"extensions":{},"format":"int32","specVersion":"V30","type":"integer","types":["integer"]},"newUserFeild":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[2].property"}},"specVersion":"V30","type":"object","types":["object"],"xml":{"name":"User"}},"parent":{"$ref":"$.changedEndpoints[3].newOperations.GET.responses.200.content.application/xml.schema.properties.owner.properties.favorite"},"photoUrls":{"exampleSetFlag":false,"extensions":{},"items":{"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"specVersion":"V30","type":"array","types":["array"],"xml":{"name":"photoUrl","wrapped":true}},"tags":{"exampleSetFlag":false,"extensions":{},"items":{"exampleSetFlag":false,"jsonSchema":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Tag"}},"properties":{"id":{"exampleSetFlag":false,"extensions":{},"format":"int64","specVersion":"V30","type":"integer","types":["integer"]},"name":{"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]}},"specVersion":"V30","type":"object","types":["object"],"xml":{"name":"Tag"}},"specVersion":"V30","type":"array","types":["array"],"xml":{"name":"tag","wrapped":true}},"status":{"description":"pet status in the store","enum":["available","pending","sold"],"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]}},"required":["name","photoUrls"],"specVersion":"V30","type":"object","types":["object"],"xml":{"name":"Pet"}}},"application/json":{"exampleSetFlag":false,"schema":{"$ref":"$.changedEndpoints[3].newOperations.GET.responses.200.content.application/xml.schema"}}},"description":"successful operation","extensions":{}},"400":{"content":{},"description":"Invalid ID supplied","extensions":{}},"404":{"content":{},"description":"Pet not found","extensions":{}}},"security":[{"api_key":[]}],"summary":"Find pet by ID","tags":["pet"]}},"pathUrl":"/pet/{petId}"},{"changedOperations":{"POST":{"addConsumes":[],"addParameters":[],"addProduces":[],"addProps":[],"addRequestProps":[],"addResponses":{},"changedParameter":[{"changeDescription":true,"changeRequired":false,"changed":[],"diff":true,"increased":[],"leftParameter":{"description":"ID of pet to update","extensions":{},"in":"path","name":"petId","required":true,"schema":{"exampleSetFlag":false,"extensions":{"$ref":"$.changedEndpoints[4].changedOperations.POST.changedParameter[0].leftParameter.extensions"},"format":"int64","specVersion":"V30","type":"integer","types":["integer"]}},"missing":[],"rightParameter":{"description":"ID of pet to update, default false","extensions":{},"in":"path","name":"petId","required":true,"schema":{"exampleSetFlag":false,"extensions":{"$ref":"$.changedEndpoints[4].changedOperations.POST.changedParameter[0].rightParameter.extensions"},"format":"int64","specVersion":"V30","type":"integer","types":["integer"]}}}],"changedProps":[],"changedRequestProps":[],"changedResponses":[],"diff":true,"diffConsumes":false,"diffParam":true,"diffProduces":false,"diffProp":false,"diffRequestProp":false,"missingConsumes":[],"missingParameters":[],"missingProduces":[],"missingProps":[],"missingRequestProps":[],"missingResponses":{},"summary":"uploads an image for pet"}},"diff":true,"missingOperations":{},"newOperations":{},"pathUrl":"/pet/{petId}/uploadImage"},{"changedOperations":{"POST":{"addConsumes":["application/json"],"addParameters":[],"addProduces":[],"addProps":[],"addRequestProps":[],"addResponses":{},"changedParameter":[],"changedProps":[{"el":"id","newEnums":false,"property":{"exampleSetFlag":false,"extensions":{},"format":"int64","specVersion":"V30","type":"integer","types":["integer"]},"removedEnums":false,"typeChange":true},{"el":"status","newEnums":true,"property":{"description":"Order Status","enum":["placed","approved","delivered"],"exampleSetFlag":false,"extensions":{},"specVersion":"V30","type":"string","types":["string"]},"removedEnums":true,"typeChange":false}],"changedRequestProps":[{"el":"id","newEnums":false,"property":{"$ref":"$.changedEndpoints[5].changedOperations.POST.changedProps[0].property"},"removedEnums":false,"typeChange":true},{"el":"status","newEnums":true,"property":{"$ref":"$.changedEndpoints[5].changedOperations.POST.changedProps[1].property"},"removedEnums":true,"typeChange":false}],"changedResponses":[{"addContentTypes":[],"addHeaders":{},"addProps":[],"changedHeaders":[],"changedProps":[{"el":"id","newEnums":false,"property":{"$ref":"$.changedEndpoints[5].changedOperations.POST.changedProps[0].property"},"removedEnums":false,"typeChange":true},{"el":"status","newEnums":true,"property":{"$ref":"$.changedEndpoints[5].changedOperations.POST.changedProps[1].property"},"removedEnums":true,"typeChange":false}],"contentTypeChanged":true,"descriptionChanged":false,"diff":true,"headersChanged":false,"missingContentTypes":["application/xml"],"missingHeaders":{},"missingProps":[],"newDescription":"successful operation","oldDescription":"successful operation","schemaChanged":true,"statusCode":"200"}],"diff":true,"diffConsumes":true,"diffParam":false,"diffProduces":true,"diffProp":true,"diffRequestProp":true,"missingConsumes":["application/xml"],"missingParameters":[],"missingProduces":["application/xml"],"missingProps":[],"missingRequestProps":[],"missingResponses":{},"summary":"Place an order for a pet"}},"diff":true,"missingOperations":{},"newOperations":{},"pathUrl":"/store/order"},{"changedOperations":{"GET":{"addConsumes":[],"addParameters":[],"addProduces":[],"addProps":[],"addRequestProps":[],"addResponses":{},"changedParameter":[],"changedProps":[{"el":"id","newEnums":false,"property":{"$ref":"$.changedEndpoints[5].changedOperations.POST.changedProps[0].property"},"removedEnums":false,"typeChange":true},{"el":"status","newEnums":true,"property":{"$ref":"$.changedEndpoints[5].changedOperations.POST.changedProps[1].property"},"removedEnums":true,"typeChange":false}],"changedRequestProps":[],"changedResponses":[{"addContentTypes":[],"addHeaders":{},"addProps":[],"changedHeaders":[],"changedProps":[{"el":"id","newEnums":false,"property":{"$ref":"$.changedEndpoints[5].changedOperations.POST.changedProps[0].property"},"removedEnums":false,"typeChange":true},{"el":"status","newEnums":true,"property":{"$ref":"$.changedEndpoints[5].changedOperations.POST.changedProps[1].property"},"removedEnums":true,"typeChange":false}],"contentTypeChanged":false,"descriptionChanged":false,"diff":true,"headersChanged":false,"missingContentTypes":[],"missingHeaders":{},"missingProps":[],"newDescription":"successful operation","oldDescription":"successful operation","schemaChanged":true,"statusCode":"200"}],"diff":true,"diffConsumes":false,"diffParam":false,"diffProduces":false,"diffProp":true,"diffRequestProp":false,"missingConsumes":[],"missingParameters":[],"missingProduces":[],"missingProps":[],"missingRequestProps":[],"missingResponses":{},"summary":"Find purchase order by ID"}},"diff":true,"missingOperations":{},"newOperations":{},"pathUrl":"/store/order/{orderId}"},{"changedOperations":{"POST":{"addConsumes":[],"addParameters":[],"addProduces":[],"addProps":[],"addRequestProps":[{"el":"newUserFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[2].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.newFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.category.newCatFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[1].property"},"removedEnums":false,"typeChange":false}],"addResponses":{},"changedParameter":[],"changedProps":[],"changedRequestProps":[],"changedResponses":[],"diff":true,"diffConsumes":false,"diffParam":false,"diffProduces":false,"diffProp":false,"diffRequestProp":true,"missingConsumes":[],"missingParameters":[],"missingProduces":[],"missingProps":[],"missingRequestProps":[{"el":"phone","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.category.name","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.tags.removedField","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"missingResponses":{},"summary":"Create user"}},"diff":true,"missingOperations":{},"newOperations":{},"pathUrl":"/user"},{"changedOperations":{"POST":{"addConsumes":[],"addParameters":[],"addProduces":[],"addProps":[],"addRequestProps":[{"el":"newUserFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[2].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.newFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.category.newCatFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[1].property"},"removedEnums":false,"typeChange":false}],"addResponses":{},"changedParameter":[],"changedProps":[],"changedRequestProps":[],"changedResponses":[],"diff":true,"diffConsumes":false,"diffParam":false,"diffProduces":false,"diffProp":false,"diffRequestProp":true,"missingConsumes":[],"missingParameters":[],"missingProduces":[],"missingProps":[],"missingRequestProps":[{"el":"phone","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.category.name","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.tags.removedField","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"missingResponses":{},"summary":"Creates list of users with given input array"}},"diff":true,"missingOperations":{},"newOperations":{},"pathUrl":"/user/createWithArray"},{"changedOperations":{"POST":{"addConsumes":[],"addParameters":[],"addProduces":[],"addProps":[],"addRequestProps":[{"el":"newUserFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[2].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.newFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.category.newCatFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[1].property"},"removedEnums":false,"typeChange":false}],"addResponses":{},"changedParameter":[],"changedProps":[],"changedRequestProps":[],"changedResponses":[],"diff":true,"diffConsumes":false,"diffParam":false,"diffProduces":false,"diffProp":false,"diffRequestProp":true,"missingConsumes":[],"missingParameters":[],"missingProduces":[],"missingProps":[],"missingRequestProps":[{"el":"phone","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.category.name","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.tags.removedField","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"missingResponses":{},"summary":"Creates list of users with given input array"}},"diff":true,"missingOperations":{},"newOperations":{},"pathUrl":"/user/createWithList"},{"changedOperations":{"GET":{"addConsumes":[],"addParameters":[],"addProduces":[],"addProps":[],"addRequestProps":[],"addResponses":{},"changedParameter":[],"changedProps":[],"changedRequestProps":[],"changedResponses":[],"diff":true,"diffConsumes":false,"diffParam":true,"diffProduces":false,"diffProp":false,"diffRequestProp":false,"missingConsumes":[],"missingParameters":[{"description":"The password for login in clear text","extensions":{},"in":"query","name":"password","required":true,"schema":{"exampleSetFlag":false,"extensions":{"$ref":"$.changedEndpoints[10].changedOperations.GET.missingParameters[0].extensions"},"specVersion":"V30","type":"string","types":["string"]}}],"missingProduces":[],"missingProps":[],"missingRequestProps":[],"missingResponses":{},"summary":"Logs user into the system"}},"diff":true,"missingOperations":{},"newOperations":{},"pathUrl":"/user/login"},{"changedOperations":{"GET":{"addConsumes":[],"addParameters":[],"addProduces":[],"addProps":[{"el":"newUserFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[2].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.newFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.category.newCatFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[1].property"},"removedEnums":false,"typeChange":false}],"addRequestProps":[],"addResponses":{},"changedParameter":[{"changeDescription":true,"changeRequired":false,"changed":[{"el":"username","newEnums":false,"property":{"exampleSetFlag":false,"extensions":{},"format":"int32","specVersion":"V30","type":"integer","types":["integer"]},"removedEnums":false,"typeChange":false}],"diff":true,"increased":[],"leftParameter":{"description":"The name that needs to be fetched. Use user1 for testing. ","extensions":{},"in":"path","name":"username","required":true,"schema":{"exampleSetFlag":false,"extensions":{"$ref":"$.changedEndpoints[11].changedOperations.GET.changedParameter[0].leftParameter.extensions"},"specVersion":"V30","type":"string","types":["string"]}},"missing":[],"rightParameter":{"description":"The name that needs to be fetched. Use user1 for testing. edited","extensions":{"$ref":"$.changedEndpoints[11].changedOperations.GET.changedParameter[0].changed[0].property.extensions"},"in":"path","name":"username","required":true,"schema":{"$ref":"$.changedEndpoints[11].changedOperations.GET.changedParameter[0].changed[0].property"}}}],"changedProps":[],"changedRequestProps":[],"changedResponses":[{"addContentTypes":[],"addHeaders":{},"addProps":[{"el":"newUserFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[2].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.newFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.category.newCatFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[1].property"},"removedEnums":false,"typeChange":false}],"changedHeaders":[],"changedProps":[],"contentTypeChanged":false,"descriptionChanged":false,"diff":true,"headersChanged":false,"missingContentTypes":[],"missingHeaders":{},"missingProps":[{"el":"phone","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.category.name","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.tags.removedField","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"newDescription":"successful operation","oldDescription":"successful operation","schemaChanged":true,"statusCode":"200"}],"diff":true,"diffConsumes":false,"diffParam":true,"diffProduces":false,"diffProp":true,"diffRequestProp":false,"missingConsumes":[],"missingParameters":[],"missingProduces":[],"missingProps":[{"el":"phone","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.category.name","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.tags.removedField","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"missingRequestProps":[],"missingResponses":{},"summary":"Get user by user name"},"PUT":{"addConsumes":[],"addParameters":[],"addProduces":[],"addProps":[],"addRequestProps":[{"el":"newUserFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[2].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.newFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.category.newCatFeild","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.addRequestProps[1].property"},"removedEnums":false,"typeChange":false}],"addResponses":{},"changedParameter":[],"changedProps":[],"changedRequestProps":[],"changedResponses":[],"diff":true,"diffConsumes":false,"diffParam":false,"diffProduces":false,"diffProp":false,"diffRequestProp":true,"missingConsumes":[],"missingParameters":[],"missingProduces":[],"missingProps":[],"missingRequestProps":[{"el":"phone","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[1].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.category.name","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[0].property"},"removedEnums":false,"typeChange":false},{"el":"favorite.tags.removedField","newEnums":false,"property":{"$ref":"$.changedEndpoints[0].changedOperations.PUT.missingRequestProps[2].property"},"removedEnums":false,"typeChange":false}],"missingResponses":{},"summary":"Updated user"}},"diff":true,"missingOperations":{},"newOperations":{},"pathUrl":"/user/{username}"}],"missingEndpoints":[{"method":"POST","operation":{"$ref":"$.changedEndpoints[3].missingOperations.POST"},"pathUrl":"/pet/{petId}","summary":"Updates a pet in the store with form data"}],"newEndpoints":[{"method":"GET","operation":{"$ref":"$.changedEndpoints[3].newOperations.GET"},"pathUrl":"/pet/{petId}","summary":"Find pet by ID"}],"newVersion":"1.0.2","oldVersion":"1.0.0"} \ No newline at end of file From daf1f8a9d65f2a0eddc7f9799159d716ca93b27f Mon Sep 17 00:00:00 2001 From: Francesco Panico Date: Wed, 1 Jul 2026 15:28:29 +0200 Subject: [PATCH 6/8] Incremento versione e aggiornamento documentazione --- README.md | 239 ++++++++++++++++++++++++++++++++++-------------------- pom.xml | 2 +- 2 files changed, 154 insertions(+), 87 deletions(-) diff --git a/README.md b/README.md index 9bfd6261..29e8ca2d 100644 --- a/README.md +++ b/README.md @@ -1,97 +1,164 @@ -# swagger-diff - -## Utilizzo +## swagger-diff + +![Build Status](https://travis-ci.org/Sayi/swagger-diff.svg?branch=master) ![jdk1.8+](https://img.shields.io/badge/jdk-1.8%2B-orange.svg) [![Coverage Status](https://coveralls.io/repos/github/Sayi/swagger-diff/badge.svg)](https://coveralls.io/github/Sayi/swagger-diff) [![Maven](https://maven-badges.herokuapp.com/maven-central/com.deepoove/swagger-diff/badge.svg?style=plastic)](https://maven-badges.herokuapp.com/maven-central/com.deepoove/swagger-diff) + +Compare two swagger/openAPI API specifications(1.x or v2.0 or openAPI 3.0.x) and render the difference to html file or markdown file. + +## :black_large_square: Command line interface (CLI) + +```shell +$ java -jar swagger-diff.jar --help +Usage: java -jar swagger-diff.jar [options] + Options: + * -old + old api-doc location:Json file path or Http url + * -new + new api-doc location:Json file path or Http url + -v + swagger version:1.0 or 2.0 or 3.0 + Default: 2.0 + -output-mode + render mode: markdown or html + Default: markdown + --help + + --version + swagger-diff tool version ``` - mvn clean compile assembly:single - java -jar swagger-diff-1.2.2-jar-with-dependencies.jar -old File.yaml -new fileNuovo.yaml -v 2.0 -output-mode html > diff.md +Here is one command-line example(`-old` and `-new` is required, `-v` and `-output-mode` is optional): +```shell +java -jar swagger-diff.jar \ +-old http://petstore.swagger.io/v2/swagger.json \ +-new http://petstore.swagger.io/v2/swagger.json \ +-v 2.0 \ +-output-mode html > diff.html ``` - -## Getting started - -To make it easy for you to get started with GitLab, here's a list of recommended next steps. - -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! - -## Add your files - -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command: - +Download the fatJar or view the changelog on the **[Release Page](https://github.com/Sayi/swagger-diff/releases),** and thanks to all contributors. + +## Feature +* Supports swagger spec v1.x and v2.0. +* Depth comparison of parameters, responses, notes, http method(GET,POST,PUT,DELETE...) +* Supports swagger api Authorization +* Render difference of property with Expression Language +* html & markdown render +* Command line interface + +## Maven +```xml + + com.deepoove + swagger-diff + 1.3.0 + ``` -cd existing_repo -git remote add origin https://git.imolinfo.it/bancoBPM/swagger-diff.git -git branch -M develop -git push -uf origin develop -``` - -## Integrate with your tools - -- [ ] [Set up project integrations](https://git.imolinfo.it/bancoBPM/swagger-diff/-/settings/integrations) - -## Collaborate with your team - -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/) - -## Test and Deploy - -Use the built-in continuous integration in GitLab. - -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) - -*** - -# Editing this README - -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template. -## Suggestions for a good README - -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. - -## Name -Choose a self-explaining name for your project. - -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. - -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. - -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. - -## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. +## Gradle +```shell +compile group: 'com.deepoove', name: 'swagger-diff', version: '1.2.2' +``` ## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. - -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. - -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. - -## Contributing -State if you are open to contributions and what your requirements are for accepting them. +SwaggerDiff can read swagger api spec from json file or http. +```java +SwaggerDiff diff = SwaggerDiff.compareV2("petstore_v2_1.json", "http://petstore.swagger.io/v2/swagger.json"); +``` +## Swagger version +v1.x +```java +SwaggerDiff.compareV1("petstore_v1_1.json", "petstore_v1_2.json"); +``` -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. +v2.0 +```java +SwaggerDiff.compareV2("petstore_v2_1.json", "petstore_v2_2.json"); +``` -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. +openAPI 3.0.x +```java +SwaggerDiff.compareV3("petstore_v3_1.json", "petstore_v3_2.json"); +``` -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. +## Render difference +#### HTML +```java +String html = new HtmlRender("Changelog", + "http://deepoove.com/swagger-diff/stylesheets/demo.css") + .render(diff); + +try { + FileWriter fw = new FileWriter("testNewApi.html"); + fw.write(html); + fw.close(); +} catch (IOException e) { + e.printStackTrace(); +} +``` +![image](./changelog.png) + +#### Markdown +```java +String render = new MarkdownRender().render(diff); +try { + FileWriter fw = new FileWriter("testDiff.md"); + fw.write(render); + fw.close(); +} catch (IOException e) { + e.printStackTrace(); +} +``` +```markdown +### What's New +--- +* `GET` /pet/{petId} Find pet by ID + +### What's Deprecated +--- +* `POST` /pet/{petId} Updates a pet in the store with form data + +### What's Changed +--- +* `PUT` /pet Update an existing pet + Parameter + + Add body.newFeild //a feild demo by sayi + Add body.category.newCatFeild + Delete body.category.name +* `POST` /pet Add a new pet to the store + Parameter + + Add tags //add new query param demo + Add body.newFeild //a feild demo by sayi + Add body.category.newCatFeild + Delete body.category.name +* `DELETE` /pet/{petId} Deletes a pet + Parameter + + Add newHeaderParam +* `POST` /pet/{petId}/uploadImage uploads an image for pet + Parameter + + petId change into not required Notes ID of pet to update change into ID of pet to update, default false +* `POST` /user Create user + Parameter + + Add body.newUserFeild //a new user feild demo + Delete body.phone +* `GET` /user/login Logs user into the system + Parameter + + Delete password //The password for login in clear text +* `GET` /user/{username} Get user by user name + Return Type + + Add newUserFeild //a new user feild demo + Delete phone +* `PUT` /user/{username} Updated user + Parameter + + Add body.newUserFeild //a new user feild demo + Delete body.phone -## License -For open source projects, say how it is licensed. +``` -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. +## How it works +![image](./swagger-diff.png) \ No newline at end of file diff --git a/pom.xml b/pom.xml index b1075187..ebd917dc 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.deepoove swagger-diff - 1.2.2 + 1.3.0 jar swagger-diff From e5d1b05838a83aa9d1953ac93b1fec966b3a0e6c Mon Sep 17 00:00:00 2001 From: Francesco Panico Date: Wed, 1 Jul 2026 15:33:58 +0200 Subject: [PATCH 7/8] Rimosso esempio poco significativo --- Example/paymentServices/diff.html | 1 - .../paymentServices/paymentServicesNew.json | 1924 ----------------- .../paymentServices/paymentServicesOld.json | 1922 ---------------- 3 files changed, 3847 deletions(-) delete mode 100644 Example/paymentServices/diff.html delete mode 100644 Example/paymentServices/paymentServicesNew.json delete mode 100644 Example/paymentServices/paymentServicesOld.json diff --git a/Example/paymentServices/diff.html b/Example/paymentServices/diff.html deleted file mode 100644 index b60f5a9e..00000000 --- a/Example/paymentServices/diff.html +++ /dev/null @@ -1 +0,0 @@ -Changelog

        Changelog

        Versions


        Changes from 5.0.0 to 5.0.0.

        What's New


          What's Deprecated


            What's Changed


            1. POST/fraud/bulk-payments/{payment-product}/{payment-id} This API allows to confirm or overwrite the SCA exception result performed by PSD2 Gateway.
              • Return Type

                • Add currencyConversionFees//Might be used by the ASPSP to transport specific currency conversion fees related to the initiated credit transfer.
                • Add debtorName//This field must contain the “owner name” info of the debited account. The “owner name” is the name of the legal account owner. If there is more than one owner, then e.g. two names might be noted here.For a corporate account, the corporate name is used for this attribute. This enables the ASPSP to transport the account owner name to the PISP in case where the regulatory need is provided and if not provided by other means like the List of Available Accounts Service.
                • Add estimatedInterbankSettlementAmount//The estimated amount to be transferred to the payee.
                • Add estimatedTotalAmount//The amount which is estimated to be debted from the debtor account.Note: This amount includes fees.
                • Add psuMessage//If the consumer is fraudster, the filed will be populated the specific error message
                • Add transactionFeeIndicator//If equals “true”, the transaction will involve specific transaction cost as shown by the ASPSP in their public price list or as agreed between ASPSP and PSU. If equals 'false', the transaction will not involve additional specific transaction costs to the PSU.
                • Add transactionFees//Can be used by the ASPSP to returns transaction fees relevant for the underlying payments.
                • DeletetransactionDecisionData.currencyConversionFees//Might be used by the ASPSP to transport specific currency conversion fees related to the initiated credit transfer.
                • DeletetransactionDecisionData.debtorName//This field must contain the “owner name” info of the debited account. The “owner name” is the name of the legal account owner. If there is more than one owner, then e.g. two names might be noted here.For a corporate account, the corporate name is used for this attribute. This enables the ASPSP to transport the account owner name to the PISP in case where the regulatory need is provided and if not provided by other means like the List of Available Accounts Service.
                • DeletetransactionDecisionData.estimatedInterbankSettlementAmount//The estimated amount to be transferred to the payee.
                • DeletetransactionDecisionData.estimatedTotalAmount//The amount which is estimated to be debted from the debtor account.Note: This amount includes fees.
                • DeletetransactionDecisionData.psuMessage//If the consumer is fraudster, the filed will be populated the specific error message
                • DeletetransactionDecisionData.transactionFeeIndicator//If equals “true”, the transaction will involve specific transaction cost as shown by the ASPSP in their public price list or as agreed between ASPSP and PSU. If equals 'false', the transaction will not involve additional specific transaction costs to the PSU.
                • DeletetransactionDecisionData.transactionFees//Can be used by the ASPSP to returns transaction fees relevant for the underlying payments.
              • Responses

                • Response 200
                  • Add currencyConversionFees//Might be used by the ASPSP to transport specific currency conversion fees related to the initiated credit transfer.
                  • Add debtorName//This field must contain the “owner name” info of the debited account. The “owner name” is the name of the legal account owner. If there is more than one owner, then e.g. two names might be noted here.For a corporate account, the corporate name is used for this attribute. This enables the ASPSP to transport the account owner name to the PISP in case where the regulatory need is provided and if not provided by other means like the List of Available Accounts Service.
                  • Add estimatedInterbankSettlementAmount//The estimated amount to be transferred to the payee.
                  • Add estimatedTotalAmount//The amount which is estimated to be debted from the debtor account.Note: This amount includes fees.
                  • Add psuMessage//If the consumer is fraudster, the filed will be populated the specific error message
                  • Add transactionFeeIndicator//If equals “true”, the transaction will involve specific transaction cost as shown by the ASPSP in their public price list or as agreed between ASPSP and PSU. If equals 'false', the transaction will not involve additional specific transaction costs to the PSU.
                  • Add transactionFees//Can be used by the ASPSP to returns transaction fees relevant for the underlying payments.
                  • DeletetransactionDecisionData.currencyConversionFees//Might be used by the ASPSP to transport specific currency conversion fees related to the initiated credit transfer.
                  • DeletetransactionDecisionData.debtorName//This field must contain the “owner name” info of the debited account. The “owner name” is the name of the legal account owner. If there is more than one owner, then e.g. two names might be noted here.For a corporate account, the corporate name is used for this attribute. This enables the ASPSP to transport the account owner name to the PISP in case where the regulatory need is provided and if not provided by other means like the List of Available Accounts Service.
                  • DeletetransactionDecisionData.estimatedInterbankSettlementAmount//The estimated amount to be transferred to the payee.
                  • DeletetransactionDecisionData.estimatedTotalAmount//The amount which is estimated to be debted from the debtor account.Note: This amount includes fees.
                  • DeletetransactionDecisionData.psuMessage//If the consumer is fraudster, the filed will be populated the specific error message
                  • DeletetransactionDecisionData.transactionFeeIndicator//If equals “true”, the transaction will involve specific transaction cost as shown by the ASPSP in their public price list or as agreed between ASPSP and PSU. If equals 'false', the transaction will not involve additional specific transaction costs to the PSU.
                  • DeletetransactionDecisionData.transactionFees//Can be used by the ASPSP to returns transaction fees relevant for the underlying payments.
            diff --git a/Example/paymentServices/paymentServicesNew.json b/Example/paymentServices/paymentServicesNew.json deleted file mode 100644 index bddab59e..00000000 --- a/Example/paymentServices/paymentServicesNew.json +++ /dev/null @@ -1,1924 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "description": "In this section are described the interfaces exposed by ASPSP to manage bulk payment and subresource transactions", - "title": "paymentServices", - "version": "5.0.0" - }, - "paths": { - "/auth/sca/{payment-id}/authorisations/{authorisation-id}": { - "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "parameters": [ - { - "description": "This field indicates the authorization purpose.The allowed values are:AUTHCANC", - "in": "header", - "name": "authorization-purpose", - "required": true, - "type": "string" - }, - { - "description": "The identification of the PSU in the ASPSP client interface.", - "in": "header", - "name": "psu-id", - "type": "string" - }, - { - "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", - "in": "header", - "name": "psu-id-type", - "type": "string" - }, - { - "description": "Identification of a Corporate, only used in a corporate context", - "in": "header", - "name": "psu-corporate-id", - "type": "string" - }, - { - "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", - "in": "header", - "name": "psu-corporate-id-type", - "type": "string" - }, - { - "description": "A unique registration number for TPP identification", - "in": "header", - "name": "tpp-registration-number", - "required": true, - "type": "string" - }, - { - "description": "The TPP name", - "in": "header", - "name": "tpp-name", - "required": true, - "type": "string" - }, - { - "description": "URI of the TPP, where the transaction flow shall be redirected to after a Redirect. Mandatory for redirect or OAuth SCA Approach ", - "in": "header", - "name": "tpp-redirect-uri", - "type": "string" - }, - { - "description": "If this URI is contained, the TPP is asking to redirect the transaction flow to this address instead of the TPP-Redirect-URI in case of a negative result of the redirect SCA method. This might be ignored by the ASPSP. ", - "in": "header", - "name": "tpp-nok-redirect-uri", - "type": "string" - }, - { - "description": "The identification of the ASPSP (for example ABI)", - "in": "header", - "name": "aspsp-code", - "required": true, - "type": "string" - }, - { - "description": "Identifier of the product in ASPSP scope.", - "in": "header", - "name": "aspsp-product-code", - "required": true, - "type": "string" - }, - { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "in": "header", - "name": "request-id", - "required": true, - "type": "string" - }, - { - "description": "The value list of products supported is:- sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-cross-border-credit-transfers", - "in": "header", - "name": "payment-product", - "type": "string" - }, - { - "description": "A session token generated by the ASPSP to ensure that an authentication session is maintained, in order to avoid re-entering client username and password (SFA) during the execution of the SCA", - "in": "header", - "name": "aspsp-authentication-session-id", - "type": "string" - }, - { - "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", - "in": "header", - "name": "Date", - "required": true, - "type": "string" - }, - { - "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", - "in": "path", - "name": "payment-id", - "required": true, - "type": "string" - }, - { - "description": "Resource identification of the related Payment Cancellation authorisation sub-resource or bulk authorisation sub-resource assigned to the created resource.", - "in": "path", - "name": "authorisation-id", - "required": true, - "type": "string" - }, - { - "description": "PaymentAuthorizationResourceScaInitiationRestRequest", - "in": "body", - "name": "body", - "schema": { - "$ref": "#/definitions/PaymentAuthorizationResourceScaInitiationRestRequest" - } - } - ], - "responses": { - "200": { - "description": "Service executed successfully", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/PaymentAuthorizationResourceScaInitiationRestResponse" - } - }, - "400": { - "description": "

            AUTH.0003

            Invalid parameter: {field name}

            AUTH.0004

            Missing parameter: {field name}

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "401": { - "description": "

            AUTH.0009

            PSU suspended or blocked

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "403": { - "description": "

            AUTH.0029

            ASPSP Default Error (Note: Error Description will be fill by ASPSP)

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "404": { - "description": "

            AUTH.0007

            Unknown PSU

            AUTH.0008

            Unknown ASPSP code

            PAY.0012

            Unknown Payment Identifier

            AUTH.0019

            Unsupported SCA approach

            AUTH.0027

            Unknown SCA method

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "409": { - "description": "

            AUTH.0002

            Operation not allowed

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "500": { - "description": "

            AUTH.0001

            Generic error

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - } - }, - "security": [ - { - "psd2_auth": [] - } - ], - "tags": [ - "paymentAuthorizationResourceScaInitiation" - ], - "operationId": "paymentAuthorizationResourceScaInitiation", - "summary": "This API allows to start a SCA process at ASPSP side." - }, - "put": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "parameters": [ - { - "description": "This field indicates the authorization purpose.The allowed values are:AUTHCANC", - "in": "header", - "name": "authorization-purpose", - "required": true, - "type": "string" - }, - { - "description": "A unique registration number for TPP identification", - "in": "header", - "name": "tpp-registration-number", - "required": true, - "type": "string" - }, - { - "description": "The TPP name", - "in": "header", - "name": "tpp-name", - "required": true, - "type": "string" - }, - { - "description": "The identification of the ASPSP (for example ABI)", - "in": "header", - "name": "aspsp-code", - "required": true, - "type": "string" - }, - { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "in": "header", - "name": "request-id", - "required": true, - "type": "string" - }, - { - "description": "The value list of products supported is: - sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-cross-border-credit-transfers", - "in": "header", - "name": "payment-product", - "type": "string" - }, - { - "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", - "in": "header", - "name": "Date", - "required": true, - "type": "string" - }, - { - "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", - "in": "path", - "name": "payment-id", - "required": true, - "type": "string" - }, - { - "description": "Resource identification of the related Payment Cancellation authorisation sub-resource or bulk authorisation sub-resource assigned to the created resource.", - "in": "path", - "name": "authorisation-id", - "required": true, - "type": "string" - }, - { - "description": "PaymentAuthorizationScaValidationRequestRestRequest", - "in": "body", - "name": "body", - "schema": { - "$ref": "#/definitions/PaymentAuthorizationScaValidationRequestRestRequest" - } - } - ], - "responses": { - "200": { - "description": "Service executed successfully", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/PaymentAuthorizationScaValidationRequestRestResponse" - } - }, - "400": { - "description": "

            AUTH.0003

            Invalid parameter: {field name}

            AUTH.0004

            Missing parameter: {field name}

            AUTH.0030

            Invalid SCA Authentication Data

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "401": { - "description": "

            AUTH.0028

            SCA validation failed

            PAY.0018

            Insufficient funds on the account

            PAY.0021

            Status Account doesn’t allow the operation

            PAY.0022

            Account type doesn’t allow the operation.

            PAY.0023

            Transaction amount exceeds the maximum authorized amount for specific payment product

            PAY.0024

            Duplicate payment

            PAY.0025

            Transaction amount exceeds transaction limit (daily, weekly, monthly)

            PAY.0026

            Transaction amount exceeds the single transaction limit

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "403": { - "description": "

            AUTH.0029

            ASPSP Default Error (Note: Error Description will be fill by ASPSP)

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "404": { - "description": "

            AUTH.0008

            Unknown ASPSP code

            PAY.0012

            Unknown Payment Identifier

            CNS.0006

            Unknown Consent

            PAY.0020

            Unknown Debtor Account

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "409": { - "description": "

            AUTH.0002

            Operation not allowed

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "500": { - "description": "

            AUTH.0001

            Generic error

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - } - }, - "security": [ - { - "psd2_auth": [] - } - ], - "tags": [ - "paymentAuthorizationScaValidationRequest" - ], - "operationId": "paymentAuthorizationScaValidationRequest", - "summary": "This API allows to validate the authentication data generated by PSU device during SCA phase. The service is used only in the case “Embedded” SCA approach." - } - }, - "/auth/sfa/{payment-id}/authorisations/{authorisation-id}": { - "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "parameters": [ - { - "description": "This field indicates the authorization purpose.The allowed values are:AUTHCANC", - "in": "header", - "name": "authorization-purpose", - "required": true, - "type": "string" - }, - { - "description": "The identification of the PSU in the ASPSP client interface.", - "in": "header", - "name": "psu-id", - "type": "string" - }, - { - "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", - "in": "header", - "name": "psu-id-type", - "type": "string" - }, - { - "description": "Identification of a Corporate, only used in a corporate context", - "in": "header", - "name": "psu-corporate-id", - "type": "string" - }, - { - "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", - "in": "header", - "name": "psu-corporate-id-type", - "type": "string" - }, - { - "description": "A unique registration number for TPP identification", - "in": "header", - "name": "tpp-registration-number", - "required": true, - "type": "string" - }, - { - "description": "The TPP name", - "in": "header", - "name": "tpp-name", - "required": true, - "type": "string" - }, - { - "description": "The identification of the ASPSP (for example ABI)", - "in": "header", - "name": "aspsp-code", - "required": true, - "type": "string" - }, - { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "in": "header", - "name": "request-id", - "required": true, - "type": "string" - }, - { - "description": "The value list of products supported is:- sepa-credit-transfers- instant-sepa-credit-transfers- target-2-payments- cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-", - "in": "header", - "name": "payment-product", - "type": "string" - }, - { - "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", - "in": "header", - "name": "Date", - "required": true, - "type": "string" - }, - { - "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", - "in": "path", - "name": "payment-id", - "required": true, - "type": "string" - }, - { - "description": "Resource identification of the related Payment Cancellation authorisation sub-resource or bulk authorisation sub-resource assigned to the created resource.", - "in": "path", - "name": "authorisation-id", - "required": true, - "type": "string" - }, - { - "description": "PaymentAuthorizationPsuAuthenticationRestRequest", - "in": "body", - "name": "body", - "schema": { - "$ref": "#/definitions/PaymentAuthorizationPsuAuthenticationRestRequest" - } - } - ], - "responses": { - "200": { - "description": "Service executed successfully", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/PaymentAuthorizationPsuAuthenticationRestResponse" - } - }, - "400": { - "description": "

            AUTH.0003

            Invalid parameter: {field name}

            AUTH.0004

            Missing parameter: {field name}

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "401": { - "description": "

            AUTH.0009

            PSU suspended or blocked

            AUTH.0016

            PSU credentials invalid

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "403": { - "description": "

            AUTH.0029

            ASPSP Default Error (Note: Error Description will be fill by ASPSP)

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "404": { - "description": "

            AUTH.0007

            Unknown PSU

            AUTH.0008

            Unknown ASPSP code

            PAY.0013

            The addressed payment product is not available for the PSU.

            PAY.0014

            Unknown payment product

            PAY.0012

            Unknown Payment Identifier

            CNS.0006

            Unknown consent

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "409": { - "description": "

            AUTH.0002

            Operation not allowed

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "500": { - "description": "

            AUTH.0001

            Generic error

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - } - }, - "security": [ - { - "psd2_auth": [] - } - ], - "tags": [ - "paymentAuthorizationPsuAuthentication" - ], - "operationId": "paymentAuthorizationPsuAuthentication", - "summary": "This API manage the PSU authentication in an “embedded” way for bulk payments and cancellation requests." - } - }, - "/bulk-payments/{payment-id}/status": { - "get": { - "produces": [ - "application/json", - "application/xml" - ], - "parameters": [ - { - "description": "A unique registration number for TPP identification", - "in": "header", - "name": "tpp-registration-number", - "required": true, - "type": "string" - }, - { - "description": "The TPP name", - "in": "header", - "name": "tpp-name", - "required": true, - "type": "string" - }, - { - "description": "The identification of the ASPSP (for example ABI)", - "in": "header", - "name": "aspsp-code", - "required": true, - "type": "string" - }, - { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "in": "header", - "name": "request-id", - "required": true, - "type": "string" - }, - { - "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", - "in": "header", - "name": "Date", - "required": true, - "type": "string" - }, - { - "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", - "in": "path", - "name": "payment-id", - "required": true, - "type": "string" - } - ], - "responses": { - "200": { - "description": "Service executed successfully ", - "headers": { - "content-type": { - "description": "application/json", - "type": "string" - }, - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/GetBulkPaymentStatusRequestRestResponse" - } - }, - "400": { - "description": "

            PAY.0003

            Invalid parameter: {field name}

            PAY.0004

            Missing parameter: {field name}

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "403": { - "description": "

            PAY.0029

            ASPSP Default Error (Note: Error Description will be fill by ASPSP)

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "404": { - "description": "

            PAY.0008

            Unknown ASPSP code

            PAY.0012

            Unknown Payment Identifier

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "409": { - "description": "

            PAY.0002

            Operation not allowed

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "500": { - "description": "

            PAY.0001

            Generic error

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - } - }, - "security": [ - { - "psd2_auth": [] - } - ], - "tags": [ - "getBulkPaymentStatusRequest" - ], - "operationId": "getBulkPaymentStatusRequest", - "summary": "This API retrieve the status of a Bulk payment initiation." - } - }, - "/fraud/bulk-payments/{payment-product}/{payment-id}": { - "post": { - "consumes": [ - "application/xml" - ], - "produces": [ - "application/json" - ], - "parameters": [ - { - "description": "The Identification of the PSU in the ASPSP client interface.", - "in": "header", - "name": "psu-id", - "required": true, - "type": "string" - }, - { - "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", - "in": "header", - "name": "psu-id-type", - "type": "string" - }, - { - "description": "Identification of a Corporate, only used in a corporate context", - "in": "header", - "name": "psu-corporate-id", - "type": "string" - }, - { - "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", - "in": "header", - "name": "psu-corporate-id-type", - "type": "string" - }, - { - "description": "The forwarded Agent header field of the http request between PSU and TPP. The User-Agent request header contains a characteristic string that allows the network protocol peers to identify the application type, operating system, software vendor or software version of the requesting software user agent.", - "in": "header", - "name": "psu-user-agent", - "type": "string" - }, - { - "description": "The forwarded IP Address header field consists of the corresponding http request IP Address field between PSU and TPP.", - "in": "header", - "name": "psu-ip-address", - "required": true, - "type": "string" - }, - { - "description": "The forwarded IP Port header field consists of the corresponding HTTP request IP Port field between PSU and TPP, if available.", - "in": "header", - "name": "psu-ip-port", - "type": "string" - }, - { - "description": "The Accept request-header field can be used to specify certain media types which are acceptable for the response", - "in": "header", - "name": "psu-accept", - "type": "string" - }, - { - "description": "The charset information sent by the PSU. The Accept-Charset request-header field can be used to indicate what character sets are acceptable for the response. ", - "in": "header", - "name": "psu-accept-charset", - "type": "string" - }, - { - "description": "The encoding information sent by the PSU. The Accept-Encoding request-header field is similar to Accept but restricts the content-codings that are acceptable in the response.", - "in": "header", - "name": "psu-accept-encoding", - "type": "string" - }, - { - "description": "The language information sent by the PSU. The Accept-Language request-header field is similar to Accept, but restricts the set of natural languages that are preferred as a response to the request", - "in": "header", - "name": "psu-accept-language", - "type": "string" - }, - { - "description": "HTTP method used at the PSU – TPP interface, if available. Valid values are: - GET - POST - PUT - PATCH - DELETE", - "in": "header", - "name": "psu-http-method", - "type": "string" - }, - { - "description": "UUID (Universally Unique Identifier) for a device, which is used by the PSU, if available.UUID identifies either a device or a device dependant application installation. In case of an installation identification this ID need to be unaltered until removal from device.", - "in": "header", - "name": "psu-device-id", - "type": "string" - }, - { - "description": "The forwarded Geo Location of the corresponding http request between PSU and TPP if available.Format using [RFC 2426], i.e. GEO:,< longitude >.", - "in": "header", - "name": "psu-geo-location", - "type": "string" - }, - { - "description": "A unique registration number for TPP identification", - "in": "header", - "name": "tpp-registration-number", - "required": true, - "type": "string" - }, - { - "description": "The TPP name", - "in": "header", - "name": "tpp-name", - "required": true, - "type": "string" - }, - { - "description": "The identification of the ASPSP (for example ABI)", - "in": "header", - "name": "aspsp-code", - "required": true, - "type": "string" - }, - { - "description": "Identifier of the product in ASPSP scope.", - "in": "header", - "name": "aspsp-product-code", - "required": true, - "type": "string" - }, - { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "in": "header", - "name": "request-id", - "required": true, - "type": "string" - }, - { - "description": "The number of bits used to display one color.The possible values are: 32, 24, 16, or 8", - "in": "header", - "name": "screen-color-depth", - "type": "string" - }, - { - "description": "Width of the user's screen Note For iOS, the resolution measurement is in points. For other operating systems, the resolution measurement is in pixels.", - "in": "header", - "name": "screen-width", - "type": "string" - }, - { - "description": "Height of the user’s screen Note For iOS, the resolution measurement is in points. For other operating systems, the resolution measurement is in pixels.", - "in": "header", - "name": "screen-height", - "type": "string" - }, - { - "description": "Vertical space of the user’s screen. Note For iOS, the resolution measurement is in points. For other operating systems, the resolution measurement is in pixels.", - "in": "header", - "name": "screen-vertical-space", - "type": "string" - }, - { - "description": "The software plug-ins installed in the user’s browser.", - "in": "header", - "name": "software-plug-ins", - "type": "string" - }, - { - "description": "The user’s current time zone, related to UTC (for example UTC+01:00)", - "in": "header", - "name": "time-zone", - "type": "string" - }, - { - "description": "The language that the user has set in the browser ", - "in": "header", - "name": "browser-language", - "type": "string" - }, - { - "description": "A Boolean value that indicates whether Java is enabled in the browserOnly “true” or “false” value is accepted.", - "in": "header", - "name": "java-support", - "type": "string" - }, - { - "description": "A Boolean value that indicates whether cookies are enabled in the user’s browserOnly “true” or “false” value is accepted.", - "in": "header", - "name": "psu-cookie-support", - "type": "string" - }, - { - "description": "The operating system installed. ", - "in": "header", - "name": "device-os", - "type": "string" - }, - { - "description": "The operating system version installed", - "in": "header", - "name": "device-os-version", - "type": "string" - }, - { - "description": "The major version of the browser.", - "in": "header", - "name": "major-version", - "type": "string" - }, - { - "description": "The browser being used. Possible values are: Netscape, Mozilla, Explorer, Camino, Firefox, Konqueror, iCab, Opera, Safari, OmniWeb, Chrome.", - "in": "header", - "name": "browser-type", - "type": "string" - }, - { - "description": "Different identifiers are retrieved for each of the operating systems: -iOS 4.x-6.x The Wi-Fi MAC address. -iOS 7.x and later The identifierFor Vendor property of the UIDevice class. -Android The Internationa l Mobile Equipment Identity (IMEI) for GSM.", - "in": "header", - "name": "hardware-id", - "type": "string" - }, - { - "description": "A positive value indicates that the device is rooted or jailbroken.Only “true” or “false” value is accepted.", - "in": "header", - "name": "device-rooted", - "type": "string" - }, - { - "description": "A positive value indicates that the client device is an emulator.Only “true” or “false” value is accepted.", - "in": "header", - "name": "emulator", - "type": "string" - }, - { - "description": "The client application creates and saves a random unique identifier, which the client application can read. This enables verification that the application is genuine and not malicious malware. Note: For iOS system, the value is permanently stored in the keychain. For Android system the value is stored in the private storage of the application. This value is only stored until the application is uninstalled.", - "in": "header", - "name": "rsa-application-key", - "type": "string" - }, - { - "description": "The currently installed RSA Adaptive Authentication Mobile SDK Modules version and build number.", - "in": "header", - "name": "sdk-version", - "type": "string" - }, - { - "description": "The Date general-header field represents the date and time at which the message was originated.  Format: EEE, dd MMM yyyy hh:mm:ss z", - "in": "header", - "name": "Date", - "type": "string" - }, - { - "description": "The model of the mobile device.", - "in": "header", - "name": "device-model", - "type": "string" - }, - { - "description": "The mobile device name defined by the end user. Note In Android, this device element is returned based on the name defined in the Bluetooth settings.", - "in": "header", - "name": "device-name", - "type": "string" - }, - { - "description": "The language displayed in the mobile device.", - "in": "header", - "name": "languages", - "type": "string" - }, - { - "description": "Indicates whether or not the mobile device supports multitasking.Only “true” or “false” value is accepted.", - "in": "header", - "name": "multitasking-supported", - "type": "string" - }, - { - "description": "A GSM Cell ID (CID) is a unique number used to identify each base transceiver station (BTS) or sector of a BTS within a location area code (LAC) or GSM network. Note This device element is not supported by iOS. ", - "in": "header", - "name": "cell-tower-id", - "type": "string" - }, - { - "description": "The height of the mobile device above the ellipsoid. This device element is measured in meters.", - "in": "header", - "name": "geolocation-altitude", - "type": "string" - }, - { - "description": "The accuracy of the mobile device’s altitude. This device element is returned in meters.", - "in": "header", - "name": "geolocation-altitude-accuracy", - "type": "string" - }, - { - "description": "The direction of travel of the mobile device. This device element is returned in degrees.", - "in": "header", - "name": "geolocation-heading", - "type": "string" - }, - { - "description": "The radius of uncertainty for the geo-location of the mobile device. This device element is measured in meters. A negative value indicates that the geo-location latitude or longitude of the mobile device is invalid.", - "in": "header", - "name": "geolocation-horizontal-accuracy", - "type": "string" - }, - { - "description": "The current ground speed of the mobile device. This device element is returned in meters per second.", - "in": "header", - "name": "geolocation-speed", - "type": "string" - }, - { - "description": "There are five possible status codes:0=success The geolocation is successfully retrieved. 1=deny The end user denies location collection. 2=location status not available. The geolocation position is unavailable. 3=location status timeout The geolocation is timed out. 4=location status not supported The geolocation collection is not supported.", - "in": "header", - "name": "geolocation-status", - "type": "string" - }, - { - "description": "The time that the geo-location was created. This device element is returned in milliseconds.", - "in": "header", - "name": "geolocation-timestamp", - "type": "string" - }, - { - "description": "The local area code. Note For Android, this device element is only available for GSM devices and does not support CDMA devices. Note This device element is not supported by iOS.", - "in": "header", - "name": "location-area-code", - "type": "string" - }, - { - "description": "The Wi-Fi card MAC address. Note This device element is mandatory for iOS versions 4.x– 6.x.", - "in": "header", - "name": "wifi-mac-address", - "type": "string" - }, - { - "description": "The country code of the mobile device.", - "in": "header", - "name": "MCC", - "type": "string" - }, - { - "description": "The mobile carrier code.", - "in": "header", - "name": "MNC", - "type": "string" - }, - { - "description": "The basic service set identification (BSSID) for each basic service set. ", - "in": "header", - "name": "wifi-networks-data-bssid", - "type": "string" - }, - { - "description": "The wireless signal strength in the database management system expressed in decibel/meters For example -40 dBmNote This device element is not supported by iOS.", - "in": "header", - "name": "wifi-networks-data-signal-strength", - "type": "string" - }, - { - "description": "The Service Set Identifier (SSID). (the network name)", - "in": "header", - "name": "wifi-networks-data-ssid", - "type": "string" - }, - { - "description": "Define the channel used from PSU in order to send the request to TPP (WEB or APP) ", - "in": "header", - "name": "channel", - "type": "string" - }, - { - "description": "The operating system identification:- iOS: Universally Unique Identifier (UUID) (in this case it is length 36 characters)-Android: The client application creates a random unique identifier that permanently persists in the keychain (Android_ID) (in this case it is length 16 characters)", - "in": "header", - "name": "os-id", - "type": "string" - }, - { - "description": "Mobile Station International Subscriber Directory Number (MSISDN).", - "in": "header", - "name": "phone-number", - "type": "string" - }, - { - "description": "The International Mobile Subscriber Identity (IMSI)", - "in": "header", - "name": "sim-id", - "type": "string" - }, - { - "description": "The addressed payment product endpoint.The value list of products supported is: - sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers ", - "in": "path", - "name": "payment-product", - "required": true, - "type": "string" - }, - { - "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", - "in": "path", - "name": "payment-id", - "required": true, - "type": "string" - }, - { - "description": "TransactionDecisionDelegationForBulkRestRequest", - "in": "body", - "name": "body", - "schema": { - "format": "binary", - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Service executed successfully", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/TransactionDecisionDelegationForBulkRestResponse" - } - }, - "400": { - "description": "

            PAY.0003

            Invalid parameter: {field name}

            PAY.0004

            Missing parameter: {field name}

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "401": { - "description": "

            PAY.0009

            PSU suspended or blocked

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "403": { - "description": "

            PAY.0029

            ASPSP Default Error (Note: Error Description will be fill by ASPSP)

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "404": { - "description": "

            PAY.0007

            Unknown PSU

            PAY.0008

            Unknown ASPSP code

            PAY.0013

            The addressed payment product is not available for the PSU.

            PAY.0014

            Unknown Payment Product

            PAY.0012

            Unknown Payment Identifier

            PAY.0020

            Unknown Debtor Account

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "409": { - "description": "

            PAY.0002

            Operation not allowed

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "500": { - "description": "

            PAY.0001

            Generic error

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - } - }, - "security": [ - { - "psd2_auth": [] - } - ], - "tags": [ - "transactionDecisionDelegationForBulk" - ], - "operationId": "transactionDecisionDelegationForBulk", - "summary": "This API allows to confirm or overwrite the SCA exception result performed by PSD2 Gateway." - } - }, - "/{payment-service}/{payment-product}/{payment-id}": { - "delete": { - "produces": [ - "application/json" - ], - "parameters": [ - { - "description": "The identification of the PSU in the ASPSP client interface.", - "in": "header", - "name": "psu-id", - "required": true, - "type": "string" - }, - { - "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", - "in": "header", - "name": "psu-id-type", - "type": "string" - }, - { - "description": "Identification of a Corporate, only used in a corporate context", - "in": "header", - "name": "psu-corporate-id", - "type": "string" - }, - { - "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", - "in": "header", - "name": "psu-corporate-id-type", - "type": "string" - }, - { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "in": "header", - "name": "request-id", - "required": true, - "type": "string" - }, - { - "description": "The identification of the ASPSP (for example ABI)", - "in": "header", - "name": "aspsp-code", - "required": true, - "type": "string" - }, - { - "description": "Identifier of the product in ASPSP scope.", - "in": "header", - "name": "aspsp-product-code", - "required": true, - "type": "string" - }, - { - "description": "A unique registration number for TPP identification", - "in": "header", - "name": "tpp-registration-number", - "required": true, - "type": "string" - }, - { - "description": "The TPP name", - "in": "header", - "name": "tpp-name", - "required": true, - "type": "string" - }, - { - "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", - "in": "header", - "name": "Date", - "required": true, - "type": "string" - }, - { - "description": "The addressed payment service.The supported values are:paymentsperiodic-paymentsbulk-payments", - "in": "path", - "name": "payment-service", - "required": true, - "type": "string" - }, - { - "description": "The addressed payment product endpoint.The value list of products supported is: - sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-cross-border-credit-transfers ", - "in": "path", - "name": "payment-product", - "required": true, - "type": "string" - }, - { - "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", - "in": "path", - "name": "payment-id", - "required": true, - "type": "string" - } - ], - "responses": { - "202": { - "description": "ASPSP requests PSU authorization to cancel the payment", - "headers": { - "Date": { - "description": "The date provided used for the signature. Format: EEE, dd MMM yyyy hh:mm:ss z", - "type": "string" - }, - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponse202" - } - }, - "204": { - "description": "Payment successfully cancelled", - "headers": { - "Date": { - "description": "The date provided used for the signature. Format: EEE, dd MMM yyyy hh:mm:ss z", - "type": "string" - }, - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponse" - } - }, - "400": { - "description": "

            PAY.0003

            Invalid parameter: {field name}

            PAY.0004

            Missing parameter: {field name}

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - }, - "401": { - "description": "

            PAY.0009

            PSU suspended or blocked

            PAY.0021

            Status Account doesn’t allow the operation

            PAY.0022

            Account type doesn’t allow the operation.

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - }, - "403": { - "description": "

            PAY.0029

            ASPSP Default Error (Note: Error Description will be fill by ASPSP)

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - }, - "404": { - "description": "

            PAY.0008

            Unknown ASPSP code

            PAY.0013

            The addressed payment product is not available for the PSU.

            PAY.0014

            Unknown Payment Product

            PAY.0012

            Unknown Payment Identifier

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - }, - "405": { - "description": "

            PAY.0005

            The addressed payment is not cancellable e.g. due to cut off time passed or legal constraints

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - }, - "409": { - "description": "

            PAY.0002

            Operation not allowed

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - }, - "500": { - "description": "

            PAY.0001

            Generic error

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - } - }, - "security": [ - { - "psd2_auth": [] - } - ], - "tags": [ - "deletePayment" - ], - "operationId": "deletePayment", - "summary": "This API allows to execute a payment cancellation requesto towards ASPSP." - } - } - }, - "definitions": { - "ChallengeData": { - "description": "Data to generate OTP. The parameter is valorized only in the case of “EMBEDDED” SCA Approach.Object Type: Challenge Data", - "properties": { - "additionalInformation": { - "description": "Additional explanation for the PSU to explain e.g. fallback mechanism for the chosen SCA method. The TPP is obliged to show this to the PSU. ", - "type": "string" - }, - "data": { - "description": "String challenge data ", - "type": "string" - }, - "image": { - "description": "PNG data (max. 512 kilobyte) to be displayed to the PSU, Base64 encoding , cp. [RFC 4648]. This attribute is used only, when PHOTO_OTP or CHIP_OTP is the selected SCA method ", - "type": "string" - }, - "imageLink": { - "description": "A link where the ASPSP will provides the challenge image for the TPP. ", - "type": "string" - }, - "otpFormat": { - "description": "The format type of the OTP to be typed in. The admitted values are:charactersinteger.", - "type": "string" - }, - "otpMaxLength": { - "description": "The maximal length for the OTP to be typed in by the PSU. ", - "format": "int32", - "type": "integer" - } - }, - "type": "object" - }, - "CredentialsDetail": { - "description": "Credentials Details", - "properties": { - "credentialDetailId": { - "description": "Credential Detail Identification", - "type": "string" - }, - "credentialValue": { - "description": "Credential Value", - "type": "string" - } - }, - "required": [ - "credentialDetailId", - "credentialValue" - ], - "type": "object" - }, - "DeletePaymentRestResponse": { - "description": "PSD2 - delete payment rest response", - "properties": { - "paymentTransactionStatus": { - "description": "Status of the payment transaction on the bank systems. See Transaction Status", - "type": "string" - }, - "signatureData": { - "$ref": "#/definitions/SignatureData" - } - }, - "required": [ - "paymentTransactionStatus" - ], - "type": "object" - }, - "DeletePaymentRestResponseKO": { - "description": "PSD2 - delete payment rest response", - "properties": { - "errorManagement": { - "$ref": "#/definitions/ErrorManagement" - } - }, - "type": "object" - }, - "DeletePaymentRestResponse202": { - "type": "object", - "description": "PSD2 - delete payment rest response in case of http status 202", - "properties": { - "paymentTransactionStatus": { - "type": "string", - "description": "Status of the payment transaction on the bank systems. See Transaction Status" - } - }, - "required": [ - "paymentTransactionStatus" - ] - }, - "ErrorManagement": { - "properties": { - "errorCode": { - "description": "Code that identifies the error occurred", - "type": "string" - }, - "errorDescription": { - "description": "Error description", - "type": "string" - } - }, - "required": [ - "errorCode", - "errorDescription" - ], - "type": "object" - }, - "FraudScoreLevel": { - "description": "Define for each rule level the related score (this is valorized in case the fraudResult is different to 000)", - "properties": { - "levelId": { - "description": "Rule level identification", - "type": "string" - }, - "score": { - "description": "Score calculated to forehead of a violation of the rule level ", - "type": "string" - } - }, - "required": [ - "levelId", - "score" - ], - "type": "object" - }, - "GetBulkPaymentStatusRequestRestResponse": { - "description": "PSD2 Bulk - get bulk payment status request rest response", - "properties": { - "paymentTransactionStatus": { - "description": "Status of the payment transaction on the bank systems. See Transaction Status", - "type": "string" - }, - "psuMessage": { - "description": "Message to be shown to the PSU. This parameter should be used in case of multi SCA authorization. The bank will provide here the information needed to the TPP and PSU to complete the authorization of the payment.", - "type": "string" - } - }, - "type": "object" - }, - "PaymentAuthorizationPsuAuthenticationRestRequest": { - "description": "PSD2 - payment authorization psu authentication rest request", - "properties": { - "psuCredentials": { - "$ref": "#/definitions/PsuCredential" - } - }, - "required": [ - "psuCredentials" - ], - "type": "object" - }, - "PaymentAuthorizationPsuAuthenticationRestResponse": { - "description": "PSD2 - payment authorization psu authentication rest response", - "properties": { - "endUserIdentification": { - "description": "End user identification cross bank. The value is derived through function of SHA512 of the concatenation of PSU fiscal code and the following string: 57Z08PPmOedjjl4YLuRauc2nMoAckyQdZG5iSfmskX2jnO8LLO0jCOUCEVl5k5V19DD8xTwgg522trK3cx02, An example:enduserIdentification=SHA512(C.F.+ 57Z08PPmOedjjl4YLuRauc2nMoAckyQdZG5iSfmskX2jnO8LLO0jCOUCEVl5k5V19DD8xTwgg522trK3cx02If it is a corporate user the concatenation is the VAT number with the following string: njMqlpKSrwS6pObSRZgMcDVV6O2YyBujTckN1Z4gXB8FPvBQE6pYXpVZYxrckZsw4B1wCWAy7IgAi1sCtQWhzBBG7An example:enduserIdentification=SHA512(P.I. + njMqlpKSrwS6pObSRZgMcDVV6O2YyBujTckN1Z4gXB8FPvBQE6pYXpVZYxrckZsw4B1wCWAy7IgAi1sCtQWhzBBG7)", - "type": "string" - }, - "psuCorporateId": { - "description": "Identification of a Corporate, only used in a corporate context", - "type": "string" - }, - "psuCorporateIdType": { - "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", - "type": "string" - }, - "psuId": { - "description": "The identification of the PSU in the ASPSP client interface.", - "type": "string" - }, - "psuIdType": { - "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", - "type": "string" - }, - "psuMessage": { - "description": "Text to be displayed to the PSU.", - "type": "string" - }, - "psuName": { - "description": "Name of the PSU.In case of a corporate account, this might be the person acting on behalf of the corporate.", - "type": "string" - } - }, - "required": [ - "endUserIdentification", - "psuId" - ], - "type": "object" - }, - "PaymentAuthorizationResourceScaInitiationRestRequest": { - "description": "PSD2 - payment authorization resource sca initiation rest request", - "properties": { - "authorisationCallbackUrl": { - "description": "Callback partial URL (without IP and PORT) of the PSD2, where the bank notifies the SCA result. The parameter will be valorized only in the case “Redirect” or “Decoupled” approach. ", - "type": "string" - }, - "psuAlreadyAuthenticated": { - "description": "'true', if the psu has been already authenticated through the platform; 'false', otherwise.", - "type": "string" - }, - "selectedScaApproach": { - "description": "The SCA approach selected. Possible values are: EMBEDDED DECOUPLED REDIRECT OAUTH", - "type": "string" - }, - "selectedScaMethod": { - "$ref": "#/definitions/ScaMethod" - } - }, - "required": [ - "psuAlreadyAuthenticated", - "selectedScaApproach", - "selectedScaMethod" - ], - "type": "object" - }, - "PaymentAuthorizationResourceScaInitiationRestResponse": { - "description": "PSD2 - payment authorization resource sca initiation rest response", - "properties": { - "aspspScaUrl": { - "description": "URL to which the TPP must redirect the PSU to perform the SCA (it is valorized only in the case oAuth or Redirect SCA).", - "type": "string" - }, - "challengeData": { - "$ref": "#/definitions/ChallengeData" - }, - "psuMessage": { - "description": "Text to be displayed to the PSU.In the case of the Decoupled SCA approach this field will be valorized with PSU Instructions to execute.", - "type": "string" - } - }, - "type": "object" - }, - "PaymentAuthorizationScaValidationRequestRestRequest": { - "description": "PSD2 - payment authorization sca validation request rest request ", - "properties": { - "scaAuthenticationData": { - "description": "SCA authentication data, depending on the chosen authentication method. If the data is binary, then it is base64 encoded. ", - "type": "string" - } - }, - "required": [ - "scaAuthenticationData" - ], - "type": "object" - }, - "PaymentAuthorizationScaValidationRequestRestResponse": { - "description": "PSD2 - payment authorization sca validation request rest response ", - "properties": { - "paymentTransactionStatus": { - "description": "Status of the payment transaction. See Transaction Status", - "type": "string" - }, - "psuMessage": { - "description": "Text to be displayed to the PSU", - "type": "string" - }, - "signatureData": { - "$ref": "#/definitions/SignatureData" - } - }, - "type": "object" - }, - "PsuCredential": { - "description": "PSU Credentials on the Bank systemObject Type: PSU Credential", - "properties": { - "credentialsDetails": { - "description": "Credentials Details", - "items": { - "$ref": "#/definitions/CredentialsDetail" - }, - "type": "array" - }, - "productCode": { - "description": "Bank Product to which the user must authenticate. ", - "type": "string" - } - }, - "required": [ - "productCode" - ], - "type": "object" - }, - "RestHref": { - "description": "The link to the authorisation end-point, where the cancellation-authorisation sub-resource has to be generated while selecting the authentication method. This link is contained under exactly the same conditions as the data element 'scaMethods”.This link can be used in the following scenarios:The PSU ID provided during the cancellation isn’t the same that authorized the payment. The platform identifys more SCA methods applicable, so the PSU has to choise one of them to starts an explicit authorisationThe payment was SCA exempt and there are more SCA methods applicable, so the PSU has to choise one of them", - "properties": { - "href": { - "type": "string" - } - }, - "type": "object" - }, - "ScaMethod": { - "description": "The SCA Method selectedObject Type: Sca Method", - "properties": { - "authenticationMethodId": { - "description": "An identification provided by the ASPSP for the later identification of the authentication method selection.", - "type": "string" - }, - "authenticationType": { - "description": "The field describes the type of the authentication method.Example values are:SMS_OTPCHIP_OTPPHOTO_OTPPUSH_OTP", - "type": "string" - }, - "authenticationVersion": { - "description": "Depending on the “authenticationType”. This version can be used by differentiating authentication tools used within performing OTP generation in the same authentication type. This version can be referred to in the ASPSP’s documentation.", - "type": "string" - }, - "explanation": { - "description": "This is a description about the authentication method.", - "type": "string" - }, - "name": { - "description": "This could be a description provided by the ASPSP like “SMS OTP on phone +49160 xxxxx 28”.This name shall be used by the TPP when presenting a list of authentication methods to the PSU, if available.", - "type": "string" - } - }, - "required": [ - "authenticationMethodId", - "authenticationType" - ], - "type": "object" - }, - "SignatureData": { - "description": "ASPSP signature. Object Type: Signature Data", - "properties": { - "aspspCertificate": { - "description": "The APSPS certificate used to verify the signature", - "type": "string" - }, - "digest": { - "description": "The field is hash concatenation of the parameters which represents the payment. It could include the following parameters (to be defined with banks) paymentIdpaymentTransactionStatusDate (one received in input header)All fields are separated by pipe eg:SHA512(paymentId|paymentTransactionStatus|Date)", - "type": "string" - }, - "digitalSignature": { - "description": "The signature of the HASH by the ASPSP through its own encryption key", - "type": "string" - } - }, - "required": [ - "aspspCertificate", - "digest", - "digitalSignature" - ], - "type": "object" - }, - "ErrorManagementWrapper": { - "description": "", - "properties": { - "errorManagement": { - "$ref": "#/definitions/ErrorManagement" - } - } - }, - "TransactionDecisionData": { - "description": "Details on analysis performed from ASPSP systemObject Type: Transaction Decision Data", - "properties": { - - "fraudResult": { - "description": "Overall outcome assigned by the ASPSP system.The transaction is granted if the value is between 000 – 099 while will be denied (and consequently the flow interrupted) if the value is >= 100 (100 included)", - "type": "string" - }, - "fraudScoreLevel": { - "description": "Define for each rule level the related score (this is valorized in case the fraudResult is different to 000)", - "items": { - "$ref": "#/definitions/FraudScoreLevel" - }, - "type": "array" - } - }, - "required": [ - "fraudResult" - ], - "type": "object" - }, - "TransactionDecisionDelegationForBulkRestResponse": { - "description": "PSD2 - transaction decision delegation for bulk rest response", - "properties": { - "transactionDecisionData": { - "$ref": "#/definitions/TransactionDecisionData" - }, - "currencyConversionFees": { - "description": "Might be used by the ASPSP to transport specific currency conversion fees related to the initiated credit transfer.", - "type": "string" - }, - "debtorName": { - "description": "This field must contain the “owner name” info of the debited account. The “owner name” is the name of the legal account owner. If there is more than one owner, then e.g. two names might be noted here.For a corporate account, the corporate name is used for this attribute. This enables the ASPSP to transport the account owner name to the PISP in case where the regulatory need is provided and if not provided by other means like the List of Available Accounts Service.", - "type": "string" - }, - "estimatedInterbankSettlementAmount": { - "description": "The estimated amount to be transferred to the payee.", - "type": "string" - }, - "estimatedTotalAmount": { - "description": "The amount which is estimated to be debted from the debtor account.Note: This amount includes fees.", - "type": "string" - }, - "psuMessage": { - "description": "If the consumer is fraudster, the filed will be populated the specific error message", - "type": "string" - }, - "transactionFeeIndicator": { - "description": "If equals “true”, the transaction will involve specific transaction cost as shown by the ASPSP in their public price list or as agreed between ASPSP and PSU. If equals 'false', the transaction will not involve additional specific transaction costs to the PSU. ", - "type": "string" - }, - "transactionFees": { - "$ref": "#/definitions/TransactionFee" - } - - }, - "required": [ - "transactionDecisionData" - ], - "type": "object" - }, - "TransactionFee": { - "description": "Can be used by the ASPSP to returns transaction fees relevant for the underlying payments. ", - "properties": { - "amount": { - "description": "The amount given with fractional digits, where fractions must be compliant to the currency definition. Up to 14 significant figures. Negative amounts are signed by minus. The decimal separator is a dot. Example: Valid representations for EUR with up to two decimals are: • 1056 • 5768.2 • -1.50• 5877.78", - "type": "string" - }, - "currency": { - "description": "Define the code of a currency, three letters for the country. (CurrencyCode ISO 20022)", - "type": "string" - } - }, - "required": [ - "currency","amount" - ], - "type": "object" - } - }, - "securityDefinitions": { - "psd2_auth": { - "flow": "application", - "scopes": { - "production": "manage psd2 orchestrator authorization flow" - }, - "tokenUrl": "https://cbiglobeopenbankingapigateway.nexi.it/auth/oauth/v2/token", - "type": "oauth2" - } - }, - "x-components": {} -} \ No newline at end of file diff --git a/Example/paymentServices/paymentServicesOld.json b/Example/paymentServices/paymentServicesOld.json deleted file mode 100644 index 730cbf9c..00000000 --- a/Example/paymentServices/paymentServicesOld.json +++ /dev/null @@ -1,1922 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "description": "In this section are described the interfaces exposed by ASPSP to manage bulk payment and subresource transactions", - "title": "paymentServices", - "version": "5.0.0" - }, - "paths": { - "/auth/sca/{payment-id}/authorisations/{authorisation-id}": { - "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "parameters": [ - { - "description": "This field indicates the authorization purpose.The allowed values are:AUTHCANC", - "in": "header", - "name": "authorization-purpose", - "required": true, - "type": "string" - }, - { - "description": "The identification of the PSU in the ASPSP client interface.", - "in": "header", - "name": "psu-id", - "type": "string" - }, - { - "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", - "in": "header", - "name": "psu-id-type", - "type": "string" - }, - { - "description": "Identification of a Corporate, only used in a corporate context", - "in": "header", - "name": "psu-corporate-id", - "type": "string" - }, - { - "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", - "in": "header", - "name": "psu-corporate-id-type", - "type": "string" - }, - { - "description": "A unique registration number for TPP identification", - "in": "header", - "name": "tpp-registration-number", - "required": true, - "type": "string" - }, - { - "description": "The TPP name", - "in": "header", - "name": "tpp-name", - "required": true, - "type": "string" - }, - { - "description": "URI of the TPP, where the transaction flow shall be redirected to after a Redirect. Mandatory for redirect or OAuth SCA Approach ", - "in": "header", - "name": "tpp-redirect-uri", - "type": "string" - }, - { - "description": "If this URI is contained, the TPP is asking to redirect the transaction flow to this address instead of the TPP-Redirect-URI in case of a negative result of the redirect SCA method. This might be ignored by the ASPSP. ", - "in": "header", - "name": "tpp-nok-redirect-uri", - "type": "string" - }, - { - "description": "The identification of the ASPSP (for example ABI)", - "in": "header", - "name": "aspsp-code", - "required": true, - "type": "string" - }, - { - "description": "Identifier of the product in ASPSP scope.", - "in": "header", - "name": "aspsp-product-code", - "required": true, - "type": "string" - }, - { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "in": "header", - "name": "request-id", - "required": true, - "type": "string" - }, - { - "description": "The value list of products supported is:- sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-cross-border-credit-transfers", - "in": "header", - "name": "payment-product", - "type": "string" - }, - { - "description": "A session token generated by the ASPSP to ensure that an authentication session is maintained, in order to avoid re-entering client username and password (SFA) during the execution of the SCA", - "in": "header", - "name": "aspsp-authentication-session-id", - "type": "string" - }, - { - "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", - "in": "header", - "name": "Date", - "required": true, - "type": "string" - }, - { - "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", - "in": "path", - "name": "payment-id", - "required": true, - "type": "string" - }, - { - "description": "Resource identification of the related Payment Cancellation authorisation sub-resource or bulk authorisation sub-resource assigned to the created resource.", - "in": "path", - "name": "authorisation-id", - "required": true, - "type": "string" - }, - { - "description": "PaymentAuthorizationResourceScaInitiationRestRequest", - "in": "body", - "name": "body", - "schema": { - "$ref": "#/definitions/PaymentAuthorizationResourceScaInitiationRestRequest" - } - } - ], - "responses": { - "200": { - "description": "Service executed successfully", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/PaymentAuthorizationResourceScaInitiationRestResponse" - } - }, - "400": { - "description": "

            AUTH.0003

            Invalid parameter: {field name}

            AUTH.0004

            Missing parameter: {field name}

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "401": { - "description": "

            AUTH.0009

            PSU suspended or blocked

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "403": { - "description": "

            AUTH.0029

            ASPSP Default Error (Note: Error Description will be fill by ASPSP)

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "404": { - "description": "

            AUTH.0007

            Unknown PSU

            AUTH.0008

            Unknown ASPSP code

            PAY.0012

            Unknown Payment Identifier

            AUTH.0019

            Unsupported SCA approach

            AUTH.0027

            Unknown SCA method

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "409": { - "description": "

            AUTH.0002

            Operation not allowed

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "500": { - "description": "

            AUTH.0001

            Generic error

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - } - }, - "security": [ - { - "psd2_auth": [] - } - ], - "tags": [ - "paymentAuthorizationResourceScaInitiation" - ], - "operationId": "paymentAuthorizationResourceScaInitiation", - "summary": "This API allows to start a SCA process at ASPSP side." - }, - "put": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "parameters": [ - { - "description": "This field indicates the authorization purpose.The allowed values are:AUTHCANC", - "in": "header", - "name": "authorization-purpose", - "required": true, - "type": "string" - }, - { - "description": "A unique registration number for TPP identification", - "in": "header", - "name": "tpp-registration-number", - "required": true, - "type": "string" - }, - { - "description": "The TPP name", - "in": "header", - "name": "tpp-name", - "required": true, - "type": "string" - }, - { - "description": "The identification of the ASPSP (for example ABI)", - "in": "header", - "name": "aspsp-code", - "required": true, - "type": "string" - }, - { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "in": "header", - "name": "request-id", - "required": true, - "type": "string" - }, - { - "description": "The value list of products supported is: - sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-cross-border-credit-transfers", - "in": "header", - "name": "payment-product", - "type": "string" - }, - { - "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", - "in": "header", - "name": "Date", - "required": true, - "type": "string" - }, - { - "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", - "in": "path", - "name": "payment-id", - "required": true, - "type": "string" - }, - { - "description": "Resource identification of the related Payment Cancellation authorisation sub-resource or bulk authorisation sub-resource assigned to the created resource.", - "in": "path", - "name": "authorisation-id", - "required": true, - "type": "string" - }, - { - "description": "PaymentAuthorizationScaValidationRequestRestRequest", - "in": "body", - "name": "body", - "schema": { - "$ref": "#/definitions/PaymentAuthorizationScaValidationRequestRestRequest" - } - } - ], - "responses": { - "200": { - "description": "Service executed successfully", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/PaymentAuthorizationScaValidationRequestRestResponse" - } - }, - "400": { - "description": "

            AUTH.0003

            Invalid parameter: {field name}

            AUTH.0004

            Missing parameter: {field name}

            AUTH.0030

            Invalid SCA Authentication Data

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "401": { - "description": "

            AUTH.0028

            SCA validation failed

            PAY.0018

            Insufficient funds on the account

            PAY.0021

            Status Account doesn’t allow the operation

            PAY.0022

            Account type doesn’t allow the operation.

            PAY.0023

            Transaction amount exceeds the maximum authorized amount for specific payment product

            PAY.0024

            Duplicate payment

            PAY.0025

            Transaction amount exceeds transaction limit (daily, weekly, monthly)

            PAY.0026

            Transaction amount exceeds the single transaction limit

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "403": { - "description": "

            AUTH.0029

            ASPSP Default Error (Note: Error Description will be fill by ASPSP)

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "404": { - "description": "

            AUTH.0008

            Unknown ASPSP code

            PAY.0012

            Unknown Payment Identifier

            CNS.0006

            Unknown Consent

            PAY.0020

            Unknown Debtor Account

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "409": { - "description": "

            AUTH.0002

            Operation not allowed

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "500": { - "description": "

            AUTH.0001

            Generic error

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - } - }, - "security": [ - { - "psd2_auth": [] - } - ], - "tags": [ - "paymentAuthorizationScaValidationRequest" - ], - "operationId": "paymentAuthorizationScaValidationRequest", - "summary": "This API allows to validate the authentication data generated by PSU device during SCA phase. The service is used only in the case “Embedded” SCA approach." - } - }, - "/auth/sfa/{payment-id}/authorisations/{authorisation-id}": { - "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "parameters": [ - { - "description": "This field indicates the authorization purpose.The allowed values are:AUTHCANC", - "in": "header", - "name": "authorization-purpose", - "required": true, - "type": "string" - }, - { - "description": "The identification of the PSU in the ASPSP client interface.", - "in": "header", - "name": "psu-id", - "type": "string" - }, - { - "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", - "in": "header", - "name": "psu-id-type", - "type": "string" - }, - { - "description": "Identification of a Corporate, only used in a corporate context", - "in": "header", - "name": "psu-corporate-id", - "type": "string" - }, - { - "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", - "in": "header", - "name": "psu-corporate-id-type", - "type": "string" - }, - { - "description": "A unique registration number for TPP identification", - "in": "header", - "name": "tpp-registration-number", - "required": true, - "type": "string" - }, - { - "description": "The TPP name", - "in": "header", - "name": "tpp-name", - "required": true, - "type": "string" - }, - { - "description": "The identification of the ASPSP (for example ABI)", - "in": "header", - "name": "aspsp-code", - "required": true, - "type": "string" - }, - { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "in": "header", - "name": "request-id", - "required": true, - "type": "string" - }, - { - "description": "The value list of products supported is:- sepa-credit-transfers- instant-sepa-credit-transfers- target-2-payments- cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-", - "in": "header", - "name": "payment-product", - "type": "string" - }, - { - "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", - "in": "header", - "name": "Date", - "required": true, - "type": "string" - }, - { - "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", - "in": "path", - "name": "payment-id", - "required": true, - "type": "string" - }, - { - "description": "Resource identification of the related Payment Cancellation authorisation sub-resource or bulk authorisation sub-resource assigned to the created resource.", - "in": "path", - "name": "authorisation-id", - "required": true, - "type": "string" - }, - { - "description": "PaymentAuthorizationPsuAuthenticationRestRequest", - "in": "body", - "name": "body", - "schema": { - "$ref": "#/definitions/PaymentAuthorizationPsuAuthenticationRestRequest" - } - } - ], - "responses": { - "200": { - "description": "Service executed successfully", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/PaymentAuthorizationPsuAuthenticationRestResponse" - } - }, - "400": { - "description": "

            AUTH.0003

            Invalid parameter: {field name}

            AUTH.0004

            Missing parameter: {field name}

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "401": { - "description": "

            AUTH.0009

            PSU suspended or blocked

            AUTH.0016

            PSU credentials invalid

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "403": { - "description": "

            AUTH.0029

            ASPSP Default Error (Note: Error Description will be fill by ASPSP)

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "404": { - "description": "

            AUTH.0007

            Unknown PSU

            AUTH.0008

            Unknown ASPSP code

            PAY.0013

            The addressed payment product is not available for the PSU.

            PAY.0014

            Unknown payment product

            PAY.0012

            Unknown Payment Identifier

            CNS.0006

            Unknown consent

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "409": { - "description": "

            AUTH.0002

            Operation not allowed

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "500": { - "description": "

            AUTH.0001

            Generic error

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - } - }, - "security": [ - { - "psd2_auth": [] - } - ], - "tags": [ - "paymentAuthorizationPsuAuthentication" - ], - "operationId": "paymentAuthorizationPsuAuthentication", - "summary": "This API manage the PSU authentication in an “embedded” way for bulk payments and cancellation requests." - } - }, - "/bulk-payments/{payment-id}/status": { - "get": { - "produces": [ - "application/json", - "application/xml" - ], - "parameters": [ - { - "description": "A unique registration number for TPP identification", - "in": "header", - "name": "tpp-registration-number", - "required": true, - "type": "string" - }, - { - "description": "The TPP name", - "in": "header", - "name": "tpp-name", - "required": true, - "type": "string" - }, - { - "description": "The identification of the ASPSP (for example ABI)", - "in": "header", - "name": "aspsp-code", - "required": true, - "type": "string" - }, - { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "in": "header", - "name": "request-id", - "required": true, - "type": "string" - }, - { - "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", - "in": "header", - "name": "Date", - "required": true, - "type": "string" - }, - { - "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", - "in": "path", - "name": "payment-id", - "required": true, - "type": "string" - } - ], - "responses": { - "200": { - "description": "Service executed successfully ", - "headers": { - "content-type": { - "description": "application/json", - "type": "string" - }, - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/GetBulkPaymentStatusRequestRestResponse" - } - }, - "400": { - "description": "

            PAY.0003

            Invalid parameter: {field name}

            PAY.0004

            Missing parameter: {field name}

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "403": { - "description": "

            PAY.0029

            ASPSP Default Error (Note: Error Description will be fill by ASPSP)

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "404": { - "description": "

            PAY.0008

            Unknown ASPSP code

            PAY.0012

            Unknown Payment Identifier

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "409": { - "description": "

            PAY.0002

            Operation not allowed

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "500": { - "description": "

            PAY.0001

            Generic error

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - } - }, - "security": [ - { - "psd2_auth": [] - } - ], - "tags": [ - "getBulkPaymentStatusRequest" - ], - "operationId": "getBulkPaymentStatusRequest", - "summary": "This API retrieve the status of a Bulk payment initiation." - } - }, - "/fraud/bulk-payments/{payment-product}/{payment-id}": { - "post": { - "consumes": [ - "application/xml" - ], - "produces": [ - "application/json" - ], - "parameters": [ - { - "description": "The Identification of the PSU in the ASPSP client interface.", - "in": "header", - "name": "psu-id", - "required": true, - "type": "string" - }, - { - "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", - "in": "header", - "name": "psu-id-type", - "type": "string" - }, - { - "description": "Identification of a Corporate, only used in a corporate context", - "in": "header", - "name": "psu-corporate-id", - "type": "string" - }, - { - "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", - "in": "header", - "name": "psu-corporate-id-type", - "type": "string" - }, - { - "description": "The forwarded Agent header field of the http request between PSU and TPP. The User-Agent request header contains a characteristic string that allows the network protocol peers to identify the application type, operating system, software vendor or software version of the requesting software user agent.", - "in": "header", - "name": "psu-user-agent", - "type": "string" - }, - { - "description": "The forwarded IP Address header field consists of the corresponding http request IP Address field between PSU and TPP.", - "in": "header", - "name": "psu-ip-address", - "required": true, - "type": "string" - }, - { - "description": "The forwarded IP Port header field consists of the corresponding HTTP request IP Port field between PSU and TPP, if available.", - "in": "header", - "name": "psu-ip-port", - "type": "string" - }, - { - "description": "The Accept request-header field can be used to specify certain media types which are acceptable for the response", - "in": "header", - "name": "psu-accept", - "type": "string" - }, - { - "description": "The charset information sent by the PSU. The Accept-Charset request-header field can be used to indicate what character sets are acceptable for the response. ", - "in": "header", - "name": "psu-accept-charset", - "type": "string" - }, - { - "description": "The encoding information sent by the PSU. The Accept-Encoding request-header field is similar to Accept but restricts the content-codings that are acceptable in the response.", - "in": "header", - "name": "psu-accept-encoding", - "type": "string" - }, - { - "description": "The language information sent by the PSU. The Accept-Language request-header field is similar to Accept, but restricts the set of natural languages that are preferred as a response to the request", - "in": "header", - "name": "psu-accept-language", - "type": "string" - }, - { - "description": "HTTP method used at the PSU – TPP interface, if available. Valid values are: - GET - POST - PUT - PATCH - DELETE", - "in": "header", - "name": "psu-http-method", - "type": "string" - }, - { - "description": "UUID (Universally Unique Identifier) for a device, which is used by the PSU, if available.UUID identifies either a device or a device dependant application installation. In case of an installation identification this ID need to be unaltered until removal from device.", - "in": "header", - "name": "psu-device-id", - "type": "string" - }, - { - "description": "The forwarded Geo Location of the corresponding http request between PSU and TPP if available.Format using [RFC 2426], i.e. GEO:,< longitude >.", - "in": "header", - "name": "psu-geo-location", - "type": "string" - }, - { - "description": "A unique registration number for TPP identification", - "in": "header", - "name": "tpp-registration-number", - "required": true, - "type": "string" - }, - { - "description": "The TPP name", - "in": "header", - "name": "tpp-name", - "required": true, - "type": "string" - }, - { - "description": "The identification of the ASPSP (for example ABI)", - "in": "header", - "name": "aspsp-code", - "required": true, - "type": "string" - }, - { - "description": "Identifier of the product in ASPSP scope.", - "in": "header", - "name": "aspsp-product-code", - "required": true, - "type": "string" - }, - { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "in": "header", - "name": "request-id", - "required": true, - "type": "string" - }, - { - "description": "The number of bits used to display one color.The possible values are: 32, 24, 16, or 8", - "in": "header", - "name": "screen-color-depth", - "type": "string" - }, - { - "description": "Width of the user's screen Note For iOS, the resolution measurement is in points. For other operating systems, the resolution measurement is in pixels.", - "in": "header", - "name": "screen-width", - "type": "string" - }, - { - "description": "Height of the user’s screen Note For iOS, the resolution measurement is in points. For other operating systems, the resolution measurement is in pixels.", - "in": "header", - "name": "screen-height", - "type": "string" - }, - { - "description": "Vertical space of the user’s screen. Note For iOS, the resolution measurement is in points. For other operating systems, the resolution measurement is in pixels.", - "in": "header", - "name": "screen-vertical-space", - "type": "string" - }, - { - "description": "The software plug-ins installed in the user’s browser.", - "in": "header", - "name": "software-plug-ins", - "type": "string" - }, - { - "description": "The user’s current time zone, related to UTC (for example UTC+01:00)", - "in": "header", - "name": "time-zone", - "type": "string" - }, - { - "description": "The language that the user has set in the browser ", - "in": "header", - "name": "browser-language", - "type": "string" - }, - { - "description": "A Boolean value that indicates whether Java is enabled in the browserOnly “true” or “false” value is accepted.", - "in": "header", - "name": "java-support", - "type": "string" - }, - { - "description": "A Boolean value that indicates whether cookies are enabled in the user’s browserOnly “true” or “false” value is accepted.", - "in": "header", - "name": "psu-cookie-support", - "type": "string" - }, - { - "description": "The operating system installed. ", - "in": "header", - "name": "device-os", - "type": "string" - }, - { - "description": "The operating system version installed", - "in": "header", - "name": "device-os-version", - "type": "string" - }, - { - "description": "The major version of the browser.", - "in": "header", - "name": "major-version", - "type": "string" - }, - { - "description": "The browser being used. Possible values are: Netscape, Mozilla, Explorer, Camino, Firefox, Konqueror, iCab, Opera, Safari, OmniWeb, Chrome.", - "in": "header", - "name": "browser-type", - "type": "string" - }, - { - "description": "Different identifiers are retrieved for each of the operating systems: -iOS 4.x-6.x The Wi-Fi MAC address. -iOS 7.x and later The identifierFor Vendor property of the UIDevice class. -Android The Internationa l Mobile Equipment Identity (IMEI) for GSM.", - "in": "header", - "name": "hardware-id", - "type": "string" - }, - { - "description": "A positive value indicates that the device is rooted or jailbroken.Only “true” or “false” value is accepted.", - "in": "header", - "name": "device-rooted", - "type": "string" - }, - { - "description": "A positive value indicates that the client device is an emulator.Only “true” or “false” value is accepted.", - "in": "header", - "name": "emulator", - "type": "string" - }, - { - "description": "The client application creates and saves a random unique identifier, which the client application can read. This enables verification that the application is genuine and not malicious malware. Note: For iOS system, the value is permanently stored in the keychain. For Android system the value is stored in the private storage of the application. This value is only stored until the application is uninstalled.", - "in": "header", - "name": "rsa-application-key", - "type": "string" - }, - { - "description": "The currently installed RSA Adaptive Authentication Mobile SDK Modules version and build number.", - "in": "header", - "name": "sdk-version", - "type": "string" - }, - { - "description": "The Date general-header field represents the date and time at which the message was originated.  Format: EEE, dd MMM yyyy hh:mm:ss z", - "in": "header", - "name": "Date", - "type": "string" - }, - { - "description": "The model of the mobile device.", - "in": "header", - "name": "device-model", - "type": "string" - }, - { - "description": "The mobile device name defined by the end user. Note In Android, this device element is returned based on the name defined in the Bluetooth settings.", - "in": "header", - "name": "device-name", - "type": "string" - }, - { - "description": "The language displayed in the mobile device.", - "in": "header", - "name": "languages", - "type": "string" - }, - { - "description": "Indicates whether or not the mobile device supports multitasking.Only “true” or “false” value is accepted.", - "in": "header", - "name": "multitasking-supported", - "type": "string" - }, - { - "description": "A GSM Cell ID (CID) is a unique number used to identify each base transceiver station (BTS) or sector of a BTS within a location area code (LAC) or GSM network. Note This device element is not supported by iOS. ", - "in": "header", - "name": "cell-tower-id", - "type": "string" - }, - { - "description": "The height of the mobile device above the ellipsoid. This device element is measured in meters.", - "in": "header", - "name": "geolocation-altitude", - "type": "string" - }, - { - "description": "The accuracy of the mobile device’s altitude. This device element is returned in meters.", - "in": "header", - "name": "geolocation-altitude-accuracy", - "type": "string" - }, - { - "description": "The direction of travel of the mobile device. This device element is returned in degrees.", - "in": "header", - "name": "geolocation-heading", - "type": "string" - }, - { - "description": "The radius of uncertainty for the geo-location of the mobile device. This device element is measured in meters. A negative value indicates that the geo-location latitude or longitude of the mobile device is invalid.", - "in": "header", - "name": "geolocation-horizontal-accuracy", - "type": "string" - }, - { - "description": "The current ground speed of the mobile device. This device element is returned in meters per second.", - "in": "header", - "name": "geolocation-speed", - "type": "string" - }, - { - "description": "There are five possible status codes:0=success The geolocation is successfully retrieved. 1=deny The end user denies location collection. 2=location status not available. The geolocation position is unavailable. 3=location status timeout The geolocation is timed out. 4=location status not supported The geolocation collection is not supported.", - "in": "header", - "name": "geolocation-status", - "type": "string" - }, - { - "description": "The time that the geo-location was created. This device element is returned in milliseconds.", - "in": "header", - "name": "geolocation-timestamp", - "type": "string" - }, - { - "description": "The local area code. Note For Android, this device element is only available for GSM devices and does not support CDMA devices. Note This device element is not supported by iOS.", - "in": "header", - "name": "location-area-code", - "type": "string" - }, - { - "description": "The Wi-Fi card MAC address. Note This device element is mandatory for iOS versions 4.x– 6.x.", - "in": "header", - "name": "wifi-mac-address", - "type": "string" - }, - { - "description": "The country code of the mobile device.", - "in": "header", - "name": "MCC", - "type": "string" - }, - { - "description": "The mobile carrier code.", - "in": "header", - "name": "MNC", - "type": "string" - }, - { - "description": "The basic service set identification (BSSID) for each basic service set. ", - "in": "header", - "name": "wifi-networks-data-bssid", - "type": "string" - }, - { - "description": "The wireless signal strength in the database management system expressed in decibel/meters For example -40 dBmNote This device element is not supported by iOS.", - "in": "header", - "name": "wifi-networks-data-signal-strength", - "type": "string" - }, - { - "description": "The Service Set Identifier (SSID). (the network name)", - "in": "header", - "name": "wifi-networks-data-ssid", - "type": "string" - }, - { - "description": "Define the channel used from PSU in order to send the request to TPP (WEB or APP) ", - "in": "header", - "name": "channel", - "type": "string" - }, - { - "description": "The operating system identification:- iOS: Universally Unique Identifier (UUID) (in this case it is length 36 characters)-Android: The client application creates a random unique identifier that permanently persists in the keychain (Android_ID) (in this case it is length 16 characters)", - "in": "header", - "name": "os-id", - "type": "string" - }, - { - "description": "Mobile Station International Subscriber Directory Number (MSISDN).", - "in": "header", - "name": "phone-number", - "type": "string" - }, - { - "description": "The International Mobile Subscriber Identity (IMSI)", - "in": "header", - "name": "sim-id", - "type": "string" - }, - { - "description": "The addressed payment product endpoint.The value list of products supported is: - sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers ", - "in": "path", - "name": "payment-product", - "required": true, - "type": "string" - }, - { - "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", - "in": "path", - "name": "payment-id", - "required": true, - "type": "string" - }, - { - "description": "TransactionDecisionDelegationForBulkRestRequest", - "in": "body", - "name": "body", - "schema": { - "format": "binary", - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Service executed successfully", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/TransactionDecisionDelegationForBulkRestResponse" - } - }, - "400": { - "description": "

            PAY.0003

            Invalid parameter: {field name}

            PAY.0004

            Missing parameter: {field name}

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "401": { - "description": "

            PAY.0009

            PSU suspended or blocked

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "403": { - "description": "

            PAY.0029

            ASPSP Default Error (Note: Error Description will be fill by ASPSP)

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "404": { - "description": "

            PAY.0007

            Unknown PSU

            PAY.0008

            Unknown ASPSP code

            PAY.0013

            The addressed payment product is not available for the PSU.

            PAY.0014

            Unknown Payment Product

            PAY.0012

            Unknown Payment Identifier

            PAY.0020

            Unknown Debtor Account

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "409": { - "description": "

            PAY.0002

            Operation not allowed

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - }, - "500": { - "description": "

            PAY.0001

            Generic error

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/ErrorManagementWrapper" - } - } - }, - "security": [ - { - "psd2_auth": [] - } - ], - "tags": [ - "transactionDecisionDelegationForBulk" - ], - "operationId": "transactionDecisionDelegationForBulk", - "summary": "This API allows to confirm or overwrite the SCA exception result performed by PSD2 Gateway." - } - }, - "/{payment-service}/{payment-product}/{payment-id}": { - "delete": { - "produces": [ - "application/json" - ], - "parameters": [ - { - "description": "The identification of the PSU in the ASPSP client interface.", - "in": "header", - "name": "psu-id", - "required": true, - "type": "string" - }, - { - "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", - "in": "header", - "name": "psu-id-type", - "type": "string" - }, - { - "description": "Identification of a Corporate, only used in a corporate context", - "in": "header", - "name": "psu-corporate-id", - "type": "string" - }, - { - "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", - "in": "header", - "name": "psu-corporate-id-type", - "type": "string" - }, - { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "in": "header", - "name": "request-id", - "required": true, - "type": "string" - }, - { - "description": "The identification of the ASPSP (for example ABI)", - "in": "header", - "name": "aspsp-code", - "required": true, - "type": "string" - }, - { - "description": "Identifier of the product in ASPSP scope.", - "in": "header", - "name": "aspsp-product-code", - "required": true, - "type": "string" - }, - { - "description": "A unique registration number for TPP identification", - "in": "header", - "name": "tpp-registration-number", - "required": true, - "type": "string" - }, - { - "description": "The TPP name", - "in": "header", - "name": "tpp-name", - "required": true, - "type": "string" - }, - { - "description": "The Date general-header field represents the date and time at which the message was originated. Format: EEE, dd MMM yyyy hh:mm:ss z", - "in": "header", - "name": "Date", - "required": true, - "type": "string" - }, - { - "description": "The addressed payment service.The supported values are:paymentsperiodic-paymentsbulk-payments", - "in": "path", - "name": "payment-service", - "required": true, - "type": "string" - }, - { - "description": "The addressed payment product endpoint.The value list of products supported is: - sepa-credit-transfers - instant-sepa-credit-transfers - target-2-payments - cross-border-credit-transfers- pain.001-sepa-credit-transfers - pain.001-instant-sepa-credit-transfers - pain.001-target-2-payments - pain.001-cross-border-credit-transfers ", - "in": "path", - "name": "payment-product", - "required": true, - "type": "string" - }, - { - "description": "PSD2 gateway payment identification. The UUID of the generated payment initiation resource.", - "in": "path", - "name": "payment-id", - "required": true, - "type": "string" - } - ], - "responses": { - "202": { - "description": "ASPSP requests PSU authorization to cancel the payment", - "headers": { - "Date": { - "description": "The date provided used for the signature. Format: EEE, dd MMM yyyy hh:mm:ss z", - "type": "string" - }, - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponse202" - } - }, - "204": { - "description": "Payment successfully cancelled", - "headers": { - "Date": { - "description": "The date provided used for the signature. Format: EEE, dd MMM yyyy hh:mm:ss z", - "type": "string" - }, - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponse" - } - }, - "400": { - "description": "

            PAY.0003

            Invalid parameter: {field name}

            PAY.0004

            Missing parameter: {field name}

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - }, - "401": { - "description": "

            PAY.0009

            PSU suspended or blocked

            PAY.0021

            Status Account doesn’t allow the operation

            PAY.0022

            Account type doesn’t allow the operation.

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - }, - "403": { - "description": "

            PAY.0029

            ASPSP Default Error (Note: Error Description will be fill by ASPSP)

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - }, - "404": { - "description": "

            PAY.0008

            Unknown ASPSP code

            PAY.0013

            The addressed payment product is not available for the PSU.

            PAY.0014

            Unknown Payment Product

            PAY.0012

            Unknown Payment Identifier

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - }, - "405": { - "description": "

            PAY.0005

            The addressed payment is not cancellable e.g. due to cut off time passed or legal constraints

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - }, - "409": { - "description": "

            PAY.0002

            Operation not allowed

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - }, - "500": { - "description": "

            PAY.0001

            Generic error

            ", - "headers": { - "request-id": { - "description": "UUID of the request, unique to the call, as determined by the initiating party.", - "type": "string" - } - }, - "schema": { - "$ref": "#/definitions/DeletePaymentRestResponseKO" - } - } - }, - "security": [ - { - "psd2_auth": [] - } - ], - "tags": [ - "deletePayment" - ], - "operationId": "deletePayment", - "summary": "This API allows to execute a payment cancellation requesto towards ASPSP." - } - } - }, - "definitions": { - "ChallengeData": { - "description": "Data to generate OTP. The parameter is valorized only in the case of “EMBEDDED” SCA Approach.Object Type: Challenge Data", - "properties": { - "additionalInformation": { - "description": "Additional explanation for the PSU to explain e.g. fallback mechanism for the chosen SCA method. The TPP is obliged to show this to the PSU. ", - "type": "string" - }, - "data": { - "description": "String challenge data ", - "type": "string" - }, - "image": { - "description": "PNG data (max. 512 kilobyte) to be displayed to the PSU, Base64 encoding , cp. [RFC 4648]. This attribute is used only, when PHOTO_OTP or CHIP_OTP is the selected SCA method ", - "type": "string" - }, - "imageLink": { - "description": "A link where the ASPSP will provides the challenge image for the TPP. ", - "type": "string" - }, - "otpFormat": { - "description": "The format type of the OTP to be typed in. The admitted values are:charactersinteger.", - "type": "string" - }, - "otpMaxLength": { - "description": "The maximal length for the OTP to be typed in by the PSU. ", - "format": "int32", - "type": "integer" - } - }, - "type": "object" - }, - "CredentialsDetail": { - "description": "Credentials Details", - "properties": { - "credentialDetailId": { - "description": "Credential Detail Identification", - "type": "string" - }, - "credentialValue": { - "description": "Credential Value", - "type": "string" - } - }, - "required": [ - "credentialDetailId", - "credentialValue" - ], - "type": "object" - }, - "DeletePaymentRestResponse": { - "description": "PSD2 - delete payment rest response", - "properties": { - "paymentTransactionStatus": { - "description": "Status of the payment transaction on the bank systems. See Transaction Status", - "type": "string" - }, - "signatureData": { - "$ref": "#/definitions/SignatureData" - } - }, - "required": [ - "paymentTransactionStatus" - ], - "type": "object" - }, - "DeletePaymentRestResponseKO": { - "description": "PSD2 - delete payment rest response", - "properties": { - "errorManagement": { - "$ref": "#/definitions/ErrorManagement" - } - }, - "type": "object" - }, - "DeletePaymentRestResponse202": { - "type": "object", - "description": "PSD2 - delete payment rest response in case of http status 202", - "properties": { - "paymentTransactionStatus": { - "type": "string", - "description": "Status of the payment transaction on the bank systems. See Transaction Status" - } - }, - "required": [ - "paymentTransactionStatus" - ] - }, - "ErrorManagement": { - "properties": { - "errorCode": { - "description": "Code that identifies the error occurred", - "type": "string" - }, - "errorDescription": { - "description": "Error description", - "type": "string" - } - }, - "required": [ - "errorCode", - "errorDescription" - ], - "type": "object" - }, - "FraudScoreLevel": { - "description": "Define for each rule level the related score (this is valorized in case the fraudResult is different to 000)", - "properties": { - "levelId": { - "description": "Rule level identification", - "type": "string" - }, - "score": { - "description": "Score calculated to forehead of a violation of the rule level ", - "type": "string" - } - }, - "required": [ - "levelId", - "score" - ], - "type": "object" - }, - "GetBulkPaymentStatusRequestRestResponse": { - "description": "PSD2 Bulk - get bulk payment status request rest response", - "properties": { - "paymentTransactionStatus": { - "description": "Status of the payment transaction on the bank systems. See Transaction Status", - "type": "string" - }, - "psuMessage": { - "description": "Message to be shown to the PSU. This parameter should be used in case of multi SCA authorization. The bank will provide here the information needed to the TPP and PSU to complete the authorization of the payment.", - "type": "string" - } - }, - "type": "object" - }, - "PaymentAuthorizationPsuAuthenticationRestRequest": { - "description": "PSD2 - payment authorization psu authentication rest request", - "properties": { - "psuCredentials": { - "$ref": "#/definitions/PsuCredential" - } - }, - "required": [ - "psuCredentials" - ], - "type": "object" - }, - "PaymentAuthorizationPsuAuthenticationRestResponse": { - "description": "PSD2 - payment authorization psu authentication rest response", - "properties": { - "endUserIdentification": { - "description": "End user identification cross bank. The value is derived through function of SHA512 of the concatenation of PSU fiscal code and the following string: 57Z08PPmOedjjl4YLuRauc2nMoAckyQdZG5iSfmskX2jnO8LLO0jCOUCEVl5k5V19DD8xTwgg522trK3cx02, An example:enduserIdentification=SHA512(C.F.+ 57Z08PPmOedjjl4YLuRauc2nMoAckyQdZG5iSfmskX2jnO8LLO0jCOUCEVl5k5V19DD8xTwgg522trK3cx02If it is a corporate user the concatenation is the VAT number with the following string: njMqlpKSrwS6pObSRZgMcDVV6O2YyBujTckN1Z4gXB8FPvBQE6pYXpVZYxrckZsw4B1wCWAy7IgAi1sCtQWhzBBG7An example:enduserIdentification=SHA512(P.I. + njMqlpKSrwS6pObSRZgMcDVV6O2YyBujTckN1Z4gXB8FPvBQE6pYXpVZYxrckZsw4B1wCWAy7IgAi1sCtQWhzBBG7)", - "type": "string" - }, - "psuCorporateId": { - "description": "Identification of a Corporate, only used in a corporate context", - "type": "string" - }, - "psuCorporateIdType": { - "description": "This is describing the type of the identification needed by the ASPSP to identify the PSU-Corporate-ID content.", - "type": "string" - }, - "psuId": { - "description": "The identification of the PSU in the ASPSP client interface.", - "type": "string" - }, - "psuIdType": { - "description": "Type of the PSU-ID, needed in scenarios where PSUs have several PSU-IDs as access possibility.", - "type": "string" - }, - "psuMessage": { - "description": "Text to be displayed to the PSU.", - "type": "string" - }, - "psuName": { - "description": "Name of the PSU.In case of a corporate account, this might be the person acting on behalf of the corporate.", - "type": "string" - } - }, - "required": [ - "endUserIdentification", - "psuId" - ], - "type": "object" - }, - "PaymentAuthorizationResourceScaInitiationRestRequest": { - "description": "PSD2 - payment authorization resource sca initiation rest request", - "properties": { - "authorisationCallbackUrl": { - "description": "Callback partial URL (without IP and PORT) of the PSD2, where the bank notifies the SCA result. The parameter will be valorized only in the case “Redirect” or “Decoupled” approach. ", - "type": "string" - }, - "psuAlreadyAuthenticated": { - "description": "'true', if the psu has been already authenticated through the platform; 'false', otherwise.", - "type": "string" - }, - "selectedScaApproach": { - "description": "The SCA approach selected. Possible values are: EMBEDDED DECOUPLED REDIRECT OAUTH", - "type": "string" - }, - "selectedScaMethod": { - "$ref": "#/definitions/ScaMethod" - } - }, - "required": [ - "psuAlreadyAuthenticated", - "selectedScaApproach", - "selectedScaMethod" - ], - "type": "object" - }, - "PaymentAuthorizationResourceScaInitiationRestResponse": { - "description": "PSD2 - payment authorization resource sca initiation rest response", - "properties": { - "aspspScaUrl": { - "description": "URL to which the TPP must redirect the PSU to perform the SCA (it is valorized only in the case oAuth or Redirect SCA).", - "type": "string" - }, - "challengeData": { - "$ref": "#/definitions/ChallengeData" - }, - "psuMessage": { - "description": "Text to be displayed to the PSU.In the case of the Decoupled SCA approach this field will be valorized with PSU Instructions to execute.", - "type": "string" - } - }, - "type": "object" - }, - "PaymentAuthorizationScaValidationRequestRestRequest": { - "description": "PSD2 - payment authorization sca validation request rest request ", - "properties": { - "scaAuthenticationData": { - "description": "SCA authentication data, depending on the chosen authentication method. If the data is binary, then it is base64 encoded. ", - "type": "string" - } - }, - "required": [ - "scaAuthenticationData" - ], - "type": "object" - }, - "PaymentAuthorizationScaValidationRequestRestResponse": { - "description": "PSD2 - payment authorization sca validation request rest response ", - "properties": { - "paymentTransactionStatus": { - "description": "Status of the payment transaction. See Transaction Status", - "type": "string" - }, - "psuMessage": { - "description": "Text to be displayed to the PSU", - "type": "string" - }, - "signatureData": { - "$ref": "#/definitions/SignatureData" - } - }, - "type": "object" - }, - "PsuCredential": { - "description": "PSU Credentials on the Bank systemObject Type: PSU Credential", - "properties": { - "credentialsDetails": { - "description": "Credentials Details", - "items": { - "$ref": "#/definitions/CredentialsDetail" - }, - "type": "array" - }, - "productCode": { - "description": "Bank Product to which the user must authenticate. ", - "type": "string" - } - }, - "required": [ - "productCode" - ], - "type": "object" - }, - "RestHref": { - "description": "The link to the authorisation end-point, where the cancellation-authorisation sub-resource has to be generated while selecting the authentication method. This link is contained under exactly the same conditions as the data element 'scaMethods”.This link can be used in the following scenarios:The PSU ID provided during the cancellation isn’t the same that authorized the payment. The platform identifys more SCA methods applicable, so the PSU has to choise one of them to starts an explicit authorisationThe payment was SCA exempt and there are more SCA methods applicable, so the PSU has to choise one of them", - "properties": { - "href": { - "type": "string" - } - }, - "type": "object" - }, - "ScaMethod": { - "description": "The SCA Method selectedObject Type: Sca Method", - "properties": { - "authenticationMethodId": { - "description": "An identification provided by the ASPSP for the later identification of the authentication method selection.", - "type": "string" - }, - "authenticationType": { - "description": "The field describes the type of the authentication method.Example values are:SMS_OTPCHIP_OTPPHOTO_OTPPUSH_OTP", - "type": "string" - }, - "authenticationVersion": { - "description": "Depending on the “authenticationType”. This version can be used by differentiating authentication tools used within performing OTP generation in the same authentication type. This version can be referred to in the ASPSP’s documentation.", - "type": "string" - }, - "explanation": { - "description": "This is a description about the authentication method.", - "type": "string" - }, - "name": { - "description": "This could be a description provided by the ASPSP like “SMS OTP on phone +49160 xxxxx 28”.This name shall be used by the TPP when presenting a list of authentication methods to the PSU, if available.", - "type": "string" - } - }, - "required": [ - "authenticationMethodId", - "authenticationType" - ], - "type": "object" - }, - "SignatureData": { - "description": "ASPSP signature. Object Type: Signature Data", - "properties": { - "aspspCertificate": { - "description": "The APSPS certificate used to verify the signature", - "type": "string" - }, - "digest": { - "description": "The field is hash concatenation of the parameters which represents the payment. It could include the following parameters (to be defined with banks) paymentIdpaymentTransactionStatusDate (one received in input header)All fields are separated by pipe eg:SHA512(paymentId|paymentTransactionStatus|Date)", - "type": "string" - }, - "digitalSignature": { - "description": "The signature of the HASH by the ASPSP through its own encryption key", - "type": "string" - } - }, - "required": [ - "aspspCertificate", - "digest", - "digitalSignature" - ], - "type": "object" - }, - "ErrorManagementWrapper": { - "description": "", - "properties": { - "errorManagement": { - "$ref": "#/definitions/ErrorManagement" - } - } - }, - "TransactionDecisionData": { - "description": "Details on analysis performed from ASPSP systemObject Type: Transaction Decision Data", - "properties": { - "currencyConversionFees": { - "description": "Might be used by the ASPSP to transport specific currency conversion fees related to the initiated credit transfer.", - "type": "string" - }, - "debtorName": { - "description": "This field must contain the “owner name” info of the debited account. The “owner name” is the name of the legal account owner. If there is more than one owner, then e.g. two names might be noted here.For a corporate account, the corporate name is used for this attribute. This enables the ASPSP to transport the account owner name to the PISP in case where the regulatory need is provided and if not provided by other means like the List of Available Accounts Service.", - "type": "string" - }, - "estimatedInterbankSettlementAmount": { - "description": "The estimated amount to be transferred to the payee.", - "type": "string" - }, - "estimatedTotalAmount": { - "description": "The amount which is estimated to be debted from the debtor account.Note: This amount includes fees.", - "type": "string" - }, - "fraudResult": { - "description": "Overall outcome assigned by the ASPSP system.The transaction is granted if the value is between 000 – 099 while will be denied (and consequently the flow interrupted) if the value is >= 100 (100 included)", - "type": "string" - }, - "fraudScoreLevel": { - "description": "Define for each rule level the related score (this is valorized in case the fraudResult is different to 000)", - "items": { - "$ref": "#/definitions/FraudScoreLevel" - }, - "type": "array" - }, - "psuMessage": { - "description": "If the consumer is fraudster, the filed will be populated the specific error message", - "type": "string" - }, - "transactionFeeIndicator": { - "description": "If equals “true”, the transaction will involve specific transaction cost as shown by the ASPSP in their public price list or as agreed between ASPSP and PSU. If equals 'false', the transaction will not involve additional specific transaction costs to the PSU. ", - "type": "string" - }, - "transactionFees": { - "$ref": "#/definitions/TransactionFee" - } - }, - "required": [ - "fraudResult" - ], - "type": "object" - }, - "TransactionDecisionDelegationForBulkRestResponse": { - "description": "PSD2 - transaction decision delegation for bulk rest response", - "properties": { - "transactionDecisionData": { - "$ref": "#/definitions/TransactionDecisionData" - } - }, - "required": [ - "transactionDecisionData" - ], - "type": "object" - }, - "TransactionFee": { - "description": "Can be used by the ASPSP to returns transaction fees relevant for the underlying payments. ", - "properties": { - "amount": { - "description": "The amount given with fractional digits, where fractions must be compliant to the currency definition. Up to 14 significant figures. Negative amounts are signed by minus. The decimal separator is a dot. Example: Valid representations for EUR with up to two decimals are: • 1056 • 5768.2 • -1.50• 5877.78", - "type": "string" - }, - "currency": { - "description": "Define the code of a currency, three letters for the country. (CurrencyCode ISO 20022)", - "type": "string" - } - }, - "required": [ - "currency","amount" - ], - "type": "object" - } - }, - "securityDefinitions": { - "psd2_auth": { - "flow": "application", - "scopes": { - "production": "manage psd2 orchestrator authorization flow" - }, - "tokenUrl": "https://cbiglobeopenbankingapigateway.nexi.it/auth/oauth/v2/token", - "type": "oauth2" - } - }, - "x-components": {} -} \ No newline at end of file From fe338d3fc6fd7dfdd851cc1fdea9cac85b5330f6 Mon Sep 17 00:00:00 2001 From: Francesco Panico Date: Wed, 1 Jul 2026 15:41:57 +0200 Subject: [PATCH 8/8] update features --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 29e8ca2d..11c4c143 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ java -jar swagger-diff.jar \ Download the fatJar or view the changelog on the **[Release Page](https://github.com/Sayi/swagger-diff/releases),** and thanks to all contributors. ## Feature -* Supports swagger spec v1.x and v2.0. +* Supports swagger spec v1.x v2.0 and openAPI 3.0.x * Depth comparison of parameters, responses, notes, http method(GET,POST,PUT,DELETE...) * Supports swagger api Authorization * Render difference of property with Expression Language @@ -54,7 +54,7 @@ Download the fatJar or view the changelog on the **[Release Page](https://github ## Gradle ```shell -compile group: 'com.deepoove', name: 'swagger-diff', version: '1.2.2' +compile group: 'com.deepoove', name: 'swagger-diff', version: '1.3.0' ``` ## Usage @@ -161,4 +161,4 @@ try { ``` ## How it works -![image](./swagger-diff.png) \ No newline at end of file +![image](./swagger-diff.png)