PayPal gateway guide

Quick Start

New to integrating PayPal with Spreedly? Here's your setup guide:

  1. Retrieve your PayPal credentials
    1. Contact the PayPal support team to obtain API credentials
  2. Get familiar with the Spreedly API
    1. Review Spreedly API basics
    2. Understand the core concepts: Gateways, Payment Methods, and Transactions
  3. Add PayPal gateway to Spreedly in sandbox mode
📘

Review this documentation to understand more about how to test transactions.

Additional notes
Spreedly gives you full control over the look and feel of your payment page. If you are going to use PayPal as your payment gateway for accepting credit cards then you must have a PayPal Payments Pro account. Pro is the only PayPal account that supports having your own unique payments page/form. If PayPal Payments Pro isn’t offered in your region you have two options:
  • Find out if Payflow Pro is offered in your region. Payflow Pro will still allow you to completely control the payment form and checkout process.
  • Using the offsite payment flow will not allow you to completely control your payment page/form nor will it allow you to accept credit cards. You will however be able to offer PayPal as a payment type.
If offering PayPal as a payment type is important you can always use a traditional gateway like Stripe, Braintree, or PayMill for credit cards and then use PayPal Payments Standard as a secondary gateway for PayPal payments.

If using special characters, please check the merchant settings in your PayPal dashboard and allow for these. Not doing so may result in a callback error from Spreedly, “Unverified call: probably not from PayPal”. Please reach out to PayPal Support with any questions about making changes to your merchant settings.

Adding a PayPal gateway

There are three different “modes” that you can use to authenticate with PayPal: Delegate, Signature, and Certificate. Which mode you decide to use is up to you; we’ve put them here in order of “ease to implement”.

To learn more about creating and managing gateways in our Marketplace, review the Gateway user guide. 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.

Delegate mode

Once permissions are set up (see Retrieve your PayPal credentials), pass the delegate mode and the email address of your PayPal account.

REQUEST

curl https://core.spreedly.com/v1/gateways.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<gateway>
        <gateway_type>paypal</gateway_type>
        <mode>delegate</mode>
        <email>[email protected]</email>
      </gateway>'

RESPONSE

<gateway>
  <token>DEkTB74m11BSKbzcraWJApwDxyx</token>
  <gateway_type>paypal</gateway_type>
  <name>PayPal</name>
  <description nil="true"/>
  <email>[email protected]</email>
  <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">true</supports_reference_purchase>
    <supports_purchase_via_preauthorization type="boolean">true</supports_purchase_via_preauthorization>
    <supports_offsite_purchase type="boolean">true</supports_offsite_purchase>
    <supports_offsite_authorize type="boolean">true</supports_offsite_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">false</supports_store>
    <supports_remove type="boolean">true</supports_remove>
    <supports_fraud_review type="boolean">true</supports_fraud_review>
    <supports_network_tokenization type="boolean">false</supports_network_tokenization>
    <supports_reference_authorization type="boolean">true</supports_reference_authorization>
  </characteristics>
  <credentials>
    <credential>
      <name>email</name>
      <value>[email protected]</value>
    </credential>
  </credentials>
  <gateway_settings>
  </gateway_settings>
  <gateway_specific_fields>
    <gateway_specific_field>recurring</gateway_specific_field>
    <gateway_specific_field>notify_url</gateway_specific_field>
    <gateway_specific_field>custom</gateway_specific_field>
    <gateway_specific_field>soft_descriptor</gateway_specific_field>
    <gateway_specific_field>soft_descriptor_city</gateway_specific_field>
    <gateway_specific_field>allow_guest_checkout</gateway_specific_field>
    <gateway_specific_field>subtotal</gateway_specific_field>
    <gateway_specific_field>shipping</gateway_specific_field>
    <gateway_specific_field>handling</gateway_specific_field>
    <gateway_specific_field>tax</gateway_specific_field>
    <gateway_specific_field>no_shipping</gateway_specific_field>
    <gateway_specific_field>payment_details_item_type</gateway_specific_field>
  </gateway_specific_fields>
  <payment_methods>
    <payment_method>credit_card</payment_method>
    <payment_method>paypal</payment_method>
  </payment_methods>
  <state>retained</state>
  <redacted type="boolean">false</redacted>
  <sandbox type="boolean">false</sandbox>
  <created_at type="dateTime">2020-12-30T15:19:51Z</created_at>
  <updated_at type="dateTime">2020-12-30T15:19:51Z</updated_at>
  <mode>delegate</mode>
