暫無描述

API.php 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <?php
  2. namespace MailPoet\Services\Bridge;
  3. if (!defined('ABSPATH')) exit;
  4. use MailPoet\Logging\LoggerFactory;
  5. use MailPoet\WP\Functions as WPFunctions;
  6. use WP_Error;
  7. class API {
  8. const SENDING_STATUS_OK = 'ok';
  9. const SENDING_STATUS_CONNECTION_ERROR = 'connection_error';
  10. const SENDING_STATUS_SEND_ERROR = 'send_error';
  11. const REQUEST_TIMEOUT = 10; // seconds
  12. const RESPONSE_CODE_KEY_INVALID = 401;
  13. const RESPONSE_CODE_STATS_SAVED = 204;
  14. const RESPONSE_CODE_TEMPORARY_UNAVAILABLE = 503;
  15. const RESPONSE_CODE_NOT_ARRAY = 422;
  16. const RESPONSE_CODE_PAYLOAD_TOO_BIG = 413;
  17. const RESPONSE_CODE_PAYLOAD_ERROR = 400;
  18. const RESPONSE_CODE_CAN_NOT_SEND = 403;
  19. private $apiKey;
  20. private $wp;
  21. /** @var LoggerFactory */
  22. private $loggerFactory;
  23. /** @var mixed|null It is an instance of \CurlHandle in PHP8 and aboove but a resource in PHP7 */
  24. private $curlHandle = null;
  25. public $urlMe = 'https://bridge.mailpoet.com/api/v0/me';
  26. public $urlPremium = 'https://bridge.mailpoet.com/api/v0/premium';
  27. public $urlMessages = 'https://bridge.mailpoet.com/api/v0/messages';
  28. public $urlBounces = 'https://bridge.mailpoet.com/api/v0/bounces/search';
  29. public $urlStats = 'https://bridge.mailpoet.com/api/v0/stats';
  30. public $urlAuthorizedEmailAddresses = 'https://bridge.mailpoet.com/api/v0/authorized_email_addresses';
  31. public function __construct(
  32. $apiKey,
  33. $wp = null
  34. ) {
  35. $this->setKey($apiKey);
  36. if (is_null($wp)) {
  37. $this->wp = new WPFunctions();
  38. } else {
  39. $this->wp = $wp;
  40. }
  41. $this->loggerFactory = LoggerFactory::getInstance();
  42. }
  43. public function checkMSSKey() {
  44. $result = $this->request(
  45. $this->urlMe,
  46. ['site' => WPFunctions::get()->homeUrl()]
  47. );
  48. $code = $this->wp->wpRemoteRetrieveResponseCode($result);
  49. switch ($code) {
  50. case 200:
  51. $body = json_decode($this->wp->wpRemoteRetrieveBody($result), true);
  52. break;
  53. default:
  54. $body = null;
  55. break;
  56. }
  57. return ['code' => $code, 'data' => $body];
  58. }
  59. public function checkPremiumKey() {
  60. $result = $this->request(
  61. $this->urlPremium,
  62. ['site' => WPFunctions::get()->homeUrl()]
  63. );
  64. $code = $this->wp->wpRemoteRetrieveResponseCode($result);
  65. switch ($code) {
  66. case 200:
  67. $body = $this->wp->wpRemoteRetrieveBody($result);
  68. if ($body) {
  69. $body = json_decode($body, true);
  70. }
  71. break;
  72. default:
  73. $body = null;
  74. break;
  75. }
  76. return ['code' => $code, 'data' => $body];
  77. }
  78. public function logCurlInformation($headers, $info) {
  79. $this->loggerFactory->getLogger(LoggerFactory::TOPIC_MSS)->addInfo(
  80. 'requests-curl.after_request',
  81. ['headers' => $headers, 'curl_info' => $info]
  82. );
  83. }
  84. public function setCurlHandle($handle) {
  85. $this->curlHandle = $handle;
  86. }
  87. public function sendMessages($messageBody) {
  88. $this->curlHandle = null;
  89. add_action('requests-curl.before_request', [$this, 'setCurlHandle'], 10, 2);
  90. add_action('requests-curl.after_request', [$this, 'logCurlInformation'], 10, 2);
  91. $result = $this->request(
  92. $this->urlMessages,
  93. $messageBody
  94. );
  95. remove_action('requests-curl.after_request', [$this, 'logCurlInformation']);
  96. remove_action('requests-curl.before_request', [$this, 'setCurlHandle']);
  97. if (is_wp_error($result)) {
  98. $this->logCurlError($result);
  99. return [
  100. 'status' => self::SENDING_STATUS_CONNECTION_ERROR,
  101. 'message' => $result->get_error_message(),
  102. ];
  103. }
  104. $responseCode = $this->wp->wpRemoteRetrieveResponseCode($result);
  105. if ($responseCode !== 201) {
  106. $response = ($this->wp->wpRemoteRetrieveBody($result)) ?
  107. $this->wp->wpRemoteRetrieveBody($result) :
  108. $this->wp->wpRemoteRetrieveResponseMessage($result);
  109. return [
  110. 'status' => self::SENDING_STATUS_SEND_ERROR,
  111. 'message' => $response,
  112. 'code' => $responseCode,
  113. ];
  114. }
  115. return ['status' => self::SENDING_STATUS_OK];
  116. }
  117. public function checkBounces(array $emails) {
  118. $result = $this->request(
  119. $this->urlBounces,
  120. $emails
  121. );
  122. if ($this->wp->wpRemoteRetrieveResponseCode($result) === 200) {
  123. return json_decode($this->wp->wpRemoteRetrieveBody($result), true);
  124. }
  125. return false;
  126. }
  127. public function updateSubscriberCount($count) {
  128. $result = $this->request(
  129. $this->urlStats,
  130. ['subscriber_count' => (int)$count],
  131. 'PUT'
  132. );
  133. return $this->wp->wpRemoteRetrieveResponseCode($result) === self::RESPONSE_CODE_STATS_SAVED;
  134. }
  135. public function getAuthorizedEmailAddresses() {
  136. $result = $this->request(
  137. $this->urlAuthorizedEmailAddresses,
  138. null,
  139. 'GET'
  140. );
  141. if ($this->wp->wpRemoteRetrieveResponseCode($result) === 200) {
  142. return json_decode($this->wp->wpRemoteRetrieveBody($result), true);
  143. }
  144. return false;
  145. }
  146. public function setKey($apiKey) {
  147. $this->apiKey = $apiKey;
  148. }
  149. public function getKey() {
  150. return $this->apiKey;
  151. }
  152. private function auth() {
  153. return 'Basic ' . base64_encode('api:' . $this->apiKey);
  154. }
  155. private function request($url, $body, $method = 'POST') {
  156. $params = [
  157. 'timeout' => $this->wp->applyFilters('mailpoet_bridge_api_request_timeout', self::REQUEST_TIMEOUT),
  158. 'httpversion' => '1.0',
  159. 'method' => $method,
  160. 'headers' => [
  161. 'Content-Type' => 'application/json',
  162. 'Authorization' => $this->auth(),
  163. ],
  164. 'body' => $body !== null ? json_encode($body) : null,
  165. ];
  166. return $this->wp->wpRemotePost($url, $params);
  167. }
  168. private function logCurlError(WP_Error $error) {
  169. $logData = [
  170. 'curl_errno' => $this->curlHandle ? curl_errno($this->curlHandle) : 'n/a',
  171. 'curl_error' => $this->curlHandle ? curl_error($this->curlHandle) : $error->get_error_message(),
  172. 'curl_info' => $this->curlHandle ? curl_getinfo($this->curlHandle) : 'n/a',
  173. ];
  174. $this->loggerFactory->getLogger(LoggerFactory::TOPIC_MSS)->addError('requests-curl.failed', $logData);
  175. }
  176. }