{"id":19187834,"url":"https://github.com/bria222/shopping-cart-api","last_synced_at":"2026-05-05T13:33:43.952Z","repository":{"id":116016749,"uuid":"588009142","full_name":"Bria222/shopping-cart-api","owner":"Bria222","description":"Complete control over your cart integration. Tokenized cart sessions let you personalize, engage, and re-engage customers any way you want.","archived":false,"fork":false,"pushed_at":"2023-01-12T13:42:23.000Z","size":74,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-23T03:27:00.455Z","etag":null,"topics":["api-server","deployment-automation","docker","postgres","rest-api","ruby-on-rails","testing"],"latest_commit_sha":null,"homepage":"https://cimeza-africa.com/","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Bria222.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-12T05:19:48.000Z","updated_at":"2023-12-07T23:31:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"0c6822b5-cf91-491c-87ea-de31ea7bc9de","html_url":"https://github.com/Bria222/shopping-cart-api","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Bria222/shopping-cart-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bria222%2Fshopping-cart-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bria222%2Fshopping-cart-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bria222%2Fshopping-cart-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bria222%2Fshopping-cart-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Bria222","download_url":"https://codeload.github.com/Bria222/shopping-cart-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bria222%2Fshopping-cart-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32651396,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-05T11:29:49.557Z","status":"ssl_error","status_checked_at":"2026-05-05T11:29:48.587Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-server","deployment-automation","docker","postgres","rest-api","ruby-on-rails","testing"],"created_at":"2024-11-09T11:21:30.155Z","updated_at":"2026-05-05T13:33:43.933Z","avatar_url":"https://github.com/Bria222.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \"Buy now\" button with Ruby on Rails and Stripe Checkout API\n\n* [Live demo](https://cimeza-africa.com/)\n* [Github source](https://github.com/Bria222)\n* [Stripe Dashboard](https://dashboard.stripe.com/)\n* [Stripe test credit cards](https://stripe.com/docs/testing)\n* [Stripe Checkout Migration guide](https://stripe.com/docs/payments/checkout/migration)\n\nButton to buy a product\n![A screenshot of the app.](./shoplify-preview.png)\n\nRedirects to Stripe Checkout page\n![stripe checkout preview.](./stripe-checkout-preview.png)\n\n****\n\ngenerate scaffold:\n```\nrails g scaffold product name price:integer description:text --no-helper --no-assets --no-controller-specs --no-view-specs --no-test-framework --no-jbuilder \n```\n\n****\n\n[Guide: editing credentials](https://blog.corsego.com/ruby-on-rails-6-credentials-tldr)\n```\nEDITOR=vim rails credentials:edit\n```\n\n****\n\ncredentials.yml structure:\n```\nstripe:\n  public: YOUR_CODE\n  secret: YOUR_CODE\n  webhook: YOUR_CODE\n```\n\n****\n\n## Next step - associate current_user with stripe customer\n\n* create stripe customer when creating a user\n\n```\nafter_create do\n  customer = Stripe::Customer.create(\n    email: email,\n  )\n  update(stripe_customer_id: customer.id)\nend\n```\n\n* associate checkout to current user / customer\n\n```\n  customer: 'cus_123',\n```\n\n## Next step - Connect products from database with Stripe Products\n\n* add stripe_product_id to product\n\n```\nstripe_product = Stripe::Product.create(name: \"iphone 14\")\nstripe_price = Stripe::Price.create(currency: \"usd\", product: stripe_product, unit_amount: 77700, lookup_key: \"iphone 14\")\nproduct = Product.create(name: stripe_product.name, price: stripe_price.unit_amount, stripe_product_id: stripe_product.id)\n```\n\n* and update webhook to find current product correctly\n\n[stripe expand docs](https://stripe.com/docs/expand)\n\n```\nStripe::Checkout::Session.retrieve({ id: session.id, expand: [\"line_items\"]})\n```\n\n## Next step - list stripe products and pay for them (without local database table) \n\nview\n```\n\u003c% @prices = Stripe::Price.list(lookup_keys: ['iphone 14', 'iphone 15'], expand: ['data.product']).data.sort_by {|p| p.unit_amount} %\u003e\n\u003c% @prices.each do |price| %\u003e\n  \u003cbr\u003e\n  \u003c%= price.product.name %\u003e\n  \u003c%= button_to checkout_create_path(price: price.id), remote: true, data: { disable_with: \"Connecting...\" } do %\u003e\n    Buy now\n    \u003c%= price.unit_amount/100 %\u003e\n    \u003c%= price.currency %\u003e\n  \u003c% end %\u003e\n\u003c% end %\u003e\n```\ncontroller\n```\n@session = Stripe::Checkout::Session.create({\n  payment_method_types: ['card'],\n  line_items: [{\n    price: params[:price],\n    quantity: 1\n  }],\n  mode: 'payment',\n  success_url: root_url,\n  cancel_url: root_url,\n})\n```\n\n## display Checkout API data on success\n\ncontroller\n```\nsuccess_url: root_url + '?session_id={CHECKOUT_SESSION_ID}',\n```\nview\n```\n\u003c% if params[:session_id].present? %\u003e\n  \u003c% @session = Stripe::Checkout::Session.retrieve(params[:session_id]) %\u003e\n  \u003c% @payment_intent = Stripe::PaymentIntent.retrieve(@session.payment_intent) %\u003e\n\n  Payement amount: \n  \u003c%= number_to_currency @payment_intent.amount_received / 100.0 %\u003e.\u003c/p\u003e\n  Payment status: \n  \u003c%= @payment_intent.status %\u003e\n  \u003cbr\u003e\n  \u003c%= debug @session %\u003e\n  \u003c%= debug @payment_intent %\u003e\n\u003c% end %\u003e\n```\n\n## possible webhook for retreiving products\n\n```\nwhen \"checkout.session.completed\"\nsession = event.data.object\nuser = User.find_by(stripe_customer_id: session.customer)\ncheckout_with_items = Stripe::Checkout.Session.retrieve({id: session.id, expand: [\"line_items\"]})\ncheckout_with_items.line_items.data.each do |line_item|\n  product = Product.find_by(stripe_product_id: line_item.price.product)\n  user.user_products.create(product: product, price: line_item.price.unit_amount)\n  product.increment!(:sales_count)\nend\n```\n\n## session-based shopping cart\n\nproducts/index inside table\n```\n\u003c% if @cart.include?(product) %\u003e\n  \u003c%= button_to \"Remove from cart\", remove_from_cart_path(product), method: :delete %\u003e\n\u003c% else %\u003e\n  \u003c%= button_to \"Add to cart\", add_to_cart_path(product) %\u003e\n\u003c% end %\u003e\n```\nroutes\n```\npost \"products/add_to_cart/:id\", to: \"products#add_to_cart\", as: \"add_to_cart\"\ndelete \"products/remove_from_cart/:id\", to: \"products#remove_from_cart\", as: \"remove_from_cart\"\n```\nproducts_controller.rb\n```\n  def add_to_cart\n    id = params[:id].to_i\n    session[:cart] \u003c\u003c id unless session[:cart].include?(id)\n    redirect_to products_path\n  end\n\n  def remove_from_cart\n    id = params[:id].to_i\n    session[:cart].delete(id)\n    redirect_to products_path\n  end\n```\napplication_controller\n```\n  before_action :initialize_session\n  before_action :load_cart\n\n  private\n\n  def initialize_session\n    session[:cart] ||= [] # empty cart = empty array\n  end\n\n  def load_cart\n    @cart = Product.find(session[:cart])\n  end\n```\napplication.html.erb\n```\n\u003ch1\u003eShopping cart\u003c/h1\u003e\nItems:\n\u003c%= @cart.size %\u003e\n\u003cbr\u003e\n\u003c% @cart.each do |cart_item| %\u003e\n  \u003cbr\u003e\n  \u003c%= cart_item.name %\u003e\n  \u003c%= link_to \"x\", remove_from_cart_path(cart_item), method: :delete %\u003e\n\u003c% end %\u003e\n```\n\n## transform items from shopping cart into stripe line_items\nproduct.rb\n```\ndef to_builder\n\tJbuilder.new do |product|\n\t  product.price stripe_price_id\n\t  product.quantity 1\n\tend\nend\n```\ncheckout_controller\n```\n@cart.collect { |item| item.to_builder.attributes! },\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbria222%2Fshopping-cart-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbria222%2Fshopping-cart-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbria222%2Fshopping-cart-api/lists"}