def registration_payment_callback(request): merchant_uid = request.POST.get("merchant_uid", None) if not merchant_uid: return render_io_error("merchant uid dose not exist") product = Product() # TODO : check stock access_token = get_access_token(settings.IMP_API_KEY, settings.IMP_API_SECRET) imp_client = Iamporter(access_token) confirm = imp_client.find_by_merchant_uid(merchant_uid) if confirm["amount"] != product.price: # TODO : cancel return render_io_error("amount is not product.price") remain_ticket_count = settings.MAX_TICKET_NUM - Registration.objects.filter(payment_status="paid").count() if remain_ticket_count <= 0: # Cancel return render_json({"success": False, "message": u"티켓이 매진 되었습니다"}) registration = Registration.objects.filter(merchant_uid=merchant_uid).get() registration.payment_status = "paid" registration.save() send_email_ticket_confirm(request, registration) return render_json({"success": True})
def registration_payment_callback(request): merchant_uid = request.POST.get('merchant_uid', None) if not merchant_uid: return render_io_error('merchant uid dose not exist') product = Product() # TODO : check stock access_token = get_access_token(settings.IMP_API_KEY, settings.IMP_API_SECRET) imp_client = Iamporter(access_token) confirm = imp_client.find_by_merchant_uid(merchant_uid) if confirm['amount'] != product.price: # TODO : cancel return render_io_error('amount is not product.price') remain_ticket_count = ( settings.MAX_TICKET_NUM - Registration.objects.filter(payment_status='paid').count()) if remain_ticket_count <= 0: # Cancel return render_json({'success': False, 'message': u"티켓이 매진 되었습니다"}) registration = Registration.objects.filter(merchant_uid=merchant_uid).get() registration.payment_status = 'paid' registration.save() send_email_ticket_confirm(request, registration) return render_json({'success': True})
def post(self, request, *args, **kwargs): client = Iamporter(imp_key=imp_key, imp_secret=imp_secret) imp_uid = request.data['imp_uid'] customer_id = request.user.pk payment_info = client.find_payment(imp_uid=imp_uid) queryset = Cart.objects.filter(customer=customer_id).aggregate( total_amount=Sum( Case(When(product__is_discount=True, then=F('product__discount_price') * F('quantity')), default=F('product__price') * F('quantity')))) instance = {'status': 'failed'} if payment_info['amount'] == queryset['total_amount']: with transaction.atomic(): ordered = Order.objects.bulk_create( Cart.objects.filter(customer=customer_id)) Cart.objects.filter(customer=customer_id).delete() for i in ordered: product = Product.objects.get(name=i.product) product.stock -= i.quantity product.save() instance = {'status': 'success'} else: client.cancel_payment(imp_uid=imp_uid, reason="amount mismatch") serializer = self.get_serializer(instance) return Response(serializer.data)
def cancel_registration(modeladmin, request, queryset): messages = [] subject = u"PyCon APAC 2016 결제 취소 알림" body = u""" 안녕하세요. PyCon APAC 준비위원회입니다. 결제가 취소되었음을 알려드립니다. 결제 대행사 사정에 따라 다소 늦게 카드 취소가 이뤄질 수 있습니다. 다른 문의 사항은 [email protected] 로 메일 부탁드립니다. 감사합니다. """ from_email = "*****@*****.**" results = [] now = datetime.now() access_token = get_access_token(config.IMP_API_KEY, config.IMP_API_SECRET) imp_client = Iamporter(access_token) for obj in queryset: if obj.payment_method != 'card': obj.cancel_reason = u'카드 결제만 취소 가능' results.append(obj) continue if obj.payment_status != 'paid': obj.cancel_reason = u'결제 완료만 취소 가능' results.append(obj) continue try: imp_params = dict( merchant_uid=obj.merchant_uid, reason=u'Cancel by admin', ) imp_client.cancel(**imp_params) except IOError: obj.cancel_status = 'IOError' results.append(obj) continue except IamporterError as e: obj.cancel_status = e.code obj.cancel_reason = e.message results.append(obj) continue obj.canceled = now obj.payment_status = 'cancelled' obj.save(update_fields=['payment_status', 'canceled']) obj.cancel_status = 'CANCELLED' results.append(obj) message = (subject, body, from_email, [obj.email]) messages.append(message) send_mass_mail(messages, fail_silently=False) return render(request, 'registration/cancellation_result.html', {'results': results})
def payment_callback(request): merchant_uid = request.POST.get('merchant_uid') registration = Registration.objects.filter(merchant_uid=merchant_uid) if not registration.exists(): return HttpResponse(status_code=404) access_token = get_access_token(config.IMP_API_KEY, config.IMP_API_SECRET) imp_client = Iamporter(access_token) result = imp_client.find_by_merchant_uid(merchant_uid) registration = registration.first() if result['status'] == 'paid': registration.confirmed = datetime.datetime.now() elif result['status'] == 'cancelled': registration.canceled = datetime.datetime.now() registration.payment_status = result['status'] registration.save() return HttpResponse()
def setUp(self): self.imp_auth = IamportAuth(TEST_IMP_KEY, TEST_IMP_SECRET) self.client = Iamporter(imp_auth=self.imp_auth)
class TestIamporter(unittest.TestCase): def setUp(self): self.imp_auth = IamportAuth(TEST_IMP_KEY, TEST_IMP_SECRET) self.client = Iamporter(imp_auth=self.imp_auth) def test_init(self): self.assertRaises(errors.ImpUnAuthorized, Iamporter, imp_key=None) self.assertRaises(errors.ImpUnAuthorized, Iamporter, imp_key="invalid_key", imp_secret="invalid_secret") def test_find_payment(self): self.assertRaises(KeyError, self.client.find_payment) self.assertRaises(errors.ImpApiError, self.client.find_payment, imp_uid='test') self.assertRaises(errors.ImpApiError, self.client.find_payment, merchant_uid='âàáaā') def test_cancel_payment(self): self.assertRaises(errors.ImpApiError, self.client.cancel_payment, imp_uid='nothing', reason='reason') try: self.client.cancel_payment(imp_uid='nothing', reason='reason') except errors.ImpApiError as e: self.assertEqual(e.response.code, 1) self.assertEqual(e.response.message, '취소할 결제건이 존재하지 않습니다.') try: self.client.cancel_payment(merchant_uid='any-merchant_uid', reason='any-reason') except errors.ImpApiError as e: self.assertEqual(e.response.code, 1) self.assertEqual(e.response.message, '취소할 결제건이 존재하지 않습니다.') self.assertRaises(KeyError, self.client.cancel_payment, merchant_uid=None, reason='some-reason아 ') def test_cancel_payment_partital(self): try: self.client.cancel_payment(imp_uid='nothing', reason='reason', amount=100) except errors.ImpApiError as e: self.assertEqual(e.response.code, 1) self.assertEqual(e.response.message, '취소할 결제건이 존재하지 않습니다.') def test_create_billkey(self): self.assertRaises(KeyError, self.client.create_billkey, customer_uid=None, card_number="0000-0000-0000-0000", expiry="2022-06", birth="960714") try: self.client.create_billkey(customer_uid="customer_1234", card_number="1111-1111-1111-1111", expiry="2022-06", birth="960714", pwd_2digit="12") except errors.ImpApiError as e: self.assertEqual(e.response.code, -1) self.assertIn("유효하지않은 카드번호를 입력하셨습니다.", e.response.message) def test_find_billkey(self): self.assertRaises(KeyError, self.client.find_billkey, customer_uid=None) try: self.client.find_billkey(customer_uid="invalid-uid") except errors.ImpApiError as e: self.assertEqual(e.response.code, 1) self.assertEqual( e.response.message, "요청하신 customer_uid(invalid-uid)로 등록된 정보를 찾을 수 없습니다.") def test_delete_billkey(self): self.assertRaises(KeyError, self.client.delete_billkey, customer_uid=None) try: self.client.delete_billkey(customer_uid="invalid-uid") except errors.ImpApiError as e: self.assertEqual(e.response.code, 1) self.assertEqual( e.response.message, "요청하신 customer_uid(invalid-uid)로 등록된 정보를 찾을 수 없습니다.") def test_create_payment_onetime(self): self.assertRaises(KeyError, self.client.create_payment, merchant_uid=None, name="테스트", amount=10000) self.assertRaises(KeyError, self.client.create_payment, merchant_uid='test', name="테스트", amount=10000, card_number="1111-1111-1111-1111", expiry="2022-06") try: self.client.create_payment(merchant_uid='some-special-uid', amount=1000, name="테스트", card_number="1111-1111-1111-1111", expiry="2022-06", birth="960714") except errors.ImpApiError as e: self.assertEqual(e.response.code, -1) self.assertIn("유효하지않은 카드번호를 입력하셨습니다.", e.response.message) def test_create_payment_again(self): try: self.client.create_payment( merchant_uid='some-special-uid-2', amount=1000, name="테스트", customer_uid="invalid-uid", ) except errors.ImpApiError as e: self.assertEqual(e.response.code, 1) self.assertEqual(e.response.message, "등록되지 않은 구매자입니다.") def tearDown(self): del self.imp_auth del self.client
def payment_process(request): if request.method == 'GET': return redirect('registration_index') # alreay registered if Registration.objects.filter(user=request.user, payment_status__in=['paid','ready']).exists(): return redirect('registration_status') payment_logger.debug(request.POST) form = RegistrationAdditionalPriceForm(request.POST) # TODO : more form validation # eg) merchant_uid if not form.is_valid(): form_errors_string = "\n".join(('%s:%s' % (k, v[0]) for k, v in form.errors.items())) return JsonResponse({ 'success': False, 'message': form_errors_string, # TODO : ... }) remain_ticket_count = (config.TOTAL_TICKET - Registration.objects.filter(payment_status__in=['paid', 'ready']).count()) # sold out if remain_ticket_count <= 0: return JsonResponse({ 'success': False, 'message': u'티켓이 매진 되었습니다', }) if form.cleaned_data.get('additional_price', 0) < 0: return JsonResponse({ 'success': False, 'message': u'후원 금액은 0원 이상이어야 합니다.', }) registration = Registration( user=request.user, name = form.cleaned_data.get('name'), email = request.user.email, additional_price = form.cleaned_data.get('additional_price', 0), company = form.cleaned_data.get('company', ''), phone_number = form.cleaned_data.get('phone_number', ''), merchant_uid = request.POST.get('merchant_uid'), option = form.cleaned_data.get('option'), payment_method = form.cleaned_data.get('payment_method') ) # sold out if registration.option.is_soldout: return JsonResponse({ 'success': False, 'message': u'{name} 티켓이 매진 되었습니다'.format(name=registration.option.name), }) try: product = registration.option access_token = get_access_token(config.IMP_API_KEY, config.IMP_API_SECRET) imp_client = Iamporter(access_token) if registration.payment_method == 'card': # TODO : use validated and cleaned data imp_params = dict( token=request.POST.get('token'), merchant_uid=request.POST.get('merchant_uid'), amount=product.price + registration.additional_price, card_number=request.POST.get('card_number'), expiry=request.POST.get('expiry'), birth=request.POST.get('birth'), pwd_2digit=request.POST.get('pwd_2digit'), customer_uid=form.cleaned_data.get('email'), name=product.name ) if request.POST.get('birth') == '': # foreign payment imp_client.foreign(**imp_params) else: imp_client.foreign(**imp_params) # imp_client.onetime(**imp_params) confirm = imp_client.find_by_merchant_uid(request.POST.get('merchant_uid')) if confirm['amount'] != product.price + registration.additional_price: # TODO : cancel return render_io_error("amount is not same as product.price. it will be canceled") registration.transaction_code = confirm.get('pg_tid') registration.payment_method = confirm.get('pay_method') registration.payment_status = confirm.get('status') registration.payment_message = confirm.get('fail_reason') registration.vbank_name = confirm.get('vbank_name', None) registration.vbank_num = confirm.get('vbank_num', None) registration.vbank_date = confirm.get('vbank_date', None) registration.vbank_holder = confirm.get('vbank_holder', None) registration.save() elif registration.payment_method == 'bank': registration.payment_status = 'ready' registration.save() else: raise Exception('Unknown payment method') # if not settings.DEBUG: # send_email_ticket_confirm(request, registration) except IamporterError as e: # TODO : other status code return JsonResponse({ 'success': False, 'code': e.code, 'message': e.message, }) else: return JsonResponse({ 'success': True, })
def payment_process(request): if request.method == 'GET': return redirect('registration_index') # alreay registered if Registration.objects.filter(user=request.user, payment_status__in=['paid','ready']).exists(): return redirect('registration_status') payment_logger.debug(request.POST) form = RegistrationAdditionalPriceForm(request.POST) # TODO : more form validation # eg) merchant_uid if not form.is_valid(): form_errors_string = "\n".join(('%s:%s' % (k, v[0]) for k, v in form.errors.items())) return JsonResponse({ 'success': False, 'message': form_errors_string, # TODO : ... }) remain_ticket_count = (config.TOTAL_TICKET - Registration.objects.filter(payment_status__in=['paid', 'ready']).count()) # sold out if remain_ticket_count <= 0: return JsonResponse({ 'success': False, 'message': u'티켓이 매진 되었습니다', }) if form.cleaned_data.get('additional_price', 0) < 0: return JsonResponse({ 'success': False, 'message': u'후원 금액은 0원 이상이어야 합니다.', }) registration = Registration( user=request.user, name = form.cleaned_data.get('name'), email = request.user.email, additional_price = form.cleaned_data.get('additional_price', 0), company = form.cleaned_data.get('company', ''), phone_number = form.cleaned_data.get('phone_number', ''), merchant_uid = request.POST.get('merchant_uid'), option = form.cleaned_data.get('option'), payment_method = form.cleaned_data.get('payment_method') ) # sold out if registration.option.is_soldout: return JsonResponse({ 'success': False, 'message': u'{name} 티켓이 매진 되었습니다'.format(name=registration.option.name), }) try: product = registration.option if registration.payment_method == 'card': access_token = get_access_token(config.IMP_API_KEY, config.IMP_API_SECRET) imp_client = Iamporter(access_token) # TODO : use validated and cleaned data imp_params = dict( token=request.POST.get('token'), merchant_uid=request.POST.get('merchant_uid'), amount=product.price + registration.additional_price, card_number=request.POST.get('card_number'), expiry=request.POST.get('expiry'), birth=request.POST.get('birth'), pwd_2digit=request.POST.get('pwd_2digit'), customer_uid=form.cleaned_data.get('email'), name=product.name, buyer_name=request.POST.get('name'), buyer_email=request.POST.get('email'), buyer_tel=request.POST.get('phone_number') ) if request.POST.get('birth') == '': # foreign payment imp_client.foreign(**imp_params) else: imp_client.foreign(**imp_params) # imp_client.onetime(**imp_params) confirm = imp_client.find_by_merchant_uid(request.POST.get('merchant_uid')) if confirm['amount'] != product.price + registration.additional_price: # TODO : cancel return render_io_error("amount is not same as product.price. it will be canceled") registration.transaction_code = confirm.get('pg_tid') registration.payment_method = confirm.get('pay_method') registration.payment_status = confirm.get('status') registration.payment_message = confirm.get('fail_reason') registration.vbank_name = confirm.get('vbank_name', None) registration.vbank_num = confirm.get('vbank_num', None) registration.vbank_date = confirm.get('vbank_date', None) registration.vbank_holder = confirm.get('vbank_holder', None) registration.save() elif registration.payment_method == 'bank': registration.transaction_code = request.POST.get('pg_tid') registration.payment_method = request.POST.get('pay_method') registration.payment_status = request.POST.get('status') registration.payment_message = request.POST.get('fail_reason') registration.vbank_name = request.POST.get('vbank_name', None) registration.vbank_num = request.POST.get('vbank_num', None) registration.vbank_date = request.POST.get('vbank_date', None) registration.vbank_holder = request.POST.get('vbank_holder', None) registration.save() else: raise Exception('Unknown payment method') # if not settings.DEBUG: # send_email_ticket_confirm(request, registration) except IamporterError as e: # TODO : other status code return JsonResponse({ 'success': False, 'code': e.code, 'message': e.message, }) else: return JsonResponse({ 'success': True, })
def registration_payment(request): max_ticket_limit = settings.MAX_TICKET_NUM if not is_registration_time(): return redirect("registration_info") if request.method == "GET": product = Product() registered = Registration.objects.filter(user=request.user, payment_status__in=["paid", "ready"]).exists() if registered: return redirect("registration_status") uid = str(uuid4()).replace("-", "") form = RegistrationForm(initial={"email": request.user.email}) return render( request, "pyconkr/registration/payment.html", { "title": _("Registration"), "IMP_USER_CODE": settings.IMP_USER_CODE, # TODO : Move to 'settings context processor' "form": form, "uid": uid, "product_name": product.name, "amount": product.price, "vat": 0, }, ) elif request.method == "POST": payment_logger.debug(request.POST) form = RegistrationForm(request.POST) # TODO : more form validation # eg) merchant_uid if not form.is_valid(): form_errors_string = "\n".join(("%s:%s" % (k, v[0]) for k, v in form.errors.items())) return render_json({"success": False, "message": form_errors_string}) # TODO : ... remain_ticket_count = ( settings.MAX_TICKET_NUM - Registration.objects.filter(payment_status__in=["paid", "ready"]).count() ) # sold out if remain_ticket_count <= 0: return render_json({"success": False, "message": u"티켓이 매진 되었습니다"}) registration, created = Registration.objects.get_or_create(user=request.user) registration.name = form.cleaned_data.get("name") registration.email = request.user.email registration.company = form.cleaned_data.get("company", "") registration.phone_number = form.cleaned_data.get("phone_number", "") registration.merchant_uid = request.POST.get("merchant_uid") registration.save() # TODO : use form.save() try: product = Product() access_token = get_access_token(settings.IMP_API_KEY, settings.IMP_API_SECRET) imp_client = Iamporter(access_token) if request.POST.get("payment_method") == "card": # TODO : use validated and cleaned data imp_client.onetime( token=request.POST.get("token"), merchant_uid=request.POST.get("merchant_uid"), amount=request.POST.get("amount"), # vat=request.POST.get('vat'), card_number=request.POST.get("card_number"), expiry=request.POST.get("expiry"), birth=request.POST.get("birth"), pwd_2digit=request.POST.get("pwd_2digit"), customer_uid=form.cleaned_data.get("email"), ) confirm = imp_client.find_by_merchant_uid(request.POST.get("merchant_uid")) if confirm["amount"] != product.price: # TODO : cancel return render_io_error("amount is not same as product.price. it will be canceled") registration.payment_method = confirm.get("pay_method") registration.payment_status = confirm.get("status") registration.payment_message = confirm.get("fail_reason") registration.vbank_name = confirm.get("vbank_name", None) registration.vbank_num = confirm.get("vbank_num", None) registration.vbank_date = confirm.get("vbank_date", None) registration.vbank_holder = confirm.get("vbank_holder", None) registration.save() send_email_ticket_confirm(request, registration) except IamporterError as e: # TODO : other status code return render_json({"success": False, "code": e.code, "message": e.message}) else: return render_json({"success": True})
def registration_payment(request): max_ticket_limit = settings.MAX_TICKET_NUM if not is_registration_time(): return redirect('registration_info') if request.method == 'GET': product = Product() registered = Registration.objects.filter( user=request.user, payment_status__in=['paid', 'ready']).exists() if registered: return redirect('registration_status') uid = str(uuid4()).replace('-', '') form = RegistrationForm(initial={'email': request.user.email}) return render( request, 'pyconkr/registration/payment.html', { 'title': _('Registration'), 'IMP_USER_CODE': settings. IMP_USER_CODE, # TODO : Move to 'settings context processor' 'form': form, 'uid': uid, 'product_name': product.name, 'amount': product.price, 'vat': 0, }) elif request.method == 'POST': payment_logger.debug(request.POST) form = RegistrationForm(request.POST) # TODO : more form validation # eg) merchant_uid if not form.is_valid(): form_errors_string = "\n".join( ('%s:%s' % (k, v[0]) for k, v in form.errors.items())) return render_json({ 'success': False, 'message': form_errors_string, # TODO : ... }) remain_ticket_count = ( settings.MAX_TICKET_NUM - Registration.objects.filter( payment_status__in=['paid', 'ready']).count()) # sold out if remain_ticket_count <= 0: return render_json({ 'success': False, 'message': u'티켓이 매진 되었습니다', }) registration, created = Registration.objects.get_or_create( user=request.user) registration.name = form.cleaned_data.get('name') registration.email = request.user.email registration.company = form.cleaned_data.get('company', '') registration.phone_number = form.cleaned_data.get('phone_number', '') registration.merchant_uid = request.POST.get('merchant_uid') registration.save() # TODO : use form.save() try: product = Product() access_token = get_access_token(settings.IMP_API_KEY, settings.IMP_API_SECRET) imp_client = Iamporter(access_token) if request.POST.get('payment_method') == 'card': # TODO : use validated and cleaned data imp_client.onetime( token=request.POST.get('token'), merchant_uid=request.POST.get('merchant_uid'), amount=request.POST.get('amount'), # vat=request.POST.get('vat'), card_number=request.POST.get('card_number'), expiry=request.POST.get('expiry'), birth=request.POST.get('birth'), pwd_2digit=request.POST.get('pwd_2digit'), customer_uid=form.cleaned_data.get('email'), ) confirm = imp_client.find_by_merchant_uid( request.POST.get('merchant_uid')) if confirm['amount'] != product.price: # TODO : cancel return render_io_error( "amount is not same as product.price. it will be canceled") registration.payment_method = confirm.get('pay_method') registration.payment_status = confirm.get('status') registration.payment_message = confirm.get('fail_reason') registration.vbank_name = confirm.get('vbank_name', None) registration.vbank_num = confirm.get('vbank_num', None) registration.vbank_date = confirm.get('vbank_date', None) registration.vbank_holder = confirm.get('vbank_holder', None) registration.save() send_email_ticket_confirm(request, registration) except IamporterError as e: # TODO : other status code return render_json({ 'success': False, 'code': e.code, 'message': e.message, }) else: return render_json({ 'success': True, })