Braintree Gateway Guide

close

Services and Compatibility

Payment Gateway Company Name:
Braintree
Services that work with Spreedly:
  • Braintree
Supported operations:
Purchase, Authorize, Capture, Refund, Void, Verify, Store, General Credit
Supported payment types:
Credit Card, Apple Pay, Google Pay, Bank Account, Paypal, Venmo
Spreedly 3DS2 Global Supported
Yes
Gateway Specific 3DS2 Supported
Yes
Populate MIT GSF Support
Yes (Beta)
Regions:
Asia Pacific, Europe, North America
API endpoint URL:
Multiple; contact success@spreedly.com for more information

Authentication and Security

Specific names for credentials:
orange mode:
Login, Password
blue mode:
Merchant Account ID, Merchant ID, Public Key, Private Key

Onboarding Merchants in:

Additional Notes

As noted above, Braintree is supported on Spreedly 3DS2 Global. In order to register with our 3DS2 Global solution certain data fields are necessary to register. In order to obtain the necessary MID and ABIN fields from Braintree to onboard with Spreedly 3DS2 Global, please reach out to success@spreedly.com.

Spreedly’s documentation expects the blue mode authentication information above; the orange mode information exists above for posterity but is no longer supported by Braintree.

Use of ACH bank account payment methods has specific requirements.

General credit transactions are disabled on Braintree merchant accounts by default. To enable this transaction type, please contact Braintree.

Currency restrictions

It is important to note that only one currency is permitted per merchant account; a separate gateway token is required for each currency you wish to support, and thus merchant account you need. If you send a different currency than what the merchant account is configured for, the transaction will display it as the attempted currency, but Braintree will in fact process the amount as the currency configured for that merchant account, with no conversion.

Adding a Braintree gateway

You just need to supply a merchant_id, public_key, and private_key:


curl https://core.spreedly.com/v1/gateways.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<gateway>
        <gateway_type>braintree</gateway_type>
        <mode>blue</mode>
        <merchant_id>MyMerchantId</merchant_id>
        <public_key>MyPublicKey</public_key>
        <private_key>MyPrivateKey</private_key>
      </gateway>'

<gateway>
  <token>Fdk89EZ7GUNtnjxhHaOepjzIy6p</token>
  <gateway_type>braintree</gateway_type>
  <name>Braintree</name>
  <description nil="true"/>
  <merchant_profile_key nil="true"/>
  <sub_merchant_key nil="true"/>
  <merchant_id>MyMerchantId</merchant_id>
  <public_key>MyPublicKey</public_key>
  <merchant_account_id nil="true"/>
  <characteristics>
    <supports_purchase type="boolean">true</supports_purchase>
    <supports_authorize type="boolean">true</supports_authorize>
    <supports_capture type="boolean">true</supports_capture>
    <supports_credit type="boolean">true</supports_credit>
    <supports_general_credit type="boolean">true</supports_general_credit>
    <supports_void type="boolean">true</supports_void>
    <supports_adjust type="boolean">false</supports_adjust>
    <supports_verify type="boolean">true</supports_verify>
    <supports_reference_purchase type="boolean">false</supports_reference_purchase>
    <supports_purchase_via_preauthorization type="boolean">false</supports_purchase_via_preauthorization>
    <supports_offsite_purchase type="boolean">false</supports_offsite_purchase>
    <supports_offsite_authorize type="boolean">false</supports_offsite_authorize>
    <supports_offsite_synchronous_purchase type="boolean">true</supports_offsite_synchronous_purchase>
    <supports_offsite_synchronous_authorize type="boolean">true</supports_offsite_synchronous_authorize>
    <supports_3dsecure_purchase type="boolean">false</supports_3dsecure_purchase>
    <supports_3dsecure_authorize type="boolean">false</supports_3dsecure_authorize>
    <supports_3dsecure_2_mpi_purchase type="boolean">true</supports_3dsecure_2_mpi_purchase>
    <supports_3dsecure_2_mpi_authorize type="boolean">true</supports_3dsecure_2_mpi_authorize>
    <supports_store type="boolean">true</supports_store>
    <supports_remove type="boolean">false</supports_remove>
    <supports_fraud_review type="boolean">false</supports_fraud_review>
    <supports_network_tokenization type="boolean">true</supports_network_tokenization>
    <supports_populate_mit_fields type="boolean">true</supports_populate_mit_fields>
    <supports_inquire_by_gateway_transaction_id type="boolean">false</supports_inquire_by_gateway_transaction_id>
    <supports_inquire_by_order_id type="boolean">false</supports_inquire_by_order_id>
    <supports_transaction_retry type="boolean">true</supports_transaction_retry>
    <supports_stored_stored_credentials type="boolean">false</supports_stored_stored_credentials>
    <supports_stored_credentials type="boolean">true</supports_stored_credentials>
    <supports_card_scheme_ntid type="boolean">true</supports_card_scheme_ntid>
  </characteristics>
  <credentials>
    <credential>
      <name>merchant_id</name>
      <value>MyMerchantId</value>
    </credential>
    <credential>
      <name>public_key</name>
      <value>MyPublicKey</value>
    </credential>
    <credential>
      <name>merchant_account_id</name>
      <value nil="true"/>
    </credential>
  </credentials>
  <gateway_settings>
  </gateway_settings>
  <gateway_specific_fields>
    <gateway_specific_field>descriptor_name</gateway_specific_field>
    <gateway_specific_field>descriptor_phone</gateway_specific_field>
    <gateway_specific_field>descriptor_url</gateway_specific_field>
    <gateway_specific_field>service_fee_amount</gateway_specific_field>
    <gateway_specific_field>merchant_account_id</gateway_specific_field>
    <gateway_specific_field>hold_in_escrow</gateway_specific_field>
    <gateway_specific_field>customer_id</gateway_specific_field>
    <gateway_specific_field>custom_fields</gateway_specific_field>
    <gateway_specific_field>recurring</gateway_specific_field>
    <gateway_specific_field>transaction_source</gateway_specific_field>
    <gateway_specific_field>map_to_customer_id</gateway_specific_field>
    <gateway_specific_field>skip_advanced_fraud_checking</gateway_specific_field>
    <gateway_specific_field>tax_amount</gateway_specific_field>
    <gateway_specific_field>tax_exempt</gateway_specific_field>
    <gateway_specific_field>purchase_order_number</gateway_specific_field>
    <gateway_specific_field>shipping_amount</gateway_specific_field>
    <gateway_specific_field>discount_amount</gateway_specific_field>
    <gateway_specific_field>ships_from_postal_code</gateway_specific_field>
    <gateway_specific_field>line_items</gateway_specific_field>
    <gateway_specific_field>device_data</gateway_specific_field>
    <gateway_specific_field>skip_avs</gateway_specific_field>
    <gateway_specific_field>skip_cvv</gateway_specific_field>
    <gateway_specific_field>travel_data</gateway_specific_field>
    <gateway_specific_field>lodging_data</gateway_specific_field>
    <gateway_specific_field>allow_card_verification</gateway_specific_field>
    <gateway_specific_field>risk_data</gateway_specific_field>
    <gateway_specific_field>ach_mandate</gateway_specific_field>
    <gateway_specific_field>venmo_profile_id</gateway_specific_field>
    <gateway_specific_field>venmo_flow_type</gateway_specific_field>
    <gateway_specific_field>paypal_flow_type</gateway_specific_field>
    <gateway_specific_field>billing_agreement_description</gateway_specific_field>
    <gateway_specific_field>partial_capture</gateway_specific_field>
    <gateway_specific_field>locale</gateway_specific_field>
    <gateway_specific_field>paypal_custom_field</gateway_specific_field>
    <gateway_specific_field>paypal_description</gateway_specific_field>
  </gateway_specific_fields>
  <payment_methods>
    <payment_method>credit_card</payment_method>
    <payment_method>third_party_token</payment_method>
    <payment_method>apple_pay</payment_method>
    <payment_method>google_pay</payment_method>
    <payment_method>bank_account</payment_method>
    <payment_method>paypal</payment_method>
    <payment_method>venmo</payment_method>
  </payment_methods>
  <state>retained</state>
  <redacted type="boolean">false</redacted>
  <sandbox type="boolean">false</sandbox>
  <mode>blue</mode>
  <created_at type="dateTime">2023-09-05T13:59:10Z</created_at>
  <updated_at type="dateTime">2023-09-05T13:59:10Z</updated_at>
  <mode>blue</mode>
</gateway>


env = Spreedly::Environment.new('C7cRfNJGODKh4Iu5Ox3PToKjniY', '4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ', base_url: 'https://core.spreedly.com')
env.add_gateway(:braintree, mode: 'blue', merchant_id: 'MyMerchantID',
               public_key: 'MyPublicKey', private_key: 'MyPrivateKey')


#<Spreedly::Gateway:0x007fe33399d270
@token="aRSuBPhP5La4Lb6j6pFqT9cc1KA",
@created_at="2017-07-27T17:47:57Z",
@updated_at="2017-07-27T17:47:57Z",
@gateway_type="braintree",
@state="retained",
@name="Braintree",
@credentials={"merchant_id"=>"MyMerchantID", "public_key"=>"MyPublicKey", "merchant_account_id"=>""}>

You can also optionally specify a merchant_account_id if you have multiple merchant accounts processing against the same Braintree gateway account. You can do so like this:


curl https://core.spreedly.com/v1/gateways.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<gateway>
        <gateway_type>braintree</gateway_type>
        <mode>blue</mode>
        <merchant_id>MyMerchantId</merchant_id>
        <public_key>MyPublicKey</public_key>
        <private_key>MyPrivateKey</private_key>
        <merchant_account_id>My Merchant Account ID</merchant_account_id>
      </gateway>'

<gateway>
  <token>MtdkxlOLRj28NIz7W7KDuIpgO64</token>
  <gateway_type>braintree</gateway_type>
  <name>Braintree</name>
  <description nil="true"/>
  <merchant_profile_key nil="true"/>
  <sub_merchant_key nil="true"/>
  <merchant_id>MyMerchantId</merchant_id>
  <public_key>MyPublicKey</public_key>
  <merchant_account_id>My Merchant Account ID</merchant_account_id>
  <characteristics>
    <supports_purchase type="boolean">true</supports_purchase>
    <supports_authorize type="boolean">true</supports_authorize>
    <supports_capture type="boolean">true</supports_capture>
    <supports_credit type="boolean">true</supports_credit>
    <supports_general_credit type="boolean">false</supports_general_credit>
    <supports_void type="boolean">true</supports_void>
    <supports_adjust type="boolean">false</supports_adjust>
    <supports_verify type="boolean">true</supports_verify>
    <supports_reference_purchase type="boolean">false</supports_reference_purchase>
    <supports_purchase_via_preauthorization type="boolean">false</supports_purchase_via_preauthorization>
    <supports_offsite_purchase type="boolean">false</supports_offsite_purchase>
    <supports_offsite_authorize type="boolean">false</supports_offsite_authorize>
    <supports_offsite_synchronous_purchase type="boolean">true</supports_offsite_synchronous_purchase>
    <supports_offsite_synchronous_authorize type="boolean">true</supports_offsite_synchronous_authorize>
    <supports_3dsecure_purchase type="boolean">false</supports_3dsecure_purchase>
    <supports_3dsecure_authorize type="boolean">false</supports_3dsecure_authorize>
    <supports_3dsecure_2_mpi_purchase type="boolean">true</supports_3dsecure_2_mpi_purchase>
    <supports_3dsecure_2_mpi_authorize type="boolean">true</supports_3dsecure_2_mpi_authorize>
    <supports_store type="boolean">true</supports_store>
    <supports_remove type="boolean">false</supports_remove>
    <supports_fraud_review type="boolean">false</supports_fraud_review>
    <supports_network_tokenization type="boolean">false</supports_network_tokenization>
    <supports_populate_mit_fields type="boolean">true</supports_populate_mit_fields>
    <supports_inquire_by_gateway_transaction_id type="boolean">false</supports_inquire_by_gateway_transaction_id>
    <supports_inquire_by_order_id type="boolean">false</supports_inquire_by_order_id>
    <supports_transaction_retry type="boolean">true</supports_transaction_retry>
    <supports_stored_stored_credentials type="boolean">false</supports_stored_stored_credentials>
    <supports_stored_credentials type="boolean">true</supports_stored_credentials>
  </characteristics>
  <credentials>
    <credential>
      <name>merchant_id</name>
      <value>MyMerchantId</value>
    </credential>
    <credential>
      <name>public_key</name>
      <value>MyPublicKey</value>
    </credential>
    <credential>
      <name>merchant_account_id</name>
      <value>My Merchant Account ID</value>
    </credential>
  </credentials>
  <gateway_settings>
  </gateway_settings>
  <gateway_specific_fields>
    <gateway_specific_field>descriptor_name</gateway_specific_field>
    <gateway_specific_field>descriptor_phone</gateway_specific_field>
    <gateway_specific_field>descriptor_url</gateway_specific_field>
    <gateway_specific_field>service_fee_amount</gateway_specific_field>
    <gateway_specific_field>merchant_account_id</gateway_specific_field>
    <gateway_specific_field>hold_in_escrow</gateway_specific_field>
    <gateway_specific_field>customer_id</gateway_specific_field>
    <gateway_specific_field>custom_fields</gateway_specific_field>
    <gateway_specific_field>recurring</gateway_specific_field>
    <gateway_specific_field>transaction_source</gateway_specific_field>
    <gateway_specific_field>map_to_customer_id</gateway_specific_field>
    <gateway_specific_field>skip_advanced_fraud_checking</gateway_specific_field>
    <gateway_specific_field>tax_amount</gateway_specific_field>
    <gateway_specific_field>tax_exempt</gateway_specific_field>
    <gateway_specific_field>purchase_order_number</gateway_specific_field>
    <gateway_specific_field>shipping_amount</gateway_specific_field>
    <gateway_specific_field>discount_amount</gateway_specific_field>
    <gateway_specific_field>ships_from_postal_code</gateway_specific_field>
    <gateway_specific_field>line_items</gateway_specific_field>
    <gateway_specific_field>device_data</gateway_specific_field>
    <gateway_specific_field>skip_avs</gateway_specific_field>
    <gateway_specific_field>skip_cvv</gateway_specific_field>
    <gateway_specific_field>travel_data</gateway_specific_field>
    <gateway_specific_field>lodging_data</gateway_specific_field>
    <gateway_specific_field>allow_card_verification</gateway_specific_field>
    <gateway_specific_field>risk_data</gateway_specific_field>
    <gateway_specific_field>ach_mandate</gateway_specific_field>
    <gateway_specific_field>venmo_profile_id</gateway_specific_field>
    <gateway_specific_field>venmo_flow_type</gateway_specific_field>
    <gateway_specific_field>paypal_flow_type</gateway_specific_field>
    <gateway_specific_field>billing_agreement_description</gateway_specific_field>
    <gateway_specific_field>partial_capture</gateway_specific_field>
    <gateway_specific_field>locale</gateway_specific_field>
    <gateway_specific_field>paypal_custom_field</gateway_specific_field>
    <gateway_specific_field>paypal_description</gateway_specific_field>
  </gateway_specific_fields>
  <payment_methods>
    <payment_method>credit_card</payment_method>
    <payment_method>third_party_token</payment_method>
    <payment_method>apple_pay</payment_method>
    <payment_method>google_pay</payment_method>
    <payment_method>bank_account</payment_method>
    <payment_method>paypal</payment_method>
    <payment_method>venmo</payment_method>
  </payment_methods>
  <state>retained</state>
  <redacted type="boolean">false</redacted>
  <sandbox type="boolean">false</sandbox>
  <mode>blue</mode>
  <created_at type="dateTime">2023-06-06T17:08:23Z</created_at>
  <updated_at type="dateTime">2023-06-06T17:08:23Z</updated_at>
  <mode>blue</mode>
