PayPal doesn't capture payment after subscription is created - React - reactjs

We are using PayPal in order to enable subscription in our platform.
I set up the product and plans inside PayPal and integrated the "PayPal Smart Buttons" using the "react-smart-payment-buttons" package (https://github.com/erksch/react-smart-payment-buttons).
I managed to create the subscription successfully but the first payment is not captured immediately or at all.
When I'm using the PayPal Subscription API in order the see when will be the next billing cycle, it shows a timestamp that has already passed.
For example, this is part of the JSON I got from the API:
"billing_info": {
"outstanding_balance": {
"currency_code": "USD",
"value": "0.0"
},
"cycle_executions": [
{
"tenure_type": "REGULAR",
"sequence": 1,
"cycles_completed": 0,
"cycles_remaining": 12,
"current_pricing_scheme_version": 1
}
],
"next_billing_time": "2019-07-01T10:00:00Z",
"failed_payments_count": 0
},
"auto_renewal": false,
"create_time": "2019-07-01T15:34:02Z"
}
As you can see, the next_billing_time value is before the create_time which doesn't make sense.
What I already did:
After the user approves the subscription, I'm getting the ID of the order and also the subscription. When trying to capture the payment by using the PayPal Payments API and the order id I got, I'm getting back an error.
I checked the status of the created subscription and it shows ACTIVE.
createSubscription(data, actions) {
let plan_id = process.env.REACT_APP_PAY_PAL_BASIC_PLAN_ID;
return actions.subscription.create({
plan_id
});
}
onApprove(data, actions) {
const Http = new XMLHttpRequest();
let url = process.env.REACT_APP_UPGRADE_USER_URL;
Http.open("POST", url);
Http.setRequestHeader("x-access-token", this.state.token);
Http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
Http.send(`plan=${this.state.plan}&subscriptionId=${data.subscriptionID}`);
}
I'll be happy if someone can assist me with this problem.
Thanks in advance.

Related

Stripe integration with angularjs

Currently I am using legacy checkout form of stripe ( open in popup ) in angularjs, and now I want to upgrade the stripe to version 3 with redirectToCheckout flow.
How to integrate Stripe v3 in angularjs with custom product? I can't add all my products in the stripe.
My current code is like :
var stripe = Stripe(data.stripeKey);
stripe
.redirectToCheckout({
lineItems: [
// Replace with the ID of your price
// Here i want to add custom product names and price for that product
{price: "123", quantity: 1},
],
mode: 'payment',
successUrl: 'https://your-website.com/success',
cancelUrl: 'https://your-website.com/canceled',
})
.then(function(result) {
// If `redirectToCheckout` fails due to a browser or network
// error, display the localized error message to your customer
// using `result.error.message`.
});
And also, angularjs is a front end of restapi so, everything is managed by the request and response so, how to implement the charge and capture flow in this? ( can this be achieved without webhooks? )
You can't use 'ad-hoc' prices with the client-only redirectToCheckout. Instead you'd need to introduce a server-side component to create a Checkout Session, where you can use the price_data parameter.

React Docusign Clickwrap Credentials

In my react application, when Im rendering the Docusign clickwrap, I need to supply the accountId and the clickwrapId. Is there a secure way to reference the accountId/clickwrapId without actually putting those values in. I dont want to expose those credentials in my react application
function App() {
React.useLayoutEffect(() => {
docuSignClick.Clickwrap.render({
environment: 'https://demo.docusign.net',
accountId: '...',
clickwrapId: '...',
onMustAgree(agreement) {
// Called when no users have previously agreed by the above client user ID for the most recent required Clickwrap version
},
onAgreed(agreement) {
// Called when either 1) the clientUserId has previously agreed 2) the clientUserId has clicked agree and completed successfully
},
onDeclined(agreement) {
// Called when the clientUserId has declined successfully
}
}, '#ds-clickwrap');
}, []);
return <div id="ds-clickwrap" />
}
Ah, you can use the server-side API to generate an agreement URL instead if that is desired.
POST /clickapi/v1/accounts/.../clickwraps/.../agreements:
Only the clientUserId is required to make this API call. You would do this from your server and then pass the URL from the response to the client.
{
"clientUserId": "..."
}
This would return an agreement URL to then be used in the snippet of JS:
{
...
"status": "created",
"agreementUrl": "https://...."
}
This agreementUrl could then be used in the snippet:
docuSignClick.render({
agreementUrl: '...agreementUrl from REST API response...',
onAgreed...
}, '#ds-clickwrap');

Issue with Google Tag Manager not listening to dataLayer.push

So we are working to implement Enhanced ECommerce tracking for a client. We have done this with a dataLayer push. The web developer has implemented our code as suggested but there have been instances when the dataLayer.push is missed for a few transactions.
I have attached the code below for how it is currently implemented on the Order success page.
There could be some issue with AngularJS implemented on the website and would be grateful if someone can help me to understand how I should implement the GTM code for those missed page views and dataLayer.push codes.
When I am viewing in GTM debug window, there are two instances that happen;
The purchase event will trigger in the dataLayer.push and we get the transaction data in Google Analytics.
The page-view will trigger and no dataLayer.push event will follow. Even though when I check the page source the dataLayer.push codes are available for purchase.
function getCartproducts() {
var dataLayerIndex = new Array();
dataLayerIndex.push({"name": "xxxxxx" , "id" : "xxxxxx" , "price" : "11.00" , "category" : "xxxxx" , "quantity" : 2});
return (JSON.stringify(dataLayerIndex));
}
function getCoupon(){
var couponLayerIndex = new Array();
couponLayerIndex.push('');
return (JSON.stringify(couponLayerIndex[0]));
}
window.dataLayer.push({
'event': 'checkout',
'ecommerce': {
'checkout': {
'actionField': { 'step': 5 },
'products':
JSON.parse(getCartproducts())
}
},
})
window.dataLayer.push({
'event': 'purchase',
'ecommerce': {
'purchase': {
'actionField': {
'id': '269459',
'revenue': 25.65,
'tax': '3.85',
'shipping':'7.50',
'coupon': getCoupon(),
},
'products': JSON.parse(getCartproducts())
}
}
});
I expect the code to trigger a custom purchase event every time the final thank you page is viewed by a user. But as described, we miss quite a number of transactions.

