Order.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | WeChatDeveloper
  4. // +----------------------------------------------------------------------
  5. // | 版权所有 2014~2023 ThinkAdmin [ thinkadmin.top ]
  6. // +----------------------------------------------------------------------
  7. // | 官方网站: https://thinkadmin.top
  8. // +----------------------------------------------------------------------
  9. // | 开源协议 ( https://mit-license.org )
  10. // | 免责声明 ( https://thinkadmin.top/disclaimer )
  11. // +----------------------------------------------------------------------
  12. // | gitee 代码仓库:https://gitee.com/zoujingli/WeChatDeveloper
  13. // | github 代码仓库:https://github.com/zoujingli/WeChatDeveloper
  14. // +----------------------------------------------------------------------
  15. namespace WePayV3;
  16. use WeChat\Contracts\Tools;
  17. use WeChat\Exceptions\InvalidArgumentException;
  18. use WeChat\Exceptions\InvalidResponseException;
  19. use WePayV3\Contracts\BasicWePay;
  20. use WePayV3\Contracts\DecryptAes;
  21. /**
  22. * 直连商户 | 订单支付接口
  23. * Class Order
  24. * @package WePayV3
  25. */
  26. class Order extends BasicWePay
  27. {
  28. const WXPAY_H5 = 'h5';
  29. const WXPAY_APP = 'app';
  30. const WXPAY_JSAPI = 'jsapi';
  31. const WXPAY_NATIVE = 'native';
  32. /**
  33. * 创建支付订单
  34. * @param string $type 支付类型
  35. * @param array $data 支付参数
  36. * @return array
  37. * @throws \WeChat\Exceptions\InvalidResponseException
  38. * @document https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
  39. */
  40. public function create($type, $data)
  41. {
  42. $types = [
  43. 'h5' => '/v3/pay/transactions/h5',
  44. 'app' => '/v3/pay/transactions/app',
  45. 'jsapi' => '/v3/pay/transactions/jsapi',
  46. 'native' => '/v3/pay/transactions/native',
  47. ];
  48. if (empty($types[$type])) {
  49. throw new InvalidArgumentException("Payment {$type} not defined.");
  50. } else {
  51. // 创建预支付码
  52. $result = $this->doRequest('POST', $types[$type], json_encode($data, JSON_UNESCAPED_UNICODE), true);
  53. if (empty($result['h5_url']) && empty($result['code_url']) && empty($result['prepay_id'])) {
  54. $message = isset($result['code']) ? "[ {$result['code']} ] " : '';
  55. $message .= isset($result['message']) ? $result['message'] : json_encode($result, JSON_UNESCAPED_UNICODE);
  56. throw new InvalidResponseException($message);
  57. }
  58. // 支付参数签名
  59. $time = strval(time());
  60. $appid = $this->config['appid'];
  61. $nonceStr = Tools::createNoncestr();
  62. if ($type === 'app') {
  63. $sign = $this->signBuild(join("\n", [$appid, $time, $nonceStr, $result['prepay_id'], '']));
  64. return ['partnerId' => $this->config['mch_id'], 'prepayId' => $result['prepay_id'], 'package' => 'Sign=WXPay', 'nonceStr' => $nonceStr, 'timeStamp' => $time, 'sign' => $sign];
  65. } elseif ($type === 'jsapi') {
  66. $sign = $this->signBuild(join("\n", [$appid, $time, $nonceStr, "prepay_id={$result['prepay_id']}", '']));
  67. return ['appId' => $appid, 'timestamp' => $time, 'timeStamp' => $time, 'nonceStr' => $nonceStr, 'package' => "prepay_id={$result['prepay_id']}", 'signType' => 'RSA', 'paySign' => $sign];
  68. } else {
  69. return $result;
  70. }
  71. }
  72. }
  73. /**
  74. * 支付订单查询
  75. * @param string $tradeNo 订单单号
  76. * @return array
  77. * @throws \WeChat\Exceptions\InvalidResponseException
  78. * @document https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_2.shtml
  79. */
  80. public function query($tradeNo)
  81. {
  82. $pathinfo = "/v3/pay/transactions/out-trade-no/{$tradeNo}";
  83. return $this->doRequest('GET', "{$pathinfo}?mchid={$this->config['mch_id']}", '', true);
  84. }
  85. /**
  86. * 关闭支付订单
  87. * @param string $tradeNo 订单单号
  88. * @return array
  89. * @throws \WeChat\Exceptions\InvalidResponseException
  90. */
  91. public function close($tradeNo)
  92. {
  93. $data = ['mchid' => $this->config['mch_id']];
  94. $path = "/v3/pay/transactions/out-trade-no/{$tradeNo}/close";
  95. return $this->doRequest('POST', $path, json_encode($data, JSON_UNESCAPED_UNICODE), true);
  96. }
  97. /**
  98. * 支付通知解析
  99. * @param array $data
  100. * @return array
  101. * @throws \WeChat\Exceptions\InvalidDecryptException
  102. */
  103. public function notify(array $data = [])
  104. {
  105. if (empty($data)) {
  106. $data = json_decode(Tools::getRawInput(), true);
  107. }
  108. if (isset($data['resource'])) {
  109. $aes = new DecryptAes($this->config['mch_v3_key']);
  110. $data['result'] = $aes->decryptToString(
  111. $data['resource']['associated_data'],
  112. $data['resource']['nonce'],
  113. $data['resource']['ciphertext']
  114. );
  115. }
  116. return $data;
  117. }
  118. /**
  119. * 创建退款订单
  120. * @param array $data 退款参数
  121. * @return array
  122. * @throws \WeChat\Exceptions\InvalidResponseException
  123. * @document https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml
  124. */
  125. public function createRefund($data)
  126. {
  127. $path = '/v3/refund/domestic/refunds';
  128. return $this->doRequest('POST', $path, json_encode($data, JSON_UNESCAPED_UNICODE), true);
  129. }
  130. /**
  131. * 退款订单查询
  132. * @param string $refundNo 退款单号
  133. * @return array
  134. * @throws \WeChat\Exceptions\InvalidResponseException
  135. * @document https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_10.shtml
  136. */
  137. public function queryRefund($refundNo)
  138. {
  139. $path = "/v3/refund/domestic/refunds/{$refundNo}";
  140. return $this->doRequest('GET', $path, '', true);
  141. }
  142. /**
  143. * 获取退款通知
  144. * @param mixed $data
  145. * @return array
  146. * @throws \WeChat\Exceptions\InvalidDecryptException
  147. * @deprecated 直接使用 Notify 方法
  148. */
  149. public function notifyRefund($data = [])
  150. {
  151. return $this->notify($data);
  152. }
  153. /**
  154. * 申请交易账单
  155. * @param array|string $params
  156. * @return array
  157. * @throws \WeChat\Exceptions\InvalidResponseException
  158. * @document https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_6.shtml
  159. */
  160. public function tradeBill($params)
  161. {
  162. $path = '/v3/bill/tradebill?' . is_array($params) ? http_build_query($params) : $params;
  163. return $this->doRequest('GET', $path, '', true);
  164. }
  165. /**
  166. * 申请资金账单
  167. * @param array|string $params
  168. * @return array
  169. * @throws \WeChat\Exceptions\InvalidResponseException
  170. * @document https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_7.shtml
  171. */
  172. public function fundflowBill($params)
  173. {
  174. $path = '/v3/bill/fundflowbill?' . is_array($params) ? http_build_query($params) : $params;
  175. return $this->doRequest('GET', $path, '', true);
  176. }
  177. /**
  178. * 下载账单文件
  179. * @param string $fileurl
  180. * @return string 二进制 Excel 内容
  181. * @throws \WeChat\Exceptions\InvalidResponseException
  182. * @document https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_6_1.shtml
  183. */
  184. public function downloadBill($fileurl)
  185. {
  186. return $this->doRequest('GET', $fileurl, '', false, false);
  187. }
  188. }