</gateway>

Required Credentials (delegate)

mode: delegate

email: Email address of your PayPal account

Signature mode

Once you have your API login, password and signature, pass them in with a mode of signature.

REQUEST

curl https://core.spreedly.com/v1/gateways.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<gateway>
        <gateway_type>paypal</gateway_type>
        <mode>signature</mode>
        <login>login</login>
        <password>password</password>
        <signature>signature</signature>
      </gateway>'

RESPONSE

<gateway>
  <token>XtLtE6Cz8OVG7Qhx0IW7JFTjxyz</token>
  <gateway_type>paypal</gateway_type>
  <name>PayPal</name>
  <description nil="true"/>
  <login>login</login>
  <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">true</supports_reference_purchase>
    <supports_purchase_via_preauthorization type="boolean">true</supports_purchase_via_preauthorization>
    <supports_offsite_purchase type="boolean">true</supports_offsite_purchase>
    <supports_offsite_authorize type="boolean">true</supports_offsite_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">false</supports_store>
    <supports_remove type="boolean">true</supports_remove>
    <supports_fraud_review type="boolean">true</supports_fraud_review>
    <supports_network_tokenization type="boolean">false</supports_network_tokenization>
    <supports_reference_authorization type="boolean">true</supports_reference_authorization>
  </characteristics>
  <credentials>
    <credential>
      <name>login</name>
      <value>login</value>
    </credential>
  </credentials>
  <gateway_settings>
  </gateway_settings>
  <gateway_specific_fields>
    <gateway_specific_field>recurring</gateway_specific_field>
    <gateway_specific_field>notify_url</gateway_specific_field>
    <gateway_specific_field>custom</gateway_specific_field>
    <gateway_specific_field>soft_descriptor</gateway_specific_field>
    <gateway_specific_field>soft_descriptor_city</gateway_specific_field>
    <gateway_specific_field>allow_guest_checkout</gateway_specific_field>
    <gateway_specific_field>subtotal</gateway_specific_field>
    <gateway_specific_field>shipping</gateway_specific_field>
    <gateway_specific_field>handling</gateway_specific_field>
    <gateway_specific_field>tax</gateway_specific_field>
    <gateway_specific_field>no_shipping</gateway_specific_field>
    <gateway_specific_field>payment_details_item_type</gateway_specific_field>
  </gateway_specific_fields>
  <payment_methods>
    <payment_method>credit_card</payment_method>
    <payment_method>paypal</payment_method>
  </payment_methods>
  <state>retained</state>
  <redacted type="boolean">false</redacted>
  <sandbox type="boolean">false</sandbox>
  <created_at type="dateTime">2020-12-30T15:19:50Z</created_at>
  <updated_at type="dateTime">2020-12-30T15:19:50Z</updated_at>
  <mode>signature</mode>
</gateway>

Required Credentials (signature)

mode: signature

login: Your PayPal API username

password: Your PayPal API password

signature: Your PayPal API signature

Certificate mode

Once you have your API login, password and pem certificate, pass them all to Core. When making your curl request, note that the pem certificate has necessary newlines in it. If you’re allowing your customers to enter their pem in your UI, we recommend a text area for it rather than a text field.

REQUEST

curl https://core.spreedly.com/v1/gateways.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<gateway>
          <gateway_type>paypal</gateway_type>
          <mode>certificate</mode>
          <login>login</login>
          <password>password</password>
          <pem>-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAn0hOiAqdiHgp94A/cB+YxqQTPJynzTHZmCGxKylRf4sd0Mrs
