Giter Club home page Giter Club logo

paymentwall-node's Introduction

About Paymentwall

Paymentwall is the leading digital payments platform for globally monetizing digital goods and services. Paymentwall assists game publishers, dating sites, rewards sites, SaaS companies and many other verticals to monetize their digital content and services. Merchants can plugin Paymentwall's API to accept payments from over 100 different methods including credit cards, debit cards, bank transfers, SMS/Mobile payments, prepaid cards, eWallets, landline payments and others.

To sign up for a Paymentwall Merchant Account, click here.

Paymentwall Node.js Library

This library allows developers to use Paymentwall APIs (Virtual Currency, Digital Goods featuring recurring billing, and Virtual Cart).

To use Paymentwall, all you need to do is to sign up for a Paymentwall Merchant Account so you can setup an Application designed for your site. To open your merchant account and set up an application, you can sign up here.

Installation

To install the library in your environment, simply run the following command:

npm install paymentwall

Then use a code sample below.

Code Samples

Digital Goods API

Web API details

Initializing Paymentwall

var Paymentwall = require('paymentwall');
Paymentwall.Configure(
  Paymentwall.Base.API_GOODS,
  'YOUR_APPLICATION_KEY',
  'YOUR_SECRET_KEY'
);

Widget Call

The widget is a payment page hosted by Paymentwall that embeds the entire payment flow: selecting the payment method, completing the billing details, and providing customer support via the Help section. You can redirect the users to this page or embed it via iframe. The sample code below renders an iframe with Paymentwall Widget.

var widget = new Paymentwall.Widget(
  'user40012',                                // id of the end-user who's making the payment
  'pw',                                       // widget code, e.g. pw; can be picked in the Widgets section of your merchant account 
  [                                           // product details for Flexible Widget Call. 
                                              // Leave empty if product selection happens on Paymentwall's side
    new Paymentwall.Product(
      'product301',                           // id of the product in your system  
      9.99,                                   // price
      'USD',                                  // currency code
      'Gold Membership',                      // product name
      // if it is a onetime charge product, you don't need to configure time-based part
      Paymentwall.Product.TYPE_SUBSCRIPTION,  // this is a time-based product
      1,                                      // length of product period
      Paymentwall.Product.PERIOD_TYPE_MONTH,  // type of product period
      true                                    // this is a recurring product
    )
  ],
  {'email': '[email protected]'}              // additional parameters. for full list check API docs
);
console.log(widget.getHtmlCode());

Pingback Processing

The Pingback is a webhook notifying about a payment being made. Pingbacks are sent via HTTP/HTTPS to your servers. To process pingbacks use the following code:

var pingback = new Paymentwall.Pingback("query data in pingback request", "ip address of pingback");
if (pingback.validate()) {
  var productId = pingback.getProduct().getId();
  if (pingback.isDeliverable()) {
    // deliver the product
  } else if (pingback.isCancelable()) {
    // withdraw the product
  } 
  console.log('OK'); // Paymentwall expects the string OK in response, otherwise the pingback will be resent
} else {
  console.log(pingback.getErrorSummary());
}

Virtual Currency API

Web API Details

Initializing Paymentwall

var Paymentwall = require('paymentwall');
Paymentwall.Configure(
  Paymentwall.Base.API_VC,
  'YOUR_APPLICATION_KEY',
  'YOUR_SECRET_KEY'
);

Widget Call

var widget = new Paymentwall.Widget(
  'user40012',
  'p10',
  [],
  {'email': '[email protected]'}
);
console.log(widget.getHtmlCode());

Pingback Processing

var pingback = new Paymentwall.Pingback("query data in pingback request", "ip address of pingback");
if (pingback.validate()) {
  var virtualCurrency = pingback.getVirtualCurrencyAmount();
  if (pingback.isDeliverable()) {
    // deliver the virtual currency
  } else if (pingback.isCancelable()) {
    // withdraw the virtual currency
  } 
  console.log('OK'); // Paymentwall expects the string OK in response, otherwise the pingback will be resent
} else {
  console.log(pingback.getErrorSummary());
}

Cart API

