예제 #1
0
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})
예제 #2
0
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})
예제 #3
0
 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)
예제 #4
0
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})
예제 #5
0
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})
예제 #6
0
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()
예제 #7
0
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()
예제 #8
0
 def setUp(self):
     self.imp_auth = IamportAuth(TEST_IMP_KEY, TEST_IMP_SECRET)
     self.client = Iamporter(imp_auth=self.imp_auth)
예제 #9
0
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
예제 #10
0
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,
        })
예제 #11
0
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,
        })
예제 #12
0
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})
예제 #13
0
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,
            })