Third Party Vaulting

In addition to the built-in credit card vault, Spreedly also supports a variety of third party vaults. There are a few use cases for third party vaults that stand out:

  • If you want to store cards in multiple vaults for extra redundancy, the Third Party Vault API enables you to easily vault cards with two or more vaulting providers without having to leave the comfort of the Spreedly API.
  • If you would like to export credit cards when you or one of your customers is leaving for another payments provider.

Supported Gateways

We support third party vaulting at the following gateways:

If you’d like to vault against a gateway that’s not listed here, drop us a line.

Storing

Given a provisioned gateway and existing payment method we could just call retain on the payment method and be done with it, but in this case we want to vault the credit card in the gateway vault instead (or in addition to; you can of course do both), so we’ll next call store on the gateway.

This transaction copies the payment method information from the Spreedly vault to the gateway’s vault and creates a new Spreedly payment method to represent the gateway’s version. The reference to the payment method at the gateway is called a ThirdPartyToken and is a separate payment method from the original payment method. It is up to you to manage the lifecycle of these linked payment methods – Spreedly does not keep them in sync in any way.


curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/store.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<transaction>
    <payment_method_token>EEifwic1wrGaHaRrdBhfLlYqecZ</payment_method_token>
  </transaction>'

In reply receive:


<transaction>
  <created_at type="dateTime">2017-07-27T17:53:22Z</created_at>
  <updated_at type="dateTime">2017-07-27T17:53:22Z</updated_at>
  <succeeded type="boolean">true</succeeded>
  <token>M6i0pval4KIZBBBGz16ZOqCVhWh</token>
  <state>succeeded</state>
  <gateway_specific_fields nil="true"/>
  <gateway_specific_response_fields>
  </gateway_specific_response_fields>
  <transaction_type>Store</transaction_type>
  <third_party_token nil="true"/>
  <gateway_transaction_id>58</gateway_transaction_id>
  <gateway_latency_ms type="integer">0</gateway_latency_ms>
  <message key="messages.transaction_succeeded">Succeeded!</message>
  <gateway_token>T11bJAANtTWnxl36GYjKWvbNK0g</gateway_token>
  <payment_method>
    <token>2MPedsuenG2o8yFfrsdOBWmOuEf</token>
    <created_at type="dateTime">2017-07-27T17:53:22Z</created_at>
    <updated_at type="dateTime">2017-07-27T17:53:22Z</updated_at>
    <gateway_type>test</gateway_type>
    <storage_state>retained</storage_state>
    <third_party_token>test_vault:4111111111111111</third_party_token>
    <payment_method_type>third_party_token</payment_method_type>
    <errors>
    </errors>
  </payment_method>
  <basis_payment_method>
    <token>EToYqm9L2xXQY0wKt9zh1NO0jlX</token>
    <created_at type="dateTime">2017-07-27T17:53:22Z</created_at>
    <updated_at type="dateTime">2017-07-27T17:53:22Z</updated_at>
    <email nil="true"/>
    <data nil="true"/>
    <storage_state>cached</storage_state>
    <test type="boolean">true</test>
    <last_four_digits>1111</last_four_digits>
    <first_six_digits>411111</first_six_digits>
    <card_type>visa</card_type>
    <first_name>Bob</first_name>
    <last_name>Smith</last_name>
    <month type="integer">2</month>
    <year type="integer">2020</year>
    <address1 nil="true"/>
    <address2 nil="true"/>
    <city nil="true"/>
    <state nil="true"/>
    <zip nil="true"/>
    <country nil="true"/>
    <phone_number nil="true"/>
    <company nil="true"/>
    <full_name>Bob Smith</full_name>
    <eligible_for_card_updater type="boolean">true</eligible_for_card_updater>
    <shipping_address1 nil="true"/>
    <shipping_address2 nil="true"/>
    <shipping_city nil="true"/>
    <shipping_state nil="true"/>
    <shipping_zip nil="true"/>
    <shipping_country nil="true"/>
    <shipping_phone_number nil="true"/>
    <payment_method_type>credit_card</payment_method_type>
    <errors>
    </errors>
    <verification_value>XXX</verification_value>
    <number>XXXX-XXXX-XXXX-1111</number>
    <fingerprint>e3cef43464fc832f6e04f187df25af497994</fingerprint>
  </basis_payment_method>
  <response>
    <success type="boolean">true</success>
    <message>Successful store</message>
    <avs_code nil="true"/>
    <avs_message nil="true"/>
    <cvv_code nil="true"/>
    <cvv_message nil="true"/>
    <pending type="boolean">false</pending>
    <result_unknown type="boolean">false</result_unknown>
    <error_code></error_code>
    <error_detail nil="true"/>
    <cancelled type="boolean">false</cancelled>
    <fraud_review nil="true"/>
    <created_at type="dateTime">2017-07-27T17:53:22Z</created_at>
    <updated_at type="dateTime">2017-07-27T17:53:22Z</updated_at>
  </response>
</transaction>


env = Spreedly::Environment.new('C7cRfNJGODKh4Iu5Ox3PToKjniY', '4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ', base_url: 'https://core.spreedly.com')
env.store_on_gateway("LlkjmEk0xNkcWrNixXa1fvNoTP4", "56wyNnSmuA6CWYP7w0MiYCVIbW6")