Web API Details

Initializing Paymentwall

var Paymentwall = require('paymentwall');
Paymentwall.Configure(
  Paymentwall.Base.API_CART,
  'YOUR_APPLICATION_KEY',
  'YOUR_SECRET_KEY'
);

Widget Call

var widget = new Paymentwall.Widget(
  'user40012',
  'p10',
  [
    new Paymentwall.Product('product301', 3.33, 'EUR'), // first product in cart
    new Paymentwall.Product('product607', 7.77, 'EUR')  // second product in cart
  ],
  {'email': '[email protected]'}
);
console.log(widget.getHtmlCode());

Pingback Processing

var pingback = new Paymentwall.Pingback("query data in pingback request", "ip address of pingback");
if (pingback.validate()) {
  var productId = pingback.getProduct().getId();
  if (pingback.isDeliverable()) {
    // deliver the product
  } else if (pingback.isCancelable()) {
    // withdraw the product
  } 
  console.log('OK'); // Paymentwall expects the string OK in response, otherwise the pingback will be resent
} else {
  console.log(pingback.getErrorSummary());
}

Brick API

Web API details

Initializing Paymentwall

var Paymentwall = require('paymentwall');
Paymentwall.Configure(
  Paymentwall.Base.API_GOODS,
  'YOUR_APPLICATION_KEY',
  'YOUR_SECRET_KEY'
);

Create a one-time token

var onetimetoken = new Paymentwall.Onetimetoken(
  4000000000000002, // Card number, digits only
  01,               // Expiration month, 2 digits from 01 to 12
  2017,             // Expiration year, 4 digits
  222               // CVC/CVV, 3-4 digits
);

onetimetoken.createOnetimetoken(function(response){
  // response is a new Response Object Entity (defined in paymentwall/lib/Response/Abstract)
  if(response.isSuccessful()){
    if(response.isActivated()){
      token = response.getOnetimeToken();         //get onetimetoken
      card = response.getCardInfo();              //get card information    
    }
  } else{
    error_code = response.getErrorCode();
    error_details = response.getErrorDetails();
  };
  console.log(response.getFullResponse());
});

Charge

var charge = new Paymentwall.Charge(
  0.5,                                 //price
  'USD',                               //currency code
  'description',                       //description of the product
  '[email protected]',             // user's email which can be gotten by req.body.email
  'fingerprint',                       // fingerprint which can be gotten by req.body.brick_fingerprint
  'onetimetoken',                      //one-time token
  {'custom[User_prfile_API]':'Value'}  //custom parameters
);

charge.createCharge(function(brick_response){
  // brick_response is a new Response Object Entity (defined in paymentwall/lib/Response/Abstract)
  if(brick_response.isSuccessful()){
    if(brick_response.isCaptured()){
      charge_id = brick_response.getChargeId();         //deliver goods to user
    } else if(brick_response.isUnderReview()){          
      charge_id = brick_response.getChargeId();         //under risk review
    } else if(brick_response.isUnder3DSecure()){        
      return_page = brick_response.get3DHtml();             //return 3D secure page
    };
  } else{
    error_code = brick_response.getErrorCode();         //handle error
    error_details = brick_response.getErrorDetails();
  };

  brick_response.getFullResponse();                      // get full response content in String format
  brick_response.getFullResponse('JSON');                // get full response content in JSON format
});

Charge Details

//get the charge details through chargeid
var charge = new Paymentwall.Charge();
charge.otherOperation(chargeid,'detail',function(brick_response){
  // brick_response is a new Response Object Entity (defined in paymentwall/lib/Response/Abstract)
  brick_response.getFullResponse();                      // get full response content in String format
  brick_response.getFullResponse('JSON');                // get full response content in JSON format
});

Charge-capture

//capture a charge through chargeid
var charge = new Paymentwall.Charge();
charge.otherOperation(chargeid,'capture',function(brick_response){
  // brick_response is a new Response Object Entity (defined in paymentwall/lib/Response/Abstract)
  brick_response.getFullResponse();                      // get full response content in String format
  brick_response.getFullResponse('JSON');                // get full response content in JSON format
});

