admin/addon/wechatpay/model/V2.php

234 lines
8.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
namespace addon\wechatpay\model;
use app\model\BaseModel;
use app\model\system\Pay as PayCommon;
use app\model\upload\Upload;
use EasyWeChat\Factory;
/**
* 微信支付v3支付
* 版本 1.0.4
*/
class V2 extends BaseModel
{
/**
* 微信支付配置
*/
private $config;
/**
* 支付实例
* @var
*/
private $app;
public function __construct($config)
{
$this->config = $config;
$this->app = Factory::payment([
'app_id' => $config['appid'], //应用id
'mch_id' => $config["mch_id"] ?? '', //商户号
'key' => $config["pay_signkey"] ?? '', // API 密钥
// 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
'cert_path' => realpath($config["apiclient_cert"]) ?? '', // apiclient_cert.pem XXX: 绝对路径!!!!
'key_path' => realpath($config["apiclient_key"]) ?? '', // apiclient_key.pem XXX: 绝对路径!!!!
'notify_url' => '',// 你也可以在下单时单独设置来想覆盖它
'response_type' => 'array',
'log' => [
'level' => 'debug',
'permission' => 0777,
'file' => 'runtime/log/wechat/easywechat.logs',
],
'sandbox' => false, // 设置为 false 或注释则关闭沙箱模式
]);
}
/**
* 支付
* @param array $param
* @return array\
*/
public function pay(array $param){
$data = [
'body' => str_sub($param["pay_body"], 15),
'out_trade_no' => $param["out_trade_no"],
'total_fee' => $param["pay_money"] * 100,
'notify_url' => $param["notify_url"],
'trade_type' => $param["trade_type"] == 'APPLET' ? 'JSAPI' : $param["trade_type"]
];
if ($param['trade_type'] == 'JSAPI' || $param['trade_type'] == 'APPLET') $data['openid'] = $param['openid'];
$result = $this->app->order->unify($data);
if ($result["return_code"] == 'FAIL') return $this->error([], $result["return_msg"]);
if ($result["result_code"] == 'FAIL') return $this->error([], $result["err_code_des"]);
$return = [];
switch ($param["trade_type"]) {
case 'JSAPI' ://微信支付 或小程序支付
$return = [
"type" => "jsapi",
"data" => $this->app->jssdk->sdkConfig($result['prepay_id'], false)
];
break;
case 'APPLET' ://微信支付 或小程序支付
$return = [
"type" => "jsapi",
"data" => $this->app->jssdk->bridgeConfig($result['prepay_id'], false)
];
break;
case 'NATIVE' :
$upload_model = new Upload($param['site_id']);
$qrcode_result = $upload_model->qrcode($result['code_url']);
$return = [
"type" => "qrcode",
"qrcode" => $qrcode_result['data'] ?? ''
];
break;
case 'MWEB' ://H5支付
$return = [
"type" => "url",
"url" => $result['mweb_url']
];
break;
case 'APP' :
$config = $this->app->jssdk->appConfig($result['prepay_id']);
$return = [
"type" => "app",
"data" => $config
];
break;
}
return $this->success($return);
}
/**
* 异步回调
*/
public function payNotify()
{
$response = $this->app->handlePaidNotify(function ($message, $fail) {
$pay_common = new PayCommon();
if ($message['return_code'] === 'SUCCESS') {
// return_code 表示通信状态,不代表支付状态
if ($message['result_code'] === 'SUCCESS') {
// 判断支付金额是否等于支付单据的金额
$pay_info = $pay_common->getPayInfo($message['out_trade_no'])['data'];
if (empty($pay_info)) return $fail('通信失败,请稍后再通知我');
if ($message['total_fee'] != round($pay_info['pay_money'] * 100)) return;
// 用户是否支付成功
$pay_common->onlinePay($message['out_trade_no'], "wechatpay", $message["transaction_id"], "wechatpay");
}
} else {
return $fail('通信失败,请稍后再通知我');
}
return true;
});
$response->send();
return $response;
}
/**
* 关闭支付单据
* @param array $param
* @return array
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \GuzzleHttp\Exception\GuzzleException */
public function payClose(array $param)
{
$result = $this->app->order->close($param["out_trade_no"]);
if ($result["return_code"] == 'FAIL') {
return $this->error([], $result["return_msg"]);
}
if ($result["result_code"] == 'FAIL') {
if ($result['err_code'] == 'ORDERPAID') return $this->error(['is_paid' => 1, 'pay_type' => 'wechatpay'], $result['err_code_des']);
return $this->error([], $result['err_code_des']);
}
return $this->success();
}
/**
* 申请退款
* @param array $param
*/
public function refund(array $param)
{
$pay_info = $param["pay_info"];
$refund_no = $param["refund_no"];
$total_fee = round($pay_info["pay_money"] * 100);
$refund_fee = round($param["refund_fee"] * 100);
$result = $this->app->refund->byOutTradeNumber($pay_info["out_trade_no"], $refund_no, $total_fee, $refund_fee, []);
//调用失败
if ($result["return_code"] == 'FAIL') return $this->error([], $result["return_msg"]);
if ($result["result_code"] == 'FAIL') return $this->error([], $result["err_code_des"]);
return $this->success();
}
/**
* 转账
* @param array $param
* @return array\
*/
public function transfer(array $param)
{
$data = [
'partner_trade_no' => $param['out_trade_no'], // 商户订单号,需保持唯一性(只能是字母或者数字,不能包含有符号)
'openid' => $param['account_number'],
'check_name' => 'FORCE_CHECK', // NO_CHECK不校验真实姓名, FORCE_CHECK强校验真实姓名
're_user_name' => $param['real_name'], // 如果 check_name 设置为FORCE_CHECK则必填用户真实姓名
'amount' => $param['amount'] * 100, // 转账金额
'desc' => $param['desc']
];
$res = $this->app->transfer->toBalance($data);
if ($res['return_code'] == 'SUCCESS') {
if ($res['result_code'] == 'SUCCESS') {
return $this->success([
'out_trade_no' => $res['partner_trade_no'], // 商户交易号
'payment_no' => $res['payment_no'], // 微信付款单号
'payment_time' => $res['payment_time'] // 付款成功时间
]);
} else {
return $this->error([], $res['err_code_des']);
}
} else {
return $this->error([], $res['return_msg']);
}
}
/**
* 付款码支付
* @param array $param
* @return array\
*/
public function micropay(array $param){
$data = [
'body' => str_sub($param["pay_body"], 15),
'out_trade_no' => $param["out_trade_no"],
'total_fee' => $param["pay_money"] * 100,
'auth_code' => $param["auth_code"]
];
$result = $this->app->base->pay($data);
if ($result[ 'return_code' ] == 'FAIL') {
return $this->error([], $result[ 'return_msg' ]);
}
if ($result[ 'result_code' ] == 'FAIL') {
return $this->error([], $result[ 'err_code_des' ]);
}
return $this->success($result);
}
}