Braintree gateway guide

Additional notes
As noted in this guide, 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 [email protected].

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, noted below.

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

To add 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>

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

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>

To learn more about creating and managing gateways in our Marketplace, review the Gateway user guide. For gateways not included in the Marketplace, review the steps below.

Create a gateway

Visit your Connections area to review all gateways and add new ones. When creating your gateways, select the gateway name and authentication mode (if prompted) before completing required fields. Select ☑️Sandbox to create a gateway in Sandbox mode, for processing test card data and transactions in your Spreedly environment.

Braintree gateways require merchant_id, public_key, and private_key, and can be added in Blue authentication mode. You can include a merchant_account_id if you are a platform with multiple connected Braintree accounts processing under the same Braintree gateway. Other fields and gateway settings are optional and can be configured as described in this gateway guide.

Third-party 3DS2 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 fieldBraintree field
three_ds_versionthree_d_secure_version
ecommerce_indicatoreci_flag
authentication_valuecavv
authentication_value_algorithmcavv_algorithm
directory_server_transaction_idds_transaction_id
directory_response_statusdirectory_response
authentication_response_statusauthentication_response

Gateway specific 3DS2

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 value from this object. It 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.

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.
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>[email protected]</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>'
  1. 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.
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>'
  1. 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>
            <network_transaction_id>12345</network_transaction_id>
          </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>
      <network_transaction_id>12345</network_transaction_id>
    </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>[email protected]</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>

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 descriptor

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 to 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>[email protected]</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>

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.

Network transaction ID

The optional network_transaction_id field can be used in conjunction with Spreedly's stored credential framework to send a previously existing network transaction id for the payment method in use.

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>[email protected]</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>

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. 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

Some account configuration and front end development is required to offer PayPal or Venmo.

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>
  1. 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.

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>
  1. Configure the 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

The following 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

The following 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 <%= base %>/v1/gateways/<%= test_gateway %>.json \
 -u '<%= curl_creds %>' \
 -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](https://developer.paypal.com/braintree/docs/guides/venmo/client-side/javascript/v3/#multiple-profiles) 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.
  • callbackActionButtonFunction: This is a callback function provided by the customer. When the button is rendered we will return { state: "Initiated", data, actions } and when the button is clicked we will return { state: "Clicked", data, actions }

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'}},
  callbackActionButtonFunction: callbackActionButtonFunction
});

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.

NameTypeAttributesDescription
quantityintegerMNumber of units of the item purchased. This value must be a whole number and can’t be negative or zero.
unit_amountintegerMPer-unit price of the item. Can include up to 2 decimal places. This value can’t be negative or zero.
namestringMItem name. Maximum 127 characters.
kindstringMIndicates whether the line item is a debit (sale) or credit (refund) to the customer. Accepted values: debit and credit.
unit_tax_amountintegerOPer-unit tax price of the item. Can include up to 2 decimal places. This value can’t be negative or zero.
descriptionstringOItem description. Maximum 127 characters.
product_codestringOProduct or UPC code for the item. Maximum 127 characters.
urlstringOThe 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.

NameTypeAttributesDescription
shipping_address1stringMStreet address
unit_amountstringOStreet address (extended)
shipping_citystringMCity
shipping_statestringMState
shipping_zipintegerMPostal code
shipping_countrystringMCountry code
shipping_phone_numberstringOPhone number
full_namestringORecipient'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.