2

I am creating an order programmatically in WooCommerce and need to charge the default saved credit card. I am using the WooCommerce stripe plugin and have figured out how to set the correct payment method but can't figure out how to actually charge the card. Below is the code I have so far.

$order = wc_create_order();

$order->add_product( wc_get_product( 52 ), 1 );
$order->set_address( $shipping_address, 'shipping' );
$order->set_address($user_info, 'billing');

$payment_gateways = WC()->payment_gateways->payment_gateways();
$order->set_payment_method($payment_gateways['stripe']);

$order->calculate_totals(); 
$order->update_status("Completed", 'First Partner Order', TRUE);
$order->save();
Cheech
  • 355
  • 3
  • 16
  • First, `$order->save();` is unneeded as it's already included in update_status() methods. I don't think that **You can't charge a credit card using this** (even with a registered credit card) for security reasons… You should never keep credit card information, as e-commerce web sites are easily hackable and favorited for hackers. – LoicTheAztec May 23 '19 at 10:03
  • Thanks for the tip. I am using the stripe so the only data that is being stored is the token which is in line with being PCI compliant. The woocommerce stripe plugin is saving the token and data so they can reuse it later down the line. I just need to figure out how to charge the card using data that's already stored. – Cheech May 23 '19 at 11:46
  • I think that it is not possible… Only the customer can do that (for security reasons). Also the data is pre-stored on Stripe, if the customer approve it. – LoicTheAztec May 23 '19 at 11:49

1 Answers1

4

I was able to figure out a solution, although not very elegant, it seems to work. The basic premise is that we use the stripe api to create a charge and then add all the custom fields manually. This will result in a successful charge that is reflected in woocommerce and can be refunded via the admin later on. Below is the code with comments. I would love to know if anybody has found a better solution.

Note: You must use the sripe php api

$order = wc_create_order();

$order->add_product( wc_get_product( 52 ), 1 ); //Add product to order
$order->set_address( $shipping_address, 'shipping' ); //Add shipping address
$order->set_address($user_info, 'billing'); //Add billing address

//Set payment gateways
$payment_gateways = WC()->payment_gateways->payment_gateways();
$order->set_payment_method($payment_gateways['stripe']);

$order->calculate_totals(true); //setting true included tax 
//Try to charge stripe card
try {

  // Get stripe  test or secret key from woocommerce settings
  $options = get_option( 'woocommerce_stripe_settings' );
  $stripeKey = 'yes' === $options['testmode'] ? $options['test_secret_key'] : 
  $options['secret_key'] ;

  //Set the Stripe API Key
  \Stripe\Stripe::setApiKey($stripeKey);

  //Get Stripe customer token that was created when the card was saved in woo
  $tokenString = get_user_meta($user_id, '_stripe_customer_id', true);

  //Get total for the order as a number
  $total = intval($order->get_total());
  $totalNoDec = $total * 100;

  //Charge user via Stripe API
  $charge = \Stripe\Charge::create([
    'amount' => $totalNoDec,
    'currency' => 'usd',
    'customer' => $tokenString,
  ]);

  //Set all the meta data that will be needed
  $order->update_meta_data( '_transaction_id', $charge->id );
  $order->update_meta_data( '_stripe_source_id', $charge->payment_method );
  $order->update_meta_data( '_stripe_charge_captured', 'yes'  );
  $order->update_meta_data( '_stripe_currency', $charge->currancy);
  $order->update_meta_data( '_stripe_customer_id', $charge->customer);

} catch (\Stripe\Error\Base $e) {
  // Code to do something with the $e exception object when an error occurs
  echo($e->getMessage());
} catch (Exception $e) {
  echo($e->getMessage());
  // Catch any other non-Stripe exceptions
}

//Set order status to processing
$order->set_status("processing");
$order->save();
Cheech
  • 355
  • 3
  • 16