Untitled
unknown
ruby
a month ago
5.4 kB
5
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 end
Editor is loading...
Leave a Comment