</gateway>


env = Spreedly::Environment.new('C7cRfNJGODKh4Iu5Ox3PToKjniY', '4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ', base_url: 'https://core.spreedly.com')
env.add_gateway(:braintree, mode: 'blue', merchant_id: 'MyMerchantID',
                public_key: 'MyPublicKey', private_key: 'MyPrivateKey',
                merchant_account_id: 'My Merchant Acount ID')


#<Spreedly::Gateway:0x007fe332b0b6f8
@token="H4fjJQBO7oxcdOgfVJpPWxGjEzw",
@created_at="2017-07-27T17:48:05Z",
@updated_at="2017-07-27T17:48:05Z",
@gateway_type="braintree",
@state="retained",
@name="Braintree",
@credentials={"merchant_id"=>"MyMerchantID", "public_key"=>"MyPublicKey", "merchant_account_id"=>"My Merchant Acount ID"}>

Third-party 3D Secure 2 auth data

Spreedly will automatically handle the field mapping for sending third-party 3DS2 authentication data to Braintree. For more information about how to use this feature, see the 3DS2 Third-party Authentication Guide. Spreedly fields map to the relevant Braintree fields as described in the following table.

Spreedly Field Braintree Field
three_ds_version three_d_secure_version
ecommerce_indicator eci_flag
authentication_value cavv
authentication_value_algorithm cavv_algorithm
directory_server_transaction_id ds_transaction_id
directory_response_status directory_response
authentication_response_status authentication_response

Gateway Specific 3D Secure 2

Spreedly also offers support for Braintree’s specific 3D Secure v2 implementation. To enable this functionality, you’ll need to include Braintree.js and the relevant 3DS scripts in your front-end page.

<script src="https://js.braintreegateway.com/web/3.97.1/js/client.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.97.1/js/three-d-secure.js"></script>
<script src="https://js.braintreegateway.com/web/3.97.1/js/hosted-fields.min.js"></script>

Complete 3DS2 transaction

To complete a 3DS2 transaction, particularly when using Braintree on the frontend, you’ll need to trigger the completion process via your backend using the designated complete endpoint.

curl https://core.spreedly.com/v1/transactions/spreedlyTransactionToken/complete.json \
 -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
 -H 'Content-Type: application/json' \
 -d '{
    "context": {
    "payment_method_nonce": <paymentMethodNonce>,
    }
  }'

How to Retrieve paymentMethodNonce:

In your browser console, you might find an object similar to this:

{
  action: "trigger-completion",
  context: {
    payment_method_nonce: <payment_method_nonce_value>
  },
  token: <token>
}

Extract the from this object. This value is needed to complete the transaction.

By following these steps and using the obtained paymentMethodNonce, you can trigger the completion of the 3DS2 transaction through your backend using the provided request.

For more detailed information to the 3DS2 gateway specific, refer to this documentation

Using ACH bank account payment methods

To be able to transact using Bank Account payment methods (aka ACH), two requirements must be met:

First, the bank account needs to be validated by Braintree. This requires the payment method to be Stored at Braintree. Attempting a non-Store transaction using a basic bank account payment will result in an error message.

Second, as part of the Store on a bank account, a validation process is performed at Braintree. This validation requires the inclusion of the gateway specific field ach_mandate. The content of this field must match specific language provided by Braintree. This language is to be shown to your customer as an acknowledgement and acceptance to use and verify their bank account information. For the specific language and details, see Braintree Authorization language.

If Braintree’s validation fails, the Store will result in a failure. Otherwise, you may use the Third Party Token payment method created by the Store to perform subsequent transactions.

Example

To make a purchase with a bank account:

1) Create the bank account in Spreedly’s vault as usual, using the payment methods end-point and get the payment method token. See an example response in the API Reference.

curl https://core.spreedly.com/v1/payment_methods.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<payment_method>
        <bank_account>
            <first_name>Jon</first_name>
            <last_name>Doe</last_name>
            <bank_name>Test Bank</bank_name>
            <bank_routing_number>021000021</bank_routing_number>
            <bank_account_number>9876543210</bank_account_number>
            <bank_account_type>checking</bank_account_type>
            <bank_account_holder_type>personal</bank_account_holder_type>
        </bank_account>
        <email>jon.doe@example.com</email>
        <data>
            <my_payment_method_identifier>448</my_payment_method_identifier>
            <extra_stuff>
                <some_other_things>Can be anything really</some_other_things>
            </extra_stuff>
        </data>
        <metadata>
          <key>String Value</key>
          <another_key>123</another_key>
          <final_key>true</final_key>
        </metadata>
      </payment_method>'

2) Use the resulting payment method token from step (1) to tokenize the bank account at the gateway, so it can be verified. Here you need to include the ach_mandate on the request. See an example response on the API Reference.

curl http://core.spreedly.test/v1/gateways/ABjT23qmrml1kFDivCDDhH48jAx/store.xml \
  -u 'Mq0RX3tcV03OQkEz5pkmIlkgVV4:9Py4mGPn2asff7FnBbuwaVaN1DuSzyQB17Tw9Y7wg6VPC4xHvvykprDY2ZL0rPI2' \
  -H 'Content-Type: application/xml' \
  -d '<transaction>
        <payment_method_token>7Gsv4oIUBMpfgMXWFzenhpa5vIE</payment_method_token>
        <gateway_specific_fields>
          <braintree>
            <ach_mandate>By clicking "Checkout", I authorize Braintree ....</ach_mandate>
          </braintree>
        </gateway_specific_fields>
      </transaction>'

