How to integrate google pay in my android app for payment - xamarin

Hi I am developing a xamarin forms application that targets both android and ios. I want to add google pay as my payment option to order items in android.
please help me is there any documentation available.

welcome to StackOverflow.
Google Pay does not process payments, and as such, it needs to reference your existing processor or gateway to do that. Here is a list of currently supported processors.
As Leo pointed out, you can integrate Google Pay in Xamarin using Xamarin's libs including Google Play Services.
During the integration, make sure to use the right configuration based on the payment processor of your choice. Follow this link to see some examples for different processors.
Hope it helps.

First of all, Google pay must be installed on the device.
Place these three methods in your MainActivity.cs
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if (requestCode == gpay_requestCode)
{
if (data != null)
{
string response = data.GetStringExtra("response");
string[] resArray = response.Split("&");
string txnId = resArray[0].Split("=")[1].ToString();
string responseCode = resArray[1].Split("=")[1].ToString();
string status = resArray[2].Split("=")[1].ToString();
string txnRef = resArray[3].Split("=")[1].ToString();
if (status == "SUCCESS")
{
Toast.MakeText(this, "Payment Success", ToastLength.Long).Show();
}
else
{
Toast.MakeText(this, "Payment Failed", ToastLength.Long).Show();
}
}
else
{
Toast.MakeText(this, "Payment Failed", ToastLength.Long).Show();
}
}
}
private void PayViaGooglePay()
{
if (IsGooglePayInstalled())
{
//Generate random unique number for transaction reference ID
string transId = $"UPI{Guid.NewGuid().ToString().Substring(0, 8)}";
using (var uri = new Android.Net.Uri.Builder()
.Scheme("upi")
.Authority("pay")
.AppendQueryParameter("pa", "yourgooglepayusername#test")//Google pay email
.AppendQueryParameter("pn", "Test Name") //Google pay name
.AppendQueryParameter("pn", "Sending Amount of 1 JOD") // Google pay note
.AppendQueryParameter("mc", "0000") //
.AppendQueryParameter("tr", transId) //transaction reference ID
.AppendQueryParameter("tn", "Pay to Test Name") //Transaction note
.AppendQueryParameter("am", "1") // Amount
.AppendQueryParameter("cu", "JOD") //Currency
.Build())
{
Intent = new Intent(Intent.ActionView);
Intent.SetData(uri);
Intent.SetPackage("com.google.android.apps.nbu.paisa.user");
StartActivityForResult(Intent, gpay_requestCode);
}
}
}
private bool IsGooglePayInstalled()
{
PackageManager pm = this.PackageManager;
bool installed = false;
try
{
pm.GetPackageInfo("com.google.android.apps.nbu.paisa.user", PackageInfoFlags.Activities);
installed = true;
}
catch (PackageManager.NameNotFoundException e)
{
Toast.MakeText(this, "Google Pay Is Not Installed", ToastLength.Long).Show();
}
return installed;
}
Because you can't call any of these methods from your shared project, you need to create a messaging center and call it wherever you wish.
Place the messaging center in your OnCreate method in the same MainActivity.cs
MessagingCenter.Subscribe<string>(this, "PayViaGooglePay", (value) =>
{
PayViaGooglePay();
});
And then you can call it wherever you want, just put this code wherever you need it
MessagingCenter.Send<string>("", "PayViaGooglePay");
I hope this helps :)

Related

Xamarin InAppBilling showing ItemUnavailable for purchase on Android