In reply receive:


#<Spreedly::Store:0x007fe332b17368
@token="EGi7bBA8f01uMlfjjKD2lltB40",
@created_at="2017-07-27T17:53:23Z",
@updated_at="2017-07-27T17:53:23Z",
@state="succeeded",
@message="Succeeded!",
@succeeded="true",
@payment_method,=
#<Spreedly::ThirdPartyToken:0x007fe332a34ba8
@token="H5MWfPUH8DYYLMHrvvIVcicpR6z",
@created_at="2017-07-27T17:53:23Z",
@updated_at="2017-07-27T17:53:23Z",
@gateway_type="test",
@storage_state="retained",
@third_party_token="test_vault:4111111111111111">,
@basis_payment_method,=
#<Spreedly::CreditCard:0x007fe33296a010
@token="1rpKvP8zOUhj4Y9EDrIoIYQzzD5",
@created_at="2017-06-26T17:04:38Z",
@updated_at="2017-07-27T17:53:23Z",
@email="joey@example.com",
@storage_state="retained",
@data="<my_payment_method_identifier>448</my_payment_method_identifier>\n      <extra_stuff>\n        <some_other_things>Can be anything really</some_other_things>\n      </extra_stuff>",
@first_name="Newfirst",
@last_name="Newlast",
@full_name="Newfirst Newlast",
@month="3",
@year="2032",
@number="XXXX-XXXX-XXXX-1111",
@last_four_digits="1111",
@first_six_digits="411111",
@card_type="visa",
@verification_value="",
@address1="",
@address2="",
@city="",
@state="",
@zip="",
@country="",
@phone_number="",
@company="",
@fingerprint="e3cef43464fc832f6e04f187df25af497994",
@eligible_for_card_updater="true",
@errors=[]>,
@response,=
#<Spreedly::Response:0x007fe3328b06d8
@success="true",
@pending="false",
@cancelled="false",
@fraud_review="",
@created_at="2017-07-27T17:53:23Z",
@updated_at="2017-07-27T17:53:23Z",
@message="Successful store",
@avs_code="",
@avs_message="",
@cvv_code="",
@cvv_message="",
@error_code="",
@error_detail="">>

The store transaction takes a Spreedly payment method and returns a ThirdPartyToken payment method. Since tokens are gateway specific, ThirdPartyToken payment methods are locked to the gateway type they were created against, and you’ll receive an error if you try to use them with the wrong gateway.

You’ll notice that the ThirdPartyToken payment method has a field called third_party_token. This is the unique ID of the payment method on the gateway side. You can use this ID if you’d like to interact with the payment methods in the third party vault separately from Spreedly.

Use

Once you have a ThirdPartyToken in hand, you can use it just like any other payment method. Let’s run a purchase:


curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<transaction>
    <amount>100</amount>
    <currency_code>USD</currency_code>
    <payment_method_token>2MPedsuenG2o8yFfrsdOBWmOuEf</payment_method_token>
  </transaction>'

And it works just as expected:


<transaction>
  <on_test_gateway type="boolean">true</on_test_gateway>
  <created_at type="dateTime">2017-07-27T17:55:55Z</created_at>
  <updated_at type="dateTime">2017-07-27T17:55:55Z</updated_at>
  <succeeded type="boolean">true</succeeded>
  <state>succeeded</state>
  <token>SG45LtL8BqzilXHEByVTjAEemsG</token>
  <transaction_type>Purchase</transaction_type>
  <order_id nil="true"/>
  <ip nil="true"/>
  <description nil="true"/>
  <email nil="true"/>
  <merchant_name_descriptor nil="true"/>
  <merchant_location_descriptor nil="true"/>
  <gateway_specific_fields nil="true"/>
  <gateway_specific_response_fields>
  </gateway_specific_response_fields>
  <gateway_transaction_id>48</gateway_transaction_id>
  <gateway_latency_ms type="integer">0</gateway_latency_ms>
  <amount type="integer">100</amount>
  <currency_code>USD</currency_code>
  <retain_on_success type="boolean">false</retain_on_success>
  <payment_method_added type="boolean">false</payment_method_added>
  <message key="messages.transaction_succeeded">Succeeded!</message>
  <gateway_token>T11bJAANtTWnxl36GYjKWvbNK0g</gateway_token>
  <shipping_address>
    <name nil="true"/>
    <address1 nil="true"/>
    <address2 nil="true"/>
    <city nil="true"/>
    <state nil="true"/>
    <zip nil="true"/>
    <country nil="true"/>
    <phone_number nil="true"/>
  </shipping_address>
  <response>
    <success type="boolean">true</success>
    <message>Successful purchase</message>
    <avs_code nil="true"/>
    <avs_message nil="true"/>
    <cvv_code nil="true"/>
    <cvv_message nil="true"/>
    <pending type="boolean">false</pending>
    <result_unknown type="boolean">false</result_unknown>
    <error_code></error_code>
    <error_detail nil="true"/>
    <cancelled type="boolean">false</cancelled>
    <fraud_review nil="true"/>
    <created_at type="dateTime">2017-07-27T17:55:55Z</created_at>
    <updated_at type="dateTime">2017-07-27T17:55:55Z</updated_at>
  </response>
  <api_urls>
  </api_urls>
  <payment_method>
    <token>2MPedsuenG2o8yFfrsdOBWmOuEf</token>
    <created_at type="dateTime">2017-07-27T17:53:22Z</created_at>
    <updated_at type="dateTime">2017-07-27T17:53:22Z</updated_at>
    <gateway_type>test</gateway_type>
    <storage_state>retained</storage_state>
    <third_party_token>test_vault:4111111111111111</third_party_token>
    <payment_method_type>third_party_token</payment_method_type>
    <errors>
    </errors>
  </payment_method>
