Skip to content

Instantly share code, notes, and snippets.

  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save iloveitaly/c384b6dc0ca1cc81d10cba729e05b1f9 to your computer and use it in GitHub Desktop.
# Michael Bianco <mike@suitesync.io>
# Description: Boilerplate implementing linking Stripe Charges to NetSuite Invoices
# Documentation: Reach out to SuiteSync for additional documentation!
# requires the following environment variables:
#
# STRIPE_KEY
# NETSUITE_EMAIL
# NETSUITE_PASSWORD
# NETSUITE_ACCOUNT
require 'stripe'
require 'netsuite'
# Replace this test mode key and run this example on your account
Stripe.api_key = ENV['STRIPE_TEST_KEY']
NetSuite.configure do
reset!
# NOTE that API versions > 2015_1 require a more complicated authentication setup
api_version '2015_1'
read_timeout 60 * 3
silent ENV['NETSUITE_SILENT'].nil? || ENV['NETSUITE_SILENT'] == 'true'
email ENV['NETSUITE_EMAIL']
password ENV['NETSUITE_PASSWORD']
account ENV['NETSUITE_ACCOUNT']
soap_header({
'platformMsgs:preferences' => {
'platformMsgs:ignoreReadOnlyFields' => true,
}
})
end
# Fake order class to generate a Stripe customer, charge, and NS items
class Order
class << self
def find(*)
customer = create_stripe_customer
create_stripe_token_with_customer(customer)
charge = Stripe::Charge.create(
amount: 10_00,
currency: "usd",
customer: customer.id,
# this is optional. The `description` is passed through to the CustomerPayment memo field
description: "A Stripe shirt and NetSuite shoes",
metadata: {
# more info on this feature: https://dashboard.suitesync.io/docs/field-customization#controlling-when-records-are-created-in-netsuite
netsuite_block_translation: true
}
)
OpenStruct.new(
stripe_charge_id: charge.id,
# NOTE this is just an example ID of a customer in NetSuite to faciliate creating a SalesOrder!
# https://system.na1.netsuite.com/app/common/entity/custjoblist.nl
netsuite_customer_id: 235724,
items: [
OpenStruct.new(
netsuite_id: create_netsuite_item.internal_id,
quantity: 1,
price: 10.0
)
],
number: "T#{Time.now.to_i}"
)
end
private
def create_netsuite_item
ns_inventory_item = NetSuite::Records::InventoryItem.new(
item_id: "suitesync_test_item",
display_name: "SuiteSync Test Item",
external_id: "suitesync_test_item",
)
# in order to fulfill this item in a testing environment, you'll need to adjust the inventory
# https://system.na1.netsuite.com/app/accounting/transactions/invadjst.nl
NetSuite::Utilities.backoff { ns_inventory_item.upsert }
if NetSuite::Utilities.request_failed?(ns_inventory_item)
fail("failed to upsert item. #{ns_inventory_item.errors}")
end
ns_inventory_item
end
def create_stripe_customer
Stripe::Customer.create(description: "Customer")
end
def create_stripe_token_with_customer(stripe_customer)
# Create a card token to be associated with a customer. This is normally done
# on your payment frontend using Stripe.js https://stripe.com/docs/custom-form
card_token = Stripe::Token.create(
:card => {
:number => '4242424242424242',
:exp_month => 8,
:exp_year => (Date.today>>24).year,
:cvc => "314",
}
)
stripe_customer.sources.create(card: card_token.id)
end
end
end
class NetSuiteWorker
def perform(type)
order = Order.find
netsuite_class = if type == :sales_order
NetSuite::Records::SalesOrder
elsif type == :invoice
NetSuite::Records::Invoice
end
ns_order = netsuite_class.new(
# It is highly recommended to use the order unique identifier as the external ID
external_id: order.number,
entity: { internal_id: order.netsuite_customer_id },
item_list: build_item_list(order),
)
# This custom field must be created in NetSuite
ns_order.custom_field_list.custbody_suitesync_authorization_code = order.stripe_charge_id
NetSuite::Utilities.backoff { ns_order.upsert }
if NetSuite::Utilities.request_failed?(ns_order)
fail("failed to upsert order. #{ns_order.errors}")
end
ns_order
end
protected
def build_item_list(order)
items = order.items.map do |line_item|
{
item: { internal_id: line_item.netsuite_id },
quantity: line_item.quantity,
rate: line_item.price
}
end
{ item: items }
end
end
ns_invoice = NetSuiteWorker.new.perform(:invoice)
# A SalesOrder must be billed to create an Invoice
# once an invoice is created, SuiteSync will create a CustomerPayment and apply it to the invoice
ns_order = NetSuiteWorker.new.perform(:sales_order)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment