def save_model(self, request, obj, form, change): if change: # 변경이 감지되면 n = Notification() if obj.status == 3 and obj.video and obj.is_alarm: # 주문완료(3) and 영상업로드 알림 전송(v) and n.video_complete(obj.phonenumber, obj.user, obj.channel) # 비디오 완성 알림 obj.save() # 주문취소 발생 시 elif obj.status == 4 and obj.cancelreason and obj.cancel: iamport = Iamport( imp_key='8161721766694252', imp_secret= 'kJqNZpHNzkWkA55fMJ9h1GyOm5ataB1vkrikRZ8qk4KUaQaWAjeB0MpmRAQ2bRxwjPRaP0B94m4fdecO' ) # 알림이 발생이 안하면 이미 주문이 취소 된 건이다. try: # 상품 아이디로 취소 iamport.cancel(u'취소하는 이유', merchant_uid=obj.merchant_uid) except Iamport.ResponseError as e: print e.code print e.message # 에러난 이유를 알 수 있음 except Iamport.HttpError as http_error: print http_error.code print http_error.reason # HTTP not 200 에러난 이유를 알 수 있음 else: # 에러가 발생하지 않았다면 아래 구문 실행 # [!] 주문취소 알람발생 n.payment_cancel(obj.phonenumber, obj.user, obj.channel, obj.created_at, obj.cancelreason) obj.save()
def cancel_reservation(meal_id, guest_id): reservation = Reservation.query.filter_by(meal_id=meal_id, guest_id=guest_id).first() if reservation.payment_id: # cancel payment transaction iamport = Iamport(imp_key=app.config['IAMPORT_API_KEY'], imp_secret=app.config['IAMPORT_API_SECRET']) iamport.cancel('예약 취소', imp_uid=reservation.payment_id) db_session.delete(reservation) db_session.flush() return redirect(url_for('meal.detail_meal', meal_id=meal_id))
def reservation(meal_id, guest_id): meal = Meal.query.get_or_404(meal_id) iamport = Iamport(imp_key=app.config['IAMPORT_API_KEY'], imp_secret=app.config['IAMPORT_API_SECRET']) if not iamport.is_paid(meal.price, imp_uid=request.form['payment_id']): iamport.cancel('Bad request', imp_uid=request.form['payment_id']) flash('잘못된 접근입니다.') raise BadRequest() else: reservations = Reservation(meal_id=meal_id, guest_id=guest_id, payment_id=request.form['payment_id']) db_session.add(reservations) db_session.flush() return redirect(url_for('meal.detail_meal', meal_id=meal_id))
def test_cancel(): iamport = Iamport() with pytest.raises(TypeError): iamport.cancel(imp_uid='nothing') with pytest.raises(Iamport.ResponseError): iamport.cancel('reason', imp_uid='nothing') try: iamport.cancel('reason', imp_uid='nothing') except Iamport.ResponseError as e: assert e.code == 1 assert e.message == u'취소할 결제건이 존재하지 않습니다.'
def payment_cancel_confirm_view(request, pk): payment = get_object_or_404(Payment, pk=pk) iamport = Iamport(imp_key=settings.IMP_KEY, imp_secret=settings.IMP_SECRET) # 입력한 취소 사유로 해당 imp_uid의 결제 취소 진행 # Iamport.ResponseError > 이미 결제 취소되어진 경우 try: cancel = iamport.cancel(payment.paymentcancel.reason, imp_uid=payment.imp_uid) except Iamport.ResponseError: raise exceptions.PermissionDenied('Already cancelled') all_fields = [f.name for f in Payment._meta.get_fields()] Payment.objects.filter(pk=pk).update( **{key: value for key, value in cancel.items() if key in all_fields}, ) payment.reservation.status = 'cancelled' payment.reservation.save() return redirect('reservations:views:reservation_check_detail', pk=payment.reservation.pk)
def payment_reservations_save_view(request): if request.method == 'POST': restaurant = int(request.POST.get('restaurant')) information = int(request.POST.get('information')) name = request.POST.get('name') party = int(request.POST.get('party')) phone_number = int(request.POST.get('phone_number')) email = request.POST.get('email') price = int(request.POST.get('price')) reservation = Reservation.objects.create( user=request.user, information=get_object_or_404(ReservationInfo, pk=information), restaurant=get_object_or_404(Restaurant, pk=restaurant), name=name, party=party, phone_number=phone_number, email=email, price=price, ) # 예약 가능 인원 수에서 예약 인원만큼 빼 줌 get_object_or_404(ReservationInfo, pk=information).acceptable_size_of_party_update(party) iamport = Iamport(imp_key=settings.IMP_KEY, imp_secret=settings.IMP_SECRET) # 입력한 imp_uid로부터 결제정보를 가져옴 payment = iamport.find(imp_uid=request.POST.get('imp_uid')) # Payment 모델에 있는 모든 필드를 리스트에 담음 all_fields = [f.name for f in Payment._meta.get_fields()] # 주문 해야할 금액과 실제 결제 금액이 일치하는지 검증 후 일치하지 않으면 자동으로 취소 # 취소 되었을 경우에는 취소 되어진 결제정보로 데이터베이스에 저장 # 또한, 취소 되었을 경우 취소되었다는 메일 보냄(celery로 비동기 처리, celery config dev로 바꾸고 배포 관련 처리 하고 주석 빼야 함) if not iamport.is_paid(int(request.POST.get('price')), imp_uid=request.POST.get('imp_uid')): cancel = iamport.cancel(u'가격 불일치', imp_uid=request.POST.get('imp_uid')) # send_mail_task.delay('Test', 'Test', '*****@*****.**') Payment.objects.create( **{key: value for key, value in cancel.items() if key in all_fields}, reservation=reservation ) else: Payment.objects.create( **{key: value for key, value in payment.items() if key in all_fields}, reservation=reservation ) return HttpResponse('success') return HttpResponse('failed')
def post(self, request, pk): reservation = get_object_or_404(Reservation, pk=pk) iamport = Iamport(imp_key=settings.IMP_KEY, imp_secret=settings.IMP_SECRET) payment = iamport.find(imp_uid=request.data.get('imp_uid')) if not iamport.is_paid(int(request.data.get('price')), imp_uid=request.data.get('imp_uid')): cancel = iamport.cancel(u'가격 불일치', imp_uid=request.data.get('imp_uid')) serializer = PaymentSerializer(data=cancel) else: serializer = PaymentSerializer(data=payment) if serializer.is_valid(raise_exception=True): try: serializer.save(reservation=reservation) except IntegrityError: raise exceptions.ValidationError return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def patch(self, request, imp_uid): payment = get_object_or_404(Payment, imp_uid=imp_uid) iamport = Iamport(imp_key=settings.IMP_KEY, imp_secret=settings.IMP_SECRET) # 입력한 취소 사유로 해당 imp_uid의 결제 취소 진행 # Iamport.ResponseError > 이미 결제 취소되어진 경우 try: cancel = iamport.cancel(request.data['reason'], imp_uid=payment.imp_uid) except Iamport.ResponseError: raise exceptions.NotAcceptable('Already cancelled') except MultiValueDictKeyError: raise exceptions.ValidationError serializer = PaymentSerializer(payment, data=cancel, partial=True) # 결제 취소가 이루어지면 해당 결제 정보에 연결된 예약 정보의 status 필드를 cancelled로 변경 if serializer.is_valid(raise_exception=True): serializer.save() payment.reservation.status = 'cancelled' payment.reservation.save() return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def post(self, request, pk): reservation = get_object_or_404(Reservation, pk=pk) iamport = Iamport(imp_key=settings.IMP_KEY, imp_secret=settings.IMP_SECRET) # 입력한 imp_uid로부터 결제정보를 가져옴 payment = iamport.find(imp_uid=request.data.get('imp_uid')) # 주문 해야할 금액과 실제 결제 금액이 일치하는지 검증 후 일치하지 않으면 자동으로 취소 # 취소 되었을 경우에는 취소 되어진 결제정보로 데이터베이스에 저장 # 또한, 취소 되었을 경우 취소되었다는 메일 보냄(celery로 비동기 처리, celery config dev로 바꾸고 배포 관련 처리 하고 주석 빼야 함) if not iamport.is_paid(int(request.data.get('price')), imp_uid=request.data.get('imp_uid')): cancel = iamport.cancel(u'가격 불일치', imp_uid=request.data.get('imp_uid')) # send_mail_task.delay('Test', 'Test', '*****@*****.**') serializer = PaymentSerializer(data=cancel) else: serializer = PaymentSerializer(data=payment) if serializer.is_valid(raise_exception=True): try: serializer.save(reservation=reservation) except IntegrityError: raise exceptions.ValidationError return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)