[Warrior Payments] Warrior Payments IPN Integration

by WarriorForum.com 16 replies
Whenever a sale is made, refunded or reversed, Warrior Payments will send a FORM POST message to the IPN notification URL specified for your product. The message will contain the EXACT response we receive from the PayPal GetTransactionDetails API call. We will also send over extra Warrior Payments product related fields in the IPN message. The following table lists the extra fields sent in the current version (0.1).

In your script that handles IPN messages, you may use any of the fields available to process the sale. Your script can also return a response with greeting messages or special access keys/credentials for your product. This information will be displayed on the "WSO Secure Checkout" page. You can use simple/basic HTML tags such as paragraph breaks to format your message. For security reasons, we do not process JavaScript or iframes in the response.

WSO_SALE_ACTION
Description: Status of the sale (SALE, REFUNDED or REVERSED)

WSO_CUSTOMER_EMAIL
Description: The email address of the customer

WSO_CUSTOMER_NAME
Description: Full Name of the Customer

WSO_PRODUCT_NAME
Description: Warrior Payments Product Name

WSO_PRODUCT_ID
Description: Warrior Payments Product ID

WSO_SALE_ID
Description: Warrior Payments Sale ID

WSO_SALE_AMOUNT
Description: Sale Amount

WSO_SALE_CURRENCY
Description: Currency Code

WSO_TXN_ID
Description: Your PayPal Transaction ID for the sale

WSO_AFF_EMAIL
Description: The email address of the affiliate of this sale (if available)

WSO_AFF_AMOUNT
Description: Affiliate payout of this sale (if available)

WSO_SIGNATURE
Description: Signature of IPN post data using secret key

WSO_IPN_VERSION
Description: The api version

IPN Signature
A WSO_SIGNATURE field is added to the POST data if an IPN Secret is specified. By recalculating the signature in your IPN processing script you can verify that the IPN notification was sent from Warrior Payments untampered. See the following code samples for the actual algorithm that can be used to verify the signature.

Python

Code:
import urllib
import hashlib


def is_signature_valid(data, signKey):
    if 'WSO_SIGNATURE' not in data:
        return False

    expected_signature = data.pop('WSO_SIGNATURE')

    sorted_data = sorted(data.items(), key=lambda x: x[0])
    encoded_data = urllib.urlencode(sorted_data)
    signature = hashlib.sha1(encoded_data + signKey).hexdigest()

    return signature == expected_signature


data = {
    "AMT": "50.00",
    "COUNTRYCODE": "AU",
    "CURRENCYCODE": "USD",
    "EMAIL": "john.doe@email.com",
    "FEEAMT": "2.25",
    "FIRSTNAME": "John",
    "LASTNAME": "Doe",
    "ORDERTIME": "2014-11-27T01:57:40Z",
    "PAYERID": "FYPB3LQJWVV72",
    "PAYERSTATUS": "verified",
    "PAYMENTSTATUS": "Completed",
    "PAYMENTTYPE": "instant",
    "PENDINGREASON": "None",
    "PROTECTIONELIGIBILITY": "Ineligible",
    "PROTECTIONELIGIBILITYTYPE": "None",
    "REASONCODE": "None",
    "RECEIVERBUSINESS": "seller@email.com",
    "RECEIVEREMAIL": "seller@email.com",
    "RECEIVERID": "7KW652V29A9XJ",
    "SALESTAX": "0.00",
    "SHIPAMOUNT": "0.00",
    "SHIPHANDLEAMOUNT": "0.00",
    "TAXAMT": "0.00",
    "TIMESTAMP": "2014-11-27T02:53:45Z",
    "TRANSACTIONID": "2D351485ST427014X",
    "TRANSACTIONTYPE": "webaccept",
    "VERSION": "95",
    "WSO_AFF_AMOUNT": "0.00",
    "WSO_AFF_EMAIL": "",
    "WSO_CUSTOMER_EMAIL": "john.doe@email.com",
    "WSO_CUSTOMER_NAME": "John Doe",
    "WSO_IPN_VERSION": "1",
    "WSO_PRODUCT_ID": "wp_product_1",
    "WSO_PRODUCT_NAME": "ProductA",
    "WSO_SALE_ACTION": "SALE",
    "WSO_SALE_AMOUNT": "50.00",
    "WSO_SALE_ID": "wp_sale_1",
    "WSO_SALE_CURRENCY": "USD",
    "WSO_SIGNATURE": "0380a0fe6515f6552bab3f23c6b5c6c22f9f1f8e",
    "WSO_TXN_ID": "2D351485ST427014X",
    "payer_email": "john.doe@email.com",
    "saleid": "wp_sale_1"
}

