You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
306 lines
12 KiB
306 lines
12 KiB
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | Niucloud-admin 企业快速开发的多应用管理平台
|
|
// +----------------------------------------------------------------------
|
|
// | 官方网址:https://www.niucloud.com
|
|
// +----------------------------------------------------------------------
|
|
// | niucloud团队 版权所有 开源版本可自由商用
|
|
// +----------------------------------------------------------------------
|
|
// | Author: Niucloud Team
|
|
// +----------------------------------------------------------------------
|
|
|
|
namespace addon\hygl\app\api\controller;
|
|
|
|
use addon\hygl\app\model\config\Config;
|
|
use addon\hygl\app\model\transaction_history\TransactionHistory;
|
|
use addon\hygl\app\model\user\User;
|
|
use addon\hygl\app\model\user_coupons\UserCoupons;
|
|
use app\model\site\Site;
|
|
use core\base\BaseApiController;
|
|
use think\facade\Log;
|
|
use Yansongda\Pay\Pay;
|
|
|
|
/**
|
|
* 微信相关控制器
|
|
* Class WeChatController
|
|
* @package addon\hygl\app\api\controller
|
|
*/
|
|
class WeChatController extends BaseApiController
|
|
{
|
|
/**
|
|
* 获取openid
|
|
*/
|
|
public function getOpenid(){
|
|
$code = $this->request->param('code','');//
|
|
$site_id = $this->request->param('site_id','');
|
|
|
|
|
|
$wx_config = Config::where('site_id',$site_id)->field('we_chat_pay_app_id,we_chat_pay_gzh_secret')->find();
|
|
|
|
$appid = $wx_config['we_chat_pay_app_id'];
|
|
$secret = $wx_config['we_chat_pay_gzh_secret'];
|
|
|
|
$tokeninfo = $this->http_curl("https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secret}&code={$code}&grant_type=authorization_code");//获取access_token
|
|
$tokeninfo = json_decode($tokeninfo, true);
|
|
|
|
|
|
if (empty($tokeninfo['openid'])){
|
|
return fail('链接失效,请重新扫码');
|
|
}
|
|
|
|
$res = [
|
|
'openid'=>$tokeninfo['openid'],//微信openid
|
|
];
|
|
return success($res);
|
|
}
|
|
|
|
//curl请求
|
|
public function http_curl($url){
|
|
$curl = curl_init();
|
|
//设置抓取的url
|
|
curl_setopt($curl, CURLOPT_URL, $url);
|
|
//设置头文件的信息作为数据流输出
|
|
curl_setopt($curl, CURLOPT_HEADER, 0);
|
|
//设置获取的信息以文件流的形式返回,而不是直接输出。
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
|
//执行命令
|
|
$data = curl_exec($curl);
|
|
//关闭URL请求
|
|
curl_close($curl);
|
|
//显示获得的数据
|
|
return $data;
|
|
}
|
|
|
|
protected $config = [
|
|
'wechat' => [
|
|
'default' => [
|
|
// 必填-商户号
|
|
'mch_id' => '1647413230',
|
|
// 必填-v3商户秘钥
|
|
'mch_secret_key' => 'jTwAPZXpylR7TCoinWn2srOQUb6ioZlL',
|
|
// 必填-商户私钥 字符串或路径
|
|
'mch_secret_cert' => 'addon/hygl/wx_mch_cert/100000/apiclient_key.pem',
|
|
// 必填-商户公钥证书路径
|
|
'mch_public_cert_path' => 'addon/hygl/wx_mch_cert/100000/apiclient_cert.pem',
|
|
// 必填
|
|
'notify_url' => 'http://hycrm.zeyan.wang/api/hygl/wechatPayNotify',
|
|
// 选填-公众号 的 app_id
|
|
'mp_app_id' => 'wxd2d733a7163bff05',
|
|
// 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SERVICE
|
|
'mode' => Pay::MODE_NORMAL,
|
|
]
|
|
],
|
|
'logger' => [ // optional
|
|
'enable' => false,
|
|
'file' => './logs/wechat.log',
|
|
'level' => 'debug', // 建议生产环境等级调整为 info,开发环境为 debug
|
|
'type' => 'single', // optional, 可选 daily.
|
|
'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天
|
|
],
|
|
'http' => [ // optional
|
|
'timeout' => 5.0,
|
|
'connect_timeout' => 5.0,
|
|
// 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
|
|
],
|
|
];
|
|
|
|
public function wxMpPay_DEMO(){
|
|
$order = [
|
|
'out_trade_no' => time().'',
|
|
'description' => 'subject-测试',
|
|
'amount' => [
|
|
'total' => 1,
|
|
],
|
|
'payer' => [
|
|
'openid' => 'oYuE665Oexv3miom7BbuRQgevkHo',
|
|
],
|
|
];
|
|
|
|
$pay = Pay::wechat($this->config)->mp($order);
|
|
dd($pay);
|
|
}
|
|
|
|
//创建微信公众号支付(JSAPI)
|
|
public function wxMpPay(){
|
|
$order_id = $this->request->param('order_id','');
|
|
$user_id = $this->request->param('user_id','');
|
|
$site_id = $this->request->param('site_id','');
|
|
|
|
if (!$order_id || !$user_id || !$site_id) {
|
|
return fail('缺少参数');
|
|
}
|
|
|
|
$order = TransactionHistory::where('id',$order_id)
|
|
->where('user_id',$user_id)
|
|
->where('pay_status',0)
|
|
->find();
|
|
|
|
if (!$order){
|
|
return fail('订单不正确,请重新扫码');
|
|
}
|
|
|
|
|
|
$config = $this->initWxPayConfig($site_id);
|
|
|
|
if(!$config['code']){
|
|
return fail($config['msg']);
|
|
}
|
|
|
|
$openid = User::where('id',$user_id)->value('wx_openid');
|
|
|
|
if (!$openid){
|
|
return fail('请重新扫码');
|
|
}
|
|
|
|
$site_name = Site::where('site_id',$site_id)->value('site_name');
|
|
$order_pay = [
|
|
'out_trade_no' => $order['order_num'],//我方订单号
|
|
'description' => $site_name,
|
|
'amount' => [
|
|
'total' => $order['price'] * 100,//金额(分)
|
|
],
|
|
'payer' => [
|
|
'openid' => $openid,//支付用户的openid
|
|
],
|
|
];
|
|
|
|
//拉起微信公众号(JSAPI)支付
|
|
$pay = Pay::wechat($config['data'])->mp($order_pay);
|
|
return success($pay->toArray());
|
|
}
|
|
|
|
//支付成功异步回调
|
|
public function wechatPayNotify($site_id)
|
|
{
|
|
$filePath = 'login/test.txt';
|
|
// $date = date('Y-m-d H:i:s') . '_$site_id=' .$site_id;
|
|
// $data = "回调成功了-{$date}"; // 要写入的数据
|
|
// $a = file_put_contents($filePath, $data);
|
|
|
|
|
|
$site_id = $this->request->param('site_id','');
|
|
$config = $this->initWxPayConfig($site_id);//初始化微信支付配置项
|
|
|
|
$pay = Pay::wechat($config['data']);
|
|
try {
|
|
// 是的,你没有看错,就是这么简单!返回值为微信回调的订单数据
|
|
$data = $pay->callback();
|
|
// $a = "{$data->summary} - {$data['resource']['ciphertext']['trade_state_desc']}";
|
|
// file_put_contents($filePath,json_encode($data, JSON_UNESCAPED_UNICODE));
|
|
Log::write($data->all(),'notice');//记录日志
|
|
//判断是否支付成功
|
|
if ($data['event_type'] == "TRANSACTION.SUCCESS" && $data['resource']['ciphertext']['trade_state'] == "SUCCESS") {
|
|
//支付成功
|
|
//防止支付回调成功后重复给用户打款
|
|
$order = TransactionHistory::where('order_num', $data['resource']['ciphertext']['out_trade_no'])
|
|
->find();//查询我方订单号是否打款
|
|
if ($order['pay_status'] == 1) {
|
|
//已经支付过了,通知微信停止异步回调
|
|
return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';//付款成功
|
|
}
|
|
|
|
//修改订单状态
|
|
$cash_fee = $data['resource']['ciphertext']['amount']['payer_total'] ?? 0;
|
|
if ($cash_fee > 0){
|
|
$cash_fee = bcdiv($cash_fee, 100, 2);
|
|
}
|
|
|
|
$update = TransactionHistory::where('id', $order['id'])
|
|
->where('pay_status', 0)
|
|
->update([
|
|
'pay_num' => $data['resource']['ciphertext']['transaction_id'],//支付平台订单号
|
|
|
|
'cash_fee' => $cash_fee,//用户实际支付金额(元) 分 / 100=元
|
|
'pay_status' => 1,//订单支付状态|默认0:未支付,1:已支付
|
|
'pay_time' => time(),//
|
|
'pay_data_json' => json_encode($data, JSON_UNESCAPED_UNICODE),//支付回调json字符串
|
|
]);
|
|
if ($order['user_coupons_id']){
|
|
//核销优惠券
|
|
UserCoupons::where('id',$order['user_coupons_id'])
|
|
->where('is_show',1)
|
|
->update([
|
|
'is_show'=>0,
|
|
]);
|
|
}
|
|
|
|
|
|
if (!$update){
|
|
Log::write("订单{$data['resource']['ciphertext']['out_trade_no']}支付回调失败", 'error');//记录日志
|
|
}
|
|
|
|
|
|
}
|
|
} catch (\Exception $exception) {
|
|
Log::write($exception->getMessage(), 'error');//记录日志
|
|
$data = "错误-{$exception->getMessage()},行={$exception->getFile()},{$exception->getLine()}";
|
|
file_put_contents($filePath, $data);
|
|
}
|
|
$str = '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
|
|
return $str;
|
|
}
|
|
|
|
//
|
|
|
|
/**
|
|
* 初始化微信支付配置项
|
|
* @param $site_id 站点id
|
|
* @return array[]
|
|
* @throws \think\db\exception\DataNotFoundException
|
|
* @throws \think\db\exception\DbException
|
|
* @throws \think\db\exception\ModelNotFoundException
|
|
*/
|
|
private function initWxPayConfig($site_id){
|
|
//微信支付配置项目
|
|
$wx_config = Config::where('site_id',$site_id)
|
|
->find();
|
|
if (!$wx_config){
|
|
$res = [
|
|
'code'=>false,//true=成功,false=失败
|
|
'msg'=>'支付配置项不正确',
|
|
'data'=>[],
|
|
];
|
|
}else{
|
|
$config = [
|
|
'wechat' => [
|
|
'default' => [
|
|
// 必填-商户号
|
|
'mch_id' => $wx_config['we_chat_pay_mch_id'],
|
|
// 必填-v3商户秘钥
|
|
'mch_secret_key' => $wx_config['we_chat_pay_key'],
|
|
// 必填-商户私钥 字符串或路径
|
|
'mch_secret_cert' => $wx_config['we_chat_pay_mch_secret_cert'],
|
|
// 必填-商户公钥证书路径
|
|
'mch_public_cert_path' => $wx_config['we_chat_pay_mch_public_cert_path'],
|
|
// 必填
|
|
'notify_url' => $wx_config['we_chat_pay_notify_url'],
|
|
// 选填-公众号 的 app_id
|
|
'mp_app_id' => $wx_config['we_chat_pay_app_id'],
|
|
// 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SERVICE
|
|
'mode' => Pay::MODE_NORMAL,
|
|
]
|
|
],
|
|
'logger' => [ // optional
|
|
'enable' => false,
|
|
'file' => './logs/wechat.log',
|
|
'level' => 'debug', // 建议生产环境等级调整为 info,开发环境为 debug
|
|
'type' => 'single', // optional, 可选 daily.
|
|
'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天
|
|
],
|
|
'http' => [ // optional
|
|
'timeout' => 5.0,
|
|
'connect_timeout' => 5.0,
|
|
// 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
|
|
],
|
|
];
|
|
$res = [
|
|
'code'=>true,//true=成功,false=失败
|
|
'msg'=>'',
|
|
'data'=>$config,
|
|
];
|
|
}
|
|
return $res;
|
|
}
|
|
|
|
|
|
}
|
|
|