def processing_payment(request, assignment_id): assignment = get_object_or_404(Assignment, id=assignment_id) if request.method == 'POST': environment = LiveEnvironment(client_id=settings.PAYPAL_CLIENT_ID, client_secret=settings.PAYPAL_SECRET_ID) client = PayPalHttpClient(environment) create_order = OrdersCreateRequest() create_order.request_body({ "intent": "CAPTURE", "purchase_units": [{ "amount": { "currency_code": "USD", "value": assignment.price, "breakdown": { "item_total": { "currency_code": "USD", "value": assignment.price } }, }, }] }) response = client.execute(create_order) data = response.result.__dict__['_dict'] return JsonResponse(data)
class PayPalHandler: def __init__(self, client_id, client_secret): self.client_id = client_id self.client_secret = client_secret self.create_environment() self.create_client() def create_environment(self): ''' Create sandbox environment for PayPal ''' self.env = SandboxEnvironment( client_id=self.client_id, client_secret=self.client_secret ) def create_client(self): ''' Create the client ''' self.client = PayPalHttpClient(self.env) def capture_order(self, order_id, debug=True): request = OrdersCaptureRequest(order_id) response = self.client.execute(request) if debug: print("Status Code: ", response.status_code) print("Status: ", response.result.status) print("Order ID: ", response.result.id) print("Links: ") for link in response.result.links: print('\t{}: {}\tCall Type: {}'.format(link.rel, link.href, link.method)) print("Capture Ids:") for purchase_unit in response.result.purchase_units: for capture in purchase_unit.payments.captures: print("\t", capture.id) return self.parse_response(response) def parse_response(self, response): return { "status_code": response.status_code, "status": response.result.status, "order_id": response.result.id, "links": [ { "rel": link.rel, "href": link.href, "method": link.method } for link in response.result.links ], "reference_id": response.result.purchase_units[0].reference_id, "buyer": { "email": response.result.payer.email_address, } } def is_completed(self, response): return response["status"] == "COMPLETED"
def create_paypal_order(session, donation): paypalSettings = getPayPalSettings() client = PayPalHttpClient(paypalSettings.environment) req = OrdersCreateRequest() # set dictionary object in session['extra_test_headers'] in TestCases if session.get('extra_test_headers', None) and donation.is_test: for key, value in session.get('extra_test_headers').items(): req.headers[key] = value req.prefer('return=representation') req.request_body(build_onetime_request_body(donation)) return client.execute(req)
def pago(request): # Creating Access Token for Sandbox client_id = "AWKxRtjpmHR9Jd8n8fMGO77lqcIw7fFHML19xSzd1Scfv4Mk-XGwnjBYJIkaRaFa_y2LC2PXBulTMPFK" client_secret = "EGlVhQYGDzop2HftvmEqh726ChUjz4e7x_Ai4Hp900iA8troRX5feiS6ThlfB-HSVwzKNdHW2W3BzCyf" # Creating an environment environment = SandboxEnvironment(client_id=client_id, client_secret=client_secret) client = PayPalHttpClient(environment) # Construct a request object and set desired parameters # Here, OrdersCreateRequest() creates a POST request to /v2/checkout/orders requestPaypal = OrdersCreateRequest() sesion_id = request.session.session_key registro = Ventas_por_enviar.objects.filter(sesion=sesion_id) posicion = (len(registro)) total = registro[posicion - 1].total total_stripe = float(total) total_stripe = total_stripe * 100 requestPaypal.prefer('return=representation') requestPaypal.request_body({ "intent": "CAPTURE", "purchase_units": [{ "amount": { "currency_code": 'MXN', "value": float(total), } }], "application_context": { "return_url": "http://127.0.0.1:8000/checkout/exitoso", "cancel_url": "http://127.0.0.1:8000/checkout/cancelado", "brand_name": "Joyapan" } }) try: # Call API with your client and get a response for your call response = client.execute(requestPaypal) if response.result.status == 'CREATED': approval_url = str(response.result.links[1].href) print(approval_url) return render(request, 'checkout/pago.html',{#aqui es donde esta el boton 'approval_url':approval_url,'STRIPE_PUBLISHABLE_KEY':settings.STRIPE_PUBLISHABLE_KEY,'total':total,'total_stripe':total_stripe, }) except IOError as ioe: print(ioe) if isinstance(ioe, HttpError): # Something went wrong server-side return render(request, 'checkout/pago_cancelado.html')
def pago_exitoso(request): # Creating Access Token for Sandbox client_id = "AWKxRtjpmHR9Jd8n8fMGO77lqcIw7fFHML19xSzd1Scfv4Mk-XGwnjBYJIkaRaFa_y2LC2PXBulTMPFK" client_secret = "EGlVhQYGDzop2HftvmEqh726ChUjz4e7x_Ai4Hp900iA8troRX5feiS6ThlfB-HSVwzKNdHW2W3BzCyf" # Creating an environment environment = SandboxEnvironment(client_id=client_id, client_secret=client_secret) client = PayPalHttpClient(environment) ordenId = request.GET.get('token') payerId = request.GET.get('PayerID') requestPaypal = OrdersCaptureRequest(ordenId) print("RequestPaypal") print(requestPaypal) requestPaypal.prefer('return=representation') try: # Call API with your client and get a response for your call response = client.execute(requestPaypal) # If call returns body in response, you can get the deserialized version from the result attribute of the response print("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") order = response.result.id sesion_id = request.session.session_key registro = Ventas_por_enviar.objects.filter(sesion=sesion_id) posicion = (len(registro)) registro[posicion - 1].autorizacion = order registro[posicion - 1].verificacion = payerId diccionario = { 'nombre': registro[posicion - 1].nombre, 'email': registro[posicion - 1].email, } registro[posicion - 1].save() envio_email_confirmacion(diccionario) except IOError as ioe: if isinstance(ioe, HttpError): # Something went wrong server-side print("Algo salio mal :c") print(ioe.status_code) print(ioe.headers) print(ioe) return render(request, 'checkout/pago_cancelado.html') else: # Something went wrong client side print(ioe) return render(request, 'checkout/pago_cancelado.html') return render(request, 'checkout/pago_exitoso.html')
def capture(request, order_id, assignment_id): assignment = get_object_or_404(Assignment, id=assignment_id) if request.method == "POST": capture_order = OrdersCaptureRequest(order_id) Order.objects.create(token=order_id, total=assignment.price, emailAddress=assignment.creator.email, assignment=assignment, paid=True, client=assignment.creator, writer=assignment.writer, support=assignment.support) environment = LiveEnvironment(client_id=settings.PAYPAL_CLIENT_ID, client_secret=settings.PAYPAL_SECRET_ID) client = PayPalHttpClient(environment) response = client.execute(capture_order) data = response.result.__dict__['_dict'] return JsonResponse(data) else: return JsonResponse({'details': "invalid request"})
def capture_paypal_order(donation, order_id): """Method to capture order using order_id""" paypalSettings = getPayPalSettings() client = PayPalHttpClient(paypalSettings.environment) req = OrdersCaptureRequest(order_id) _debug('PayPal: Capture Order') try: response = client.execute(req) except IOError as ioe: fail_reason = str(ioe) if isinstance(ioe, HttpError): # Something went wrong server-side httpError = json.loads(ioe.message) if 'details' in httpError and len(httpError['details']) > 0: fail_reason = process_capture_failure( donation, httpError['details'][0]['issue'], httpError['details'][0]['description']) # update donation status to failed donation.payment_status = STATUS_FAILED donation.save() raise IOError(fail_reason) return response.result
def create_checkout_session(request): data = json.loads(request.body) # Coupon coupon_code = data['coupon_code'] coupon_value = 0 if coupon_code != '': coupon = Coupon.objects.get(code=coupon_code) if coupon.can_use(): coupon_value = coupon.value coupon.use() # cart = Cart(request) items = [] for item in cart: product = item['product'] price = int(product.price * 100) if coupon_value > 0: price = int(price * (int(coupon_value) / 100)) obj = { 'price_data': { 'currency': 'usd', 'product_data': { 'name': product.title }, 'unit_amount': price }, 'quantity': item['quantity'] } items.append(obj) gateway = data['gateway'] session = '' order_id = '' payment_intent = '' if gateway == 'stripe': stripe.api_key = settings.STRIPE_API_KEY_HIDDEN session = stripe.checkout.Session.create( payment_method_types=['card'], line_items=items, mode='payment', success_url='http://127.0.0.1:8000/cart/success/', cancel_url='http://127.0.0.1:8000/cart/' ) payment_intent = session.payment_intent # # Create order orderid = checkout(request, data['first_name'], data['last_name'], data['email'], data['address'], data['zipcode'], data['place'], data['phone']) total_price = 0.00 for item in cart: product = item['product'] total_price = total_price + (float(product.price) * int(item['quantity'])) if coupon_value > 0: total_price = total_price * (coupon_value / 100) if gateway == 'razorpay': order_amount = total_price * 100 order_currency = 'INR' client = razorpay.Client(auth=(settings.RAZORPAY_API_KEY_PUBLISHABLE, settings.RAZORPAY_API_KEY_HIDDEN)) data = { 'amount': order_amount, 'currency': order_currency } payment_intent = client.order.create(data=data) # PayPal if gateway == 'paypal': order_id = data['order_id'] environment = SandboxEnvironment(client_id=settings.PAYPAL_API_KEY_PUBLISHABLE, client_secret=settings.PAYPAL_API_KEY_HIDDEN) client = PayPalHttpClient(environment) request = OrdersCaptureRequest(order_id) response = client.execute(request) order = Order.objects.get(pk=orderid) order.paid_amount = total_price order.used_coupon = coupon_code if response.result.status == 'COMPLETED': order.paid = True order.payment_intent = order_id order.save() decrement_product_quantity(order) send_order_confirmation(order) else: order.paid = False order.save() else: order = Order.objects.get(pk=orderid) if gateway == 'razorpay': order.payment_intent = payment_intent['id'] else: order.payment_intent = payment_intent order.paid_amount = total_price order.used_coupon = coupon_code order.save() # return JsonResponse({'session': session, 'order': payment_intent})
class PaymentProcessor: client = None def __init__(self): credentials = { 'client_id': settings.PAYPAL_CLIENT_ID, 'client_secret': settings.PAYPAL_CLIENT_SECRET, } if getattr(settings, 'PAYPAL_SANDBOX_MODE', True): environment = SandboxEnvironment(**credentials) else: environment = LiveEnvironment(**credentials) self.client = PayPalHttpClient(environment) def build_order_create_request_body( self, basket, currency, return_url, cancel_url, order_total, address=None, shipping_charge=None, intent=None, ): application_context = { 'return_url': return_url, 'cancel_url': cancel_url, 'landing_page': get_landing_page(), 'shipping_preference': 'SET_PROVIDED_ADDRESS' if address is not None else 'NO_SHIPPING', # TODO: ??? 'user_action': 'PAY_NOW' if buyer_pays_on_paypal() else 'CONTINUE', } if getattr(settings, 'PAYPAL_BRAND_NAME', None) is not None: application_context['brand_name'] = settings.PAYPAL_BRAND_NAME breakdown = { 'item_total': { 'currency_code': currency, 'value': format_amount(basket.total_incl_tax_excl_discounts), }, 'discount': { 'currency_code': currency, 'value': format_amount( sum([ discount['discount'] for discount in basket.offer_discounts + basket.voucher_discounts ], D(0))), }, 'shipping_discount': { 'currency_code': currency, 'value': format_amount( sum([ discount['discount'] for discount in basket.shipping_discounts ], D(0))), } } if shipping_charge is not None: breakdown['shipping'] = { 'currency_code': currency, 'value': format_amount(shipping_charge), } purchase_unit = { 'amount': { 'currency_code': currency, 'value': format_amount(order_total), 'breakdown': breakdown, } } items = [] for line in basket.all_lines(): product = line.product item = { 'name': product.get_title(), 'description': format_description(product.description), 'sku': product.upc if product.upc else '', 'unit_amount': { 'currency_code': currency, 'value': format_amount(line.unit_price_incl_tax) }, 'quantity': line.quantity, 'category': 'PHYSICAL_GOODS' if product.is_shipping_required else 'DIGITAL_GOODS' } items.append(item) purchase_unit['items'] = items if address is not None: purchase_unit['shipping'] = { 'name': { 'full_name': address.name }, 'address': { 'address_line_1': address.line1, 'address_line_2': address.line2, 'admin_area_2': address.line4, 'admin_area_1': address.state, 'postal_code': address.postcode, 'country_code': address.country.iso_3166_1_a2 } } body = { 'intent': intent, 'application_context': application_context, 'purchase_units': [purchase_unit] } return body def build_refund_order_request_body(self, amount, currency): return { 'amount': { 'value': format_amount(amount), 'currency_code': currency } } def create_order( self, basket, currency, return_url, cancel_url, order_total, address=None, shipping_charge=None, intent=None, preferred_response='minimal', ): request = OrdersCreateRequest() request.prefer(f'return={preferred_response}') request.request_body( self.build_order_create_request_body( basket=basket, currency=currency, return_url=return_url, cancel_url=cancel_url, order_total=order_total, intent=intent, address=address, shipping_charge=shipping_charge, )) response = self.client.execute(request) return response.result def get_order(self, token): request = OrdersGetRequest(token) response = self.client.execute(request) return response.result def get_authorize_request_body(self): return {} def authorize_order(self, order_id, preferred_response='minimal'): request = OrdersAuthorizeRequest(order_id) request.prefer(f'return={preferred_response}') request.request_body(self.get_authorize_request_body()) response = self.client.execute(request) return response.result def void_authorized_order(self, authorization_id): request = AuthorizationsVoidRequest(authorization_id) self.client.execute(request) def refund_order(self, capture_id, amount, currency, preferred_response='minimal'): request = CapturesRefundRequest(capture_id) request.prefer(f'return={preferred_response}') request.request_body( self.build_refund_order_request_body(amount, currency)) response = self.client.execute(request) return response.result def capture_order(self, token, intent, preferred_response='minimal'): capture_request = INTENT_REQUEST_MAPPING[intent] request = capture_request(token) request.prefer(f'return={preferred_response}') response = self.client.execute(request) return response.result
class PayPalHttpClientTest(PayPalTestHarness): def setUp(self): self.client = PayPalHttpClient(self.environment()) @responses.activate def testPayPalHttpClient_execute_fetchesAccessTokenIfNone(self): request = SimpleRequest("/", "POST") self.stub_request_with_response(request) self.stubaccesstokenrequest() self.client.execute(request) self.assertEqual(2, len(responses.calls)) accesstokenrequest = responses.calls[0].request self.assertEqual(self.environment().base_url + "/v1/oauth2/token", accesstokenrequest.url) self.assertEqual("application/x-www-form-urlencoded", accesstokenrequest.headers["Content-Type"]) expectedauthheader = "Basic {0}".format( base64.b64encode(("{0}:{1}".format( self.environment().client_id, self.environment().client_secret)).encode()).decode()) self.assertEqual(expectedauthheader, accesstokenrequest.headers["Authorization"]) self.assertEqual("grant_type=client_credentials", accesstokenrequest.body) @responses.activate def testPayPalHttpClient_execute_fetchesAccessTokenIfExpired(self): request = SimpleRequest("/", "POST") self.stub_request_with_response(request) self.client._access_token = self.simpleaccesstoken() self.client._access_token.expires_in = 0 self.stubaccesstokenrequest() self.client.execute(request) self.assertEqual(2, len(responses.calls)) accesstokenrequest = responses.calls[0].request self.assertEqual(self.environment().base_url + "/v1/oauth2/token", accesstokenrequest.url) @responses.activate def testPayPalHttpClient_execute_doesNotFetchAccessTokenIfAuthorizationHeaderAlreadyPresent( self): request = SimpleRequest("/", "POST") request.headers["Authorization"] = "custom-header-value" self.stub_request_with_response(request) self.client.execute(request) self.assertEqual(1, len(responses.calls)) actualRequest = responses.calls[0].request self.assertEqual(self.environment().base_url + "/", actualRequest.url) self.assertEqual("custom-header-value", actualRequest.headers["Authorization"]) @responses.activate def testPayPalHttpClient_withRefreshToken_fetchesAccessTokenWithRefreshToken( self): request = SimpleRequest("/", "POST") self.stub_request_with_response(request) self.client = PayPalHttpClient(self.environment(), refresh_token="refresh-token") self.stubaccesstokenrequest(refresh_token="refresh-token") self.client.execute(request) self.assertEqual(2, len(responses.calls)) accesstokenrequest = responses.calls[0].request self.assertEqual(self.environment().base_url + "/v1/oauth2/token", accesstokenrequest.url) self.assertEqual("application/x-www-form-urlencoded", accesstokenrequest.headers["Content-Type"]) expectedauthheader = "Basic {0}".format( base64.b64encode(("{0}:{1}".format( self.environment().client_id, self.environment().client_secret)).encode()).decode()) self.assertEqual(expectedauthheader, accesstokenrequest.headers["Authorization"]) self.assertTrue("grant_type=refresh_token" in accesstokenrequest.body) self.assertTrue( "refresh_token=refresh-token" in accesstokenrequest.body) @responses.activate def testPayPalHttpClient_execute_setsCommonHeaders_signsRequest(self): self.client._access_token = self.simpleaccesstoken() request = SimpleRequest("/", "POST") self.stub_request_with_response(request) self.client.execute(request) self.assertEqual(len(responses.calls), 1) actualrequest = responses.calls[0].request self.assertEqual(actualrequest.headers["Accept-Encoding"], "gzip") self.assertEqual(actualrequest.headers["Authorization"], "Bearer sample-access-token") @responses.activate def testPayPalHttpClient_execute_refreshTokenRequest(self): refresh_token_request = RefreshTokenRequest(self.environment(), "auth-code") self.stub_request_with_response(refresh_token_request) self.client.execute(refresh_token_request) self.assertEqual(len(responses.calls), 1) actualrequest = responses.calls[0].request expectedauthheader = "Basic {0}".format( base64.b64encode(("{0}:{1}".format( self.environment().client_id, self.environment().client_secret)).encode()).decode()) self.assertEqual( actualrequest.url, self.environment().base_url + "/v1/identity/openidconnect/tokenservice") self.assertEqual(actualrequest.headers["Authorization"], expectedauthheader) self.assertEqual(actualrequest.headers["Content-Type"], "application/x-www-form-urlencoded") self.assertTrue("grant_type=authorization_code" in actualrequest.body) self.assertTrue("code=auth-code" in actualrequest.body)
class PaypalClient(PaymentSystemClient): """Клиент платёжной системы PayPal. Содержит методы для инициализации сессии и обработки платежей в виде PayPal Checkout - выписки, захвата, верификации и завершения Checkout.""" _link_pattern = PayPalStrings.LINK_PATTERN.value def __init__(self) -> None: """Инициализирует сессию работы с системой PayPal.""" # Creating an environment environment = SandboxEnvironment(client_id=PAYPAL_CLIENT_ID, client_secret=PAYPAL_CLIENT_SECRET) self.client = PayPalHttpClient(environment) self.process_notification = { # todo should this be here? PayPalStrings.WEBHOOK_APPROVED.value: self.capture, PayPalStrings.WEBHOOK_COMPLETED.value: self.fulfill, } def fulfill(self, wh_data: Dict[str, Any]) -> None: """Завершает заказ, уведомляет клиента.""" capture_id = wh_data['resource']['id'] try: checkout = Checkout.objects.fulfill_checkout(capture_id) send_payment_completed(checkout) except UpdateCompletedCheckoutError as e: print(e) def verify(self, request: HttpRequest) -> bool: """Проверяет соответствие подписи вебхука на случай попытки имитации оповещения. Возвращает результат проверки.""" print('RECEIVED A PAYPAL WEBHOOK') h = request.headers pprint(h) transmission_id = h['Paypal-Transmission-Id'] timestamp = h['Paypal-Transmission-Time'] actual_sig = h['Paypal-Transmission-Sig'] webhook_id = PAYPAL_WEBHOOK_ID cert_url = h['Paypal-Cert-Url'] auth_algo = h['PayPal-Auth-Algo'] if WebhookEvent.verify( transmission_id, timestamp, webhook_id, request.body.decode('utf-8'), cert_url, actual_sig, auth_algo ): return True else: # raise PayPalVerificationFailed() return False def capture(self, wh_data: Dict[str, Any]) -> None: """Выполняет операции, связанные с захватом средств после платежа""" # после выполнения capture приходит второй аналогичный по типу вебхук, содержащий сведения об оплате # todo вообще говоря, следует здесь сверять данные по позиции и сумме, а также комиссии if 'payments' in wh_data['resource']['purchase_units'][0]: return checkout_id = wh_data['resource']['id'] # if we call for a capture, then the customer has approved a payment for it Checkout.objects.update_checkout(checkout_id, PaypalOrderStatus.APPROVED.value) # Here, OrdersCaptureRequest() creates a POST request to /v2/checkout/orders request = OrdersCaptureRequest(checkout_id) # todo выделить в отдельный метод try: # Call API with your client and get a response for your call response = self.client.execute(request) # If call returns body in response, you can get the deserialized version # from the result attribute of the response order = response.result.id result = response.status_code if response.status_code == 201: capture_id = response.result.purchase_units[0].payments.captures[0].id Checkout.objects.update_capture(checkout_id, capture_id) print(order, result) except IOError as ioe: if isinstance(ioe, HttpError): # Something went wrong server-side print(ioe.status_code) print(ioe.headers) print(ioe) else: # Something went wrong client side print(ioe) def _initiate_payment_system_checkout(self, checkout_data: Dict[str, Any]) -> str: """Создаёт чекаут в системе PayPal, возвращает его id.""" pp_capture = PaypalCheckout.Schema().load(checkout_data) request = OrdersCreateRequest() request.prefer('return=representation') request.request_body(pp_capture.Schema().dump(pp_capture)) tracking_id: str = '' try: response = self.client.execute(request) if response.result.status == PaypalOrderStatus.CREATED.value: tracking_id = response.result.id else: print(response.status_code) for link in response.result.links: logger.debug('\t{}: {}\tCall Type: {}'.format(link.rel, link.href, link.method)) logger.debug('Total Amount: {} {}'.format(response.result.purchase_units[0].amount.currency_code, response.result.purchase_units[0].amount.value)) # If call returns body in response, you can get the deserialized version # from the result attribute of the response order = response.result logger.debug(order) except IOError as ioe: logger.error(f'Paypal failed Checkout creation{ioe}') if isinstance(ioe, HttpError): # Something went wrong server-side logger.error(ioe.status_code) return tracking_id def check_out(self, order_id: int, product_id: int) -> str: """Создаёт Checkout по параметрам заказа, возвращает соответствующий tracking_id.""" # todo create a builder? product = Product.objects.get_product_by_id(product_id) checkout_data = { 'intent': PaypalIntent.CAPTURE, 'purchase_units': [{ 'reference_id': str(order_id), 'description': product['description'][:127], 'amount': { 'currency_code': Currency.RUB, 'value': str(product['price'].amount), 'breakdown': { 'item_total': { 'currency_code': Currency.RUB, 'value': str(product['price'].amount), } }, }, 'items': [ { 'name': product['name'], 'description': product['description'][:127], 'unit_amount': { 'currency_code': Currency.RUB, 'value': str(product['price'].amount), }, 'quantity': 1, 'category': PaypalGoodsCategory.PHYSICAL_GOODS, } ] }], 'application_context': { 'shipping_preference': PaypalShippingPreference.GET_FROM_FILE, 'user_action': PaypalUserAction.PAY_NOW, } } checkout_id = self._initiate_payment_system_checkout(checkout_data) Checkout.objects.make_checkout(PaymentSystem.PAYPAL, checkout_id, order_id) approve_link = self._link_pattern.format(checkout_id=checkout_id) return approve_link
class PayGateWay(AbstractPayFactory): config = { "__sandbox": False, "__client_id": "应用ID", "__client_secret": "商户私钥", "__currency_code": "USD", "#说明": "去掉 __ 启用对应的选项,#号为备注字典" } paypal = None def __init__(self, data: dict): super(PayGateWay, self).__init__(data) _env_config = { 'client_id': self.config['client_id'], 'client_secret': self.config['client_secret'] } if self.config['sandbox']: environment = SandboxEnvironment(**_env_config) else: environment = LiveEnvironment(**_env_config) self.paypal = PayPalHttpClient(environment) def create_order(self, data: BaseTransactionSlip, *args, **kwargs) -> BaseCreateOrderResult: if not isinstance(data, BaseTransactionSlip): raise RuntimeError("请传入一个 BaseTransactionSlip 实例") # params = {"out_trade_no": data.sid, "subject": data.name, # "total_amount": data.price, "return_url": data.sync_url} request = OrdersCreateRequest() request.prefer('return=representation') request.request_body({ "application_context": { "return_url": data.sync_url }, "intent": "CAPTURE", '' "purchase_units": [{ "invoice_id": data.sid, "description": data.name, "amount": { "currency_code": self.config['currency_code'], "value": data.price } }] }) response = self.paypal.execute(request) print("创建订单数据") self.__print_paypal_response(response) for link in response.result.links: if link.rel == 'approve': return BaseCreateOrderResult(link.href) def notify_order(self, request, *args, **kwargs) -> BaseTransactionResult: print("=========收到异步通知数据=========") data = request.data print(data) print("=========收到异步通知数据=========") token = data['resource']['id'] _sid, _pid, _status = self.__order_get_request(token) if _status == 'APPROVED': orders_capture_request = OrdersCaptureRequest(data['token']) capture_res = self.paypal.execute(orders_capture_request) print(f"确认{token}订单并收款") self.__print_paypal_response(capture_res) res_status = BaseTransactionResult.SUCCESSFULLY_VERIFIED result = BaseTransactionResult(_sid, _pid, res_status) elif _status == 'COMPLETED': res_status = BaseTransactionResult.SUCCESSFULLY_VERIFIED result = BaseTransactionResult(_sid, _pid, res_status) else: res_status = BaseTransactionResult.SIGN_VERIFICATION_FAILED result = BaseTransactionResult(_sid, _pid, res_status) return result def return_order(self, data: dict, *args, **kwargs) -> BaseTransactionResult: print("=========收到同步通知数据=========") print(data) data = self.__deal_dict(data) print(data) print("=========收到同步通知数据=========") _sid, _pid, _status = self.__order_get_request(data['token']) res_status = BaseTransactionResult.UNKNOWN_PAYMENT_STATUS if _status == 'APPROVED': orders_capture_request = OrdersCaptureRequest(data['token']) capture_res = self.paypal.execute(orders_capture_request) print(f"确认{_pid}订单并收款") self.__print_paypal_response(capture_res) res_status = BaseTransactionResult.SUCCESSFULLY_VERIFIED result = BaseTransactionResult(_sid, _pid, res_status) return result def __order_get_request(self, token): request = OrdersGetRequest(token) response = self.paypal.execute(request) print(f"查询 {token} 订单数据") self.__print_paypal_response(response) _pid = response.result.id _purchase_units = response.result.purchase_units[0] _status = response.result.status _sid = _purchase_units['invoice_id'] return _sid, _pid, _status def query_order(self, data: BaseOrderId) -> dict: request = OrdersGetRequest(data.pid) response = self.paypal.execute(request) json_data = PayPalResultFormatUtil.object_to_json(response.result) return json_data def cancel_order(self, data: BaseOrderId) -> BaseCancelOrder: return BaseCancelOrder(status=False, detail={"msg": "PayPal 不支持取消未支付的订单"}) def request_refund(self, data: BaseRequestRefund) -> bool: request = OrdersGetRequest(data.pid) response = self.paypal.execute(request) capture_id = response.result.purchase_units[0].payments.captures[0].id print(f"退款数据 {capture_id}") self.__print_paypal_response(response) request = CapturesRefundRequest(capture_id) request.prefer("return=representation") _post_data = { "amount": { "value": f"{data.price}", "currency_code": self.config['currency_code'] } } request.request_body(_post_data) try: response = self.paypal.execute(request) return True except Exception as e: print(e) return False @staticmethod def __print_paypal_response(response): data = PayPalResultFormatUtil.object_to_json(response) print(json.dumps(data)) @staticmethod def __deal_dict(data: dict): _data = {} for i in data: if isinstance(data[i], list): _data[i] = data[i][0] else: _data[i] = data[i] return _data @staticmethod def gateway_config() -> dict: return PayGateWay.config @staticmethod def success_http() -> HttpResponse: """ When your app receives the notification message, it must respond with an HTTP 200-level status code. If your app responds with any other status code, PayPal tries to resend the notification message 25 times over the course of three days. @return: HttpResponse 200 """ return HttpResponse('success', status=status.HTTP_200_OK) @staticmethod def failed_http() -> HttpResponse: return HttpResponse('failed', status=status.HTTP_409_CONFLICT) @staticmethod def gateway_name(): return "PayPal" @staticmethod def gateway_description(): return "PayPal 接口"
class PayPalClient: def __init__(self): if settings.PAYPAL_USE_SANDBOX: environment = SandboxEnvironment( client_id=settings.PAYPAL_SANDBOX_CLIENT_ID, client_secret=settings.PAYPAL_SANDBOX_SECRET_KEY, ) else: environment = LiveEnvironment( client_id=settings.PAYPAL_LIVE_CLIENT_ID, client_secret=settings.PAYPAL_LIVE_SECRET_KEY, ) # Returns PayPal HTTP client instance with environment that # has access credentials context. Use this instance to invoke # PayPal APIs, provided the credentials have access. self.client = PayPalHttpClient(environment) def get_order(self, order_id): """Query the PayPal api for information about the order. Return the amount of the payment (in cents) upon success or 0 otherwise """ try: request = OrdersGetRequest(order_id) response = self.client.execute(request) except HttpError as e: logger.error('HttpError while fetching PayPal order: {}'.format(e)) return '', 0 try: assert response.result.intent == 'CAPTURE', 'bad payment intent' assert response.status_code == 200, 'bad http response code' assert response.result.status == 'COMPLETED', 'tx not completex' assert response.result.id == order_id, 'order id does not match' purchase = response.result.purchase_units[0] srb = purchase.payments.captures[0].seller_receivable_breakdown assert srb.paypal_fee.currency_code == 'USD', 'foreign currency' assert srb.net_amount.currency_code == 'USD', 'foreign currency' assert srb.gross_amount.currency_code == 'USD', 'foreign currency' parts = srb.paypal_fee.value.split('.') fee = int(parts[0]) * 100 + int(parts[1]) assert fee > 0, 'invalid fee amount' parts = srb.net_amount.value.split('.') net = int(parts[0]) * 100 + int(parts[1]) assert fee > 0, 'invalid net amount' parts = srb.gross_amount.value.split('.') gross = int(parts[0]) * 100 + int(parts[1]) assert fee > 0, 'invalid gross amount' assert fee + net == gross, 'conversion error' payment_id = purchase.payments.captures[0].id assert payment_id, 'missing paypal TransactionID' except AssertionError as e: logger.error( 'AssertionError while fetching PayPal order: {}'.format(e)) return '', 0 return payment_id, net, fee
def post(self): try: data = request.get_json() identity = get_jwt_identity() validation = order.validate_razorpay_paypal_cod_order(data) if validation['isValid']: if identity['id']: args = { 'user_id': identity['id'], 'user_amount': data['amount'], 'user_display_amount': data['displayAmount'], 'order_id': data['orderId'], 'coupon_id': data['couponId'] if 'couponId' in data else None } # Price check result = run_db_query( 'select _finaltotalvalue, status from ' ' store.fncheckprice(' '_user_id=>%(user_id)s, ' '_order_id=>%(order_id)s, ' '_coupon_id=>%(coupon_id)s, ' '_webtotalvalue=>%(user_amount)s )', args, 'price check call', True) if result == 'error': raise Exception elif result['status']: # Creating Access Token for Sandbox client_id = secrets['LIVE_PAYPAL_ID'] client_secret = secrets['LIVE_PAYPAL_SECRET'] # Creating an environment # environment = SandboxEnvironment(client_id=client_id, client_secret=client_secret) environment = LiveEnvironment( client_id=client_id, client_secret=client_secret) client = PayPalHttpClient(environment) order_request = OrdersCreateRequest() order_request.prefer('return=representation') order_request.request_body({ "intent": "CAPTURE", "purchase_units": [{ "amount": { "currency_code": "USD", "value": args['user_display_amount'] } }], "application_context": { "shipping_preference": 'NO_SHIPPING' } }) try: # Call API with your client and get a response for your call response = client.execute(order_request) if response.result and response.result.id: return { 'message': 'success', 'data': { 'orderId': response.result.id } }, 200 else: return { 'message': 'Error while completing payment, please retry.' }, 500 except IOError as ioe: if isinstance(ioe, HttpError): # Something went wrong server-side print(ioe.status_code) return { 'message': 'Error while completing payment, please retry.' ' If the issue still persists, try after sometime.' }, 500 else: return { 'message': 'Price changed for one or more product. Getting the latest price' }, else: return {'message': 'User Auth is missing.'}, 401 else: return {'message': 'Validation error, try again'}, 500 except Exception as e: app.logger.debug(e) return { 'message': 'Error while completing payment, please retry.' ' If the issue still persists, try after sometime.' }, 500
def initGatewayByReturn(request): # a get param named 'token' contains the order_id paypalSettings = getPayPalSettings() client = PayPalHttpClient(paypalSettings.environment) donation_id = None subscription_obj = {} kwargs = {} if request.GET.get('subscription_id', None): # recurring payment subscription_obj = getSubscriptionDetails( request.session, request.GET.get('subscription_id')) kwargs['subscription_obj'] = subscription_obj if 'custom_id' in subscription_obj: donation_id = subscription_obj['custom_id'] else: raise ValueError( _('Missing custom_id(donation_id) in curlPaypal-returned subscription' )) elif request.GET.get('token', None): # onetime payment req = OrdersGetRequest(request.GET.get('token')) # might throw IOError response = client.execute(req) _debug('PayPal: Returns from Gateway') _debug('PayPal: Order status: ' + response.result.status) donation_id = response.result.purchase_units[0].custom_id kwargs['order_id'] = request.GET.get('token') kwargs['order_status'] = response.result.status if not donation_id: raise ValueError( _("Missing donation_id in purchase_units custom_id attribute" )) else: raise ValueError(_("Missing token from PayPal request")) try: donation = Donation.objects.get(pk=donation_id) if request.GET.get('subscription_id', None): # raise error if paypal_subscription_id already found in DonationPaymentMeta dpm = DonationPaymentMeta.objects.filter( donation=donation, field_key='paypal_subscription_id', field_value=request.GET.get('subscription_id')) if len(dpm) >= 1: raise ValueError( _("PayPal subscription id found. Return request from PayPal is already invalid." )) else: dpm = DonationPaymentMeta( donation=donation, field_key='paypal_subscription_id', field_value=request.GET.get('subscription_id')) dpm.save() elif request.GET.get('token', None): # raise error if paypal_token already found in DonationPaymentMeta dpm = DonationPaymentMeta.objects.filter( donation=donation, field_key='paypal_token', field_value=request.GET.get('token')) if len(dpm) >= 1: raise ValueError( _("PayPal token found. Return request from PayPal is already invalid." )) else: dpm = DonationPaymentMeta( donation=donation, field_key='paypal_token', field_value=request.GET.get('token')) dpm.save() return Factory_Paypal.initGateway(request, donation, None, **kwargs) except Donation.DoesNotExist: raise ValueError( _("Donation object not found by id: ") + str(donation_id))