Untitled
unknown
ruby
8 months ago
5.4 kB
6
Indexable
module BxBlockInapppurchasing
class ProgramWebhooksController < ApplicationController
skip_before_action :validate_json_web_token, :current_user, only: [:apple_iap, :google_iap]
# Handle Apple IAP webhooks for programs
def apple_iap
signed_payload = params[:signedPayload]
decoded_payload = decode_jwt(signed_payload)
process_webhook_data(decoded_payload)
render json: { message: 'Success' }, status: :ok
rescue JWT::DecodeError => e
render json: { error: "JWT error: #{e.message}" }, status: :unprocessable_entity
end
# Handle Google IAP webhooks for programs
def google_iap
signed_payload = params[:message][:data]
decoded_payload = decode_base64(signed_payload)
manage_google_program(decoded_payload)
render json: { message: 'Success' }, status: :ok
rescue JWT::DecodeError => e
render json: { error: "JWT error: #{e.message}" }, status: :unprocessable_entity
rescue JSON::ParserError => e
render json: { error: "JSON parse error: #{e.message}" }, status: :unprocessable_entity
end
private
# Decode JWT token from Apple
def decode_jwt(signed_payload)
JWT.decode(signed_payload, nil, false).first
end
# Process Apple webhook data
def process_webhook_data(decoded_token)
transaction_info = decoded_token.dig('data', 'signedTransactionInfo')
webhook_response = JWT.decode(transaction_info, nil, false).first
manage_program(webhook_response) if webhook_response
end
# Process Apple program purchase
def manage_program(transaction)
program = find_program_by_apple_id(transaction['productId'])
user = get_user_from_transaction(transaction)
return unless program && user
ActiveRecord::Base.transaction do
program_purchase = create_program_purchase(user, program)
if program_purchase
create_program_subscriptions(user, program)
update_program_payment_history(transaction, user, program_purchase)
end
end
end
# Find program by Apple product ID
def find_program_by_apple_id(product_id)
BxBlockCustomUserSubs::Program.find_by(apple_product_id: product_id)
end
# Find program by Google product ID
def find_program_by_google_id(product_id)
BxBlockCustomUserSubs::Program.find_by(google_product_id: product_id)
end
# Create program purchase record
def create_program_purchase(user, program)
BxBlockCustomUserSubs::ProgramPurchase.create(
account_id: user.id,
program_id: program.id,
is_expire: false,
user_type: 'normal_user',
active: true
)
end
# Create subscription records for each subscription in the program
def create_program_subscriptions(user, program)
program.subscriptions.each do |subscription|
BxBlockCustomUserSubs::UserSubscription.create(
account_id: user.id,
subscription_id: subscription.id,
is_expire: false,
user_type: 'normal_user',
active: true
)
end
end
# Get user from transaction data
def get_user_from_transaction(transaction)
AccountBlock::Account.find_by(uuid: transaction['appAccountToken'])
end
# Update payment history for program purchase
def update_program_payment_history(transaction, user, program_purchase)
currency = transaction['currency'] || 'USD'
BxBlockStripeIntegration::PaymentHistory.create!(
account_id: user.id,
program_id: program_purchase.id,
payment_type: 'program',
amount: program_purchase.program&.price,
currency: currency,
status: 'success',
stripe_payment_intent_id: transaction['transactionId'] || @response['latestOrderId'],
payment_method: 'in_app_purchase',
customer_id: 'sk'
)
end
# Decode Base64 data from Google
def decode_base64(signed_payload)
decoded_data = Base64.decode64(signed_payload)
JSON.parse(decoded_data)
end
# Process Google program purchase
def manage_google_program(transaction)
notification = transaction['subscriptionNotification']
return unless valid_google_transaction?(notification)
user = get_google_user(transaction)
program = find_program_by_google_id(notification['subscriptionId'])
return unless user && program
ActiveRecord::Base.transaction do
program_purchase = create_program_purchase(user, program)
if program_purchase
create_program_subscriptions(user, program)
update_program_payment_history(notification, user, program_purchase)
end
end
end
# Get user from Google transaction
def get_google_user(transaction)
@response = BxBlockStripeIntegration::GoogleApiService.new(
transaction['packageName'],
transaction['subscriptionNotification']['purchaseToken']
).get_token unless Rails.env.test?
return nil if @response.nil? || @response[:error]
uuid = @response['externalAccountIdentifiers']['obfuscatedExternalAccountId']
AccountBlock::Account.find_by(uuid: uuid)
end
# Validate Google transaction
def valid_google_transaction?(transaction)
transaction['purchaseToken'].present? && transaction['notificationType'] == 4
end
end
endEditor is loading...
Leave a Comment