准备工作
准备来laravel框架,下载好overtrue/laravel-wechat第三方插件composerrequireovertrue/wechat:~4.0-vvv
PHP代码
调用支付接口生成key签名use function EasyWeChat\Kernel\Support\generate_sign;
use Overtrue\LaravelWeChat\Facade as EasyWeChat;
use Illuminate\Http\Request;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use EasyWeChat\Kernel\Support\Collection;
/**
* 微信支付
* @var \EasyWeChat\Payment\Application
*/
protected $wxpay;
/**
* 微信小程序
* @var \EasyWeChat\MiniProgram\Application
*/
protected $mini;
/**
* OrderController constructor.
* @param ContractsCacheRepository $cache
* @param EasyWeChat $facade
*/
public function __construct(ContractsCacheRepository $cache, EasyWeChat $facade)
{
$this->wxpay = $facade->payment();
$this->mini = $facade->miniProgram();
}
/**
* 生成签名
*
* @param $code
* @param $body
* @param $out_trade_no
* @param $total_fee
* @return array|Collection|object|ResponseInterface|string
* @throws InvalidConfigException
* @link /
* @Date /5/30
* @author Bob
*/
public function wechatPay($code, $body, $out_trade_no, $total_fee)
{
$item = $this->mini->auth->session($code); // $code 为wx.login里的code
$result = $this->wxpay->order->unify([
'body' => $body, //标题或者商品名称
'out_trade_no' => $out_trade_no, //商户生成的订单号
'total_fee' => intval($total_fee * 100), //支付总价格 分
'trade_type' => 'JSAPI',
'openid' => $item['openid'], //openid
'notify_url' => 'https://xxxxxx/api/wechat/notify' //回调地址
]);
// 如果成功生成统一下单的订单,那么进行二次签名
if ($result['return_code'] === 'SUCCESS') {
// 二次签名的参数必须与下面相同
$params = [
'appId' => config('wechat.mini_program.default.app_id'),
'timeStamp' => (string)time(),
'nonceStr' => $result['nonce_str'],
'package' => 'prepay_id=' . $result['prepay_id'],
'signType' => 'MD5'
];
// config('wechat.payment.default.key')为商户的key签名
$params['paySign'] = generate_sign($params, config('wechat.payment.default.key'));
return $params;
} else {
return $result;
}
}
回调地址接口/**
* 微信支付回调
*
* @author Bob
* @link /
* @Date /5/30
*/
public function wechatNotify()
{
$response = $this->wxpay->handlePaidNotify(function ($message, $fail) {
// 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
$order = Order::where('order_no', $message['out_trade_no'])->first();
//订单不存在或者订单已支付
if (!$order || $order->pay_time) {
return true;
}
if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
if (array_get($message, 'result_code') === 'SUCCESS') { // 用户是否支付成功
$order->pay_time = Carbon::now(); // 更新支付时间为当前时间
$order->pay_status = 20; //支付状态 成功
$order->transaction_id = $message['transaction_id']; //微信交易号
} elseif (array_get($message, 'result_code') === 'FAIL') { // 用户支付失败
$order->status = 30; //支付状态 失败
}
} else {
return $fail('通信失败,请稍后再通知我');
}
$order->save(); // 保存订单
return true; // 返回处理完成
});
return response()->json(['code' => 1, 'msg' => '订单支付成功!', 'data' => $response]);
}
订单支付结果/**
* 订单支付结果
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
* @throws InvalidConfigException
* @author Bob
* @link /
* @Date /5/31
*/
public function orderPayResult(Request $request)
{
$order_no = $request->post('order_no');
//根据商品订单号查询
$wx_order = $this->wxpay->order->queryByOutTradeNumber($order_no);
if ($wx_order && $wx_order['trade_state'] === 'SUCCESS') {
return response()->json(['code' => 1, 'msg' => '交易成功!']);
}
return response()->json(['code' => 0, 'msg' => '支付失败!', 'data' => $wx_order]);
}
小程序代码/**
* 支付成功
*/
paysuccess: function () {
wx.login({
success: res1 => {
//根据订单ID调用支付接口生成sign签名
wx.request({
url: '/api/market/order/pay',
method: 'POST',
data: {
code: res1.code,
order_id: order_id //订单ID
},
header: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Bearer ${ wx.getStorageSync('access_token') }`
},
success: function (res) {
console.log(res)
wx.requestPayment(
{
'timeStamp': res.data.data.timeStamp,
'nonceStr': res.data.data.nonceStr,
'package': res.data.data.package,
'signType': res.data.data.signType,
'paySign': res.data.data.paySign,
'success': function (res) {
console.log(res)
//订单号查询订单支付状态
wx.request({
url: '/api/market/order/result',
method: 'POST',
data: {
order_no: order_no //订单号
},
header: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Bearer ${wx.getStorageSync('access_token')}`
},
success: function (res2) {
console.log(res2);
alert(res.data.msg);
}
})
},
'fail': function (res) { },
'complete': function (res) { }
})
},
fail: function (e) {
wx.showToast({
title: '服务器错误',
duration: 2000
});
},
})
}
})
}
在这儿提一些我遇到的坑和自己犯得傻
1、生成签名时提供的total_fee订单总金额,单位为分!!! 记住了,是分,意思是要 支付金额 x 100,然后去掉小数点
2、回调地址。我当时把回调地址写在route里面的auth:api中间件里面了,然后。。。调试了半天,最好查看nginx日志的时候才发现微信请求我回调地址的时候一直报错 401。自己埋得坑,坑了自己。
转载声明:本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处,尊重他人劳动。
欢迎捐赠赞赏