EcommerceBillHandler.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <?php
  2. namespace App\Handlers;
  3. use App\Models\EcommerceBillW;
  4. use Illuminate\Console\Command;
  5. use Illuminate\Support\Facades\Log;
  6. class EcommerceBillHandler extends Command
  7. {
  8. //获取二级商户资金账单
  9. public function getecommercebill($bill_date,$account_type,$algorithm){
  10. $url='https://api.mch.weixin.qq.com/v3/ecommerce/bill/fundflowbill?bill_date='.$bill_date.'&account_type='.$account_type.'&algorithm='.$algorithm;
  11. $merchant_id=config('wechat.payment.default.mch_id');//商户号
  12. $serial_no=config('wechat.payment.default.serial_no');//不是平台证书序列号
  13. $handle=new SignHandler();
  14. $mch_private_key=$handle->getPublicKey();//读取商户api证书公钥 getPublicKey()获取方法 见下文
  15. $timestamp=time();//时间戳
  16. $nonce=$handle->nonce_str();//随机字符串
  17. $body="";
  18. $sign=$handle->sign($url,'GET',$timestamp,$nonce,$body,$mch_private_key,$merchant_id,$serial_no);//签名
  19. $header=[
  20. 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $sign,
  21. 'Accept:application/json',
  22. 'User-Agent:' . $merchant_id,
  23. 'Content-Type:application/json',
  24. 'Wechatpay-Serial:' . $handle->getzhengshu()//获取平台证书序列号
  25. ];
  26. $result=$handle->curl($url,'',$header,'GET');
  27. $res=json_decode($result,true);
  28. if(!array_key_exists('download_bill_list', $res)){
  29. Log::info($res);
  30. return $res;
  31. }
  32. Log::info($bill_date.'下载资金账单,页数为'.count($res['download_bill_list']));
  33. foreach($res['download_bill_list'] as $key=>$val){
  34. $ciphertext= $this->down($val['download_url']);
  35. $key=$this->getDecrypt($val['encrypt_key'],'',$val['nonce']);
  36. $result_str=$this->decryptToString('',$val['nonce'],base64_encode($ciphertext),$key);
  37. $res_arr=$this->deal_ecommerce_bill($result_str);
  38. $bill_day = $res_arr['bill'][0]['bill_date'];
  39. $trade_info = EcommerceBillW::where('bill_date',$bill_day)->first();
  40. if(!$trade_info){
  41. if(count($res_arr['bill']) > 1000){
  42. $arr = array_chunk($res_arr['bill'],1000);
  43. foreach($arr as $k=>$v){
  44. EcommerceBillW::insert($v);
  45. }
  46. }else{
  47. EcommerceBillW::insert($res_arr['bill']);
  48. }
  49. }
  50. }
  51. return $res;
  52. }
  53. public function down($url){
  54. $merchant_id=config('wechat.payment.default.mch_id');//商户号
  55. $serial_no=config('wechat.payment.default.serial_no');//不是平台证书序列号
  56. $handle=new SignHandler();
  57. $mch_private_key=$handle->getPublicKey();//读取商户api证书公钥 getPublicKey()获取方法 见下文
  58. $timestamp=time();//时间戳
  59. $nonce=$handle->nonce_str();//随机字符串
  60. $body="";
  61. $sign=$handle->sign($url,'GET',$timestamp,$nonce,$body,$mch_private_key,$merchant_id,$serial_no);//签名
  62. $header=[
  63. 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $sign,
  64. 'Accept:application/json',
  65. 'User-Agent:' . $merchant_id,
  66. 'Content-Type:application/json',
  67. 'Wechatpay-Serial:' . $handle->getzhengshu()//获取平台证书序列号
  68. ];
  69. $result=$handle->curl($url,'',$header,'GET');
  70. return $result;
  71. }
  72. //解密数据
  73. public function getDecrypt($ciphertext, $associatedData, $nonceStr){
  74. $mch_private_key= file_get_contents(config('wechat.payment.default.key_path'));
  75. // Log::info($mch_private_key);
  76. $str = base64_decode($ciphertext);
  77. openssl_private_decrypt($str,$encrypted,$mch_private_key,OPENSSL_PKCS1_OAEP_PADDING);
  78. return $encrypted;
  79. }
  80. //解密返回的信息
  81. public function decryptToString($associatedData,$nonceStr,$ciphertext,$aesKey){
  82. if (strlen($aesKey) != 32) {
  83. throw new InvalidArgumentException('无效的ApiV3Key,长度应为32个字节');
  84. }
  85. $ciphertext=\base64_decode($ciphertext);
  86. if (strlen($ciphertext) <= 16) {
  87. return false;
  88. }
  89. if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') &&
  90. \sodium_crypto_aead_aes256gcm_is_available()) {
  91. return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey);
  92. }
  93. // ext-libsodium (need install libsodium-php 1.x via pecl)
  94. if (function_exists('\Sodium\crypto_aead_aes256gcm_is_available') &&
  95. \Sodium\crypto_aead_aes256gcm_is_available()) {
  96. return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey);
  97. }
  98. // if(function_exists('\sodium_crypto_aead_aes256gcm_is_available')&& \sodium_crypto_aead_aes256gcm_is_available()){
  99. // return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext,$associatedData,$nonceStr,$aesKey);
  100. // }
  101. if(PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())){
  102. $ctext=substr($ciphertext,0,-16);
  103. $authTag=substr($ciphertext,-16);
  104. return \openssl_decrypt(
  105. $ctext,
  106. 'aes-256-gcm',
  107. $aesKey,
  108. \OPENSSL_RAW_DATA,
  109. $nonceStr,
  110. $authTag,
  111. $associatedData
  112. );
  113. }
  114. throw new \RuntimeException('php7.1');
  115. }
  116. public function deal_ecommerce_bill($response){
  117. $result = array();
  118. $response = str_replace(","," ",$response);
  119. $response = explode(PHP_EOL, $response);
  120. foreach ($response as $key=>$val){
  121. if(strpos($val, '`') !== false){
  122. $data = explode('`', $val);
  123. array_shift($data); // 删除第一个元素并下标从0开始
  124. if(count($data) == 13){ // 处理账单数据
  125. $result['bill'][] = array(
  126. 'bill_time' => $data[0], // 记账时间
  127. 'wx_order_no' => $data[1], // 微信支付业务单号
  128. 'fee_order_no' => $data[2], // 资金流水单号
  129. 'bill_name' => $data[3], // 业务名称
  130. 'bill_type' => $data[4], // 业务类型
  131. 'fee_type' => $data[5], // 收支类型
  132. 'amount' => $data[6], // 收支金额(元)
  133. 'account_fee' => $data[7], // 账户结余(元)
  134. 'apply_name' => $data[8], // 资金变更提交申请人
  135. 'remark' => $data[9], // 备注
  136. 'bill_cre_no' => $data[10], // 业务凭证号
  137. 'sub_mch_id' => $data[11], // 电商二级商户号
  138. 'account_type' => $data[12], // 账户类型
  139. 'bill_date' => date("Y-m-d", strtotime($data[0]))
  140. );
  141. }
  142. if(count($data) == 1){ // 统计数据
  143. $result['summary'] = array(
  144. 'order_num' => $data[0], // 资金流水总笔数
  145. );
  146. }
  147. }
  148. }
  149. return $result;
  150. }
  151. }