可能是我用过的最优雅的 Alipay 和 WeChat 的支付 SDK 扩展包了 # yansongda/pay
下面以微信为例,支付宝写法大同小异
下载地址:https://github.com/yansongda/pay
安装
composer require yansongda/pay -vvv
laravel框架
配置参数
在config
目录下创建一个wechat.php
微信支付配置文件
return [
// APP APPID
'appid' => 'wxb3fxxxxxxxxxxx',
//公众号 APPID
'app_id' => 'wxb3fxxxxxxxxxxx',
//小程序 APPID
'miniapp_id' => 'wxb3fxxxxxxxxxxx',
//AppSecret
'app_secret' => 'mF2suE9sU6Mk1Cxxxxxxxxxxx',
//小程序授权的url
'auth_url' => "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
//商户号
'mch_id' => '14577xxxx',
//API密钥
'key' => 'mF2suE9sU6Mk1Cxxxxxxxxxxx',
//回调
'notify_url' => 'http://xxx/payment/notify/native',
//证书
'cert_client' => resource_path('cert/apiclient_cert.pem'),
'cert_key' => resource_path('cert/apiclient_key.pem'),
//日志
'log' => [
'file' => storage_path('logs/wechat_pay.log')
],
//自动退款时间,30天
'refunde_time' => 10
];
注册一个wechat_pay
微信支付服务单例
app->singleton('wechat_pay', function () {
$config = config('wechat');
if (app()->environment() !== 'production') {
$config['log']['level'] = Logger::DEBUG;
} else {
$config['log']['level'] = Logger::WARNING;
}
// 调用 Yansongda\Pay 来创建一个微信支付对象
return Pay::wechat($config);
});
}
}
代码解析:
$this->app->singleton()
往服务容器中注入一个单例对象,第一次从容器中取对象时会调用回调函数来生成对应的对象并保存到容器中,之后再去取的时候直接将容器中的对象返回。
app()->environment()
获取当前运行的环境,线上环境会返回 production。对于支付宝,如果项目运行环境不是线上环境,则启用开发模式,并且将日志级别设置为 DEBUG。由于微信支付没有开发模式,所以仅仅将日志级别设置为 DEBUG
扫码支付
money;
if (!$money) {
return failed(400, '充值金额不能为空');
}
$out_trade_no = 'RE'.date('YmdHis').$this->user_id;
RechargeModel::create([
'recharge_no' => $out_trade_no,
'admin_id' => $this->user_id,
'money' => $money
]);
$wechat = app('wechat_pay')->scan([
'out_trade_no' => $out_trade_no,
'body' => '代理充值',
'total_fee' => $money * 100
]);
//生成支付二维码
$qr_code = new QrCode($wechat->code_url);
header('Content-Type: '.$qr_code->getContentType());
return successful(['code_url' => base64_encode($qr_code->writeString())]);
}
/**
* @api {post} /payment/notify/native 扫码回调
*/
public function notify(Request $request)
{
$data = app('wechat_pay')->verify();
$order = RechargeModel::where('recharge_no', $data->out_trade_no)->first();
if (!$order) {
return failed(400, '订单不存在');
}
if ($order->payment_at) {
return app('wechat_pay')->success();
}
DB::beginTransaction();
try {
//更新充值订单信息
RechargeModel::where('recharge_no', $data->out_trade_no)->update([
'payment_at' => Carbon::now(),
'payment_no' => $data->transaction_id,
'payment_type' => 1,
]);
//增加代理余额
AdminModel::where('id', $order->admin_id)->increment('money', $order->money);
DB::commit();
} catch (\Exception $e) {
DB::rollback();
}
return isset($e) ? failed(401, $e->getMessage()) : app('wechat_pay')->success();
}
}
生成二维码# endroid/qr-code
composer require endroid/qr-code
企业付款到零钱
type) {
return failed(400, '类型不能为空');
}
$withdraw = WithdrawModel::find($withdraw_id);
if (!$withdraw) {
return failed(404, '提现记录不存在');
}
if ($withdraw->status != 1) {
return failed(401, '该提现已审核,无需再次操作');
}
//用户提现
$user_id = $withdraw->user_id;
//代理提现
if ($withdraw->type == 2) {
$user_id = AdminModel::where('id', $withdraw->user_id)->value('user_id');
}
$openid = UserModel::where('id', $user_id)->value('openid');
if (!$openid) {
return failed(402, '用户不存在');
}
$result = app('wechat_pay')->transfer([
'openid' => $openid,
'check_name' => 'NO_CHECK',
'partner_trade_no' => $withdraw->withdraw_no,
'amount' => $withdraw->money * 100,
'desc' => '提现'
]);
if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') {
$withdraw->payment_no = $result->payment_no;
$withdraw->payment_time = $result->payment_time;
$withdraw->status = 3;
$withdraw->payment_type = 1;
$result = $withdraw->save();
} else {
$result = 0;
}
return $result ? successful() : failed(403, '审核失败,请联系管理员');
}
}
注:企业付款到零钱,需在产品设置中添加服务器的IP
其他支付,请参考文档和微信支付文档
生成二维码 endroid/qr-code
支付SDK yansongda/pay
2.X支付文档 https://pay.yanda.net.cn/docs/2.x/overview
微信支付文档 https://pay.weixin.qq.com/wiki/doc/api/index.html