Documentation
Digital Goods API
- Introduction
- Paymentwall Widget Call
- Stored Product Widget Call
- Widget URL
- Request Method
- Protocols Supported
- Parameters
- Mobile Widgets Use Case
- Widget Signature Calculation
- Examples
- Non-Stored Product Widget Call
- Widget URL
- Request Method
- Protocols Supported
- Parameters
- Mobile Widget Use Case
- Signature Calculation and Building Widget URL
- Server-Side Widget Call
- Pingback Processing
Introduction
Digital Goods / Subscriptions / One-Time Payments API allows you to monetize such products and services as:
- Recurring membership
- In-game virtual items
- Digital content
- Full version of a game
- Other one-time payments
Technical integration includes two steps:
- Paymentwall Widget Call
- Pingback Processing
Paymentwall Widget Call
Paymentwall securely captures all the required payment details via widgets hosted on Paymentwall Platform.
Paymentwall Widget as an HTML/HTML5 based widget can be displayed to users in two alternative ways:
- Iframe - Paymentwall Widget can be embed into merchant's website as an iframe.
- Full-page - Users can be redirected to Paymentwall Widget as an external page. This is preferrable for Mobile Widgets (Paymentwall Mobile, Offerwall Mobile)
In both cases the URL of the widget is generated in the same way as described below.
Stored Product Widget Call can be used when Paymentwall stores the product inventory on Paymentwall end.
Non-Stored Product Widget Call can be used if you have your own product inventory system.
Stored Product Widget Call (ex. Default Widget Call)
This shows a widget, where stored products in Products section of Merchant Account are available for payment. Widget URL
For payments widgets (p1, p2, p3): https://api.paymentwall.com/api/subscription/
For offers widgets (w1, w2, s1, s2, s3): https://api.paymentwall.com/api/
GET
HTTP, HTTPS
Parameter | Required | Possible values | Description |
---|---|---|---|
key | yes | hexadecimal, 32 characters long | Project key, can be found in General Settings of the Project inside of your Merchant Account |
uid | yes | alphanumeric, up to 64 characters long | ID of the end-user in your system (usually it is an email) who is viewing the widget. Examples: numeric ID, username or email. Please note that uid parameter is not case-sensitive (e.g. JohnDoe and johndoe are considered the same user). If your project allows case sensitive usernames, please use a numeric ID for the uid parameter |
widget | yes | alphanumeric | Widget key, e.g. p1. Can be obtained in Merchant Account / Projects / Widgets section |
ps | only for some widgets (p2,m2,p1) | cc, paysafecard, test, etc. | Shortcode of the payment method which is displayed in the widget. List of shortcodes. |
ts | no | numeric, Unix timestamp | Time when request was initiated, represented as Unix timestamp - seconds since the Unix epoch (January 1 1970 00:00:00 GMT). If it's older then 60 minutes, user sees an error message. Recommended for preventing widget from being shared. |
sign | recommended | hexadecimal, 32 characters long, lowercase | If you want to secure the widget and disallow unauthorized widget access, you can sign the widget. By default this parameter is not required for widget call. If you want to make it required, please contact us. |
sign_version | no | 2, 3 | Signature Version |
country_code | no | ISO 3166-1 alpha-2 code of the country | Overrides default geo-targeting. Requires widget signature. |
yes | string | End-user's email. If this parameter is present, Paymentwall will automatically send a payment / offer completion receipt to the user. | |
User Profile API parameters | yes | array | Parameters for enhanced Risk Scoring, such as lastname, firstname, address, birthday, engagement history. Refer to User Profile API |
evaluation | no | 1, 0 | If 1, widget can be loaded even until the project status is Live without being logged into the merchant account in the same browser session. Requires signature version 2 or higher. |
lang | no | ISO 639-1, e.g. en | Language code to override the default geo-targeted language of the widget. Please refer to this article for the full supported language codes list |
success_url | no | URL | URL of the thank you page where the end-user should be redirected to after the payment is complete. This URL shouldn't be used instead of the Pingback Processing for the actual product delivery and updating the merchant's database. |
failure_url | no | URL | URL of the page where the end-user should be redirected to after if payment has failed. Only is used when there is no way to complete this payment with this method. For credit cards user is not redirected to this page as he can still correct the error by using another card. |
default_goodsid | no | alphanumeric | The id of the product which you want to be chosen by default in the widget |
hide_goodsid[] | no | alphanumeric | ID's of the products that should not be displayed in the widget (e.g. &hide_goodsid[0]=product_1&hide_goodsid[1]=product_2). The array needs to be indexed explicitly for correct request signature calculation (e.g. hide_goodsid[0]=product_1 and not hide_goodsid[]=product_1) |
display_goodsid | no | alphanumeric | Id of the product to display in the widget (e.g. &display_goodsid=1). Also can be an array, e.g. display_goodsid[0]=product_1&display_goodsid[1]=product_2, which should be indexed explicitly |
pingback_url | no | URL | Optional URL of pingback listener script where pingbacks should be sent. Overrides the default Pingback URL set up in Project Settings inside of merchant account. Takes effect only if activated for the merchant account per request. Requires widget call to be signed with signature version 2 or higher. |
Widget Type | Description |
---|---|
Paymentwall Mobile | widget parameter is m2 or m2_x (e.g. m2_1). Widget base URL is https://api.paymentwall.com/api/ps/ |
Offerwall Mobile | widget parameter is mw1 or mw1_x (e.g. mw1_2). Widget base URL is https://api.paymentwall.com/api/ |
For mobile websites, users should be redirected to Widget page as an external standalone page.
For mobile apps, the Widget URL should be embed into project via WebView.
Signature (version 1)
sign = MD5([USER_ID][SECRET_KEY])
MD5 lowercase hash in the form of 32 digit hexadecimal number.
Example:
- SECRET_KEY = 3b5949e0c26b87767a4752a276de9570
- uid = 100
- sign = MD5([USER_ID][SECRET_KEY]) = MD5(1003b5949e0c26b87767a4752a276de9570) = 2fa09ff8065a6151844135261f95ad58
Signature (version 2 and 3)
Please refer to Signature Calculation documentation.
http://api.paymentwall.com/api/subscription/?key=test_f9088da998ff21613dc7db38b67&uid=100&widget=p1
http://api.paymentwall.com/api/subscription/?key=test_f9088da998ff21613dc7db38b67&uid=100&widget=p2&ps=cc
http://api.paymentwall.com/api/?key=test_f9088da998ff21613dc7db38b67&uid=100&widget=w1
Non-Stored Product Widget Call (ex. Flexible Widget Call)
This shows a widget, where only 1 product is available for payment and its details are passed via API parameters below dynamically (including price, ID and description).
https://api.paymentwall.com/api/subscription
GET
HTTP, HTTPS
Parameter | Required | Possible values | Description |
---|---|---|---|
key | yes | hexadecimal, 32 characters long | Project key, can be found in General Settings of the Project inside of your Merchant Account |
uid | yes | alphanumeric, up to 64 characters long | ID of the end-user in your system who is viewing the widget. Examples: numeric ID, username or email. Please note that uid parameter is case-insensitive (e.g. JohnDoe and johndoe are considered the same user). If your project allows case sensitive usernames, please use a numeric ID for the uid parameter |
widget | yes | alphanumeric | Widget key, e.g. p1. Can be obtained in Merchant Account / Projects / Widgets section |
amount | yes | numeric, with "." as decimal delimiter | Amount of the purchase, e.g. 10.00 |
currencyCode | yes | ISO 4217 | Currency of the purchase, e.g. USD, EUR |
ps | only for some widgets (p2,m2,p1) | cc, paysafecard, zong, etc. | Name of the payment method which is displayed in the widget. List of shortcodes. |
ag_name | yes | alphanumeric, up to 256 characters long | Product name |
ag_external_id | yes | alphanumeric, up to 256 characters long | Alphanumeric ID of the product in your system, which we communicate back to you via the pingback as goodsid parameter. |
ag_type | yes | fixed / subscription | subscription type is used for time based products, e.g. 3 month membership; fixed is used for one-time payments, like lifetime membership. |
ag_period_length | yes* | numeric | Length of product period, e.g. 3. Required when ag_type is subscription. |
ag_period_type | yes* | day / week / month / year | Type of product period. Required when ag_type is subscription. |
ag_recurring | no | 1 or 0 | Whether the product is recurring. Recurring billing is supported only when ag_type is subscription. If product is trial ag_recurring should always be 1. By default, recurring billing is only supported for product with duration of at least 3 days and less than 1 year. |
ag_promo | no | (e.g. "Save 20%") | Text of the custom promo message for the product. |
ag_trial** | no | 1 or 0 | Whether the product is trial. In this case post trial product should be specified too. |
ag_post_trial_period_length** | no | numeric | Length of post-trial product period, e.g. 3. Required when ag_trial is 1. |
ag_post_trial_period_type** | no | day / week / month / year | Type of post-trial product period. Required when ag_trial is 1. |
ag_post_trial_external_id** | no | alphanumeric, up to 256 characters long | Alphanumeric ID of the post-trial product in your system, which we communicate back to you via the pingback as goodsid parameter. Required when ag_trial is 1. |
post_trial_amount** | no | numeric, with "." as decimal delimiter | Amount of the post-trial product purchase, e.g. 10.00. Required when ag_trial is 1. |
post_trial_currencyCode** | no | ISO 4217 | Currency of the post-trial purchase, e.g. USD, EUR. Required when ag_trial is 1. |
ag_post_trial_name** | no | alphanumeric, up to 256 characters long | Name of post-trial product. |
hide_post_trial_good** | no | 1 or 0 | Hide post-trial good and show only trial product or not. If set to 0, user will be able to buy post-trial product without buying trial first. |
ts | no | numeric, Unix timestamp | Time when request was initiated, represented as Unix timestamp - seconds since the Unix epoch (January 1 1970 00:00:00 GMT). If it-s older then 60 minutes, user sees an error message. Recommended for preventing widget from being shared. |
sign_version | yes | 2, 3 | Signature version |
sign | yes | hexadecimal, 32 characters long, lowercase | Request signature. All parameters in request need to be signed. |
country_code | no | ISO 3166-1 alpha-2 code of the country | Overrides default geo-targeting. Requires widget signature. |
yes | string | End-user's email. If this parameter is present, Paymentwall will automatically send a payment / offer completion receipt to the user. | |
User Profile API parameters | yes | array | Parameters for enhanced Risk Scoring, such as lastname, firstname, address, birthday, engagement history. Refer to User Profile API |
evaluation | no | 1, 0 | If 1, widget can be loaded even until the project status is Live without being logged into the merchant account in the same browser session. Requires signature version 2 or higher. |
lang | no | ISO 639-1, e.g. en | Language code to override the default geo-targeted language of the widget. Please refer to this article for the full supported language codes list |
success_url | no | URL | URL of the page where the end-user should be redirected to after the payment is complete. This URL shouldn't be used instead of the Pingback Processing for the actual product delivery and updating the merchant's database. Supports $ag_external_id placeholder for Non-Stored Product Widget Call. |
failure_url | no | URL | URL of the page where the end-user should be redirected to after if payment has failed. Only is used when there is no way to complete this payment with this method. For credit cards user is not redirected to this page as he can still correct the error by using another card. |
pingback_url | no | URL | Optional URL of pingback listener script where pingbacks should be sent. Overrides the default Pingback URL set up in Project Settings inside of merchant account. Takes effect only if activated for the merchant account per request. Requires widget call to be signed with signature version 2 or higher |
show_trial_non_recurring* | no | 1 or 0 (default value is '0') | Hides trial product for non recurring payment methods |
show_trial_recurring* | no | 1 or 0 (default value is '0') | Hides trial product for recurring payment methods |
show_post_trial_non_recurring* | no | 1 or 0 (default value is '1') | Shows post-trial product for non recurringpayment methods |
show_post_trial_recurring* | no | 1 or 0 (default value is '1') | Shows post-trial product for recurring payment methods |
* - These parameters can be activatable by request
** - Fields for trial widget call
Widget Type | Description |
---|---|
Paymentwall Mobile | widget parameter is m2 or m2_x (e.g. m2_1). Widget base URL is https://api.paymentwall.com/api/subscription/ |
For mobile websites, users should be redirected to Widget page as an external standalone page.
For mobile apps, the Widget URL should be embed into project via WebView.
Signature Calculation and Building Widget URL
Signature Calculation
For detailed info on signature calculation please refer to Signature Calculation documentation.
Building Widget URL with Paymentwall PHP Library at GitHub
require_once('/path/to/paymentwall-php/lib/paymentwall.php');
Paymentwall_Base::setApiType(Paymentwall_Base::API_GOODS);
Paymentwall_Base::setAppKey('YOUR_PROJECT_KEY'); // available in your Paymentwall merchant area
Paymentwall_Base::setSecretKey('YOUR_SECRET_KEY'); // available in your Paymentwall merchant area
$widget = new Paymentwall_Widget(
'user40012', // id of the end-user who's making the payment
'p1_1', // widget code, e.g. p1; can be picked inside of your merchant account
array( // product details for Non-Stored Product Widget Call. To let users select the product on Paymentwall's end, leave this array empty
new Paymentwall_Product(
'product301', // id of the product in your system
9.99, // price
'USD', // currency code
'Gold Membership', // product name
Paymentwall_Product::TYPE_SUBSCRIPTION, // this is a time-based product; for one-time products, use Paymentwall_Product::TYPE_FIXED and omit the following 3 array elements
1, // duration is 1
Paymentwall_Product::PERIOD_TYPE_MONTH, // month
true // recurring
)
),
array('email' => 'user@hostname.com') // additional parameters
);
echo $widget->getHtmlCode();
For more code samples in different programming languages, please visit https://www.paymentwall.com/en/documentation/getting-started/
Server-Side Widget Call
This allows using Non-Stored Product Call, but sending all the widget parameters via server side and getting a widget session key - one token that can be used for loading the widget. This allows sending data that shouldn't be visible via the browser, such as unique order ID. User can then be redirected to the widget using the generated widget session key.
This feature can be activated for your account if you email us at devsupport@paymentwall.com
https://api.paymentwall.com/api/standalone/
GET
HTTP, HTTPS
See non-stored widget call for digital goods API
32 character widget session key as an Json Object e.g. {"type":"success","skey":"12345678901234567890123456abcdef"}
https://api.paymentwall.com/api/subscription/
GET
HTTP, HTTPS
Parameter | Required | Possible values | Description |
---|---|---|---|
skey | yes | hexadecimal, 32 characters long, lowercase | Widget session key. |
Please refer to Signature Calculation documentation.
Pingback Processing
Whenever a user pays or completes an offer, we send you a pingback, also known as callback, postback, or instant payment notification.
Pingbacks can be sent in one of the two formats:
Type | Description |
---|---|
HTTP Request | HTTP request is sent from our servers to your Pingback listener script where we communicate to your server details about the payment so that your server can process the pingback automatically and deliver the virtual currency to the according user. URL of your script that listens for pingbacks is called Pingback URL. This format is preferable. |
An email is sent to the address that you configure as your Pingback Email once a user pays or completes an offer. Once you receive the email, you should deliver the product manually to the according user. |
http://www.yourserver.com/anypath?uid=[USER_ID]&goodsid=[GOODS_ID]&slength=[SUBSCRIPTION_LENGTH]&speriod=[SUBSCRIPTION_PERIOD]&type=[TYPE]&ref=[REF]&sig=[SIGNATURE]
GET
HTTP, HTTPS
- uid - id of user to be credited. The value of uid parameter from Paymentwall Call is used (e.g. Facebook Third-Party ID). The uid parameter is also case-insensitive, so the usernames such as superUser and Superuser are going to be the same thing
- goodsid - id of product (subscription, package) that you enter when defining products (Product ID column in the Products section). If Non-Stored Product Widget Call is used, goodsid equals ag_external_id parameter of the widget call. Alphanumeric, e.g. gold_membership
- slength - length of product, positive whole number, e.g. 5. When sold item is a fixed package, slength contains empty string
- speriod - period of product: day, week, month, year. When sold item is a fixed package, speriod contains empty string
- type - type of pingback:
- type=0 - when product is purchased
- type=1 - when product is given as a customer service courtesy (write-off)
- type=2 - in case of chargeback (see below)
- type=12 - subscription cancellation (e.g. if a user cancels his subscription; sent immediately upon cancellation, e.g. in the middle of current premium month)
- type=13 - subscription expired
- type=14 - subscription payment failed (sent if the subscription is stopped due to failing payments e.g. due to insufficient funds)
Additionally, the following pingback types are sent for payments done via Brick API:
- type=200 - payment is currently under review by Paymentwall risk team
- type=201 - payment that has been under risk review has now been accepted by the risk team
- type=202 - payment that has been under risk review has now been declined by the risk team and the user has been refunded
- type=203 - authorization has been voided due to no capture request received on time
For pingback signature version 1
sig = MD5(uid=[USER_ID]goodsid=[GOODS_ID]slength=[PRODUCT_LENGTH]speriod=[PRODUCT_PERIOD]type=[TYPE]ref=[REF][SECRET_KEY])
For pingback signature version 2, please refer to Signature Calculation documentation.
Custom Parameters
Merchants can also set up custom pingback parameters in My Projects > Settings > Custom Pingback Parameters section. There, any custom parameters can be added by specifying their name and value. For receiving back the parameters sent in the widget call, their name should be specified along with value=OWN. Various other values are supported, such as user's country, payment method used, revenue etc. Screenshot of Custom Pingback Parameters.
- SECRET\_KEY = 3b5949e0c26b87767a4752a276de9570
- uid = 1
- goodsid = gold\_membership
- slength = 3
- speriod = month
- type = 0
- ref = 3
- sig = MD5(goodsid=[GOODS_ID]ref=[REF]slength=[PRODUCT_LENGTH]speriod=[PRODUCT_PERIOD]type=[TYPE]uid=[USER_ID][SECRET_KEY]) = MD5(goodsid=gold_membershipref=3slength=3speriod=monthtype=0uid=13b5949e0c26b87767a4752a276de9570) =ffcbeba5f97f92e800c297ab27ff9796
http://www.yourserver.com/anypath?uid=1&goodsid=gold_membership&slength=3&speriod=month&type=0&ref=3&sig=84d081d1af73ccdf5f7281a145d03ce6
If you are able to process the pingback requests, please start your response message with 'OK'. If we don't receive a confirmation message, or if the response status code is different from 200, we'll send pingback again within 30 minutes and the subsequent retries will happen at 30 minute increments after that.
Please add the following IP Addresses as authorized IP addresses to access the script:
- 174.36.92.186
- 174.36.92.187
- 174.36.92.192
- 174.36.96.66
- 174.37.14.28
Please note that certain load balancing services, such as CloudFlare, may alter the originating IP of the request. In such case, the IP address of the request visible on your server may different from original IP address. In this case, using HTTP_X_REAL_IP request header should help getting the original Paymentwall's IP to check if it is whitelisted.
Required. This is used in cases of fraud, correction etc. Paymentwall sends request to the Callback URL and communicates how much virtual currency should be taken back from which userID. Format, Request method and Parameters are the same as for common Callback except for:
- currency - negative whole number (e.g. -2)
- type = 2 in case of chargeback
- reason - code of chargeback reason. Possible reasons are:
Code | Reason | Recommendation | |
---|---|---|---|
1 | Chargeback | ||
2 | Credit Card fraud | Ban User | |
3 | Order fraud | Ban User | |
4 | Bad data entry | ||
5 | Fake / Proxy user | ||
6 | Rejected by advertiser | ||
7 | Duplicate conversions | ||
8 | Goodwill credit taken back | ||
9 | Canceled order, e.g. refund | ||
10 | Partially reversed transaction |
Sample Pingback Listener Script
Sample code using Paymentwall PHP library at GitHub.
require_once('/path/to/paymentwall-php/lib/paymentwall.php');
Paymentwall_Base::setApiType(Paymentwall_Base::API_GOODS);
Paymentwall_Base::setAppKey('YOUR_PROJECT_KEY'); // available in your Paymentwall merchant area
Paymentwall_Base::setSecretKey('YOUR_SECRET_KEY'); // available in your Paymentwall merchant area
$pingback = new Paymentwall_Pingback($_GET, $_SERVER['REMOTE_ADDR']);
if ($pingback->validate()) {
$productId = $pingback->getProduct()->getId();
if ($pingback->isDeliverable()) {
// deliver the product
} else if ($pingback->isCancelable()) {
// withdraw the product
} else if ($pingback->isUnderReview()) {
// set "pending" as order status
}
echo 'OK'; // Paymentwall expects response to be OK, otherwise the pingback will be resent
} else {
echo $pingback->getErrorSummary();
}
For more code samples in different programming languages, please visit https://www.paymentwall.com/en/documentation/getting-started/
Client-side Callback
If you would like to redirect the user after a payment is made, you can pass the success_url parameter that will be used as the URL of Continue button displayed to the end-user after a payment is made.
Additionally, Paymentwall can send a client-side JavaScript callback once a payment is made that you can receive in the following way:
Version 1 (Deprecated)
<script type="text/javascript">
window.addEventListener('message', function(event) {
if(event.origin !== 'https://api.paymentwall.com') return;
var data = eval('(' + event.data + ')');
},false);
function PaymentwallWidgetSuccessHandler() {
// hide the widget
}
// optional function for resizing the iframe that can be requested from devsupport
function PaymentwallWidgetResizeHandler(dimensions) {
document.getElementById('paymentwall_iframe').style.height = dimensions.height;
}
</script>
Version 2
For specific events Paymentwall sends a client-side callback via window.postMessage() mechanism with the event data in JSON format into the parent page of the merchant that embeds the iframe widget. This can be used for updating your page respectively (e.g. blocking Close button if the payment is being processed), tracking events in Google Analytics etc. Currently supported events:
Event | Description |
---|---|
paymentSuccess | Sent once a payment has been successfully. Payment details are sent in data field of the JSON message. The format of data is similar to Payment Status API response (see example below). |
widgetLoaded | Sent once the widget has been loaded. |
widgetSizeChanged | Sent once the widget dimensions have been changed. Dimensions are sent in data field of JSON message in the following format: {"height":"1000px","width":"700px"} |
paymentProcessingStart | Sent once a user started making a payment, e.g. a payment method popup has been opened or a payment method iframe has been loaded. Recommended action: prevent the widget from closing until paymentSuccess or paymentProcessingEnd is received. |
paymentProcessingEnd | Sent once a user stopped making a payment, e.g. by closing a payment method popup or by switching to another payment method thus closing the previously opened iframe. |
{
"event":"paymentSuccess",
"data":{
"object":"payment",
"id":"b123456",
"created":1419438832,
"amount":"9.99",
"currency":"USD",
"refunded":false,
"risk":"approved",
"uid":"user_200255",
"product_id":"product_100244",
"payment_system":"cc",
}
}
Below is sample listener that can be used:
<script type="text/javascript">
window.addEventListener('message', function(event) {
if(event.origin !== 'https://api.paymentwall.com') return;
var eventData = JSON.parse(event.data);
if (eventData.event == 'paymentSuccess') {
// handle the successful payment scenario
alert('Thank you for paying ' + eventData.data.amount + ' ' + eventData.data.currency);
}
},false);
</script>
This feature can be activated for your account if you email us at devsupport@paymentwall.com