Application.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <?php
  2. /*
  3. * This file is part of the overtrue/wechat.
  4. *
  5. * (c) overtrue <i@overtrue.me>
  6. *
  7. * This source file is subject to the MIT license that is bundled
  8. * with this source code in the file LICENSE.
  9. */
  10. namespace EasyWeChat\Payment;
  11. use Closure;
  12. use EasyWeChat\BasicService;
  13. use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
  14. use EasyWeChat\Kernel\ServiceContainer;
  15. use EasyWeChat\Kernel\Support;
  16. use EasyWeChat\OfficialAccount;
  17. /**
  18. * Class Application.
  19. *
  20. * @property \EasyWeChat\Payment\Bill\Client $bill
  21. * @property \EasyWeChat\Payment\Jssdk\Client $jssdk
  22. * @property \EasyWeChat\Payment\Order\Client $order
  23. * @property \EasyWeChat\Payment\Refund\Client $refund
  24. * @property \EasyWeChat\Payment\Coupon\Client $coupon
  25. * @property \EasyWeChat\Payment\Reverse\Client $reverse
  26. * @property \EasyWeChat\Payment\Redpack\Client $redpack
  27. * @property \EasyWeChat\BasicService\Url\Client $url
  28. * @property \EasyWeChat\Payment\Transfer\Client $transfer
  29. * @property \EasyWeChat\Payment\Security\Client $security
  30. * @property \EasyWeChat\Payment\ProfitSharing\Client $profit_sharing
  31. * @property \EasyWeChat\OfficialAccount\Auth\AccessToken $access_token
  32. *
  33. * @method mixed pay(array $attributes)
  34. * @method mixed authCodeToOpenid(string $authCode)
  35. */
  36. class Application extends ServiceContainer
  37. {
  38. /**
  39. * @var array
  40. */
  41. protected $providers = [
  42. OfficialAccount\Auth\ServiceProvider::class,
  43. BasicService\Url\ServiceProvider::class,
  44. Base\ServiceProvider::class,
  45. Bill\ServiceProvider::class,
  46. Coupon\ServiceProvider::class,
  47. Jssdk\ServiceProvider::class,
  48. Merchant\ServiceProvider::class,
  49. Order\ServiceProvider::class,
  50. Redpack\ServiceProvider::class,
  51. Refund\ServiceProvider::class,
  52. Reverse\ServiceProvider::class,
  53. Sandbox\ServiceProvider::class,
  54. Transfer\ServiceProvider::class,
  55. Security\ServiceProvider::class,
  56. ProfitSharing\ServiceProvider::class,
  57. ];
  58. /**
  59. * @var array
  60. */
  61. protected $defaultConfig = [
  62. 'http' => [
  63. 'base_uri' => 'https://api.mch.weixin.qq.com/',
  64. ],
  65. ];
  66. /**
  67. * Build payment scheme for product.
  68. *
  69. * @param string $productId
  70. *
  71. * @return string
  72. */
  73. public function scheme(string $productId): string
  74. {
  75. $params = [
  76. 'appid' => $this['config']->app_id,
  77. 'mch_id' => $this['config']->mch_id,
  78. 'time_stamp' => time(),
  79. 'nonce_str' => uniqid(),
  80. 'product_id' => $productId,
  81. ];
  82. $params['sign'] = Support\generate_sign($params, $this['config']->key);
  83. return 'weixin://wxpay/bizpayurl?'.http_build_query($params);
  84. }
  85. /**
  86. * @param string $codeUrl
  87. *
  88. * @return string
  89. */
  90. public function codeUrlScheme(string $codeUrl)
  91. {
  92. return \sprintf('weixin://wxpay/bizpayurl?sr=%s', $codeUrl);
  93. }
  94. /**
  95. * @param \Closure $closure
  96. *
  97. * @return \Symfony\Component\HttpFoundation\Response
  98. *
  99. * @codeCoverageIgnore
  100. *
  101. * @throws \EasyWeChat\Kernel\Exceptions\Exception
  102. */
  103. public function handlePaidNotify(Closure $closure)
  104. {
  105. return (new Notify\Paid($this))->handle($closure);
  106. }
  107. /**
  108. * @param \Closure $closure
  109. *
  110. * @return \Symfony\Component\HttpFoundation\Response
  111. *
  112. * @codeCoverageIgnore
  113. *
  114. * @throws \EasyWeChat\Kernel\Exceptions\Exception
  115. */
  116. public function handleRefundedNotify(Closure $closure)
  117. {
  118. return (new Notify\Refunded($this))->handle($closure);
  119. }
  120. /**
  121. * @param \Closure $closure
  122. *
  123. * @return \Symfony\Component\HttpFoundation\Response
  124. *
  125. * @codeCoverageIgnore
  126. *
  127. * @throws \EasyWeChat\Kernel\Exceptions\Exception
  128. */
  129. public function handleScannedNotify(Closure $closure)
  130. {
  131. return (new Notify\Scanned($this))->handle($closure);
  132. }
  133. /**
  134. * Set sub-merchant.
  135. *
  136. * @param string $mchId
  137. * @param string|null $appId
  138. *
  139. * @return $this
  140. */
  141. public function setSubMerchant(string $mchId, string $appId = null)
  142. {
  143. $this['config']->set('sub_mch_id', $mchId);
  144. $this['config']->set('sub_appid', $appId);
  145. return $this;
  146. }
  147. /**
  148. * @return bool
  149. */
  150. public function inSandbox(): bool
  151. {
  152. return (bool) $this['config']->get('sandbox');
  153. }
  154. /**
  155. * @param string|null $endpoint
  156. *
  157. * @return string
  158. *
  159. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  160. */
  161. public function getKey(string $endpoint = null)
  162. {
  163. if ('sandboxnew/pay/getsignkey' === $endpoint) {
  164. return $this['config']->key;
  165. }
  166. $key = $this->inSandbox() ? $this['sandbox']->getKey() : $this['config']->key;
  167. if (empty($key)) {
  168. throw new InvalidArgumentException('config key should not empty.');
  169. }
  170. if (32 !== strlen($key)) {
  171. throw new InvalidArgumentException(sprintf("'%s' should be 32 chars length.", $key));
  172. }
  173. return $key;
  174. }
  175. /**
  176. * @param string $name
  177. * @param array $arguments
  178. *
  179. * @return mixed
  180. */
  181. public function __call($name, $arguments)
  182. {
  183. return call_user_func_array([$this['base'], $name], $arguments);
  184. }
  185. }