SD8kzhaGoUo4/KUSXuATjHpfnBbtHWWVzbN7V8y0457q0qo76jSQj8ce+bfOGatN
FPirNZ35Tw8W2o9v1GJeSEsRFCudd2kAoJOOF5Gf7quDzWk/0LpIcAb8sKZ7amNV
fQF4KIyoLF/wSdXA2A5KkuFBdenQcqjD3OwTk2lbQBeT1fuZYHjTK1T3id2/pHMZ
1aobTeXwnt+y+8W79TtiCYFCPpsjV3rmBxwflsshd+LbDpt6+fUhmNxIHA2NuJtd
I7a9XkNk7EehVZKKvc/MRm4hVxHJrgrvyI+i9QIDAQABAoIBADhTMmoLDu/+RiDe
ehBlK/o6dQ7++pumICMa7vKrVsV6ZV27FFjr81DpSExq2cIFgXyJUoBfmcWxmcHG
dXXbHSfMHL9NKA684hkM433kVQDLTZdoKwbadHiuV0XsuREqncoFyv9XhD+UuMdM
G0utQhb1iQ+2GRKfQFDIPutWnS698ZFJ8vVkPZbX/nNbnhM8Ct/8qyj6IyOJleJI
jAUNM1m9o9Ox1ggG6q2Ey2XaSzkamqK2b4xDm88Z0kGJUTvv67zQzydFa07HVLae
bWppGBZDghNjA4IsFjT3w++6D5rwSJEnXLfEkhs/GW19bMG53srlW3pCfkH7Rm0S
zr+RSYECgYEAz7kYbbDMc8VcYK5A9LFn8t1JgNAGE+oL/zvDVlVeDFDdM26hzvDe
VwN3vCqXIziXFAnlECWXU+NIYSdoNjJFMX38xapIw3hmEN153RPLd0bHckNyPd5q
GbLvL+Ohq9sSguvwDAPpJM7LO2xdEd/k0fATKqT1+2Mph8fQcyq/SFUCgYEAxE0j
7lsAZHImZopIR8uHOJwpVKmOgPBp6fW063lKnm4uScKSvy99fNDi/UeeWKjrhLeK
LgXNeR91vsvmJEIxdqEgXbzxZO8/pjB9ITL1blCo2KFElZNC6ArxNg66D1XIPs0R
UhV145bpkWJpuUHuLtCVzJgoVRfvR0Zq9dXaECECgYAC0iasxqvgHpwEjBlBuW8J
80tePnT2rEUBcFRUxdADJs36NtRntQmv8NIdcg6fYdNbaE7+CySk9P80oo5dvg0G
gQl/vbJDRU1NiVRwViZ7NjDbMmNIx851DuMEqXi2lsEHmiCmaR8vaseDxRL2fS3k
U/hOqfLVOSGFQIdqKPh0CQKBgAwNkH86JzQDrkfthbKi1JKtQ/xmzNEt8dLju1Aa
CnLf4Qe2YrxKdjILwWQ72YUoGg30Fw/sW0lsnRYx/teLGO5nxkz7JPdFmWri30wC
jP9RBI0ImeV1PU5yHY1sKhB2++yfOskHeE2ZHo5GtKcjXTSSqh/917wh1BdUQ40E
rHcBAoGAMtXp+rfxxBxQWZUpxFHgdWXPn+5MtkFtSUQ3QJD8HyIsRLc6YP1iggd8
pN+wWJY+cL31XAyqNA2GA8+vf2JD/pVHqHREbRXtrwuFN9SdWBO1SLTNPW2ni42E
L2qsUyUaOIRteOE0kUR3YkDrtGMr1n7KgRArpeDZSxssQJHX98U=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIEogIBAAKCAQEAn0hOiAqdiHgp94A/cB+YxqQTPJynzTHZmCGxKylRf4sd0Mrs
SD8kzhaGoUo4/KUSXuATjHpfnBbtHWWVzbN7V8y0457q0qo76jSQj8ce+bfOGatN
FPirNZ35Tw8W2o9v1GJeSEsRFCudd2kAoJOOF5Gf7quDzWk/0LpIcAb8sKZ7amNV
fQF4KIyoLF/wSdXA2A5KkuFBdenQcqjD3OwTk2lbQBeT1fuZYHjTK1T3id2/pHMZ
1aobTeXwnt+y+8W79TtiCYFCPpsjV3rmBxwflsshd+LbDpt6+fUhmNxIHA2NuJtd
I7a9XkNk7EehVZKKvc/MRm4hVxHJrgrvyI+i9QIDAQABAoIBADhTMmoLDu/+RiDe
ehBlK/o6dQ7++pumICMa7vKrVsV6ZV27FFjr81DpSExq2cIFgXyJUoBfmcWxmcHG
dXXbHSfMHL9NKA684hkM433kVQDLTZdoKwbadHiuV0XsuREqncoFyv9XhD+UuMdM
G0utQhb1iQ+2GRKfQFDIPutWnS698ZFJ8vVkPZbX/nNbnhM8Ct/8qyj6IyOJleJI
jAUNM1m9o9Ox1ggG6q2Ey2XaSzkamqK2b4xDm88Z0kGJUTvv67zQzydFa07HVLae
bWppGBZDghNjA4IsFjT3w++6D5rwSJEnXLfEkhs/GW19bMG53srlW3pCfkH7Rm0S
zr+RSYECgYEAz7kYbbDMc8VcYK5A9LFn8t1JgNAGE+oL/zvDVlVeDFDdM26hzvDe
VwN3vCqXIziXFAnlECWXU+NIYSdoNjJFMX38xapIw3hmEN153RPLd0bHckNyPd5q
GbLvL+Ohq9sSguvwDAPpJM7LO2xdEd/k0fATKqT1+2Mph8fQcyq/SFUCgYEAxE0j
7lsAZHImZopIR8uHOJwpVKmOgPBp6fW063lKnm4uScKSvy99fNDi/UeeWKjrhLeK
LgXNeR91vsvmJEIxdqEgXbzxZO8/pjB9ITL1blCo2KFElZNC6ArxNg66D1XIPs0R
UhV145bpkWJpuUHuLtCVzJgoVRfvR0Zq9dXaECECgYAC0iasxqvgHpwEjBlBuW8J
80tePnT2rEUBcFRUxdADJs36NtRntQmv8NIdcg6fYdNbaE7+CySk9P80oo5dvg0G
gQl/vbJDRU1NiVRwViZ7NjDbMmNIx851DuMEqXi2lsEHmiCmaR8vaseDxRL2fS3k
U/hOqfLVOSGFQIdqKPh0CQKBgAwNkH86JzQDrkfthbKi1JKtQ/xmzNEt8dLju1Aa
CnLf4Qe2YrxKdjILwWQ72YUoGg30Fw/sW0lsnRYx/teLGO5nxkz7JPdFmWri30wC
jP9RBI0ImeV1PU5yHY1sKhB2++yfOskHeE2ZHo5GtKcjXTSSqh/917wh1BdUQ40E
rHcBAoGAMtXp+rfxxBxQWZUpxFHgdWXPn+5MtkFtSUQ3QJD8HyIsRLc6YP1iggd8
pN+wWJY+cL31XAyqNA2GA8+vf2JD/pVHqHREbRXtrwuFN9SdWBO1SLTNPW2ni42E
L2qsUyUaOIRteOE0kUR3YkDrtGMr1n7KgRArpeDZSxssQJHX98U=
-----END CERTIFICATE-----
</pem>
      </gateway>'

