(1)需要去微信开放平台注册账号
相关的申请流程可以参考网站: https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Pay/Vendor_Service_Center.html
(2)将对应的配置写入配置文件中(配置文件可以参考我下面封装的微信类)
(3)创建订单表
$app = (new WeChatService())->connect(2);
$result = $app->order->unify([
'body' => $subject,
'out_trade_no' => $orderNumber,
'total_fee' => $amount * 100, // **单位:分**
'spbill_create_ip' => '', // 可选,如不传该参数,SDK 将会自动获取相应 IP 地址
'notify_url' => Env::get('web.host') . '/api/vip/wechatNotify', // 支付结果通知网址,如果不设置则会使用配置里的默认地址
'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
'openid' => $user['openid'], //从用户额外表中取到openId
]);
$res = json_decode($result, 1)['return_msg'];
if ($res == 'OK') $this->success(MSG_OK,$result); //支付成功
$this->error('支付失败'); //支付失败
/**
* @ApiTitle (微信异步支付会员VIP)
* @ApiRoute (/api/Vip/wechatNotify)
* @ApiInternal
*/
public function wechatNotify()
{
$app = (new WeChatService())->connect(1);
$response = $app->handlePaidNotify(function ($message, $fail) {
$type = input('type') ?? 1; //类型:1、开通/续费VIP
$outTradeNo = $message['out_trade_no']; //自定义订单号
//查询是否存在订单
$res = (new UserAccountModel)->where('order_number', $outTradeNo)->find();
// 如果订单不存在 或者 订单已经支付过了
if (!$res || $res->pay_time) return true;
if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
$tradeNo = $message['transaction_id']; //微信支付订单号
$totalFee = $message['total_fee']; //充值总金额
$timeEnd = $message['time_end']; //支付完成时间
//如果金额不匹配直接退出
if (($res->money) != $totalFee / 100) return true;
if ($message['result_code'] === 'SUCCESS') {
//支付成功
//更新资金表状态
(new UserAccountModel)->where('order_number', $outTradeNo)->update([
'trade_no' => $tradeNo, //支付时间
'pay_time' => $timeEnd, //支付时间
'pay_status' => 1, //支付状态:0=未到账,1=已到账
]);
//开通/升级VIP
if ($type == 1) $this->vipSuccess($res['from_id'], $outTradeNo);
}
} else {
return $fail('通信失败,请稍后再通知我');
}
return true;
});
$response->send(); // Laravel 里请使用:return $response;
}
public function getPayStatus()
{
$orderNumber = input('order_number'); //内部订单流水号
$order = (new UserAccountModel)->where('order_number', $orderNumber)->find();
if (!$order) $this->error('订单不存在!');
$status = $order['pay_status']; //支付状态:0=待支付,1=支付成功
if (!$status) $this->error('订单尚未支付成功!');
$this->success('订单支付成功!');
}
composer require yansongda/pay
(1)申请支付开放平台并填写资料 https://open.alipay.com/platform/home.htm
(2)填写配置文件,如下
//支付宝支付设置
'alipay' => [
'app_id' => '20160926005xxxxxx',
'notify_url' => 'http://yansongda.cn/notify.php',
'return_url' => 'http://yansongda.cn/return.php',
'ali_public_key' => '',
'private_key' => '',
// 使用公钥证书模式,请配置下面两个参数,同时修改ali_public_key为以.crt结尾的支付宝公钥证书路径,如(./cert/alipayCertPublicKey_RSA2.crt)
// 'app_cert_public_key' => './cert/appCertPublicKey.crt', //应用公钥证书路径
// 'alipay_root_cert' => './cert/alipayRootCert.crt', //支付宝根证书路径
'log' => [ // optional
'file' => './logs/alipay.log',
'level' => 'info', // 建议生产环境等级调整为 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)
],
'mode' => 'dev', // optional,设置此参数,将进入沙箱模式
],
//订单内容
$order = [
'out_trade_no' => $orderNumber,
'total_amount' => $amount,
'subject' => $subject,
];
$alipay = Pay::alipay(config('alipay'))->web($order); //网页支付
//$alipay = Pay::alipay(config('alipay'))->app($order); //app支付
return $alipay->send();// laravel 框架中请直接 `return $alipay`
/**
* @ApiTitle (支付宝同步接口)
* @ApiRoute (/api/Payment/alipayReturn)
* @ApiInternal
*/
public function alipayReturn()
{
$data = Pay::alipay(config('alipay'))->verify(); // 是的,验签就这么简单!
// 订单号:$data->out_trade_no
// 支付宝交易号:$data->trade_no
// 订单总金额:$data->total_amount
// 订单号:$data->out_trade_no
// 支付宝交易号:$data->trade_no
// 订单总金额:$data->total_amount
Db::startTrans();
try {
//验证数据
$outTradeNo = $data->out_trade_no;
$totalAmount = $data->total_amount;
$tradeNo = $data->trade_no;
$appId = $data->app_id;
$res = (new UserAccountModel)->where('order_number', $outTradeNo)->find();
if (!$res) $this->error('未找到该充值订单!');
if ($res['money'] != $totalAmount) $this->error('充值订单金额异常!');
if ($appId != config('alipay.app_id')) $this->error('充值支付平台异常!');
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
$data = [
'order_number' => $outTradeNo, //订单流水号
'trade_no' => $tradeNo, //支付宝/微信订单号
'total_amount' => $totalAmount, //资金金额
];
$this->success('操作成功,等待充值结果!', $data);
}
/**
* @ApiTitle (支付宝异步接口)
* @ApiRoute (/api/Payment/vipAliNotify)
* @return \Symfony\Component\HttpFoundation\Response
* @ApiAuthor (黄育华 2020/3/9)
* @ApiInternal
*/
public function alipayNotify()
{
$alipay = Pay::alipay(config('alipay'));
$type = input('type') ?? 1; //类型:1、开通/续费VIP
Db::startTrans();
try {
$data = $alipay->verify(); // 是的,验签就这么简单!
$state = $data->trade_status; //订单状态
$outTradeNo = $data->out_trade_no; //自定义订单号
$tradeNo = $data->trade_no; //支付宝订单号
$totalAmount = $data->total_amount; //充值总金额
$appId = $data->app_id; //收款方的APPID
//获取对应订单的资金流水信息
$res = (new UserAccountModel)->where('order_number', $outTradeNo)->find();
// 请自行对 trade_status 进行判断及其它逻辑进行判断,在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时,支付宝才会认定为买家付款成功。
// 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号;
// 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额);
// 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email);
// 4、验证app_id是否为该商户本身。
// 5、其它业务逻辑情况。
if (!in_array($state, ['TRADE_SUCCESS', 'TRADE_FINISHED'])) return $alipay->success()->send();
if (!$res) return $alipay->success()->send();
if ($res['money'] != $totalAmount) return $alipay->success()->send();
if ($appId != config('alipay.app_id')) return $alipay->success()->send();
//以下执行操作......
//更新资金表状态
(new UserAccountModel)->where('order_number', $outTradeNo)->update([
'trade_no' => $tradeNo, //支付时间
'pay_time' => time(), //支付时间
'pay_status' => 1, //支付状态:0=未到账,1=已到账
]);
//开通/升级VIP
if ($type == 1) $this->vipSuccess($res['from_id'], $outTradeNo);
Log::debug('Alipay notify', $data->all());
Db::commit();
} catch (\Exception $e) {
Db::rollback();
}
return $alipay->success()->send();// laravel 框架中请直接 `return $alipay->success()`
}
欢迎来指导和学习,如果有什么问题可以在留言区留言并一起探讨。