config = $config; } /** * 支付接口 * @param array $order * [ * 'title' => '订单标题' * 'order_no' => '交易流水号' * 'amount' => 金额 * 'mall_id' => 商城ID * 'notify_url' => '回调地址', * 'type' => '汇聚支付方式' * 'open_id' => '微信openid' * ] * @return array|mixed * @throws Exception */ public function pay($order) { $mch = MiddleMch::getMch($order['mall_id']); $request = $this->getRequest($order, $mch); $res = (new PayApiLogic($mch))->create_order($request); OrderModel::addLog([ 'mall_id' => $order['mall_id'], 'merchant_no' => $request['alt_mch_no'], 'trade_id' => $order['trade_id'], 'trade_type' => $order['type'], 'sys_order_no' => $res['sys_order_no'], 'trx_no' => $res['trx_no'], 'fee' => $res['alt_fee'], 'status' => $res['status'], ]); return $res; } /** * 获取请求参数 * * @param array $order * @param MiddleMch $mch * @return array */ private function getRequest($order, $mch) { $request = [ 'alt_mch_no' => $this->config['merchant_no'], // 分账方 'order_no' => $order['order_no'], // 商户订单号 'amount' => $order['amount'], // 订单金额 'product_name' => $order['title'], // 商品名称 'product_desc' => $order['title'], // 商品描述 'mp' => '', // 公用回传参数,如果商户请求时传递了该参 数,则返回给商户时会原值传 回 'notify_url' => $order['notify_url'], // 服务器异步通知地址 'frp_code' => $order['type'], // 交易类型 'auth_code' => '', // 付款码数字,被扫支付必填 'buyerId' => '', // 支付宝服务窗 支付必填 'transaction_model' => '', // 微信/支付宝 H5 模式 ]; // 微信环境获取对应的openid if ($order['type'] == HuijuBillTypeEnum::WEIXIN_GZH) { $request['open_id'] = $order['open_id'] ?? ''; $request['app_id'] = Yii::$app->services->setting->mall->get($order['mall_id'], 'wechat.app_id'); } if ($order['type'] == HuijuBillTypeEnum::WEIXIN_XCX) { $request['open_id'] = $order['open_id'] ?? ''; $request['app_id'] = Yii::$app->services->setting->mall->get($order['mall_id'], 'mini_program.app_id'); } return $request; } /** * 查询订单支付状态 * @params string $trade_no * @return array * @throws */ public function query($trade_no) { $request = [ 'p1_MerchantNo' => $this->config['merchant_no'], 'p2_OrderNo' => $trade_no, ]; $secret = $this->config['merchant_secret']; $request['hmac'] = urlencode(RequestUtil::hmacRequest($request, $secret)); $result = RequestUtil::http_post($this->order_query_url, $request); return json_decode($result, true); } /** * 退款 * @param array $info * [ * 'refund_order_no' => $refund_order_no, * 'out_refund_no' => $out_trade_no, * 'refund_amount' => 1, * 'refund_reason' => 1 * ] * * @return bool * @throws */ public function refund($data) { $mch = MiddleMch::getMch($data['mall_id']); // 获取支付流水单号 $out_trade_no = PaymentTradeOrder::getOutTradeNoOfOrderNo($data['order_no']); if (empty($out_trade_no)) { throw new Exception("订单:{$data['order_no']} 支付流水单号不存在"); } $res = (new PayApiLogic($mch))->order_refund([ 'order_no' => $out_trade_no, 'refund_order_no' => $data['refund_order_no'], 'refund_amount' => $data['money'], 'reason' => $data['desc'], 'notify_url' => Url::toApi(['notify/huiju_bill_refund'], true), // 退款结果通知网址 ]); // 添加记录 OrderRefundModel::addLog([ 'mall_id' => $data['mall_id'], 'out_trade_no' => $out_trade_no, 'sys_order_no' => $res['sys_order_no'], 'trx_no' => $res['trx_no'], 'refund_id' => $data['refund_id'], 'refund_amount' => $data['money'], 'refund_order_no' => $data['refund_order_no'], 'status' => $res['status'], ]); return true; } /** * 异步回调 * * @param array $data * @return void */ public function notify($data, $trade) { $mch = MiddleMch::getMch($trade->mall_id); if (empty($mch)) { throw new Exception('mch为空'); } $data = (new PayApiLogic($mch))->order_query($data['sys_order_no']); // 是否支付成功 if (isset($data['status']) && $data['status'] == StatusEnum::STATUS_100) { // 回调成功 删除缓存 Payment::delAlipayHtml($data['order_no']); return true; } return false; } /** * 退款回调处理 * @param $res * @return bool * @throws */ public function refund_notify($data, $refund_order) { $mch = MiddleMch::getMch($refund_order->mall_id); if (empty($mch)) { throw new Exception('mch为空'); } // 查询 $data = (new PayApiLogic($mch))->order_refund_query($data['refund_order_no']); if (isset($data['status']) && $data['status'] == StatusEnum::STATUS_100) { return true; } return false; } }