RESPONSE

<gateway>
  <token>K09DZ1z6svNAGhsL3h1slKVZxyz</token>
  <gateway_type>paypal</gateway_type>
  <name>PayPal</name>
  <description nil="true"/>
  <login>login</login>
  <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">true</supports_reference_purchase>
    <supports_purchase_via_preauthorization type="boolean">true</supports_purchase_via_preauthorization>
    <supports_offsite_purchase type="boolean">true</supports_offsite_purchase>
    <supports_offsite_authorize type="boolean">true</supports_offsite_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">false</supports_store>
    <supports_remove type="boolean">true</supports_remove>
    <supports_fraud_review type="boolean">true</supports_fraud_review>
    <supports_network_tokenization type="boolean">false</supports_network_tokenization>
    <supports_reference_authorization type="boolean">true</supports_reference_authorization>
  </characteristics>
  <credentials>
    <credential>
      <name>login</name>
      <value>login</value>
    </credential>
  </credentials>
  <gateway_settings>
  </gateway_settings>
  <gateway_specific_fields>
    <gateway_specific_field>recurring</gateway_specific_field>
    <gateway_specific_field>notify_url</gateway_specific_field>
    <gateway_specific_field>custom</gateway_specific_field>
    <gateway_specific_field>soft_descriptor</gateway_specific_field>
    <gateway_specific_field>soft_descriptor_city</gateway_specific_field>
    <gateway_specific_field>allow_guest_checkout</gateway_specific_field>
    <gateway_specific_field>subtotal</gateway_specific_field>
    <gateway_specific_field>shipping</gateway_specific_field>
    <gateway_specific_field>handling</gateway_specific_field>
    <gateway_specific_field>tax</gateway_specific_field>
    <gateway_specific_field>no_shipping</gateway_specific_field>
    <gateway_specific_field>payment_details_item_type</gateway_specific_field>
  </gateway_specific_fields>
  <payment_methods>
    <payment_method>credit_card</payment_method>
    <payment_method>paypal</payment_method>
  </payment_methods>
  <state>retained</state>
  <redacted type="boolean">false</redacted>
  <sandbox type="boolean">false</sandbox>
  <created_at type="dateTime">2020-12-30T15:19:50Z</created_at>
  <updated_at type="dateTime">2020-12-30T15:19:50Z</updated_at>
  <mode>certificate</mode>
