Stripe : New customer created even when customer_id is not empty? - php

I'm trying to retrieve my user's existing cards from Stripe with the below code. That said, when I use the below backend, even though I'm telling Stripe to ONLY create a new customer if $customer_id is NOT present, a new customer ID is created anyway even when customer_id is NOT null? I feel like I'm missing something obvious here...
.php
$email = $_POST['email'];
$customer_id = $_POST['customer_id']; //get this id from somewhere a database table, post parameter, etc.
$customer = \Stripe\Customer::create(array(
'email' => $email,
));
$customer_id = $_POST['customer_id']; //get this id from somewhere a database table, post parameter, etc.
// if the customer id doesn't exist create the customer
if ($customer_id !== null) {
$key = \Stripe\EphemeralKey::create(
["customer" => $customer->id],
["stripe_version" => $_POST['api_version']]
);
header('Content-Type: application/json');
exit(json_encode($key));
} else {
// \Stripe\Customer::retrieve($customer_id);
$cards = \Stripe\Customer::retrieve($customer_id)->sources->all();
// return the cards
header('Content-Type: application/json');
exit(json_encode($key));
}

Your IF condition should we switched around. Currently you create a customer if the customer_id is present. Based on the description you'd like to see the opposite, right?
In this case all you'd need to do is to switch around the if / else bodies:
if ($customer_id !== null) {
$cards = \Stripe\Customer::retrieve($customer_id)->sources->all();
// return the cards
header('Content-Type: application/json');
exit(json_encode($cards)); // you might want to return the cards here?
} else {
$key = \Stripe\EphemeralKey::create(
["customer" => $customer->id],
["stripe_version" => $_POST['api_version']]
);
header('Content-Type: application/json');
exit(json_encode($key));
}
AND remove the create block at the top. That will create a customer object as well, which you don't need.

Related

Laravel Twilio Store User Reply Input to Database in Response to Send SMS Order ID

I need help in Twilio getting reply responses and storing them in the database in response to sending SMS after user input in response to the message. I am sending an SMS to the user about his/her order schedule and asking him/her to confirm delivery by inputting Ok and when he/she confirm, I am getting his response successfully.
The question or the issue I am facing is that I want to know that when he/she confirm the delivery, I want to update the database record in response to the delivery SMS we sent to him/her earlier. My issue will be resolved if I am able to get order_id from the first message and send it in replytoSMS function.
My Code to send SMS and webhook (replytoSMS) are given below.
<?php
public function initiateSMS(Request $request) {
try {
foreach ( $request->get('items') as $item ) {
$order_id = $item['order_id'];
$phone = $item['phone_number'];
$order = Orders::where('id', $order_id)->first();
$phone_number = $this->client->lookups->v1->phoneNumbers($phone)->fetch();
if($phone_number) {
$template_value = $order->message;
$sms = $this->client->messages->create($phone, [
'from' => $this->from,
'body' => $template_value,
"method" => 'POST',
"statusCallbackMethod" => 'POST',
"statusCallback" => 'https://example.com/simply/public/api/notification/statusMessageBack?order_id='.$order_id.'',
]);
// print($sms->sid);
}
} // foreach loop end
if($sms){
return Response::json(['success' => 'sms initiated successfully!']);
}
} catch (Exception $e) {
return Response::json(['Error' => $e->getMessage()]);
} catch (RestException $rest) {
return Response::json(['Error' => $rest->getMessage()]);
}
}
function statusMessageBack(){
header('Content-type: text/xml');
header('Cache-Control: no-cache');
$response = new MessagingResponse();
$order_id = $_REQUEST['order_id'];
$user_phone = $_REQUEST['To'];
$MessageSid = (!empty($_REQUEST['MessageSid'])) ? $_REQUEST['MessageSid'] : '';
$MessageStatus = (!empty($_REQUEST['MessageStatus'])) ? $_REQUEST['MessageStatus'] : '';
if($MessageStatus && $MessageStatus == "delivered"){
$notification = Notification::create([
"response_code" => $MessageSid,
"type" => $category,
"table_ref" => "orders",
"table_ref_pk" => $order_id,
"response_status" => "",
"medium" => $user_phone,
"status" => $MessageStatus,
"sender_id" => $sender_id
]);
}
print $response; exit;
}
public function replyToSMS(){
header('Content-type: text/xml');
header('Cache-Control: no-cache');
$response = new MessagingResponse();
$MessageSid = (!empty($_REQUEST['MessageSid'])) ? $_REQUEST['MessageSid'] : '';
$MessageStatus = (!empty($_REQUEST['MessageStatus'])) ? $_REQUEST['MessageStatus'] : '';
$body = $_REQUEST['Body'];
$order_id = $_REQUEST['order_id'];
$from_phone = $_REQUEST['From'];
if (strtolower($body) == 'ok' || strtolower($body) == 'yes' || strtolower($body) == 'confirm') {
$response->message('Your delivery has been confirmed. Thank you', [
'callbackUrl' => "https://example.com/api/notification/reply_status?order_id='.$order_id.'",
'callbackMethod' => "POST"
]);
$notification = Notification::where('order_id', $order_id)->update(array("response_status" => "confirmed"));
} else {
$response->message('Sorry');
$notification = Notification::where('order_id', $order_id)->update(array("response_status" => "call store"));
}
print $response;
}
function reply_status(){
header('Content-type: text/xml');
header('Cache-Control: no-cache');
$response = new MessagingResponse();
echo $order_id = $_REQUEST['order_id'];
$user_phone = $_REQUEST['To'];
$MessageSid = (!empty($_REQUEST['MessageSid'])) ? $_REQUEST['MessageSid'] : '';
$MessageStatus = (!empty($_REQUEST['MessageStatus'])) ? $_REQUEST['MessageStatus'] : '';
if($MessageStatus && $MessageStatus == "delivered"){
}
print $response; exit;
}
The SMS protocol does not any concept of additional metadata with SMS messages, nor does it have the concept of replying to a specific message (you can test this by opening your phone's SMS application and trying to respond to any message from someone that wasn't the last one you received).
You can only really tell what someone may be responding to chronologically. That is, if you have sent them a message, then their response is related to that last message that you sent.
This is an issue if you intend to send more than one message asking for a response at the same time. In this situation, we recommend you use two different From numbers to send the message and store that From number against the order in your system. That way you can tell which message was being responded to by matching up the user's phone number and the phone number that you used to send the message.

Stripe - adding new customers to an existing plan?

I have a simple form that registers users. The form also uses Stripe to process payments. Stripe's API is super clean but for some reason I can't seem to figure this out. Please tell me if i'm doing something wrong here.
Right now I'm in a test account with Stripe, but every time I register a user in stripe it keeps creating a new plan. I know in my code below I have "Stripe\Plan::create" that's because I don't know how to add a new customer to an existing plan. Is this normal the way I'm doing this currently?
In the screenshot below you will see that it will create a new plan for that customer and assign them to it. Is it possible to just keep adding new customers to an existing plan?
// Include configuration file
require_once 'stripe/config.php';
// Include Stripe PHP library
require_once 'vendor/autoload.php';
$payment_id = $statusMsg = $api_error = '';
$ordStatus = 'error';
// Check whether stripe token is not empty
if(!empty($_POST['stripeToken'])){
// Retrieve stripe token, card and user info from the submitted form data
$token = $_POST['stripeToken'];
$users_email = $_POST['email'];
$first_name = $_POST['first_name'];
$last_name = $_POST['last_name'];
$full_name = $first_name.' '.$last_name;
// Set API key
\Stripe\Stripe::setApiKey(STRIPE_API_KEY);
// Add customer to stripe
$customer = \Stripe\Customer::create(array(
'email' => $users_email,
'name' => $full_name,
'source' => $token
));
// Create a plan
try {
$plan = \Stripe\Plan::create([
'amount' => 3000,
'currency' => 'usd',
'interval' => 'month',
// 'product' => ['name' => 'Standard Plan'],
'product' => 'prod_ktItFVvqgr4edf',
]);
}catch(Exception $e) {
$api_error = $e->getMessage();
}
if(empty($api_error) && $plan){
// Creates a new subscription
try {
$subscription = \Stripe\Subscription::create(array(
"customer" => $customer->id,
"items" => array(
array(
"plan" => $plan->id,
),
),
));
}catch(Exception $e) {
$api_error = $e->getMessage();
}
if(empty($api_error) && $subscription){
// Retrieve subscription data
$subsData = $subscription->jsonSerialize();
// Check whether the subscription activation is successful
if($subsData['status'] == 'active'){
// Subscription info
$subscrID = $subsData['id'];
$custID = $subsData['customer'];
$planID = $subsData['plan']['id'];
$created = date("Y-m-d H:i:s", $subsData['created']);
$status = $subsData['status'];
// Insert into database
// Insert into database
}else{
$statusMsg = "Subscription activation failed!";
}
}else{
$statusMsg = "Subscription creation failed! ".$api_error;
}
}else{
$statusMsg = "Plan creation failed! ".$api_error;
}
}else{
$statusMsg = "Error on form submission, please try again.";
}
To create a subscription with an existing plan, simply pass in that older plan's ID when creating the subscription instead of creating a new plan for each customer. In your // Create a plan block, either retrieve an existing plan and use that to create the subscription or create a new plan if needed. Or better yet, store the plan ID's in your own database for easier retrieval.

