I'm using Stripe's php library to create a customer with a subscription that contains a coupon. I don't want to add the coupon at the customer level, I want to add it at the subscription level. The below code is what I'm currently using and according to their support, this should work, but it doesn't. I was hoping someone will be able to help.
$params = array(
'card'=>'SOME_TOKEN_FROM_JS_LIBRARY',
'plan'=>'valid_plan_id',
'coupon'=>'valid_coupon_id'
);
$c = Stripe_Customer::create($params);
if(!empty($params['coupon'])){
$c->updateSubscription(array(
'plan'=>$params['plan'],
'coupon'=>$params['coupon']
));
}
This successfully creates the customer and charges the card with the coupon applied.
Ended up going with the code below, it does what I want it to do. Also, the goal with the code below is to delete the customer if the charge fails for whatever reason, so I'm not left with customers that don't belong anywhere.
$_c = Stripe_Customer::create($params);
try{
$_c->subscriptions->create(array('plan'=>$plan, 'coupon'=>$coupon));
}catch(Exception $e){
$_c->delete();
throw new Exception($e->getMessage());
}
$c = Stripe_Customer::retrieve($_c->id); //to get the customer object with the latest data
Related
I'm working on getting all the active members in our Braintree account. I can list all customers but I don't know how to list the active ones.
In the Braintree dashboard, I can easily see it by going to subscriptions and filtering all Active subscriptions then clicking the subscription ID. From there I can see which customer has that subscription ID.
Then I tried getting all the active subscriptions first but I can't find any connection with any customers either.
I'm using the PHP SDK.
Here's how I get our active subscriptions.
My subscription code in my library:
function active_subscriptions(){
return Braintree_Configuration::gateway()->subscription()->search([
Braintree_SubscriptionSearch::status()->in([Braintree_Subscription::ACTIVE])
]);
}
Here's for the controller:
function active_subscriptions(){
$active_subscriptions = $this->braintree_lib->active_subscriptions();
$counter = 5;
foreach($active_subscriptions as $subscription) {
if($counter == 0){
die();
}
echo 'Subscription ID: '.$subscription->id.'<br />';
echo 'merchantAccountId: '.$subscription->merchantAccountId.'<br />';
echo 'planId: '.$subscription->planId.'<br /><br />';
$counter--;
}
}
I found this but it's in Ruby on Rails and there are no details about it in the documentation.
Full disclosure: I work at Braintree. If you have any further questions, feel free to contact
support.
Just to make sure I understand the result you are looking for: You are currently attempting to retrieve all of the customer records that are tied to active subscriptions, correct?
If so, you can achieve this by doing the following:
Iterate over the collection of active subscriptions you received from your search result.
Parse each subscription object for the payment method token associated to each subscription.
Separately, run a paymentMethod.find() call to retrieve the payment method's object.
The payment method object will contain the customer ID.
After following the above steps you can then create a list from your results, which will contain all customers with active subscriptions.
Here is a basic example of how this would be achieved:
$collection = $gateway->subscription()->search([
Braintree_SubscriptionSearch::status()->in(
[Braintree_Subscription::ACTIVE]
)
]);
foreach($collection as $subscription) {
$token = $subscription->paymentMethodToken;
$paymentMethod = $gateway->paymentMethod()->find($token);
$customer = $paymentMethod->customerId;
echo $customer . "\n";
}
If this isn't what you are looking for, or if you have any additional questions you can reach out to Braintree Support directly and we can assist you further.
OK, I've been banging my head against this for a few days now. I'm building a payment process into a PHP application which will allow for upselling products after a customer approves a payment.
I can get the payment charged to the customer without an issue, but if they select any kind of upsell product which requires the order value to change, then I get errors even though it is following to the letter what was in the documentation I could find...
Below is the test function I'm using, this is the function which is called when the user is redirected back to the website AFTER approving the payment.
public function confirmOrder($payer_id, $payment_id, $incentives = false){
//GET PAYMENT
$payment = Payment::get($payment_id, $this->apiContext);
//CREATE EXECUTION WITH PAYER ID
$execution = new PaymentExecution();
$execution->setPayerId($payer_id);
//APPLY PAYMENT AMOUNT - Original amount was 7.00
$amount = new Amount();
$amount = $amount->setCurrency('GBP')->setTotal('8.00');
//PATCH REPLACE
$patchReplace = new Patch();
$patchReplace = $patchReplace->setOp('replace')->setPath('/transactions/0/amount')->setValue($amount);
//CREATE PATCH OBJECT
$patchRequest = new PatchRequest();
$patchRequest = $patchRequest->setPatches(array($patchReplace));
try {
$payment->update($patchRequest, $this->apiContext);
} catch (PayPalConnectionException $ex) {
return "PATCH ERROR: State(" . $payment->getState() . ") ".$ex->getData();
}
}
This isn't the final code I will use but right now I'm just trying to get an order updated before I build in more of the logic. This code gives me the following error:
PATCH ERROR: State(created) {"name":"PAYMENT_STATE_INVALID","message":"This request is invalid due to the current state of the payment","information_link":"https://developer.paypal.com/webapps/developer/docs/api/#PAYMENT_STATE_INVALID","debug_id":"9caacdc1d652b"}
You can see I'm outputting the getState() which is coming back as 'created' which would normally be fine for updating in everything I can find but it is still failing.
Does anyone else have experience with the PayPal PHP SDK and could help point me in the right direction?
In PayPal, once the user has approved the payment from the consent screen, the amount cannot be changed, as you can understand the user agreed to pay only the amount he/she saw on the consent screen. Modifying the amount after user approves it, is not allowed, and that's why you are seeing that state exception, as the state is already approved.
Anyway, looking at your scenario, I think you might be interested in either creating order, or capture, instead of sale.
Also, in our PayPal-PHP-SDK, there are a lot of interesting documents that could help you understand PHP-SDK better. We also provide a lot of runnable samples, that you could setup in your local machine, by one command only.
I am trying to create a paypal payment page, but for some reason when I try to add a custom web profile to the payment the option of checking out as a guest suddenly disappears.
First I am creating the web profile this way:
$flowConfig = new FlowConfig();
$flowConfig
->setLandingPageType("billing")
->setBankTxnPendingUrl("...");
$presentation = new Presentation();
$presentation
->setLogoImage("...")
->setBrandName("...")
->setLocaleCode("...");
$inputFields = new InputFields();
$inputFields
->setNoShipping(1)
->setAddressOverride(0);
$webProfile = new WebProfile();
$webProfile->setName("PROFILE" . uniqid())
->setFlowConfig($flowConfig)
->setPresentation($presentation)
->setInputFields($inputFields);
$request = clone $webProfile;
try {
$createProfileResponse = $webProfile->create($apiContext);
} catch (PayPal\Exception\PayPalConnectionException $ex) {
...
}
$profileId = $createProfileResponse->getId();
Then, I have updated the payment code in this way
$paypalPayment = new PayPalPayment();
$paypalPayment->setIntent("sale");
$paypalPayment->setPayer($payer);
$paypalPayment->setRedirectUrls($redirectUrls);
$paypalPayment->setTransactions(array($transaction));
$paypalPayment->setExperienceProfileId($profileId);
The weird thing is that if I comment the last line I can perform payments as a guest without any issue. If, instead, I leave it this way, I get the customized page but the "Check out as a guest" button is replaced by "Create an account".
Do I really have to choose between having a customized checkout page and the possibility to perform payments without creating paypal accounts? Or am I missing something? I didn't find anything related to this issue in the documentation nor here in stackoverflow, and it seems at least strange!
Thank you
Are you using Express Checkout? It looks like recurring payments without a PayPal account are only compatible with Website Payments Pro accounts.
You can still create recurring payments with EC but they will need a PayPal account to accept them, no guest checkout allowed by the looks of it.
https://www.paypal-community.com/t5/Merchant-services-Archive/How-to-accept-recurring-payments-from-buyers-who-don-t-have-a/td-p/178232
I am using Magento 1.7.0.2. Whilst on the product page, if a customer attempts to add a quantity greater than we have in stock they receive a message stating ".. the requested quantity is not available".
Is there any way for magento to either email or log when this occurs? I.e. I receive an automatic email stating a customer has attempted to add X number of item X? This would allow me to identify lost sales due to us not having enough stock of a particular item?
Has anyone come across anything like this before or is this even possible?
Thank you in advance
Mike Prentice
yes this is possible
You have to code for this.
I came across this problem one time and what i have do like this below.
I have make one observer event to check if customer is requesting quantity more then available if so i sent email to admin.
What you can do is create one observer for chekout_cart_add_before event in this event you can put your logic.
Or otherwise you can use magento feature Backorders you can find this in inventory tab,if you enable this then customer can order even requested quantity > available quantity, customer can see one message in cart page about backorder.
There is no standart functionality to notify about low quantity products by email.
But there is RSS notification http://www.magentocommerce.com/wiki/modules_reference/english/mage_adminhtml/system_config/edit/cataloginventory
Extend this functionality to match your needs.
You could write some script which would parse RSS, and send email etc.
EDIT
Here is some extension you may like http://www.magentocommerce.com/magento-connect/low-stock-email-notification.html
But is is not free.
Here's how I've done it so that it sends a google analytics tracking event whenever a customer tries to order more than the available stock level.
First copy: app/code/core/Mage/CatalogInventory/Model/Stock/Item.php
To: app/code/local/Mage/CatalogInventory/Model/Stock/Item.php
so that you're not modifying a core file.
In app/code/local/Mage/CatalogInventory/Model/Stock/Item.php add this function
public function notifyOutOfStock($productId){
$session = Mage::getSingleton('checkout/session');
//Initialise as empty array, or use existing session data
$outOfStockItems = array();
if ($session->getOutOfStock()){
$outOfStockItems = $session->getOutOfStock();
}
try {
$product = Mage::getModel('catalog/product')->load($productId);
$sku = $product->getSKu();
if($sku){
//Add the current sku to our out of stock items (if not already there)
if(! isset($outOfStockItems[$sku]) ) {
$outOfStockItems[$sku] = 0;
}
}
} catch (Exception $e){
//Log your error
}
Mage::getSingleton('checkout/session')->setOutOfStock($outOfStockItems);
}
In that same file is another function called checkQuoteItemQty.
Inside that function you need to call your new function using $this->notifyOutOfStock($this->getProductId()); right after it sets each of the error messages and before the return statement.
So:
public function checkQuoteItemQty($qty, $summaryQty, $origQty = 0)
{
....
if ($this->getMinSaleQty() && ($qty) < $this->getMinSaleQty()) {
$result->setHasError(true)
->setMessage(
$_helper->__('The minimum quantity allowed for purchase is %s.', $this->getMinSaleQty() * 1)
)
->setQuoteMessage($_helper->__('Some of the products cannot be ordered in requested quantity.'))
->setQuoteMessageIndex('qty');
//** Call to new function **
$this->notifyOutOfStock($this->getProductId());
return $result;
}
.....
->setQuoteMessageIndex('qty');
//** Call to new function **
$this->notifyOutOfStock($this->getProductId());
return $result;
.....
What this does is add your product sku to an array in the checkout session.
This means you will have access to that info in the template file right after your page loads displaying the "Insufficient stock" notification.
So in one of your template files you can add some code to render the necessary JavaScript.
I've chosen header.phtml since it loads on every page. (Users can add quantities of items to the cart in the cart page as well as the product view page).
app/design/frontend/CUSTOMNAME/default/template/page/html/header.phtml
Somewhere down the bottom of the code add this:
<!-- GA tracking for out of stock items -->
<script>
try {
<?php
$session = Mage::getSingleton('checkout/session');
if ($session->getOutOfStock()){
$outOfStockItems = $session->getOutOfStock();
foreach($outOfStockItems as $sku=>$value) {
if($value==0){
//Render the GA tracking code
echo "_gaq.push(['_trackEvent', 'AddToCart', 'ProductQtyNotAvailable', '".$sku."']); \r\n";
//Set it to 1 so we know not to track it again this session
$outOfStockItems[$sku] = 1;
}
}
//Update the main session
Mage::getSingleton('checkout/session')->setOutOfStock($outOfStockItems);
}
?>
}
catch(err) {
//console.log(err.message);
}
</script>
Can confirm this works well and in my opinion is better than an email or RSS feed as you can analyse it along with the rest of your analytics.
I am trying to write a module that syncs my newsletter subscribers in Magento with a external database. I need to be able to update the subscription status in Magento programmatically but I am having diffuculty getting the "setStatus" method in Magento to work. It does not throw any errors but the code does not seem to have any effect. Below is the code where I call the method:
$collection = Mage::getResourceModel('newsletter/subscriber_collection')->showStoreInfo()->showCustomerInfo();
foreach ($collection as $cust) {
$cust->setStatus(1);
}
In theory, this should set the status of all of my subscribers to "subscribed". I could optionally change the argument sent to "setStatus" to any of the below ints for a different status.
1: Subscribed
2: Status Not Active
3: Unsubscribed
How to best change the subscriber status or get this code working?
Here an import script:
<?php
require_once("./app/Mage.php");
Mage::app();
$subscribers = array('email1#server1.com', 'email2#server2.com');
foreach ($subscribers as $email) {
# create new subscriber without send an confirmation email
Mage::getModel('newsletter/subscriber')->setImportMode(true)->subscribe($email);
# get just generated subscriber
$subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($email);
# change status to "subscribed" and save
$subscriber->setStatus(Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED);
$subscriber->save();
}
?>
It seems that newsletter subscribers are also stored elsewhere. What you are setting is just a check in the customer base for some other use.
You need to do the following for each customer as well.
Mage::getModel('newsletter/subscriber')->subscribe($email);
See this link for a complete reference.
Thanks to the link #Ozair shared I was able to figure out what I needed to do.
I was successfully setting the status of the subscriber in the Magento subscriber object but I was not saving the object. I needed to call Magento's save method so it would call the ORM and write it to the database. All I need to do was add
$cust->save();
in the for loop. Below is the whole code snippet.
$collection = Mage::getResourceModel('newsletter/subscriber_collection')->showStoreInfo()->showCustomerInfo();
foreach ($collection as $cust) {
$cust->setStatus(1);
$cust->save();
}
I Hope this helps someone in the future. I needed it for a Constant Contact - Magento Synchronization extension I was making: http://www.freelunchlabs.com/store/constant-contact-and-magento-sync.html