Skip to content

Instantly share code, notes, and snippets.

@jreviews
Created November 15, 2019 21:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jreviews/3113bf38e69d13dedd581d788d9495e2 to your computer and use it in GitHub Desktop.
Save jreviews/3113bf38e69d13dedd581d788d9495e2 to your computer and use it in GitHub Desktop.
How to do e-commerce with JReviews and Stripe https://www.jreviews.com/blog/ecommerce-with-jreviews-and-stripe
<?php
defined('MVC_FRAMEWORK') or die;
require dirname(dirname(__FILE__)).DS.'filters/stripe_config.php';
DeveloperController::macro('stripe_checkout', function() use ($stripe_config)
{
$config = $stripe_config;
$client = new \GuzzleHttp\Client();
if ( !($listingId = $this->params['id']) )
{
return $this->reponse->json()->not_found();
}
S2App::import('Component','listings_repository','jreviews');
$listingRepo = (new ListingsRepositoryComponent())->startup($this);
$listing = $listingRepo->whereListingId($listingId)->one();
$price = S2Array::get($listing,'Field.pairs.'.$config['price_field'].'.value.0',null);
if ( !$price )
{
return $this->response->json()->not_found();
}
$image = S2Array::get($listing,'MainMedia.media_info.image.url');
$data = [
'payment_method_types' => $config['payment_method_types'],
'line_items' => [
[
'name' => $listing['Listing']['title'],
'amount' => $price * 100, // Stripe works in cents
'currency' => $config['currency'],
'quantity' => 1,
'images' => $image ? [$image] : [],
]
],
'payment_intent_data' => [
'description' => $config['statement_descriptor'], // Statement Descriptor
'metadata' => [
'listing_id' => $listing['Listing']['listing_id'],
'title' => $listing['Listing']['title'],
'user_id' => $this->auth->id,
'name' => $this->auth->name
]
],
// ,'customer' => '' // This needs to be a Stripe customer object
'client_reference_id' => $this->auth->id,
'success_url' => $config['success_url'],
'cancel_url' => $config['cancel_url'] ?? cmsFramework::makeAbsUrl(cmsFramework::getCurrentUrl()),
];
$response = $client->post('https://api.stripe.com/v1/checkout/sessions', [
'auth' => [$config['stripe_sk'],''],
'form_params' => $data,
'http_errors' => false,
]);
if ( $response->getStatusCode() == 200 )
{
$checkoutSession = json_decode((string) $response->getBody(),true);
return $this->response->json()->array(['success'=>true,'session_id'=>$checkoutSession['id']]);
}
});
<?php
defined('MVC_FRAMEWORK') or die;
require 'stripe_checkout.php';
<?php
defined('MVC_FRAMEWORK') or die;
require_once 'stripe_config.php';
$jreviewsCheckout = new JReviewsCheckout($stripe_config);
Clickfwd\Hook\Filter::add('post_get_listing_detailpage_query', [$jreviewsCheckout, 'store_add_buy_button'], 10);
Clickfwd\Hook\Filter::add('before_theme_render_viewvars_com_content_com_content_view', [$jreviewsCheckout, 'stripe_bootstrap'], 10);
class JReviewsCheckout {
protected $config;
public function __construct($config)
{
$this->config = $config;
}
public function store_add_buy_button($listing, $params)
{
// Only process if the listing has a price set
if( !S2Array::get($listing,'Field.pairs.'.$this->config['price_field'].'.value.0',null) )
{
return $listing;
}
$auth = S2Object::make('auth');
$field = ['jr_store_buy'=>[
'field_id' => 99999,
'group_id' => 'store',
'name' => 'jr_store_buy',
'type' => 'banner',
'title' => '',
'value' => ['banner'],
'text' => ['banner'],
// We pass the listing ID as a data attribute so it can be sent to the server
// where we read the price and generate the Stripe checkout session ID
'description' => sprintf('%s', $this->config['buy_button_css'], $listing['Listing']['listing_id'], $this->config['buy_button_text']),
'image' => [],
'properties' => [
'show_title' => 0,
'location' => 'content',
'contentview' => 1,
'listview' => 0,
'listsort' => 0,
'search' => 0,
'access' => $auth->getAllAccessGroupId(),
'access_view' => $auth->getAllAccessGroupId(),
'output_format' => '{fieldtext}',
],
]
];
$group = ['store'=>[
'Group'=>[
'group_id'=> 'store',
'title'=> 'Store',
'name'=> 'store',
'show_title'=>0
],
'Fields'=>$field
]];
if ( !empty($listing['Field']['groups']) )
{
$listing['Field']['groups'] = array_merge($group,$listing['Field']['groups']);
}
if ( !empty($listing['Field']['pairs']) )
{
$listing['Field']['pairs'] = array_merge($field,$listing['Field']['pairs']);
}
return $listing;
}
public function stripe_bootstrap($viewVars, $params)
{
// Only process if the listing has a price set
if( !S2Array::get($viewVars,'listing.Field.pairs.'.$this->config['price_field'].'.value.0',null) )
{
return $viewVars;
}
cmsFramework::addScript('https://js.stripe.com/v3/', 'stripe-api');
$asset_manager = S2Object::make('asset_manager');
// The script below makes a request to DeveloperController::stripe_checkout, which is a custom
// method that we will add using a controller macro. We send the listing ID with this request.
$script = "
var stripe = Stripe('".$this->config['stripe_pk']."');
jreviews.stripeStore = {
bootstrap: function() {
jQuery('body').on('click','.jr-stripe-buy',function(e) {
e.preventDefault();
jreviews.dispatch({
method:'post',
type:'json',
controller:'developer',
action:'stripe_checkout',
data:{ id: jQuery(this).data('id') }
}).then( res => {
if ( res && res.success ) {
stripe.redirectToCheckout({ sessionId: res.session_id }).then(handleResult);
}
})
});
var handleResult = function(result) {
if (result.error) {
console.log(result.error);
}
};
}
};
if ( typeof head == 'function' ) {
head.ready(function() {
jreviews.addOnload('stripe-bootstrap',jreviews.stripeStore.bootstrap);
});
} else {
jreviews.addOnload('stripe-bootstrap',jreviews.stripeStore.bootstrap);
}
";
$asset_manager->addScript($script,'jreviews-stripe-checkout','addon');
return $viewVars;
}
}
<?php
defined('MVC_FRAMEWORK') or die;
$stripe_config = [
// Name of custom field you want to use for price information
'price_field' => 'jr_productprice',
// Get the private and secret keys from your Stripe dashboard and add them below.
'stripe_pk' => 'pk_live_........................',
'stripe_sk' => 'sk_live_........................',
// This appears in the client's credit card statement for the transaction
'statement_descriptor' => 'Statement Descriptor',
'currency' => 'usd',
// Include 'ideal' in the array below if you enable iDEAL payments in the Stripe dashboard,
// and set the currency to EUR which is required for iDEAL payments
'payment_method_types' => ['card'],
// Set 'billing_address_collection' to 'required' to always collect customer billing info
'billing_address_collection' => 'auto',
// Can use stripe template var {CHECKOUT_SESSION_ID}
// Create a success page on your site and update the URL below
'success_url' => 'https://your-domain/success-page',
// Create a cancel page on your site and update the URL below. Leave null to go back to referrer page.
'cancel_url' => null,
'buy_button_text' => 'Buy now',
'buy_button_css' => 'jrButton jrBlue',
];
@jreviews
Copy link
Author

To use these files, follow the instructions in the How to do e-commerce with JReviews and Stripe blog post.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment