'', 'timestamp' => '', 'version' => '', 'charset' => '', 'method' => '', 'sign_type' => '', ]; const SIGN_TYPE = "RSA2"; // 签名规则 const VERSION = "1.0.1"; const CHARSET = "UTF-8"; // 字符集 const REQ_URL = "https://api.tengtren.com/"; // 支付请求地址 const SUCCESS = "SUCCESS"; const FAIL = "fail"; private $rsa_helper; public function __construct(){ $this->config = config('xty_pay'); // dump($this->config['private_file'], $this->config['public_file']); $this->rsa_helper = new RSAUtil($this->config['private_file'], $this->config['public_file']); } /** * 初始化公共参数 * @param string $type 请求类型 * * @return array */ public function initCommonData($type){ if(!$type){ return []; } switch ($type){ case 'pay_h5': $method = 'trade.h5.pay'; break; case 'order_query': $method = 'trade.order.query'; break; case 'refund': $method = 'trade.order.refund'; break; case 'refund_query': $method = 'trade.refund.query'; break; } $this->commonData = [ 'app_id' => $this->config['app_id'], 'timestamp' => ParameterUtil::getCurrentDateStr(), 'version' => self::VERSION, 'charset' => self::CHARSET, 'method' => $method, 'sign_type' => self::SIGN_TYPE, ]; return $this->commonData; } // 发起H5支付 public function payH5($pay_channel, $return_type, $data){ try { $requestData = $this->initCommonData('pay_h5'); $requestData['req_data'] = [ "out_trade_no" => $data['out_trade_no'], "pay_channel" => $pay_channel, // 支付渠道: WX=微信, ALI=支付宝, UNI=银联 "order_name" => $data['order_name'], "total_amount" => $data['total_amount'], // 金额(分) "order_desc" => $data['order_desc'], "notify_url" => $data['notify_url'], // 回调地址 "return_type" => $return_type, // 返回类型: 1=返回跳转支付收银台 URL, 2=返回支付链接, 3=返回官方标准支付 URL, 4=返回支付宝 qrCode "return_url" => $data['return_url'], // 前端跳转地址 // "limit_pay" => "1", "payer_client_ip" => $data['ip'], // "h5_info" => "{\"type\":\"Android\",\"app_name\": \"XXXXXX\",\"package_name\": \"com.tencent.tmgp.sgame\"}", // 微信H5场景信息 "reserved" => $data['reserved']??"", // 附加数据 ]; $sign = $this->rsa_helper->createRSA2Sign(json_encode($requestData)); // 请求的为JSON类型的数据 $result = HttpRequestUtil::sendPost(self::REQ_URL, json_encode($requestData), $sign); // $result["responseData"] = {"resp_code":"SUCCESS","resp_data":"{\"order_no\":\"1010371122024090311352084041\",\"biz_code\":\"SUCCESS\",\"pay_data\":\"https://api.tengtren.com/wxH5Pay?orderNo=1010371122024090311352084041&payUrl=weixin%3A%2F%2Fdl%2Fbusiness%2F%3Ft%3DpYe3V25CZ3m&payScene=H5&appId=A17222309452323464&version=1.0.1\"}","resp_msg":"成功","timestamp":"20240903113520"} $resp_data_json = json_decode($result["responseData"], TRUE); if ("SUCCESS" == $resp_data_json["resp_code"]) { if ($this->rsa_helper->verifyRSA2Sign($result["responseData"], $result["signature"])) { $newRespData = json_decode($resp_data_json['resp_data'], true); if (!empty($newRespData['pay_data'])) { return ['code' => 200, 'msg' => "success", 'data' => $newRespData['pay_data']]; } } } return ['code' => -100, 'msg' => "请求失败: " . $resp_data_json['resp_data'], 'data' => []]; } catch (\Exception $e) { return ['code' => -110, 'msg' => "请求异常:".$e->getMessage(), 'data' => []]; } } /** * 订单查询 * * @param $order_no string 交易流水号 * @param $out_trade_no string 商户订单号 * * @return array */ public function orderQuery($out_trade_no, $order_no = '') { try { $request_data = $this->initCommonData('order_query'); $request_data['req_data'] = [ "out_trade_no" => $out_trade_no, ]; if(!empty($order_no)){ $request_data['req_data']['order_no'] = $order_no; } $sign = $this->rsa_helper->createRSA2Sign(json_encode($request_data)); // 请求的为JSON类型的数据 $result = HttpRequestUtil::sendPost(self::REQ_URL, json_encode($request_data), $sign); $resp_data_json = json_decode($result["responseData"], TRUE); if ("SUCCESS" != $resp_data_json["resp_code"]) { return ['code' => -100, 'msg' => "订单查询失败:" . $resp_data_json['resp_data'], 'data' => []]; } if ($this->rsa_helper->verifyRSA2Sign($result["responseData"], $result["signature"]) != true) { return ['code' => -101, 'msg' => "订单-签名解析失败: msg=" . $resp_data_json['resp_msg'], 'data' => []]; } $resp_data = json_decode($resp_data_json["resp_data"], TRUE); if($resp_data['biz_code'] != "SUCCESS"){ return ['code' => -103, 'msg' => "订单业务失败状态!", 'data' => []]; } if($resp_data['trade_status'] != "SUCCESS"){ return ['code' => -104, 'msg' => "订单已关闭或未支付!", 'data' => []]; } return ['code' => 200, 'msg' => "success", 'data' => $resp_data]; } catch (\Exception $e) { return ['code' => -110, 'msg' => "订单查询异常:".$e->getMessage(), 'data' => []]; } } // 回调通知 public function notify($bodyData) { // 回调验证走查询订单接口验证即可。 } /** * 退款 * * @param $out_trade_no * @param $out_refund_no * @param $refund_amount * @param $refund_reason * * @return array */ public function refund($out_trade_no, $out_refund_no, $refund_amount, $refund_reason) { try { $queryResult = $this->orderQuery($out_trade_no); // dump($queryResult); if ($queryResult['code'] != 200) { return ['code' => -100, 'msg' => $queryResult['msg'], 'data' => []]; } $request_data = $this->initCommonData('refund'); $request_data['req_data'] = [ "out_trade_no" => $out_trade_no, // 商户订单号 // "order_no" => $order_no, // 交易流水号 "out_refund_no" => $out_refund_no, // 商户退款单号 "refund_amount" => formatYuanToFen($refund_amount), // 退款金额(分) "refund_reason" => $refund_reason, // 退款原因 ]; // dump('$request_data: ', $request_data); $sign = $this->rsa_helper->createRSA2Sign(json_encode($request_data)); // 请求的为JSON类型的数据 $result = HttpRequestUtil::sendPost(self::REQ_URL, json_encode($request_data), $sign); $respDataJson = json_decode($result["responseData"], TRUE); // dump($respDataJson); $respData = ""; if(!empty($respDataJson)){ $respData = json_decode($respDataJson['resp_data'], TRUE); } // dump($respDataJson, $respData, 'xxxxasd'); /** * 退款成功返回样例: * * array(4) { * ["resp_code"]=>string(7) "SUCCESS" * ["resp_data"]=>string(313) "{"order_no":"1010317712026012015442715994","refund_ch_order_no":"300220260121000000015829065830","biz_code":"SUCCESS","out_trade_no":"WL17688950675041100742","refund_status":"PROCESSING","out_refund_no":"REF17689609400390212861","total_amount":1,"refund_amount":1,"refund_order_no":"1010417742026012110022036442"}" * ["resp_msg"]=>string(6) "成功" * ["timestamp"]=>string(14) "20260121100220" * } * * 退款请求失败样例: * array(4) { * ["resp_code"]=>string(7) "SUCCESS" * ["resp_data"]=> * string(130) "{"biz_code":"FAIL","error_msg":"请求参数错误:out_trade_no和order_no参数至少一个必填","error_code":"PARAMS_INVALID"}" * string(145) "{"biz_code":"FAIL","error_msg":"业务规则检查异常:退款金额不能大于可退金额","refund_status":"FAIL","error_code":"BIZ_INVALID"}" * string(149) "{"biz_code":"FAIL","error_msg":"频率限制:同一笔订单多次退款受限,请稍后再试","refund_status":"FAIL","error_code":"RATE_LIMITED"}" * ["resp_msg"]=>string(6) "成功" * ["timestamp"]=>string(14) "20260121100420" * } * */ if (!empty($respData) && !empty($respDataJson) && !empty($respData["biz_code"]) && $respData["biz_code"] == "SUCCESS" && ($respData["refund_status"] == "SUCCESS" || $respData["refund_status"] == "PROCESSING")) { return ['code' => 200, 'msg' => "success", 'data' => []]; } $errorMsg = $respDataJson['resp_msg']; if(!empty($respData['error_msg'])){ $errorMsg = $respData['error_msg']; } return ['code' => -100, 'msg' => "退款失败:" . $errorMsg, 'data' => []]; } catch (\Exception $e) { return ['code' => -110, 'msg' => $e->getMessage(), 'data' => []]; } } // 退款查询 public function refund_query($out_refund_no, $refund_order_no){ try { $request_data = $this->initCommonData('refund_query'); $request_data['req_data'] = [ "out_refund_no" => $out_refund_no, // 商户退款单号 "refund_order_no" => $refund_order_no, // 退款交易流水号 ]; // dump($request_data); $sign = $this->rsa_helper->createRSA2Sign(json_encode($request_data)); // 请求的为JSON类型的数据 $result = HttpRequestUtil::sendPost(self::REQ_URL, json_encode($request_data), $sign); // dump($result); $respDataJson = json_decode($result["responseData"], TRUE); $respData = ""; if(!empty($respDataJson)){ $respData = json_decode($respDataJson['resp_data'], TRUE); } // dump($respDataJson, $respData, 'xxxxasd'); /** * 退款成功返回样例: * * array(4) { * ["resp_code"]=>string(7) "SUCCESS" * ["resp_data"]=>string(313) "{"order_no":"1010317712026012015442715994","refund_ch_order_no":"300220260121000000015829065830","biz_code":"SUCCESS","out_trade_no":"WL17688950675041100742","refund_status":"PROCESSING","out_refund_no":"REF17689609400390212861","total_amount":1,"refund_amount":1,"refund_order_no":"1010417742026012110022036442"}" * ["resp_msg"]=>string(6) "成功" * ["timestamp"]=>string(14) "20260121100220" * } * * 退款请求失败样例: * array(4) { * ["resp_code"]=>string(7) "SUCCESS" * ["resp_data"]=> * string(130) "{"biz_code":"FAIL","error_msg":"请求参数错误:out_trade_no和order_no参数至少一个必填","error_code":"PARAMS_INVALID"}" * string(145) "{"biz_code":"FAIL","error_msg":"业务规则检查异常:退款金额不能大于可退金额","refund_status":"FAIL","error_code":"BIZ_INVALID"}" * string(149) "{"biz_code":"FAIL","error_msg":"频率限制:同一笔订单多次退款受限,请稍后再试","refund_status":"FAIL","error_code":"RATE_LIMITED"}" * ["resp_msg"]=>string(6) "成功" * ["timestamp"]=>string(14) "20260121100420" * } * */ if (!empty($respData) && !empty($respDataJson) && !empty($respData["biz_code"]) && $respData["biz_code"] == "SUCCESS" && ($respData["refund_status"] == "SUCCESS" || $respData["refund_status"] == "PROCESSING")) { return ['code' => 200, 'msg' => "success", 'data' => []]; } $errorMsg = $respDataJson['resp_msg']; if(!empty($respData['error_msg'])){ $errorMsg = $respData['error_msg']; } return ['code' => -100, 'msg' => "退款失败:" . $errorMsg, 'data' => []]; } catch (\Exception $e) { return ['code' => -110, 'msg' => $e->getMessage(), 'data' => []]; } } }