</transaction>

Custom token

Some gateways support specifying your own unique token for the vaulted payment method, and you can leverage that by passing third_party_token when calling store:


curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/store.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<transaction>
    <payment_method_token>EEifwic1wrGaHaRrdBhfLlYqecZ</payment_method_token>
    <third_party_token>123</third_party_token>
  </transaction>'

<transaction>
  <created_at type="dateTime">2017-07-27T17:53:24Z</created_at>
  <updated_at type="dateTime">2017-07-27T17:53:24Z</updated_at>
  <succeeded type="boolean">true</succeeded>
  <token>3vQADWBbNlw0r9NW25t3gnQ5OPu</token>
  <state>succeeded</state>
  <gateway_specific_fields nil="true"/>
  <gateway_specific_response_fields>
  </gateway_specific_response_fields>
  <transaction_type>Store</transaction_type>
  <third_party_token>123</third_party_token>
  <gateway_transaction_id>49</gateway_transaction_id>
  <gateway_latency_ms type="integer">0</gateway_latency_ms>
  <message key="messages.transaction_succeeded">Succeeded!</message>
  <gateway_token>T11bJAANtTWnxl36GYjKWvbNK0g</gateway_token>
  <payment_method>
    <token>Ie5EsdQXd8XKU7HU4DG2PA8FBpI</token>
    <created_at type="dateTime">2017-07-27T17:53:24Z</created_at>
    <updated_at type="dateTime">2017-07-27T17:53:24Z</updated_at>
    <gateway_type>test</gateway_type>
    <storage_state>retained</storage_state>
    <third_party_token>test_vault:4111111111111111:123</third_party_token>
    <payment_method_type>third_party_token</payment_method_type>
    <errors>
    </errors>
  </payment_method>
  <basis_payment_method>
    <token>XTCZd0hH1lRicJ8HsmkdmAzdlMC</token>
    <created_at type="dateTime">2017-07-27T17:53:23Z</created_at>
    <updated_at type="dateTime">2017-07-27T17:53:24Z</updated_at>
    <email nil="true"/>
    <data nil="true"/>
    <storage_state>cached</storage_state>
    <test type="boolean">true</test>
    <last_four_digits>1111</last_four_digits>
    <first_six_digits>411111</first_six_digits>
    <card_type>visa</card_type>
    <first_name>Bob</first_name>
    <last_name>Smith</last_name>
    <month type="integer">2</month>
    <year type="integer">2020</year>
    <address1 nil="true"/>
    <address2 nil="true"/>
    <city nil="true"/>
    <state nil="true"/>
    <zip nil="true"/>
    <country nil="true"/>
    <phone_number nil="true"/>
    <company nil="true"/>
    <full_name>Bob Smith</full_name>
    <eligible_for_card_updater type="boolean">true</eligible_for_card_updater>
    <shipping_address1 nil="true"/>
    <shipping_address2 nil="true"/>
    <shipping_city nil="true"/>
    <shipping_state nil="true"/>
    <shipping_zip nil="true"/>
    <shipping_country nil="true"/>
    <shipping_phone_number nil="true"/>
    <payment_method_type>credit_card</payment_method_type>
    <errors>
    </errors>
    <verification_value>XXX</verification_value>
    <number>XXXX-XXXX-XXXX-1111</number>
    <fingerprint>e3cef43464fc832f6e04f187df25af497994</fingerprint>
  </basis_payment_method>
  <response>
    <success type="boolean">true</success>
    <message>Successful store</message>
    <avs_code nil="true"/>
    <avs_message nil="true"/>
    <cvv_code nil="true"/>
    <cvv_message nil="true"/>
    <pending type="boolean">false</pending>
    <result_unknown type="boolean">false</result_unknown>
    <error_code></error_code>
    <error_detail nil="true"/>
    <cancelled type="boolean">false</cancelled>
    <fraud_review nil="true"/>
    <created_at type="dateTime">2017-07-27T17:53:24Z</created_at>
    <updated_at type="dateTime">2017-07-27T17:53:24Z</updated_at>
  </response>
</transaction>

Since this is the test gateway it joins the custom id together with its internal token that allows the payment method to function, separated by :, but for (most) production gateways you would see the exact token you specified used. That said, if you need to interact with the third_party_token value, you should assume that the gateway can munge it and thus you should use the final value on the ThirdPartyToken payment method that is returned.