config = $config; $config['mch_secret_cert'] = url_to_path($config['mch_secret_cert'] ?? ''); $config['mch_public_cert_path'] = url_to_path($config['mch_public_cert_path'] ?? ''); Pay::config($this->payConfig($config, 'wechat')); } /** * 公众号支付 * @param array $params * @return mixed|Collection */ public function mp(array $params) { $result = $this->returnFormat(Pay::wechat()->mp([ 'out_trade_no' => $params['out_trade_no'], 'description' => $params['boby'], 'amount' => [ 'total' => $params['money'], ], 'payer' => [ 'openid' => $params['openid'], ], ])); $code = $result['code'] ?? 0; if ($code == 0) return $result; //支付错误抛出 throw new PayException($result['message']); } /** * 手机网页支付 * @param array $params * @return mixed */ public function wap(array $params) { $order = [ 'out_trade_no' => $params['out_trade_no'], 'description' => $params['boby'], 'amount' => [ 'total' => $params['money'], ], 'scene_info' => [ 'payer_client_ip' => request()->ip(), 'h5_info' => [ 'type' => 'Wap', ] ], ]; //这儿有些特殊, 默认情况下,H5 支付所使用的 appid 是微信公众号的 appid,即配置文件中的 mp_app_id 参数,如果想使用关联的小程序的 appid,则只需要在调用参数中增加 ['_type' => 'mini'] 即可 if (!empty($order['type'])) { $order['_type'] = 'mini'; // 注意这一行 } return $this->returnFormat(Pay::wechat()->wap($order)); } public function web(array $params) { } /** * app支付 * @param array $params * @return mixed|ResponseInterface */ public function app(array $params) { return $this->returnFormat(Pay::wechat()->app([ 'out_trade_no' => $params['out_trade_no'], 'description' => $params['boby'], 'amount' => [ 'total' => $params['money'], ], ])); } /** * 小程序支付 * @param array $params * @return mixed|ResponseInterface */ public function mini(array $params) { return $this->returnFormat(Pay::wechat()->mini([ 'out_trade_no' => $params['out_trade_no'], 'description' => $params['boby'], 'amount' => [ 'total' => $params['money'], 'currency' => 'CNY',//一般是人民币 ], 'payer' => [ 'openid' => $params['openid'], ] ])); } /** * 付款码支付 * @param array $params * @return mixed|Collection */ public function pos(array $params) { //todo 需要自定义通过plugin来侧载开发 $app = Factory::payment([ 'app_id' => $this->config['appid'], //应用id 'mch_id' => $this->config["mch_id"] ?? '', //商户号 'key' => $this->config["pay_v2_signkey"] ?? '', // API 密钥 todo 注意: 是v2密钥 是v2密钥 是v2密钥 'response_type' => 'array', 'log' => [ 'level' => 'debug', 'permission' => 0777, 'file' => 'runtime/log/wechat/easywechat.logs', ], 'sandbox' => false, // 设置为 false 或注释则关闭沙箱模式 ]); $data = [ 'body' => $params['boby'], 'out_trade_no' => $params['out_trade_no'], 'total_fee' => $params['money'], 'auth_code' => $params["auth_code"],//传入的付款码 ]; $result = $app->base->pay($data);//没有注释路由,调用没有问题 return $this->returnFormat($result); } /** * 扫码支付 * @param array $params * @return mixed|Collection */ public function scan(array $params) { return $this->returnFormat(Pay::wechat()->scan([ 'out_trade_no' => $params['out_trade_no'], 'description' => $params['boby'], 'amount' => [ 'total' => $params['money'], ], ])); } /** * 转账(微信的转账是很多笔的) * @param array $params * @return array */ public function transfer(array $params) { //这儿的批次信息可能是这儿生成的,但依然需要记录 $order = [ 'out_batch_no' => time() . '',// 'batch_name' => $params['remark'], 'batch_remark' => $params['remark'], ]; $transfer_list = $params['transfer_list']; //单笔转账 if (empty($transfer_list)) { $transfer_list = array( [ 'transfer_no' => $params['transfer_no'] . '1', 'money' => (int)$params['money'], 'remark' => $params['remark'], 'openid' => $params['to_no'] ] ); } $total_amount = 0; $total_num = 0; foreach ($transfer_list as $v) { $item_transfer = [ 'out_detail_no' => time() . '1', 'transfer_amount' => (int)$v['money'], 'transfer_remark' => $v['remark'], 'openid' => $v['openid'], ]; $total_amount += (int)$v['money']; $total_num++; if (!empty($v['user_name'])) { $item_transfer['user_name'] = $v['user_name'];// 明文传参即可,sdk 会自动加密 } $order['transfer_detail_list'][] = $item_transfer; } $order['total_amount'] = $total_amount; $order['total_num'] = $total_num; $result = $this->returnFormat(Pay::wechat()->transfer($order)); if (!empty($result['code'])) { // if($result['code'] == 'PARAM_ERROR'){ // throw new PayException(); // }else if($result['code'] == 'INVALID_REQUEST'){ // throw new PayException(); // } if ($result['code'] == 'INVALID_REQUEST') { throw new PayException(700010); } throw new PayException($result['message']); } return ['batch_id' => $result['batch_id'], 'out_batch_no' => $result['out_batch_no']]; } /** * 支付关闭 * @param string $out_trade_no * @return void * @throws ContainerException * @throws InvalidParamsException * @throws ServiceNotFoundException */ public function close(string $out_trade_no) { $result = Pay::wechat()->close([ 'out_trade_no' => $out_trade_no, ]); return $this->returnFormat($result); } /** * 退款 * @param array $params * @return array * @throws ContainerException * @throws InvalidParamsException * @throws ServiceNotFoundException */ public function refund(array $params) { $out_trade_no = $params['out_trade_no']; $money = $params['money']; $total = $params['total']; $refund_no = $params['refund_no']; $result = Pay::wechat()->refund([ 'out_trade_no' => $out_trade_no, 'out_refund_no' => $refund_no, 'amount' => [ 'refund' => $money, 'total' => $total, 'currency' => 'CNY', ], ]); $result = $this->returnFormat($result); $refund_status_array = [ 'SUCCESS' => RefundDict::SUCCESS, 'CLOSED' => RefundDict::FAIL, 'PROCESSING' => RefundDict::DEALING, 'ABNORMAL' => RefundDict::FAIL, ]; return [ 'status' => $refund_status_array[$result['status']], 'refund_no' => $refund_no, 'out_trade_no' => $out_trade_no ]; } /** * 异步回调 * @param string $action * @param callable $callback * @return ResponseInterface|Response */ public function notify(string $action, callable $callback) { try { $result = $this->returnFormat(Pay::wechat()->callback()); if ($action == 'pay') {//支付 if ($result['event_type'] == 'TRANSACTION.SUCCESS') { $pay_trade_data = $result['resource']['ciphertext']; $temp_params = [ 'trade_no' => $pay_trade_data['transaction_id'], 'mch_id' => $pay_trade_data['mchid'], 'status' => OnlinePayDict::getWechatPayStatus($pay_trade_data['trade_state']) ]; $callback_result = $callback($pay_trade_data['out_trade_no'], $temp_params); if (is_bool($callback_result) && $callback_result) { return Pay::wechat()->success(); } } } else if ($action == 'refund') {//退款 if ($result['event_type'] == 'REFUND.SUCCESS') { $refund_trade_data = $result['resource']['ciphertext']; $refund_status_array = [ 'SUCCESS' => RefundDict::SUCCESS, 'CLOSED' => RefundDict::FAIL, 'PROCESSING' => RefundDict::DEALING, 'ABNORMAL' => RefundDict::FAIL, ]; $temp_params = [ 'trade_no' => $refund_trade_data['transaction_id'], 'mch_id' => $refund_trade_data['mchid'], 'refund_no' => $refund_trade_data['out_refund_no'], 'status' => $refund_status_array[$refund_trade_data['refund_status']], ]; $callback_result = $callback($refund_trade_data['out_trade_no'], $temp_params); if (is_bool($callback_result) && $callback_result) { return Pay::wechat()->success(); } } } return $this->fail(); } catch ( Throwable $e ) { // throw new PayException($e->getMessage()); return $this->fail($e->getMessage()); } } /** * 查询普通支付订单 * @param array $params * @return array|MessageInterface|Collection|null * @throws ContainerException * @throws InvalidParamsException * @throws ServiceNotFoundException */ public function getOrder(array $params = []) { $out_trade_no = $params['out_trade_no']; $transaction_id = $params['transaction_id'] ?? ''; $order = [ ]; if (!empty($out_trade_no)) { $order['out_trade_no'] = $out_trade_no; } if (!empty($transaction_id)) { $order['transaction_id'] = $transaction_id; } $result = Pay::wechat()->find($order); if (empty($result)) return $result; $result = $this->returnFormat($result); return [ 'status' => OnlinePayDict::getWechatPayStatus($result['trade_state']), ]; } /** * 查询退款单据 * @param string|null $out_trade_no * @param string|null $refund_no * @return array|Collection|MessageInterface|null * @throws ContainerException * @throws InvalidParamsException * @throws ServiceNotFoundException */ public function getRefund(?string $out_trade_no, ?string $refund_no = '') { $order = [ '_type' => 'refund', 'out_refund_no' => $refund_no ]; $result = Pay::wechat()->find($order); if (empty($result)) return $result; $result = $this->returnFormat($result); $refund_status_array = [ 'SUCCESS' => RefundDict::SUCCESS, 'CLOSED' => RefundDict::FAIL, 'PROCESSING' => RefundDict::DEALING, 'ABNORMAL' => RefundDict::FAIL, ]; return [ 'status' => $refund_status_array[$result['status']], 'refund_no' => $refund_no, 'out_trade_no' => $out_trade_no ]; } /** * 获取转账订单(todo 切勿调用) * @param string $transfer_no * @return array * @throws ContainerException * @throws InvalidParamsException */ public function getTransfer(string $transfer_no) { $params = [ 'out_batch_no' => $transfer_no, ]; $allPlugins = Pay::wechat()->mergeCommonPlugins([QueryOutBatchNoPlugin::class]); $result = Pay::wechat()->pay($allPlugins, $params); $result = $this->returnFormat($result); //微信转账状态 $transfer_status_array = [ 'INIT' => TransferDict::DEALING,//初始态。 系统转账校验中 'WAIT_PAY' => TransferDict::DEALING, 'PROCESSING' => TransferDict::DEALING, 'FAIL' => TransferDict::FAIL, 'SUCCESS' => TransferDict::SUCCESS, ]; return [ 'status' => $transfer_status_array[$result['status']], 'transfer_no' => $transfer_no ]; } public function fail($message = '') { $response = [ 'code' => 'FAIL', 'message' => $message ?: '失败', ]; return response($response, 400, [], 'json'); } }