From a74d363bf8746e667cbc0ae1eaf739f8c0031235 Mon Sep 17 00:00:00 2001 From: Lei OT Date: Tue, 16 Sep 2025 15:15:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E4=BB=98=E5=AE=9D=E9=80=80?= =?UTF-8?q?=E6=AC=BEAPI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pay/controllers/AlipayTradeService.php | 160 +++++++++++++++++- .../pay/helpers/payment_helper.php | 39 +++++ 2 files changed, 194 insertions(+), 5 deletions(-) diff --git a/webht/third_party/pay/controllers/AlipayTradeService.php b/webht/third_party/pay/controllers/AlipayTradeService.php index 0af5cadf..b84d9fba 100644 --- a/webht/third_party/pay/controllers/AlipayTradeService.php +++ b/webht/third_party/pay/controllers/AlipayTradeService.php @@ -49,6 +49,7 @@ class AlipayTradeService extends CI_Controller $this->load->model('AlipayTradePagePayContentBuilder'); $this->load->model('AlipayTradeWapPayContentBuilder'); $this->load->model('AlipayTradeQueryContentBuilder'); + $this->load->model('AlipayTradeRefundContentBuilder'); $this->load->model('Alipay_note_model'); $this->load->model('Alipay_model'); $this->load->model('Group_model'); @@ -105,7 +106,7 @@ class AlipayTradeService extends CI_Controller "2021004129643221" => "trippest", "2017092108849921" => "cht", // "CHT", ); - return $app_id ? $code_fundsource[$app_id] : 'cht'; + return $app_id && isset($code_fundsource[$app_id]) ? $code_fundsource[$app_id] : 'cht'; } public function index() @@ -618,6 +619,9 @@ class AlipayTradeService extends CI_Controller */ public function send_refund($item, $old_ssje=null, $handpick) { + if (empty($item->ALI_resultMsg)) { + return; + } // raw $raw = json_decode($item->ALI_memo); $parent_order = $raw->out_trade_no; @@ -861,15 +865,15 @@ class AlipayTradeService extends CI_Controller /*! * 查询退款 * @date 2019-04-24 - * @param [type] $dealId 必须, 退款请求号.out_biz_no, 或原始交易订单号 + * @param [type] $request_no 必须, 退款请求号.out_biz_no, 或原始交易订单号 * @param [type] $trade_no 必须, 原收款交易号, 和order_id不能同时为空 * @param [type] $order_id 必须, 原收款订单号, 和trade_no不能同时为空 * * @ignore 只能查询API发起的退款, 后台的退款查不到 */ - public function query_refund($dealId=NULL,$trade_no=NULL, $order_id=NULL) + public function query_refund($request_no=NULL,$trade_no=NULL, $order_id=NULL) { - $this->AlipayTradeQueryContentBuilder->setOutRequestNo($dealId); + $this->AlipayTradeQueryContentBuilder->setOutRequestNo($request_no); $this->AlipayTradeQueryContentBuilder->setTradeNo($trade_no); $this->AlipayTradeQueryContentBuilder->setOutTradeNo($order_id); @@ -878,7 +882,7 @@ class AlipayTradeService extends CI_Controller $request->setBizContent ( $biz_content ); $response = $this->aopclientRequestExecute ($request); - // $response = $response->alipay_trade_fastpay_refund_query_response; + $response = $response->alipay_trade_fastpay_refund_query_response; return $response; // return $this->output->set_content_type('application/json')->set_output(json_encode($response)); } @@ -1378,6 +1382,152 @@ class AlipayTradeService extends CI_Controller ); } + /** + * 退款API ***************************************************************************************************** + * ************************************************************************************************************ + */ + function call_refund($builder){ + $biz_content=$builder->getBizContent(); + + $request = new AlipayTradeRefundRequest(); + $request->setBizContent ( $biz_content ); + + $response = $this->aopclientRequestExecute ($request); + // var_dump($response); + $response = $response->alipay_trade_refund_response; + + // log_message('error','test:rrr2 ' . __CLASS__ . PHP_EOL . var_export($response, 1)); + return $response; + } + + public function Refund() + { + $this->set_merchant('cht'); + $refund_payload = $this->input->post(); + $res = array( + "errcode" => "0", + "errmsg" => "", + "result" => new stdClass(), + ); + + $refundRequestId = $refund_payload['refund_id']; + $dealId = $refund_payload['res_id']; + $orderId = ''; + // $originRow = $this->Alipay_note_model->note($dealId); + $originRows = []; + if (!empty($dealId)) { + $originRows = $this->online_note->get_note_where(['OPN_transactionId' => ['=', $dealId]]); + } + if (empty($originRows)) { + $orderId = $refund_payload['order_id']; + $orderId = trim($orderId); + $originRows = $this->online_note->get_note_where([ + 'OPN_rawOrderId' => ['=', $orderId], + 'OPN_noticeType' => ['=', 'pay'], + 'OPN_accountMethod' => ['=', 15015], + ]); + } + if (empty($originRows)) { + $res['errcode'] = '1'; + $res['errmsg'] = '没有找到该笔交易'; + return $this->output->set_content_type('application/json')->set_output(json_encode($res)); // test + } + $originRow = $originRows[0]; + $dealId = $originRow->OPN_transactionId; + $dealAccount = $originRow->OPN_fundSource; + $paymentOrder = $originRow->OPN_rawOrderId; + $this->set_merchant($dealAccount ? $dealAccount : 'cht'); + // * refund_amount 退款金额 + $this->AlipayTradeRefundContentBuilder->setRefundAmount($refund_payload['amount']); + // * out_trade_no trade_no 二选一 传入. 优先取值trade_no + // - out_trade_no 订单支付时传入的商户订单号 + // - trade_no 支付宝交易号 + $this->AlipayTradeRefundContentBuilder->setTradeNo($dealId); + if ($paymentOrder) { + $this->AlipayTradeRefundContentBuilder->setOutTradeNo($paymentOrder); + } + // refund_reason len 256 + $this->AlipayTradeRefundContentBuilder->setRefundReason($refund_payload['reason']); + // * out_request_no 退款请求号。 标识一次退款请求 + $generateId = $refundRequestId ? $refundRequestId : str_replace('-', '', getGuid()); + $this->AlipayTradeRefundContentBuilder->setOutRequestNo($generateId); + // [-] query_options 同步需要额外返回的信息字段 ["refund_detail_item_list"] + + // var_dump($this->AlipayTradeRefundContentBuilder); + $response = $this->call_refund($this->AlipayTradeRefundContentBuilder); + $refund_res = $response; + $refund_res->id = $generateId; + $refund_res->custom_id = $refund_payload['custom_id']; + // $ret_status_mapped = array( + // "Y" => "1", // COMPLETED + // "N" => "3", // FAILED + // // "PENDING" => "2", // todo: + // // "CANCELLED" => "-1", // todo: + // ); + // $refund_res->status = $response->code === '10000' ? '1' : '3'; + $refund_res->status = $response->code === '10000' && $response->fund_change === 'Y' ? '1' : $response->code === '10000' ? '2' : '3'; + $refund_res->refund_payload = $refund_payload; + // log_message('error','test: ' . __METHOD__ . ': ' . __LINE__ . ' ' . PHP_EOL . var_export($response, 1)); + // var_dump($response); + $res['errcode'] = $response->code === '10000' ? '0' : '1'; + + // query result + // var_dump($generateId, $dealId, $paymentOrder); + $query_res = $this->query_refund($generateId, $dealId, $paymentOrder); + $refund_res->query_refund_result = $query_res; + $refund_res->status2 = isset($query_res->refund_status) && $query_res->refund_status === 'REFUND_SUCCESS' ? '1' : '3'; + + $res['result'] = $refund_res; + + // if ($refund_res->status !== '3') { + if ($refund_res->status2 === '1') { + // $ALI_dealId,$ALI_orderId,$ALI_currencyCode,$ALI_orderAmount,$ALI_payAmount,$ALI_stateCode,$ALI_acquiringTime,$ALI_completeTime,$ALI_memo,$ALI_payType,$ALI_resultCode=null,$ALI_resultMsg=null,$ALI_payerName=null,$ALI_payerEmail=NULL, $check_exists=false + $this->Alipay_note_model->save_alipay( + strval($generateId) + ,strval($paymentOrder) + ,"CNY" + ,"-" . strval($query_res->refund_amount) + ,NULL + ,NULL + ,date('Y-m-d H:i:s') + ,date('Y-m-d H:i:s') + ,json_encode($query_res,JSON_UNESCAPED_UNICODE) + ,'refund' + ,NULL + ,$refund_res->status2 === '1' ? 'TRADE_SUCCESS' : '' + ,NULL + ,NULL + ); + } + + return $this->output->set_content_type('application/json')->set_output(json_encode($res)); + } + + public function query_refund_result() + { + // $res = array( + // "errcode" => "0", + // "errmsg" => "", + // "result" => new stdClass(), + // ); + + $request_no = $this->input->get_post('request_no'); + $trade_no = $this->input->get_post('trade_no'); + $order_id = $this->input->get_post('order_id'); + $query_res = $this->query_refund($request_no, $trade_no, $order_id); + $status2 = isset($query_res->refund_status) && $query_res->refund_status === 'REFUND_SUCCESS' ? '1' : '3'; + + $originRow = $this->Alipay_note_model->note($request_no); + // $originRows = $this->online_note->get_note_where(['OPN_transactionId' => ['=', $dealId]]); + + // $res['errcode'] = $query_res->code === '10000' ? '0' : '1'; + // $res['result'] = $query_res; + // return $this->output->set_content_type('application/json')->set_output(json_encode($res)); + } + + public function query_refund_queue() + { + } } diff --git a/webht/third_party/pay/helpers/payment_helper.php b/webht/third_party/pay/helpers/payment_helper.php index fdc17b5b..827cbda7 100644 --- a/webht/third_party/pay/helpers/payment_helper.php +++ b/webht/third_party/pay/helpers/payment_helper.php @@ -556,3 +556,42 @@ function refund_status_send($code) { /** * End 连连支付 */ + + + +/** + * Returns a string representation of a version 4 GUID, which uses random + * numbers.There are 6 reserved bits, and the GUIDs have this format: + * xxxxxxxx-xxxx-4xxx-[8|9|a|b]xxx-xxxxxxxxxxxx + * where 'x' is a hexadecimal digit, 0-9a-f. + * + * See http://tools.ietf.org/html/rfc4122 for more information. + * + * Note: This function is available on all platforms, while the + * com_create_guid() is only available for Windows. + * + * @return string A new GUID. + */ +function getGuid() +{ + // @codingStandardsIgnoreStart + + return sprintf( + '%04x%04x-%04x-%04x-%02x%02x-%04x%04x%04x', + mt_rand(0, 65535), + mt_rand(0, 65535), // 32 bits for "time_low" + mt_rand(0, 65535), // 16 bits for "time_mid" + mt_rand(0, 4096) + 16384, // 16 bits for "time_hi_and_version", with + // the most significant 4 bits being 0100 + // to indicate randomly generated version + mt_rand(0, 64) + 128, // 8 bits for "clock_seq_hi", with + // the most significant 2 bits being 10, + // required by version 4 GUIDs. + mt_rand(0, 256), // 8 bits for "clock_seq_low" + mt_rand(0, 65535), // 16 bits for "node 0" and "node 1" + mt_rand(0, 65535), // 16 bits for "node 2" and "node 3" + mt_rand(0, 65535) // 16 bits for "node 4" and "node 5" + ); + + // @codingStandardsIgnoreEnd +}