Application.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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. * @param string $productId
  74. *
  75. * @return string
  76. */
  77. public function scheme(string $productId): string
  78. {
  79. $params = [
  80. 'appid' => $this['config']->app_id,
  81. 'mch_id' => $this['config']->mch_id,
  82. 'time_stamp' => time(),
  83. 'nonce_str' => uniqid(),
  84. 'product_id' => $productId,
  85. ];
  86. $params['sign'] = Support\generate_sign($params, $this['config']->key);
  87. return 'weixin://wxpay/bizpayurl?'.http_build_query($params);
  88. }
  89. /**
  90. * @param string $codeUrl
  91. *
  92. * @return string
  93. */
  94. public function codeUrlScheme(string $codeUrl)
  95. {
  96. return \sprintf('weixin://wxpay/bizpayurl?sr=%s', $codeUrl);
  97. }
  98. /**
  99. * @param \Closure $closure
  100. *
  101. * @return \Symfony\Component\HttpFoundation\Response
  102. *
  103. * @codeCoverageIgnore
  104. *
  105. * @throws \EasyWeChat\Kernel\Exceptions\Exception
  106. */
  107. public function handlePaidNotify(Closure $closure)
  108. {
  109. return (new Notify\Paid($this))->handle($closure);
  110. }
  111. /**
  112. * @param \Closure $closure
  113. *
  114. * @return \Symfony\Component\HttpFoundation\Response
  115. *
  116. * @codeCoverageIgnore
  117. *
  118. * @throws \EasyWeChat\Kernel\Exceptions\Exception
  119. */
  120. public function handleRefundedNotify(Closure $closure)
  121. {
  122. return (new Notify\Refunded($this))->handle($closure);
  123. }
  124. /**
  125. * @param \Closure $closure
  126. *
  127. * @return \Symfony\Component\HttpFoundation\Response
  128. *
  129. * @codeCoverageIgnore
  130. *
  131. * @throws \EasyWeChat\Kernel\Exceptions\Exception
  132. */
  133. public function handleScannedNotify(Closure $closure)
  134. {
  135. return (new Notify\Scanned($this))->handle($closure);
  136. }
  137. /**
  138. * Set sub-merchant.
  139. *
  140. * @param string $mchId
  141. * @param string|null $appId
  142. *
  143. * @return $this
  144. */
  145. public function setSubMerchant(string $mchId, string $appId = null)
  146. {
  147. $this['config']->set('sub_mch_id', $mchId);
  148. $this['config']->set('sub_appid', $appId);
  149. return $this;
  150. }
  151. /**
  152. * @return bool
  153. */
  154. public function inSandbox(): bool
  155. {
  156. return (bool) $this['config']->get('sandbox');
  157. }
  158. /**
  159. * @param string|null $endpoint
  160. *
  161. * @return string
  162. *
  163. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  164. */
  165. public function getKey(string $endpoint = null)
  166. {
  167. if ('sandboxnew/pay/getsignkey' === $endpoint) {
  168. return $this['config']->key;
  169. }
  170. $key = $this->inSandbox() ? $this['sandbox']->getKey() : $this['config']->key;
  171. if (empty($key)) {
  172. throw new InvalidArgumentException('config key should not empty.');
  173. }
  174. if (32 !== strlen($key)) {
  175. throw new InvalidArgumentException(sprintf("'%s' should be 32 chars length.", $key));
  176. }
  177. return $key;
  178. }
  179. /**
  180. * @param string $name
  181. * @param array $arguments
  182. *
  183. * @return mixed
  184. */
  185. public function __call($name, $arguments)
  186. {
  187. return call_user_func_array([$this['base'], $name], $arguments);
  188. }
  189. }