</gateway>

Required Credentials (certificate)

mode: certificate

login: Your PayPal API username

password: Your PayPal API password

pem: Your PayPal PEM certificate (preserve newlines)

Purchase

curl https://core.spreedly.com/v1/gateways/[gateway_token]/purchase.xml \
  -u 'EnvironmentKey:AccessSecret' \
  -H 'Content-Type: application/xml' \
  -d '<transaction>
        <payment_method_token>your_payment_method_token</payment_method_token>
        <amount>100</amount>
        <currency_code>USD</currency_code>
      </transaction>'

Offsite purchases, ACHs, and IPN notifications

If you allow PayPal offsite payments, you’ll need to change the language encoding configuration in your account from windows-1252 to UTF-8. You will also need to adjust your gateway settings to enable Spreedly to hear about the state of payments as their status changes over time.

When you enable Instant Payment Notification (IPN) in PayPal Profile settings, specify the notification URL as https://core.spreedly.com/paypal/ipn/dev/null. This will allow Spreedly to hear about changes such as when the funds for an ACH actually reach your account. And then Spreedly can notify you with an offsite callback.

Syncing transactions

Spreedly supports updating the status of transactions that have been initiated at the PayPal gateway. PayPal currently supports using gateway_transaction_id for updates. The gateway_transaction_id is the payment unique identifier. See our documentation for more information.

Gateway Specific Fields

When interacting with a PayPal gateway to run transactions, there are some gateway specific fields you can specify when making a purchase or authorize call.

<gateway_specific_fields>
  <paypal>
    <recurring>Y</recurring>
    <soft_descriptor>Company Name</soft_descriptor>
    <soft_descriptor_city>New York</soft_descriptor_city>
    <allow_guest_checkout>true</allow_guest_checkout>
    <no_shipping>true</no_shipping>
    <notify_url>https://example.com/notify_me</notify_url>
    <custom>A custom string</custom>
    <subtotal>80</subtotal>
    <shipping>5</shipping>
    <handling>5</handling>
    <tax>10</tax>
    <complete_type>NotComplete</complete_type>
    <refund_type>Partial</refund_type>
    <payment_details_item_type>
      <items>
        <name>Item one name</name>
        <number>1</number>
        <quantity>1</quantity>
        <item_amount>50</item_amount>
        <description>Item one description</description>
      </items>
    </payment_details_item_type>
  </paypal>