3) This request will create a Third Party Token payment method that references the bank account vaulted at Braintree, which may be used for purchases as normal.

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

Gateway specific fields

When interacting with a Braintree gateway to run transactions, there are a number of gateway specific fields you can specify. See the details below the example for more information on each field.


curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/store.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<transaction>
        <payment_method_token>56wyNnSmuA6CWYP7w0MiYCVIbW6</payment_method_token>
        <amount>100</amount>
        <currency_code>USD</currency_code>
        <gateway_specific_fields>
          <braintree>
            <customer_id>103</customer_id>
            <descriptor_name>company*theproduct</descriptor_name>
            <descriptor_phone>1331131131</descriptor_phone>
            <descriptor_url>company.com</descriptor_url>
            <merchant_account_id>TheId</merchant_account_id>
            <hold_in_escrow>true</hold_in_escrow>
            <paypal_custom_field>item</paypal_custom_field>
            <paypal_description>sample</paypal_description>
            <recurring>true</recurring>
            <transaction_source>recurring</transaction_source>
            <service_fee_amount>23.44</service_fee_amount>
            <map_to_customer_id>true</map_to_customer_id>
            <skip_advanced_fraud_checking>true</skip_advanced_fraud_checking>
            <skip_avs>true</skip_avs>
            <skip_cvv>true</skip_cvv>
            <tax_amount>30</tax_amount>
            <tax_exempt>true</tax_exempt>
            <purchase_order_number>873645</purchase_order_number>
            <shipping_amount>200</shipping_amount>
            <discount_amount>300</discount_amount>
            <ships_from_postal_code>90210</ships_from_postal_code>
            <line_items>
              <![CDATA[
                [{"product_description": "coffee mug", "product_code": 1234}]
              ]]>
            </line_items>
            <device_data>device data</device_data>
            <travel_data>
              <travel_package>flight</travel_package>
              <departure_date>2050-07-22</departure_date>
              <lodging_check_in_date>2050-07-22</lodging_check_in_date>
              <lodging_check_out_date>2050-07-25</lodging_check_out_date>
              <lodging_name>Best Hotel Ever</lodging_name>
            </travel_data>
            <lodging_data>
              <folio_number>ABC123</folio_number>
              <check_in_date>2050-12-22</check_in_date>
              <check_out_date>2050-12-25</check_out_date>
              <room_rate>80.00</room_rate>
            </lodging_data>
            <allow_card_verification>true</allow_card_verification>
            <ach_mandate>By clicking "Checkout", I authorize Braintree ....</ach_mandate>
          </braintree>
        </gateway_specific_fields>
      </transaction>'

<transaction>
  <created_at type="dateTime">2023-03-10T21:27:28Z</created_at>
  <currency_code>USD</currency_code>
  <updated_at type="dateTime">2023-03-10T21:27:28Z</updated_at>
  <succeeded type="boolean">true</succeeded>
  <token>5y90jC81gbKWz7IYiGnpjYO1J24</token>
  <state>succeeded</state>
  <gateway_specific_fields>
    <braintree>
      <customer_id>103</customer_id>
      <descriptor_name>company*theproduct</descriptor_name>
      <descriptor_phone>1331131131</descriptor_phone>
      <descriptor_url>company.com</descriptor_url>
      <merchant_account_id>TheId</merchant_account_id>
      <hold_in_escrow>true</hold_in_escrow>
      <paypal_custom_field>item</paypal_custom_field>
      <paypal_description>sample</paypal_description>
      <recurring>true</recurring>
      <transaction_source>recurring</transaction_source>
      <service_fee_amount>23.44</service_fee_amount>
      <map_to_customer_id>true</map_to_customer_id>
      <skip_advanced_fraud_checking>true</skip_advanced_fraud_checking>
      <skip_avs>true</skip_avs>
      <skip_cvv>true</skip_cvv>
      <tax_amount>30</tax_amount>
      <tax_exempt>true</tax_exempt>
      <purchase_order_number>873645</purchase_order_number>
      <shipping_amount>200</shipping_amount>
      <discount_amount>300</discount_amount>
      <ships_from_postal_code>90210</ships_from_postal_code>
      <line_items>
        [{"product_description": "coffee mug", "product_code": 1234}]
      </line_items>
      <device_data>device data</device_data>
      <travel_data>
        <travel_package>flight</travel_package>
        <departure_date>2050-07-22</departure_date>
        <lodging_check_in_date>2050-07-22</lodging_check_in_date>
        <lodging_check_out_date>2050-07-25</lodging_check_out_date>
        <lodging_name>Best Hotel Ever</lodging_name>
      </travel_data>
      <lodging_data>
        <folio_number>ABC123</folio_number>
        <check_in_date>2050-12-22</check_in_date>
        <check_out_date>2050-12-25</check_out_date>
        <room_rate>80.00</room_rate>
      </lodging_data>
      <allow_card_verification>true</allow_card_verification>
      <ach_mandate>By clicking "Checkout", I authorize Braintree ....</ach_mandate>
    </braintree>
  </gateway_specific_fields>
  <gateway_specific_response_fields>
  </gateway_specific_response_fields>
  <transaction_type>Store</transaction_type>
  <third_party_token nil="true"/>
  <gateway_transaction_id>52</gateway_transaction_id>
  <gateway_latency_ms type="integer">1</gateway_latency_ms>
  <message key="messages.transaction_succeeded">Succeeded!</message>
  <gateway_token>T11bJAANtTWnxl36GYjKWvbNK0g</gateway_token>
  <gateway_type>test</gateway_type>
  <payment_method>
    <token>DjP6gofisYFgSAb8mbDFLUuWQrD</token>
    <created_at type="dateTime">2023-03-10T21:27:28Z</created_at>
    <updated_at type="dateTime">2023-03-10T21:27:28Z</updated_at>
    <gateway_type>test</gateway_type>
    <storage_state>retained</storage_state>
    <metadata nil="true"/>
    <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>1rpKvP8zOUhj4Y9EDrIoIYQzzD5</token>
    <created_at type="dateTime">2017-06-26T17:04:38Z</created_at>
    <updated_at type="dateTime">2023-03-10T21:27:28Z</updated_at>
    <email>joey@example.com</email>
    <data>
      <my_payment_method_identifier>448</my_payment_method_identifier>
      <extra_stuff>
        <some_other_things>Can be anything really</some_other_things>
      </extra_stuff>
    </data>
    <storage_state>retained</storage_state>
    <test type="boolean">true</test>
    <metadata>
      <key>string value</key>
    </metadata>
    <callback_url nil="true"/>
    <last_four_digits>1111</last_four_digits>
    <first_six_digits>411111</first_six_digits>
    <card_type>visa</card_type>
    <first_name>Newfirst</first_name>
    <last_name>Newlast</last_name>
    <month type="integer">3</month>
    <year type="integer">2032</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>Newfirst Newlast</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"/>
    <issuer_identification_number>41111111</issuer_identification_number>
    <click_to_pay type="boolean">false</click_to_pay>
    <payment_method_type>credit_card</payment_method_type>
    <errors>
    </errors>
    <verification_value></verification_value>
    <number>XXXX-XXXX-XXXX-1111</number>
    <fingerprint>e3cef43464fc832f6e04f187df25af497994</fingerprint>
    <stored_credential_usage>
      <test>
        <original_network_transaction_id>37be5367d6dbe4a88c9d</original_network_transaction_id>
        <network_transaction_id>37be5367d6dbe4a88c9d</network_transaction_id>
      </test>
    </stored_credential_usage>
  </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 nil="true"/>
    <error_detail nil="true"/>
    <cancelled type="boolean">false</cancelled>
    <fraud_review nil="true"/>
    <created_at type="dateTime">2023-03-10T21:27:28Z</created_at>
    <updated_at type="dateTime">2023-03-10T21:27:28Z</updated_at>
  </response>