PHP: Stripe API does not display any error when entering a bad card number

It seems I am missing something when trying to handle some errors with Stripe in test mode with PHP.
Payment are successful when I enter a test card number like 4242424242424242 (for VISA) but I have no error and nothing is recorded when I enter a bad card number.
It is like if the button "Pay" was not working although it displays an error message if I use a real correct card number in test mode.
Does someone know what am I doing wrong here ? Thanks.
Here is the PHP code :
// Check whether stripe token is not empty
if(!empty($_POST['stripeToken'])){
// Retrieve stripe token, card and user info from the submitted form data
$token = $_POST['stripeToken'];
$name = $_POST['name'];
$email = $_POST['email'];
$card_number = $_POST['card_number'];
$card_exp_month = $_POST['card_exp_month'];
$card_exp_year = $_POST['card_exp_year'];
$card_cvc = $_POST['card_cvc'];
$itemPrice = $_POST['itemPrice'];
$itemNumber = $_POST['itemNumber'];
$Ticket_number = $_POST['Ticket_number'];
// Include Stripe PHP library
require_once 'stripe-php/init.php';
// Set API key
\Stripe\Stripe::setApiKey(STRIPE_API_KEY);
// Add customer to stripe
$customer = \Stripe\Customer::create(array(
'email' => $email,
'source' => $token
));
// Unique order ID
$orderID = strtoupper(str_replace('.','',uniqid('', true)));
// Convert price to cents
$itemPrice = ($itemPrice*100);
// Charge a credit or a debit card
$charge = \Stripe\Charge::create(array(
'customer' => $customer->id,
'amount' => $itemPrice,
'currency' => $currency,
'description' => $itemName,
'metadata' => array(
'order_id' => $orderID
)
));
// Retrieve charge details
$chargeJson = $charge->jsonSerialize();
// Check whether the charge is successful
if($chargeJson['amount_refunded'] == 0 && empty($chargeJson['failure_code']) && $chargeJson['paid'] == 1 && $chargeJson['captured'] == 1){
// Order details
$transactionID = $chargeJson['balance_transaction'];
$paidAmount = $chargeJson['amount'];
$paidCurrency = $chargeJson['currency'];
$payment_status = $chargeJson['status'];
// Include database connection file
include_once 'dbConnect.php';
$itemPrice = ($itemPrice/100);
$paidAmount = ($paidAmount/100);
// Insert tansaction data into the database
$sql = "INSERT INTO orders(name,email,card_number,card_exp_month,card_exp_year,item_name,item_number,item_price,item_price_currency,paid_amount,paid_amount_currency,txn_id,payment_status,created,modified) VALUES('".$name."','".$email."','".$card_number."','".$card_exp_month."','".$card_exp_year."','".$itemName."','".$itemNumber."','".$itemPrice."','".$currency."','".$paidAmount."','".$paidCurrency."','".$transactionID."','".$payment_status."',NOW(),NOW())";
$insert = $db->query($sql);
$payment_id = $db->insert_id;
// If the order is successful
if($payment_status == 'succeeded'){
$ordStatus = 'success';
$statusMsg = '';
}else{
$statusMsg = "Your Payment has Failed!";
}
}else{
print '<pre>';print_r($chargeJson);
$statusMsg = "Transaction has been failed!";
}
}else{
$statusMsg = "Error on form submission.";
}
?>
Thank you for your answers but in fact it was a dummy mistake : I did not declare an id to display my error. I had to add the following code in my form :
<p id="payment-status" role="alert"></p>

Stripe check for existing card

