I have implemented Razor Pay payment gateway in my Android application. Everything is working fine for debit/credit card.
I am facing problem with UPI payment. Actually for UPI payment user has to visit UPI app to make the payment. Everything is working for UPI as well but the only problem is callback methods are not invoked if payment is successful or not until and unless I visit the app again.
This is big problem for me because sometime if user pay via UPI app and does not open the app again, it's been difficult for me to save the entries in the database for the payment.
I am saving entries in the database every time success callback method is invoked. How do I call success method when app is in background but not closed.
Here is the code snippet:
To open the payment activity:
Intent intent = new Intent(context, PaymentActivity.class);
intent.putExtra("orderId", order_id);
intent.putExtra("totalAmount", String.valueOf(totalPrice));
intent.putExtra("email", email);
intent.putExtra("phoneNo", phone_number);
intent.putExtra("userId", user_id);
startActivityForResult(intent, 2);
overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out);
To call the Razor pay Activity:
final Activity activity = this;
price = Double.parseDouble(total_price);
double paisa_double = price * 100;
int paisa_int = (int) paisa_double;
final Checkout checkout = new Checkout();
checkout.setKeyID(getResources().getString(R.string.razor_pay_key));
try {
JSONObject options = new JSONObject();
options.put("name", "Razorpay Corp");
options.put("description", "Order No: " + order_id);
options.put("order_id", razor_id);
//You can omit the image option to fetch the image from dashboard
options.put("image", "https://s3.amazonaws.com/rzp-mobile/images/rzp.png");
options.put("currency", "INR");
options.put("amount", String.valueOf(paisa_int));
//options.put("amount", "100");
JSONObject preFill = new JSONObject();
preFill.put("email", email);
preFill.put("contact", phone_no);
options.put("prefill", preFill);
JSONObject notes = new JSONObject();
notes.put("notes", order_id);
options.put("notes", notes);
checkout.open(activity, options);
} catch (Exception e) {
Toast.makeText(activity, "Error in payment: " + e.getMessage(), Toast.LENGTH_SHORT)
.show();
e.printStackTrace();
}
And these are the callback methods:
#Override
public void onPaymentSuccess(String razorpayPaymentID, PaymentData paymentData) {
try {
//Toast.makeText(this, "Payment Successful: " + razorpayPaymentID, Toast.LENGTH_SHORT).show();
Intent intent = new Intent();
intent.putExtra("razorpayPaymentID", razorpayPaymentID);
setResult(2, intent);
finish();
} catch (Exception e) {
Log.e(TAG, "Exception in onPaymentSuccess", e);
}
}
#Override
public void onPaymentError(int code, String response, PaymentData paymentData) {
try {
Toast.makeText(this, "Payment failed: " + code + " " + response, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e(TAG, "Exception in onPaymentError", e);
}
}
Use Razor pay web hooks in the back end code for the above problem.
Link:
https://razorpay.com/docs/webhooks/
Related
I've searched a lot on the Internet trying to find an answer for my needs, but in vain.
Here's my problem: I'm making an app that "counts time". The user press "Start" button and then go away for pretty much a long time of work on the field (2h,even more).
Then he has to come back and press the "End" button to show he have finished his job. My app then computes how long has he worked ( and some other thing I wont explain here ), and the user send the total of his work hours by mails to his superior.
Problem is :
-First my app is closed when the phone is locked and so the Start time is lost and calculations are off.
-Second : the user has to repeat the Start-End cycle many times a day, so i have a way of computing the total work hours, but again it's lost when the app is closed
So I'm opened to any idea/suggestions to solve my issues :)
Oh and I have Huawei P8 Lite for info, if that matters in anyway
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext=MainActivity.this;
mTimeListenerD.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { //Button to set the Start time
setDebutTime();
checkEnabled();
writeToFile(sName,sTempsTravail);
}
});
mTimeListenerF.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { //Button to set the End Time
setFinTime();
checkEnabled();
getHeureSupp(mTimeD, mTimeF);
FindSmallest(TimeRegister);
Clock();
writeToFile(sName,sTempsTravail);
readFromFile();
try {
copyFile(src,dst);
} catch (IOException e) {
e.printStackTrace();
}
Reinit();
}
});
mMail.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendMail();
}
}); //Send data by mail
readFromFile();
getName();
checkEnabled();
}
public Calendar setDebutTime() { // Set the Start Time
mTimeD = Calendar.getInstance();
mTimeD.getTime();
//Toast.makeText(this, mTimeD.getTime().toString(), Toast.LENGTH_SHORT).show();
sDebut = mTimeD.get(Calendar.DAY_OF_MONTH) + "/" + mTimeD.get(Calendar.MONTH) + "/" + mTimeD.get(Calendar.YEAR) + "--" + mTimeD.get(Calendar.HOUR_OF_DAY) + ":" + mTimeD.get(Calendar.MINUTE) + ":" + mTimeD.get(Calendar.SECOND);
mGetTimeDebut.setText("" + sDebut);
start=true;
notif=false;
String pathToMyAttachedFile = "/Android/data/com.example.benjii.saphir_astreinte/files/Documents/SAPHIRAgent.csv"; //A changer
File root = Environment.getExternalStorageDirectory();
File file = new File(root, pathToMyAttachedFile);
boolean deleted =file.delete();
if(!deleted){file.delete();}
return mTimeD;
}
public Calendar setFinTime() { // set the End Time
mTimeF = Calendar.getInstance();
mTimeF.getTime();
// Toast.makeText(this, mTimeF.getTime().toString(), Toast.LENGTH_SHORT).show();
sFin = mTimeF.get(Calendar.DAY_OF_MONTH) + "/" + mTimeF.get(Calendar.MONTH) + "/" + mTimeF.get(Calendar.YEAR) + "--" + mTimeF.get(Calendar.HOUR_OF_DAY) + ":" + mTimeF.get(Calendar.MINUTE) + ":" + mTimeF.get(Calendar.SECOND);
mGetTimeFin.setText("" + sFin);
start=false;
notif=true;
return mTimeF;
}
Then I have some function to do the calculations I need with the worked hours.
Once it is done I write it into a file on Internal Storage but then copy it to external storage:
public void writeToFile(String Name,String TempsTravail){ //File that'll be send by mail
try{
OutputStreamWriter StrW= new OutputStreamWriter(this.openFileOutput("SAPHIRAgent.csv", Context.MODE_PRIVATE));
src=mContext.getFilesDir().getAbsolutePath()+"/file.csv";
dst=mContext.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath()+"/file.csv";
//Toast.makeText(this,dst,Toast.LENGTH_LONG).show();
StrW.append(Name);
StrW.append(separator);
StrW.append(sDebut);
StrW.append(separator);
StrW.append(sFin);
StrW.append(separator);
StrW.append(TempsTravail);
StrW.append("\n"+mTempsTravail);
if(cool){
StrW.append(separator);
StrW.append(sCool);
}
if(warning){
StrW.append(separator);
StrW.append(sWarning);
}
if(critical){
StrW.append(separator);
StrW.append(sCritical);
}
StrW.flush();
StrW.close();
}
catch (IOException e){
Log.e("ExceptionFile","Failed to write "+e.toString());
}
}
Then I send the file by mail:
public void sendMail(){ //SendMail function
Intent emailIntent = new Intent(Intent.ACTION_SEND);
final String[] to={"xxx#gmail.com"};
final String subj="Sortie Agent "+sName;
final String body="Voir pièce jointe";
emailIntent.setType("text/plain");
emailIntent.putExtra(Intent.EXTRA_EMAIL, to);
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subj);
emailIntent.putExtra(Intent.EXTRA_TEXT, body);
File root = Environment.getExternalStorageDirectory();
String pathToMyAttachedFile = "/Android/data/com.example.myapp/files/Documents/file.csv";
File file = new File(root, pathToMyAttachedFile);
//Toast.makeText(this,"RootPath "+root.getAbsolutePath(),Toast.LENGTH_LONG).show();
if (!file.exists() || !file.canRead()) {
Toast.makeText(this,"ToastError",Toast.LENGTH_LONG).show();
return;
}
Uri uri = Uri.fromFile(file);
emailIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(emailIntent, "Choisissez votre application de Mail (Gmail,Outlook...)"));
}
But as I said, my app constantly closing is such an issue to my work, I hope you have any solutions !
Activity's are designed to stop once the phone sleeps.
What you need is a background service that runs always.
https://developer.android.com/training/run-background-service/create-service.html
http://www.vogella.com/tutorials/AndroidServices/article.html
So thanks to #Matthew Shearer, I've been able to fix my issues,learn many things about services and have a fully functionnal app on all phones, but Huawei.I learnt that Huawei phones had a specific function called "Protected Apps" which gave me many problems to keep my service alive.
But there is a solution here :
"Protected Apps" setting on Huawei phones, and how to handle it
Copy paste the code, use the ifHuaweiAlert() in the onCreate() and enjoy!
I have implemented In-App Billing in my Activity
this is my onIabPurchaseFinished() method:
#Override
public void onIabPurchaseFinished(IabResult result, Purchase info) {
if (!verifyDeveloperPayload(info)) {
Toast.makeText(this, R.string.error_purchasing, Toast.LENGTH_LONG).show();
}
Toast.makeText(this, R.string.premium_bought, Toast.LENGTH_LONG).show();
if (info.getSku().equals("chords_premium")) {
/** salva isPremium tra SharedPreferences */
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("status", "purchased");
editor.apply();
}
}
As you can see I save the String "status" to SharedPreferences so that I can access it from anywhere, and keep it stored even after the app is closed.
Then in my other Activities where ads are implemented I wrote like this:
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
final String status = prefs.getString("status", "free");
/** gestisce le pubblicita */
if (status.equals("free")) {
MobileAds.initialize(getApplicationContext(), "ca-app-pub-6723047396589178/2654753246");
AdView listBanner = (AdView) findViewById(R.id.chords_list_banner);
AdRequest adRequest = new AdRequest.Builder().build();
listBanner.loadAd(adRequest);
/** carica Ad a tutto schermo */
chordsListAd = new InterstitialAd(this);
chordsListAd.setAdUnitId("ca-app-pub-6723047396589178/7447672046");
requestNewInterstitial();
chordsListAd.setAdListener(new AdListener() {
#Override
public void onAdClosed() {
requestNewInterstitial();
}
});
}
As you can see here the Ads are surrounded by an if statement that checks if the "status"String is set to free.
The problem is that when I buy Premium, the Ads are still shown. How can I fix it?
It's because you are saving your data in Base Context and trying to find it in the current Activity context using (this).
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
to
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
Also, a more recommeded way to query In-App purchased items is to query In- App inventory instead of storing in sharedprefs.
As mention in Google Docs
Query Purchased Items
Upon a successful purchase, the user’s purchase data is cached locally by Google Play’s In-app Billing service. It is good practice to frequently query the In-app Billing service for the user’s purchases, for example whenever the app starts up or resumes, so that the user’s current in-app product ownership information is always reflected in your app.
To retrieve the user’s purchases from your app, call queryInventoryAsync(QueryInventoryFinishedListener) on your IabHelper instance. The QueryInventoryFinishedListener argument specifies a listener that is notified when the query operation has completed and handles the query response. It is safe to make this call fom your main thread.
mHelper.queryInventoryAsync(mGotInventoryListener); //mHelper is IabHelper instance
If the query is successful, the query results are stored in an Inventory object that is passed back to the listener. The In-app Billing service returns only the purchases made by the user account that is currently logged in to the device.
IabHelper.QueryInventoryFinishedListener mGotInventoryListener
= new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
if (result.isFailure()) {
// handle error here
}
else {
// does the user have the premium upgrade?
mIsPremium = inventory.hasPurchase(SKU_PREMIUM);
// update UI accordingly
}
}
};
Check if the inapp purchase is made:
//*************************************checking in app purchase has been made********************************//
void testInApp()
{
if (!blnBind) return;
if (mService == null) return;
int result;
try {
result = mService.isBillingSupported(3, getPackageName(), "inapp");
//Toast.makeText(context, "isBillingSupported() - success : return " + String.valueOf(result), Toast.LENGTH_SHORT).show();
Log.i(tag, "isBillingSupported() - success : return " + String.valueOf(result));
} catch (RemoteException e) {
e.printStackTrace();
//Toast.makeText(context, "isBillingSupported() - fail!", Toast.LENGTH_SHORT).show();
Log.w(tag, "isBillingSupported() - fail!");
return;
}
}
void checkInApp()
{
if (!blnBind) return;
if (mService == null) return;
Bundle ownedItems;
try {
ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
//Toast.makeText(context, "getPurchases() - success return Bundle", Toast.LENGTH_SHORT).show();
Log.i(tag, "getPurchases() - success return Bundle");
} catch (RemoteException e) {
e.printStackTrace();
//Toast.makeText(context, "getPurchases - fail!", Toast.LENGTH_SHORT).show();
Log.w(tag, "getPurchases() - fail!");
return;
}
int response = ownedItems.getInt("RESPONSE_CODE");
//Toast.makeText(context, "getPurchases() - \"RESPONSE_CODE\" return " + String.valueOf(response), Toast.LENGTH_SHORT).show();
Log.i(tag, "getPurchases() - \"RESPONSE_CODE\" return " + String.valueOf(response));
if (response != 0) return;
ArrayList<String> ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
ArrayList<String> purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
ArrayList<String> signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE");
String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN");
Log.i(tag, "getPurchases() - \"INAPP_PURCHASE_ITEM_LIST\" return " + ownedSkus.toString());
Log.i(tag, "getPurchases() - \"INAPP_PURCHASE_DATA_LIST\" return " + purchaseDataList.toString());
Log.i(tag, "getPurchases() - \"INAPP_DATA_SIGNATURE\" return " + (signatureList != null ? signatureList.toString() : "null"));
Log.i(tag, "getPurchases() - \"INAPP_CONTINUATION_TOKEN\" return " + (continuationToken != null ? continuationToken : "null"));
// TODO: management owned purchase
try {
if(purchaseDataList.size()>0){
jinapp=new JSONArray(purchaseDataList.toString());
JSONObject c = jinapp.getJSONObject(0);
String productid=c.getString("productId");
if(productid!=null){
SharedPreferences.Editor editor = prefpurchase.edit();
editor.putBoolean(Constants.APP_IS_PURCHASED,true);
editor.commit();
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO: management owned purchase
}
Write the code in your SplashScreen
Now in the activity/fragment in which you are showing your ad,write the following code:
//*******************to check purchase has been made.If yes disable ads and no then show ads******************//
prefpurchase = this.getSharedPreferences(Constants.GET_IN_APP_STATE, Context.MODE_PRIVATE);
//Toast.makeText(context, "bindService - return " + String.valueOf(blnBind), Toast.LENGTH_SHORT).show();
//In App Purchase
ispurchased=prefpurchase.getBoolean(Constants.APP_IS_PURCHASED,false);
System.out.println("ispurchased-->"+ispurchased);
if(ispurchased)
{
setContentView(R.layout.activity_home_noads);
}else{
System.out.println("Getting ad");
setContentView(R.layout.activity_home);
//Locate the Banner Ad in activity_main.xml
AdView adView = (AdView) this.findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder()
// Add a test device to show Test Ads
//.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
//.addTestDevice("B2D63***************************")
.build();
// Load ads into Banner Ads
adView.loadAd(adRequest);
}
//*******************************************************************************************************//
The logic is simple,you are creating two versions of your layout,one with ad and the other without ad.
Load the correct layout depending on the value of sharedpreference.
mService:
Write this code globally in splashscreen before onCreate():
private IInAppBillingService mService;
private ServiceConnection mServiceConn = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IInAppBillingService.Stub.asInterface(service);
}
};
blnBind
Declare blnBind globally:
boolean blnBind;
In onCreate() of SplashActivity write:
// Bind Service
blnBind = bindService(new Intent(
"com.android.vending.billing.InAppBillingService.BIND"),
mServiceConn, Context.BIND_AUTO_CREATE);
//Toast.makeText(context, "bindService - return " + String.valueOf(blnBind), Toast.LENGTH_SHORT).show();
Log.i(tag, "bindService - return " + String.valueOf(blnBind));
//In App Purchase
GET_IN_APP_STATE or APP_IS_PURCHASED are created for shared Preferences,that acts as a key for preference values.
//Preferences to check in app purchase
final static public String GET_IN_APP_STATE = "prefinapp";
public static final String APP_IS_PURCHASED ="AppIsPurchased";
Whenever a purchase is made,don't forget to set the shared preference value to true.
I have followed twitter fabric log in and everything is working fine except for the part where i try to post a tweet. When i execute this following code i need to login again, so it seems like i have to check an access token or some, but i have no idea and can't find how to do that.
#Override
public void onCreate(Bundle savedInstanceState) {
//initialize facebook sdk
FacebookSdk.sdkInitialize(getActivity().getApplicationContext());
super.onCreate(savedInstanceState);
TwitterSession session = Twitter.getSessionManager().getActiveSession();
TwitterAuthToken authToken = session.getAuthToken();
String token = authToken.token;
String secret = authToken.secret;
if (token != null ) {
Log.d(TAG, "twitter token" + token);
}
if (secret != null ) {
Log.d(TAG, "twitter secret" + secret);
}
TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET);
Fabric.with(this.getActivity(), new TwitterCore(authConfig), new TweetComposer());
}
then i am using a function to post the tweet
public void TwitterSharing() {
Log.d(TAG, "Running twitter share");
Log.d(TAG, "Share on twitter 1: " + sport);
Log.d(TAG, "Share on twitter 2: " + speed);
Log.d(TAG, "Share on twitter 3: " + distance);
Log.d(TAG, "Share on twitter 4: " + date);
Log.d(TAG, "Shared image url: " + sharedImage);
TweetComposer.Builder builder = new TweetComposer.Builder(this.getActivity())
.text("just setting up my Fabric.")
.image(Uri.parse(sharedImage));
builder.show();
}
It all works but on the web page it is loading i need to login again, that should not happen but i have no idea how.
Thanks for any input.
For that, you need to make an Activity as the launcher activity. Let's call it DispatchActivity
public class DispatchActivity extends Activity{
#Override
public void onCreate(Bundle savedInstanceState){
This returns true if user is logged in.
boolean isLoggedIn = mSharedPreferences.getBoolean(PREF_KEY_TWITTER_LOGIN, false);
if (isLoggedIn){
//User is logged in, take him to your activity
Intent i = new Intent(this,yourMainActivity.class);
this.startActivity(i);
}
else{
//User is not logged in, take him to your SignIn activity
Intent i = new Intent(this,SignUp.class);
this.startActivity(i);
}
}
}
Remember to make this your launcher activity, and don't create a layout file for it.
This is my code, an attempt to launch an in app purchase when a button is pressed:
purchaseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(purchased.equals("remove_ads")) {
Toast.makeText(getApplicationContext(), "You already own the item.",
Toast.LENGTH_LONG).show();
}
else{
try{
Bundle buyIntentBundle = mservice.getBuyIntent(3, getPackageName(),
"remove_ads", "inapp", "key");
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
try{
startIntentSenderForResult(pendingIntent.getIntentSender(), ///NPE here
1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0),
Integer.valueOf(0));
}
catch(IntentSender.SendIntentException ee){
Toast.makeText(getApplicationContext(), "Error was: " + ee,
Toast.LENGTH_LONG).show();
}
catch(NullPointerException n){
Toast.makeText(getApplicationContext(), "Error was: " + n,
Toast.LENGTH_LONG).show();
}
}
catch (RemoteException e){
Toast.makeText(getApplicationContext(), "Error was: " + e,
Toast.LENGTH_LONG).show();
mHelper.flagEndAsync();
mHelper.launchPurchaseFlow(store.this, "remove_ads", 10001,
mPurchaseFinishedListener, "key");
}
}
}
});
and for some reason I get the NPE at the line indicated startIntentSenderForResult... and I don't understand what could cause it. Previously I used this code in another in app purchase exactly as shown except it was a different sku. Could it make a difference since I have 2 identical copies of this code block shown in the same class? Stacktrace doesn't show anything useful either, just the NPE.
I've tested my android app successfully using Paypal Sandbox environment. I am about to release my app, so want to change the paypal configuration to 'PRODUCTION'
To do this, I've changed the following for production:
private static final String CONFIG_ENVIRONMENT = PaymentActivity.ENVIRONMENT_PRODUCTION;
private static final String CONFIG_CLIENT_ID = "my client id for production";
private static final String CONFIG_RECEIVER_EMAIL = "live-id#gmail.com";
Now when I try to make a payment using my another paypal account, I am getting error:
Login Failed
System error. Please try again later.
Same thing happens using the emulator with production settings.
My question is do I have to make any other changes to move from sandbox to production env?
Thanks
UPDATE 1
All the above settings are for the 'production' environment.
Using direct payment
I've noticed problems using paypal from my app when I name the String before onCreate so what I did was..
//When you want to initiate payment...
public void onBuyPressed(View pressed) {
PayPalPayment thingToBuy = new PayPalPayment(new BigDecimal(valuez), "USD", iu);
PaymentActivity.ENVIRONMENT_LIVE);//etc
I dont know if "PRODUCTION" or "LIVE" makes a difference but give it a try.
I'm going to add more hope this helps this is what i did
get rid of all those paypal strings before onCreate and just when they get ready to pay have textbox with onClick is onBuyPressed...
public void onBuyPressed(View pressed) {
TextView inptP =(TextView)findViewById(R.id.WHATHEYAREBUYING);
String iu =inptP.getText().toString();
TextView inptt =(TextView)findViewById(R.id.WHATITCOST);
String it =inptt.getText().toString();
try{
double valuez =Double.parseDouble(it);
if(valuez> 0)
{
PayPalPayment thingToBuy = new PayPalPayment(new BigDecimal(valuez), "USD", iu);
Intent intent = new Intent(this, PaymentActivity.class);
TextView id =(TextView)findViewById(R.id.MYPAYPALID);
String uname = id.getText().toString();
TextView iz =(TextView)findViewById(R.id.MYPAYPALEMAIL);
String insane = iz.getText().toString();
TextView name =(TextView)findViewById(R.id.MYCUSTOMERSNAME);
String custname = name.getText().toString();
Time now = new Time();
now.setToNow();
// comment this line out for live or set to PaymentActivity.ENVIRONMENT_SANDBOX for sandbox
intent.putExtra(PaymentActivity.EXTRA_PAYPAL_ENVIRONMENT, PaymentActivity.ENVIRONMENT_LIVE);
// it's important to repeat the clientId here so that the SDK has it if Android restarts your
// app midway through the payment UI flow.
intent.putExtra(PaymentActivity.EXTRA_CLIENT_ID, uname);
// Provide a payerId that uniquely identifies a user within the scope of your system,
// such as an email address or user ID.
intent.putExtra(PaymentActivity.EXTRA_PAYER_ID, custname);
intent.putExtra(PaymentActivity.EXTRA_RECEIVER_EMAIL, insane);
intent.putExtra(PaymentActivity.EXTRA_PAYMENT, thingToBuy);
startActivityForResult(intent, 0);
}
else{
Toast.makeText(getApplicationContext(), "You haven't entered anything.",
Toast.LENGTH_LONG).show();
}} catch (NumberFormatException e) {
}}
#Override
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
PaymentConfirmation confirm = data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
//THINGS YOU WANT IT TO WHEN THE PAYMENT IS FINISHED GO BETWEEN HERE
//AND HERE
if (confirm != null) {
try {
Log.i("paymentExample", confirm.toJSONObject().toString(4));
// TODO: send 'confirm' to your server for verification.
// see https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/
// for more details.
} catch (JSONException e) {
Log.e("paymentExample", "an extremely unlikely failure occurred: ", e);
}
}
}
else if (resultCode == Activity.RESULT_CANCELED) {
Log.i("paymentExample", "The user canceled.");
}
else if (resultCode == PaymentActivity.RESULT_PAYMENT_INVALID) {
Log.i("paymentExample", "An invalid payment was submitted. Please see the docs.");
}}
No need to put PaymentActivity.EXTRA_PAYPAL_ENVIRONMENT for live.
This is my code which is working fine.
Declare these constants is class scope. NOTE: There are two client ids in page of your application in developer Paypal. One in "Test credentials" and The other under "Live credentials" that you should click on "show" link in order to see it. Select client id of "Live credentials" if you want to release your application.
private static final String PAYPAL_CLIENT_ID = "YOUR-CLIENT-IT";
private static final String PAYPAL_RECEIVER_EMAIL = "YOUR-EMAIL";
Then define service in onCreate():
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// start Paypal service
Intent intent = new Intent(this, PayPalService.class);
// live: don't put any environment extra
// sandbox: use PaymentActivity.ENVIRONMENT_SANDBOX
intent.putExtra(PaymentActivity.EXTRA_PAYPAL_ENVIRONMENT, PaymentActivity.ENVIRONMENT_PRODUCTION);
intent.putExtra(PaymentActivity.EXTRA_CLIENT_ID, PAYPAL_CLIENT_ID);
startService(intent);
}
When user hit a button following method will run:
private void openDonateBtnPressed(BigDecimal donation) {
PayPalPayment payment = new PayPalPayment(donation, "USD", "Donation");
Intent intent = new Intent(this, PaymentActivity.class);
// comment this line out for live or set to PaymentActivity.ENVIRONMENT_SANDBOX for sandbox
intent.putExtra(PaymentActivity.EXTRA_PAYPAL_ENVIRONMENT, PaymentActivity.ENVIRONMENT_PRODUCTION);
// it's important to repeat the clientId here so that the SDK has it if Android restarts your
// app midway through the payment UI flow.
intent.putExtra(PaymentActivity.EXTRA_CLIENT_ID, PAYPAL_CLIENT_ID);
// Provide a payerId that uniquely identifies a user within the scope of your system,
// such as an email address or user ID.
intent.putExtra(PaymentActivity.EXTRA_PAYER_ID, "<someuser#somedomain.com>");
intent.putExtra(PaymentActivity.EXTRA_RECEIVER_EMAIL, PAYPAL_RECEIVER_EMAIL);
intent.putExtra(PaymentActivity.EXTRA_PAYMENT, payment);
startActivityForResult(intent, 0);
}
and this is onActivityResult():
#Override
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
PaymentConfirmation confirm = data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
if (confirm != null) {
try {
Toast.makeText(RateTheAppActivity.this, R.string.rate_donation_received, Toast.LENGTH_LONG).show();
Log.d(TAG, confirm.toJSONObject().toString(4));
} catch (JSONException e) {
Log.e(TAG, "an extremely unlikely failure occurred: ", e);
}
}
}
else if (resultCode == Activity.RESULT_CANCELED) {
Log.d(TAG, "The user canceled.");
}
else if (resultCode == PaymentActivity.RESULT_PAYMENT_INVALID) {
Log.e(TAG, "An invalid payment was submitted. Please see the docs.");
}
}