#調用統一支付接口
有什么優勢,開發者再也不用去關注支付寶或者微信等三方支付的任何邏輯,只需要調用錢包模塊暴露出來的通用支付接口就可以完成一切支付。
以官方模塊為例,官方的商城模塊、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">×</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;
}
?>
```
- 簡介
- 環境要求
- 安裝系統
- 目錄結構
- 常見問題
- 基礎知識
- 編輯器
- 前端規范
- 前端框架文檔
- Builder教程
- Builder的來歷
- ListBuilder使用
- setMetaTitle
- addTopButton
- setSearch
- addSearchItem
- setTabNav
- addTableColumn
- setTableDataList
- setTableDataListKey
- setTableDataPage
- addRightButton
- alterTableData
- setExtraHtml
- setTemplate
- FormBuilder使用
- setMetaTitle
- setTabNav
- setExtraItems
- setPostUrl
- addFormItem
- setFormData
- setExtraHtml
- setAjaxSubmit
- setTemplate
- 擴展FormBuilder
- 模塊開發
- 創建模塊
- 描述文件
- 模型( M )
- 模版( V )
- 控制器( C )
- API接口
- 核心模塊
- 文件上傳
- 微信小程序模塊
- 注冊登陸接口
- 錢包模塊
- 統一支付
- Cms模塊
- 幻燈片接口
- 文檔列表接口
- 文檔詳情接口
- 發表評論接口
- 評論列表接口
- 收藏的文檔接口
- 收藏接口
- 分類列表接口
- IM模塊
- 發送消息接口
- 最近聊天列表接口
- 查詢新消息接口
- 插件相關
- 短信插件
- 支付插件
- 支付寶支付
- 微信支付
- 站群模塊
- 模板開發
- 準備工作
- 目錄結構
- 數據調用
- 專題
- 插件開發
- 圖片顯示
- 獲取用戶信息
- 判斷用戶登陸
- 表單提交AjaX
- 文件上傳
- 2.0兼容寫法
- 模板標簽
- 核心模塊
- Cms模塊
- 欄目分類調用
- Cordova
- 配置跨域支持
- 本地開發調試教程
- 打包成apk和ipa
- 自定義APP信息
- 常見問題
- 申請Apple開發者賬戶
- 多主題開發
- 新建主題
- 目錄結構
- 模板變量
- 定制安裝部署