</transaction>


env = Spreedly::Environment.new('C7cRfNJGODKh4Iu5Ox3PToKjniY', '4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ', base_url: 'https://core.spreedly.com')
env.purchase_on_gateway("LlkjmEk0xNkcWrNixXa1fvNoTP4", "56wyNnSmuA6CWYP7w0MiYCVIbW6", 4432,
  gateway_specific_fields: {
    braintree: {
      customer_id: "103",
      descriptor_name: "company*theproduct",
      descriptor_phone: "1331131131",
      descriptor_url: "company.com",
      merchant_account_id: "TheId",
      hold_in_escrow: "true",
      recurring: "true",
      service_fee_amount: "23.44",
      map_to_customer_id: "true",
      skip_advanced_fraud_checking: "true",
      risk_data: {
        customer_browser: "User-Agent Header",
        customer_ip: "127.0.0.1"
      }
    }
  }
)


#<Spreedly::Purchase:0x00007fde70125da8
@token="ILXCYXgZvoXawCaD9HO43moG0yq",
@created_at="2021-04-28T18:29:23Z",
@updated_at="2021-04-28T18:29:23Z",
@state="succeeded",
@message="Succeeded!",
@succeeded="true",
@order_id="",
@ip="",
@description="",
@gateway_token="T11bJAANtTWnxl36GYjKWvbNK0g",
@gateway_transaction_id="50",
@email="",
@transaction_type="Purchase",
@merchant_name_descriptor="",
@merchant_location_descriptor="",
@on_test_gateway="true",
@currency_code="USD",
@callback_url="",
@stored_credential_initiator="",
@stored_credential_reason_type="",
@amount="4432",
@response,=
#<Spreedly::Response:0x00007fde7015ae68
@success="true",
@pending="false",
@cancelled="false",
@fraud_review="",
@created_at="2021-04-28T18:29:23Z",
@updated_at="2021-04-28T18:29:23Z",
@message="Successful purchase",
@avs_code="",
@avs_message="",
@cvv_code="",
@cvv_message="",
@error_code="",
@error_detail="">,
@shipping_address,=
#<Spreedly::ShippingAddress:0x00007fde70129340
@name="Newfirst Newlast",
@address1="",
@address2="",
@city="",
@state="",
@zip="",
@country="",
@phone_number="">,
@gateway_specific_fields={:braintree=>{:customer_id=>"103", :descriptor_name=>"company*theproduct", :descriptor_phone=>"1331131131", :descriptor_url=>"company.com", :merchant_account_id=>"TheId", :hold_in_escrow=>"true", :recurring=>"true", :service_fee_amount=>"23.44", :map_to_customer_id=>"true", :skip_advanced_fraud_checking=>"true", :risk_data=>"\n        User-Agent Header\n        127.0.0.1\n      "}},
@gateway_specific_response_fields={},
@payment_method,=
#<Spreedly::CreditCard:0x00007fde701687c0
@token="1rpKvP8zOUhj4Y9EDrIoIYQzzD5",
@created_at="2017-06-26T17:04:38Z",
@updated_at="2021-04-26T18:48:29Z",
@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>",
@payment_method_type="credit_card",
@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=[]>>

Please refer to using a payment method for more information on how to send GSFs

Braintree customer ID

Braintree’s vault has a top-level concept of a Customer, and the Spreedly API allows limited interaction with the Customer when storing credit cards in Braintree’s vault.

If you specify the customer_id as a gateway specific field, the Spreedly API will use that customer id when adding the card, and if the customer already exists it will add the card to the customer rather than throwing a duplicate customer error.

Braintree dynamic descriptors

Braintree dynamic descriptors can be used by the merchant to define what will appear on the customer’s credit card statement for the purchase. You can specify the descriptor_name, descriptor_phone, and descriptor_url.

Service fee amount

You can specify a service_fee_amount.

Merchant account ID

You can specify a per-transaction merchant_account_id that will overide the default merchant_account_id.

Hold in escrow

You can specify hold_in_escrow. The merchant_account_id field MUST be submitted with this field.

Recurring

Set this optional gateway specific field to "true" to enable the recurring flag in authorize and purchase transactions. By default it’s disabled.

Transaction source

You can specify a transaction_source.

Map to customer ID

When using migrated payment methods created with Braintree customer_id as reference, set map_to_customer_id true on authorize and purchase transactions. It allows Spreedly to pass on the Braintree reference correctly.

Skip advanced fraud checking

Set this optional gateway specific field to "true" to enable the skip_advanced_fraud_checking flag in authorize and purchase transactions.

Skip AVS

Set this optional gateway specific field to "true" to enable the skip_avs flag in authorize and purchase transactions.

Skip CVV

Set this optional gateway specific field to "true" to enable the skip_cvv flag in authorize and purchase transactions.

Level 2 data

Level 2 processing requires purchase_order_number and tax_amount and/or tax_exempt (boolean).

Level 3 data

For Level 3 processing, Level 2 fields are required along with line_items, an array of JSON objects detailing the line items of the purchase, and the following fields:

  • shipping_amount
  • discount_amount
  • ships_from_postal_code
  • A postal code in the shipping address
  • A country in the shipping address

Travel and lodging data

The travel_data and lodging_data gateway specific fields can be used to send optional industry-specific fields on transactions. Information for only one industry type may be sent per transaction.

Account Type

The account_type gateway specific field can be used to specify the account type (credit or debit). Note that this field can only be used when the merchant_account_id is configured to use BRL currency.

Allow Card Verification

The allow_card_verification gateway specific field can be used to trigger a $0 verification in place of the standard authorization/void process. Please note that use of the $0 verification requires it being enabled on the merchant’s account. This is a manual process that has to be enabled by the merchant’s CSM at Braintree.

Risk Data

The risk_data gateway specific field can be used as part of Braintree’s fraud tools. The field contains customer device information, which is used by supported processors for fraud analysis. See Braintree’s risk data documentation for more details on how this information is used.

Custom fields

Custom fields provide an easy way to collect additional information about your customers or their purchase, like the name of the product they purchased. They can be included when creating a transaction or adding a customer to the Vault, and can be stored in the Braintree gateway for reporting purposes

Note that custom fields cannot be created via an API request so you’ll need to configure them directly in the Control Panel. See Braintree’s custom fields documentation for more information.


curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<transaction>
        <payment_method_token>56wyNnSmuA6CWYP7w0MiYCVIbW6</payment_method_token>
        <amount>100</amount>
        <currency_code>USD</currency_code>
        <gateway_specific_fields>
          <braintree>
            <custom_fields>
              <work_email>TheWorkEmail</work_email>
              <cat_name>Waffles</cat_name>
            </custom_fields>
          </braintree>
        </gateway_specific_fields>
      </transaction>'

<transaction>
  <on_test_gateway type="boolean">true</on_test_gateway>
  <created_at type="dateTime">2017-07-27T17:47:57Z</created_at>
  <updated_at type="dateTime">2017-07-27T17:47:57Z</updated_at>
  <succeeded type="boolean">true</succeeded>
  <state>succeeded</state>
  <token>3xwFfEH9SYPCfCFBJuhHlAZJKaZ</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>
    <braintree>
      <custom_fields>
        <work_email>TheWorkEmail</work_email>
        <cat_name>Waffles</cat_name>
      </custom_fields>
    </braintree>
  </gateway_specific_fields>
  <gateway_specific_response_fields>
  </gateway_specific_response_fields>
  <gateway_transaction_id>54</gateway_transaction_id>
  <gateway_latency_ms type="integer">51</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>Newfirst Newlast</name>
    <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:47:57Z</created_at>
    <updated_at type="dateTime">2017-07-27T17:47:57Z</updated_at>
  </response>
  <api_urls>
  </api_urls>
  <payment_method>
    <token>1rpKvP8zOUhj4Y9EDrIoIYQzzD5</token>
    <created_at type="dateTime">2017-06-26T17:04:38Z</created_at>
    <updated_at type="dateTime">2017-07-27T17:47:55Z</updated_at>
    <email>joey@example.com</email>
    <data>
      <my_payment_method_identifier>448</my_payment_method_identifier>
      <extra_stuff>
        <some_other_things>Can be anything really</some_other_things>
      </extra_stuff>
    </data>
    <storage_state>retained</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>Newfirst</first_name>
    <last_name>Newlast</last_name>
    <month type="integer">3</month>
    <year type="integer">2032</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>Newfirst Newlast</full_name>
    <eligible_for_card_updater nil="true"/>
    <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></verification_value>
    <number>XXXX-XXXX-XXXX-1111</number>
    <fingerprint>e3cef43464fc832f6e04f187df25af497994</fingerprint>
  </payment_method>
</transaction>


env = Spreedly::Environment.new('C7cRfNJGODKh4Iu5Ox3PToKjniY', '4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ', base_url: 'https://core.spreedly.com')
env.purchase_on_gateway("LlkjmEk0xNkcWrNixXa1fvNoTP4", "56wyNnSmuA6CWYP7w0MiYCVIbW6", 4432,
  gateway_specific_fields: {
    braintree: {
      custom_fields: {
        work_email: "TheWorkEmail",
        cat_name: "Waffles"
      }
    }
  }
)


#<Spreedly::Purchase:0x007fe3338ddcb8
@token="FKE0rlBSngfMZnf0Gt2ihcDR3NF",
@created_at="2017-07-27T17:47:58Z",
@updated_at="2017-07-27T17:47:58Z",
@state="succeeded",
@message="Succeeded!",
@succeeded="true",
@order_id="",
@ip="",
@description="",
@gateway_token="T11bJAANtTWnxl36GYjKWvbNK0g",
@gateway_transaction_id="58",
@email="",
@merchant_name_descriptor="",
@merchant_location_descriptor="",
@on_test_gateway="true",
@currency_code="USD",
@amount="4432",
@response,=
#<Spreedly::Response:0x007fe3338af6d8
@success="true",
@pending="false",
@cancelled="false",
@fraud_review="",
@created_at="2017-07-27T17:47:58Z",
@updated_at="2017-07-27T17:47:58Z",
@message="Successful purchase",
@avs_code="",
@avs_message="",
@cvv_code="",
@cvv_message="",
@error_code="",
@error_detail="">,
@shipping_address,=
#<Spreedly::ShippingAddress:0x007fe33388f310
@name="Newfirst Newlast",
@address1="",
@address2="",
@city="",
@state="",
@zip="",
@country="",
@phone_number="">,
@gateway_specific_fields={:braintree=>{:custom_fields=>"\n        TheWorkEmail\n        Waffles\n      "}},
@payment_method,=
#<Spreedly::CreditCard:0x007fe33385ad90
@token="1rpKvP8zOUhj4Y9EDrIoIYQzzD5",
@created_at="2017-06-26T17:04:38Z",
@updated_at="2017-07-27T17:47:57Z",
@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="",
@errors=[]>>

ACH mandate

The content of ach_mandate specific field should be the same that you presented to your customer as an acknowledgment and acceptance to use and verify its bank account information, for more information see Braintree Authorization language.

Gateway specific response fields

A response from Braintree gateway may contain additional fields which you can find in the gateway_specific_response_fields. These currently include additional_processor_response if it is enabled for your account, as well as risk_data fields, processor_authorization_code, prepaid, debit, issuing_bank, and braintree_status. If you are transacting via PayPal, then the payer_id and payer_email fields may also be returned.

For example:

<transaction>
  <token>LgpTNGjsWQs9DwdxcbreUVz0R8p</token>
  <transaction_type>Purchase</transaction_type>
  <gateway_specific_response_fields>
     <braintree>
       <additional_processor_response>2004</additional_processor_response>
       <risk_data_decision>Approve</risk_data_decision>
       <risk_data_device_data_captured>true</risk_data_device_data_captured>
       <risk_data_id>123</risk_data_id>
       <processor_authorization_code>1234</processor_authorization_code>
       <debit>Yes</debit>
       <prepaid>Yes</prepaid>
       <issuing_bank>XYZ</issuing_bank>
       <braintree_status>authorized</braintree_status>
       <payer_id>12345</payer_id>
       <payer_email>john@paypal.com</payer_email>
     </braintree>
  </gateway_specific_response_fields>
</transaction>


Additionally, the fields gateway_message, gateway_rejection_reason, duplicate_transaction_id will be available on transactions that fail when the gateway is rejected.

<transaction>
  <token>LgpTNGjsWQs9DwdxcbreUVz0R8p</token>
  <transaction_type>Purchase</transaction_type>
  <gateway_specific_response_fields>
     <braintree>
       <gateway_message>Transaction declined - gateway rejected</additional_processor_response>
       <gateway_rejection_reason>duplicate</gateway_rejection_reason>
       <duplicate_transaction_id>1hn4ls8s</gateway_rejection_reason>
     </braintree>
  </gateway_specific_response_fields>
</transaction>


If you’d like to request any gateway_specific_fields or gateway_specific_response_fields, please contact Support with your request and the gateway documentation for the fields of interest.

Populate MIT Field Support

We support automatic MIT data handling on Braintree via the populate_mit_fields flag.

Manual MIT Support on 3DS2 Global

If not using the populate_mit_fields flag, you can ensure that your recurring transactions have the best chance of being marked as out of scope by properly setting the transaction_source gateway specific field. See Spreedly’s implementation of stored credentials.