When is ProfileDataRequestContext.RequestedClaimTypes not empty?

I'm trying out IdentityServer4 demo project and I'm adding user claims to ProfileDataRequestContext.IssuedClaims in IProfileService implementation. One thing I've noticed is that there is a context.RequestedClaimTypes collection, which is always empty in any resource/identity/scope configuration variations I've tried. Under what condition does this collection has data?
If in the definition of your ApiResources you define UserClaims, these will then be populated in the context.RequestClaimTypes.
For example:
new ApiResource
{
Name = "TestAPI",
ApiSecrets = { new Secret("secret".Sha256()) },
UserClaims = {
JwtClaimTypes.Email,
JwtClaimTypes.EmailVerified,
JwtClaimTypes.PhoneNumber,
JwtClaimTypes.PhoneNumberVerified,
JwtClaimTypes.GivenName,
JwtClaimTypes.FamilyName,
JwtClaimTypes.PreferredUserName
},
Description = "Test API",
DisplayName = "Test API",
Enabled = true,
Scopes = { new Scope("testApiScore) }
}
Then your ProfileDataRequestContext.RequestClaimTypes will contain these request claims, for your Identity Server to fulfil how you see fit.
I've found out that it if you set client.GetClaimsFromUserInfoEndpoint = true and additional roundtrip is made to /connect/userinfo endpoint and the request has requested value "sub".
Answer: https://github.com/IdentityServer/IdentityServer4/issues/1067
Whenever you request a scope that has associated claims.

Error 404 when creating a calendar with Google Calendar Api v3 using c# .net

I am trying to create a calendar using Google Calendar API v3 if it does not already exist. My implementation successfully retrieves all my calendars and events and can change calendars, but I am struggling with adding a new calendar. This is what I do in order to try to add a new calendar for the user:
...
var calendarService = new CalendarService(_authenticator);
var calendarId = "com.somedomain.somename.1234"; // Some random ID
try {
calendarManager.GetCalendar(calendarId); // No calandar found
} catch(GoogleCalandarServiceProxyException e){
// Ok, so far so good, calendar not found (that is correct) and I am here
var someCalendar = new Google.Apis.Calendar.v3.Data.CalendarListEntry {
Summary = "Some summary!",
Description = "A calendar descr.",
AccessRole = "writer",
BackgroundColor = "#E7323C",
Id = calendarId
};
calendarService.CalendarList.Insert(someCalendar).Fetch(); // Fetch to execute
}
Request generated:
insert # https://www.googleapis.com/calendar/v3/users/me/calendarList?alt=json&prettyPrint=true
RequestError:
Google.Apis.Request.RequestErrorNotFound[404]Errors [Message[Not Found]Location[-] Reason[notFound] Domain[global]]]
Weird thing is that doing a GET at https://www.googleapis.com/calendar/v3/users/me/calendarList?alt=json&prettyPrint=true does not return something, so it should be there.
I hope that there is some awesome guy/girl out there which knows what to do! I'm completely stuck.
Update
Seems like I am receiving the same 404 error on CalendarList Google Api Explorer also:
Url:
https://developers.google.com/google-apps/calendar/v3/reference/calendarList/insert
Request:
POST https://www.googleapis.com/calendar/v3/users/me/calendarList?key={YOUR_API_KEY}
Content-Type: application/json
Authorization: Bearer ya29.AHES6ZQTj-D6uIMOWr_AoFYVvfefsEGcVvLvvMf4aKhgrdvQE25aVw
X-JavaScript-User-Agent: Google APIs Explorer
{
"id": "hastalavista"
}
Response:
404 Not Found
- Show headers - { "error": { "errors": [ {
"domain": "global",
"reason": "notFound",
"message": "Not Found" } ], "code": 404, "message": "Not Found" } }
Does anyone know whether Google have changed the URL for this resource? And if yes, how I change the Google Calendar Api v3 to use the updated url ...?
Okey, my bad:
You can't create a calendar with your own identifier, the purpose of CalendarListEntry.Insert() is to insert a created Calendar into the list of calendars
So to create a new calendar one has to:
Insert a new Calendar: https://developers.google.com/google-apps/calendar/v3/reference/calendars/insert
(DO NOT add id as paramater, this will be automatically created)
Insert the ID of the calendar created in step 1 and insert it into the calendarList: https://developers.google.com/google-apps/calendar/v3/reference/calendarList/insert
I'm still totally confused as to Google's distinction between a Calendar and a CalendarList since the data seems to overlap. Why is a calendar considered a "secondary" calendar.
The next code dit the trick for me, The mentioned reference is Java not .Net and, as usual ther e are some anoying differences...
private bool createCalendar()
{
// use Google.Apis.Calendar
Calendar calendar = new Calendar();
calendar.Summary = "MyNewCalendar";
calendar.Description = "Your new Calendar";
calendar.Location = "Aadorp";
calendar.TimeZone = "Europe/Amsterdam";
try
{
// Not inserting in CalendarList but in Calendar!
calendarService.Calendars.Insert(calendar).Execute();
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
return false;
}
return true;
}

Resources