The problem is that I cannot pass the paymentID variable that the PayPal script needs from PHP to JS. (Either this or the PHP script never runs).
I am following the steps here: https://developer.paypal.com/docs/integration/direct/express-checkout/integration-jsv4/advanced-integration/#set-up-the-payment
and I'm stuck on step 4.
I've used the code from this tutorial: http://paypal.github.io/PayPal-PHP-SDK/sample/doc/payments/CreatePaymentUsingPayPal.html
Here is the HTML:
{% extends 'layout/master.twig' %}
{% block title %} {{ parent() }}PayPal {% endblock title %}
{% block head %}
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
{% endblock %}
{% block header %} Testing PayPal {% endblock header %}
{% block content %}
<div id="paypal-button"></div>
{% endblock content %}
{% block scripts %}
<script>
paypal.Button.render({
env: 'sandbox', // Optional: specify 'production' environment
payment: function(resolve, reject) {
var CREATE_PAYMENT_URL = 'http://patch-request.app/paypal/payment/create';
paypal.request.get(CREATE_PAYMENT_URL)
.then(function(data) {
alert(data);
console.log(data);
resolve(data.paymentID);
})
.catch(function(err) {
alert(data);
console.log(data);
reject(err);
});
},
onAuthorize: function(data) {
// Note: you can display a confirmation page before executing
var EXECUTE_PAYMENT_URL = 'http://patch-request.com/paypal/execute-payment';
paypal.request.post(EXECUTE_PAYMENT_URL,
{ paymentID: data.paymentID, payerID: data.payerID })
.then(function(data) { /* Go to a success page */ })
.catch(function(err) { /* Go to an error page */ });
}
}, '#paypal-button');
</script>
{% endblock scripts %}
And here is the script I'm trying to run:
public function create_payment ()
{
$payer = new Payer();
$payer->setPaymentMethod("paypal");
$item1 = new Item();
$item1->setName('Ground Coffee 40 oz')
->setCurrency('USD')
->setQuantity(1)
->setSku("123123")// Similar to `item_number` in Classic API
->setPrice(7.5);
$item2 = new Item();
$item2->setName('Granola bars')
->setCurrency('USD')
->setQuantity(5)
->setSku("321321")// Similar to `item_number` in Classic API
->setPrice(2);
$itemList = new ItemList();
$itemList->setItems([$item1, $item2]);
$details = new Details();
$details->setShipping(1.2)
->setTax(1.3)
->setSubtotal(17.50);
$amount = new Amount();
$amount->setCurrency("USD")
->setTotal(20)
->setDetails($details);
$transaction = new Transaction();
$transaction->setAmount($amount)
->setItemList($itemList)
->setDescription("Payment description")
->setInvoiceNumber(uniqid());
// $baseUrl = getBaseUrl();
$baseUrl = "http://patch-request.app";
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl("$baseUrl/ExecutePayment.php?success=true")
->setCancelUrl("$baseUrl/ExecutePayment.php?success=false");
$payment = new Payment();
$payment->setIntent("sale")
->setPayer($payer)
->setRedirectUrls($redirectUrls)
->setTransactions([$transaction]);
$request = clone $payment;
try
{
$payment->create($this->apiContext); //$payment is a JSON
}
catch (Exception $ex)
{
echo 'Sth went wrong';
}
$approvalUrl = $payment->getApprovalLink();
return json_encode(['paymentID' => $payment->id]);
}
Any ideas?
I've got no idea what templating system you're using but you could try this
{% block head %}
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
// add it here
<script>
window.paymentID = '<?= getPaymentID(); ?>'; // you need to implement this
</script>
{% endblock %}
Now you can access window.paymentID anywhere in you other JS
Related
detail.html
{% if request.user.is_authenticated %}
<form class="like-forms d-inline" data-book-id="{{ book.pk }}" data-review-id="{{ review.pk }}">
{% csrf_token %}
<h4>
{% if request.user in review.like_users.all %}
<button type="submit" id="btn-like-{{ review.pk }}" class="btn-none bi bi-emoji-heart-eyes"></button>
{% else %}
<button type="submit" id="btn-like-{{ review.pk }}" class="btn-none bi bi-emoji-angry"></button>
{% endif %}
</h4>
</form>
{% endif %}
<!-js-->
<script>
const likeForms = document.querySelectorAll('.like-forms')
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value
likeForms.forEach((form) => {
form.addEventListener('submit', function (event) {
event.preventDefault()
const reviewId = event.target.dataset.reviewId
const bookId = event.target.dataset.bookId
axios({
method: 'post',
url: `/detail/${bookId}/like/${reviewId}/`,
headers: {'X-CSRFToken': csrfToken},
})
.then(response => {
const isLiked = response.data.isLiked
const likeBtn = document.querySelector(`#btn-like-${reviewId}`)
console.log(isLiked)
if (isLiked === true) {
likeBtn.classList.add('bi-emoji-heart-eyes')
likeBtn.classList.remove('bi-emoji-angry')
} else {
likeBtn.classList.add('bi-emoji-angry')
likeBtn.classList.remove('bi-emoji-heart-eyes')
}
})
.catch(error => {
console.log(error)
})
})
})
</script>
urls.py
path("detail/<int:book_pk>", views.detail, name="detail"),
path("detail/<int:book_pk>/like/<int:review_pk>", views.like, name="like"),
.....
views.py
def detail(request, book_pk):
reviews = Review.objects.order_by("-pk")
book = Book.objects.get(pk=book_pk)
context = {
"reviews": reviews,
"book": book,
}
return render(request, "review/detail.html", context)
def like(request, book_pk, review_pk):
review = Review.objects.get(pk=review_pk)
book = Book.objects.get(pk=book_pk)
if review.like_users.filter(pk=request.user.pk).exists():
review.like_users.remove(request.user)
is_liked = False
else:
review.like_users.add(request.user)
is_liked = True
data = {
"isLiked": is_liked,
}
return JsonResponse(data)
I got a 404 not found error while writing code for a "like" async function.
data-book-id="{{ book.pk }}" data-review-id="{{ review.pk }} in the form
I seem to get pk values for books and book reviews, but I don't know what causes the 404 error.
Console error message : POST http://localhost:8000/detail/1/like/2/ 404 (Not Found)
I am running this on localhost (http://localhost:8000/)
Thanks for reading..!
I am trying to create a if statement in my Django view that detects when I am redirected to my complete order url. I want to do this because I would like to change my Django model Order 'complete' field to true. My redirect is coming from a javascript function in my paypal intergration.
checkout.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<h1>Checkout</h1>
<div class='container'>
<div class='row'>
<div class='col-6'>
<form action="" method='post' id='payement-form'>
{% csrf_token %}
<!-- {{ form|crispy }} -->
<div class='col-12' id='paypal-button-container'></div>
</form>
<script
src="https://www.paypal.com/sdk/js?client-id="> // Required. Replace YOUR_CLIENT_ID with your sandbox client ID.
</script>
<script>
function redirect() {
var url = "{% url 'complete-order' %}"
window.location.href = url
}
paypal.Buttons({
createOrder: function (data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: '0.01'
}
}]
});
},
onApprove: function (data, actions) {
// This function captures the funds from the transaction.
return actions.order.capture().then(function (details) {
// This function is the redirect
redirect()
alert('Transaction completed by ' + details.payer.name.given_name);
});
}
}).render('#paypal-button-container');
</script>
</div>
{% endblock content %}
views.py
#login_required(login_url='login')
def checkout(request):
order = Order.objects.get(user=request.user, complete=False)
context = {
'order': order
}
return render(request, 'videogames/checkout.html', context)
#login_required(login_url='login')
def paymentComplete(request):
order = Order.objects.get(user=request.user, complete=True)
context = {
'order': order
}
return render(request, 'videogames/complete.html', context)
There are many ways that should be selected according to your project.
before redirection, in the view , call a link with Ajax to change the status
#login_required(login_url='login')
def paymentSetComplete(request):
order = Order.objects.get(id=request.payment_id=,user=request.user, complete=False)
order.complete=True
order.save() # or update directly
return
Change the status when the request to load the complate page was sent to django
I do not know what measures you have taken to secure and prevent the fake purchases
But know that users can repeat requests that come to the server
Trying to get Bootoast to work on my website, where I try to pass a message. You can see the code below. Using Django-bootstrap for front-end.
BASE.HTML
<script srs="https://unpkg.com/bootoast#1.0.1/dist/bootoast.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/bootoast#1.0.1/dist/bootoast.min.css">
<script>
function toast(message, type) {
bootoast.toast({
position: 'bottom-center',
message,
type,
});
}
{% if messages %}
{% for message in messages %}
toast('{{ message }}', '{{ message.tags }}')
{% endfor %}
{% endif %}
</script>
VIEWS.PY
#login_required(login_url="/sign-in/?next=/customer/")
def profile_page(request):
user_form = forms.BasicUserForm(instance=request.user)
customer_form = forms.BasicCustomerForm(instance=request.user.customer)
if request.method == "POST":
user_form = forms.BasicUserForm(request.POST, instance=request.user)
customer_form = forms.BasicCustomerForm(request.POST, request.FILES, instance=request.user.customer)
if user_form.is_valid() and customer_form.is_valid():
user_form.save()
customer_form.save()
messages.success(request, 'Your profile has been updated')
return redirect(reverse('customer:profile'))
return render(request, 'customer/profile.html', {
"user_form": user_form,
"customer_form": customer_form
})
So the error I'm getting is this:
(index):197 Uncaught ReferenceError: bootoast is not defined
I'm blind or isn't this defined?
<script srs="https://unpkg.com/bootoast#1.0.1/dist/bootoast.min.js"></script>
Should have been
<script src="https://unpkg.com/bootoast#1.0.1/dist/bootoast.min.js"></script>
I am a little bit stuck on my Symfony code.
Let me explain,
I have a todo-list table in my database containing :
An ID called : id
A name field called : todo
And 3 others fields that don't matter : "completed", "created_at", "updated_at".
Before going further : here is my codes,
The concerned Controller :
/**
* #Route("/todos/delete/{id}", name="todo.delete", methods={"POST"})
* #param Todo $todo
* #param ObjectManager $manager
* #param Request $request
* #return \Symfony\Component\HttpFoundation\RedirectResponse
*/
public function delete(Todo $todo, ObjectManager $manager, Request $request)
{
$manager->remove($todo);
$manager->flush();
if ( $request->isXmlHttpRequest()) {
return $this->redirectToRoute('todo.home', [
'id' => $todo->getId()
]);
}
throw $this->createNotFoundException('The todo couldn\'t be deleted');
}
The view :
{% extends 'base.html.twig' %}
{% block title %}Todos{% endblock %}
{% block content %}
<br>
<form action="{{ path('todo.create') }}" method="post">
<input type="hidden" name="token" value="{{ csrf_token('todo-create') }}"/>
<label for="todo">Todo</label>
<input type="text" id="todo" name="todo" class="form-control input-group-lg" placeholder="Create a new todo">
</form><br>
{% for todo in todos %}
{{ todo.todo }}
Update
x
{% if todo.completed %}
Completed !
{% else %}
Mark as completed
{% endif %}
<hr>
{% endfor %}
{% endblock %}
We focus on :
x
The JavaScript :
$(document).ready(function () {
$('.js-delete-todo').on('click', function (e) {
e.preventDefault();
var url = $(this).attr('href');
delTodo(url);
function delTodo(url) {
$.ajax({
type: "POST",
url: url
}).done(function (data) {
$('#id').remove();
}).fail(function () {
alert('Could not be deleted');
});
}
});
});
Actually,
Everything seems to work : it does a POST ajax request, and delete the row in my table in my database.
The only issue is that I have to hit F5 to see it.
How can I make it work without reloading the page nor hitting the F5 hotkey?
In your symfony code you should return JSON format like here.
Wrap your todo in container like this
{% for todo in todos %}
<div id="todo-{{todo.id}}">
// your todo staff here
</div>
{% endfor %}
Then change your javascript to
function delTodo(url) {
$.ajax({
type: "POST",
url: url
}).done(function (data) {
var id = JSON.parse(data).id;
$('#todo-' + id).remove();
}).fail(function ()
alert('Could not be deleted');
});
}
I'm trying to make an infinite Scrolling in Ajax.
I really don't know what is missing.
Html Index:
<div class="container">
<!-- Menu -->
{% include '::announce/menu.html.twig' %}
{% for announce in announces|slice(0, 4) %}
<!-- Announce Preview -->
{% include '::announce/' ~ game ~ '/preview.html.twig' %}
{% endfor %}
</div>
<div id="content"> loop content </div>
<nav id="pagination">
<p>Page 2</p>
</nav>
{% endblock %}
{% block javascripts %}
<script src="{{ asset('js/jquery-ias.min.js') }}"></script>
{% endblock %}
My controller index:
public function indexAction(Request $request, $game)
{
$em = $this->getDoctrine()->getManager();
$announces $em->getRepository('PlatformBundle:Announce')->byGame($game);
return $this->render('announce/index.html.twig', array(
'announces' => $announces,
'game' => $game
));
}
With this i have my index page with 4 announce
Now i show you my code for scrolling and adding more announce
Ajax File:
$(window).scroll(function () {
if($(window).scrollTop() + $(window).height()>= $(document).height()){
getmoredata();
}
})
function getmoredata() {
$.ajax({
type: "GET",
url: "{{ path('announce_page', {'id': '2', 'game': game}) }}",
dataType: "json",
cache: false,
success: function (response) {
$("#content").append(response.classifiedList);
$('#spinner').hide();
console.log(response);
},
error: function (response) {
console.log(response);
}
});
}
And this is the controller for page:
public function pageAction(Request $request, $game)
{
$em = $this->getDoctrine()->getManager();
$announces = $em->getRepository('PlatformBundle:Announce')->byGame($game);
$list = $this->renderView('announce/result.html.twig', array(
'announces' => $announces,
'game' => $game
));
$response = new JsonResponse();
$response->setData(array('classifiedList' => $list));
return $response;
}
Last code, it's the html content for ajax (result.html.twig)
{% for announce in announces|slice(4, 4) %}
<!-- Affichage Annonce -->
{% include '::announce/' ~ game ~ '/preview.html.twig' %}
{% endfor %}
For resume, i have my index with 4 announce, when i scroll in bottom, i have a positive ajax request without error. But nothing appear after the 4 announce.
If i go to announce page 2 directly with pagination, i can see 4 other announce. So my routing is working but something don't works in ajax code i think.
Any idea? :)
Thanks