Application.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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\Fundflow\Client $fundflow
  22. * @property \EasyWeChat\Payment\Jssdk\Client $jssdk
  23. * @property \EasyWeChat\Payment\Order\Client $order
  24. * @property \EasyWeChat\Payment\Refund\Client $refund
  25. * @property \EasyWeChat\Payment\Coupon\Client $coupon
  26. * @property \EasyWeChat\Payment\Reverse\Client $reverse
  27. * @property \EasyWeChat\Payment\Redpack\Client $redpack
  28. * @property \EasyWeChat\BasicService\Url\Client $url
  29. * @property \EasyWeChat\Payment\Transfer\Client $transfer
  30. * @property \EasyWeChat\Payment\Security\Client $security
  31. * @property \EasyWeChat\Payment\ProfitSharing\Client $profit_sharing
  32. * @property \EasyWeChat\Payment\Contract\Client $contract
  33. * @property \EasyWeChat\OfficialAccount\Auth\AccessToken $access_token
  34. *
  35. * @method mixed pay(array $attributes)
  36. * @method mixed authCodeToOpenid(string $authCode)
  37. */
  38. class Application extends ServiceContainer
  39. {
  40. /**
  41. * @var array
  42. */
  43. protected $providers = [
  44. OfficialAccount\Auth\ServiceProvider::class,
  45. BasicService\Url\ServiceProvider::class,
  46. Base\ServiceProvider::class,
  47. Bill\ServiceProvider::class,
  48. Fundflow\ServiceProvider::class,
  49. Coupon\ServiceProvider::class,
  50. Jssdk\ServiceProvider::class,
  51. Merchant\ServiceProvider::class,
  52. Order\ServiceProvider::class,
  53. Redpack\ServiceProvider::class,
  54. Refund\ServiceProvider::class,
  55. Reverse\ServiceProvider::class,
  56. Sandbox\ServiceProvider::class,
  57. Transfer\ServiceProvider::class,
  58. Security\ServiceProvider::class,
  59. ProfitSharing\ServiceProvider::class,
  60. Contract\ServiceProvider::class,
  61. ];
  62. /**
  63. * @var array
  64. */
  65. protected $defaultConfig = [
  66. 'http' => [
  67. 'base_uri' => 'https://api.mch.weixin.qq.com/',
  68. ],
  69. ];
  70. /**
  71. * Build payment scheme for product.
  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. * @return string
  87. */
  88. public function codeUrlScheme(string $codeUrl)
  89. {
  90. return \sprintf('weixin://wxpay/bizpayurl?sr=%s', $codeUrl);
  91. }
  92. /**
  93. * @return \Symfony\Component\HttpFoundation\Response
  94. *
  95. * @codeCoverageIgnore
  96. *
  97. * @throws \EasyWeChat\Kernel\Exceptions\Exception
  98. */
  99. public function handlePaidNotify(Closure $closure)
  100. {
  101. return (new Notify\Paid($this))->handle($closure);
  102. }
  103. /**
  104. * @return \Symfony\Component\HttpFoundation\Response
  105. *
  106. * @codeCoverageIgnore
  107. *
  108. * @throws \EasyWeChat\Kernel\Exceptions\Exception
  109. */
  110. public function handleRefundedNotify(Closure $closure)
  111. {
  112. return (new Notify\Refunded($this))->handle($closure);
  113. }
  114. /**
  115. * @return \Symfony\Component\HttpFoundation\Response
  116. *
  117. * @codeCoverageIgnore
  118. *
  119. * @throws \EasyWeChat\Kernel\Exceptions\Exception
  120. */
  121. public function handleScannedNotify(Closure $closure)
  122. {
  123. return (new Notify\Scanned($this))->handle($closure);
  124. }
  125. /**
  126. * Set sub-merchant.
  127. *
  128. * @return $this
  129. */
  130. public function setSubMerchant(string $mchId, string $appId = null)
  131. {
  132. $this['config']->set('sub_mch_id', $mchId);
  133. $this['config']->set('sub_appid', $appId);
  134. return $this;
  135. }
  136. public function inSandbox(): bool
  137. {
  138. return (bool) $this['config']->get('sandbox');
  139. }
  140. /**
  141. * @return string
  142. *
  143. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  144. */
  145. public function getKey(string $endpoint = null)
  146. {
  147. if ('sandboxnew/pay/getsignkey' === $endpoint) {
  148. return $this['config']->key;
  149. }
  150. $key = $this->inSandbox() ? $this['sandbox']->getKey() : $this['config']->key;
  151. if (empty($key)) {
  152. throw new InvalidArgumentException('config key should not empty.');
  153. }
  154. if (32 !== strlen($key)) {
  155. throw new InvalidArgumentException(sprintf("'%s' should be 32 chars length.", $key));
  156. }
  157. return $key;
  158. }
  159. /**
  160. * @param string $name
  161. * @param array $arguments
  162. *
  163. * @return mixed
  164. */
  165. public function __call($name, $arguments)
  166. {
  167. return call_user_func_array([$this['base'], $name], $arguments);
  168. }
  169. }