print is_signature_valid(data, 'BIG_SECRET')
Ruby:

Code:
require 'open-uri'
require 'digest/sha1'

def is_signature_valid(data, signKey)
    return false unless data.include?('WSO_SIGNATURE')

    expected_signature = data.delete('WSO_SIGNATURE')
    data = data.sort_by { |key,value| key }
    encoded_data = URI.encode_www_form(data)
    signature = Digest::SHA1.hexdigest(encoded_data + signKey)

    return signature == expected_signature
end

data = {
    "AMT" =>"50.00",
    "COUNTRYCODE" =>"AU",
    "CURRENCYCODE" =>"USD",
    "EMAIL" =>"ivan.ivanovich@email.com",
    "FEEAMT" =>"2.25",
    "FIRSTNAME" =>"Ivan",
    "LASTNAME" =>"Ivanovich",
    "ORDERTIME" =>"2014-11-27T01:57:40Z",
    "PAYERID" =>"FYPB3LQJWVV72",
    "PAYERSTATUS" =>"verified",
    "PAYMENTSTATUS" =>"Completed",
    "PAYMENTTYPE" =>"instant",
    "PENDINGREASON" =>"None",
    "PROTECTIONELIGIBILITY" =>"Ineligible",
    "PROTECTIONELIGIBILITYTYPE" =>"None",
    "REASONCODE" =>"None",
    "RECEIVERBUSINESS" =>"seller@email.com",
    "RECEIVEREMAIL" =>"seller@email.com",
    "RECEIVERID" =>"7KW652V29A9XJ",
    "SALESTAX" =>"0.00",
    "SHIPAMOUNT" =>"0.00",
    "SHIPHANDLEAMOUNT" =>"0.00",
    "TAXAMT" =>"0.00",
    "TIMESTAMP" =>"2014-11-27T02:53:45Z",
    "TRANSACTIONID" =>"2D351485ST427014X",
    "TRANSACTIONTYPE" =>"webaccept",
    "VERSION" =>"95",
    "WSO_AFF_AMOUNT" =>"0.00",
    "WSO_AFF_EMAIL" =>"",
    "WSO_CUSTOMER_EMAIL" =>"ivan.ivanovich@email.com",
    "WSO_CUSTOMER_NAME" =>"Ivan Ivanovich",
    "WSO_IPN_VERSION" =>"1",
    "WSO_PRODUCT_ID" =>"wp_product_1",
    "WSO_PRODUCT_NAME" =>"ProductA",
    "WSO_SALE_ACTION" =>"SALE",
    "WSO_SALE_AMOUNT" =>"50.00",
    "WSO_SALE_ID" =>"wp_sale_1",
    "WSO_SALE_CURRENCY" =>"USD",
    "WSO_SIGNATURE" =>"78a0929ea59807ea3bcd5089b35ef5858a403f3f",
    "WSO_TXN_ID" =>"2D351485ST427014X",
    "payer_email" =>"ivan.ivanovich@email.com",
    "saleid" =>"wp_sale_1"
}

puts is_signature_valid(data, 'BIG_SECRET')
PHP:

Code:
<?php

function is_signature_valid($data, $signKey) {
    if (!array_key_exists('WSO_SIGNATURE', $data)) {
        return false;
    }

    $expected_signature = $data['WSO_SIGNATURE'];
    unset($data['WSO_SIGNATURE']);

    ksort($data);
    $encoded_data = http_build_query($data);
    $signature = sha1($encoded_data.$signKey);

    return $signature == $expected_signature;
}

