最近在开发一个项目包含web端、H5端和App端,在开发支付功能时每个端的情况略有不同在这里做一下记录,支付宝支付使用Yangsongda,微信支付使用EasyWeChat,如有不对之处欢迎指正。
安装Yansongda
composer require yansongda/pay -vvv
安装EasyWeChat
composer require w7corp/easywechat
下面上代码,可以直接使用
use EasyWeChat\Factory;
use Yansongda\LaravelPay\Facades\Pay;
class PayController extends BaseController
{
public function buyVip(Request $request)
{
$user_id = $this->getUserId();
$type = $request->input('type', '');
$id = (int)$request->input('id', 0);
$device_type = $this->deviceType;
if (!$type) {
return $this->error('支付类型不能为空');
}
if (!$id) {
return $this->error('商品ID不能为空');
}
$vip = Vip::where('id', $id)->first();
if (!$vip) {
return $this->error('充值金额不存在');
}
if ($type == 'wxpay') {
$order = OrderService::createOrder($user_id, $vip, 'alipay');
$config = config('wechat.payment.default');
$app = Factory::payment($config);
if ($device_type == 'app') {
// APP支付
$result = $app->order->unify([
'body' => $order['subject'],
'out_trade_no' => $order['order_sn'],
'total_fee' => $order['amount'] * 100,
//'notify_url' => 'https://pay.weixin.qq.com/wxpay/pay.action', // 支付结果通知网址,如果不设置则会使用配置里的默认地址
'trade_type' => 'APP', // 请对应换成你的支付方式对应的值类型
]);
} else {
if (isWechat()) {
$openid = DB::table('user')->where('id', $user_id)->value('wechat_openid');
if (!$openid) {
return $this->error('openid不存在');
}
//h5 微信jssdk
$result = $app->order->unify([
'body' => $order['subject'],
'out_trade_no' => $order['order_sn'],
'total_fee' => $order['amount'] * 100,
//'notify_url' => 'https://pay.weixin.qq.com/wxpay/pay.action', // 支付结果通知网址,如果不设置则会使用配置里的默认地址
'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
'openid' => $openid,
]);
} else {
// web/h5 扫码支付
$result = $app->order->unify([
'body' => $order['subject'],
'out_trade_no' => $order['order_sn'],
'total_fee' => $order['amount'] * 100,
//'notify_url' => 'https://pay.weixin.qq.com/wxpay/pay.action', // 支付结果通知网址,如果不设置则会使用配置里的默认地址
'trade_type' => 'NATIVE', // 请对应换成你的支付方式对应的值类型
]);
}
}
if ($result['return_code'] != 'SUCCESS') {
return $this->error('通信失败:' . $result['return_msg'], $result);
}
if ($result['result_code'] != 'SUCCESS') {
return $this->error('支付失败:' . $result['err_code'] . ':' . $result['err_code_des'], $result);
}
return $this->success('支付成功', $result);
} elseif ($type == 'alipay') {
$order = OrderService::createOrder($user_id, $vip, 'alipay');
$config = config('pay.alipay');
$alipay = Pay::alipay($config);
$body = [
'subject' => $order['subject'],
'out_trade_no' => $order['order_sn'],
'total_amount' => $order['amount'],
];
if ($device_type == 'app') {
return $alipay->web($body);
} else {
if (isMobile()) {
return $alipay->wap($body);
} else {
return $alipay->app($body);
}
}
} elseif ($type == 'applepay') {
$order = OrderService::createOrder($user_id, $vip, 'applepay');
$data = [
'order_id' => $order['id'],
'order_sn' => $order['order_sn'],
'price' => $order['amount'],
'payment' => $order['payment']
];
return $this->success('操作成功', $data);
}
return $this->error('error');
}
//微信支付异步回调
public function wxpayNotify()
{
$config = config('wechat.payment.default');
$app = Factory::payment($config);
$response = $app->handlePaidNotify(function ($message, $fail) {
// 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
$order = Order::where('order_sn', $message['out_trade_no'])->first();
if (!$order || $order->status == 1) { // 如果订单不存在 或者 订单已经支付过了
return true; // 告诉微信,我已经处理完了,订单没找到,别再通知我了
}
/ <- 建议在这里调用微信的【订单查询】接口查一下该笔订单的情况,确认是已经支付 /
if ($message['return_code'] != 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
return $fail('通信失败,请稍后再通知我');
}
// 用户是否支付成功
if (array_get($message, 'result_code') === 'SUCCESS') {
$order->pay_time = time(); // 更新支付时间为当前时间
$order->status = 1;
// 用户支付失败
} elseif (array_get($message, 'result_code') === 'FAIL') {
$order->status = 2;
}
$order->save(); // 保存订单
return true; // 返回处理完成
});
return $response;
}
//支付宝支付异步回调
public function alipayNotify(Request $request)
{
$config = config('pay.alipay');
$alipay = Pay::alipay($config);
try {
$data = $alipay->verify(); // 是的,验签就这么简单!
//以下根据自己业务进行支付校验
$order = Order::where('order_sn', $data->out_trade_no)->first();
if (!$order || $order->status == 1) {
//如果订单状态异常直接退出
return $alipay->success();
}
\Log::debug('Alipay notify', $data->all());
//进行订单状态变更等支付成功操作
PayService::handleOrderPaid($order);
return $alipay->success();
} catch (\Exception $e) {
}
return $alipay->success();// laravel 框架中请直接 `return $alipay->success()`
}
//支付宝支付同步接口
public function alipayReturn(Request $request)
{
$config = config('pay.alipay');
$alipay = Pay::alipay($config);
return $alipay->gateway()->verify($request->all());
}
//苹果支付订单结果查询
public function appleNotify(Request $request)
{
$receipt_data = $request->input('receipt-data', '');
$order_sn = $request->input('order_sn', '');
$is_sandbox = (int)$request->input('is_sandbox', 0);
if (!$receipt_data || !$order_sn) {
return $this->error('缺少必要参数');
}
//是否沙箱环境
$sandbox = false;
if ($is_sandbox) {
$sandbox = true;
}
$result = PayService::validateApplePay($receipt_data, $sandbox);
if ($result['status'] == true) {
//通过验证
$order = Order::where('order_sn', $order_sn)->first();
if (!$order) {
return $this->error('订单不存在');
}
if ($order['status'] != 1) {
PayService::handleOrderPaid($order);
}
return $this->success('支付成功');
} else {
return $this->error($result['message']);
}
}
}
代码中有几个类库没有引入,要根据自己实际情况添加。
也可以参考该文章:
可能是我用过的最优雅的 Alipay 和 WeChat 的支付 SDK 扩展包了 — 闫嵩达 | yansongda
Web端调起支付效果
移动端调起支付效果