Am trying to verify user transaction on paystack. After a user makes payment, I want what to append the reference to the Api URL to check if the payment was succcessful. If the payment is successful then save the model.
import requests
from django.conf import settings
class Paystack:
PAYSTACK_SECRET_KEY = "sk_test_3cd83d64a1de3a7334bdad47e3fdfa01bf16a059"
base_url = "https://api.paystack.co"
def verify_payment(self, reference, *args, **kwargs):
path = f'/transaction/verify/{reference}'
headers ={
"Authorization": f"Bearer {self.PAYSTACK_SECRET_KEY}",
"Content-Type":'application/json'
}
url = self.base_url + path
response = requests.get(url, headers=headers)
if response.status_code == 200:
response_data = response.json()
return response_data['status'], response_data['data']
response_data = response.json()
return response_data["status"], response_data["message"]
def process_payment(request, slug, amount, award, votes):
reason = request.GET.get('reason')
transaction_id = request.GET.get('reference')
amount = (str(int(amount) / 100))
paystack = Paystack()
status = paystack.process_payment(self.reference)
if status == "success":
transaction = SuccessfulTransactionHistory(
nominee_name=slug,
transaction_id=transaction_id,
amount=amount,
award=award
)
transaction.save()
Nomination.objects.filter(slug=slug).update(votes=F('votes') + votes)
Award.objects.filter(slug=award).update(amount=F('amount') + amount)
return redirect('vote:paymentsuccess', slug=slug)
else:
context = {
'error': reason
}
transaction = FailedTransactionHistory(
nominee_name=slug,
transaction_id=transaction_id,
amount=amount,
award=award
)
transaction.save()
return render(request, 'payment_error.html', context=context)
This is the eeror i get
AttributeError at /payment/Paul/000000000020/halotech-award-8/1/
'Paystack' object has no attribute 'process_payment'
verify_payment vs process_payment.
def verify_payment(self, reference, *args, **kwargs):
status = paystack.process_payment(self.reference)
Related
I would like to write an api with django rest framework, I got some issues with my callback function.
I can get the access code, but how to give it to my app?
This is my callback function :
#api_view(['GET'])
def callback(request):
if request.method == 'GET':
code = request.GET.get("code")
encoded_credentials = base64.b64encode(envi.SECRET_ID.encode() + b':' + envi.SECRET_PASS.encode()).decode("utf-8")
token_headers = {
"Authorization": "Basic " + encoded_credentials,
"Content-Type": "application/x-www-form-urlencoded"
}
token_data = {
"grant_type": "authorization_code",
"code": code,
"redirect_uri": "http://127.0.0.1:800/callback"
}
test = "test :" + code
return JsonResponse(test, safe=False)
And this is my view where I try to do some stuff (I use spotify's API, with spotipy), I need to get the users name or mail :
#api_view(['GET'])
#permission_classes([permissions.IsAuthenticated])
def test(request):
if request.method == 'GET':
test = "test " + request.user.username
scope = "user-read-private"
sp = getScope(scope)
print(sp.current_user())
urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu'
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=envi.SECRET_ID, client_secret=envi.SECRET_PASS, redirect_uri=envi.SPOTIPY_REDIRECT_URI))
artist = sp.artist(urn)
print(artist)
user = sp.current_user()
return JsonResponse(user, safe=False)
def getScope(spotipyScope):
token = SpotifyOAuth(scope=spotipyScope,client_id=envi.SECRET_ID, client_secret=envi.SECRET_PASS, redirect_uri=envi.SPOTIPY_REDIRECT_URI)
spotifyObject = spotipy.Spotify(auth_manager= token)
return spotifyObject
When I do a get on 127.0.0.1:8000/test/, I have a new page on my browser, from spotify, I connect my account, and then, it redirects me on 127.0.0.1:8000/callback/?code=some_code
How can I give it to my first page waiting for the code so I can print the users stuff pls?
is there any solution to add CORS in odoo 10?, i want to access this restful API:
#validate_token
#http.route("/api/survey.survey/all", type="http", auth="none", methods=["GET", "OPTIONS"], csrf=False, cors='*') #Keperluan Web
def get_survey_survey_all(self, id=None, **payload):
model = "v.survey.survey"
ioc_name = model
_model = request.env[self._model].sudo().search([("model", "=", model)], limit=1)
custFields = ['id', 'title', 'stage_id', 'date_start', 'date_end', 'narasi', 'tot_comp_survey', 'department_id', 'responden'
, 'jenis_penelitian_id', 'polda_id', 'polres_id', 'fungsi', 'tahun', 'public_url', 'result_url']
custDomain = [("public_publish", "=", "1")]
if _model:
domain, fields, offset, limit, order = extract_arguments(payload)
fields = custFields
domain = custDomain
data = (request.env[_model.model].sudo().search_read(
domain = domain,
fields = fields,
offset = offset,
limit = limit,
order = order
))
if data:
return valid_response(data)
else:
return valid_response(data)
return invalid_response(
"Invalid object model",
"The model %s is not available in the registry." % ioc_name
)
i've add cors='*' but it's still got an error because access_token not allowed from header Access-Control-Allow-Headers
and this is my valid response code
def valid_response(data, status=200):
"""Valid Response
This will be return when the http request was successfully processed."""
data = {"count": len(data), "data": data}
return werkzeug.wrappers.Response(
status=status,
content_type="application/json; charset=utf-8;",
headers=[
("Access-Control-Allow-Headers", "access_token")
],
response=json.dumps(data),
)
I am trying to test a user login with setUpClass, but the credentials of the saved user do not get accepted (403) during authentification although it works if I register the user manually (but I wanted to omit that for all functions so I do not have to do that, that's why I looked up setUpclass())
Am I missing something? test_register() works just fine.
class AuthenticationTest(APITestCase):
#classmethod
def setUpClass(cls):
super(AuthenticationTest, cls).setUpClass()
cls.user_object = UserFactory.build()
cls.user_saved = UserFactory.create()
cls.client = APIClient()
cls.base_url_login = reverse("api:login-list")
cls.base_url_register = reverse("api:register-list")
cls.base_url_logout = reverse("api:logout-list")
cls.base_url_check_session = reverse("api:check-session-list")
cls.faker_obj = Faker()
def test_register(self):
# Prepare data
signup_dict = {
'username': self.user_object.username,
'password': 'test_Pass',
'email': self.user_object.email,
}
# Make request
response = self.client.post(
self.base_url_register, signup_dict
)
# Check status response
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
response_data = response.json()
self.assertEqual(response_data["success"], True)
self.assertEqual(User.objects.count(), 2)
# Check database
new_user = User.objects.get(username=self.user_object.username)
self.assertEqual(
new_user.email,
self.user_object.email,
)
def test_login(self):
# Prepare Data
login_dict = {
'password': self.user_saved.password,
'email': self.user_saved.email,
}
# Make request
response = self.client.post(self.base_url_login, login_dict)
# Check status response
self.assertEqual(response.status_code, status.HTTP_200_OK)
response_data = response.json()
self.assertEqual(response_data["success"], True)
...
class UserFactory(django.DjangoModelFactory):
class Meta:
model = User
username = Faker("user_name")
email = Faker("email")
#post_generation
def password(self, create: bool, extracted: Sequence[Any], **kwargs):
password = (
extracted
if extracted
else FakerClass().password(
length=30,
special_chars=True,
digits=True,
upper_case=True,
lower_case=True,
)
)
self.set_password(password)
my view is like :
def get_user_pending_order(request):
user_profile = get_object_or_404(Profile, user=request.user)
order = Order.objects.filter(owner=user_profile, is_ordered=False)
if order.exists():
return order[0]
return 0
MERCHANT = 'xxx...xxx'
ZP_API_REQUEST = "https://api.zarinpal.com/pg/v4/payment/request.json"
ZP_API_VERIFY = "https://api.zarinpal.com/pg/v4/payment/verify.json"
ZP_API_STARTPAY = "https://www.zarinpal.com/pg/StartPay/{authority}"
amount = ''
description = "text" # Required
email = 'example#email.com' # Optional
mobile = '09999999999' # Optional
# Important: need to edit for realy server.
CallbackURL = 'https://example.com/payment/verify/'
def send_request(request):
print(get_user_pending_order(request).owner.phone_number)
req_data = {
"merchant_id": MERCHANT,
"amount": int(get_user_pending_order(request).get_total()),
"callback_url": CallbackURL,
"description": description,
"metadata": {"mobile": mobile,
"email": email}
}
req_header = {"accept": "application/json",
"content-type": "application/json'"}
req = requests.post(url=ZP_API_REQUEST, data=json.dumps(
req_data), headers=req_header)
authority = req.json()['data']['authority']
if len(req.json()['errors']) == 0:
return redirect(ZP_API_STARTPAY.format(authority=authority))
else:
e_code = req.json()['errors']['code']
e_message = req.json()['errors']['message']
return HttpResponse(f"Error code: {e_code}, Error Message: {e_message}")
def verify(request):
t_status = request.GET.get('Status')
t_authority = request.GET['Authority']
if request.GET.get('Status') == 'OK':
req_header = {"accept": "application/json",
"content-type": "application/json'"}
req_data = {
"merchant_id": MERCHANT,
"amount": int(get_user_pending_order(request).get_total()),
"authority": t_authority
}
req = requests.post(url=ZP_API_VERIFY, data=json.dumps(req_data), headers=req_header)
if len(req.json()['errors']) == 0:
t_status = req.json()['data']['code']
if t_status == 100:
user = request.user
order_to_purchase = get_user_pending_order(request)
order_to_purchase.is_ordered = True
order_to_purchase.date_ordered=datetime.datetime.now()
order_to_purchase.created_on_time=datetime.datetime.now()
order_to_purchase.save()
order_items = order_to_purchase.items.all()
for order_item in order_items:
order_item.product.quantity = order_item.product.quantity - 1
order_item.product.save()
order_items.update(is_ordered=True, date_ordered=datetime.datetime.now())
subject = 'successful'
c = {
"refid":str(req.json()['data']['ref_id']),
"ref_code":order_to_purchase.ref_code,
"owner":order_to_purchase.owner,
}
email_template_name = "pay/after_pay_confirm_email.html"
email_html = render_to_string(email_template_name, c)
email_from = settings.EMAIL_HOST_USER
send_mail(subject, email_html, email_from, [user.email], html_message=email_html)
ctx = {'message_good':'good'}
return render(request, 'pay/verify.html', ctx)
elif t_status == 101:
...
else:
....
else:
...
else:
...
At first about user, is logged. and about send_request function it work totally fine...so it pass user into Payment gateway and after successful payment it come back to verify function by CallbackURL. to show success page and do order_to_purchase.is_ordered = True ...
for me with my pc, phone, other android phones, ios, windows, linux. and about browsers like chrome Firefox it work correctly and everything is fine.
but some clients tell me they face to 'AnonymousUser' object is not iterable after successful payment and when they back to verify. its kinda like that they logged out by pushing request to payment gateway.
also i made purchase by that account exactly same way and i didn't face to that error. it show is that phone or browser problem that half of my clients faced to that. i have no idea what should i do!!!
I am sending a get request in my view and then using the response to fill my database and I need some confirmation on the following:
should i make an api call inside of a view?
what should that view response be?
if i have done it wrong then what would be the right way to send get requests in Django?
my_app/views.py
class api(APIView):
template_name = 'payment/api.html'
def get(self, request):
#I SEND THE GET REQUEST HERE
config = configparser.ConfigParser()
config.read('config.ini')
r = requests.get(config['DEFAULT']['api'])
response = r.json()
#HERE I FILTER THE RESPONSE AND PUT IN A DB
for item in response:
if 'Covered Recipient Physician' in item.values():
person, _ = models.Person.objects.get_or_create(
profile_id = int(item['physician_profile_id']),
first_name = item['physician_first_name'].lower(),
last_name = item['physician_last_name'].lower()
)
address, _ = models.Address.objects.get_or_create(
business_street =
item['recipient_primary_business_street_address_line1'].lower(),
city = item['recipient_city'].lower(),
state = item['recipient_state'].lower(),
country = item['recipient_country'].lower()
)
business, _ = models.Business.objects.get_or_create(
business = item['submitting_applicable_manufacturer_or_applicable_gpo_name'].lower(),
)
business_address_link = models.Business_address_link.objects.create(
business = business,
address = address
)
business_address_link.save()
payment = models.Payment.objects.create(
record_id = int(item['record_id']),
amount = float(item['total_amount_of_payment_usdollars']),
date = item['date_of_payment'],
number_of_payments = int(item['number_of_payments_included_in_total_amount']),
payment_form = item['form_of_payment_or_transfer_of_value'],
nature_of_payment = item['nature_of_payment_or_transfer_of_value']
)
payment.save()
person_payment_information = models.Person_payment_information.objects.create(
person = person,
business_address_link = business_address_link,
payment = payment
)
person_payment_information.save()
Try to use this function for GET request -
#require_http_methods(['GET'])
def get_persons(request):
try:
data = list(Message.objects.all.values())
return render(request=request, template_name='template.html', context={"data": data})
except Exception as e:
return render(request=request, template_name='template.html', context={"error": e})
Once you get the response and send it to template.html, you can display it in any way you want.
If you want to add information to the DB you better use POST request, for example -
#require_http_methods(['POST'])
def add_person(request):
try:
data = json.loads(request.body)
new_person = Person(**data)
new_person.save()
return render(request=request, template_name='template.html', context={"data": data})
except Exception as e:
return render(request=request, template_name='template.html', context={"error": e})