$data = array(
    "AMT" =>"50.00",
    "COUNTRYCODE" =>"AU",
    "CURRENCYCODE" =>"USD",
    "EMAIL" =>"john.doe@email.com",
    "FEEAMT" =>"2.25",
    "FIRSTNAME" =>"John",
    "LASTNAME" =>"Doe",
    "ORDERTIME" =>"2014-11-27T01:57:40Z",
    "PAYERID" =>"FYPB3LQJWVV72",
    "PAYERSTATUS" =>"verified",
    "PAYMENTSTATUS" =>"Completed",
    "PAYMENTTYPE" =>"instant",
    "PENDINGREASON" =>"None",
    "PROTECTIONELIGIBILITY" =>"Ineligible",
    "PROTECTIONELIGIBILITYTYPE" =>"None",
    "REASONCODE" =>"None",
    "RECEIVERBUSINESS" =>"seller@email.com",
    "RECEIVEREMAIL" =>"seller@email.com",
    "RECEIVERID" =>"7KW652V29A9XJ",
    "SALESTAX" =>"0.00",
    "SHIPAMOUNT" =>"0.00",
    "SHIPHANDLEAMOUNT" =>"0.00",
    "TAXAMT" =>"0.00",
    "TIMESTAMP" =>"2014-11-27T02:53:45Z",
    "TRANSACTIONID" =>"2D351485ST427014X",
    "TRANSACTIONTYPE" =>"webaccept",
    "VERSION" =>"95",
    "WSO_AFF_AMOUNT" =>"0.00",
    "WSO_AFF_EMAIL" =>"",
    "WSO_CUSTOMER_EMAIL" =>"ivan.ivanovich@email.com",
    "WSO_CUSTOMER_NAME" =>"Ivan Ivanovich",
    "WSO_IPN_VERSION" =>"1",
    "WSO_PRODUCT_ID" =>"wp_product_1",
    "WSO_PRODUCT_NAME" =>"ProductA",
    "WSO_SALE_ACTION" =>"SALE",
    "WSO_SALE_AMOUNT" =>"50.00",
    "WSO_SALE_ID" =>"wp_sale_1",
    "WSO_SALE_CURRENCY" =>"USD",
    "WSO_SIGNATURE" =>"43122361d4ca2896548d0dc4f0ff02cb4a675441",
    "WSO_TXN_ID" =>"2D351485ST427014X",
    "payer_email" =>"johndoe@email.com",
    "saleid" =>"wp_sale_1"
);

echo is_signature_valid($data, 'BIG_SECRET');

***Update 27/07/2016***

Warrior Special Offers IPN Library

https://github.com/warriorforum/wso-ipn

This repository contains libraries for different web programming languages for handling WSO IPN (Instant Payment Notification) service.


WSO IPN Library for Java

This contains the class WsoIpn that accepts the http request's parameter names mapped to its value and/or the secret key and instantiates the WsoIpn. The class includes methods for signature validation and simple field getters.
This folder also includes unit tests for all the classes used in WsoIpn class.
An example on how to instantiate and use the WsoIpn class is shown in the servlet IPNListenerServlet.
The WsoIpn class can be extended to include functionalities (i.e., logging, persistence, etc.) necessary for other programs.
Note: The WsoIpn class was written to include very little to no dependency to third party libraries.


WSO IPN for Python

This contains the class WsoIpn that accepts the http request's dictionary of parameter and values. The class includes methods for signature validation and getter of necessary IPN data.
This also contains unit tests for signature validation and an example of a Listener that uses Flask.


WSO IPN for PHP

This contains the class WsoIpn that accepts the http request's dictionary of parameter and values. The class includes methods for signature validation and getter of necessary IPN data.
This also contains unit tests for signature validation and an example of a Listener.


Note:

