payment-provider-framework

Apply when designing or implementing a Payment Connector in VTEX IO. Covers PPF implementation, TypeScript 3.9.7 builder-hub constraints and safe dependency resolutions, configuration.json schema validation, PaymentProviderService clients wiring, Secure Proxy scope (authorize-only), ExternalClient v

By vtex · 742 installs

npx skills add vtex/skills --skill payment-provider-framework

Source repository · Upstream listing

Payment Provider Framework (VTEX IO) When this skill applies Use this skill when: Creating or maintaining a payment connector implemented as a VTEX IO app (not a standalone HTTP service you host yourself) Wiring @vtex/payment provider , PaymentProvider , and PaymentProviderService in node/index.ts Configuring the paymentProvider builder, configuration.json (payment methods, customFields , feature flags) Implementing this.retry(request) for Gateway retry semantics on IO Extending SecureExternalClient and passing secureProxy on requests for card flows on IO Testing via payment affiliation, workspaces, beta/stable releases, the VTEX App Store, and VTEX homologation Do not use this skill for: PPP HTTP contracts, response field by field requirements, and the nine endpoints in the abstract — use [ payment provider protocol ](../payment provider protocol/SKILL.md) Idempotency and duplicate paymentId handling — use [ payment idempotency ](../payment idempotency/SKILL.md) Async undefined status, callbackUrl notification vs retry (IO vs non IO) — use [ payment async flow ](../payment async flow/SKILL.md) PCI rules, logging, and token semantics beyond IO wiring — use [ payment pci security ](../payment pci security/SKILL.md) Decision rules PPF on IO : "Payment Provider Framework is the VTEX IO–based way to build payment connectors." The app uses IO infrastructure; API routes, request/response types, and Secure Proxy are integrated per VTEX guides. Start from the example app described in the official Payment Provider Framework documentation. Prerequisites : Follow implementation prerequisites in the Payment Provider Protocol article and the guide on integrating a new payment provider on VTEX. Dependencies : In the app node folder, add @vtex/payment provider (for example 1.x in package.json ). Keep @vtex/api in devDependencies (for example 6.x ); linking may bump it beyond 6.x , which is acceptable. If types break, delete node modules and yarn.lock in the project root and in node , then run yarn install f in both. paymentProvider builder : In manifest.json , include "paymentProvider": "1.x" next to node so policies for Payment Gateway callbacks and PPP routes apply. configuration.json : Declare paymentMethods so the builder can implement them without re declaring everything on /manifest . Use names matching the List Payment Provider Manifest API reference; only invent a new name when the method is genuinely new. New methods in Admin may require a support ticket. PaymentProvider : One class method per PPP route; TypeScript enforces shapes — see Payment Flow endpoints in the API reference. PaymentProviderService : Registers default routes /manifest , /payments , /settlements , /refunds , /cancellations , /inbound ; pass extra routes / clients when needed. Overriding /manifest : Only with an approved use case — open a ticket. See the Preferred pattern section for an example route override shape. Configurable options : Use configuration.json / builder options for flags such as implementsOAuth , implementsSplit , usesProviderHeadersName , usesBankInvoiceEnglishName , usesSecureProxy , requiresDocument , acceptSplitPartialRefund , usesAutoSettleOptions . Set name and rely on auto generated serviceUrl on IO unless documented otherwise. Do not invent fields — unknown keys (such as usesTestSuite ) cause builder validation errors. See the "configuration.json schema" constraint below for the canonical list and customFields format. Gateway retry : In PPF, call this.retry(request) where the protocol requires retry — see the Payment authorization section in the PPP article. Card data on IO : "Prefer SecureExternalClient with secureProxy: secureProxyUrl from Create Payment; destination must be allowlisted." Supported Content Type values for Secure Proxy: application/json and application/x www form urlencoded only. Important: only the Create Payment (authorize) request carries secureProxyUrl . Post authorization operations (cancel, capture, refund) do not transport card data and must call the PSP API directly via ExternalClient with credentials and outbound access policies. Checkout testing : Account must be allowed for IO connectors (ticket with app name and account). Publish beta, install on master , wait ~1 hour, open affiliation URL, enable test mode and workspace, configure payment condition (~10 minutes), place test order; then stable + homologation. Publication : Configure billingOptions per the Billing Options guide; submit via Submitting your app. Prepare homologation artifacts (connector app name, partner contact, production endpoint, allowed accounts, new methods/flows) per the Integrating a new payment provider on VTEX guide (SLA often ~30 days). Updates : Ship changes in a new beta, re test affiliations, then stable; re homologate if required. Hard constraints Constraint: Builder Hub uses TypeScript 3.9.7 — code and dependencies MUST be compatible The vtex.builder hub compiles IO apps with TypeScript 3.9.7 . It also ignores skipLibCheck: true in tsconfig.json — every .d.ts file in node modules is type checked. This means that even if your own code is valid, a transitive dependency shipping modern .d.ts syntax will break the build with hundreds of errors unrelated to your code. Why this matters Agents and developers regularly produce code with TS 4.x+ syntax or install the latest @types/ packages. The build fails with cryptic errors in files the developer never touched, causing many wasted iterations. Prohibited syntax (incompatible with TS 3.9.7) Syntax Minimum TS version Example Template literal types 4.1 type X = ${string}/${string} Typed catch clause 4.0 catch (error: any) override keyword 4.3 override method() in classes import type ... = require() 4.5 import type X = require("pkg") satisfies operator 4.9 obj satisfies Type Correct catch block pattern Unused variables are errors, not warnings. The builder hub treats declared but unused variables as compilation errors. Avoid destructuring fields you do not use: Safe dependency versions (compatible with TS 3.9.7) Use resolutions in node/package.json to pin transitive dependencies to versions that do not ship modern .d.ts syntax. The /<package pattern pins nested copies too. Package Safe version First broken version Reason @types/node 12.20.55 13.x+ (some APIs) Modern syntax in .d.ts @types/express serve static core 4.17.2 4.17.13+ Template literal types @types/express 4.17.10 4.17.11+ Depends on @types/express serve static core@^4.17.18 @types/koa 2.15.0 3.x import type ... = require() @opentelemetry/api 1.0.4 Newer versions TS 4.x syntax @types/serve static 1.15.0 Newer versions Transitive dependency issues Diagnosing new broken packages: if the build fails with errors in .d.ts files from node modules , identify the package from the error path, test older versions until you find one without modern syntax, and add it to both devDependencies and resolutions (with /<package pattern). Detection If the generated code uses any syntax from the table above, or if package.json lacks resolutions for type packages, STOP and fix before attempting vtex link . Constraint: configuration.json must use only valid schema fields and correct customFields format The paymentProvider builder validates configuration.json against a strict schema. Unknown fields cause build errors. The customFields[].options array for select type fields must use text and value keys — never label . Why this matters Invalid fields like usesTestSuite or useAntifraud (if not in the current schema) cause immediate vtex link failure. Using label instead of text in select options silently breaks the Admin UI or fails validation. Canonical fields (verify against current VTEX documentation): name (required), serviceUrl (auto on IO), implementsOAuth , implementsSplit , usesProviderHeadersName , usesBankInvoiceEnglishName , usesSecureProxy , requiresDocument , acceptSplitPartialRefund , usesAutoSettleOptions , paymentMethods , customFields . Fields known to break the build: usesTestSuite (does not exist in the schema). Correct customFields with select Wrong customFields Detection If configuration.json contains keys not in the canonical list, or uses label instead of text in select options, STOP and fix before build. Constraint: Declare the paymentProvider builder and a real connector identity in configuration.json IO connectors MUST include the paymentProvider builder in manifest.json and a paymentProvider/configuration.json with a non placeholder name and accurate paymentMethods . Do not ship the literal placeholder "MyConnector" (or equivalent) as production configuration. Why this matters Without the builder, PPP routes and Gateway policies are not wired. A placeholder name breaks Admin, affiliations, and homologation. Detection If manifest.json lacks paymentProvider , or configuration.json still uses example placeholder names, stop and fix before publishing. Correct Wrong Constraint: Register PPP routes only through PaymentProviderService with a PaymentProvider implementation The service MUST wrap a class extending PaymentProvider from @vtex/payment provider so standard PPP paths are registered. Do not hand roll the same route surface without the package unless VTEX explicitly prescribes an alternative. Why this matters Missed or mismatched routes break Gateway calls and homologation; the package keeps handlers aligned with the protocol. Detection If node/index.ts exposes PPP paths manually and does not instantiate PaymentProviderService with the connector class, reconcile with the documented pattern. Correct Wrong Constraint: PaymentProviderService clients field requires { implementation, options } — not the class directly When passing custom IOClients to PaymentProviderService , the clients field expects an object with implementation (the class) and options (retry/timeout config), following the ServiceConfig interface from @vtex/api . Passing the class directly causes a runtime error. Why this matters This is a common mistake that produces a confusing runtime error instead of a clear type error, since the PPF types may not enforce this strictly. Correct Wrong Constraint: Use this.retry(request) for Gateway retry on IO Where the PPP flow requires retry semantics on IO, handlers MUST invoke this.retry(request) as specified in the protocol — not a custom retry helper that bypasses the framework. Why this matters "The Gateway expects framework driven retry behavior; omitting it causes inconsistent authorization and settlement behavior." Detection Search payment handlers for protocol retry cases; if retries are implemented without this.retry , fix before release. Correct Wrong Constraint: Forward card authorization calls through Secure Proxy on IO with allowlisted destinations For card flows on IO with usesSecureProxy behavior, proxied HTTP calls MUST go through SecureExternalClient (or equivalent VTEX pattern), MUST pass secureProxy set to the secureProxyUrl from the payment request, and MUST target a VTEX allowlisted PCI endpoint. Only application/json or application/x www form urlencoded bodies are supported. If usesSecureProxy is false, the provider must be PCI certified and supply AOC for serviceUrl per VTEX. Why this matters "Skipping Secure Proxy or wrong content types breaks PCI scope, proxy validati