PayPal Adaptive Payment (Chained Payment) Integration in Android - paypal-sandbox

I am integrating PayPal Adaptive payment in my apps and searching for solution of my problem.If any one had implemented chained payment in android please provide me help.
Problem:-
When integrating chained payment in my app using PayPal_MPL.jar.Its working fine for me but there is a problem that there is no credit card payment option in paypal dialog.
Thanks
I am referring this link

first implement method
private void initLibrary() {
PayPal pp = PayPal.getInstance();
if(pp == null) {
pp = PayPal.initWithAppID(this, PAYPAL_APP_ID, PayPal.ENV_SANDBOX);
pp.setLanguage("en_US"); // Sets the language for the library.
pp.setFeesPayer(PayPal.FEEPAYER_EACHRECEIVER);
// pp.setShippingEnabled(true);
pp.setDynamicAmountCalculationEnabled(false);
}
}
**paypal button click event code**
double secondary_payment = 0;
double primary_payment = 0;
PayPalAdvancedPayment advPayment = makeChainedPayment(secondary_payment,primary_payment,"primary_email","secondary_email");
Intent checkoutIntent = PayPal.getInstance().checkout(advPayment, your_current_activity);
startActivityForResult(checkoutIntent, 1);
=============================================
private PayPalAdvancedPayment makeChainedPayment(double priceSecondary, double pricePrimary, String primary_email, String secondary_email) {
PayPalAdvancedPayment payment = new PayPalAdvancedPayment();
payment.setCurrencyType("USD");
// payment.setMerchantName("PushND");
BigDecimal bigDecimalPrimary=new BigDecimal(pricePrimary);
PayPalReceiverDetails receiverPrimary = new PayPalReceiverDetails();
receiverPrimary.setRecipient(primary_email);
//receiverPrimary.setRecipient("adaptive_receiver_1#pushnd.com");
receiverPrimary.setSubtotal(bigDecimalPrimary);
receiverPrimary.setIsPrimary(true);
payment.getReceivers().add(receiverPrimary);
PayPalReceiverDetails receiverSecondary= new PayPalReceiverDetails();
receiverSecondary.setRecipient(secondary_email);
BigDecimal bigDecimalSecond=new BigDecimal(priceSecondary);
receiverSecondary.setSubtotal(bigDecimalSecond);
payment.getReceivers().add(receiverSecondary);
return payment;
}

