cum să utilizezi wc_create_order cu produse de tip abonament
Vreau să creez o nouă comandă programatic.
Acest cod funcționează bine cu produse simple,
$product = get_product($product_id);
$order = wc_create_order();
$order->add_product( $product , 1 );
$order->calculate_totals();
// atribuie comanda utilizatorului curent
update_post_meta($order->id, '_customer_user', get_current_user_id() );
// finalizare plată
$order->payment_complete();
dar când îl folosesc pentru un produs de tip abonament, nu adaugă abonamentul, ci doar comanda.

Iată codul meu pentru crearea unei abonări -- a fost nevoie de multă încercare și eroare pentru a descoperi totul. Mult succes!
function create_test_sub() {
$email = 'test@test.com';
$start_date = '2015-01-01 00:00:00';
$address = array(
'first_name' => 'Jeremy',
'last_name' => 'Test',
'company' => '',
'email' => $email,
'phone' => '777-777-777-777',
'address_1' => '31 Main Street',
'address_2' => '',
'city' => 'Auckland',
'state' => 'AKL',
'postcode' => '12345',
'country' => 'AU'
);
$default_password = wp_generate_password();
if (!$user = get_user_by('login', $email)) $user = wp_create_user( $email, $default_password, $email );
// Am folosit un singur produs cu multiple variații
$parent_product = wc_get_product(22998);
$args = array(
'attribute_billing-period' => 'Yearly',
'attribute_subscription-type' => 'Both'
);
$product_variation = $parent_product->get_matching_variation($args);
$product = wc_get_product($product_variation);
// Fiecare variație are și propria clasă de livrare
$shipping_class = get_term_by('slug', $product->get_shipping_class(), 'product_shipping_class');
WC()->shipping->load_shipping_methods();
$shipping_methods = WC()->shipping->get_shipping_methods();
// Am o logică pentru selectarea metodei de livrare; cazul tău va fi probabil diferit, așa că identifică metoda de care ai nevoie și stocheaz-o în $selected_shipping_method
$selected_shipping_method = $shipping_methods['free_shipping'];
$class_cost = $selected_shipping_method->get_option('class_cost_' . $shipping_class->term_id);
$quantity = 1;
// După câte văd, trebuie să creezi mai întâi comanda, apoi abonamentul
$order = wc_create_order(array('customer_id' => $user->id));
$order->add_product( $product, $quantity, $args);
$order->set_address( $address, 'billing' );
$order->set_address( $address, 'shipping' );
$order->add_shipping((object)array (
'id' => $selected_shipping_method->id,
'label' => $selected_shipping_method->title,
'cost' => (float)$class_cost,
'taxes' => array(),
'calc_tax' => 'per_order'
));
$order->calculate_totals();
$order->update_status("completed", 'Comandă importată', TRUE);
// Comanda creată, acum creează abonamentul atașat -- opțional dacă nu creezi un abonament
// Fiecare variație are o perioadă diferită de abonament
$period = WC_Subscriptions_Product::get_period( $product );
$interval = WC_Subscriptions_Product::get_interval( $product );
$sub = wcs_create_subscription(array('order_id' => $order->id, 'billing_period' => $period, 'billing_interval' => $interval, 'start_date' => $start_date));
$sub->add_product( $product, $quantity, $args);
$sub->set_address( $address, 'billing' );
$sub->set_address( $address, 'shipping' );
$sub->add_shipping((object)array (
'id' => $selected_shipping_method->id,
'label' => $selected_shipping_method->title,
'cost' => (float)$class_cost,
'taxes' => array(),
'calc_tax' => 'per_order'
));
$sub->calculate_totals();
WC_Subscriptions_Manager::activate_subscriptions_for_order($order);
print "<a href='/wp-admin/post.php?post=" . $sub->id . "&action=edit'>Abonament creat! Click aici pentru editare</a>";
}

Mulțumesc pentru asta, dar nu reușesc să o fac să funcționeze. Ce funcție este wcs_create_subscription()
? Nu este definită, nici wc_create_subscription()
dacă e o greșeală de scriere.

