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.
Related
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');
I want to search in all pages, but my code only search in the current page.
For example I'm in the page 2/5 when I type the name of a tourist who is present in this page it shows me the data,
but when I type a tourist which is in the page 4/5 it not show me anything.
I'm using Laravel in backend.
Here's the backend code :
$tourists = Tourist::where('hotel_id', $request->hotel_id)->orderBy('created_at', 'DESC')->paginate(10);
return $toursits;
Frontend code :
this.state = {
activePage: 1,
tourists: []
}
async componentDidMount() {
await this.getTourists();
}
async getTourists() {
let response = await callApi('tourists/paginate', { page: this.state.activePage, hotel_id: this.context.hotel_id[0] });
this.setState({ tourists: response.data, perPage: response.meta.per_page, total: response.meta.total, lastPage: response.meta.last_page });
}
Render method:
{this.state.tourists
.filter(x => new RegExp (this.state.first_name, 'i').test(x.first_name)
.map((tourist, i) =>
<tr>
<td>{tourist.first_name}</td>
</tr>)}
You are getting a paginated list of results from the backend but you are implementing the search functionality on the frontend.
When you first go to your page, you get the first 10 results from your server. At the time, your React application as no idea that there are more results to be parsed and can only "see" the 10 paginated results your are sending from your server. By filtering these results you will not be able to get any other result which was not sent by the server in the first place.
You have 2 solutions:
Implement the pagination client-side,
Implement the search functionality server-side
Given that you already implemented pagination on the server I assume that you have a lot of results and that sending all of them at once would not be practical.
This leaves us with option n°2. Adding to your code example, you could do something like:
$tourists = Tourist::where('hotel_id', $request->hotel_id)
// Add this to filter results by first_name
->where('first_name', 'like', "%{$request->first_name}%"))
->orderBy('created_at', 'DESC')->paginate(10);
return $tourists;
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.
I'm building an ordering app, where I do the backend with Laravel and the front end with both ReactJS and React Native
I want real-time updates whenever a customer posts an order and whenever an order gets updated.
Currently, I managed to get WebSocket running that uses the pusher API using devmarketer his tutorial.
I'm successful in echoing the order in the console, but now I want to access the channel using my react app
And at this step is where I am facing difficulties.
As I'm unsure how to create a route that is accessible to both my apps and how to access the channel through this route.
The official laravel documentation gives an example of how to access pusher but not how to connect to it with for example an outside connection (example: my react native app)
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'rapio1',
host: 'http://backend.rapio',
authEndpoint: 'http://backend.rapio/broadcasting/auth',
auth: {
headers: {
// Authorization: `Bearer ${token}`,
Accept: 'application/json',
},
}
// encrypted: true
});
window.Echo.channel('rapio.1').listen('OrderPushed', (e) =>{
console.log(e.order)
})
So my question is how can I access a broadcasting channel on my React apps?
ADDED BACKEND EVENT
class OrderPushed implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $neworder;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Order $neworder)
{
$this->neworder = $neworder;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
//return new Channel('Rapio.'.$this->neworder->id);
return new Channel('Rapio');
}
public function broadcastWith()
{
return [
'status' => $this->neworder->status,
'user' => $this->neworder->user->id,
];
}
}
Are you using the broadcastAs() method on the backend?
It's important to know this in order to answer your question properly because if you are, the Laravel echo client assumes that the namespace is App\OrderPushed.
When using broadcastAs() you need to prefix it with a dot, to tell echo not to use the namespacing so in your example, it would be:
.listen('.OrderPushed')
Also, you don't need to do any additional setup on the backend in order for each client application to connect to the socket server unless you want to have a multi-tenancy setup whereby different backend applications will make use of the WebSockets server.
I also use wsHost and wsPort instead of just host and port, not sure if that makes a difference though
If you can access the data on the frontend by simply console.log'ing to the console you should already be most of the way there.
The way you would actually get the data into your react components depends on if you're using a state management library (such as redux) or just pure react.
Basically, you would maintain a local copy of the data on the frontend and then use the Echo events to update that data. For example, you could have a list of orders in either redux, one of your react components, or somewhere else, that you could append to and modify based on creation, update, and deletion events.
I would personally create an OrderCreated, OrderUpdated, and OrderDeleted event on the backend that would contain the given order model.
class OrdersList extends React.Component {
componentDidMount() {
this.fetchInitialDataUsingHttp();
//Set up listeners when the component is being mounted
window.Echo.channel('rapio.1').listen('OrderCreated', (e) =>{
this.addNewOrder(e.order);
}).listen('OrderUpdated', (e) =>{
this.updateOrder(e.order);
}).listen('OrderDeleted', (e) =>{
this.removeOrder(e.order);
});
}
componentWillUnmount() {
//#TODO: Disconnect echo
}
}
I am follow this tutorial in order to get a transactions/accounts detail from the plaid API. Plaid'd quickstart guide user ejs in order to send to the server with the onSuccess function. How do I create this token using ionic?
Plaid quick guide also suggests that we use code blow
var linkHandler = Plaid.create({
env: 'sandbox',
clientName: 'Client Name',
key: '<PUBLIC_KEY>',
product: ['auth', 'transactions'],
token: '<GENERATED_PUBLIC_TOKEN>',
onSuccess: function(public_token, metadata) {
// You do not need to repeat the /item/public_token/exchange
// process when a user uses Link in update mode.
// The Item's access_token has not changed.
},
and also suggest to use this code
// Create a public_token for use with Plaid Link's update mode
client.createPublicToken(ACCESS_TOKEN, (err, result) => {
// Handle err
// Use the generated public_token to initialize Plaid Link in update
// mode for a user's Item so that they can provide updated credentials
// or MFA information
const publicToken = result.public_token;
});
in order to create a public token and get the access token. I can't use this function because I'm getting an error 'Plaid and/or client is not defined
How do I create this public token using Ionic front end and node back end?
What's the workflow here?
Thanks in advance
On the server side, you'll need to initialize the Plaid node client library first. You will also want to make an exchange token call, to exchange the public_token from Link for an API access_token. You'll then save the access_token and use it to retrieve transaction and account data:
// Initialize the Plaid API client with your API keys (https://dashboard.plaid.com/account/keys)
// Use plaid.environments.production, plaid.environments.development, or plaid.environments.sandbox
const plaid = require('plaid');
const client = new plaid.Client(client_id, secret, public_key, plaid.environments.sandbox);
client.exchangePublicToken(PUBLIC_TOKEN, function(error, tokenResponse) {
if (error != null) {
var msg = 'Could not exchange public_token!';
console.log(msg + '\n' + error);
}
const ACCESS_TOKEN = tokenResponse.access_token;
const ITEM_ID = tokenResponse.item_id;
console.log('Access Token: ' + ACCESS_TOKEN);
console.log('Item ID: ' + ITEM_ID);
// Now retrieve transactions or account information with the access_token
});
For the client-side in your Ionic app, you'll need to include the link-initialize.js script before calling Plaid.create. Specifically:
<script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js">
</script>
Here's a full client-side HTML example:
<button id="link-button">Link Account</button>
<script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<script type="text/javascript">
var handler = Plaid.create({
clientName: 'Plaid Walkthrough Demo',
env: 'sandbox',
key: '[PUBLIC_KEY]', // public_key is at https://dashboard.plaid.com/account/keys
product: ['auth'],
onLoad: function() {
// Optional, called when Link loads
},
onSuccess: function(public_token, metadata) {
// Send the public_token to your app server.
// The metadata object contains info about the institution the
// user selected and the account ID, if `selectAccount` is enabled.
$.post('/get_access_token', {
public_token: public_token,
});
},
onExit: function(err, metadata) {
// The user exited the Link flow.
}
});
</script>
An Angular library was recently created: click here and here
I had some issues implementing Plaid successfully at first; these tips should help:
Implement the library as shown in the second link above. Make sure for step two you import in your app.module.ts file. Don't use the jQuery provided in the documentation.
Using this library, a button will be automatically created within the Angular element <mr-ngx-plaid-link-button>. This button will act as a submit button unless you use DOM or other methods to change it to type button on ngAfterViewInit()
All five events in step three are listeners for various events. The onSuccess() callback will return the public token - only after you have (a) successfully submitted bank credentials (user_good / pass_good on Sandbox) and (b) clicked the Continue button to exit the Plaid Link