Please find the below link and check for your answer...
https://github.com/paypal/PayPal-Android-SDK
PayPal pp = PayPal.getInstance();
launchChainedPayment = pp.getCheckoutButton(this, PayPal.BUTTON_194x37, CheckoutButton.TEXT_PAY);
launchChainedPayment.setOnClickListener(this);
private void initLibrary() {
PayPal pp = PayPal.getInstance();
if(pp == null) {
pp = PayPal.initWithAppID(this, Constant.PAYPAL_APP_ID, Constant.server);
pp.setLanguage("en_US"); // Sets the language for the library.
pp.setFeesPayer(PayPal.FEEPAYER_EACHRECEIVER);
pp.setShippingEnabled(true);
pp.setDynamicAmountCalculationEnabled(false);
}
}
private PayPalAdvancedPayment makeChainedPayment(double priceDouble,double pricePrimary,String primary_email,JSONObject jsonObject) {
PayPalAdvancedPayment payment = new PayPalAdvancedPayment();
payment.setCurrencyType("USD");
payment.setMerchantName("PushND");
BigDecimal bigDecimalPrimary=new BigDecimal(String.valueOf(priceDouble));
PayPalReceiverDetails receiverPrimary = new PayPalReceiverDetails();
receiverPrimary.setRecipient(primary_email);
//receiverPrimary.setRecipient("adaptive_receiver_1#pushnd.com");
receiverPrimary.setSubtotal(bigDecimalPrimary);
receiverPrimary.setIsPrimary(true);
payment.getReceivers().add(receiverPrimary);
try {
JSONObject jsonObjectSecondary = jsonObject;
Iterator<Object> keys = jsonObjectSecondary.keys();
while (keys.hasNext())
{
String Key=String.valueOf(keys.next());
PayPalReceiverDetails receiverSecondary= new PayPalReceiverDetails();
receiverSecondary.setRecipient(jsonObjectSecondary.getJSONObject(Key).get("email").toString());
// receiverSecondary.setRecipient("adaptive_receiver_2#pushnd.com");
double priceSecondary=priceDouble*((Double.parseDouble(jsonObjectSecondary.getJSONObject(Key).get("profit_percent").toString()))/100);
BigDecimal bigDecimalSecondary=new BigDecimal(String.valueOf(priceSecondary));
receiverSecondary.setSubtotal(bigDecimalSecondary);
receiverSecondary.setIsPrimary(false);
payment.getReceivers().add(receiverSecondary);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return payment;
}

Related

Nested subscription to messages on xamarin forms

I'm new with Xamarin forms and don't know how to deal with this case. I've tryed to implement it in several ways but with no success.
I have a page where when user makes an action (write a text on a text box and send it with enter key) my app must make some checkings. Depending on the result of the checks, it could be necessary to show a modal page with a list of item to select. Ones user makes the selection process must continue with other checks. And here is my problem, because in this next checkings I have to show another page. User must make a selection/enter some date, and then continue to complete the proccess, but this page is not appear.
I'm using the messagingCenter to subscribe to the modal pages. First modal page appears and makes the selection well. Second modal page is never shown and then proccess never complets.
Here is some of my code:
NavigationPage navigationPage = new NavigationPage(new ListItemsPage(products));
Navigation.PushModalAsync(navigationPage);
MessagingCenter.Subscribe<ListItemsPage, Guid?>(this, "Select product", (obj, item) =>
{
try
{
if (item != null)
{
product = products.SingleOrDefault(x => x.Guid == item);
if (product != null) ProcessLine(product);
}
}
catch(Exception ex)
{
throw ex;
}
finally
{
MessagingCenter.Unsubscribe<ListItemsPage, Guid?>(this, "Select product");
}
});
On ListItemsPage I have this code whe item is selected:
private void MenuItem_Clicked(object sender, EventArgs e)
{
// some logic...
Navigation.PopModalAsync();
MessagingCenter.Send(this, "Select product", SelectedGuid);
}
SelectedGuid is a Guid type data and when debbugin is well selected.
Problems comes when goes to ProcessLine method.
private void ProcessLine(Product product) {
// make some logic...
NavigationPage navigationPage = new NavigationPage(new ControlUnitsPage(model));
Navigation.PushModalAsync(navigationPage);
MessagingCenter.Subscribe<ControlUnitsPage, ControlUnits>(this, "Select units, date and lot code", (obj, item) =>
{
try
{
if (item != null)
{
_date = item.Date;
_code = item.Code;
_units = item.Units;
Save(productLine, product, _units, _date,_code);
}
}
catch(Exception ex)
{
throw ex;
}
finally
{
MessagingCenter.Unsubscribe<ControlUnitsPage, ControlUnits>(this, "Select units, date and lot code");
}
});
}
ControlUnitsPage has the same structure as the last one page. First makes a PopModalAsync and then sends the message sending an instance of ControlUnits type.
private void Button_Clicked(object sender, EventArgs e)
{
//some logic...
Item = new ControlUnits() { Date = DateField.Date, Code = CodeField.Text, Units = int.Parse(SelectedUnits.Value.ToString()) };
Navigation.PopModalAsync();
MessagingCenter.Send(this, "Select units, date and lot code", Item);
}
I think problem is in the order of invoking method but dont know what is the properly order because I am not able to understand how pushmodal, popmodal methods work, whether or not I should use await with it if after that comes a subscription. I really don't know and I need help, please.
Thank you so much!
your Send and Subscribe calls both need to use matching parameters
if Subscribe looks like this
MessagingCenter.Subscribe<ControlUnitsPage, ControlUnits>(this, "Select units, date and lot code", (obj, item) => ... );
then Send needs to match
MessagingCenter.Send<ControlUnitsPage, ControlUnits>(this, "Select units, date and lot code", Item);

Firebase Dynamic Links in Unity

Where should I put this chunk of code in order the listener function works every time I enter the app from the deep link?
Now in my unity mobile app I have this code in the initial load, however it does not work well.
The first case of entering the app from the deep link is not being handled. Only after initial load when I click the deep link my listener function works (as the listener is already set).
Is there any solution to this issue?
void Start()
{
DynamicLinks.DynamicLinkReceived += OnDynamicLink;
}
// Display the dynamic link received by the application.
void OnDynamicLink(object sender, EventArgs args)
{
var dynamicLinkEventArgs = args as ReceivedDynamicLinkEventArgs;
Debug.LogFormat("Received dynamic link {0}", dynamicLinkEventArgs.ReceivedDynamicLink.Url.OriginalString);
}
Test this, feel free to edit.
void Start()
{
StartCoroutine(WaitLoader()); //Loader
}
public void trueAwoken()
{
DynamicLinks.DynamicLinkReceived += OnDynamicLink;
}
public IEnumerator WaitLoader()
{
int i = 0;
while (i < 5) // Potential for true load state 5 (increase this 0-1000+?, it depends on your build?)
{
i++;
//Debug.Log("Waiting: " + i + "/" + Time.deltaTime);
yield return new WaitForFixedUpdate();
}
trueAwoken();
}

I have a "Upload Record" PXAction to load records to grid and release these records

I have a custom PXbutton called UploadRecords, when I click this button I should populate the grid with records and release the records.
Release Action is pressed in the UploadRecords action delegate. The problem I get with this code is, the code here function properly for less records by release action but when passes thousands of records to release, it takes huge time(> 30 min.) and show the error like Execution timeout.
suggest me to avoid more execution time and release the records fastly.
namespace PX.Objects.AR
{
public class ARPriceWorksheetMaint_Extension : PXGraphExtension<ARPriceWorksheetMaint>
{
//public class string_R112 : Constant<string>
//{
// public string_R112()
// : base("4E5CCAFC-0957-4DB3-A4DA-2A24EA700047")
// {
// }
//}
public class string_R112 : Constant<string>
{
public string_R112()
: base("EA")
{
}
}
public PXSelectJoin<InventoryItem, InnerJoin<CSAnswers, On<InventoryItem.noteID, Equal<CSAnswers.refNoteID>>,
LeftJoin<INItemCost, On<InventoryItem.inventoryID, Equal<INItemCost.inventoryID>>>>,
Where<InventoryItem.salesUnit, Equal<string_R112>>> records;
public PXAction<ARPriceWorksheet> uploadRecord;
[PXUIField(DisplayName = "Upload Records", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
[PXButton]
public IEnumerable UploadRecord(PXAdapter adapter)
{
using (PXTransactionScope ts = new PXTransactionScope())
{
foreach (PXResult<InventoryItem, CSAnswers, INItemCost> res in records.Select())
{
InventoryItem invItem = (InventoryItem)res;
INItemCost itemCost = (INItemCost)res;
CSAnswers csAnswer = (CSAnswers)res;
ARPriceWorksheetDetail gridDetail = new ARPriceWorksheetDetail();
gridDetail.PriceType = PriceTypeList.CustomerPriceClass;
gridDetail.PriceCode = csAnswer.AttributeID;
gridDetail.AlternateID = "";
gridDetail.InventoryID = invItem.InventoryID;
gridDetail.Description = invItem.Descr;
gridDetail.UOM = "EA";
gridDetail.SiteID = 6;
InventoryItemExt invExt = PXCache<InventoryItem>.GetExtension<InventoryItemExt>(invItem);
decimal y;
if (decimal.TryParse(csAnswer.Value, out y))
{
y = decimal.Parse(csAnswer.Value);
}
else
y = decimal.Parse(csAnswer.Value.Replace(" ", ""));
gridDetail.CurrentPrice = y; //(invExt.UsrMarketCost ?? 0m) * (Math.Round(y / 100, 2));
gridDetail.PendingPrice = y; // (invExt.UsrMarketCost ?? 0m)* (Math.Round( y/ 100, 2));
gridDetail.TaxID = null;
Base.Details.Update(gridDetail);
}
ts.Complete();
}
Base.Document.Current.Hold = false;
using (PXTransactionScope ts = new PXTransactionScope())
{
Base.Release.Press();
ts.Complete();
}
List<ARPriceWorksheet> lst = new List<ARPriceWorksheet>
{
Base.Document.Current
};
return lst;
}
protected void ARPriceWorksheet_RowSelected(PXCache cache, PXRowSelectedEventArgs e, PXRowSelected InvokeBaseHandler)
{
if (InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (ARPriceWorksheet)e.Row;
uploadRecord.SetEnabled(row.Status != SPWorksheetStatus.Released);
}
}
}
First, Do you need them all to be in a single transaction scope? This would revert all changes if there is an exception in any. If you need to have them all committed without any errors rather than each record, you would have to perform the updates this way.
I would suggest though moving your process to a custom processing screen. This way you can load the records, select one or many, and use the processing engine built into Acumatica to handle the process, rather than a single button click action. Here is an example: https://www.acumatica.com/blog/creating-custom-processing-screens-in-acumatica/
Based on the feedback that it must be all in a single transaction scope and thousands of records, I can only see two optimizations that may assist. First is increasing the Timeout as explained in this blog post. https://acumaticaclouderp.blogspot.com/2017/12/acumatica-snapshots-uploading-and.html
Next I would load all records into memory first and then loop through them with a ToList(). That might save you time as it should pull all records at once rather than once for each record.
going from
foreach (PXResult<InventoryItem, CSAnswers, INItemCost> res in records.Select())
to
var recordList = records.Select().ToList();
foreach (PXResult<InventoryItem, CSAnswers, INItemCost> res in recordList)

Xamarin.Forms iOS Create animation using images

I work on Xamarin.Fomrs shared project. I want to display multiple images at same place with 100 ms interval. So that it will look like a GIF. In Android It is working. I created drawable file and in that I have put all the images with time interval. But in iOS, I am facing problem.
I found CAKeyFrameAnimation is used to implement this type of functionality. But I couldn't find how to implement it as I want.
I have implemented CAKeyFrameAnimation in ImageRenderer like this
class AnimatedImageRenderer : ImageRenderer
{
public AnimatedImageRenderer() { }
Animation objAnimation = new Animation();
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if (Control != null)
{
try
{
CAKeyFrameAnimation anim = CAKeyFrameAnimation.FromKeyPath("contents");
anim.Duration = 1;
//anim.KeyTimes = new[] {
// NSNumber.FromDouble (0), // FIRST VALUE MUST BE 0
// NSNumber.FromDouble (0.1),
// NSNumber.FromDouble(0.2),
// NSNumber.FromDouble(0.3),
// NSNumber.FromDouble(0.5),
// NSNumber.FromDouble(0.6),
// NSNumber.FromDouble(0.8),
// NSNumber.FromDouble(1.0), // LAST VALUE MUST BE 1
// };
anim.Values = new NSObject[] {
FromObject(UIImage.FromFile("bomb1.png")),
FromObject(UIImage.FromFile("bomb2.png")),
FromObject(UIImage.FromFile("bomb3.png")),
FromObject(UIImage.FromFile("bomb4.png")),
FromObject(UIImage.FromFile("bomb5.png")),
FromObject(UIImage.FromFile("bomb6.png")),
FromObject(UIImage.FromFile("bomb7.png")),
};
//anim.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.Linear);
anim.RepeatCount = 1;
anim.RemovedOnCompletion = false;
//anim.CalculationMode = CAAnimation.AnimationLinear;
//c.Init();
Control.Layer.AddAnimation(anim, "bomb");
}
catch (System.Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
// ModCommon.TraceLog("AnimatedImageRenderer tm_Tick" + ex.Message);
}
}
}
}
I don't know what extra property is missing. Please guide me.
Thank you :)
You should use CGImage instead of UIImage. Change your animation's value to:
anim.Values = new NSObject[] {
FromObject(UIImage.FromFile("bomb1.png").CGImage),
FromObject(UIImage.FromFile("bomb2.png").CGImage),
FromObject(UIImage.FromFile("bomb3.png").CGImage),
FromObject(UIImage.FromFile("bomb4.png").CGImage),
FromObject(UIImage.FromFile("bomb5.png").CGImage),
FromObject(UIImage.FromFile("bomb6.png").CGImage),
FromObject(UIImage.FromFile("bomb7.png").CGImage),
};

Firebase Deep Link short URL

Can the links for Firebase deep links be shortened? Do they have that feature? Links generated are too long and that is not good.
UPDATE
Firebase now supports shorten dynamic links programmatically.
I've faced the same problem getting a long and not user friendly URL when creating a dynamic link programmatically.
The solution I've found is to use the Google URL Shortener API that works brilliant.
That link points to the Java library, I'm using it in Android, but you can do also a simple http request.
I'll post my Android code in case you need it:
private void createDynamicLink() {
// 1. Create the dynamic link as usual
String packageName = getApplicationContext().getPackageName();
String deepLink = "YOUR DEEPLINK";
Uri.Builder builder = new Uri.Builder()
.scheme("https")
.authority(YOUR_DL_DOMAIN)
.path("/")
.appendQueryParameter("link", deepLink)
.appendQueryParameter("apn", packageName);
final Uri uri = builder.build();
//2. Create a shorten URL from the dynamic link created.
Urlshortener.Builder builderShortener = new Urlshortener.Builder (AndroidHttp.newCompatibleTransport(), AndroidJsonFactory.getDefaultInstance(), null);
final Urlshortener urlshortener = builderShortener.build();
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
Url url = new Url();
url.setLongUrl(uri.toString());
try {
Urlshortener.Url.Insert insert=urlshortener.url().insert(url);
insert.setKey("YOUR_API_KEY");
url = insert.execute();
Log.e("url.getId()", url.getId());
return url.getId();
} catch (IOException e) {
e.printStackTrace();
return uri.toString();
}
}
#Override
protected void onPostExecute(String dynamicLink) {
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, getResources().getString(R.string.share_subject));
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, dynamicLink);
startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.share_using)));
Log.e("dynamicLink", dynamicLink);
}
}.execute(null, null, null);
}
Hope it helps!!
The links can be shortened in the Firebase console in the Dynamic Links tab. Tap on 'New Dynamic Link', which gives you an option to create a short link from an existing link.
This can be done programmatically using the Firebase Dynamic Links REST API, for example:
POST https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=api_key
Content-Type: application/json
{
"longDynamicLink": "https://abc123.app.goo.gl/?link=https://example.com/&apn=com.example.android&ibi=com.example.ios"
}
See https://firebase.google.com/docs/dynamic-links/short-links
And I just had to code it for Android - here's the code in case it helps someone:
at the top of the activity:
lateinit private var dynamicLinkApi: FbDynamicLinkApi
private var remoteCallSub: Subscription? = null // in case activity is destroyed after remote call made
in onCreate (not really but to keep it simple, actually you should inject it):
val BASE_URL = "https://firebasedynamiclinks.googleapis.com/"
val retrofit = Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io()))
.build()
dynamicLinkApi = retrofit.create(FbDynamicLinkApi::class.java)
then when it's time to shorten a URL:
remoteCallSub = dynamicLinkApi.shortenUrl(getString(R.string.fbWebApiKey), UrlRo(dynamicLink))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ url -> Log.d("Shortened: $url") },
{ e -> Log.e("APP","Error with dynamic link REST api", e) })
Don't forget to unsubscribe in onDestroy:
override fun onDestroy() {
super.onDestroy()
remoteCallSub?.unsubscribe()
}
And here's the classes you need for the dynamic API:
interface FbDynamicLinkApi {
#POST("v1/shortLinks")
fun shortenUrl(#Query("key") key: String, #Body urlRo: UrlRo): Observable<ShortUrlRo>
}
data class UrlRo(val longDynamicLink: String, val suffix: SuffixRo = SuffixRo())
data class SuffixRo(val option: String = "UNGUESSABLE")
data class ShortUrlRo(val shortLink: String, val warnings: List<WarningRo>, val previewLink: String)
data class WarningRo(val warningCode: String, val warningMessage: String)
This cannot be done programmatically as of the moment.
Try This , its working fine in my case,
https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=[api-key]
{
"dynamicLinkInfo": {
"dynamicLinkDomain": "peg3z.app.goo.gl",
"link": "[Your Long Url Which you want to make short]",
"androidInfo": {
"androidPackageName": "com.xyz"//
},
"iosInfo": {
"iosBundleId": "com.dci.xyz"
}
}
}
'Content-Type: text/plain'

Resources