Changeset 6834 for sites/trunk/wordcamp.org/public_html/wp-content/plugins
- Timestamp:
- 03/07/2018 01:45:42 AM (7 years ago)
- Location:
- sites/trunk/wordcamp.org/public_html/wp-content/plugins
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-qbo-client/wordcamp-qbo-client.php
r6833 r6834 16 16 17 17 public static function load_options() { 18 if ( isset( self::$options ) ) 18 if ( isset( self::$options ) ) { 19 19 return self::$options; 20 } 20 21 21 22 self::$options = wp_parse_args( get_option( 'wordcamp-qbo-client', array() ), array( … … 34 35 ) ); 35 36 36 foreach ( $init_options as $key => $value ) 37 foreach ( $init_options as $key => $value ) { 37 38 self::$$key = $value; 38 39 if ( empty( self::$hmac_key ) ) 40 return; 39 } 40 41 if ( empty( self::$hmac_key ) ) { 42 return; 43 } 41 44 42 45 add_action( 'admin_init', array( __CLASS__, 'admin_init' ), 20 ); … … 46 49 $cap = is_multisite() ? 'manage_network' : 'manage_options'; 47 50 48 if ( ! current_user_can( $cap ) ) 49 return; 50 51 if ( ! class_exists( 'WCP_Payment_Request' ) ) 52 return; 51 if ( ! current_user_can( $cap ) ) { 52 return; 53 } 54 55 if ( ! class_exists( 'WCP_Payment_Request' ) ) { 56 return; 57 } 53 58 54 59 add_action( 'add_meta_boxes', array( __CLASS__, 'add_meta_boxes' ) ); … … 59 64 public static function admin_notices() { 60 65 $screen = get_current_screen(); 61 if ( $screen->id != 'wcp_payment_request' ) 62 return; 66 if ( $screen->id != 'wcp_payment_request' ) { 67 return; 68 } 63 69 64 70 $post = get_post(); 65 if ( $post->post_status == 'auto-draft' ) 66 return; 71 if ( $post->post_status == 'auto-draft' ) { 72 return; 73 } 67 74 68 75 $data = get_post_meta( $post->ID, '_wordcamp-qbo-client-data', true ); 69 if ( empty( $data['last_error'] ) ) 70 return; 76 if ( empty( $data['last_error'] ) ) { 77 return; 78 } 71 79 72 80 printf( '<div class="notice error is-dismissible"><p>QBO Sync Error: %s</p></div>', esc_html( $data['last_error'] ) ); … … 97 105 self::load_options(); 98 106 99 $post = get_post();107 $post = get_post(); 100 108 $classes = self::get_classes(); 101 $data = get_post_meta( $post->ID, '_wordcamp-qbo-client-data', true );109 $data = get_post_meta( $post->ID, '_wordcamp-qbo-client-data', true ); 102 110 103 111 $selected_class = self::$options['default-class']; 104 if ( ! empty( $data['class'] ) && array_key_exists( $data['class'], $classes ) ) 112 if ( ! empty( $data['class'] ) && array_key_exists( $data['class'], $classes ) ) { 105 113 $selected_class = $data['class']; 114 } 106 115 107 116 ?> … … 113 122 <?php if ( empty( $data['transaction_id'] ) ) : ?> 114 123 <p>This request has not been synced with QuickBooks yet.</p> 115 <?php else : ?>124 <?php else : ?> 116 125 <pre><?php echo esc_html( print_r( $data, true ) ); ?></pre> 117 126 <?php endif; ?> … … 152 161 153 162 public static function save_post( $post_id, $post ) { 154 if ( $post->post_type !== WCP_Payment_Request::POST_TYPE ) 155 return; 156 157 if ( empty( $_POST['wordcamp-qbo-client-nonce'] ) || empty( $_POST['wordcamp-qbo-client-post'] ) ) 158 return; 159 160 if ( intval( $_POST['wordcamp-qbo-client-post'] ) !== $post->ID ) 161 return; 162 163 if ( ! wp_verify_nonce( $_POST['wordcamp-qbo-client-nonce'], 'wordcamp-qbo-client-push-' . $post->ID ) ) 163 if ( $post->post_type !== WCP_Payment_Request::POST_TYPE ) { 164 return; 165 } 166 167 if ( empty( $_POST['wordcamp-qbo-client-nonce'] ) || empty( $_POST['wordcamp-qbo-client-post'] ) ) { 168 return; 169 } 170 171 if ( intval( $_POST['wordcamp-qbo-client-post'] ) !== $post->ID ) { 172 return; 173 } 174 175 if ( ! wp_verify_nonce( $_POST['wordcamp-qbo-client-nonce'], 'wordcamp-qbo-client-push-' . $post->ID ) ) { 164 176 wp_die( 'Could not verify QBO nonce. Please go back, refresh the page and try again.' ); 177 } 165 178 166 179 // No need to push. 167 if ( empty( $_POST['wordcamp-qbo-client-push'] ) ) 168 return; 169 170 if ( $post->post_status != 'paid' ) 180 if ( empty( $_POST['wordcamp-qbo-client-push'] ) ) { 181 return; 182 } 183 184 if ( $post->post_status != 'paid' ) { 171 185 wp_die( 'A request has to be marked as paid before it could be synced to QuickBooks.' ); 172 173 if ( empty( $_POST['wordcamp-qbo-client-class'] ) ) 186 } 187 188 if ( empty( $_POST['wordcamp-qbo-client-class'] ) ) { 174 189 wp_die( 'You need to set a QuickBooks class before you can sync this payment request.' ); 190 } 175 191 176 192 $class = $_POST['wordcamp-qbo-client-class']; 177 if ( ! array_key_exists( $class, self::get_classes() ) ) 193 if ( ! array_key_exists( $class, self::get_classes() ) ) { 178 194 wp_die( 'The class you have picked does not exist.' ); 179 180 $data = get_post_meta( $post->ID, '_wordcamp-qbo-client-data', true ); 195 } 196 197 $data = get_post_meta( $post->ID, '_wordcamp-qbo-client-data', true ); 181 198 $txn_id = false; 182 199 183 if ( ! is_array( $data ) ) 200 if ( ! is_array( $data ) ) { 184 201 $data = array(); 202 } 185 203 186 204 // This request has not been synced before. 187 if ( ! empty( $data['transaction_id'] ) ) 205 if ( ! empty( $data['transaction_id'] ) ) { 188 206 $txn_id = $data['transaction_id']; 207 } 189 208 190 209 $amount = get_post_meta( $post->ID, '_camppayments_payment_amount', true ); … … 193 212 194 213 $currency = get_post_meta( $post->ID, '_camppayments_currency', true ); 195 if ( strtoupper( $currency ) != 'USD' ) 214 215 if ( strtoupper( $currency ) != 'USD' ) { 196 216 wp_die( 'Non-USD payments sync to QuickBooks is not available yet.' ); 217 } 197 218 198 219 $description_chunks = array( $post->post_title ); 199 $description = get_post_meta( $post->ID, '_camppayments_description', true ); 200 if ( ! empty( $description ) ) 220 $description = get_post_meta( $post->ID, '_camppayments_description', true ); 221 222 if ( ! empty( $description ) ) { 201 223 $description_chunks[] = $description; 224 } 202 225 203 226 $description_chunks[] = esc_url_raw( get_edit_post_link( $post->ID, 'raw' ) ); 204 $description = implode( "\n", $description_chunks ); 227 $description = implode( "\n", $description_chunks ); 228 205 229 unset( $description_chunks ); 206 230 207 231 $category = get_post_meta( $post->ID, '_camppayments_payment_category', true ); 208 $date = absint( get_post_meta( $post->ID, '_camppayments_date_vendor_paid', true ) );232 $date = absint( get_post_meta( $post->ID, '_camppayments_date_vendor_paid', true ) ); 209 233 210 234 $body = array( 211 'id' => $txn_id,212 'date' => $date,213 'amount' => $amount,214 'category' => $category,235 'id' => $txn_id, 236 'date' => $date, 237 'amount' => $amount, 238 'category' => $category, 215 239 'description' => $description, 216 'class' => $class,217 ); 218 219 $body = json_encode( $body );220 $request_url = esc_url_raw( self::$api_base . '/expense/' );240 'class' => $class, 241 ); 242 243 $body = json_encode( $body ); 244 $request_url = esc_url_raw( self::$api_base . '/expense/' ); 221 245 $request_args = array( 222 246 'timeout' => self::REMOTE_REQUEST_TIMEOUT, 223 'body' => $body,247 'body' => $body, 224 248 'headers' => array( 225 'Content-Type' => 'application/json',249 'Content-Type' => 'application/json', 226 250 'Authorization' => self::_get_auth_header( 'post', $request_url, $body ), 227 251 ), 228 252 ); 229 $response = wp_remote_post( $request_url, $request_args );253 $response = wp_remote_post( $request_url, $request_args ); 230 254 231 255 Logger\log( 'remote_request', compact( 'request_url', 'request_args', 'response' ) ); … … 242 266 unset( $data['last_error'] ); 243 267 $data['transaction_id'] = $body['transaction_id']; 244 $data['timestamp'] = time();245 $data['class'] = $class;268 $data['timestamp'] = time(); 269 $data['class'] = $class; 246 270 247 271 // Remember this class for future reference. … … 307 331 'description' => sanitize_text_field( $invoice_meta['_wcbsi_description' ][0] ), 308 332 309 'statement_memo' => sprintf(333 'statement_memo' => sprintf( 310 334 'WordCamp.org Invoice: %s', 311 335 esc_url_raw( admin_url( sprintf( 'post.php?post=%s&action=edit', $invoice_id ) ) ) … … 340 364 341 365 $args = array( 366 'body' => $body, 342 367 'timeout' => self::REMOTE_REQUEST_TIMEOUT, 343 368 'headers' => array( … … 345 370 'Content-Type' => 'application/json', 346 371 ), 347 'body' => $body,348 372 ); 349 373 … … 498 522 * @param string $request_url The clean request URI, without any query arguments. 499 523 * @param string $body The payload body. 500 * @param array $args The query arguments.524 * @param array $args The query arguments. 501 525 * 502 526 * @return string A sha256 HMAC signature. 503 527 */ 504 528 private static function _get_auth_header( $method, $request_url, $body = '', $args = array() ) { 505 $signature = hash_hmac( 'sha256', json_encode( array( strtolower( $method ), 506 strtolower( $request_url ), $body, $args ) ), self::$hmac_key ); 529 $signature = hash_hmac( 'sha256', json_encode( array( 530 strtolower( $method ), 531 strtolower( $request_url ), 532 $body, 533 $args, 534 ) ), self::$hmac_key ); 507 535 508 536 return 'wordcamp-qbo-hmac ' . $signature; -
sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-qbo/class-wordcamp-qbo-oauth-client.php
r2325 r6834 3 3 * WordCamp QBO Oauth Client 4 4 * 5 * Note: This is NOT a general-purpose OAuth client, it is only suitable5 * SECURITY WARNING: This is NOT a general-purpose OAuth client, it is only suitable 6 6 * for the WordCamp QBO plugin. 7 7 */ 8 8 class WordCamp_QBO_OAuth_Client { 9 10 11 12 9 private $consumer_key; 10 private $consumer_secret; 11 private $oauth_token; 12 private $oauth_token_secret; 13 13 14 15 * @param string $consumer_keyThe OAuth consumer key16 17 18 19 $this->consumer_key= $consumer_key;20 21 14 /** 15 * @param string $consumer_key The OAuth consumer key 16 * @param string $consumer_secret The secret 17 */ 18 public function __construct( $consumer_key, $consumer_secret ) { 19 $this->consumer_key = $consumer_key; 20 $this->consumer_secret = $consumer_secret; 21 } 22 22 23 24 25 26 * @param string $oauth_tokenAn OAuth token.27 28 29 30 $this->oauth_token= $oauth_token;31 32 23 /** 24 * Set current OAuth token 25 * 26 * @param string $oauth_token An OAuth token. 27 * @param string $oauth_token_secret The OAuth token secret. 28 */ 29 public function set_token( $oauth_token, $oauth_token_secret ) { 30 $this->oauth_token = $oauth_token; 31 $this->oauth_token_secret = $oauth_token_secret; 32 } 33 33 34 35 36 37 38 39 * @return arrayAn array with the tokens.40 41 42 43 44 34 /** 35 * Get a request token. 36 * 37 * @param string $callback_url The URL to which a successful authentication will return. 38 * 39 * @return array|WP_Error An array with the tokens. 40 */ 41 public function get_request_token( $request_url, $callback_url ) { 42 $args = array_merge( $this->_get_default_args(), array( 43 'oauth_callback' => $callback_url, 44 ) ); 45 45 46 47 $args= array_map( 'rawurlencode', $args );46 $args['oauth_signature'] = $this->_get_signature( 'POST', $request_url, $args ); 47 $args = array_map( 'rawurlencode', $args ); 48 48 49 $response = wp_remote_post( add_query_arg( $args, $request_url ) ); 50 if ( is_wp_error( $response ) ) 51 return $response; 49 $response = wp_remote_post( add_query_arg( $args, $request_url ) ); 52 50 53 if ( wp_remote_retrieve_response_code( $response ) != 200 ) 54 return new WP_Error( 'error', 'Could not get OAuth request token.' ); 51 if ( is_wp_error( $response ) ) { 52 return $response; 53 } 55 54 56 $result = wp_parse_args( wp_remote_retrieve_body( $response ), array( 57 'oauth_token' => '', 58 'oauth_token_secret' => '', 59 'oauth_callback_confirmed' => '', 60 ) ); 55 if ( wp_remote_retrieve_response_code( $response ) != 200 ) { 56 return new WP_Error( 'error', 'Could not get OAuth request token.' ); 57 } 61 58 62 return $result; 63 } 59 $result = wp_parse_args( wp_remote_retrieve_body( $response ), array( 60 'oauth_token' => '', 61 'oauth_token_secret' => '', 62 'oauth_callback_confirmed' => '', 63 ) ); 64 64 65 /** 66 * Get an OAuth access token. 67 * 68 * @param string $verifier A verifier token from the authentication flow. 69 * 70 * @return array The access token. 71 */ 72 public function get_access_token( $request_url, $verifier ) { 73 $args = array_merge( $this->_get_default_args(), array( 74 'oauth_verifier' => $verifier, 75 'oauth_token' => $this->oauth_token, 76 ) ); 65 return $result; 66 } 77 67 78 $args['oauth_signature'] = $this->_get_signature( 'POST', $request_url, $args ); 79 $args = array_map( 'rawurlencode', $args ); 68 /** 69 * Get an OAuth access token. 70 * 71 * @param string $verifier A verifier token from the authentication flow. 72 * 73 * @return array|WP_Error The access token. 74 */ 75 public function get_access_token( $request_url, $verifier ) { 76 $args = array_merge( $this->_get_default_args(), array( 77 'oauth_verifier' => $verifier, 78 'oauth_token' => $this->oauth_token, 79 ) ); 80 80 81 $response = wp_remote_post( add_query_arg( $args, $request_url ) ); 81 $args['oauth_signature'] = $this->_get_signature( 'POST', $request_url, $args ); 82 $args = array_map( 'rawurlencode', $args ); 82 83 83 if ( is_wp_error( $response ) ) 84 return $response; 84 $response = wp_remote_post( add_query_arg( $args, $request_url ) ); 85 85 86 if ( wp_remote_retrieve_response_code( $response ) != 200 ) 87 return new WP_Error( 'error', 'Could not get OAuth access token.' ); 86 if ( is_wp_error( $response ) ) { 87 return $response; 88 } 88 89 89 $result = wp_parse_args( wp_remote_retrieve_body( $response ), array( 90 'oauth_token' => '', 91 'oauth_token_secret' => '', 92 ) ); 90 if ( wp_remote_retrieve_response_code( $response ) != 200 ) { 91 return new WP_Error( 'error', 'Could not get OAuth access token.' ); 92 } 93 93 94 return $result; 95 } 94 $result = wp_parse_args( wp_remote_retrieve_body( $response ), array( 95 'oauth_token' => '', 96 'oauth_token_secret' => '', 97 ) ); 96 98 97 /** 98 * Get a string suitable for the Authorization header. 99 * 100 * @see http://oauth.net/core/1.0a/#auth_header 101 * 102 * @param string $method The request method. 103 * @param string $request_url The request URL (without query) 104 * @param array|string $request_args Any additional query/body args. 105 * 106 * @return string An OAuth string ready for the Authorization header. 107 */ 108 public function get_oauth_header( $method, $request_url, $request_args = array() ) { 109 $oauth_args = array_merge( $this->_get_default_args(), array( 110 'oauth_token' => $this->oauth_token, 111 ) ); 99 return $result; 100 } 112 101 113 $all_args = $oauth_args; 114 if ( is_array( $request_args ) && ! empty( $request_args ) ) 115 $all_args = array_merge( $oauth_args, $request_args ); 102 /** 103 * Get a string suitable for the Authorization header. 104 * 105 * @see http://oauth.net/core/1.0a/#auth_header 106 * 107 * @param string $method The request method. 108 * @param string $request_url The request URL (without query) 109 * @param array|string $request_args Any additional query/body args. 110 * 111 * @return string An OAuth string ready for the Authorization header. 112 */ 113 public function get_oauth_header( $method, $request_url, $request_args = array() ) { 114 $oauth_args = array_merge( $this->_get_default_args(), array( 115 'oauth_token' => $this->oauth_token, 116 ) ); 116 117 117 $oauth_args['oauth_signature'] = $this->_get_signature( $method, $request_url, $all_args );118 $all_args = $oauth_args; 118 119 119 $header_parts = array(); 120 foreach ( $oauth_args as $key => $value ) 121 $header_parts[] = sprintf( '%s="%s"', rawurlencode( $key ), rawurlencode( $value ) ); 120 if ( is_array( $request_args ) && ! empty( $request_args ) ) { 121 $all_args = array_merge( $oauth_args, $request_args ); 122 } 122 123 123 $header = 'OAuth ' . implode( ',', $header_parts ); 124 return $header; 125 } 124 $oauth_args['oauth_signature'] = $this->_get_signature( $method, $request_url, $all_args ); 126 125 127 /** 128 * Get a default set of OAuth arguments. 129 * 130 * @return array Default OAuth arguments. 131 */ 132 private function _get_default_args() { 133 return array( 134 'oauth_nonce' => md5( wp_generate_password( 12 ) ), 135 'oauth_consumer_key' => $this->consumer_key, 136 'oauth_signature_method' => 'HMAC-SHA1', 137 'oauth_timestamp' => time(), 138 'oauth_version' => '1.0', 139 ); 140 } 126 $header_parts = array(); 141 127 142 /** 143 * Get an OAuth signature. 144 * 145 * @see http://oauth.net/core/1.0a/#signing_process 146 * 147 * @param string $method The request method, GET, POST, etc. 148 * @param string $url The request URL (without any query) 149 * @param array $args An optional array of query or body args. 150 * 151 * @return string A base64-encoded hmac-sha1 signature. 152 */ 153 private function _get_signature( $method, $url, $args ) { 154 ksort( $args ); 128 foreach ( $oauth_args as $key => $value ) { 129 $header_parts[] = sprintf( '%s="%s"', rawurlencode( $key ), rawurlencode( $value ) ); 130 } 155 131 156 // Don't sign a signature. 157 unset( $args['oauth_signature'] ); 132 $header = 'OAuth ' . implode( ',', $header_parts ); 133 return $header; 134 } 158 135 159 $parameter_string = ''; 160 foreach ( $args as $key => $value ) 161 $parameter_string .= sprintf( '&%s=%s', rawurlencode( $key ), rawurlencode( $value ) ); 136 /** 137 * Get a default set of OAuth arguments. 138 * 139 * @return array Default OAuth arguments. 140 */ 141 private function _get_default_args() { 142 return array( 143 'oauth_nonce' => md5( wp_generate_password( 12 ) ), 144 'oauth_consumer_key' => $this->consumer_key, 145 'oauth_signature_method' => 'HMAC-SHA1', 146 'oauth_timestamp' => time(), 147 'oauth_version' => '1.0', 148 ); 149 } 162 150 163 $parameter_string = trim( $parameter_string, '&' ); 164 $signature_base = strtoupper( $method ) . '&' . rawurlencode( $url ) . '&' . rawurlencode( $parameter_string ); 165 $signing_key = rawurlencode( $this->consumer_secret ) . '&' . rawurlencode( $this->oauth_token_secret ); 151 /** 152 * Get an OAuth signature. 153 * 154 * @see http://oauth.net/core/1.0a/#signing_process 155 * 156 * @param string $method The request method, GET, POST, etc. 157 * @param string $url The request URL (without any query) 158 * @param array $args An optional array of query or body args. 159 * 160 * @return string A base64-encoded hmac-sha1 signature. 161 */ 162 private function _get_signature( $method, $url, $args ) { 163 ksort( $args ); 166 164 167 return base64_encode( hash_hmac( 'sha1', $signature_base, $signing_key, true ) ); 168 } 165 // Don't sign a signature. 166 unset( $args['oauth_signature'] ); 167 168 $parameter_string = ''; 169 170 foreach ( $args as $key => $value ) { 171 $parameter_string .= sprintf( '&%s=%s', rawurlencode( $key ), rawurlencode( $value ) ); 172 } 173 174 $parameter_string = trim( $parameter_string, '&' ); 175 $signature_base = strtoupper( $method ) . '&' . rawurlencode( $url ) . '&' . rawurlencode( $parameter_string ); 176 $signing_key = rawurlencode( $this->consumer_secret ) . '&' . rawurlencode( $this->oauth_token_secret ); 177 178 return base64_encode( hash_hmac( 'sha1', $signature_base, $signing_key, true ) ); 179 } 169 180 } -
sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-qbo/wordcamp-qbo.php
r6833 r6834 23 23 24 24 public static function load_options() { 25 if ( isset( self::$options ) ) 25 if ( isset( self::$options ) ) { 26 26 return self::$options; 27 } 27 28 28 29 self::$options = wp_parse_args( get_option( 'wordcamp-qbo', array() ), array( … … 50 51 51 52 $init_options = wp_parse_args( apply_filters( 'wordcamp_qbo_options', array() ), array( 52 'app_token' => '',53 'consumer_key' => '',53 'app_token' => '', 54 'consumer_key' => '', 54 55 'consumer_secret' => '', 55 'hmac_key' => '',56 57 'categories_map' => array(),56 'hmac_key' => '', 57 58 'categories_map' => array(), 58 59 ) ); 59 60 60 foreach ( $init_options as $key => $value ) 61 foreach ( $init_options as $key => $value ) { 61 62 self::$$key = $value; 63 } 62 64 63 65 // There's no point in doing anything if we don't have the secrets. 64 if ( empty( self::$consumer_key ) ) 66 if ( empty( self::$consumer_key ) ) { 65 67 return; 68 } 66 69 67 70 self::$api_base_url = sprintf( … … 87 90 public static function rest_api_init() { 88 91 register_rest_route( 'wordcamp-qbo/v1', '/expense', array( 89 'methods' => 'GET, POST',92 'methods' => 'GET, POST', 90 93 'callback' => array( __CLASS__, 'rest_callback_expense' ), 91 94 ) ); 92 95 93 96 register_rest_route( 'wordcamp-qbo/v1', '/invoice', array( 94 'methods' => 'GET, POST',97 'methods' => 'GET, POST', 95 98 'callback' => array( __CLASS__, 'rest_callback_invoice' ), 96 99 ) ); 97 100 98 101 register_rest_route( 'wordcamp-qbo/v1', '/invoice_pdf', array( 99 'methods' => 'GET',102 'methods' => 'GET', 100 103 'callback' => array( __CLASS__, 'rest_callback_invoice_pdf' ), 101 104 ) ); 102 105 103 106 register_rest_route( 'wordcamp-qbo/v1', '/paid_invoices', array( 104 'methods' => 'GET',107 'methods' => 'GET', 105 108 'callback' => array( __CLASS__, 'rest_callback_paid_invoices' ), 106 109 ) ); … … 113 116 */ 114 117 public static function rest_callback_expense( $request ) { 115 if ( ! self::_is_valid_request( $request ) ) 118 if ( ! self::_is_valid_request( $request ) ) { 116 119 return new WP_Error( 'unauthorized', 'Unauthorized', array( 'status' => 401 ) ); 120 } 117 121 118 122 self::load_options(); … … 121 125 122 126 $amount = floatval( $request->get_param( 'amount' ) ); 123 if ( ! $amount ) 127 if ( ! $amount ) { 124 128 return new WP_Error( 'error', 'An amount was not given.' ); 129 } 125 130 126 131 $description = $request->get_param( 'description' ); 127 if ( empty( $description ) ) 132 if ( empty( $description ) ) { 128 133 return new WP_Error( 'error', 'The expense description can not be empty.' ); 134 } 129 135 130 136 $category = $request->get_param( 'category' ); 131 if ( empty( $category ) || ! array_key_exists( $category, self::$categories_map ) ) 137 if ( empty( $category ) || ! array_key_exists( $category, self::$categories_map ) ) { 132 138 return new WP_Error( 'error', 'The category you have picked is invalid.' ); 139 } 133 140 134 141 $date = $request->get_param( 'date' ); 135 if ( empty( $date ) ) 142 if ( empty( $date ) ) { 136 143 return new WP_Error( 'error', 'The expense date can not be empty.' ); 144 } 137 145 138 146 $date = absint( $date ); 139 147 140 148 $class = $request->get_param( 'class' ); 141 if ( empty( $class ) ) 149 if ( empty( $class ) ) { 142 150 return new WP_Error( 'error', 'You need to set a class.' ); 151 } 143 152 144 153 $classes = self::_get_classes(); 145 if ( ! array_key_exists( $class, $classes ) ) 154 if ( ! array_key_exists( $class, $classes ) ) { 146 155 return new WP_Error( 'error', 'Unknown class.' ); 156 } 147 157 148 158 $class = array( 149 159 'value' => $class, 150 'name' => $classes[ $class ],160 'name' => $classes[ $class ], 151 161 ); 152 162 153 163 $payload = array( 154 'AccountRef' => self::$account,155 'TxnDate' => gmdate( 'Y-m-d', $date ),164 'AccountRef' => self::$account, 165 'TxnDate' => gmdate( 'Y-m-d', $date ), 156 166 'PaymentType' => 'Cash', 157 'Line' => array(167 'Line' => array( 158 168 array( 159 'Id' => 1,160 'Description' => $description,161 'Amount' => $amount,162 'DetailType' => 'AccountBasedExpenseLineDetail',169 'Id' => 1, 170 'Description' => $description, 171 'Amount' => $amount, 172 'DetailType' => 'AccountBasedExpenseLineDetail', 163 173 'AccountBasedExpenseLineDetail' => array( 164 'ClassRef' => $class,174 'ClassRef' => $class, 165 175 'AccountRef' => self::$categories_map[ $category ], 166 176 ), … … 176 186 177 187 $oauth_header = $oauth->get_oauth_header( 'GET', $request_url ); 178 $response = wp_remote_get( $request_url, array(188 $response = wp_remote_get( $request_url, array( 179 189 'timeout' => self::REMOTE_REQUEST_TIMEOUT, 180 190 'headers' => array( 181 191 'Authorization' => $oauth_header, 182 'Accept' => 'application/json',192 'Accept' => 'application/json', 183 193 ), 184 194 ) ); 185 195 Logger\log( 'remote_request_sync_token', compact( 'response' ) ); 186 196 187 if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) != 200 ) 197 if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) != 200 ) { 188 198 return new WP_Error( 'error', 'Could not find purchase to update.' ); 199 } 189 200 190 201 $body = json_decode( wp_remote_retrieve_body( $response ), true ); 191 if ( ! isset( $body['Purchase']['SyncToken'] ) ) 202 if ( ! isset( $body['Purchase']['SyncToken'] ) ) { 192 203 return new WP_Error( 'error', 'Could not decode purchase for update.' ); 204 } 193 205 194 206 $payload['SyncToken'] = $body['Purchase']['SyncToken']; … … 196 208 } 197 209 198 $payload = json_encode( $payload );210 $payload = json_encode( $payload ); 199 211 $request_url = esc_url_raw( sprintf( '%s/v3/company/%d/purchase', 200 212 self::$api_base_url, self::$options['auth']['realmId'] ) ); 201 213 202 214 $oauth_header = $oauth->get_oauth_header( 'POST', $request_url, $payload ); 203 $response = wp_remote_post( $request_url, array(215 $response = wp_remote_post( $request_url, array( 204 216 'timeout' => self::REMOTE_REQUEST_TIMEOUT, 205 217 'headers' => array( 206 218 'Authorization' => $oauth_header, 207 'Accept' => 'application/json',208 'Content-Type' => 'application/json',209 ), 210 'body' => $payload,219 'Accept' => 'application/json', 220 'Content-Type' => 'application/json', 221 ), 222 'body' => $payload, 211 223 ) ); 212 224 Logger\log( 'remote_request_create_expense', compact( 'payload', 'response' ) ); 213 225 214 if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) != 200 ) 226 if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) != 200 ) { 215 227 return new WP_Error( 'error', 'Could not create purchase.' ); 228 } 216 229 217 230 $body = json_decode( wp_remote_retrieve_body( $response ), true ); 218 if ( empty( $body ) ) 231 if ( empty( $body ) ) { 219 232 return new WP_Error( 'error', 'Could not decode create purchase result.' ); 233 } 220 234 221 235 return array( … … 248 262 249 263 $args = array( 250 'query' => 'SELECT * FROM Class MAXRESULTS 1000',264 'query' => 'SELECT * FROM Class MAXRESULTS 1000', 251 265 'minorversion' => 4, 252 266 ); … … 256 270 257 271 $oauth_header = $oauth->get_oauth_header( 'GET', $request_url, $args ); 258 $response = wp_remote_get(272 $response = wp_remote_get( 259 273 esc_url_raw( add_query_arg( $args, $request_url ) ), 260 274 array( … … 262 276 'headers' => array( 263 277 'Authorization' => $oauth_header, 264 'Accept' => 'application/json',265 ) 278 'Accept' => 'application/json', 279 ), 266 280 ) 267 281 ); … … 475 489 */ 476 490 $description_limit = abs( 995 - strlen( $payment_instructions ) ); 477 $customer_memo = sprintf(491 $customer_memo = sprintf( 478 492 "%s\n\n%s", 479 493 substr( $description, 0, $description_limit ), … … 502 516 'Line' => array( 503 517 array( 504 'Amount' => $amount,505 'Description' => $line_description,506 'DetailType' => 'SalesItemLineDetail',518 'Amount' => $amount, 519 'Description' => $line_description, 520 'DetailType' => 'SalesItemLineDetail', 507 521 508 522 'SalesItemLineDetail' => array( 509 'ItemRef' => array(523 'ItemRef' => array( 510 524 'value' => '20', // Sponsorship 511 525 ), 512 526 513 'ClassRef' => array(527 'ClassRef' => array( 514 528 'value' => $class_id, 515 529 ), … … 517 531 'UnitPrice' => $amount, 518 532 'Qty' => 1, 519 ) 520 ) 521 ), 522 523 'CustomerRef' => array(533 ), 534 ), 535 ), 536 537 'CustomerRef' => array( 524 538 'value' => $customer_id, 525 539 ), … … 533 547 ), 534 548 535 'BillEmail' => array(549 'BillEmail' => array( 536 550 'Address' => $customer_email, 537 551 ), … … 566 580 'Content-Type' => 'application/json', 567 581 ), 568 'body' => $payload,582 'body' => $payload, 569 583 ); 570 584 571 585 return array( 572 586 'url' => $request_url, 573 'args' => $args 587 'args' => $args, 574 588 ); 575 589 } … … 630 644 'Content-Type' => 'application/octet-stream', 631 645 ), 632 'body' => '',646 'body' => '', 633 647 ); 634 648 … … 717 731 'Content-Type' => 'application/pdf', 718 732 ), 719 'body' => '',733 'body' => '', 720 734 ); 721 735 … … 946 960 947 961 'CurrencyRef' => array( 948 'value' => $currency_code 949 ), 950 951 'PreferredDeliveryMethod' => 'Email',952 953 'GivenName' => $sponsor['first-name'],954 'FamilyName' => $sponsor['last-name'],955 'CompanyName' => $sponsor['company-name'],956 'DisplayName' => sprintf( '%s - %s', $sponsor['company-name'], $currency_code ),957 'PrintOnCheckName' => $sponsor['company-name'],958 959 'PrimaryPhone' => array(962 'value' => $currency_code, 963 ), 964 965 'PreferredDeliveryMethod' => 'Email', 966 967 'GivenName' => $sponsor['first-name'], 968 'FamilyName' => $sponsor['last-name'], 969 'CompanyName' => $sponsor['company-name'], 970 'DisplayName' => sprintf( '%s - %s', $sponsor['company-name'], $currency_code ), 971 'PrintOnCheckName' => $sponsor['company-name'], 972 973 'PrimaryPhone' => array( 960 974 'FreeFormNumber' => $sponsor['phone-number'], 961 975 ), 962 976 963 'PrimaryEmailAddr' => array(977 'PrimaryEmailAddr' => array( 964 978 'Address' => $sponsor['email-address'], 965 979 ), … … 985 999 'Content-Type' => 'application/json', 986 1000 ), 987 'body' => $payload,1001 'body' => $payload, 988 1002 ); 989 1003 … … 1102 1116 */ 1103 1117 private static function _is_valid_request( $request ) { 1104 if ( ! $request->get_header( 'authorization' ) ) 1118 if ( ! $request->get_header( 'authorization' ) ) { 1105 1119 return false; 1106 1107 if ( ! preg_match( '#^wordcamp-qbo-hmac (.+)$#', $request->get_header( 'authorization' ), $matches ) ) 1120 } 1121 1122 if ( ! preg_match( '#^wordcamp-qbo-hmac (.+)$#', $request->get_header( 'authorization' ), $matches ) ) { 1108 1123 return false; 1109 1110 $given_hmac = $matches[1]; 1124 } 1125 1126 $given_hmac = $matches[1]; 1111 1127 $request_url = esc_url_raw( home_url( parse_url( home_url( $_SERVER['REQUEST_URI'] ), PHP_URL_PATH ) ) ); 1112 $payload = json_encode( array( strtolower( $request->get_method() ), strtolower( $request_url ), 1113 $request->get_body(), $request->get_query_params() ) ); 1128 $payload = json_encode( array( 1129 strtolower( $request->get_method() ), 1130 strtolower( $request_url ), 1131 $request->get_body(), 1132 $request->get_query_params(), 1133 ) ); 1114 1134 1115 1135 return hash_equals( hash_hmac( 'sha256', $payload, self::$hmac_key ), $given_hmac ); … … 1128 1148 */ 1129 1149 public static function maybe_oauth_request() { 1130 if ( empty( $_GET['wordcamp-qbo-oauth-request'] ) ) 1150 if ( empty( $_GET['wordcamp-qbo-oauth-request'] ) ) { 1131 1151 return; 1132 1133 if ( empty( $_GET['wordcamp-qbo-oauth-nonce'] ) || ! wp_verify_nonce( $_GET['wordcamp-qbo-oauth-nonce'], 'oauth-request' ) ) 1152 } 1153 1154 if ( empty( $_GET['wordcamp-qbo-oauth-nonce'] ) || ! wp_verify_nonce( $_GET['wordcamp-qbo-oauth-nonce'], 'oauth-request' ) ) { 1134 1155 wp_die( 'Could not verify nonce.' ); 1156 } 1135 1157 1136 1158 self::load_options(); … … 1140 1162 1141 1163 // We don't have an access token yet. 1142 $request_url = 'https://oauth.intuit.com/oauth/v1/get_request_token';1164 $request_url = 'https://oauth.intuit.com/oauth/v1/get_request_token'; 1143 1165 $callback_url = esc_url_raw( add_query_arg( array( 1144 1166 'wordcamp-qbo-oauth-request' => 1, 1145 'wordcamp-qbo-oauth-nonce' => wp_create_nonce( 'oauth-request' ),1167 'wordcamp-qbo-oauth-nonce' => wp_create_nonce( 'oauth-request' ), 1146 1168 ), admin_url() ) ); 1147 1169 1148 1170 $request_token = $oauth->get_request_token( $request_url, $callback_url ); 1149 if ( is_wp_error( $request_token ) ) 1171 if ( is_wp_error( $request_token ) ) { 1150 1172 wp_die( $request_token->get_error_message() ); 1173 } 1151 1174 1152 1175 update_user_meta( get_current_user_id(), 'wordcamp-qbo-oauth', $request_token ); … … 1161 1184 $request_token = get_user_meta( get_current_user_id(), 'wordcamp-qbo-oauth', true ); 1162 1185 1163 if ( $request_token['oauth_token'] != $_GET['oauth_token'] ) 1186 if ( $request_token['oauth_token'] != $_GET['oauth_token'] ) { 1164 1187 wp_die( 'Could not verify OAuth token.' ); 1165 1166 if ( empty( $_GET['oauth_verifier'] ) ) 1188 } 1189 1190 if ( empty( $_GET['oauth_verifier'] ) ) { 1167 1191 wp_die( 'Could not obtain OAuth verifier.' ); 1192 } 1168 1193 1169 1194 $oauth->set_token( $request_token['oauth_token'], $request_token['oauth_token_secret'] ); … … 1172 1197 $access_token = $oauth->get_access_token( $request_url, $_GET['oauth_verifier'] ); 1173 1198 1174 if ( is_wp_error( $access_token ) ) 1199 if ( is_wp_error( $access_token ) ) { 1175 1200 wp_die( 'Could not obtain an access token.' ); 1201 } 1176 1202 1177 1203 // We have an access token. 1178 1204 $data = array( 1179 'oauth_token' => $access_token['oauth_token'],1205 'oauth_token' => $access_token['oauth_token'], 1180 1206 'oauth_token_secret' => $access_token['oauth_token_secret'], 1181 'realmId' => $_GET['realmId'],1207 'realmId' => $_GET['realmId'], 1182 1208 ); 1183 1209 … … 1185 1211 1186 1212 $oauth->set_token( self::$options['auth']['oauth_token'], self::$options['auth']['oauth_token_secret'] ); 1187 $request_url = sprintf( '%s/v3/company/%d/companyinfo/%d', 1188 self::$api_base_url, self::$options['auth']['realmId'], self::$options['auth']['realmId'] ); 1213 1214 $request_url = sprintf( 1215 '%s/v3/company/%d/companyinfo/%d', 1216 self::$api_base_url, 1217 self::$options['auth']['realmId'], 1218 self::$options['auth']['realmId'] 1219 ); 1189 1220 1190 1221 $oauth_header = $oauth->get_oauth_header( 'GET', $request_url ); 1191 $response = wp_remote_get( $request_url, array(1222 $response = wp_remote_get( $request_url, array( 1192 1223 'timeout' => self::REMOTE_REQUEST_TIMEOUT, 1193 1224 'headers' => array( 1194 1225 'Authorization' => $oauth_header, 1195 'Accept' => 'application/json',1196 ) 1226 'Accept' => 'application/json', 1227 ), 1197 1228 ) ); 1198 1229 Logger\log( 'remote_request', compact( 'response' ) ); … … 1208 1239 $company_name = $body['CompanyInfo']['CompanyName']; 1209 1240 1210 self::$options['auth']['name'] = $company_name;1241 self::$options['auth']['name'] = $company_name; 1211 1242 self::$options['auth']['timestamp'] = time(); 1212 1243 self::update_options();
Note: See TracChangeset
for help on using the changeset viewer.