Documentation
PWLocal Android SDK§
PWLocal Android SDK§
Introduction§
Do you need to have an ability to accept payments from mobile users in different countries, considering which payment methods fit best? PWLocal is a global payment gateway that makes it easy to accept payments from customers in more than 200 countries with 100+ alternative payment options. PWLocal Android SDK will become a native part of your application, it eliminates the necessity to open a web browser for payments, as a result you will receive a higher conversions rate. All you have to do is import the library into your Android project and start using our SDK to accept in-app payments. It is quick and easy! We'll guide you through the process here.
How does it work ?§
- The customer clicks on the “Buy” button inside your application.
- The PWLocal SDK is called at this moment and opens application dialog with the list of payment systems.
- User chooses a payment system and clicks on “Buy”. After it, a new application dialog opens. It would be a "thank you" screen or a dialog for providing payment details, such as credit card number, if needed.
- The payment is completed and your callback function is triggered to handle its result. Your backend will be also notified about it.
Requirements§
Android 2.2 (API Level 8) and above
Credentials§
Your mobile integration requires a Project key.
You can obtain these Paymentwall API credentials in the application settings of your Merchant Account at paymentwall.com
Add SDK§
Our SDK is delivered as a JAR package so just drop it into your project.
It also requires android-support-v4.jar
, if your project doesn’t have it, please add one.
Modify your AndroidManifest.xml§
Add required permission§
<uses-permission android:name="android.permission.INTERNET" />
Add required activity§
<activity
android:name="com.paymentwall.sdk.pwlocal.ui.PwLocalActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:theme="@android:style/Theme.Translucent" />
First payment§
Import§
import com.paymentwall.sdk.pwlocal.message.*;
import com.paymentwall.sdk.pwlocal.ui.PwLocalActivity;
import com.paymentwall.sdk.pwlocal.utils.Key;
import com.paymentwall.sdk.pwlocal.utils.PaymentMethod;
import com.paymentwall.sdk.pwlocal.utils.ResponseCode;
import com.paymentwall.sdk.pwlocal.utils.MessageUtils;
Create a request§
We have 2 types of PWLocal payment request: LocalDefaultRequest
and LocalFlexibleRequest
We support 3 API type: ApiType.VIRTUAL_CURRENCY
, ApiType.DIGITAL_GOODS
, ApiType.CART
For more information, please refer to:
https://www.paymentwall.com/en/documentation/Digital-Goods-API/710
Defined request§
We defined 2 types of request: LocalDefaultRequest
and LocalFlexibleRequest
. You can simply use setters to set required parameters. Please note that all the parameters are changed from under_score to camelCase format. Your signature will be calculated automatically if signVersion
and secret
are set.
Example§
LocalDefaultRequest request = new LocalDefaultRequest();
request.setKey(PROJECT_KEY);
request.setUid(USER_ID);
request.setWidget(WIDGET_TYPE);
request.setApiType(API_TYPE);
request.setSecretKey(SECRET_KEY);
request.setSignVersion(3);
request.setMobileDownloadLink(YOUR_MOBILE_APP_DOWNLOAD_LINK);
Custom request§
If our defined request does not match your need. We also supported Map-like query. It follows the parameters in https://www.paymentwall.com/en/documentation/Digital-Goods-API/710. Most of the parameters are already defined in Const.P
class. Your signature will be calculated automatically if signVersion
and secret
are set.
Example§
CustomRequest request = new CustomRequest();
request.put(Const.P.KEY, PROJECT_KEY);
request.put(Const.P.WIDGET, "m2_1");
request.put(Const.P.EVALUATION, "1");
request.put(Const.P.UID, "testuser");
request.put(Const.P.AG_EXTERNAL_ID, "testitem");
request.put(Const.P.AG_NAME, "Test item");
request.put(Const.P.CURRENCYCODE, "USD");
request.put(Const.P.AMOUNT, "0.5");
request.put(Const.P.AG_TYPE, "fixed");
request.setMobileDownloadLink(YOUR_MOBILE_APP_DOWNLOAD_LINK);
request.setSecretKey(SECRET_KEY);
request.setSignVersion(3);
Widget signature§
Using Widget signature secures your widget and prevents unauthorized access.
Auto signing (unsecured)§
Normally, autoSigned
is turned off. You can turn it on by setting a secretKey
. Your widget call will be automatically signed.
request.setSignVersion(3);
request.setSecretKey("Your Secret Key");
By using this method, your secretKey
can be compromised against reverse-engineering. Please consider storing it in a secured place.
Manual signing§
Storing secretKey
on your own backend lower your risk of exposing it. Signing your request remotely is recommended to secure your project.
Please note that some parameters are added by default.
Use this method to get all required parameters for signing
/// default parameters
Map<String,String> defaultParameters = MessageUtils.getDefaultParameters();
Or
// do this after setting all parameters
Map<String,String> generatedParameters = MessageUtils.getDefaultParameters(request);
Sorting parameters alphabetically (ie: using a TreeMap
) before signing is required to work with PWLocal SDK.
Defined request§
request.setSignVersion(3);
request.setSign("Signature Value");
Custom request§
request.setSignVersion(3);
request.put(Const.P.SIGN,"Signature Value");
Please see Signature calculation for signing algorithm.
User Profile API§
PWLocal SDK supports User Profile API. Setting UserProfile
can be done by simply put it in a Defined Request as following
UserProfile userProfile = new UserProfile();
//Please set user email and registration date here
userProfile.setEmail(USER_EMAIL);
userProfile.setRegistrationDate(REGISTRATION_DATE);
request.setUserProfile(userProfile);
Or to a Custom request
UserProfile userProfile = new UserProfile();
//Please set user email and registration date here
userProfile.setEmail(USER_EMAIL);
userProfile.setRegistrationDate(REGISTRATION_DATE);
request.putAll(userProfile.toParameters());
Start PWLocal dialog§
Defined request§
Intent intent = new Intent(getApplicationContext(), PwLocalActivity.class);
//PaymentMethod.PW_LOCAL_DEFAULT or PaymentMethod.PW_LOCAL_FLEXIBLE
intent.putExtra(Key.PAYMENT_TYPE, PaymentMethod.PW_LOCAL_DEFAULT);
intent.putExtra(Key.PWLOCAL_REQUEST_MESSAGE, (Parcelable) request);
startActivityForResult(intent, PwLocalActivity.REQUEST_CODE);
Custom request§
Intent intent = new Intent(getApplicationContext(), PwLocalActivity.class);
intent.putExtra(Key.CUSTOM_REQUEST_TYPE, ApiType.DIGITAL_GOODS);
intent.putExtra(Key.CUSTOM_REQUEST_MAP, request);
startActivityForResult(intent, PwLocalActivity.REQUEST_CODE);
Handle result§
You can handle payment results by defining your callback function. We recommend syncing up with your server at this point to sync up user's balance, confirm purchased item etc. See the example:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode==PwLocalActivity.REQUEST_CODE) {
switch (resultCode) {
case ResponseCode.CANCEL:
break;
case ResponseCode.ERROR:
String errorMessage = data.getStringExtra(Key.SDK_ERROR_MESSAGE);
break;
case ResponseCode.SUCCESSFUL:
break;
default:
break;
}
}
}
resultCode
code can have one of the following values:
ResponseCode.SUCCESSFUL
: the user has completed the payment
ResponseCode.CANCEL
: the user has aborted the payment
ResponseCode.ERROR
: the payment cannot be done due to some error:
- Network error
- Invalid supplying request
If widget call request is set, the request is also returned via data
Defined request§
if (data != null && data.hasExtra(Key.PWLOCAL_REQUEST_MESSAGE)) {
LocalRequest request = data.getParcelableExtra(Key.PWLOCAL_REQUEST_MESSAGE);
}
Custom request§
if (data!=null && data.hasExtra(Key.CUSTOM_REQUEST_MAP)) {
CustomRequest parameters = data.getParcelableExtra(Key.CUSTOM_REQUEST_MAP);
}
Payment Status API utils§
Our SDK also supports Payment Status API.
Create PaymentStatusRequest§
Unsigned call
PaymentStatusRequest request = new PaymentStatusRequest.Builder().setQuery(
PROJECT_KEY, // your project key
USER_ID, // user id
AG_EXTERNAL_ID) // external id of the product
.build();
Signed call
PaymentStatusRequest request = new PaymentStatusRequest.Builder().setQuery(
PROJECT_KEY, // your project key
USER_ID, // user id
AG_EXTERNAL_ID // external id of the product
SECRET_KEY, // project secret key
3) // sign version
.build();
Unsigned call can be enabled by request. Please inform our bizdev. Please note that, enabling unsigned Payment Status API call can make your information less secured.
Get payment status§
PaymentStatusUtils.getPaymentStatus(request, new PaymentStatusCallback(){
@Override
public void onError(Exception e) {
// Handle error
}
@Override
public void onSuccess(List<PaymentStatus> result) {
// Handle the result
}
});
Payment Status in activityResult
§
Experimental feature
We also return PaymentStatus in activityResult
if your call meets 4 following requirements:
- It's a flexible widget call (custom or defined request)
- It has
agExternalId
,uid
andprojectKey
set - Payment Status extra is enable in request
Intent
intent.putExtra(Key.ENABLE_PAYMENT_STATUS, true);
- There is only 1 returned Payment Status
The returned Payment Status can be get from onActivityResult
callback
Bundle paymentStatusBundle = data.getBundleExtra(Key.RESULT_PAYMENT_STATUS);
if (paymentStatusBundle != null && paymentStatusBundle.containsKey(Key.PAYMENT_STATUS_IS_SUCCESSFUL)) {
boolean successful = paymentStatusBundle.getBoolean(Key.PAYMENT_STATUS_IS_SUCCESSFUL);
if (successful) {
PaymentStatus status = paymentStatusBundle.getParcelable(Key.PAYMENT_STATUS_MESSAGE);
} else {
Exception e = (Exception) paymentStatusBundle.getSerializable(Key.PAYMENT_STATUS_EXCEPTION);
}
Pingback handling§
After each successful payment we will notify your server about it. We recommend to use this feature as it is the most reliable way to know when the payment went through. Even if your application crashes for some reason, your server will still be notified, so you can sync up later. Please use pingback processing documentation for more information.
Appendix§
Proguard configuration§
If Proguard is used, please kindly add these lines to your proguard configuration file
-keep class com.paymentwall.sdk.pwlocal.** { *; }
-dontwarn com.paymentwall.sdk.pwlocal.**
Supported parameters§
Here's the list of supported parameters in defined requests
Common parameters§
Data type | Parameter |
String | key |
String | sign |
Integer | signVersion |
Long | timeStamp |
String | uid |
String | urlParameters |
String | secretKey |
String | |
Integer | evaluation |
String | firstname |
String | lang |
String | lastname |
String | locationAddress |
String | locationCity |
String | locationCountry |
String | locationState |
String | locationZip |
String | pingbackUrl |
String | paymentSystem |
String | sex |
String | successUrl |
String | widget |
String | birthday |
String | countryCode |
String | apiType |
Map<Integer, String> | externalIds |
Map<Integer, Float> | prices |
Map<Integer, String> | currencies |
LocalDefaultRequest§
Data type | Parameter |
String | defaultGoodsId |
Map<Integer, String> | displayGoods |
Map<Integer, String> | hideGoods |
LocalFlexibleRequest§
Data type | Parameter |
String | agExternalId |
String | agName |
Integer | agPeriodLength |
String | agPeriodType |
String | agPostTrialExternalId |
String | agPostTrialName |
Integer | agPostTrialPeriodLength |
String | agPostTrialPeriodType |
String | agPromo |
Integer | agRecurring |
Integer | agTrial |
String | agType |
String | currencycode |
Integer | hidePostTrialGood |
String | postTrialAmount |
String | postTrialCurrencycode |
Integer | showPostTrialNonRecurring |
Integer | showPostTrialRecurring |
Integer | showTrialNonRecurring |
Integer | showTrialRecurring |
Float | amount |
UserProfile§
Data type | Parameter |
String | |
Long | registrationDate |
Long | birthday |
String | sex |
String | username |
String | firstname |
String | lastname |
String | city |
String | state |
String | address |
String | country |
String | zip |
String | membership |
Long | membershipDate |
String | registrationCountry |
String | registrationIp |
String | registrationEmail |
Boolean | registrationEmailVerified |
String | registrationName |
String | registrationLastname |
String | registrationSource |
Integer | loginsNumber |
Integer | paymentsNumber |
Double | paymentsAmount |
Integer | followers |
Integer | messageSent |
Integer | messageSentLast24h |
Integer | messageReceived |
Integer | interactions |
Integer | interactionsLast24h |
Float | riskScore |
Integer | complaints |
Boolean | wasBanned |
Integer | deliveredProducts |
Integer | canceledPayments |
Float | rating |
Integer | registrationAge |
Boolean | enable3dSecure |
For more information, please see User Profile API