Как создать заказ в админке после завершения оплаты
Я делаю сайт, где вы покупаете товары и платите через PayPal. Я закончил с частью PayPal, теперь я пытаюсь получить ситуацию, когда после завершения оплаты в checkout купленный товар попадает в заказы в админке.
Это модель заказа.py:
class Order (models.Model):
product = models.ForeignKey(Coinpack, max_length=200, null=True, blank=True, on_delete = models.SET_NULL)
created = models.DateTimeField(auto_now_add=True)
вот часть кода PayPal в файле checkout.html:
<script src="https://www.paypal.com/sdk/js?client-id=idexample¤cy=USD"></script>
<script>
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
const csrftoken = getCookie('csrftoken');
var total = '{{checkout.price}}'
var productId = '{{checkout.id}}'
function completeOrder(){
var url = "{% url 'complete' %}"
fecth(url, {
method: 'POST',
headers:{
'content-type':'aplication/json',
'X-CSRFToken': csrftoken,
},
body: JSON.stringify({'productId':productId})
})
}
// Render the PayPal button into #paypal-button-container
paypal.Buttons({
// Set up the transaction
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: total
}
}]
});
},
// Finalize the transaction
onApprove: function(data, actions) {
return actions.order.capture().then(function(orderData) {
// Successful capture! For demo purposes:
completeOrder()
console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
var transaction = orderData.purchase_units[0].payments.captures[0];
alert('Transaction '+ transaction.status + ': ' + transaction.id + '\n\nSee console for all available details');
});
}
}).render('#paypal-button-container');
</script>
</body>
</html>
и вот views.py
def paymentComplete(request):
body = json.loads(request.body)
print('BODY:', body)
product = checkout.objects.get(id=body['productId'])
Order.objects.create(
product=product
)
return JsonResponse('Payment completed!', safe=False)
Я следовал учебнику, но учебник и моя версия отличаются, поэтому я запутался и не знаю, что делать, пожалуйста, помогите.
У меня также завершена оплата в urls.py:
path('complete/', views.paymentComplete, name="complete"),
Спасибо.
Не используйте actions.order.create() / actions.order.capture() для создания и захвата заказа на стороне клиента, если вы затем собираетесь выполнять операции на стороне сервера с выполненным платежом. Эти JS-функции предназначены для простых случаев использования, а не для того, что вы пытаетесь сделать.
Вместо этого используйте API PayPal v2/checkout/orders и сделайте два маршрута (пути url) на вашем сервере, один для 'Create Order' и один для 'Capture Order'. Вы можете использовать (недавно устаревший) Checkout-PHP-SDK для API вызовов маршрутов к PayPal, или вашу собственную реализацию HTTPS, сначала получающую токен доступа, а затем выполняющую вызов. Оба этих маршрута должны возвращать/выводить только JSON данные (без HTML или текста). Внутри второго маршрута, когда API захват успешен, вы должны убедиться, что сумма была правильной, и сохранить полученные платежные данные в вашей базе данных (в частности purchase_units[0].payments.captures[0].id
, который является идентификатором транзакции PayPal) и выполнить любую необходимую бизнес-логику (например, зарезервировать продукт или отправить электронное письмо) непосредственно перед пересылкой возвращаемого JSON фронтенду. В случае ошибки также передайте детали JSON, так как фронтенд должен обрабатывать такие случаи.
Сопрягите эти 2 маршрута с этим фронтенд-потоком утверждения: https://developer.paypal.com/demo/checkout/#/pattern/server . (Если вам нужно отправить какие-либо дополнительные данные с клиента на сервер, например, массив элементов или выбранные опции, добавьте body
параметр в fetch со значением, которое является строкой JSON или объектом)