Last active
October 3, 2019 13:08
-
-
Save lucashour/af4b666cabd488b1c9fd429776d24a61 to your computer and use it in GitHub Desktop.
RoR: Mercado Pago webhooks integration
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/services/mercadopago_client/base.rb | |
module MercadopagoClient | |
class Base | |
require 'mercadopago' | |
STATUSES = [ | |
APPROVED = 'approved', | |
BPP_COVERED = 'bpp_covered', | |
CHARGED_BACK = 'charged_back', | |
IN_MEDIATION = 'in_mediation', | |
IN_PROCESS = 'in_process', | |
PARTIALLY_REFUNDED = 'partially_refunded', | |
REFUNDED = 'refunded', | |
REJECTED = 'rejected' | |
].freeze | |
TOPICS = [ | |
PAYMENT = 'payment', | |
CHARGEBACKS = 'chargebacks' | |
].freeze | |
private | |
def connector | |
MercadoPago.new(Rails.application.secrets['mercadopago']['access_token']) | |
end | |
def valid_response?(response) | |
['200', '201'].include?(response[:status].to_s) | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/services/mercadopago_client/webhook.rb | |
module MercadopagoClient | |
class Webhook < Base | |
def initialize(params) | |
@params = params | |
end | |
def call | |
case @params[:topic] | |
when PAYMENT then process_payment_webhook | |
when CHARGEBACKS then process_chargeback_webhook | |
end | |
true | |
rescue | |
false | |
end | |
private | |
def process_payment_webhook | |
payment = gateway_payment@params[:id]) | |
return false unless payment | |
data = payment[:response][:collection] | |
status = data[:status] | |
status_detail = data[:status_detail] | |
@invoice = Invoice.find(data[:external_reference]) | |
if bpp_covered_refund?(status, status_detail) | |
process_bpp_covered_refund(data) | |
elsif refunded?(status, status_detail) | |
process_refund(data[:refunds]) | |
elsif charged_back?(status, status_detail) | |
process_charged_back_payment | |
elsif in_mediation?(status) | |
process_in_mediation_payment | |
elsif in_process?(status) | |
process_in_process_payment | |
elsif rejected?(status) | |
process_rejected_payment | |
elsif approved?(status) | |
process_created_payment(data) | |
end | |
end | |
def bpp_covered_refund?(status, status_detail) | |
status == REFUNDED && status_detail == BPP_COVERED | |
end | |
def refunded?(status, status_detail) | |
status == REFUNDED || status_detail == PARTIALLY_REFUNDED | |
end | |
def charged_back?(status, status_detail) | |
status == CHARGED_BACK && status_detail == IN_PROCESS | |
end | |
def in_mediation?(status) | |
status == IN_MEDIATION | |
end | |
def in_process?(status) | |
status == IN_PROCESS | |
end | |
def rejected?(status) | |
status == REJECTED | |
end | |
def approved?(status) | |
status == APPROVED | |
end | |
def process_chargeback_webhook | |
return unless chargeback | |
payment = gateway_payment(chargeback[:payments].first) | |
return unless payment | |
# ... | |
end | |
def process_chargeback(payment_transaction, payment) | |
# ... | |
end | |
def unsolved_chargeback? | |
chargeback[:coverage_applied].nil? | |
end | |
def chargeback_favorable_resolution? | |
chargeback[:coverage_applied] | |
end | |
def process_refund(refunds) | |
# ... | |
end | |
def process_bpp_covered_refund(data) | |
# ... | |
end | |
def process_charged_back_payment | |
# ... | |
end | |
def process_in_mediation_payment | |
# ... | |
end | |
def process_in_process_payment | |
# ... | |
end | |
def process_rejected_payment | |
# ... | |
end | |
def process_created_payment(data) | |
# ... | |
end | |
def gateway_payment(id) | |
data = connector | |
.get_payment_info(id.to_s) | |
.deep_symbolize_keys | |
valid_response?(data) ? data : false | |
end | |
def chargeback | |
return @chargeback if @chargeback | |
data = connector | |
.get("/v1/chargebacks/#{@params[:id]}") | |
.deep_symbolize_keys | |
@chargeback = valid_response?(data) ? data : false | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/controllers/api/v1/webhooks_controller.rb | |
class Api::V1::WebhooksController < ApiController | |
def mercadopago | |
MercadopagoClient::Webhook.new(params).delay.call # Using Delayed::Job | |
render nothing: true, status: :ok | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment