Giter VIP home page Giter VIP logo

payment-provider-example's Introduction

Payment Provider Framework (IO)

⚠️ Disclaimer

This is a feature in BETA stage, which means it's on a testing phase. In case there is a new scenario that PPF is not ready, our team will take some time to perform an investigation. If it's a case that need the development of anything new, this will enter the process of prioritization of the product team. This can take some time, so we don't recommend the use of this Beta version of PPF for connectors related to stores with rollout date close (less than 3 months).

🐣 Getting Started

⬇️ Cloning base repository

If you're starting a brand new project, we recommend you clone the example repository, as it already has all the basic configuration setup.

🆕 Updating project

Your first step should be to run the following command on your node folder:

yarn add @vtex/payment-provider

Afterwards, go to your package.json and make sure it has been added as a dependency with the correct version:

"@vtex/payment-provider": "1.x",

Also check in the package.json is the version of vtex/api, which should be listed in the devDependencies as follows:

"@vtex/api": "6.x",

(When linking your app, this version might get updated to a later 6.x version, which is fine.)

In case it's not listed as a devDependency, run the following command on your node folder:

yarn add -D @vtex/api

ℹ️ Info: If you get any type errors or conflicts in your project related to @vtex/api, follow these steps to resolve the problem: delete the node_modules folder and the yarn.lock file from both your project root and your project's node folder, then run the command yarn install -f in both folders.

Lastly, in your manifest.json, you should check the builders section, in which you must include the paymentProvider in it's current version:

"builders": {
  "node": "6.x", 
  "paymentProvider": "1.x"
}

ℹ️ Info: This will add policies to callback the Payment Gateway APIs and also expose Payment Provider protocol routes.

Now, in order to create your service, you must implement your payment provider connector and the service itself. To help you with them, keep reading the next sections.

💳 Payment Provider

This is an abstract class with the signatures of the routes functions required in your connector, according to the protocol.

You must create a new class extending the PaymentProvider, which must implement a function for each route. The functions will receive the request body (when there is one) as a parameter and the response must be returned as an object, such as the example shown below:

import {
	PaymentProvider,
	// ...
} from '@vtex/payment-provider'

class YourPaymentConnector extends PaymentProvider {

	// ... implementation of the other routes functions
}

Typescript should automatically check for typing errors, but if you need, you can check the requests and responses signatures here.

🏗️ Payment Provider Builder

In order to specify which payment methods the connector will accept to process, you need to create a folder named paymentProvider using the following folder structure

node
paymentProvider
manifest.json

Then, inside paymentProvider folder you must create a file named configuration.json

node
paymentProvider
   |--configuration.json
manifest.json

Next, declare the accepted payment methods, for instance:

{
  "name": "MyConnector",
  "paymentMethods": [
    {
      "name": "Visa",
      "allowsSplit": "onCapture"
    },
    {
      "name": "American Express",
      "allowsSplit": "onCapture"
    },
    {
      "name": "Diners",
      "allowsSplit": "onCapture"
    },
    {
      "name": "Elo",
      "allowsSplit": "onCapture"
    },
    {
      "name": "Hipercard",
      "allowsSplit": "onCapture"
    },
    {
      "name": "Mastercard",
      "allowsSplit": "onCapture"
    },
    {
      "name": "BankInvoice",
      "allowsSplit": "onAuthorize"
    }
  ]
}

By doing this you don't need to declare /manifest or /payment-methods route, it will be implemented automatically by the builder.

⚙️️ Overriding Default Routes

You can also override the default generated routes by redeclaring it on service.json

{
  "memory": 256,
  "ttl": 10,
  "timeout": 10,
  "minReplicas": 2,
  "maxReplicas": 3,
  "routes": {
    "authorize": {
      "path": "/_v/api/my-connector/payments",
      "public": true
    },
    "cancel": {
      "path": "/_v/api/my-connector/payments/:paymentId/cancellations",
      "public": true
    },
    "settle": {
      "path": "/_v/api/my-connector/payments/:paymentId/settlements",
      "public": true
    },
    "refund": {
      "path": "/_v/api/my-connector/payments/:paymentId/refunds",
      "public": true
    },
    "inbound": {
      "path": "/_v/api/my-connector/payments/:paymentId/inbound/hooks",
      "public": true
    }
  }
}

Then you must specify which is the new serviceUrl on paymentProvider/configuration.json

{
  "name": "MyConnector",
  "serviceUrl": "/_v/api/my-connector",
  "paymentMethods": [
    {
      "name": "Visa",
      "allowsSplit": "onCapture"
    },
    {
      "name": "American Express",
      "allowsSplit": "onCapture"
    },
    {
      "name": "Diners",
      "allowsSplit": "onCapture"
    },
    {
      "name": "Elo",
      "allowsSplit": "onCapture"
    },
    {
      "name": "Hipercard",
      "allowsSplit": "onCapture"
    },
    {
      "name": "Mastercard",
      "allowsSplit": "onCapture"
    },
    {
      "name": "BankInvoice",
      "allowsSplit": "onAuthorize"
    }
  ]
}

