4
votes

I have a site that is using Stripe to process a subscription payments. There is only one type of subscription. I followed this tutorial on NetTuts to do the initial setup. Had a form working fine processing subscriptions and everything worked. Client requested a coupon code. Stripe supports this so I set out trying to add a coupon code to the existing form.

I set up coupon codes in Stripe, set my testing keys and switched to test mode in stripe. I'm performing a couple of checks in my code:

  1. Check to see whether a coupon was entered, if not create a new customer object without a coupon option
  2. Check to see whether the Coupon is valid, if not return an error

If there has been a coupon entered and it is valid, then pass the matching Stripe coupon object as an option when creating a new customer.

 if(isset($couponCode) && strlen($couponCode) > 0) {
  $using_discount = true;
  try {
        $coupon = Stripe_Coupon::retrieve($couponCode);
        if($coupon !== NULL) {
           $cCode = $coupon;
        }
        // if we got here, the coupon is valid

     } catch (Exception $e) {

        // an exception was caught, so the code is invalid
        $message = $e->getMessage();
        returnErrorWithMessage($message);

     }


}

try
{ 
  if($using_discount == true) {
    $customer = Stripe_Customer::create(array(
          "card" => $token,
          "plan" => "basic_plan",
          "email" => $email,
          "coupon" => $cCode
       ));
  }
  else {
        $customer = Stripe_Customer::create(array(
          "card" => $token,
          "plan" => "basic_plan",
          "email" => $email
       ));
  }

$couponCode is populated with the form field correctly the same way all other fields are populated, I've triple checked that it is being pulled correctly.

When I try to submit the form without a coupon code, it charges the full amount and passes through Stripe correctly.

However if I enter either a valid OR invalid coupon code, it does not pass a coupon object with the customer object when creating a new customer object and charges the full amount when passing through Stripe.

I've looked at the code for hours and can't seem to figure out why it is always failing to recognize the discount code and pass the matching coupon object to Stripe.

2

2 Answers

4
votes

This is probably a little out dated and you found a solution for your code. But it would seem all you need to do is pass through your original $couponCode as the array value for Coupon. As stated by codasaurus you are just getting an array back from stripe of the coupon, which you don't need unless you did $cCode->id and pass the ID back to your array to create a customer.

I changed when you set the $using_discount to true, as this would trigger to send a coupon code if the coupon was valid or not.

Once the coupon is actually valid we then send the coupon. You only need the value of your submitted state so $coupon is the reference to the discount in there system. Or you could use the $coupon->id if you wanted to create it that way.

Here is my take on a solution based on your code, it could be better, but I hope it helps others looking for a solution like me.

if($coupon!='' && strlen($coupon) > 0) {
          try {
                $coupon = Stripe_Coupon::retrieve($coupon); //check coupon exists
                if($coupon !== NULL) {
                 $using_discount = true; //set to true our coupon exists or take the coupon id if you wanted to.
                }
                // if we got here, the coupon is valid

             } catch (Exception $e) {
                // an exception was caught, so the code is invalid
                $message = $e->getMessage();
                returnErrorWithMessage($message);
             }

        }
        if($using_discount==true)
        {
            $customer = Stripe_Customer::create(array(
                  "card" => $token,
                  "plan" => $plan,
                  "email" => $id,
                  "coupon"=>$coupon) //original value input example: "75OFFMEMBER" stripe should be doing the rest.
                );
        }
        else
        {
            $customer = Stripe_Customer::create(array(
                  "card" => $token,
                  "plan" => $plan,
                  "email" => $id)
                );
        }
2
votes

Looking at the documentation https://stripe.com/docs/api#create_customer, the Stripe_Customer::create() call is looking for just the coupon code. It looks like you're passing in the entire coupon object.

Unless your first try catch fails, $couponCode already has your coupon code. Also, there are several other checks you need to perform to determine if the coupon is valid. For example, if the coupon->times_redeemed < coupon->max_redemptions, or if the coupon->redeem_by has passed, etc. You might also want to check if the customer is already using the coupon by checking the customer discount object.

If any of these checks fail, just set your $using_discount = false;