Charge-void

//void a charge through chargeid
var charge = new Paymentwall.Charge();
charge.otherOperation(chargeid,'void',function(brick_response){
  // response is a new Response Object Entity (defined in paymentwall/lib/Response/Abstract)
  brick_response.getFullResponse();                     // get full response content in String format
  brick_response.getFullResponse('JSON');               // get full response content in JSON format
});

Charge-refund

//refund a charge through chargeid
var charge = new Paymentwall.Charge();
charge.otherOperation(chargeid,'refund',function(brick_response){
  // response is a new Response Object Entity (defined in paymentwall/lib/Response/Abstract)
  brick_response.getFullResponse();                      // get full response content in String format
  brick_response.getFullResponse('JSON');                // get full response content in JSON format
});

Subscription

//create a subscription
var subscription = new Paymentwall.Subscription(
  0.5,                                 //price
  'USD',                               //currency code
  'description',                       //description of the product
  '[email protected]',             // user's email which can be gotten by req.body.email
  'fingerprint',                       // fingerprint which can be gotten by req.body.brick_fingerprint
  'onetimetoken',                      //one-time token
  'day',                               // day/week/month/year
  3,                                   // duration
  {
    // parameters for trial period
    'trial[amount]':0.5,
    'trial[currency]':'USD',
    'trial[period]':'day',
    'trial[period_duration]':3
  },
  {'custom[User_prfile_API]':'Value'}  //custom parameters, if there is a trail, plan is required
);

subscription.createSubscription(function(brick_response){
  // brick_response is a new Response Object Entity (defined in paymentwall/lib/Response/Abstract)
  if(brick_response.isSuccessful()){
    if(brick_response.isActivated()&&brick_response.isStarted()){
      subscription_id = getSubscriptionId();
      charge_id = brick_response.getChargeId();         //deliver goods to user
    } else if(brick_response.isUnderReview()){          
      subscription_id = getSubscriptionId();
      charge_id = brick_response.getChargeId();         //under risk review
    } else if(brick_response.isUnder3DSecure()){        
      return_page = brick_response.get3DHtml();             //return 3D secure page
    };
  } else{
    error_code = brick_response.getErrorCode();         //handle error
    error_details = brick_response.getErrorDetails();
  };

  brick_response.getFullResponse();                      // get full response content in String format
  brick_response.getFullResponse('JSON');                // get full response content in JSON format
});

Subscription-details

//get the subscription details through subscriptionid
var subscription = new Paymentwall.Subscription();
subscription.otherOperation(subscriptionid,'detail',function(response){
  // response is a new Response Object Entity (defined in paymentwall/lib/Response/Abstract)
  response.getFullResponse();                      // get full response content in String format
  response.getFullResponse('JSON');                // get full response content in JSON format
});

Subscription-cancel

//cancel a subscription through subscriptionid
var subscription = new Paymentwall.Subscription();
subscription.otherOperation(subscriptionid,'cancel',function(response){
  // response is a new Response Object Entity (defined in paymentwall/lib/Response/Abstract)
  response.getFullResponse();                      // get full response content in String format
  response.getFullResponse('JSON');                // get full response content in JSON format
});

Pingback Processing

The Pingback is a webhook notifying about a payment being made. Pingbacks are sent via HTTP/HTTPS to your servers. To process pingbacks use the following code:

var pingback = new Paymentwall.Pingback("query data in pingback request", "ip address of pingback");
if (pingback.validate()) {
  var productId = pingback.getProduct().getId();
  if (pingback.isDeliverable()) {
    // deliver the product
  } else if (pingback.isCancelable()) {
    // withdraw the product
  } 
  console.log('OK'); // Paymentwall expects the string OK in response, otherwise the pingback will be resent
} else {
  console.log(pingback.getErrorSummary());
}

Signature API

Web API details

Widget Signature

var Paymentwall = require('paymentwall');
var widget_signature = Paymentwall.WidgetSignature.calculateSignature(parameters,secret_key, signature_version);

Pingback Signature

var Paymentwall = require('paymentwall');
var pingback_signature = Paymentwall.PingbackSignature.calculateSignature(parameters,secret_key, signature_version);

