class Workarea::Paypal::Gateway

Public Instance Methods

capture(order_id) click to toggle source
# File lib/workarea/paypal/gateway.rb, line 60
def capture(order_id)
  request = PayPalCheckoutSdk::Orders::OrdersCaptureRequest.new(order_id)
  request.prefer("return=representation")

  if ENV['PAYPAL_MOCK_RESPONSE'].present? && Rails.env.in?(%w(test development))
    request.headers['PayPal-Mock-Response'] = ENV['PAYPAL_MOCK_RESPONSE']
  end

  handle_transaction_errors do
    response = send_request(request)
    result = response.result
    capture = result&.purchase_units&.first&.payments&.captures&.last
    success = response.status_code == 201 && capture&.status != 'DECLINED'

    ActiveMerchant::Billing::Response.new(
      success,
      "PayPal capture #{success ? 'succeeded' : 'failed'}",
      Paypal.transform_values(success ? capture : result)
    )
  end
end
client() click to toggle source
# File lib/workarea/paypal/gateway.rb, line 14
def client
  PayPal::PayPalHttpClient.new(environment)
end
client_id() click to toggle source
# File lib/workarea/paypal/gateway.rb, line 150
def client_id
  ENV['WORKAREA_PAYPAL_CLIENT_ID'].presence ||
    Rails.application.credentials.paypal.try(:[], :client_id) ||
    Workarea.config.paypal_client_id
end
configured?() click to toggle source
# File lib/workarea/paypal/gateway.rb, line 146
def configured?
  client_id.present? && client_secret.present?
end
create_order(body:) click to toggle source
# File lib/workarea/paypal/gateway.rb, line 40
def create_order(body:)
  request = PayPalCheckoutSdk::Orders::OrdersCreateRequest.new
  request.request_body(body)

  handle_connection_errors do
    response = send_request(request)
    response.result
  end
end
create_webhook(url:, event_types:) click to toggle source
# File lib/workarea/paypal/gateway.rb, line 117
def create_webhook(url:, event_types:)
  request = Workarea::Paypal::Requests::CreateWebhook.new
  request.request_body(
    url: url,
    event_types: Array.wrap(event_types).map { |type| { name: type } }
  )

  response = handle_connection_errors { send_request(request) }

  throw_request_error(response) unless response.status_code == 201
  response
end
delete_webhook(webhook_id) click to toggle source
# File lib/workarea/paypal/gateway.rb, line 130
def delete_webhook(webhook_id)
  request = Workarea::Paypal::Requests::DeleteWebhook.new(webhook_id)
  response = handle_connection_errors { send_request(request) }

  throw_request_error(response) unless response.status_code == 204
  response
end
environment() click to toggle source
# File lib/workarea/paypal/gateway.rb, line 6
def environment
  @environment =
    Workarea.config.paypal_environment.constantize.new(
      client_id,
      client_secret
    )
end
generate_token(user: nil) click to toggle source

This gets a token required to render hosted fields. Not used for smart payment buttons.

# File lib/workarea/paypal/gateway.rb, line 27
def generate_token(user: nil)
  request = Workarea::Paypal::Requests::GenerateToken.new
  id = user&.id.to_s.last(22) # length limit
  request.request_body(customer_id: id) if user.present?

  handle_connection_errors { send_request(request) }
end
get_order(order_id) click to toggle source
# File lib/workarea/paypal/gateway.rb, line 35
def get_order(order_id)
  request = PayPalCheckoutSdk::Orders::OrdersGetRequest.new(order_id)
  handle_connection_errors { send_request(request) }
end
list_webhooks() click to toggle source
# File lib/workarea/paypal/gateway.rb, line 138
def list_webhooks
  request = Workarea::Paypal::Requests::ListWebhooks.new
  response = handle_connection_errors { send_request(request) }

  throw_request_error(response) unless response.status_code == 200
  response
end
refund(capture_id, amount: nil) click to toggle source

No body means refunding the entire captured amount, otherwise an amount object needs to be supplied.

# File lib/workarea/paypal/gateway.rb, line 85
def refund(capture_id, amount: nil)
  request = PayPalCheckoutSdk::Payments::CapturesRefundRequest.new(capture_id)
  request.prefer("return=representation")

  if amount.present?
    request.request_body(
      amount: {
        value: amount.to_s,
        currency_code: amount.currency.iso_code
      }
    )
  end

  handle_transaction_errors do
    response = send_request(request)
    refund = response.result
    success = response.status_code == 201 && refund.status != 'CANCELLED'

    ActiveMerchant::Billing::Response.new(
      success,
      "PayPal refund #{success ? 'succeeded' : 'failed'}",
      {
        id: refund.id,
        status: refund.status,
        status_details: refund.status_details.to_h,
        capture_id: capture_id,
        amount: amount.to_s
      }
    )
  end
end
send_request(request) click to toggle source
# File lib/workarea/paypal/gateway.rb, line 18
def send_request(request)
  # Do not change this
  request.headers["PayPal-Partner-Attribution-Id"] = 'Workarea_SP'

  client.execute(request)
end
update_order(order_id, body: {}) click to toggle source
# File lib/workarea/paypal/gateway.rb, line 50
def update_order(order_id, body: {})
  request = PayPalCheckoutSdk::Orders::OrdersPatchRequest.new(order_id)
  request.request_body(body)

  handle_connection_errors do
    response = send_request(request)
    response.result
  end
end

Private Instance Methods

client_secret() click to toggle source
# File lib/workarea/paypal/gateway.rb, line 158
def client_secret
  ENV['WORKAREA_PAYPAL_CLIENT_SECRET'].presence ||
    Rails.application.credentials.paypal.try(:[], :client_secret) ||
    Workarea.config.paypal_client_secret
end
handle_connection_errors() { || ... } click to toggle source
# File lib/workarea/paypal/gateway.rb, line 174
def handle_connection_errors
  begin
    yield
  rescue PayPalHttp::HttpError => error
    Rails.logger.error(error.message)
    Rails.logger.error(error.result)
    throw_request_error(error)
  end
end
handle_transaction_errors() { || ... } click to toggle source
# File lib/workarea/paypal/gateway.rb, line 184
def handle_transaction_errors
  begin
    yield
  rescue PayPalHttp::HttpError => error
    ActiveMerchant::Billing::Response.new(
      false,
      I18n.t('workarea.paypal.gateway.capture_error'),
      status_code: error.status_code,
      debug_id: error.headers['paypal-debug-id']
    )
  rescue StandardError => error
    ActiveMerchant::Billing::Response.new(false, error.message, {})
  end
end
throw_request_error(error) click to toggle source
# File lib/workarea/paypal/gateway.rb, line 164
def throw_request_error(error)
  raise RequestError.new(
    I18n.t(
      'workarea.paypal.gateway.http_error',
      status: error.status_code,
      debug_id: error.headers['paypal-debug-id']
    )
  )
end