APP接入支付宝APP支付的ThinkPHP5的实现

支付流程

QQ截图20180703183003.png


下载支付宝php版的sdk 地址:https://docs.open.alipay.com/54/103419/
文件夹重命名Alipay放到thinkPHP 的extend下


代码实现

<?php
namespace app\api\controller;
use app\common\controller\Api;
use think\Db;
require_once EXTEND_PATH . '/alipay/AopSdk.php';
/**
 * 支付宝
 */
class Alipay extends Api
{
protected $noNeedLogin = '*';
protected $noNeedRight = '*';
/**
     * 应用ID
     */
const APPID = '';
/**
     *请填写开发者私钥去头去尾去回车,一行字符串
     */
const RSA_PRIVATE_KEY = '';
/**
     *请填写支付宝公钥,一行字符串
     */
const ALIPAY_RSA_PUBLIC_KEY = '';
/**
     * 支付宝服务器主动通知商户服务器里指定的页面
     * @varstring
     */
private $callback = "";
/**
     *生成APP支付订单信息 userId:用户id  goodsId:商品id  trade_type:支付类型,wxpay,alipay amount:金额 body:商品描述 subject:支付商品的标题 expire:该笔订单允许的最晚付款时间,逾期将关闭交易
     * @paramstring $orderId   商品订单ID
     * @paramstring $subject   支付商品的标题
     * @paramstring $body      支付商品描述
     * @paramfloat $pre_price  商品总支付金额
     * @paramint $expire       支付交易时间
     * @returnbool|string  返回支付宝签名后订单信息,否则返回false
     */
public function create_order()
{
if (!$this->request->request('userId') || !$this->request->request('goodsId') || !$this->request->request('trade_type') || !$this->request->request('amount')) {
$ret = array(
'code' => 200,
'msg' => "参数错误",
);
echo json_encode($ret);
exit();
}
$orderInfo = array(
'orderSn' => $this->get_order_no(),
'userId' => $this->request->request('userId'),
'goodsId' => $this->request->request('goodsId'),
'payType' => $this->request->request('trade_type'),
'amount' => $this->request->request('amount'),
'create_time' => date('Y-m-d H:i:s'),
'result' => '',
'status' => 0,
);
//生成订单入库
//$result = Db::table('GameOrderSn')->insert($orderInfo);
$result = 1;
if ($result) {
try {
$aop = new \AopClient();
$aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
$aop->appId = self::APPID;
$aop->rsaPrivateKey = self::RSA_PRIVATE_KEY;
$aop->format = "json";
$aop->charset = "UTF-8";
$aop->signType = "RSA2";
$aop->alipayrsaPublicKey = self::ALIPAY_RSA_PUBLIC_KEY;
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
$request = new \AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数
$bizcontent = "{\"body\":\"{$this->request->request('body')}\","//支付商品描述
. "\"subject\":\"{$this->request->request('subject')}\","//支付商品的标题
. "\"out_trade_no\":\"{$orderInfo['orderSn']}\","//商户网站唯一订单号
. "\"timeout_express\":\"{$this->request->request('expire')}m\","//该笔订单允许的最晚付款时间,逾期将关闭交易
. "\"total_amount\":\"{$orderInfo['amount']}\","//订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]
. "\"product_code\":\"QUICK_MSECURITY_PAY\""
. "}";
$request->setNotifyUrl($this->callback);
$request->setBizContent($bizcontent);
//这里和普通的接口调用不同,使用的是sdkExecute
$response = $aop->sdkExecute($request);
//htmlspecialchars是为了输出到页面时防止被浏览器将关键参数html转义,实际打印到日志以及http传输不会有这个问题

return htmlspecialchars($response); //就是orderString 可以直接给客户端请求,无需再做处理。
//return $response;
} catch (\Exception $e) {
return false;
}
}
}
public function notify()
{
// require_once('/alipay/aop/AopClient.php');
//验证签名
$aop = new \AopClient();
$aop->alipayrsaPublicKey = self::ALIPAY_RSA_PUBLIC_KEY;
$flag = $aop->rsaCheckV1($_POST, null, "RSA2");
file_put_contents(ROOT_PATH . '/public/alipayback' . date('Y-m-d') . '.log', var_export($flag, true) . PHP_EOL, 8);
exit();
//验签
if ($flag) {
//处理业务,并从$_POST中提取需要的参数内容
if ($_POST['trade_status'] == 'TRADE_SUCCESS'
|| $_POST['trade_status'] == 'TRADE_FINISHED') { //处理交易完成或者支付成功的通知
//获取订单号
$orderSn = $_POST['out_trade_no'];
//交易号
$trade_no = $_POST['trade_no'];
//订单支付时间
$gmt_payment = $_POST['gmt_payment'];
//转换为时间戳
$gtime = strtotime($gmt_payment);
//此处编写回调处理逻辑
//写支付记录,更新订单表
//to do...
$order = array(
'paySn' => $trade_no, //微信支付订单号
'status' => 1,
'pay_time' => date('Y-m-d H:i:s',$gtime),
);
//查看订单状态,为已支付则完成流程
$orderInfo = Db::table('GameOrderSn')->where('orderSn', $orderSn)->find();
if ($orderInfo['status'] == 1) {
exit('');
}
// 启动事务
Db::startTrans();
try {
$userId = $orderInfo['userId'];
$goodsId = $orderInfo['goodsId'];
$amount = $orderInfo['amount'];
Db::table('GameOrderSn')->where('orderSn', $orderSn)->update($order); //更新订单信息
//查询商品,为已支付则完成流程
$goodsInfo = Db::table('ShopInfoList')->where('ItemID', $goodsId)->find();
//计算购买道具数据量
$nums = ($amount / $goodsInfo['Price']) * $goodsInfo['GoodsNum'];
//更新用户道具
Db::table('GameScoreInfo')->where('UserID', $userId)->setInc('InsureScore', $nums);
Db::commit();
//处理购买后的业务逻辑.通知充值结果到服务器
$codeM = 13;
$codeS = 1;
$this->send_msg($userId, $codeM, $codeS);
} catch (\Exception $e) {
// 回滚事务
Db::rollback();
}
//处理成功一定要返回 success 这7个字符组成的字符串,
die('success'); //响应success表示业务处理成功,告知支付宝无需在异步通知
}
}
}
/**
     * 生成订单号
     *
     */
public function get_order_no()
{
$yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
$orderSn = $yCode[intval(date('Y')) - 2018] . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
return $orderSn;
}
/**
     * 通知充值结果到服务器
     * @param $params
     * @returnstring
     */
public function send_msg($userId, $codeM, $codeS)
{

}