</gateway_specific_fields>

recurring: Special flag indicating you have a billing agreement in place with your customer. This flag may lower your decline rates. Can also be used with reference transactions.

notify_url: IPN listener URL for a specific payment.

custom: Any custom string to send along with the transaction.

no_shipping: Set to true to prevent shipping info being displayed when using offsite payments with PayPal Express.

allow_guest_checkout: Set to true to allow checkout with PayPal Express without signing in. Requires “PayPal Account Optional” turned ON for your gateway account.

subtotal, shipping, handling, tax: Order total components. To use any of these fields, all four must be sent and should add up to the order total.

payment_details_item_type: Line item details for PayPal and PayPal Express. For offsite transactions, these show on the PayPal Express hosted payment page.

soft_descriptor / soft_descriptor_city: Per-transaction description shown on the buyer’s statement.

complete_type: Used on capture for multiple partial settlements. Set to NotComplete when more captures are expected.

refund_type: Set to Partial when performing a partial refund of a settled transaction.

These gateway specific fields may be added as shown in this example:

REQUEST

curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<transaction>
        <payment_method_token>56wyNnSmuA6CWYP7w0MiYCVIxyz</payment_method_token>
        <amount>100</amount>
        <currency_code>USD</currency_code>
        <gateway_specific_fields>
          <paypal>
            <recurring>Y</recurring>
            <soft_descriptor>Company Name</soft_descriptor>
            <soft_descriptor_city>New York</soft_descriptor_city>
            <allow_guest_checkout>true</allow_guest_checkout>
            <no_shipping>true</no_shipping>
            <notify_url>https://example.com/notify_me</notify_url>
            <custom>A custom string</custom>
            <subtotal>80</subtotal>
            <shipping>5</shipping>
            <handling>5</handling>
            <tax>10</tax>
            <payment_details_item_type>
              <items>
                <name>Item one name</name>
                <number>1</number>
                <quantity>1</quantity>
                <item_amount>50</item_amount>
                <description>Item one description</description>
              </items>
              <items>
                <name>Item two name</name>
                <number>2</number>
                <quantity>1</quantity>
                <item_amount>50</item_amount>
                <description>Item two description</description>
              </items>
            </payment_details_item_type>
          </paypal>
        </gateway_specific_fields>
      </transaction>'

In addition, the recurring flag can be used with reference transactions:

curl https://core.spreedly.com/v1/transactions/KS3oZgWXCfFeirK16anYbijLxR/purchase.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<transaction>
        <amount>80</amount>
        <gateway_specific_fields>
          <paypal>
            <recurring>Y</recurring>
          </paypal>
        </gateway_specific_fields>
      </transaction>'

Multiple partial settlements

PayPal allows you to settle multiple partial amounts against the same authorization. When performing a partial capture, use the complete_type gateway-specific field to indicate that you are performing a partial capture and that more captures are expected.

{
  "transaction": {
    "amount": 750,
    "currency_code": "USD",
    "gateway_specific_fields": {
      "paypal": {
        "complete_type": "NotComplete"
      }
    }
  }
}

Multiple partial refunds

In order to perform a partial refund, you must set the gateway-specific field refund_type to Partial. This explicitly specifies to the gateway that you are processing a partial refund rather than a full refund of the settled transaction amount.