paymentwall-node's People

Contributors

hdolinski avatar ivan-kovalyov avatar liangnex avatar liufanhhh avatar masonpham avatar osminushkin avatar paymentwall-dev avatar svtslvskl avatar witem avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

paymentwall-node's Issues

Parameter key or uid is missing (error code 05)

Hello,
I have an error:
Parameter key or uid is missing (error code 05)
My widget in my express controller is:

<code> var widget = new Paymentwall.Widget(
user._id, // id of the end-user who's making the payment
'mw1_1', // widget code, e.g. pw; can be picked in the Widgets section of your merchant account
[ // product details for Flexible Widget Call.
// Leave empty if product selection happens on Paymentwall's side
new Paymentwall.Product(
'test sku id', // id of the product in your system
10, // price
'EUR', // currency code
'In the picture', // product name
// if it is a onetime charge product, you don't need to configure time-based part
Paymentwall.Product.TYPE_SUBSCRIPTION, // this is a time-based product
1, // length of product period
Paymentwall.Product.PERIOD_TYPE_MONTH, // type of product period
true // this is a recurring product
)
],
{'email': user.email} // additional parameters. for full list check API docs
);
console.log(widget.getHtmlCode());
return res.send(widget.getHtmlCode()); </code>

Case sensitive file systems brake on require

Throughout the codebase several instances of require("") use lowercase filenames, even though the real filename has a capital letter in it. On macOS this is totally fine, since the fs is case insensitive. But on ubuntu which is case sensitive, we get the following error:

Error: Cannot find module './base'
    at Function.Module._resolveFilename (module.js:470:15)
    at Function.Module._load (module.js:418:25)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/home/ubuntu/XXXXXX/node_modules/paymentwall/lib/Widget.js:3:12)

This at line 3 in Widget.js
var Base = require('./base'), should be var Base = require('./Base')

Partial refund?

According to the docs, partial refund is available,
image

However, the api suggests only a full refund

//refund a charge through chargeid
var charge = new Paymentwall.Charge();
charge.otherOperation(chargeid,'refund',function(brick_response){
  // response is a new Response Object Entity (defined in paymentwall/lib/Response/Abstract)
  brick_response.getFullResponse();                      // get full response content in String format
  brick_response.getFullResponse('JSON');                // get full response content in JSON format
});

If I want to refund 90% of the charge amount, how do I do that?

Fix readme - not existing WidgetSignature method

I suggest to change README.md Widget Signature section for something like this:

var widget = new Paymentwall.Widget();
var widget_signature = widget.calculateSignature('param1=param1Value', 'secret', Paymentwall.Base.SIGNATURE_VERSION_2);

Pingback validation is very broken

