/*
* Copyright 2010-2011 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package blackberry.payment;
import java.util.Vector;
import org.w3c.dom.Document;
import net.rim.device.api.browser.field2.BrowserField;
import net.rim.device.api.script.ScriptEngine;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.util.SimpleSortingVector;
import net.rim.device.api.web.WidgetConfig;
import net.rim.device.api.web.WidgetException;
import blackberry.common.util.JSUtilities;
import blackberry.common.util.json4j.JSONArray;
import blackberry.common.util.json4j.JSONObject;
import blackberry.core.IJSExtension;
import blackberry.core.JSExtensionRequest;
import blackberry.core.JSExtensionResponse;
import blackberry.core.JSExtensionReturnValue;
import net.rimlib.blackberry.api.payment.*;
/**
* JavaScript extension for blackberry.payment
*/
public class PaymentExtension implements IJSExtension {
private static Vector SUPPORTED_METHODS;
public static final String FUNCTION_PURCHASE = "purchase";
public static final String FUNCTION_GETEXISTINGPURCHASES = "getExistingPurchases";
public static final String FUNCTION_GETMODE = "getDevelopmentMode";
public static final String FUNCTION_SETMODE = "setDevelopmentMode";
public static boolean developmentMode = true;
private static final String KEY_DG_ID = "digitalGoodID";
private static final String KEY_DG_SKU = "digitalGoodSKU";
private static final String KEY_DG_NAME = "digitalGoodName";
private static final String KEY_METADATA = "metaData";
private static final String KEY_APP_NAME = "purchaseAppName";
private static final String KEY_APP_ICON = "purchaseAppIcon";
private static final String KEY_REFRESH = "allowRefresh";
private static final int CODE_USER_CANCEL = 1;
private static final int CODE_SYS_BUSY = 2;
private static final int CODE_SYS_ERROR = 3;
private static final int CODE_NOT_FOUND = 4;
private static final int CODE_ILLEGAL_APP = 5;
static {
SUPPORTED_METHODS = new Vector();
SUPPORTED_METHODS.addElement( FUNCTION_PURCHASE );
SUPPORTED_METHODS.addElement( FUNCTION_GETEXISTINGPURCHASES );
SUPPORTED_METHODS.addElement( FUNCTION_GETMODE );
SUPPORTED_METHODS.addElement( FUNCTION_SETMODE );
}
private static String[] JS_FILES = { "payment_dispatcher.js", "payment_ns.js" };
public String[] getFeatureList() {
return new String[] { "blackberry.payment" };
}
/**
* Implements invoke() of interface IJSExtension. Methods of extension will be called here.
*
* @throws WidgetException
* if specified method cannot be recognized
*/
public void invoke( JSExtensionRequest request, JSExtensionResponse response ) throws WidgetException {
String method = request.getMethodName();
Object[] args = request.getArgs();
String msg = "";
int code = JSExtensionReturnValue.SUCCESS;
JSONObject data = new JSONObject();
JSONArray dataArray = new JSONArray();
JSONObject returnValue = null;
PaymentEngine engine = PaymentSystem.getInstance();
if( engine == null ) {
throw new IllegalArgumentException(
"Sorry, in-app purchases are unavailable. Make sure BlackBerry App World v2.1 or higher is installed on your device." );
}
if( !SUPPORTED_METHODS.contains( method ) ) {
throw new WidgetException( "Undefined method: " + method );
}
try {
if( method.equals( FUNCTION_PURCHASE ) ) {
String digitalGoodID = (String) request.getArgumentByName( KEY_DG_ID );
String digitalGoodSKU = (String) request.getArgumentByName( KEY_DG_SKU );
String digitalGoodName = (String) request.getArgumentByName( KEY_DG_NAME );
String metaData = (String) request.getArgumentByName( KEY_METADATA );
String purchaseAppName = (String) request.getArgumentByName( KEY_APP_NAME );
String purchaseAppIcon = (String) request.getArgumentByName( KEY_APP_ICON );
PurchaseArgumentsBuilder arguments = new PurchaseArgumentsBuilder().withDigitalGoodId( digitalGoodID )
.withDigitalGoodName( digitalGoodName ).withDigitalGoodSku( digitalGoodSKU ).withMetadata( metaData )
.withPurchasingAppName( purchaseAppName )
.withPurchasingAppIcon( ( purchaseAppIcon != null ? Bitmap.getBitmapResource( purchaseAppIcon ) : null ) );
// Blocking call: engine.purchase() invokes AppWorld screen.
Purchase successfulPurchase = engine.purchase( arguments.build() );
String purchaseJSON = purchaseToJSONString( successfulPurchase );
data = new JSONObject( purchaseJSON );
code = JSExtensionReturnValue.SUCCESS;
msg = "Purchase Successful";
} else if( method.equals( FUNCTION_GETEXISTINGPURCHASES ) ) {
String refresh = (String) request.getArgumentByName( KEY_REFRESH );
// Blocking call: engine.getExistingPurchases() invokes AppWorld screen.
Purchase[] purchases = engine.getExistingPurchases( parseBoolean( refresh ) );
if( purchases.length != 0 ) {
for( int i = 0; i < purchases.length; i++ ) {
String purchaseJSON = "";
purchaseJSON += purchaseToJSONString( purchases[ i ] );
JSONObject temp = new JSONObject( purchaseJSON );
dataArray.add( temp );
}
}
} else if( method.equals( new String( FUNCTION_GETMODE ) ) ) {
data.put( "developmentMode", PaymentSystem.getMode() );
code = JSExtensionReturnValue.SUCCESS;
msg = "developmentMode set to: " + PaymentSystem.getMode();
} else if( method.equals( new String( FUNCTION_SETMODE ) ) ) {
String s = (String) request.getArgumentByName( "developmentMode" );
if( s.equals( "true" ) ) {
PaymentSystem.setMode( true );
} else {
PaymentSystem.setMode( false );
}
code = JSExtensionReturnValue.SUCCESS;
msg = "developmentMode set to: " + s;
}
} catch( UserCancelException e ) {
code = CODE_USER_CANCEL;
msg = e.getMessage();
} catch( DigitalGoodNotFoundException e ) {
code = CODE_NOT_FOUND;
msg = e.getMessage();
} catch( PaymentServerException e ) {
code = CODE_SYS_ERROR;
msg = e.getMessage();
} catch( IllegalApplicationException e ) {
code = CODE_ILLEGAL_APP;
msg = e.getMessage();
} catch( PaymentException e ) {
code = CODE_SYS_ERROR;
msg = e.getMessage();
} catch( Exception e ) {
code = JSExtensionReturnValue.FAIL;
msg = e.getMessage();
}
if( method.equals( FUNCTION_GETEXISTINGPURCHASES ) ) {
returnValue = new JSExtensionReturnValue( msg, code, dataArray ).getReturnValue();
} else {
returnValue = new JSExtensionReturnValue( msg, code, data ).getReturnValue();
}
response.setPostData( returnValue.toString().getBytes() );
}
private static boolean parseBoolean( String str ) {
return ( str != null && str.equals( Boolean.TRUE.toString() ) );
}
public String purchaseToJSONString( Purchase obj ) {
StringBuffer buffer = new StringBuffer();
buffer.append( "{" );
buffer.append( "\"digitalGoodID\":\"" + obj.getDigitalGoodId() + "\"," );
buffer.append( "\"digitalGoodSKU\":\"" + obj.getDigitalGoodSku() + "\"," );
buffer.append( "\"date\":\"" + Long.toString( obj.getDate().getTime() ) + "\"," );
buffer.append( "\"licenseKey\":\"" + obj.getLicenseKey() + "\"," );
buffer.append( "\"metaData\":\"" + obj.getMetadata() + "\"," );
buffer.append( "\"transactionID\":\"" + obj.getTransactionId() + "\"," );
buffer.append( "}" );
return buffer.toString();
}
public void loadFeature( String feature, String version, Document document, ScriptEngine scriptEngine,
SimpleSortingVector jsInjectionPaths ) {
JSUtilities.loadJS( scriptEngine, JS_FILES, jsInjectionPaths );
}
public void register( WidgetConfig widgetConfig, BrowserField browserField ) {
}
public void unloadFeatures() {
}
}