i am trying to Integration.Phonepe payment gateway for android app
public class PhonePePayActivity extends BaseActivity {
String TAG ="PhonePePayActivity";
private static int B2B_PG_REQUEST_CODE = 777;
#Override
protected int getLayoutId() {
return R.layout.activity_phone_pe_pay;
}
#Override
public void setView() {
super.setView();
}
String apiEndPoint = "/pg/v1/pay";
String SaltKey = "a6334ff7-da0e-4d51-a9ce-76b97d518b1e";
int KeyIndex = 1;
#RequiresApi(api = Build.VERSION_CODES.O)
#OnClick({R.id.pay_button})
public void onClick(View v) {
switch (v.getId()) {
case R.id.pay_button:
HashMap<String, Object> data = new HashMap();
data.put("merchantTransactionId",createTrnId()); //String. Mandatory
data.put("merchantId", "ON24MARTUAT"); //String. Mandatory
data.put("merchantUserId", "u123"); //String. Conditional
data.put("amount",100); //Long. Mandatory
data.put("mobileNumber","8510988965"); //String. Optional
data.put("callbackUrl","https://webhook.site/callback-url");
PaymentInstrumentPe mPaymentInstrument = new PaymentInstrumentPe();
mPaymentInstrument.setType("UPI_INTENT");
mPaymentInstrument.setTargetApp("com.phonepe.app");
data.put("paymentInstrument",mPaymentInstrument);
DeviceContextPe mDeviceContextPe = new DeviceContextPe();
mDeviceContextPe.setDeviceOS("ANDROID"); // ENUM. Mandatory
data.put("deviceContext", mDeviceContextPe); //OBJECT. Mandatory
String originalInput = new Gson().toJson(data);
String base64Body = Base64.getEncoder().encodeToString(originalInput.getBytes());
Log.e(TAG, "onClick: " + base64Body );
String checksum = sha256(base64Body + apiEndPoint + SaltKey) + "###"+ KeyIndex;
Log.e(TAG, "onClick: "+ checksum );
B2BPGRequest b2BPGRequest = new B2BPGRequestBuilder()
.setData(base64Body)
.setChecksum(checksum)
.setUrl(apiEndPoint)
.build();
try {
startActivityForResult(PhonePe.getImplicitIntent(
this, b2BPGRequest, "com.phonepe.app.preprod"),B2B_PG_REQUEST_CODE);
} catch(PhonePeInitException e){
Log.e(TAG, "onClick: error-" + e.toString() );
e.printStackTrace();
}
break;
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == B2B_PG_REQUEST_CODE) {
// Log.e(TAG, "onActivityResult: " +data.toString() );
/*This callback indicates only about completion of UI flow.
Inform your server to make the transaction
status call to get the status. Update your app with the
success/failure status.*/
}
}
private String createTrnId() {
Date date = new Date();
long createTransactionId = date.getTime();
return "on24m_"+ createTransactionId;
}
private static String sha256(String input) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(input.getBytes("UTF-8"));
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
i am not getting response and all details in it (getting response
something went wrong :404
). and Thanks,if you can help me with this.
i am following this doc.
PG SDK Details
Android PG SDK -
https://developer.phonepe.com/v1/docs/android-pg-sdk-integration
PAY API DetailsPAY API -
https://developer.phonepe.com/v1/reference/pay-api
Response AuthorizationCheck Status API -
https://developer.phonepe.com/v1/reference/check-status-api
Server to Server Response -
https://developer.phonepe.com/v1/reference/server-to-server-callback-4
Related
I need help with my project please. I don't really have a lot to say other than that I'm trying to add payment gateway to my android app using stripe. I followed the documentation here. Towards the end where I have to test everything my app crashes and I get this error message I am almost done with this but this is the only thing in my way. Please help me. Thanks in advance
//My code is here
private void startCheckout() {
// Create a PaymentIntent by calling the sample server's /create-payment-intent endpoint.
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
String json = "{"
+ "\"currency\":\"usd\","
+ "\"items\":["
+ "{\"id\":\"photo_subscription\"}"
+ "]"
+ "}";
RequestBody body = RequestBody.create(mediaType,json);
Request request = new Request.Builder()
.url(BACKEND_URL + "create-payment-intent")
.post(body)
.build();
httpClient.newCall(request)
.enqueue(new PayCallback(this));
// Hook up the pay button to the card widget and stripe instance
Button payButton = findViewById(R.id.payButton);
payButton.setOnClickListener((View view) -> {
CardInputWidget cardInputWidget = findViewById(R.id.cardInputWidget);
PaymentMethodCreateParams params = cardInputWidget.getPaymentMethodCreateParams();
if (params != null) {
ConfirmPaymentIntentParams confirmParams = ConfirmPaymentIntentParams
.createWithPaymentMethodCreateParams(params, paymentIntentClientSecret);
stripe.confirmPayment(this, confirmParams);
}
});
}
private void displayAlert(#NonNull String title,
#Nullable String message,
boolean restartDemo) {
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(message);
if (restartDemo) {
builder.setPositiveButton("Restart demo",
(DialogInterface dialog, int index) -> {
CardInputWidget cardInputWidget = findViewById(R.id.cardInputWidget);
cardInputWidget.clear();
startCheckout();
});
} else {
builder.setPositiveButton("Ok", null);
}
builder.create().show();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Handle the result of stripe.confirmPayment
stripe.onPaymentResult(requestCode, data, new PaymentResultCallback(this));
}
private void onPaymentSuccess(#NonNull final Response response) throws IOException {
Gson gson = new Gson();
Type type = new TypeToken<Map<String, String>>(){}.getType();
Map<String, String> responseMap = gson.fromJson(
Objects.requireNonNull(response.body()).string(),
type
);
// The response from the server includes the Stripe publishable key and
// PaymentIntent details.
// For added security, our sample app gets the publishable key from the server
String stripePublishableKey = responseMap.get("publishableKey");
paymentIntentClientSecret = responseMap.get("clientSecret");
// Configure the SDK with your Stripe publishable key so that it can make requests to the Stripe API
stripe = new Stripe(
getApplicationContext(),
Objects.requireNonNull(stripePublishableKey)
);
}
private static final class PayCallback implements Callback {
#NonNull private final WeakReference<PaymentPageActivity> activityRef;
PayCallback(#NonNull PaymentPageActivity activity) {
activityRef = new WeakReference<>(activity);
}
#Override
public void onFailure(Request request, IOException e) {
final PaymentPageActivity activity = activityRef.get();
if (activity == null) {
return;
}
activity.runOnUiThread(() ->
Toast.makeText(
activity, "Error: " + e.toString(), Toast.LENGTH_LONG
).show()
);
}
#Override
public void onResponse(Response response) throws IOException {
final PaymentPageActivity activity = activityRef.get();
if (activity == null) {
return;
}
if (!response.isSuccessful()) {
activity.runOnUiThread(() ->
Toast.makeText(
activity, "Error: " + response.toString(), Toast.LENGTH_LONG
).show()
);
} else {
activity.onPaymentSuccess(response);
}
}
}
private static final class PaymentResultCallback
implements ApiResultCallback<PaymentIntentResult> {
#NonNull private final WeakReference<PaymentPageActivity> activityRef;
PaymentResultCallback(#NonNull PaymentPageActivity activity) {
activityRef = new WeakReference<>(activity);
}
#Override
public void onSuccess(#NonNull PaymentIntentResult result) {
final PaymentPageActivity activity = activityRef.get();
if (activity == null) {
return;
}
PaymentIntent paymentIntent = result.getIntent();
PaymentIntent.Status status = paymentIntent.getStatus();
if (status == PaymentIntent.Status.Succeeded) {
// Payment completed successfully
Gson gson = new GsonBuilder().setPrettyPrinting().create();
activity.displayAlert(
"Payment completed",
gson.toJson(paymentIntent),
true
);
} else if (status == PaymentIntent.Status.RequiresPaymentMethod) {
// Payment failed – allow retrying using a different payment method
activity.displayAlert(
"Payment failed",
Objects.requireNonNull(paymentIntent.getLastPaymentError()).getMessage(),
false
);
}
}
#Override
public void onError(#NonNull Exception e) {
final PaymentPageActivity activity = activityRef.get();
if (activity == null) {
return;
}
// Payment request failed – allow retrying using the same payment method
activity.displayAlert("Error", e.toString(), false);
}
}
int this line
Map<String, String> responseMap = gson.fromJson(
Objects.requireNonNull(response.body()).string(),
type
);
you shold pass a json Object not a String, use GSON to fix it
something like that :
Gson g = new Gson();
Foo f = g.fromJson(jsonString, bar.class)
I am trying to implement multiple concurrent file uploads using IntentService for which I am using ThreadExecutor. I am iterating through a map and one-by-one and I am fetching the information and instantiating a workerthread. Inside the loop I have executor which is executing those threads. Below is my code.
#Override
protected void onHandleIntent(Intent intent) {
Debug.print("Called handleIntent");
mFileMap = (HashMap<String, Integer>) intent.getSerializableExtra("pdf_info");
mMapSize = mFileMap.size();
Log.e("pdf", mFileMap.toString());
mExecutor = Executors.newFixedThreadPool(2);
mTotalFileSize = getTotalFileSize();
Log.e("total_file_size", mTotalFileSize + "");
ArrayList<UploadWorker> uploadWorkerArrayList = new ArrayList<>();
Iterator it = mFileMap.entrySet().iterator();
for(Map.Entry<String, Integer> entry : mFileMap.entrySet())
{
String filePath = (String) entry.getKey();
Log.e("map_path: ", filePath);
int categoryId = (int) entry.getValue();
Log.e("map_no: ", categoryId + "");
// uploadWorkerArrayList.add(new UploadWorker(filePath, categoryId));
UploadWorker worker = new UploadWorker(filePath, categoryId);
mExecutor.submit(worker);
}
mExecutor.shutdown();
Log.e("workerlist: ", uploadWorkerArrayList.toString());
}
Below is my UploadWorker code.
class UploadWorker implements Runnable {
String filePath;
int categoryId;
public UploadWorker(String filePath, int categoryId) {
this.filePath = filePath;
this.categoryId = categoryId;
}
#Override
public synchronized void run() {
mFile = new File(filePath);
Log.e("uploadworker", filePath);
mParams = new LinkedHashMap<>();
mParams.put("file_type", 2 + "");
mParams.put("file_name", mFile.getName());
mParams.put("category_id", categoryId + "");
notificationId++;
mNotificationMap.put(filePath, notificationId);
createNotification(notificationId, mFile.getName());
int response = uploadPDF(filePath);
if (response == 1) {
JSONObject jObject = null;
String status = null;
try {
jObject = new JSONObject(mServerResponse);
status = jObject.getString("status");
int id = mNotificationMap.get(filePath);
updateNotification(100, id);
} catch (JSONException e) {
e.printStackTrace();
}
Log.e("<><>", status);
} else {
Log.e("<><>", "Upload fail");
}
}
}
However it happens that if say my maplist has 2 entries, then the iterator is first fetching both the entries and the executor is uploading only the final entry, that too twice. Please help.
I am implementing Inapp billing for the products in my app for that i refered dungeons example and implementing from that!! But now i am not about to display checkout dialog box in my application and i even not getting any error in logcat..The application showing result as ERROR in a dialog box with NO CONNECTION MESSAGE IN IT
I am tracing the problem using logs.The code that i am using to display checkout dialog box is
In My Main Class::::::::::
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent j = getIntent();
int position = j.getExtras().getInt("BId");
System.err.println("Bid="+position);
Log.i("J","gf");
mHandler = new Handler();
mBooksPurchaseObserver = new BooksPurchaseObserver(mHandler);
mBillingService = new BillingService();
mBillingService.setContext(this);
mItemName = getString(CATALOG[position].nameId);
mSku = CATALOG[position].sku;
System.err.println("mSku_______="+mSku);
System.err.println("mItemName____="+mItemName);
System.err.println("Consts.DEBUG=="+Consts.DEBUG);
ResponseHandler.register(mBooksPurchaseObserver);
if (mBillingService.checkBillingSupported()) {
Log.i("ds","bsc_checkconnection");
}
if (Consts.DEBUG!=true) {
Log.d(TAG, "buying: " + mItemName + " sku: " + mSku);
Log.i("x","x");
}
mPurchaseDatabase = new PurchaseDatabase(this);
if(!mBillingService.requestPurchase(mItemName, mSku)){
Log.e("this is exp","request purchase______________");
showDialog(DIALOG_BILLING_NOT_SUPPORTED_ID);
}
setupWidgets();
Log.i("ga","Request purchaseeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee");
// Check if billing is supported.
Log.i("ga","Request purchaseeeeeeeeeee");
}
In Billing Service Class::::
class RequestPurchase extends BillingRequest {
public final String mProductId;
public final String mDeveloperPayload;
public RequestPurchase(String itemId) {
this(itemId, null);
Log.i("ga","Request purchase");
}
public RequestPurchase(String itemId, String developerPayload) {
// This object is never created as a side effect of starting this
// service so we pass -1 as the startId to indicate that we should
// not stop this service after executing this request.
super(-1);
System.err.println("itemId="+itemId);
Log.i("fads","request only");
mProductId = itemId;
mDeveloperPayload = developerPayload;
}
#Override
protected long run() throws RemoteException {
Log.i("gaaaaaaaaa","Request purchase");
Bundle request = makeRequestBundle("REQUEST_PURCHASE");
request.putString(Consts.BILLING_REQUEST_ITEM_ID, mProductId);
// Note that the developer payload is optional.
if (mDeveloperPayload != null) {
request.putString(Consts.BILLING_REQUEST_DEVELOPER_PAYLOAD, mDeveloperPayload);
}
System.err.println("mService===="+mService);
Bundle response = mService.sendBillingRequest(request);
System.err.println("response__"+response);
System.err.println("response__!!!!!!!!!!!!"+Consts.BILLING_RESPONSE_PURCHASE_INTENT);
PendingIntent pendingIntent
= response.getParcelable(Consts.BILLING_RESPONSE_PURCHASE_INTENT);
System.err.println("Pending Intent==="+pendingIntent);
Log.i("12","12");
if (pendingIntent == null) {
Log.e(TAG, "Error with requestPurchase");
return Consts.BILLING_RESPONSE_INVALID_REQUEST_ID;
}
Log.i("2","2");
Intent intent = new Intent();
Log.i("222222","11111");
System.err.println("Intent is equals to__"+intent);
System.err.println("pendingIntent is equals to__"+pendingIntent);
// System.err.printf("fsd",ResponseHandler.buyPageIntentResponse(pendingIntent, intent));
ResponseHandler.buyPageIntentResponse(pendingIntent, intent);
Log.i("f","fdas");
return response.getLong(Consts.BILLING_RESPONSE_REQUEST_ID,
Consts.BILLING_RESPONSE_INVALID_REQUEST_ID);
}
#Override
protected void responseCodeReceived(ResponseCode responseCode) {
Log.i("response code","response code");
ResponseHandler.responseCodeReceived(BillingService.this, this, responseCode);
}
}
My CheckbillingSupporting class
class CheckBillingSupported extends BillingRequest {
public CheckBillingSupported() {
// This object is never created as a side effect of starting this
// service so we pass -1 as the startId to indicate that we should
// not stop this service after executing this request.
super(-1);
}
#Override
protected long run() throws RemoteException {
Bundle request = makeRequestBundle("CHECK_BILLING_SUPPORTED");
Bundle response = mService.sendBillingRequest(request);
System.err.println("response code____"+Consts.BILLING_RESPONSE_RESPONSE_CODE);
int responseCode = response.containsKey(Consts.BILLING_RESPONSE_RESPONSE_CODE)
? response.getInt(Consts.BILLING_RESPONSE_RESPONSE_CODE)
: ResponseCode.RESULT_BILLING_UNAVAILABLE.ordinal();
if (Consts.DEBUG) {
Log.i(TAG, "CheckBillingSupported response code: " +
ResponseCode.valueOf(responseCode));
}
boolean billingSupported = (responseCode == ResponseCode.RESULT_OK.ordinal());
ResponseHandler.checkBillingSupportedResponse(billingSupported);
return Consts.BILLING_RESPONSE_INVALID_REQUEST_ID;
}
}
Could any one tell me were i went wrong?
I implemented Google cloud printing in my project but when i attach text file in Google cloud then it show that 1 page to print but not show its content.
So how do I show the content of text file when file attach to google cloud and how to get existing google account from the user phone and how to make setting of google chrome to print from my code so that user easily print the doc from my app.so please provide me the code or some good tutorial to deal with google cloud in my requirement way.
Intent printIntent = new Intent(ExportActivity.this, PrintDialogActivity.class);
printIntent.setDataAndType(Uri.fromFile(file), "text/*");
printIntent.putExtra("title", "Dictionary");
public class PrintDialogActivity extends Activity {
private static final String PRINT_DIALOG_URL = "https://www.google.com/cloudprint/dialog.html";
private static final String JS_INTERFACE = "AndroidPrintDialog";
private static final String CONTENT_TRANSFER_ENCODING = "base64";
private static final String ZXING_URL = "http://zxing.appspot.com";
private static final int ZXING_SCAN_REQUEST = 65743;
/**
* Post message that is sent by Print Dialog web page when the printing dialog needs to be closed.
*/
private static final String CLOSE_POST_MESSAGE_NAME = "cp-dialog-on-close";
/**
* Web view element to show the printing dialog in.
*/
private WebView dialogWebView;
/**
* Intent that started the action.
*/
Intent cloudPrintIntent;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.print_dialog);
dialogWebView = (WebView) findViewById(R.id.webview);
cloudPrintIntent = this.getIntent();
WebSettings settings = dialogWebView.getSettings();
settings.setJavaScriptEnabled(true);
dialogWebView.setWebViewClient(new PrintDialogWebClient());
dialogWebView.addJavascriptInterface(new PrintDialogJavaScriptInterface(), JS_INTERFACE);
dialogWebView.loadUrl(PRINT_DIALOG_URL);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == ZXING_SCAN_REQUEST && resultCode == RESULT_OK) {
dialogWebView.loadUrl(intent.getStringExtra("SCAN_RESULT"));
}
}
final class PrintDialogJavaScriptInterface {
public String getType() {
return cloudPrintIntent.getType();
}
public String getTitle() {
return cloudPrintIntent.getExtras().getString("title");
}
public String getContent() {
try {
ContentResolver contentResolver = getContentResolver();
InputStream is = contentResolver.openInputStream(cloudPrintIntent.getData());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int n = is.read(buffer);
while (n >= 0) {
baos.write(buffer, 0, n);
n = is.read(buffer);
}
is.close();
baos.flush();
return Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
public String getEncoding() {
return CONTENT_TRANSFER_ENCODING;
}
public void onPostMessage(String message) {
if (message.startsWith(CLOSE_POST_MESSAGE_NAME)) {
finish();
}
}
}
private final class PrintDialogWebClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(ZXING_URL)) {
Intent intentScan = new Intent("com.google.zxing.client.android.SCAN");
intentScan.putExtra("SCAN_MODE", "QR_CODE_MODE");
try {
startActivityForResult(intentScan, ZXING_SCAN_REQUEST);
} catch (ActivityNotFoundException error) {
view.loadUrl(url);
}
} else {
view.loadUrl(url);
}
return false;
}
#Override
public void onPageFinished(WebView view, String url) {
if (PRINT_DIALOG_URL.equals(url)) {
// Submit print document.
view.loadUrl("javascript:printDialog.setPrintDocument(printDialog.createPrintDocument(" + "window." + JS_INTERFACE + ".getType(),window." + JS_INTERFACE + ".getTitle()," + "window." + JS_INTERFACE + ".getContent(),window." + JS_INTERFACE + ".getEncoding()))");
// Add post messages listener.
view.loadUrl("javascript:window.addEventListener('message'," + "function(evt){window." + JS_INTERFACE + ".onPostMessage(evt.data)}, false)");
}
}
}
}
I am adding a in app purchase in my coding, it's working well while purchase but gives error and application closes when I try to add Restore_Transaction code when application is removed and installed again, I have added below coding
in onCreate i wrote
startService(new Intent(mContext, BillingService.class));
BillingHelper.setCompletedHandler(mTransactionHandler);
if (BillingHelper.isBillingSupported()) {
BillingHelper.restoreTransactionInformation(BillingSecurity
.generateNonce());
}
and then i called handler using
public Handler mTransactionHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (BillingHelper.latestPurchase.isPurchased()) {
showItem();
}
};
};
private void showItem() {
purchased = Purchased.getPurchaseInfo(getApplicationContext());
if (purchased == null) {
Date d = new Date();
Toast.makeText(getApplicationContext(), "--- Upgrated ---",
Toast.LENGTH_LONG).show();
purchased = new Purchased(getApplicationContext());
purchased.isPurchased = 1;
purchased.purchasedDate = d.getTime();
purchased.save();
Intent intent = new Intent(ActorGenieActivity.this,
SplashScreen.class);
startActivity(intent);
}
}
I found the answer to my question, thanx to anddev
You have to check for purchases not to be null
public static void verifyPurchase(String signedData, String signature) {
ArrayList<VerifiedPurchase> purchases = BillingSecurity.verifyPurchase(
signedData, signature);
if (purchases != null && !purchases.isEmpty()) {
latestPurchase = purchases.get(0);
confirmTransaction(new String[] { latestPurchase.notificationId });
if (mCompletedHandler != null) {
mCompletedHandler.sendEmptyMessage(0);
} else {
Log
.e(
TAG,
"verifyPurchase error. Handler not instantiated. Have you called setCompletedHandler()?");
}
}
}
and in Confirm_Notification u hav to check for
if (notifyIds[0] != null)
Follow this:
confirmTransaction(new String[] { latestPurchase.notificationId });
here and do this:
protected static void confirmTransaction(String[] notifyIds) {
if (amIDead()) {
return;
}
// there isn't a notifyid then this was the restore transaction call and this should be skipped
if (notifyIds[0] != null){
Log.i(TAG, "confirmTransaction()");
Bundle request = makeRequestBundle("CONFIRM_NOTIFICATIONS");
......
......
}
Works like a charm form me.. Thanks Guys...
You can use the below code to get purchase history:
public static ArrayList<VerifiedPurchase> verifyPurchase(String signedData,
String signature) {
if (signedData == null) {
//Log.e(TAG, "data is null");
return null;
}
if (Constans.DEBUG) {
//Log.i(TAG, "signedData: " + signedData);
}
boolean verified = false;
if (!TextUtils.isEmpty(signature)) {
/**
* Compute your public key (that you got from the Android Market
* publisher site).
*
* Instead of just storing the entire literal string here embedded
* in the program, construct the key at runtime from pieces or use
* bit manipulation (for example, XOR with some other string) to
* hide the actual key. The key itself is not secret information,
* but we don't want to make it easy for an adversary to replace the
* public key with one of their own and then fake messages from the
* server.
*
* Generally, encryption keys / passwords should only be kept in
* memory long enough to perform the operation they need to perform.
*/
String base64EncodedPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKgldGQPL/xV9WKLmY62UVgEm7gsPI/T/nQxRKpYN17m8Sq3gO9nWD17wXew4oNaHmMAmArS7s7eFi3Z+XiyWil1iZvEOdBOdZD502BzujPoBa4Fu9eITPBO9tzBEdvNLXf8amnsRj53TA4bcxB2O6OcXrQIv3t3n5Dg5Nn+rJpoKSNUv7NEzJagG/2NhyjIysAObbvQ5SBQ5NgRtZlvhsTeQJPMLhRAoRcTK/+47VkhrxM3PppeGjoNRryn6d+RhMjs/nydvoQtP2V76UcUu4m+daDnK3PxOnwLt50hNtQhNf3VgixVrSKfHUWp240uEz9MHstjj8BWPH9BFF/TewIDAQAB";
PublicKey key = Security.generatePublicKey(base64EncodedPublicKey);
verified = Security.verify(key, signedData, signature);
if (!verified) {
//Log.w(TAG, "signature does not match data.");
return null;
}
}
JSONObject jObject;
JSONArray jTransactionsArray = null;
int numTransactions = 0;
long nonce = 0L;
try {
jObject = new JSONObject(signedData);
// The nonce might be null if the user backed out of the buy page.
nonce = jObject.optLong("nonce");
jTransactionsArray = jObject.optJSONArray("orders");
if (jTransactionsArray != null) {
numTransactions = jTransactionsArray.length();
}
} catch (JSONException e) {
return null;
}
if (!Security.isNonceKnown(nonce)) {
//Log.w(TAG, "Nonce not found: " + nonce);
return null;
}
ArrayList<VerifiedPurchase> purchases = new ArrayList<VerifiedPurchase>();
try {
for (int i = 0; i < numTransactions; i++) {
JSONObject jElement = jTransactionsArray.getJSONObject(i);
int response = jElement.getInt("purchaseState");
PurchaseState purchaseState = PurchaseState.valueOf(response);
String productId = jElement.getString("productId");
String packageName = jElement.getString("packageName");
long purchaseTime = jElement.getLong("purchaseTime");
String orderId = jElement.optString("orderId", "");
String notifyId = null;
if (jElement.has("notificationId")) {
notifyId = jElement.getString("notificationId");
}
String developerPayload = jElement.optString(
"developerPayload", null);
// If the purchase state is PURCHASED, then we require a
// verified nonce.
if (purchaseState == PurchaseState.PURCHASED && !verified) {
continue;
}
purchases.add(new VerifiedPurchase(purchaseState, notifyId,
productId, orderId, purchaseTime, developerPayload));
}
} catch (JSONException e) {
//Log.e(TAG, "JSON exception: ", e);
return null;
}
removeNonce(nonce);
return purchases;
}
You can call this method from the below method in BillingService class:
private void purchaseStateChanged(int startId, String signedData,
String signature) {
ArrayList<Security.VerifiedPurchase> purchases;
purchases = Security.verifyPurchase(signedData, signature);
if (purchases == null) {
return;
}
ArrayList<String> notifyList = new ArrayList<String>();
for (VerifiedPurchase vp : purchases) {
if (vp.notificationId != null) {
notifyList.add(vp.notificationId);
}
ResponseHandler.purchaseResponse(this, vp.purchaseState,
vp.productId, vp.orderId, vp.purchaseTime,
vp.developerPayload);
}
if (!notifyList.isEmpty()) {
String[] notifyIds = notifyList.toArray(new String[notifyList
.size()]);
confirmNotifications(startId, notifyIds);
}
}