⚠️ Important: Prefer using default generated routes!

⚙️️ Overriding the Manifest Route

The manifest route is special, it is automatically generated by the builder, our payment gateway exposes it as a proxy of your app.

Generally speaking, the manifest route makes no difference at runtime, and if you have a use case to override the default route tell us.

But, if you want to override it anyway you have to add special parameters on it:

{
  "memory": 256,
  "ttl": 10,
  "timeout": 10,
  "minReplicas": 2,
  "maxReplicas": 3,
  "routes": {
    "manifest": {
        "path": "/_v/api/my-connector/manifest",
        "handler": "[email protected]/providerManifest",
        "headers": {
          "x-provider-app": "$appVendor.$appName@$appVersion"
        },
        "public": true
      }
  }
}

Pay attention on x-provider-app. It should be updated every time that your major changes. Example:

The same applies to payment-methods route.

You can also omit the handler and headers parameters, by doing it you will need to implement it by your own

⚙️ Available Configurable Options

Along with manifest fields (paymentMethods and customFields) there are another configurable options:

  • serviceUrl (required, default: auto-generated for IO Connectors)
    • A valid url (can include relative paths)
  • implementsOAuth (default: false)
    • true - The provider implements the configuration flow supporting OAuth.
    • false - The provider dosnt implements the configuration flow
  • implementsSplit (default: false)
    • true - The provider implements can receive recipients on payment flow (capture or authorization)
    • false - The provider doesn't implements the split flow
  • usesProviderHeadersName (default: true, for IOConnectors it should be true)
    • true - The provider will reiceve appKey and appToken headers as "x-provider-api-appKey" & "x-provider-api-appToken"
    • false - The provider will reiceve appKey and appToken headers as "x-vtex-api-appKey" & "x-vtex-api-appToken"
  • usesAntifraud (default: false)
    • true - The provider can be used along antifrauds.
    • false - The provider can't be used along antifrauds
  • usesBankInvoiceEnglishName (default: false)
  • name (required)
    • The connector name
  • usesSecureProxy (default: true)
    • true - The provider can process payment without being PCI-Certified, the connector will receive a secureProxyUrl on createPayment flow, and the card encrypted data.
    • false - The provider MUST be a PCI-Certified entity, and we should receive the AoC containing the provided serviceUrl. Apps implemented within VTEX IO cannot have the secureProxy disabled, this option only works for a configuration app.
  • requiresDocument (default: false)
    • true - The customer must include the card holder document on checkout. A new field will appear on checkout form.
    • false - The customer doesn't need to include card holder document.
  • acceptSplitPartialRefund (default: false)
    • true - Partial refund will be sent when payment split occurs.
    • false - The connector couldn't process partial refund when payment split occurs.
  • usesAutoSettleOptions (default: false)
    • true - The client will be able to choose the behaviour of the auto settlement in the VTEX admin configurations of the provider. The options available are the following: Use behavior recommended by the payment processor, Automatic capture immediately after payment authorization, Automatic capture immediately after anti-fraud analysis, Deactivated: Not automatically captured.
    • false - The connector won't have this dropdown configuration field for auto settlement.

🔁 Request a retry from Payment Gateway

A retry is required in order to develop your connector according to the protocol, so we built a function, which can be invoked like shown below:

this.retry(request)

Callback flow is replaced by retry flow. Payment Providers implemented using VTEX IO are not able to callback the Payment Gateway with the Payment status updated. Instead, the retry flow allow the connector to ask the Payment Gateway to call create payment route again. The connector should be able to respond approved/denied consistently.

image

💵 Payment Provider Service

This is a class that extends the Service from @vtex/api. You must invoke it passing the developed connector as a property of the first parameter and it will automatically setup the required routes for you.

import {
	PaymentProviderService,
} from '@vtex/payment-provider'

new PaymentProviderService({
	connector: YourPaymentConnector,
})

By default, the Payment Provider Service declares the following routes:

  • /payment-methods
  • /manifest
  • /payments
  • /settlements
  • /refunds
  • /cancellations
  • /inbounds

If your service requires any extra routes, you must declare them separately and use them as parameters:

new PaymentProviderService({
	routes: newRoutes,
	connector: YourPaymentConnector,
})

If your connector requires any extra clients, you must also pass them in the parameters along with the connector:

new PaymentProviderService({
	clients: NewClients,
	connector: YourPaymentConnector,
})

🔒 Using Secure Proxy

Those who aren't PCI-certified, could use Secure Proxy to make calls to a PCI-Certified endpoint.