You should be performing 3DS on the first transaction as usual and pass the transaction_source field with the subsequent transactions:

  • set the transaction_source field to "unscheduled" and do not pass the recurring gateway specific field for unscheduled transactions
  • set the transaction_source field to "recurring" for recurring transactions

Alternative Payment Methods

Spreedly supports purchases and authorizations with alternative payment methods (APMs) by leveraging Braintree’s PayPal and Venmo. At a high level, the general steps are as follows:

  1. Create a purchase or authorize transaction on a Braintree Blue Gateway

  2. Use the Spreedly iFrame to display the Braintree Payment Elements using data from the processing transaction.

  3. Use Spreedly’s confirm endpoint to complete the transaction.

Prerequisites before rendering Braintree Payment Elements

In order to offer PayPal or Venmo, some account configuration and front end development is required.

To offer PayPal

  1. Create, verify, and link your PayPal account in the Braintree Control Panel.
  2. Add Braintree.js to your page:
<script src="https://js.braintreegateway.com/web/3.85.3/js/client.min.js"></script>
 <script src="https://js.braintreegateway.com/web/3.85.3/js/paypal-checkout.min.js"></script>


- If using vault and checkout with vault flow add an additional script

<script src="https://js.braintreegateway.com/web/3.85.3/js/data-collector.min.js"></script>


3. Create HTML DOM element where the PayPal button will be injected into.

<div id="paypal-button"></div>


UX Best Practices

PayPal requires specific user experience standards. These will be part of the contracts and agreements you sign with Braintree, so please review them thoroughly. Below are some examples to get you started, that should cover you during initial integration and testing:

  1. The correct capitalization of “PayPal” is always used in text and images (instead of “Paypal”, “Pay Pal”, etc.)
  2. For the buyer’s first payment, no payment method should be preselected on the payment page. For subsequent payments, the buyer’s previously used payment method may be preselected.
  3. When a payment method is selected, any fields specific to other payment methods are hidden (e.g. credit card fields are hidden if a customer selects PayPal)
  4. PayPal logos and payment marks are displayed in parity with other payment methods across the integration and payment page.
  5. Selecting the PayPal payment method takes the buyer directly to PayPal without any deviations or interstitial steps and back to the merchant site.
  6. The complete PayPal experience is in parity with other payment methods across the integration.

To offer Venmo

1) Setup your Venmo account in the Braintree Control Panel.

2) Add Braintree.js to page:

  • If you are offering both PayPal and Venmo, only one instance of the Client.js and Data-collector.js is required

       <script src="https://js.braintreegateway.com/web/3.85.3/js/client.min.js"></script>
       <script src="https://js.braintreegateway.com/web/3.85.3/js/venmo.min.js"></script>
       <script src="https://js.braintreegateway.com/web/3.85.3/js/data-collector.min.js"></script>
    


3) Configure Venmo button

  • The Venmo button needs to be created from scratch unlike PayPal.
  • Download the Venmo assets from the link provided above
  • It’s important to hide the button initially by using a display value of none.

       <div id="venmo-button" style="display: none;">...</button>
    


Step 1: Create a purchase or authorize

Call Spreedly’s #purchase or #authorize endpoint using either PayPal or Venmo. Include the following required fields:

  • Payment Method
    • payment_method_type to be paypal or venmo
    • offsite_sync to be true
  • Amount
  • Currency Code
  • Required gateway specific fields for PayPal and Venmo
    • venmo_flow_type or paypal_flow_type

Creating a purchase

This is an example of a purchase made using PayPal as the payment method. paypal_flow_type is a required gateway specific field that indicates the payment flow for PayPal. line_items is the optional gateway specific field that shows a breakdown of specified items in the total amount.

curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.json \
 -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
 -H 'Content-Type: application/xml' \
 -d '{
    "transaction": {
      "amount": 1000,
      "currency_code": "USD",
      "payment_method": {
        "payment_method_type": "paypal",
        "offsite_sync": true,
        "shipping_address1": "123 test way",
        "shipping_city": "Durham",
        "shipping_state": "NC",
        "shipping_zip": 27703,
        "shipping_country": "US",
        "shipping_phone_number": "123-456-789",
        "full_name": "Suzy Storm"
      }, 
      "gateway_specific_fields": {
        "braintree": {
          "paypal_flow_type": "checkout",
          "line_items": [{
              "name": "black T-Shirt",
              "quantity": 2,
              "unit_price" : 5000,
              "tax_rate" : 0,
              "total_amount" : 10000,
              "total_tax_amount" : 0
          }]
        }
      }
    }
  }'


Creating an authorization

This is an example of an authorize made with Venmo as the payment method. venmo_flow_type is a required gateway specific field that indicates the payment flow for Venmo. venmo_profile_id is required field for merchants who have onboarded multiple profiles to a single Braintree gateway.

curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.json \
 -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
 -H 'Content-Type: application/xml' \
 -d '{
    "transaction": {
      "amount": 1000,
      "currency_code": "USD",
      "payment_method": {
        "payment_method_type": "venmo",
        "offsite_sync": true
      }, 
      "gateway_specific_fields": {
        "braintree": {
          "venmo_flow_type": "multi_use",
          "venmo_profile_id": "12345"
        }
      }
    }
  }'


As long as the authorization or purchase request successfully reaches Braintree, the transaction state will be processing in the response. Grab the transaction token and proceed to Step 2 to present the Payment Element to your customer. We will use that transaction token to make an internal call and use the transaction information when rendering the different buttons.

PayPal Flow Type

When using PayPal as a payment method the paypal_flow_type needs to be specified. The three flows available are vault, checkout, or checkout_with_vault.

  • Checkout is for one-time payments. The checkout flow also supports use of the Pay Later button**.
  • Vault allows you to save the payment method for later use.
  • Checkout with Vault is a combination of the two previously mentioned. With this flow you can perform a one-time payment but also save the payment method for later use.

** Pay Later button is automatically enabled for the Checkout flow type. To disable the Pay Later button update your gateway with the enable_paylater_button field and set it to false. curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4.json \ -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \ -H 'Content-Type: application/xml' \ -d '{ "gateway": { "enable_paylater_button": 'false' } }'

Venmo Flow Type

When using Venmo as a payment method the venmo_flow_type needs to be specified. The two options available are multi_use or single_use. Single use is for one-time payments while multi use allows you to save the payment method for later use. If you have onboarded multiple profiles under a single Braintree gateway, you’ll need to pass venmo_profile_id to specify which Venmo profile to present during the payment flow. Each new profile must be submitted for approval by Braintree.

Step 2: Display the Braintree Payment Element

Once the transaction has been created the Braintree Payment Elements can be rendered using Spreedly’s iFrame:

  • callbackFunction: This is a callback function provided by the customer. When we receive a successful, cancelled or error response from Braintree we will return a hash/object to that callback function. The response returned here will be used in Step 3.

  • transactionToken: The Spreedly transaction token returned by the processing transaction from Step 1.

  • environmentKey: The Spreedly environment key.

  • paymentElements: An object with the HTML DOM element that the Payment Element will be injected into. Send the payment elements you are trying to render.

  • style: An object that accepts parameters to configured the display of the PayPal button. The accepted parameters are color, height, shape and layout.

