问题描述
我在我的 Django 项目中使用 Braintree Drop-in。当我在开发环境 (manage.py runserver) 中使用它时,它完全正常工作。但是当我在弹性 beantalk 上访问相同的内容时,我收到错误“只能将 str(而不是“元组”)连接到 str”。以下是我的代码。
extras.py
from django.conf import settings
import braintree
gateway = braintree.BraintreeGateway(
braintree.Configuration(
braintree.Environment.SandBox,merchant_id=settings.BT_MERCHANT_ID,public_key=settings.BT_PUBLIC_KEY,private_key=settings.BT_PRIVATE_KEY,)
)
def generate_client_token():
return gateway.client_token.generate()
def transact(options):
return gateway.transaction.sale(options)
def find_transaction(id):
return gateway.transaction.find(id)
信号.py
from django.db.models.signals import post_save
from django.dispatch import receiver
#from django.conf import settings
from invoices.extras import gateway
@receiver(post_save,sender=User)
def create_phone(sender,instance,created,**kwargs):
if created:
gateway.customer.create({
"first_name": instance.first_name,"last_name": instance.last_name,"email": instance.email,"phone": instance.phone_number,"id": instance.id,})
views.py
@login_@R_404_3889@()
def customer_invoice_view(request,ticket_id):
ticket = get_object_or_404(Ticket,pk=ticket_id)
customer = ticket.customer
client_token = gateway.client_token.generate({"customer_id": str(customer.id)})
invoice = ticket.invoice
if request.method == 'POST':
result = transact({
'amount': invoice.amount_payable,'payment_method_nonce': request.POST['payment_method_nonce'],'options': {
"submit_for_settlement": True
}
})
if result.is_success or result.transaction:
invoice.is_paid = True
invoice.save()
ticket = invoice.ticket
ticket.status ='Payment Made'
ticket.paid = True
ticket.save()
return redirect(customer_invoice_view,ticket_id=ticket.id)
else:
for x in result.errors.deep_errors:
messages.info(request,x)
return redirect(customer_invoice_view,ticket_id=ticket.id)
context = {
'ticket' : ticket,'invoice' : invoice,'client_token' : client_token,}
return render(request,'invoice/ticket_invoice_view.html',context)
ticket_invoice_view.html
<div class="p-3">
{% if not invoice.is_paid%}
<div class="row no-gutters">
<div class="mb-2">
<ul>
{% for message in messages %}
<li class="text-dark">{{message}}</li>
{% endfor %}
</ul>
</div>
</div>
<div class="row no-gutters my-4">
<form id="payment-form" method="post" action="" autocomplete="off">
{% csrf_token %}
<section>
<div class="bt-drop-in-wrapper">
<div id="bt-dropin"></div>
</div>
</section>
<input type="hidden" id="nonce" name="payment_method_nonce" />
<button class="btn-success" type="submit" id="submit-button"><span>Make Payment</span></button>
</form>
</div>
{% endif %}
</div>
<script src="https://js.braintreegateway.com/web/dropin/1.25.0/js/dropin.min.js"></script>
<script>
var form = document.querySelector('#payment-form');
var client_token = '{{ client_token }}';
braintree.dropin.create({
authorization: client_token,container: '#bt-dropin',paypal: {
flow: 'vault'
}
},function (createErr,instance) {
form.addEventListener('submit',function (event) {
event.preventDefault();
instance.requestPaymentMethod(function (err,payload) {
if (err) {
console.log('Error',err);
return;
}
// Add the nonce to the form and submit
document.querySelector('#nonce').value = payload.nonce;
form.submit();
});
});
});
</script>
当我在本地运行项目 (manage.py runserver) 时,它工作正常,当创建用户时,会在 Braintree 中创建一个客户,用户 ID 为客户 ID。而且付款也得到了处理,没有任何问题。但是当通过弹性豆茎完成同样的操作时,我收到错误“只能将 str(而不是“元组”)连接到 str”。
以下是回溯。
TypeError: can only concatenate str (not "tuple") to str
File "django/core/handlers/exception.py",line 47,in inner
response = get_response(request)
File "django/core/handlers/base.py",line 179,in _get_response
response = wrapped_callback(request,*callback_args,**callback_kwargs)
File "django/contrib/auth/decorators.py",line 21,in _wrapped_view
return view_func(request,*args,**kwargs)
File "accounts/decorators.py",line 20,in wrapper_func
return view_func(request,**kwargs)
File "invoices/views.py",line 33,in customer_invoice_view
client_token = gateway.client_token.generate({"customer_id": str(customer.id),},)
File "braintree/client_token_gateway.py",line 26,in generate
response = self.config.http().post(self.config.base_merchant_path() + "/client_token",params)
File "braintree/configuration.py",line 113,in base_merchant_path
return "/merchants/" + self.merchant_id
这是 Post Save Signal Error 的回溯。
TypeError: can only concatenate str (not "tuple") to str
File "django/core/handlers/exception.py",**callback_kwargs)
File "django/views/generic/base.py",line 70,in view
return self.dispatch(request,**kwargs)
File "django/utils/decorators.py",line 43,in _wrapper
return bound_method(*args,**kwargs)
File "django/views/decorators/debug.py",line 89,in sensitive_post_parameters_wrapper
return view(request,**kwargs)
File "allauth/account/views.py",line 230,in dispatch
return super(SignupView,self).dispatch(request,line 75,in dispatch
request,**kwargs
File "allauth/account/views.py",line 204,in dispatch
return super(CloseableSignupMixin,**kwargs)
File "django/views/generic/base.py",line 98,in dispatch
return handler(request,line 102,in post
response = self.form_valid(form)
File "allauth/account/views.py",line 246,in form_valid
self.user = form.save(self.request)
File "allauth/account/forms.py",line 419,in save
adapter.save_user(request,user,self)
File "allauth/account/adapter.py",in save_user
user.save()
File "django/contrib/auth/base_user.py",line 67,in save
super().save(*args,**kwargs)
File "django/db/models/base.py",line 754,in save
force_update=force_update,update_fields=update_fields)
File "django/db/models/base.py",line 803,in save_base
update_fields=update_fields,raw=raw,using=using,File "django/dispatch/dispatcher.py",in send
for receiver in self._live_receivers(sender)
File "django/dispatch/dispatcher.py",in <listcomp>
for receiver in self._live_receivers(sender)
File "accounts/signals.py",line 30,in create_phone
"id": instance.id,File "braintree/customer_gateway.py",line 24,in create
return self._post("/customers",{"customer": params})
File "braintree/customer_gateway.py",line 79,in _post
response = self.config.http().post(self.config.base_merchant_path() + url,in base_merchant_path
return "/merchants/" + self.merchant_id
如果有人能帮我解决,我将不胜感激。
解决方法
谢谢你这么详细的问题!
错误就是线索。它说你试图连接一个元组和一个不允许的字符串。由于该行是 return "/merchants/" + self.merchant_id
并且我没有看到表示无关元组的逗号,这意味着问题出在 self.merchant_id
上。这似乎是从 settings.BT_MERCHANT_ID
设置的。我的预感是 settings.BT_MERCHANT_ID
在它的末尾有一个逗号,它不应该导致它成为一个元组。
例如:
x = 1
导致 x
被设置为整数 1
。但是
x = 1,
导致 x
被设置为元组 (1,)
。这是一个痛苦的陷阱,最终会咬住每个 Python 开发人员。