1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
<?php
include(SIMPLE_WP_MEMBERSHIP_PATH . 'ipn/swpm_handle_subsc_ipn.php');
class SwpmStripeSubscriptionIpnHandler {
public function __construct() {
$this->handle_stripe_ipn(); }
public function handle_stripe_ipn() { if (isset($_GET['hook'])) { //this is Webhook notify from Stripe //TODO: add Webhook Signing Secret verification //To do this, we need to get customer ID, retreive its details from Stripe, get button_id from metadata //and see if the button has Signing Secret option set. If it is - we need to check signatures //More details here: https://stripe.com/docs/webhooks#signatures
$input = @file_get_contents("php://input"); if (empty($input)) { SwpmLog::log_simple_debug("Stripe Subscription Webhook sent empty data or page was accessed directly. Aborting.", false); echo 'Empty Webhook data received.'; die; } //SwpmLog::log_simple_debug($input, true); $event_json = json_decode($input);
$type = $event_json->type;
if ($type == 'customer.subscription.deleted' || $type == "charge.refunded") { //Subscription expired or refunded event SwpmLog::log_simple_debug("Stripe Subscription Webhook received. Processing request...", true); //Let's form minimal ipn_data array for swpm_handle_subsc_cancel_stand_alone $customer = $event_json->data->object->customer; $subscr_id = $event_json->data->object->id; $ipn_data = array(); $ipn_data['subscr_id'] = $subscr_id; $ipn_data['parent_txn_id'] = $customer;
swpm_handle_subsc_cancel_stand_alone($ipn_data); } http_response_code(200); //tells Stripe we received this notify return; }
SwpmLog::log_simple_debug("Stripe Subscription IPN received. Processing request...", true); //SwpmLog::log_simple_debug(print_r($_REQUEST, true), true);//Useful for debugging purpose //Include the Stripe library. include(SIMPLE_WP_MEMBERSHIP_PATH . 'lib/stripe-gateway/init.php');
//Read and sanitize the request parameters. $button_id = sanitize_text_field($_REQUEST['item_number']); $button_id = absint($button_id); $button_title = sanitize_text_field($_REQUEST['item_name']);
$stripe_token = sanitize_text_field($_POST['stripeToken']); $stripe_token_type = sanitize_text_field($_POST['stripeTokenType']); $stripe_email = sanitize_email($_POST['stripeEmail']);
//Retrieve the CPT for this button $button_cpt = get_post($button_id); if (!$button_cpt) { //Fatal error. Could not find this payment button post object. SwpmLog::log_simple_debug("Fatal Error! Failed to retrieve the payment button post object for the given button ID: " . $button_id, false); wp_die("Fatal Error! Payment button (ID: " . $button_id . ") does not exist. This request will fail."); }
$plan_id = get_post_meta($button_id, 'stripe_plan_id', true); $descr = 'Subscription to "' . $plan_id . '" plan';
$membership_level_id = get_post_meta($button_id, 'membership_level_id', true);
//Validate and verify some of the main values. //Validation passed. Go ahead with the charge. //Sandbox and other settings $settings = SwpmSettings::get_instance(); $sandbox_enabled = $settings->get_value('enable-sandbox-testing'); if ($sandbox_enabled) { SwpmLog::log_simple_debug("Sandbox payment mode is enabled. Using test API key details.", true); $secret_key = get_post_meta($button_id, 'stripe_test_secret_key', true); ; //Use sandbox API key } else { $secret_key = get_post_meta($button_id, 'stripe_live_secret_key', true); ; //Use live API key }
//Set secret API key in the Stripe library \Stripe\Stripe::setApiKey($secret_key);
// Get the credit card details submitted by the form $token = $stripe_token;
// Create the charge on Stripe's servers - this will charge the user's card try { $customer = \Stripe\Customer::create(array( 'description' => $descr, 'email' => $stripe_email, 'source' => $token, 'plan' => $plan_id, 'trial_from_plan' => 'true', )); } catch (Exception $e) { SwpmLog::log_simple_debug("Error occurred during Stripe Subscribe. " . $e->getMessage(), false); $body = $e->getJsonBody(); $error = $body['error']; $error_string = print_r($error, true); SwpmLog::log_simple_debug("Error details: " . $error_string, false); wp_die("Stripe Subscription Error! " . $e->getMessage() . $error_string); }
//Everything went ahead smoothly with the charge. SwpmLog::log_simple_debug("Stripe Subscription successful.", true);
//let's add button_id to metadata $customer->metadata = array('button_id' => $button_id); try { $customer->save(); } catch (Exception $e) { SwpmLog::log_simple_debug("Error occurred during Stripe customer metadata update. " . $e->getMessage(), false); $body = $e->getJsonBody(); SwpmLog::log_simple_debug("Error details: " . $error_string, false); }
//Grab customer ID and set it as the transaction ID. $txn_id = $customer->id; //$charge->balance_transaction; //Grab subscription ID $subscr_id = $customer->subscriptions->data[0]->id; $custom = sanitize_text_field($_REQUEST['custom']); $custom_var = SwpmTransactions::parse_custom_var($custom); $swpm_id = isset($custom_var['swpm_id']) ? $custom_var['swpm_id'] : '';
$payment_amount = $customer->subscriptions->data[0]->plan->amount / 100;
//Create the $ipn_data array. $ipn_data = array(); $ipn_data['mc_gross'] = $payment_amount; $ipn_data['first_name'] = ''; $ipn_data['last_name'] = ''; $ipn_data['payer_email'] = $stripe_email; $ipn_data['membership_level'] = $membership_level_id; $ipn_data['txn_id'] = $txn_id; $ipn_data['subscr_id'] = $subscr_id . '|' . $button_id; $ipn_data['swpm_id'] = $swpm_id; $ipn_data['ip'] = $custom_var['user_ip']; $ipn_data['custom'] = $custom; $ipn_data['gateway'] = 'stripe'; $ipn_data['status'] = 'completed';
$ipn_data['address_street'] = ''; $ipn_data['address_city'] = ''; $ipn_data['address_state'] = ''; $ipn_data['address_zipcode'] = ''; $ipn_data['country'] = '';
//Handle the membership signup related tasks. swpm_handle_subsc_signup_stand_alone($ipn_data, $membership_level_id, $txn_id, $swpm_id);
//Save the transaction record SwpmTransactions::save_txn_record($ipn_data); SwpmLog::log_simple_debug('Transaction data saved.', true);
//Trigger the stripe IPN processed action hook (so other plugins can can listen for this event). do_action('swpm_stripe_ipn_processed', $ipn_data);
do_action('swpm_payment_ipn_processed', $ipn_data);
//Redirect the user to the return URL (or to the homepage if a return URL is not specified for this payment button). $return_url = get_post_meta($button_id, 'return_url', true); if (empty($return_url)) { $return_url = SIMPLE_WP_MEMBERSHIP_SITE_HOME_URL; } SwpmLog::log_simple_debug("Redirecting customer to: " . $return_url, true); SwpmLog::log_simple_debug("End of Stripe Subscription IPN processing.", true, true); SwpmMiscUtils::redirect_to_url($return_url); }
}
$swpm_stripe_subscription_ipn = new SwpmStripeSubscriptionIpnHandler();
|