企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
#调用统一支付接口 有什么优势,开发者再也不用去关注支付宝或者微信等三方支付的任何逻辑,只需要调用钱包模块暴露出来的通用支付接口就可以完成一切支付。 以官方模块为例,官方的商城模块、VIP模块、应用市场模块都是调用的钱包的统一支付接口。 接口地址:U('Wallet/Index/pay') ##模块提交订单 有支付需求的模块将用户的订单信息保存到数据库,比如商城模块将订单号为test_123的订单信息保存到ly_shop_order表里。 ##模块调用支付接口 以session方式设置支付信息和配置 有种调用接口的方式: ### 第一代 out_trade_no: 订单号 title:订单标题 money:订单需要支付的金额 callback:当前模块的一个控制器地址 allow_redbag:允许红包参与支付 allow_coupon:允许折扣券参与支付 ### 第二代(钱包模块必须大于1.6.0版本) out_trade_no: 订单号 title:订单标题 money:订单需要支付的金额 callback: > 支持两种回调 action:模块/控制器:方法 model:模块/模型:方法 allow_third:是否允许直接调用第三方支付 allow_money:是否允许余额支付,设为false表示直接采用参访支付 return_url:支付完成后钱包模块跳转回去的地址 allow_redbag:允许红包参与支付 allow_coupon:允许折扣券参与支付 ##钱包模块提交账单 根据支付配置生成支付页面 用户选择支付方式,提交支付信息 钱包模块内部支付 ### 第一代方式或者第二代方式余额足够本次支付 钱包处理完成后直接通过指定的callback地址或者方法处理模块订单的回调事情。 ### 第二代方式 如果是需第三方支付的第二代方式,计算账单,并写入数据库。跳转到钱包模块openPay方法准备调用第三方支付。 根据数据库账单信息,生成第三方支付地址,并转到第三方支付页面,支付完成后第三方服务器会异步通知钱包模块处理订单。用户在第三方服务器支付完成后根据传递给第三方服务器的地址跳转到return_url,回调处理会在notify方法中得到异步处理。 ## 第一代调用实例 ```php // +---------------------------------------------------------------------- namespace Vip\Controller; use Home\Controller\HomeController; /** * 订单控制器 * @author jry <598821125@qq.com> */ class OrderController extends HomeController { /** * 初始化方法 * @author jry <598821125@qq.com> */ protected function _initialize() { parent::_initialize(); $this->is_login(); } /** * 开通会员 * @author jry <598821125@qq.com> */ public function index() { if (request()->isPost()) { $data['out_trade_no'] = \lyf\Str::createOutTradeNo(); // 随机生成一个订单号,你可以定义自己的规则 $data['total_price'] = 88.88; $order_object = D('Vip/Order'); $add_data = $order_object->create($data); if ($add_data) { $result = $order_object->add($add_data); if ($result) { $pay_data['out_trade_no'] = $add_data['out_trade_no']; $pay_data['title'] = '开通VIP'; $pay_data['money'] = $add_data['total_price']; $pay_data['callback'] = U('Vip/Order/callback', array('out_trade_no' => $pay_data['out_trade_no']), true, true); $pay_data['allow_redbag'] = true; $pay_data['allow_coupon'] = true; session('pay_data_' . $pay_data['out_trade_no'], $pay_data); // 注意了,这里就是跳转到钱包模块统一支付接口 redirect(U('Wallet/Index/pay', array('out_trade_no' => $pay_data['out_trade_no']), true, true)); } else { $this->error('订单错误' . $order_object->getError()); } } else { $this->error('订单错误' . $order_object->getError()); } } else { $this->assign('meta_title', "开通会员"); $this->display(); } } /** * 开通会员回调接口 * @author jry <598821125@qq.com> */ public function callback($out_trade_no) { $pay_data = session('pay_data_' . $out_trade_no); if (($pay_data['pay_verify'] === true) && ($pay_data['is_callback'] !== true)) { if (!$pay_data['out_trade_no']) { $this->error('参数错误'); } else { $order_object = D('Vip/Order'); $order_info = $order_object->where(array('out_trade_no' => $pay_data['out_trade_no']))->find(); if (($order_info['total_price'] !== $pay_data['money']) || ($order_info['out_trade_no'] !== $pay_data['out_trade_no'])) { $this->error('订单异常'); } else { $result = $order_object->where(array('id' => $order_info['id']))->setField('is_pay', 1); if ($result) { // 这里是开通会员处理逻辑 // 这里是开通会员处理逻辑 // 这里是开通会员处理逻辑 session('pay_data_' . $out_trade_no . '.is_callback', true); $this->success('支付成功', U('index')); } else { $order_object->where(array('id' => $order_info['id']))->setField('status', 0); $this->error('订单异常'); } } } } else { $this->error('支付失败'); } } } ``` ## 第二代调用实例 ```php where($map)->find(); if (!$order_info) { $this->error('订单无效'); } if ($order_info['is_pay']) { $this->success('订单已支付'); } //清除支付session session('pay_data_' . $out_trade_no, null); $order_object = D('Order'); $map['out_trade_no'] = $out_trade_no; $order_info = $order_object->where($map)->find(); if (empty($order_info) || $order_info['is_pay']) { $this->error('订单已支付或订单无效'); } $pay_data['out_trade_no'] = $order_info['out_trade_no']; $pay_data['title'] = '在线订单-首饰金额'; $pay_data['money'] = $order_info['price'] + 20; $pay_data['callback'] = 'action:Shop/Order:callback';//action:模块/控制器:方法,或者//model:模块/模型:方法 // 这是钱包模块支付网关完成支付后跳转到指定的网址 $pay_data['return_url'] = U('Order/paySuccess', array('out_trade_no' => $order_info['out_trade_no']), true, true); $pay_data['allow_redbag'] = true; $pay_data['allow_coupon'] = true; $pay_data['allow_third'] = true; $pay_data['allow_money'] = true; session('pay_data_' . $pay_data['out_trade_no'], $pay_data); redirect(U('Wallet/Index/pay', array('out_trade_no' => $pay_data['out_trade_no']), true, true)); // 余额支付接口 } //完成以上步骤之后,页面跳转到支付页面/wallet/index/pay,用户最终确认订单信息,同时需要用户在前端操作来完成支付。前端代码示例如下: <form class="col-xs-12 form-horizontal form-pay" action="{:U('Wallet/Index/dopay')}" method="POST" role="form"> <legend>订单信息</legend> <div class="form-group"> <label class="col-xs-3">订单标题:</label> <p class="col-xs-9 text-primary">{$pay_data.title}</p> </div> <div class="form-group"> <label class="col-xs-3">应付金额</label> <p class="col-xs-9 text-primary original-money">{$pay_data.money}</p> </div> <?php if($redbag_list): ?> <div class="form-group"> <label class="col-xs-3">使用红包</label> <p class="col-xs-9"> <select name="redbag_id" class="form-control lyui-select col-sm-4"> <option value="" data-price="0">选择可用红包</option> <volist name="redbag_list" id="rl"> <option value="{$rl.id}" data-price="{$rl.money}">{$rl.money}元红包-满{$rl.limit}可用-{$rl.title}</option> </volist> </select> </p> </div> <?php endif; ?> <?php if($coupon_list): ?> <div class="form-group"> <label class="col-xs-3">使用折扣券</label> <p class="col-xs-9"> <select name="coupon_id" class="form-control lyui-select col-sm-4"> <option value="" data-price="0">选择可用折扣券</option> <volist name="coupon_list" id="cl"> <option value="{$cl.id}" data-price="{$cl.coupon}">{$cl.coupon}折扣券-满{$cl.limit}可用-{$cl.title}</option> </volist> </select> </p> </div> <?php endif; ?> <div class="form-group"> <label class="col-xs-3">实际需付</label> <p class="col-xs-9 text-danger">¥ <span class="actual-money">{$pay_data.money}</span></p> </div> <div class="form-group"> <label class="col-xs-3">钱包余额</label> <p class="col-xs-9" id="user-money"> <span>¥ {$user_info.money|default='0.00'}</span> <a class="m-l" target="blank" href="{:U('Wallet/Recharge/index', '', true, true)}">余额充值</a> </p> </div> <?php if($pay_data['allow_money']): ?> <div class="form-group"> <label class="col-xs-3">余额支付</label> <div class="col-xs-9 checkbox checkbox-slider--b-flat checkbox-slider-md"> <label style="position: relative;"> <input id="allow_money_toggle" type="checkbox" checked="checked"> <span>使用余额支付</span> <input id="allow_money" type="hidden" name="allow_money" value="1"> </label> </div> </div> <?php endif; ?> <?php if($pay_data['allow_third']): ?> <div class="form-group" id="allow_pay_type"> <label class="col-xs-3">支付方式</label> <p class="col-xs-9 text-primary"> <volist name="allow_pay_type" id="pt"> <label class="radio" for="pay_type_{$pt.type}"> <input type="radio" id="pay_type_{$pt.type}" class="radio" name="pay_type" value="{$pt.type}" <if condition="$i eq 1">checked="checked"</if>> <img src="{$pt.logo}" style="height: 30px;"> </label> </volist> </p> </div> <?php endif; ?> <div class="form-group"> <div class="col-xs-12 col-sm-4 col-sm-offset-8"> <a class="btn btn-warning" data-toggle="modal" href='#modal-pay'>立即支付</a> </div> <div class="modal fade" id="modal-pay"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> <h4 class="modal-title">确认支付</h4> </div> <div class="modal-body row"> <div class=" col-xs-12"> <input type="password" class="form-control input-lg" name="password" placeholder="请输入用户密码"> </div> </div> <div class="modal-footer"> <input type="hidden" class="form-control" name="out_trade_no" value="{$pay_data.out_trade_no}"> <button type="submit" class="btn btn-block btn-lg btn-success" id="pay_submit" target-form="form-pay">确认支付</button> </div> </div> </div> </div> </div> </form> //以上的表单将支付信息提交到wallet/index/dopay最终执行支付,该方法较为完善,后期开发中一般不需要过多改动。 //支付成功之后钱包模块会调用callback字段中的方法(支持类型为action和model) //此处只允许读取钱包模块数据,禁止修改账单的任何数据 //订单表必须支持事务 此处无需开启事务,所有回调事务均在Wallet/pay页面或notify页面 public function callback($out_trade_no = null) { if (!$out_trade_no) { $this->error = '订单号必须'; return false; } //获取订单数据 $order_object = D('Shop/Order'); $order_info = $order_object->where(array('out_trade_no' => $out_trade_no))->find(); //数据校对 if (!$order_info) { $this->error = '订单不存在'; return false; } //判断订单是否已回调,此处已is_pay为标记 if ($order_info['is_pay']) { return true; } //执行回调,并将is_pay设为1, 作为上一步骤的回调成功标记 $data = array(); $data['is_pay'] = 1; $data['pay_time'] = time(); $data['pay_money'] = $pay_data['money'] + $pay_data['third_money']; $result = $order_object->where(array('id' => $order_info['id']))->setField($data); if (false === $result) { $this->error = $order_object->getError(); return false; } return true; } ?> ```