⚠️ Important: The endpoint must be allowed by VTEX Secure Proxy by sending the AOC with the wanted endpoint.

⚠️ Important: Currently we only accept two Content-Types: application/json or application/x-www-form-urlencoded. Any other Content-Type will not be supported by the Secure Proxy.

In order to make calls over our Secure Proxy, you must:

  1. Extend SecureExternalClient abstract class. In the code example below, it means that VTEX allows http://my-pci-certified-domain.com as one of the trusted destinations by receiving its AOC.

    import { SecureExternalClient } from '@vtex/payment-provider'
    import type {
      InstanceOptions,
      IOContext
    } from '@vtex/api'
    export class MyPCICertifiedClient extends SecureExternalClient {
      constructor(protected context: IOContext, options?: InstanceOptions) {
        super('http://my-pci-certified-domain.com', context, options)
      }
      // ...
    }
  2. Set secure proxy URL on the request that you want to be proxied:

    import { SecureExternalClient, CardAuthorization } from '@vtex/payment-provider'
    import type {
      InstanceOptions,
      IOContext,
      RequestConfig,
    } from '@vtex/api'
    
    export class MyPCICertifiedClient extends SecureExternalClient {
      constructor(protected context: IOContext, options?: InstanceOptions) {
        super('http://my-pci-certified-domain.com', context, options)
      }
    
      public myPCIEndpoint = (cardRequest: CardAuthorization) => {
            return this.http.post(
                'my-pci-endpoint',
          {
                    holder: cardRequest.holderToken,
                    number: cardRequest.numberToken,
                  expiration: cardRequest.expiration,
                csc: cardRequest.cscToken
          },
          {
                    headers: {
                Authorization: 'my-pci-endpoint-authorization',
            },
                    secureProxy: cardRequest.secureProxyUrl,
          } as RequestConfig
        )
      }
    }

    ℹ️ Info: SecureProxyURL is received on createPayment flow

🛍️ Placing an Order with your new Connector

Now that we have a new connector ready to be use, we can test it entirely in the production flow using your store's checkout. To submit a request to add an account to test IO connectors, you can use the workflow "Allow Account to test" in the #provider-review slack channel.

Attention: The account MUST BE ALLOWED to use IO Connectors!

Attention: For processing NEW payment methods, their creation must be requested!

A prerequisite for this step is to have products for sale at your store for testing

  1. Launch a beta version of your connector, e.g. [email protected]

  2. Install the beta version on master workspace (wait ~1 hour)

  3. Go to https://${account}.myvtex.com/admin/pci-gateway/#/affiliations/vtex-payment-provider-test-v0/

    The format is: ${vendor}-${appName}-${appMajor}

    new-configuration-production

  4. Change the toggle configuration to Test

  5. Click save and refresh page

  6. Enter again in the saved configuration and you will notice that a new field appears, called workspace

  7. Set the workspace as you wish (you can leave it as master)

    new-configuration-test

  8. Configure a payment condition with your newly created connector and wait 10 minutes to appear on checkout!

📖 Making your connector available to everyone

⚠️ Important: If you want to make your connector available to all accounts, make sure to have the billing options field in your manifest

The publication process is made via app store, more info on how to do that here:

Submitting your app in the VTEX app store

After the homolog step is complete, your app needs to be installed in the account that wants to use it, and after that, a new affiliation will be available to configure it.

The app should be available at apps.vtex.com.

📄Upcoming documentation

payment-provider-example's People

Contributors

amb-lucas avatar guerreirobeatriz avatar kaisermann avatar manuellacorreia avatar mcandeia avatar midejesus avatar pedro-vasconcellos-vtex avatar renanmagagnin avatar vandialves avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

payment-provider-example's Issues

How to make a http call to payment service from connector.ts?

What are you trying to accomplish? Please describe.
We are trying integrate paypal payflow pro with vtex

What have you tried so far?
Tried to make an external api call in connector.ts file using this.http.post(). Not able to access http object in the context.
image
Additional info
Add extra content here (code samples, screenshots,...)

Can you pls let me know how to make http calls?

Account Workspace
your account your workspace

Add "usesAutoSettleOptions" configuration option to documentation

We use this paymentProvider/configuration.json property in the PayPalCP connector. If set to true, it causes a dropdown to appear in the Gateway Affiliation settings which controls the gateway's auto-settle behavior (including a way to disable auto-settle). This is not currently mentioned in this repo's documentation.

Unable to publish

Describe the bug
When trying to publish my test app using vtex-cli i get the following error:

Types for '[email protected]' specify a linked app, but this is unallowed on publish or on CI build

To Reproduce
Clone https://github.com/vtex-apps/ppp-decidir and try to publish Beta version.

Expected behavior
A beta version should be released using vtex-cli

Screenshots
Captura de Pantalla 2021-04-26 a la(s) 11 39 40

Desktop environment:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.