From a39ac52406d91cff75d93507c3273c206045589c Mon Sep 17 00:00:00 2001 From: Lei OT Date: Thu, 21 Dec 2023 15:50:46 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20wxpay:=20=E8=AF=B7=E6=B1=82=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E6=9F=A5=E8=AF=A2=E6=94=B6=E6=AC=BE/=E9=80=80?= =?UTF-8?q?=E6=AC=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pay/controllers/WxpayService.php | 29 ++++++ .../third_party/pay/libraries/wxpay_call.php | 63 ++++++++++++- .../pay/models/Online_payment_note_model.php | 91 ++++++++++++++++++- .../pay/models/WxpayQueryContentBuilder.php | 6 ++ webht/third_party/pay/views/payment_list.php | 1 + 5 files changed, 184 insertions(+), 6 deletions(-) diff --git a/webht/third_party/pay/controllers/WxpayService.php b/webht/third_party/pay/controllers/WxpayService.php index df2ac142..2f018387 100644 --- a/webht/third_party/pay/controllers/WxpayService.php +++ b/webht/third_party/pay/controllers/WxpayService.php @@ -166,6 +166,35 @@ class WxpayService extends CI_Controller { return; } + public function query() + { + $all_account = explode(",", $this->config->item('all_account', 'wxpay')); + $GLOBALS['__WX_SITE_NAME__'] = $all_account[0]; + + $transaction_id = $this->input->get_post("keywords"); + $this->load->model('WxpayQueryContentBuilder', 'query_builder'); + $this->query_builder->set_transaction_id($transaction_id); + $this->load->library('Wxpay_call'); + foreach ($all_account as $account) { + + $resultR = $this->wxpay_call->query_order_refund($this->query_builder, 0, $account); + $result = $this->wxpay_call->query_order_refund($this->query_builder, 1, $account); + if ($result['status'] === true) { + $this->note_model->add_note_wxpay($result['data'], $account, 'pay'); + } + if ($resultR['status'] === true) { + $this->note_model->add_note_wxpay($resultR['data'], $account, 'refund'); + } + // log_message('error',"query wxpay failed. $account $transaction_id"); + } + $data['method_code'] = 15016; + $data["method_name"] = 'WeChat'; + $data['date'] = date('Y-m-d'); + $data['notelist'] = $this->note_model->search_key($transaction_id); + $this->load->view("payment_list",$data); + return; + } + public function response_to_wx($response_arr) { $response_body = to_xml($response_arr); diff --git a/webht/third_party/pay/libraries/wxpay_call.php b/webht/third_party/pay/libraries/wxpay_call.php index 42aff5a4..f632b733 100644 --- a/webht/third_party/pay/libraries/wxpay_call.php +++ b/webht/third_party/pay/libraries/wxpay_call.php @@ -7,22 +7,75 @@ class Wxpay_call protected $ci; private $api_info_arr = array(); + private $merchant_account = ''; - public function __construct() + public function __construct($account = '') { $this->ci =& get_instance(); $this->ci->load->helper('payment'); $this->ci->config->load('wxpay', true); // $this->ci->load->model('WxpayQueryContentBuilder', 'query_builder'); + $this->merchant_account = $account; } - private function init_api() + private function init_api($account = '') { - $this->wx_site_config = $this->ci->config->item($GLOBALS['__WX_SITE_NAME__'], 'wxpay'); + $account = $account ? $account : ($this->merchant_account ? $this->merchant_account : $GLOBALS['__WX_SITE_NAME__']); + $this->wx_site_config = $this->ci->config->item($account, 'wxpay'); $this->api_info_arr['appid'] = $this->wx_site_config['app_id']; $this->api_info_arr['mch_id'] = $this->wx_site_config['mch_id']; - $this->api_info_arr['key'] = $this->wx_site_config['key']; - $this->api_info_arr['app_secret'] = $this->wx_site_config['app_secret']; + // $this->api_info_arr['key'] = $this->wx_site_config['key']; + // $this->api_info_arr['app_secret'] = $this->wx_site_config['app_secret']; + } + + public function query_order_refund($query_content, $query_refund=0, $account = '') + { + $ret = array('status'=>false, 'data'=>array()); + $this->init_api($account); + // return false; + $url = $query_refund === 0 ? "https://api.mch.weixin.qq.com/pay/refundquery" : "https://api.mch.weixin.qq.com/pay/orderquery"; + $query_content_input = $query_content->getBizContent(true); + //检测必填参数 + if( ! $query_content_input['transaction_id']) { + throw new WxPayException("查询接口中,缺少必填参数 transaction_id !"); + } + $this->api_info_arr['nonce_str'] = ($this->get_nonce_str());//随机字符串 + + $this->api_info_arr['sign'] = $this->make_sign(array_merge($this->api_info_arr, $query_content_input));//签名 + $xml = to_xml(array_merge($this->api_info_arr, $query_content_input)); + // log_message('error','test: ' . __CLASS__ . PHP_EOL . var_export(array_merge($this->api_info_arr, $query_content_input), 1)); + + $response = $this->post_xml_curl($this->api_info_arr, $xml, $url, 20); + $response_arr = from_xml($response); + $ret['status'] = $response_arr['return_code'] === 'SUCCESS' && $response_arr['result_code'] === 'SUCCESS'; + if ($query_refund !== 0) { + $ret['data'] = [$response_arr]; + return $ret; + } + if ($ret['status'] !== true) { + return $ret; + } + // log_message('error','test: response_arr ' .$query_refund . __CLASS__ . PHP_EOL . var_export($response_arr, 1)); + $refund_times = strval($response_arr['refund_count']); + $order_keys = ( array_filter(array_keys($response_arr), function ($k) { + return stripos($k, 'refund') === false; + })); + $order_item = array_intersect_key($response_arr, array_flip($order_keys)); + for ($i=0; $i < $refund_times; $i++) { + $filteredKeys = array_filter(array_keys($response_arr), function ($k) use ($i) { + return substr($k, -2) === '_' . $i; + }); + $refund_item_raw = array_intersect_key($response_arr, array_flip($filteredKeys)); + $suffix = '_' . $i; + $refund_item = array_combine( + array_map(function($key) use ($suffix) { + return substr($key, 0, -strlen($suffix)); + }, array_keys($refund_item_raw)), + $refund_item_raw + ); + $ret['data'][] = array_merge($order_item, $refund_item); + } + return $ret; } /** diff --git a/webht/third_party/pay/models/Online_payment_note_model.php b/webht/third_party/pay/models/Online_payment_note_model.php index 7ab43b39..b5482767 100644 --- a/webht/third_party/pay/models/Online_payment_note_model.php +++ b/webht/third_party/pay/models/Online_payment_note_model.php @@ -113,6 +113,37 @@ class Online_payment_note_model extends CI_Model { $this->orderby = ' ORDER BY OPN_SN DESC '; } + private $code_brandname = array( + "15002" => "PayPal", + "15010" => "PayPal", + "15015" => "Alipay", + "15016" => "WeChat", + "15018" => "Credit Card-iPaylinks", + ); + private $wxpay_app = array( + "wx749246dd935ca07b" => "APP", + "wx5d01021a6d515098" => "HLY", // "花梨鹰小程序", // 交行收款码 + "wxd6c8dd69af5128cd" => "", // "NATIVE", + "wx7e605820faf98a05" => "Trippest-NATIVE", + "0" => "unknown", + ); + public function set_brandname(&$ele) + { + $ele->brand_name = "none"; + if ($this->code_brandname[$ele->OPN_accountMethod]) { + $ele->brand_name = $this->code_brandname[$ele->OPN_accountMethod]; + } + + $raw = json_decode($ele->OPN_rawContent); + $wx_app = isset($raw->app_id) ? $raw->app_id : '0'; + $wx_app = $wx_app!=='0' ? $wx_app : (isset($raw->appid) ? $raw->appid : '0'); + + $ele->app_name = ""; + if ($this->wxpay_app[$wx_app]) { + $ele->app_name = $this->wxpay_app[$wx_app]; + } + } + public function query_note() { $top_sql = $this->topnum ? (" TOP " . $this->topnum) : ""; @@ -128,7 +159,9 @@ class Online_payment_note_model extends CI_Model { // log_message('error', PHP_EOL . $sql); $query = $this->info->query($sql); - return $query->result(); + $result = $query->result(); + array_walk($result, 'Online_payment_note_model::set_brandname'); + return $result; } public function get_note($opn_id) @@ -147,6 +180,7 @@ class Online_payment_note_model extends CI_Model { $search_sql = ""; if ( ! empty($keyword)) { $search_sql.=" AND ( OPN_transactionId = '$keyword' + OR OPN_relatedId like '%$keyword%' OR OPN_orderId like '%$keyword%' OR OPN_rawOrderId like '%$keyword%' )"; } @@ -404,6 +438,61 @@ class Online_payment_note_model extends CI_Model { return $result_object; } + public function add_note_wxpay($result_data, $target_account, $type='pay') + { + $this->load->model('Online_payment_account_model', 'account_model'); + foreach ($result_data as $key => $row) { + $save_column = array(); + $save_column['OPN_accountMethod'] = $this->config->item('method_code', 'wxpay'); + $total_fee = bcdiv($row['total_fee'], $this->config->item('currency_unit', 'wxpay')); + $OPN_currency = isset($row['currency_type']) ? $row['currency_type'] : (isset($row['fee_type']) ? $row['fee_type'] : 'CNY'); + if ($type != 'pay') { + // 退款 + $refund_fee = bcdiv($row['refund_fee'], $this->config->item('currency_unit', 'wxpay')); + $ssje = $this->account_model->get_ssje($refund_fee, str_replace("CNY", "RMB", strtoupper($OPN_currency)), $save_column['OPN_accountMethod']); + $save_column['OPN_transactionId'] = $row['refund_id']; + $save_column['OPN_orderAmount'] = "-" . $refund_fee; + $save_column['OPN_payAmount'] = "-" . $refund_fee; + $save_column['OPN_resultCode'] = $row['refund_status']; + $save_column['OPN_resultMsg'] = $row['refund_status']; + $save_column['OPN_entryAmountCNY'] = floatval("-" . $ssje); + $save_column['OPN_noticeType'] = $type; + $save_column['OPN_relatedId'] = $row['transaction_id']; + $save_column['OPN_acquiringTime'] = date('Y-m-d H:i:s', strtotime($row['refund_success_time'])); + $save_column['OPN_completeTime'] = date('Y-m-d H:i:s', strtotime($row['refund_success_time'])); + } else { + // 收款 + $total_fee = bcdiv($row['total_fee'], $this->config->item('currency_unit', 'wxpay')); + $ssje = $this->account_model->get_ssje($total_fee, str_replace("CNY", "RMB", strtoupper($OPN_currency)), $save_column['OPN_accountMethod']); + $save_column['OPN_transactionId'] = $row['transaction_id']; + $save_column['OPN_orderAmount'] = $total_fee; + $save_column['OPN_payAmount'] = $total_fee; + $save_column['OPN_resultCode'] = $row['trade_state']; + $save_column['OPN_resultMsg'] = $row['trade_state']; + $save_column['OPN_entryAmountCNY'] = floatval($ssje); + $save_column['OPN_noticeType'] = 'pay'; + $save_column['OPN_relatedId'] = ''; + $save_column['OPN_acquiringTime'] = date('Y-m-d H:i:s', strtotime($row['time_end'])); + $save_column['OPN_completeTime'] = date('Y-m-d H:i:s', strtotime($row['time_end'])); + } + $save_column['OPN_noticeSendStatus'] = 'unsend'; + $save_column['OPN_transactionResult'] = 'completed'; + $save_column['OPN_orderId'] = $row['out_trade_no']; + $save_column['OPN_rawOrderId'] = $row['out_trade_no']; + $save_column['OPN_invoiceId'] = $row['out_trade_no']; + $save_column['OPN_subject'] = isset($row['item_name']) ? $row['item_name'] : ''; + $save_column['OPN_currency'] = $OPN_currency; + $save_column['OPN_remark'] = empty($row['attach']) ? '' : json_encode($row['attach']); + $save_column['OPN_payerLogId'] = isset( $row['openid']) ? $row['openid'] : ''; + $save_column['OPN_fundSource'] = $target_account; + $save_column['OPN_rawContent'] = json_encode($row); + $save_column['OPN_noticeTime'] = date('Y-m-d H:i:s'); + + // $this->insert_note($save_column) ; // todo: + // log_message('error', 'test: ' . __CLASS__ . PHP_EOL . var_export($save_column, 1)); + } + return; + } } diff --git a/webht/third_party/pay/models/WxpayQueryContentBuilder.php b/webht/third_party/pay/models/WxpayQueryContentBuilder.php index ffa56617..ba8d03b7 100644 --- a/webht/third_party/pay/models/WxpayQueryContentBuilder.php +++ b/webht/third_party/pay/models/WxpayQueryContentBuilder.php @@ -49,6 +49,12 @@ class WxpayQueryContentBuilder extends CI_Model $this->bizContentarr['tar_type'] = $tar_type; } + public function set_transaction_id($v) + { + $this->transaction_id = $v; + $this->bizContentarr['transaction_id'] = $v; + } + } /* End of file WxpayQueryContentBuilder.php */ diff --git a/webht/third_party/pay/views/payment_list.php b/webht/third_party/pay/views/payment_list.php index 76e6f9b9..05eab178 100644 --- a/webht/third_party/pay/views/payment_list.php +++ b/webht/third_party/pay/views/payment_list.php @@ -165,6 +165,7 @@