{
  "transaction": {
    "amount": 600,
    "currency_code": "USD",
    "gateway_specific_fields": {
      "paypal": {
        "refund_type": "Partial"
      }
    }
  }
}
Field NameTypeRequiredUse Case (Description)Example Value
recurringStringNoIndicates a billing agreement is in place with the customer; may lower decline rates. Also usable on reference purchases.Y
notify_urlStringNoIPN listener URL for a specific payment.https://example.com/notify_me
customStringNoArbitrary custom string sent with the transaction.A custom string
soft_descriptorStringNoPer-transaction description passed to the consumer’s credit card statement.Company Name
soft_descriptor_cityStringNoSoft descriptor city / phone component for the statement descriptor.New York
allow_guest_checkoutBooleanNoAllow PayPal Express checkout without signing in (requires PayPal Account Optional ON).true
no_shippingBooleanNoHide shipping info on PayPal Express hosted checkout.true
subtotalIntegerNoOrder subtotal in cents. Must be sent with shipping, handling, and tax.80
shippingIntegerNoShipping amount in cents. Must be sent with subtotal, handling, and tax.5
handlingIntegerNoHandling amount in cents. Must be sent with subtotal, shipping, and tax.5
taxIntegerNoTax amount in cents. Must be sent with subtotal, shipping, and handling.10
payment_details_item_typeObjectNoLine item details for PayPal / PayPal Express (shown on Express hosted page for offsite).See example above
complete_typeStringNoOn capture: NotComplete when more partial captures are expected; omit or use Complete for final.NotComplete
refund_typeStringNoSet to Partial for partial refunds of a settled amount.Partial

Gateway Specific Response Fields

A response from PayPal may contain additional fields in gateway_specific_response_fields.

<gateway_specific_response_fields>
  <paypal>
    <payer>[email protected]</payer>
    <first_name>Waxillium</first_name>
    <last_name>Ladrian</last_name>
    <street1>3911 Main Street</street1>
    <street2>Apartment 3</street2>
    <city_name>Wanaque</city_name>
    <state_or_province>NJ</state_or_province>
    <postal_code>28592-8851</postal_code>
    <country>US</country>
    <billing_agreement_id>B-6HS9055508963942J</billing_agreement_id>
    <billing_street1>3911 Main Street</billing_street1>
    <billing_city>Wanaque</billing_city>
    <billing_state_or_province>NJ</billing_state_or_province>
    <billing_country_code>US</billing_country_code>
    <billing_country_name>United States</billing_country_name>
    <billing_zip>28592-8851</billing_zip>
  </paypal>
</gateway_specific_response_fields>

Buyer information

If you’re using PayPal with offsite payments, PayPal shares additional information about transactions. After a purchase and after a purchase via preauth you can determine:

  • payer
  • first_name
  • last_name
  • street1
  • street2
  • city_name
  • state_or_province
  • postal_code
  • country

After an authorization you can determine billing address fields:

  • billing_street1 (billing street)
  • billing_city
  • billing_state_or_province (billing state)
  • billing_country_code
  • billing_country_name (billing country)
  • billing_zip (billing postal code)

Example after purchase:

<transaction>
  <token>XspZooGud4SNm5Id9iwHHpWRxyz</token>
  <transaction_type>Purchase</transaction_type>
  <gateway_specific_response_fields>
    <paypal>
      <payer>[email protected]</payer>
      <first_name>Waxillium</first_name>
      <last_name>Ladrian</last_name>
      <street1>3911 Main Street</street1>
      <street2>Apartment 3</street2>
      <city_name>Wanaque</city_name>
      <state_or_province>NJ</state_or_province>
      <postal_code>28592-8851</postal_code>
      <country>US</country>
    </paypal>
  </gateway_specific_response_fields>
</transaction>

Billing agreement ID

billing_agreement_id from a purchase (or a purchase via preauth) transaction is included under gateway_specific_response_fields

<transaction>
  <token>XspZooGud4SNm5Id9iwHHpWRxyz</token>
  <transaction_type>Purchase</transaction_type>
  <gateway_specific_response_fields>
    <paypal>
      <billing_agreement_id>B-6HS9055508963942J</billing_agreement_id>
    </paypal>
  </gateway_specific_response_fields>
</transaction>

Sending email addresses