The classes can be extended to include methods necessary for a program.
The provided code only serves as a guideline and example as to how to handle a WSO IPN. The way any of the code was structured should not be treated as standards.
The author is not liable for any errors caused by any WSO IPN library and shall not be responsible for any financial loss.
#warrior forum help #ipn #payments #processing #script #variables #warrior
Avatar of Unregistered
  • Profile picture of the author Cosmit
    Can you elaborate on this piece of code:

    Code:
    if (!array_key_exists('WSO_SIGNATURE', )) {
            return true;
        }
    Why does the function return true if WSO_SIGNATURE is missing? What is the point of validating a POST var that can simply be removed and pass as valid?
    {{ DiscussionBoard.errors[10018144].message }}
    • Profile picture of the author Ben Hernandez
      Originally Posted by Cosmit View Post

      Can you elaborate on this piece of code:

      Code:
      if (!array_key_exists('WSO_SIGNATURE', )) {
              return true;
          }
      Why does the function return true if WSO_SIGNATURE is missing? What is the point of validating a POST var that can simply be removed and pass as valid?
      Good point. The sample has been updated so that is_signature_valid returns false if there is no WSO_SIGNATURE.
      {{ DiscussionBoard.errors[10321483].message }}
  • Profile picture of the author luane
    HI there, trying to post a SELF-Hosted WSO, but can't get pass the IPN Url or Secret Key...

    Can you please explain and provide an EXAMPLE of exactly WHAT goes into those two fields? Thank you!
    {{ DiscussionBoard.errors[10161126].message }}
    • Profile picture of the author Webel
      Originally Posted by luane View Post

      HI there, trying to post a SELF-Hosted WSO, but can't get pass the IPN Url or Secret Key...

      Can you please explain and provide an EXAMPLE of exactly WHAT goes into those two fields? Thank you!
      Me too - why so complex, why nobody answering simple questions? Anybody home? Hello!
      {{ DiscussionBoard.errors[10318738].message }}
    • Profile picture of the author Ben Hernandez
      Originally Posted by luane View Post

      HI there, trying to post a SELF-Hosted WSO, but can't get pass the IPN Url or Secret Key...

      Can you please explain and provide an EXAMPLE of exactly WHAT goes into those two fields? Thank you!
      IPN url is the url of your server which gets called everytime a product sale is called. If your webserver is running on http://www.example.com, the url may be http://www.example.com/webhook_product_sale

      The Secret Key is whatever you want to make up. In the sample it is 'BIG_SECRET', you need to enter this in the "IPN SECRET" field in on the https://payments.warriorforum.com/post-wso (or equivalent) page.

      Let me know if you have further questions.
      {{ DiscussionBoard.errors[10321490].message }}
  • Profile picture of the author SageSound
    The PHP code example seems to have gotten the top part of code deleted.
    {{ DiscussionBoard.errors[10216997].message }}
  • Profile picture of the author BDazzler
    Looking at the Warrior Payments setup page --- were is the field WSO_PRODUCT_ID assigned?
    {{ DiscussionBoard.errors[10382615].message }}
    • Profile picture of the author Rick Rodriguez
      Originally Posted by BDazzler View Post

      Looking at the Warrior Payments setup page --- were is the field WSO_PRODUCT_ID assigned?
      WSO_PRODUCT_ID is generated from the internal product id.
      {{ DiscussionBoard.errors[10382668].message }}
  • Profile picture of the author floxtero
    Can anyone help me to setup.
    {{ DiscussionBoard.errors[10408416].message }}
    • Profile picture of the author Ben Hernandez
      Originally Posted by floxtero View Post

      Can anyone help me to setup.
      yes, what is the problem you are having?
      {{ DiscussionBoard.errors[10409818].message }}
  • Profile picture of the author myproductlaunch
    Is it possible to run a test order to make sure it's working? I input my Paypal IPN url, not sure what to put in the IPN secret. I have not idea if it's working or not.
    {{ DiscussionBoard.errors[10434864].message }}
  • Profile picture of the author mike_somerville
    In the process of developing a new tracking platform and we want to add this to the services. Does the IPN send information for affiliates too ? or is this just for Vendors ?

    Thanks!!
    Signature

    Get Paid To Build A List, While Building An Online Business On Autopilot Today! Click here to learn more.

    {{ DiscussionBoard.errors[10491046].message }}
  • Profile picture of the author KingBeven
    I am just a beautiful idiot and this whole conversation just went over my head.

    No one feel like putting this into steps, maybe just to get me starting in the right place.

    Thank you in advance your effort.

    Beven
    {{ DiscussionBoard.errors[10523552].message }}
    • Profile picture of the author Mark Kooijman
      Can anyone help me to setup an IPN Message?
      I don't understand this IPN Message Guide how to set up an IPN Message? GetTransactionDetails API call?

      Can you please explain and provide a VIDEO EXAMPLE of exactly WHAT goes into those fields?

      Thank you!
      Mark Kooijman
      PLR DAILY
      {{ DiscussionBoard.errors[11060710].message }}
Avatar of Unregistered

Trending Topics