RequestOptions.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <?php
  2. namespace Stripe\Util;
  3. class RequestOptions
  4. {
  5. /**
  6. * @var array<string> a list of headers that should be persisted across requests
  7. */
  8. public static $HEADERS_TO_PERSIST = [
  9. 'Stripe-Account',
  10. 'Stripe-Version',
  11. ];
  12. /** @var array<string, string> */
  13. public $headers;
  14. /** @var null|string */
  15. public $apiKey;
  16. /** @var null|string */
  17. public $apiBase;
  18. /**
  19. * @param null|string $key
  20. * @param array<string, string> $headers
  21. * @param null|string $base
  22. */
  23. public function __construct($key = null, $headers = [], $base = null)
  24. {
  25. $this->apiKey = $key;
  26. $this->headers = $headers;
  27. $this->apiBase = $base;
  28. }
  29. /**
  30. * @return array<string, string>
  31. */
  32. public function __debugInfo()
  33. {
  34. return [
  35. 'apiKey' => $this->redactedApiKey(),
  36. 'headers' => $this->headers,
  37. 'apiBase' => $this->apiBase,
  38. ];
  39. }
  40. /**
  41. * Unpacks an options array and merges it into the existing RequestOptions
  42. * object.
  43. *
  44. * @param null|array|RequestOptions|string $options a key => value array
  45. * @param bool $strict when true, forbid string form and arbitrary keys in array form
  46. *
  47. * @return RequestOptions
  48. */
  49. public function merge($options, $strict = false)
  50. {
  51. $other_options = self::parse($options, $strict);
  52. if (null === $other_options->apiKey) {
  53. $other_options->apiKey = $this->apiKey;
  54. }
  55. if (null === $other_options->apiBase) {
  56. $other_options->apiBase = $this->apiBase;
  57. }
  58. $other_options->headers = \array_merge($this->headers, $other_options->headers);
  59. return $other_options;
  60. }
  61. /**
  62. * Discards all headers that we don't want to persist across requests.
  63. */
  64. public function discardNonPersistentHeaders()
  65. {
  66. foreach ($this->headers as $k => $v) {
  67. if (!\in_array($k, self::$HEADERS_TO_PERSIST, true)) {
  68. unset($this->headers[$k]);
  69. }
  70. }
  71. }
  72. /**
  73. * Unpacks an options array into an RequestOptions object.
  74. *
  75. * @param null|array|RequestOptions|string $options a key => value array
  76. * @param bool $strict when true, forbid string form and arbitrary keys in array form
  77. *
  78. * @throws \Stripe\Exception\InvalidArgumentException
  79. *
  80. * @return RequestOptions
  81. */
  82. public static function parse($options, $strict = false)
  83. {
  84. if ($options instanceof self) {
  85. return $options;
  86. }
  87. if (null === $options) {
  88. return new RequestOptions(null, [], null);
  89. }
  90. if (\is_string($options)) {
  91. if ($strict) {
  92. $message = 'Do not pass a string for request options. If you want to set the '
  93. . 'API key, pass an array like ["api_key" => <apiKey>] instead.';
  94. throw new \Stripe\Exception\InvalidArgumentException($message);
  95. }
  96. return new RequestOptions($options, [], null);
  97. }
  98. if (\is_array($options)) {
  99. $headers = [];
  100. $key = null;
  101. $base = null;
  102. if (\array_key_exists('api_key', $options)) {
  103. $key = $options['api_key'];
  104. unset($options['api_key']);
  105. }
  106. if (\array_key_exists('idempotency_key', $options)) {
  107. $headers['Idempotency-Key'] = $options['idempotency_key'];
  108. unset($options['idempotency_key']);
  109. }
  110. if (\array_key_exists('stripe_account', $options)) {
  111. $headers['Stripe-Account'] = $options['stripe_account'];
  112. unset($options['stripe_account']);
  113. }
  114. if (\array_key_exists('stripe_version', $options)) {
  115. $headers['Stripe-Version'] = $options['stripe_version'];
  116. unset($options['stripe_version']);
  117. }
  118. if (\array_key_exists('api_base', $options)) {
  119. $base = $options['api_base'];
  120. unset($options['api_base']);
  121. }
  122. if ($strict && !empty($options)) {
  123. $message = 'Got unexpected keys in options array: ' . \implode(', ', \array_keys($options));
  124. throw new \Stripe\Exception\InvalidArgumentException($message);
  125. }
  126. return new RequestOptions($key, $headers, $base);
  127. }
  128. $message = 'The second argument to Stripe API method calls is an '
  129. . 'optional per-request apiKey, which must be a string, or '
  130. . 'per-request options, which must be an array. (HINT: you can set '
  131. . 'a global apiKey by "Stripe::setApiKey(<apiKey>)")';
  132. throw new \Stripe\Exception\InvalidArgumentException($message);
  133. }
  134. private function redactedApiKey()
  135. {
  136. $pieces = \explode('_', $this->apiKey, 3);
  137. $last = \array_pop($pieces);
  138. $redactedLast = \strlen($last) > 4
  139. ? (\str_repeat('*', \strlen($last) - 4) . \substr($last, -4))
  140. : $last;
  141. $pieces[] = $redactedLast;
  142. return \implode('_', $pieces);
  143. }
  144. }