I'm looking to do the following sequence (using the Stripe API) when a customer submits a credit card:
Check if the user has a stripe customer id in their meta
If they don't, create a new customer, save the entered card to that user
If the user already has a customer id, check if the entered card is already one of their saved cards.
If it is, charge that card
If it's not, add the new card to the customer object, and then charge that card.
In my current code, Stripe is returning an invalid_request error upon trying to create the charge. Here's the section of code that relates:
//See if our user already has a customer ID, if not create one
$stripeCustID = get_user_meta($current_user->ID, 'stripeCustID', true);
if (!empty($stripeCustID)) {
$customer = \Stripe\Customer::retrieve($stripeCustID);
} else {
// Create a Customer:
$customer = \Stripe\Customer::create(array(
'email' => $current_user->user_email,
'source' => $token,
));
$stripeCustID = $customer->id;
//Add to user's meta
update_user_meta($current_user->ID, 'stripeCustID', $stripeCustID);
}
//Figure out if the user is using a stored card or a new card by comparing card fingerprints
$tokenData = \Stripe\Token::retrieve($token);
$thisCard = $tokenData['card'];
$custCards = $customer['sources']['data'];
foreach ($custCards as $card) {
if ($card['fingerprint'] == $thisCard['fingerprint']) {
$source = $thisCard['id'];
}
}
//If this card is not an existing one, we'll add it
if ($source == false) {
$newSource = $customer->sources->create(array('source' => $token));
$source=$newSource['id'];
}
// Try to authorize the card
$chargeArgs = array(
'amount' => $cartTotal,
'currency' => 'usd',
'description' => 'TPS Space Rental',
'customer' => $stripeCustID,
'source' => $source,
'capture' => false, //this pre-authorizes the card for 7 days instead of charging it immedietely
);
try {
$charge = \Stripe\Charge::create($chargeArgs);
Any help is appreciated.
The issue turned out to be this section:
if ($card['fingerprint'] == $thisCard['fingerprint']) {
$source = $thisCard['id'];
}
If a fingerprint match is successful, I need to grab the id of the card already in the users's meta, not the matching card that was inputted. So, this works:
if ($card['fingerprint'] == $thisCard['fingerprint']) {
$source = $card['id'];
}

Magento update order shipping address

At the end of the purchase, the user has the possibility to change your shipping address. Im trying to update this information, but it dosen't work. This is my code:
$customer = Mage::getModel('customer/session')->getCustomer();
$order = Mage::getSingleton('checkout/session')->getLastOrder();
$postData = Mage::app()->getRequest()->getPost();
$_new_address = array (
'firstname' => $postData['nombre'],
'lastname' => $postData['apellidos'],
'street' => array ('0' => $postData['direccion']),
'city' => $postData['localidad'],
'region_id' => $postData['provincia_id'],
'region' => '',
'postcode' => $postData['codigo_postal'],
'country_id'=> 'ES',
'telephone' => $postData['telefono']
);
$customAddress = Mage::getModel('customer/address');
$customAddress->setData($_new_address)
->setCustomerId($customer->getId())
->setIsDefaultBilling('1')
->setIsDefaultShipping('1')
->setSaveInAddressBook('1');
// Save address
try {
$customAddress->save();
} catch (Exception $e) {
Mage::getSingleton('core/session')->addError($e->getMessage());
header('Location: /');
exit;
}
// Update the order
try {
$order->setShippingAddress($customAddress)->save();
} catch (Exception $e) {
Mage::getSingleton('core/session')->addError($e->getMessage());
header('Location: /');
exit;
}
Can I update an order or is not allowed? Can anyone give me a tip?
My problem was that the Billing address and shipping address in the order, are different than having the user has as default addresses.
At the end the code looks like this:
$order = Mage::getSingleton('checkout/session')->getLastOrder();
$postData = Mage::app()->getRequest()->getPost();
// Try to get shipping and billing address data.
$orderShippingAddress = $order->getShippingAddress()->getId();
$orderShipping = Mage::getModel('sales/order_address')->load($orderShippingAddress);
$orderBillingAddress = $order->getBillingAddress()->getId();
$orderBilling = Mage::getModel('sales/order_address')->load($orderBillingAddress);
// Updating data.
$orderShipping->addData($postData);
$orderBilling->addData($postData);
try {
$orderShipping->implodeStreetAddress()->save();
$orderBilling->implodeStreetAddress()->save();
} catch (Exception $e) {
Mage::logException($e);
Mage::getSingleton('core/session')->addError($e->getMessage());
header('Location: /after/success/envio');
exit;
}
Now, it works. Thanks for your help #R.S
Assuming that you want to update the shipping address for an order, take a look # addressSaveAction() in /app/code/core/Mage/Adminhtml/controllers/Sales/OrderController.php
$order = Mage::getSingleton('checkout/session')->getLastOrder();
//Get shipping address Id
$addressId = $order->getShippingAddress()->getId();
$address = Mage::getModel('sales/order_address')->load($addressId);
$data = $this->getRequest()->getPost();
$address->addData($data);
$address->implodeStreetAddress()->save();
Also i'm not sure if Mage::getSingleton('checkout/session')->getLastOrder() will still contain a valid order id after you submit your form since you will be loading a new page
While functioning correctly both other answers have an excessive address loading. The getShippingAddress already returns instance of sales/order_address. So the procedure can be simplified to following:
$order = Mage::getSingleton('checkout/session')->getLastOrder();
$data = $this->getRequest()->getPost();
$order->getShippingAddress()->addData($data)
->save();
Also implodeStreetAddress method call only required if you use multiline street address.

Categories