PayPal expects email to be passed as part of the address. If the address is not sent, the email will not be sent either. If you don’t collect a customer address as part of your transaction flow, but still want the email parameter to be passed, you can populate the address section with default details.

Field NameTypeDescription
payerstringBuyer PayPal email / payer identifier from offsite purchase or purchase via preauth.
first_namestringBuyer first name from offsite purchase or purchase via preauth.
last_namestringBuyer last name from offsite purchase or purchase via preauth.
street1stringBuyer street address line 1.
street2stringBuyer street address line 2.
city_namestringBuyer city.
state_or_provincestringBuyer state or province.
postal_codestringBuyer postal / ZIP code.
countrystringBuyer country code.
billing_agreement_idstringBilling agreement ID from purchase or purchase via preauth.
billing_street1stringBilling street returned after authorization.
billing_citystringBilling city returned after authorization.
billing_state_or_provincestringBilling state/province returned after authorization.
billing_country_codestringBilling country code returned after authorization.
billing_country_namestringBilling country name returned after authorization.
billing_zipstringBilling postal code returned after authorization.

Idempotency

Idempotency is supported on capture, refund, and void. Pass the gateway-specific field idempotency_key on those requests. PayPal uses this value as MsgSubID. A successful replay returns the original transaction result, including cases where PayPal returns error 11607, which Spreedly treats as a success when a transaction ID is present in the response.

{
  "transaction": {
    "amount": 100,
    "currency_code": "USD",
    "gateway_specific_fields": {
      "paypal": {
        "idempotency_key": "capture-order-4471-01"
      }
    }
  }
}
📘

Merchants own key uniqueness per operation

Reusing the same idempotency_key across different actions (for example, using the same key for a capture and then a void) can collide. Use a distinct key per request intent to avoid unexpected results.

Not fully supported (purchase / authorize)

Purchase and authorize (DoDirectPayment) do not support MsgSubID / idempotency_key as true idempotency.

A soft-dedupe option is available instead, by mapping the Spreedly order_id field to PayPal's InvoiceID

A duplicate order_id is typically rejected by PayPal (for example, error 10536).
This prevents a second charge from being processed, but it is not a true idempotent success — you will not receive the original successful response or a replay of the same authorization.

Network advice code

PayPal returns a PaymentAdviceCode value in its SOAP response for certain declined transactions. Spreedly's Gatekeeper service parses this value as payment_advice_code, and Core maps it onto Spreedly's normalized transaction response field network_advice_code.

For example, if PayPal returns

<PaymentAdviceCode>03</PaymentAdviceCode>

The Spreedly transaction response includes

{
  "network_advice_code": "03"
}


If PayPal does not return a PaymentAdviceCode, network_advice_code is omitted from the response (or returned as null)

Stored Credentials

PayPal supports Spreedly's native stored credential fields on Purchase and Authorize requests:

  • stored_credential_initiator
  • stored_credential_reason_type

Spreedly maps these to Paypal <StoredCredentials> element as usage (FIRST / USED). stored_credential_reason_type will support 2 values in PayPal — recurring and unscheduled.
Spreedly maps these to PayPal's stored credential parameters to properly flag the transaction as a customer-initiated (CIT) or merchant-initiated (MIT) transaction.

📘

Learn more about how Spreedly enables use of stored credentials by reviewing our Stored credentials Guide

First / credential-on-file setup (CIT)

reason_typeinitiatorPayPal usage
recurringcardholderFIRST
unscheduledcardholderFIRST

Subsequent use

reason_typeinitiatorPayPal usage
recurringmerchantUSED
recurringcardholderUSED
unscheduledmerchantUSED
unscheduledcardholderUSED

Stored credential alternate gateway
You can use another gateway as the stored_credential_alternate_gateway while processing a payment on PayPal.

However, you cannot use PayPal as the stored_credential_alternate_gateway while processing a payment on any other gateway.

Additional resources

📘

If you need support with this gateway, please contact Support at [email protected].

📘

PayPal documentation: Reference


Did this page help you?