PCI Vault Logo
Stripe Example

This guide will get you started in sending your PCI Vault tokens to Stripe. The code examples for this guide can be found at https://github.com/pci-vault/golang-vue-example

Overview

In this guide we will cover:

  1. Capturing payment card data.
  2. Sending the captured data to Stripe.

Step 1: Capturing Card Data

Create an endpoint for capturing data using the POST /capture endpoint. For an example of how to do this using Golang: check this code. For more documentation on capture endpoints, check this documentation.

Once you have the unique capturing endpoint, you can use that to capture card data with our PCD Form.

The PCD Form will submit the user-entered data directly to PCI Vault, without ever touching your own servers. The submitted data will also be ready for submitting to Stripe, without having to undergo any transformation.

The data in the vault will be very similar to this JSON object:

{
  "card_number": "2343 2534 5456 4557",
  "card_holder": "Test Person",
  "cvv": "123",
  "expiry": "02/27",
  "expiry_year": "2027",
  "expiry_month": "02"
}

Keep this in mind for the next step, also storing the token and reference for the card to send to Stripe.

Step 2: Sending the Captured Data to Stripe

Send the data to Stripe using the POST /proxy/post endpoint. For an example of how to do this using Golang: check this code. For more documentation on proxy endpoints, check this documentation.

In order to POST the data Stripe, you will need to use the token and reference as stored in Step 1. You can specify the HTTP request to send to Stripe in JSON format like this:

{
  "request": {
    "body": "type=card\u0026card[number]={{card_number}}\u0026card[exp_month]={{expiry_month}}\u0026card[exp_year]={{expiry_year}}",
    "headers": [
      {
        "Content-Type": "application/x-www-form-urlencoded"
      },
      {
        "Authorization": "Basic c2tfdGVzdF9FeGFtcGxlU3RyaXBlS2V5MTMzNzo="
      }
    ],
    "method": "POST",
    "url": "https://api.stripe.com/v1/sources"
  },
  "webhook": {
    "url": "https://reply-to.me/example"
  }
}

This example request will create a source at Stripe that can be charged at a later date. You can change the url if you want to do something else.

Note that the body on the request JSON is specified as

type=card&card[number]={{card_number}}&card[exp_month]={{expiry_month}}&card[exp_year]={{expiry_year}}

This is a mustache template that (for our example) will resolve to

type=card&card%5Bnumber%5D=2343 2534 5456 4557&card%5Bexp_month%5D=02&card%5Bexp_year%5D=2027

before being sent to Stripe.

It is also possible and recommended to add webhook details. The response from Stripe will be forwarded to the given webhook. A successful call to Stripe will generate a webhook body like this:

{
  "headers": [
    {
      "Access-Control-Expose-Headers": "Request-Id, Stripe-Manage-Version, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required"
    },
    {
      "Idempotency-Key": "55feb4ff-0b91-4894-96e0-ae938b3dc28e"
    },
    {
      "Request-Id": "req_tlJ0eneDD5auHu"
    },
    {
      "Stripe-Should-Retry": "false"
    },
    {
      "Content-Type": "application/json"
    },
    {
      "Cache-Control": "no-cache, no-store"
    },
    {
      "Original-Request": "req_tlJ0eneDD5auHu"
    },
    {
      "Content-Length": "946"
    },
    {
      "Access-Control-Allow-Credentials": "true"
    },
    {
      "Access-Control-Max-Age": "300"
    },
    {
      "Stripe-Version": "2019-03-14"
    },
    {
      "Strict-Transport-Security": "max-age=63072000; includeSubDomains; preload"
    },
    {
      "Date": "Thu, 26 Jan 2023 09:31:18 GMT"
    },
    {
      "Access-Control-Allow-Methods": "GET, POST, HEAD, OPTIONS, DELETE"
    },
    {
      "Access-Control-Allow-Origin": "*"
    },
    {
      "Server": "nginx"
    }
  ],
  "body": "{\n  \"id\": \"src_1MURndBXqPmQKuMXJ6YLEgxx\",\n  \"object\": \"source\",\n  \"amount\": null,\n  \"card\": {\n    \"address_line1_check\": null,\n    \"address_zip_check\": null,\n    \"brand\": \"MasterCard\",\n    \"country\": null,\n    \"cvc_check\": null,\n    \"dynamic_last4\": null,\n    \"exp_month\": 2,\n    \"exp_year\": 2027,\n    \"fingerprint\": \"5SYfsE30rhbPsvSF\",\n    \"funding\": \"unknown\",\n    \"last4\": \"4557\",\n    \"name\": null,\n    \"three_d_secure\": \"optional\",\n    \"tokenization_method\": null\n  },\n  \"client_secret\": \"src_client_secret_7ePbhdmIcfV1aiLZSw9QUMAZ\",\n  \"created\": 1674725477,\n  \"currency\": null,\n  \"flow\": \"none\",\n  \"livemode\": false,\n  \"metadata\": {},\n  \"owner\": {\n    \"address\": null,\n    \"email\": null,\n    \"name\": null,\n    \"phone\": null,\n    \"verified_address\": null,\n    \"verified_email\": null,\n    \"verified_name\": null,\n    \"verified_phone\": null\n  },\n  \"statement_descriptor\": null,\n  \"status\": \"chargeable\",\n  \"type\": \"card\",\n  \"usage\": \"reusable\"\n}",
  "status_code": 200
}