Pentru această parte ai nevoie de extensia Subscriptions! (Nu uita că poți căuta numele de funcții pe Google, de obicei sunt foarte ușor de găsit pentru că sunt foarte specifice.)

Da, aveam pluginul Subscriptions, dar se pare că aveam o versiune mai veche (1.5.). Am actualizat la 2.0. acum și codul pare să funcționeze. Mulțumesc mult!

Utilizare interesantă și exemplu bun pentru wc_create_order + wcs_create_subscription!

Continuă să mi se afișeze eroarea Call to undefined method WP_Error::add_product()
, aveți vreo idee de ce?

Din păcate, trebuie să gestionați manual crearea abonamentului prin cod, deoarece simpla adăugare a unei comenzi nu se ocupă automat de acest lucru.
Iată funcția mea personalizată pe care am construit-o pe baza tuturor răspunsurilor găsite pe SO și a analizării codului sursă al abonamentelor.
Testat cu
- WordPress 5.2.5
- WooCommerce 3.8.0
- WooCommerce Subscriptions 2.6.1
https://gist.github.com/tripflex/a3123052f36daf18f7cb05391d752223
function give_user_subscription( $product, $user_id, $note = '' ){
// Mai întâi verificăm dacă toate funcțiile și clasele necesare există
if( ! function_exists( 'wc_create_order' ) || ! function_exists( 'wcs_create_subscription' ) || ! class_exists( 'WC_Subscriptions_Product' ) ){
return false;
}
$order = wc_create_order( array( 'customer_id' => $user_id ) );
if( is_wp_error( $order ) ){
return false;
}
$user = get_user_by( 'ID', $user_id );
$fname = $user->first_name;
$lname = $user->last_name;
$email = $user->user_email;
$address_1 = get_user_meta( $user_id, 'billing_address_1', true );
$address_2 = get_user_meta( $user_id, 'billing_address_2', true );
$city = get_user_meta( $user_id, 'billing_city', true );
$postcode = get_user_meta( $user_id, 'billing_postcode', true );
$country = get_user_meta( $user_id, 'billing_country', true );
$state = get_user_meta( $user_id, 'billing_state', true );
$address = array(
'first_name' => $fname,
'last_name' => $lname,
'email' => $email,
'address_1' => $address_1,
'address_2' => $address_2,
'city' => $city,
'state' => $state,
'postcode' => $postcode,
'country' => $country,
);
$order->set_address( $address, 'billing' );
$order->set_address( $address, 'shipping' );
$order->add_product( $product, 1 );
$sub = wcs_create_subscription(array(
'order_id' => $order->get_id(),
'status' => 'pending', // Starea trebuie setată inițial la "pending" pentru a corespunde procesului normal de checkout
'billing_period' => WC_Subscriptions_Product::get_period( $product ),
'billing_interval' => WC_Subscriptions_Product::get_interval( $product )
));
if( is_wp_error( $sub ) ){
return false;
}
// Modelat după WC_Subscriptions_Cart::calculate_subscription_totals()
$start_date = gmdate( 'Y-m-d H:i:s' );
// Adăugăm produsul la abonament
$sub->add_product( $product, 1 );
$dates = array(
'trial_end' => WC_Subscriptions_Product::get_trial_expiration_date( $product, $start_date ),
'next_payment' => WC_Subscriptions_Product::get_first_renewal_payment_date( $product, $start_date ),
'end' => WC_Subscriptions_Product::get_expiration_date( $product, $start_date ),
);
$sub->update_dates( $dates );
$sub->calculate_totals();
// Actualizăm starea comenzii cu o notă personalizată
$note = ! empty( $note ) ? $note : __( 'Comandă și abonament adăugate programatic.' );
$order->update_status( 'completed', $note, true );
// De asemenea, actualizăm starea abonamentului la "active" din "pending" (și adăugăm nota)
$sub->update_status( 'active', $note, true );
return $sub;
}
