Transfer.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <?php
  2. namespace JiaLeo\Payment\Wechatpay;
  3. use JiaLeo\Payment\Common\PaymentException;
  4. class Transfer extends BaseWechatpay
  5. {
  6. public $payUrl = '/mmpaymkttransfers/promotion/transfers';
  7. public $errorCode; //错误代码
  8. public $errorCodeDes; //错误描述
  9. /**
  10. * 银行编码
  11. * @var array
  12. */
  13. public $bankCode = array(
  14. '1002' => '工商银行',
  15. '1005' => '农业银行',
  16. '1026' => '中国银行',
  17. '1003' => '建设银行',
  18. '1001' => '招商银行',
  19. '1066' => '邮储银行',
  20. '1020' => '交通银行',
  21. '1004' => '浦发银行',
  22. '1006' => '民生银行',
  23. '1009' => '兴业银行',
  24. '1010' => '平安银行',
  25. '1021' => '中信银行',
  26. '1025' => '华夏银行',
  27. '1027' => '广发银行',
  28. '1022' => '光大银行',
  29. '1032' => '北京银行',
  30. '1056' => '宁波银行',
  31. );
  32. /**
  33. * 企业付款到零钱
  34. * @return mixed
  35. * @throws PaymentException
  36. */
  37. public function handle($params)
  38. {
  39. //检查订单号是否合法
  40. if (empty($params['partner_trade_no'])) {
  41. throw new PaymentException('商户订单号不能为空');
  42. }
  43. // 需要转账金额不能低于1
  44. if (empty($params['amount']) || $params['amount'] < 100) {
  45. throw new PaymentException('转账金额不能为空,且不能低于 1 元');
  46. }
  47. if (empty($params['openid'])) {
  48. throw new PaymentException('openid不能为空');
  49. }
  50. $is_check_name = !empty($params['check_name']) ? true : false;
  51. if (empty($params['re_user_name']) && $is_check_name) {
  52. throw new PaymentException('校验用户姓名选项为验证时,收款用户姓名(re_user_name)不能为空');
  53. }
  54. if (!isset($params['create_ip'])) {
  55. $ip_address = !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
  56. //兼容处理
  57. $ip_address_arr = explode(',', $ip_address);
  58. $ip_address = $ip_address_arr[0];
  59. } else {
  60. $ip_address = $params['create_ip'];
  61. }
  62. $data = array(
  63. 'mch_appid' => $this->config['appid'],
  64. 'mchid' => $this->config['mchid'],
  65. 'nonce_str' => $this->getNonceStr(),
  66. 'partner_trade_no' => $params['partner_trade_no'],
  67. 'amount' => $params['amount'],
  68. 'openid' => $params['openid'],
  69. 'check_name' => !$is_check_name ? 'NO_CHECK' : 'FORCE_CHECK',
  70. 'spbill_create_ip' => $ip_address,
  71. );
  72. if ($is_check_name) {
  73. $data['re_user_name'] = $params['re_user_name'];
  74. }
  75. if (!empty($params['desc'])) {
  76. $data['desc'] = $params['desc'];
  77. }
  78. //签名
  79. $data['sign'] = $this->makeSign($data);
  80. //转换成xml
  81. $xml = $this->toXml($data);
  82. $result = $this->postXmlCurl($this->gateway . $this->payUrl, $xml, $this->config['sslcert_path'], $this->config['sslkey_path']);
  83. $get_result = $this->fromXml($result);
  84. try {
  85. if (!isset($get_result['return_code']) || $get_result['return_code'] != 'SUCCESS') {
  86. throw new PaymentException('调起转账失败!错误信息:' . isset($get_result['return_msg']) ? $get_result['return_msg'] : $get_result);
  87. }
  88. if ($get_result['result_code'] != 'SUCCESS') {
  89. throw new PaymentException('调起转账失败!错误信息:' . isset($get_result['err_code_des']) ? $get_result['err_code_des'] : $get_result);
  90. }
  91. } catch (\Exception $e) {
  92. $this->errorCode = $get_result['err_code'];
  93. $this->errorCodeDes = $get_result['err_code_des'];
  94. return false;
  95. }
  96. return $get_result;
  97. }
  98. /**
  99. * 转账到银行卡
  100. * @param $params
  101. * @return bool
  102. * @throws PaymentException
  103. */
  104. public function handleToBank($params)
  105. {
  106. $this->payUrl = '/mmpaysptrans/pay_bank';
  107. //检查订单号是否合法
  108. if (empty($params['partner_trade_no'])) {
  109. throw new PaymentException('商户订单号不能为空');
  110. }
  111. // 需要转账金额不能低于1
  112. if (empty($params['amount']) || $params['amount'] < 100) {
  113. throw new PaymentException('转账金额不能为空,且不能低于 1 元');
  114. }
  115. if (empty($params['bank_no'])) {
  116. throw new PaymentException('bank_no不能为空');
  117. }
  118. if (empty($params['true_name'])) {
  119. throw new PaymentException('true_name不能为空');
  120. }
  121. if (empty($params['bank_code']) || !isset($this->bankCode[$params['bank_code']])) {
  122. throw new PaymentException('bank_code不能为空或银行编号错误!');
  123. }
  124. $data = array(
  125. 'mch_id' => $this->config['mchid'],
  126. 'nonce_str' => $this->getNonceStr(),
  127. 'partner_trade_no' => $params['partner_trade_no'],
  128. 'amount' => $params['amount'],
  129. 'enc_bank_no' => $this->rsaPublicEncrypt($params['bank_no']),
  130. 'enc_true_name' => $this->rsaPublicEncrypt($params['true_name']),
  131. 'bank_code' => $params['bank_code'],
  132. );
  133. !isset($params['desc']) ?: $data['desc'] = $params['desc'];
  134. //签名
  135. $data['sign'] = $this->makeSign($data);
  136. //转换成xml
  137. $xml = $this->toXml($data);
  138. $result = $this->postXmlCurl($this->gateway . $this->payUrl, $xml, $this->config['sslcert_path'], $this->config['sslkey_path']);
  139. $get_result = $this->fromXml($result);
  140. try {
  141. if (!isset($get_result['return_code']) || $get_result['return_code'] != 'SUCCESS') {
  142. throw new PaymentException('调起转账失败!错误信息:' . isset($get_result['return_msg']) ? $get_result['return_msg'] : $get_result);
  143. }
  144. if ($get_result['result_code'] != 'SUCCESS') {
  145. throw new PaymentException('调起转账失败!错误信息:' . isset($get_result['err_code_des']) ? $get_result['err_code_des'] : $get_result);
  146. }
  147. } catch (\Exception $e) {
  148. $this->errorCode = $get_result['err_code'];
  149. $this->errorCodeDes = $get_result['err_code_des'];
  150. return false;
  151. }
  152. return $get_result;
  153. }
  154. /**
  155. * 查询企业打款信息
  156. * @param $params
  157. * $params[partner_trade_no] int 商户订单号
  158. * $params[nonce_str] string 随机字符串,长度小于32位
  159. * @return bool|mixed
  160. * @throws PaymentException
  161. */
  162. public function queryBankOrder($params)
  163. {
  164. $this->payUrl = '/mmpaysptrans/query_bank';
  165. $param = [
  166. 'mch_id' => $this->config['mchid'],
  167. 'partner_trade_no' => $params['partner_trade_no'],
  168. 'nonce_str' => $params['nonce_str'],
  169. ];
  170. // 签名
  171. $sign = $this->makeSign($param);
  172. $param['sign'] = $sign;
  173. //转换成xml
  174. $xml = $this->toXml($param);
  175. $result = $this->postXmlCurl($this->gateway . $this->payUrl, $xml, $this->config['sslcert_path'], $this->config['sslkey_path']);
  176. $get_result = $this->fromXml($result);
  177. try {
  178. if (!isset($get_result['return_code']) || $get_result['return_code'] != 'SUCCESS') {
  179. throw new PaymentException('查询企业打款到银行卡信息!错误信息:' . isset($get_result['return_msg']) ? $get_result['return_msg'] : $get_result);
  180. }
  181. if ($get_result['result_code'] != 'SUCCESS') {
  182. throw new PaymentException('查询企业打款到银行卡信息!错误信息:' . isset($get_result['err_code_des']) ? $get_result['err_code_des'] : $get_result);
  183. }
  184. } catch (\Exception $e) {
  185. $this->errorCode = $get_result['err_code'];
  186. $this->errorCodeDes = $get_result['err_code_des'];
  187. return false;
  188. }
  189. return $get_result;
  190. }
  191. /**
  192. * RSA公钥加密
  193. * @param $str
  194. * @return string
  195. * @throws PaymentException
  196. */
  197. public function rsaPublicEncrypt($str)
  198. {
  199. $publicstr = file_get_contents($this->config['transfer_rsa_public_path']);
  200. $publickey = openssl_pkey_get_public($publicstr); // 读取公钥
  201. if (!$publickey) {
  202. throw new PaymentException('读取公钥错误!');
  203. }
  204. $r = openssl_public_encrypt($str, $encrypted, $publickey, OPENSSL_PKCS1_OAEP_PADDING);
  205. if (!$r) {
  206. throw new PaymentException('公钥加密失败错误!');
  207. }
  208. return base64_encode($encrypted);
  209. }
  210. }