This library is currently unusable because the Pingback class doesn't work for a variety of reasons. I'm in the middle of a project at the moment so unfortunately don't have the time to rewrite this class, but I'll detail the issues I came across here in the hopes that a kind soul can start on fixing them.

  1. this is not available in the functions in which it's used, which means that attempting to access this.parameters fails and everything falls apart. There's a PR (#10) that attempts to fix this but it doesn't work. I'm not sure how this class is supposed to be modeled but the functions/this usage do not work in the way that it's intended.
  2. The sortObject function by nature can't work because JS objects don't guarantee the order of keys. This means that signature verification will often fail because the keys need to be in order. Rather than trying to sort the parameters first it's better to just iterate over the sorted parameters and directly construct the baseString - example below.

In the meantime, I made a small function to validate pingbacks - input params and IP like the normal Pingback constructor. This works for sig version 2, "goods API" pingbacks.

function validatePingback(params,ip) {
    // Check ip
    var ipsWhitelist = [
        '174.36.92.186',
        '174.36.96.66',
        '174.36.92.187',
        '174.36.92.192',
        '174.37.14.28'
    ];

    if(!~ipsWhitelist.indexOf(ip)) return false; // IP address not whitelisted

    // Check params
    var baseString = "", sig = params.sig;
    Object.keys(params).sort().forEach(function(key,i) {
        if(key === "sig") return;

        var value = params[key] || "";

        baseString += key + '=' + value;
    });
    baseString += Payment.getPaymentwallKey();

    var hash = crypto.createHash("md5").update(baseString).digest("hex");

    if(hash !== sig) return false; // Signature mismatch

    return true;
};

Improve documentation

There are lots of typos in the readme. I was wondering for quite a while what the trail of a subscription is. Also colons missing in some parts.

In many places it needs extensive research what the format of the parameters are. Just an example:
Birck / payment processing:

var pingback = new Paymentwall.Pingback(queryData, ipAddress, true);

what is the queryData exactly? what is the format? which ipAdress?
it would be very nice to have at least a link to paymentwall's appropriate doc, as I just couldn't find it.

Although this seems to be a very helpful library, I have to use it always reading its source code and trying to figure out which paymentwall doc is the relevant. The otherway of using this lib is trial and error, but its also time consuming.

Cart API Widget iframe generation is broken

adding multiple products in a flexible cart is not possible because the product names are not taken in consideration, see Widget.js line 76:

REPLACE:
if (product.currencyCode) {
params['currencies[' + index + ']'] = product.getCurrencyCode();
}
index++;

BY:
if (product.currencyCode) {
params['currencies[' + index + ']'] = product.getCurrencyCode();
}
if (product.name) {
params['names[' + index + ']'] = product.getName();
}
index++;

Base prototype contains static `errors` field

This field fills up as paymentwall errors are encountered. No public methods are exposed. I think it is a security issue, since nodejs server is doomed to leak and may be ddos'ed via paymentwall pingback endpoint.

It looks like you're not authorized to view this content. The request signature is wrong or expired

I get this error:

It looks like you're not authorized to view this content. The request signature is wrong or expired (sign=a04bbf8b4ad2fab2677604ead15938ea1cfe840d780a98fc204fe4478a8c6ad6).

This is my code:

var Paymentwall = require('paymentwall');
Paymentwall.Configure(
	Paymentwall.Base.API_GOODS,
	'KEY',
	'KEY'
);

var widget = new Paymentwall.Widget(
	'user40012', // uid
	'pw_1', // widget 
	[
		new Paymentwall.Product(
			'product301', // ag_external_id
			9.99, // amount
			'USD', // currencycode
			'Gold Membership', // ag_name
			Paymentwall.Product.TYPE_FIXED // ag_type
		)
	], {
		'email': '[email protected]',
		'history[registration_date]': 'registered_date_of_user',
		'ps': 'all', // Replace it with specific payment system short code for single payment methods
		'additional_param_name': 'additional_param_value'
	}
);
let url = widget.getUrl();
console.log(url)
const open = require('open');

// opens the url in the default browser 
open(url);

What's the issue? I just copied the code from your documentation, started setting up a shop and it's not working. The example code doesn't work.

Abstract.sortObject() ignores number value 0

In Abstract.sortObject() method used for signature calculation, if parameter has a numeric value of 0 (happens for me for for pingback type=0), it's improperly cast to "" instead of "0", thus failing the validation of signature. I'd make a PR, but not sure how exactly you want to treat this issue - what's the policy regarding undefined or null values passed. For now I'll use a workaround and manually cast each pingback parameter to String. OK, I see the issue - type is manually cast to Int in getType() method, so if I use this method before validating signature, it breaks it...

Another issue is that Pingback.getPingbackUniqueId() gets undefined for the second bit, but I haven't looked into that (if it's related to sortObject implementation). So for example pingback with params type=0&ref=ABC123XYZ, getPingbackUniqueId() returns ABC123XYZ_undefined.

refund with Widget

Hi,

we are using Widget api to accept payments... after the ipn we upgrade users (digital goods)... All well but i am still looking a way to refund clients via API. I understand that brick API might have something available but we are using Widget API. Can you please push us towards right API ? Many thanks

Pingback error

pingback.js getType 120

  if (this.parameters['type']) { ... }

When I have successful callback with type = 0 it fails on this string

It has to have another checking only for undefined, like this

  if (typeof this.parameters['type'] != 'undefined') { ... }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.