I'm implementing the InAppBilling plugin in my Xamarin Forms 5 app for auto-renewing subscriptions.
I have the "subscriptions" set up on Google Play and they're active. When I ask for a list of subscription items, I get the list fine but when I try make a purchase, I get the following error that indicates the item is not available.
I'm running this on a real device connected to my laptop via USB. Any idea what I'm doing wrong?
Here's my purchase subscription method which is directly from documentation here:
public async Task<bool> Subscribe(string productId)
{
var billing = CrossInAppBilling.Current;
try
{
var connected = await billing.ConnectAsync();
if (!connected)
return false;
//check purchases
var purchase = await billing.PurchaseAsync(productId, ItemType.Subscription);
//possibility that a null came through.
if (purchase == null)
{
//did not purchase
return false;
}
else
{
//purchased!
if (Device.RuntimePlatform == Device.Android)
{
// Must call AcknowledgePurchaseAsync else the purchase will be refunded
//await billing.AcknowledgePurchaseAsync(purchase.PurchaseToken);
}
return true;
}
}
catch (InAppBillingPurchaseException purchaseEx)
{
//Billing Exception handle this based on the type
throw new Exception("Error: " + purchaseEx);
}
catch (Exception ex)
{
//Something else has gone wrong, log it
throw new Exception();
}
finally
{
await billing.DisconnectAsync();
}
}
As I mentioned before, I see the subscription items available and active on Google Play. I also made sure, I'm getting them from "Subscriptions" and NOT "In-App Products". I'm using the ID that I copy and paste from the "Product ID" column on Google Play Console -- see below:
Any idea what the issue here may be?

Fetching data from the internet after a page opens in Xamarin forms

I am having some performance issues with my code. I am working with basic MVVM in Xamarin forms project, and I want to fetch data from the internet when someone navigates to another page. Below is what I have done;
This is how I am navigating to another page via Command; (To be honest I don't really know if this method of navigation has some performance penalties)
if (Application.Current.MainPage.Navigation.NavigationStack.Last().GetType() != typeof(SubcategoryPage))
{
await Application.Current.MainPage.Navigation.PushAsync(new SubcategoryPage());
}
Here, I am passing Id of a particular category to get its corresponding subcategories
public SubcategoryPage(int id)
{
InitializeComponent();
this.BindingContext = new SubcategoryPageViewModel(id);
}
In the constructor of the SubcategoryPageViewModel, I used the Id to fetch the data online like so;
public SubcategoryPageViewModel(int id)
{
SubcategoryLoader(id);
}
Below is the method that is fetching the data from the internet through my DataService class. The code below work well in getting the data from the internet;
private async Task SubcategoryLoader(int id)
{
try
{
var subCategories = await SubcategoryDataService.GetSubcategories(id);
if (subCategories.code == 1) // StatusCode = Successful
{
SubCategories = subCategories.document;
}
else
{
await Application.Current.MainPage.DisplayAlert("Oops!","Something went wrong", "Ok");
}
}
catch (Exception ex)
{
await Application.Current.MainPage.DisplayAlert("Oops!", ex.Message, "Ok");
}
}
Now my problem is that the SubcategoryPage doesn't open until the online service is over which leads to a serious lags. So what I want to have happen is to open the SubcategoryPage before the internet services happen.
Please any assistance is appreciated.
Move it to OnAppearing method .
Add a simple check .
protected override void OnAppearing()
{
base.OnAppearing();
if(BindingContext == null)
{
BindingContext = new SubcategoryPageViewModel(id);
}
}

How to check internet connection continuously in Xamarin.Android Native?

My application is completely based on internet and it does not work without it, when the internet is not available or it is slow my application is getting stopped unfortunately.
I tried to implement try, catch but it is not helping me out as it is not throwing any exception, then I thought that I have to check the internet connectivity continuously till the app is running and stop any activity from performing and set a popup to connect to the internet.
I am able to get the popup whenever I call a method which has the following code inside it,
ConnectivityManager connectivityManager = (ConnectivityManager)GetSystemService(ConnectivityService);
NetworkInfo networkInfo = connectivityManager.ActiveNetworkInfo;
if (networkInfo == null)
{
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.SetTitle("Network");
alert.SetMessage("Please turn of your Wifi or Mobile Data From Settings");
alert.SetPositiveButton("OK", (senderAlert, args) => {
Intent intent = new Intent(Android.Provider.Settings.ActionSettings);
StartActivity(intent);
});
alert.SetNegativeButton("Cancel", (senderAlert, args) => {
Toast.MakeText(this, "Cancelled!", ToastLength.Short).Show();
Finish();
});
Dialog dialog = alert.Create();
dialog.Show();
But I am unable to get the connection checked continuously, So Can some one Please help me to complete get this functionality in my application.
You need to use a BroadcastReceiver to monitor network changes.
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "android.net.conn.CONNECTIVITY_CHANGE" })]
[Android.Runtime.Preserve(AllMembers = true)]
public class ConnectivityChangeBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action != ConnectivityManager.ConnectivityAction)
return;
//Check if is connected and raise a custom event or store
//the current in a static global variable
}
}
}
In Android 7.0, you need to remove IntentFilter from the class and register the receiver.
var receiver = new ConnectivityChangeBroadcastReceiver();
Application.Context.RegisterReceiver(receiver, new IntentFilter(ConnectivityManager.ConnectivityAction));
Another option is to use the ConnectivityPlugin https://github.com/jamesmontemagno/ConnectivityPlugin , which is easier to use.
CrossConnectivity.Current.ConnectivityChanged += HandleConnectivityChanged;
void HandleConnectivityChanged (object sender, ConnectivityChangedEventArgs e)
{
// You can check the network status in
//e.IsConnected
}
Note that The ACCESS_NETWORK_STATE and ACCESS_WIFI_STATE permissions are required.

How to add an Attachment to Outlook Mail from UWP App programmatically?

I am developing an UWP Application , i want to add a Attachment to outlook from UWP app programmatically
Request you to please me know if any alternatives are there.
Looking forward for your response.
You can use the share contract to send some data to the compliant applications (including outlook). It allows you to share some text and data with any compliant apps.
To activate the sharing, you just need to register to the DataRequested event and show the share UI:
DataTransferManager.GetForCurrentView().DataRequested += OnDataRequested;
DataTransferManager.ShowShareUI();
Then, in the event handler:
private async void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
var deferral = args.Request.GetDeferral();
try
{
args.Request.Data.Properties.Title = "Share Title"
args.Request.Data.Properties.Description = "Share some data/file";
var file = await ApplicationData.Current.TemporaryFolder.GetFileAsync("myFileToShare.xxx");
args.Request.Data.SetStorageItems(new IStorageItem[] { logFile });
}
catch
{
args.Request.FailWithDisplayText("Unable to share data");
}
finally
{
deferral.Complete();
sender.DataRequested -= OnDataRequested;
}
}
Once done, the system will show the share UI where the user will be able to select the app he want. This app will receive the sent data.
While #Vincent's answer is perfect when you want to use Share Contract, if you want to use Just Email and attach the File, Below is a simple Method that i use in one of my App.
internal async void ShowEmail(string body, string subject, StorageFile attachment)
{
EmailMessage email = new EmailMessage();
email.Subject = subject;
email.Body = body;
var stream = RandomAccessStreamReference.CreateFromFile(attachment);
email.SetBodyStream(EmailMessageBodyKind.Html, stream);
await EmailManager.ShowComposeNewEmailAsync(email);
}
Above method is a strip down of the example from Here

Google Places API in Android gives Place StatusCode as PLACES_API_USAGE_LIMIT_EXCEEDED

I have used Google Places API for adding the place. Below is the code for GoogleApiClient and Adding a Place.
Start indented code:
mGoogleApiClient = new GoogleApiClient
.Builder(this)
.enableAutoManage(this, 0, this)
.addApi(Places.GEO_DATA_API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
AddPlaceRequest place =
new AddPlaceRequest(
"xyz",
new LatLng(point.latitude, point.longitude),
"2095",
Collections.singletonList(Place.TYPE_SHOE_STORE),
"+123456789",
Uri.parse("www.abc.com/")
);
Places.GeoDataApi.addPlace(mGoogleApiClient, place).setResultCallback(new ResultCallback<PlaceBuffer>() {
#Override
public void onResult(PlaceBuffer places) {
if (!places.getStatus().isSuccess()) {
Log.e(TAG, "Place query did not complete. Error: " + places.getStatus().toString());
places.release();
return;
}
final Place place = places.get(0);
Log.i(TAG, "Place add result: " + place.getName());
places.release();
}
});
I am getting Output as :
Place query did not complete. Error:
Status{statusCode=PLACES_API_USAGE_LIMIT_EXCEEDED, resolution=null}
I have not even requested more than 25 times for Google Places API. Even if I try from different account also it gives me the same error. Thanks in advance.

Resources