For more details on this function, see our iFrame Reference.

Render only PayPal payment element:

const element = Spreedly.createBraintreePaymentElements({
  callbackFunction: callbackFunction,
  transactionToken: transactionToken,
  environmentKey: enviornmentKey,
  paymentElements: {paypal: 'paypal-payment-element'},
  style: {paypal: { color: 'blue', height: 45, shape: 'rect'}}
});

Render only Venmo payment element:

const element = Spreedly.createBraintreePaymentElements({
  callbackFunction: callbackFunction,
  transactionToken: transactionToken,
  environmentKey: enviornmentKey,
  paymentElements: {venmo: 'venmo-payment-element'}
});

Render both Venmo and PayPal:

  • It’s possible to render both buttons at the same time.
    To do this make sure you have followed the Prerequisite steps for PayPal and Venmo and send both payment elements to the iFrame function.

       const element = Spreedly.createBraintreePaymentElements({
          callbackFunction: callbackFunction,
          transactionToken: transactionToken,
          environmentKey: enviornmentKey,
          paymentElements: {venmo: 'venmo-payment-element', paypal: 'paypal-payment-element'}
      });
    

Step 3: Complete transaction

After receiving a response through your callback function you will need to complete the transaction through a request to the transactions#confirm endpoint. You can also optionally send gateway specific fields in the confirm call.

curl https://core.spreedly.com/v1/transactions/spreedlyTransactionToken/confirm.json \
 -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
 -H 'Content-Type: application/json' \
 -d '{
    "state": "Successful",
    "nonce": "paymentMethodNonce",
    "payment_method": {
      "payment_method_type": "paypal"
    },
    "gateway_specific_fields": {
      "braintree": {
        "paypal_custom_field": "test",
        "paypal_description": "test1"
      }
    }
  }'


By sending the payment method we can update the transactions if the initial payment method differs from the final one used. For example, in Step 1 you created a Purchase with payment_method_type: 'paypal'. You used that transaction token in Step 2 to render both Braintree payment elements, Venmo & PayPal. Your customer successfully completes the payment with Venmo and the hash returned to your callbackFunction is similar to the one below. You use the below hash when completing the transaction in Step 3. This final step will not only update the transaction state but also update the payment method type.

  {
    "state": "Successful",
    "nonce": "0f06891d-f35d-068a-bc69-58bd537d668e",
    "device_data": "{\"correlation_id\":\"49b4663d254981e8263def3ea4b579b5\"}",
    "username": "@username",
    "payment_method": {
      "payment_method_type": "venmo"
  }

Example responses for callbackFunction:

Failed:

PayPal

 {
   "state": "Failed",
   "message": "undefined Error: PayPal payment options are invalid. at Tr.error…",
   "payment_method": {
     "payment_method_type": "paypal"
   }
 }


Venmo

 {
    "state": "Failed",
    "message": "An error occurred: ${custom message}",
    "payment_method": {
      "payment_method_type": "venmo"
    }
 }

Cancelled:

PayPal

 {
   "state": "Cancelled",
   "message": "PayPal payment cancelled, {\n \"orderID\": \"EC-8XN05533WV243142V\"\n}",
   "payment_method": {
     "payment_method_type": "paypal" // or venmo
   }
 }


Venmo

 {
  "state": "Cancelled",
  "message": "App is not available or user aborted payment flow",
  "payment_method": {
    "payment_method_type": "venmo"
  }
}

Successful:

PayPal

 {
   "state": "Successful",
   "nonce": "0f06891d-f35d-068a-bc69-58bd537d668e",
   "device_data": "{\"correlation_id\":\"49b4663d254981e8263def3ea4b579b5\"}", // only for Vault and Checkout with Vault
   "payment_method": {
     "payment_method_type": "paypal"
   }
 }


Venmo

 {
   "state": "Successful",
   "nonce": "0f06891d-f35d-068a-bc69-58bd537d668e",
   "device_data": "{\"correlation_id\":\"49b4663d254981e8263def3ea4b579b5\"}",
   "username": "@username",
   "payment_method": {
     "payment_method_type": "venmo"
   }
 }

Multiple Partial Settlements

Braintree allows you to settle multiple partial amounts against the same authorization for PayPal and Venmo. It is important to note that an authorization for PayPal expires after 29 days and Venmo after 10 days.

Creating a partial capture:

curl https://core.spreedly.com/v1/transactions/spreedlyTransactionToken/capture.json \
 -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
 -H 'Content-Type: application/json' \
 -d '{
    "transaction": {
      "amount": 100,
      "currency_code": "USD",
      "gateway_specific_fields": {
        "braintree": {
            "partial_capture": true
        }
      }
    }
  }

Additional transactions with vaulted payment methods

This section only applies to payment methods that have been vaulted in Braintree. If you used checkout_with_vault or vault for paypal_flow_type or multi_use for venmo_flow_type then your payment method was vaulted when you completed Step 3. You only need payment_method_token when creating a purchase or authorization with a vaulted payment method.

curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.json \
 -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
 -H 'Content-Type: application/json' \
 -d '{
    "transaction": {
      "payment_method_token": "QpxOaxBqLsCOSK5E4SJafu68v8i",
      "amount": 100,
      "currency_code": "USD"
    }
  }

PayPal Gateway Specific Fields

When using the checkout or checkout_with_vault flow, line_items, shipping address and locale are optional fields. locale can be used to change the language, terminology and links in the customer’s PayPal profile. If you decided to use the checkout_with_vault or vault flow you can optionally pass billing_agreement_description to make the description of the pre approved payment agreement visible to customers in their PayPal profile.

Line Items

It’s important to note that quantity, unit_amount, name and kind must be included in order for line items to be render in the customer’s PayPal profile.

Name Type Attributes Description
quantity integer M Number of units of the item purchased. This value must be a whole number and can’t be negative or zero.
unit_amount integer M Per-unit price of the item. Can include up to 2 decimal places. This value can’t be negative or zero.
name string M Item name. Maximum 127 characters.
kind string M Indicates whether the line item is a debit (sale) or credit (refund) to the customer. Accepted values: debitandcredit`.
unit_tax_amount integer O Per-unit tax price of the item. Can include up to 2 decimal places. This value can’t be negative or zero.
description string O Item description. Maximum 127 characters.
product_code string O Product or UPC code for the item. Maximum 127 characters.
url string O The URL to product information.

Shipping Address

It’s important to note that all mandatory shipping parameters must be included in order for shipping address to be render in the customer’s PayPal profile. Shipping address is part of the payment method object.

Name Type Attributes Description
shipping_address1 string M Street address.
unit_amount string O Street address (extended).
shipping_city string M City.
shipping_state string M State.
shipping_zip integer M Postal code.
shipping_country string M Country code.
shipping_phone_number string O Phone number.
full_name string O Recipient’s name.

Network Tokenization

Braintree requires merchants to be enabled on the gateway end before transacting with network tokens. In order to be enabled at the gateway please contact Braintree and request to have Third Party Card-On-File network tokens enabled on their merchant accounts.