支付宝支付
app\common\service\Alipay.php
<?php
/**
* Created by PhpStorm.
* Date: 2020/6/17
* Time: 0:01
*/
namespace app\common\service;
use app\common\model\LogModel;
use think\Request;
class Alipay {
private $config;
public function __construct( $config = [] )
{
if( !empty($config) ){
$this->config = $config;
}else{
$this->config = config('alipay');
}
}
//支付宝app支付
public function appPay($param){
$aliset = $this->config;
import('alipay.AopClient',EXTEND_PATH);
import('alipay.request.AlipayTradeAppPayRequest',EXTEND_PATH);
$log=[];
$log['title']='支付宝APP支付';
$log['content']['param']= $param;
$aop = new \AopClient(); // new AopClient;
$aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
$aop->appId = $aliset['app_id'];
$aop->rsaPrivateKey = $aliset['private_key'];
$aop->format = "json";
$aop->charset = "UTF-8";
$aop->signType = "RSA2";
$aop->alipayrsaPublicKey = $aliset['ali_public_key'];
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
$request = new \AlipayTradeAppPayRequest(); //new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数
$bizcontent = "{\"body\":\"支付宝APP支付\","
. "\"subject\": \"{$param['subject']}\","
. "\"out_trade_no\": \"{$param['out_trade_no']}\","
. "\"timeout_express\": \"30m\","
. "\"total_amount\": \"{$param['total_amount']}\","
. "\"product_code\":\"QUICK_MSECURITY_PAY\""
. "}";
$request->setNotifyUrl($param['notify_url']);
$request->setBizContent($bizcontent);
//这里和普通的接口调用不同,使用的是sdkExecute
$response = $aop->sdkExecute($request);
LogModel::add($log);
//htmlspecialchars是为了输出到页面时防止被浏览器将关键参数html转义,实际打印到日志以及http传输不会有这个问题
return $response;//htmlspecialchars($response);//就是orderString 可以直接给客户端请求,无需再做处理。
}
}
调用控制器方法
function num_random($length = 6) {
$pool = '0123456789';
return substr(str_shuffle(str_repeat($pool, 5)), 0, $length);
}
protected function makeToken($uid, $money)
{
$k = $uid . md5($money) . $uid;
$k = md5(sha1($k));
return $k;
}
$token = $this->makeToken($model->id, $money);
$data = ['id' => $model->id, 'money' => $money, 'app_token' => $token, 'notify_type' => 'device_notify'];
$data['type'] = 'alipay';
$sign = base64_encode(json_encode($data));
$order = [
'out_trade_no' => $user_info['id'] . time() . num_random(4),
'subject' => '商品支付',
'total_amount' => $money,
'notify_url' => $app_host . 'scan_doctor_app/notify_service/device_notify/' . $sign];
$alipay = new Alipay();
// $this->alipay($order,config('alipay'));
$pay = [];
$pay['pay_info'] = $alipay->appPay($order);
支付回调(微信及支付宝支付通用型回调,处理后续业务逻辑)
支付回调接口的请求格式必须是restful风格的:Route::any(‘/scan_doctor_app/notify_service/device_notify/:sign’, ‘scan_doctor_app/v1.notify_service/device_notify’);
// 成功回调
public function device_notify($sign)
{
try {
//$sign = input('sign');
$log = [];
$log['title'] = '支付回调';
$log['content']['request'] = $_REQUEST;
$log['content']['msg'] = '';
$log['content']['sign'] = empty($sign) ? '未传参' : $sign;
$signData = json_decode(base64_decode($sign), true);
$token = $this->makeToken($signData['id'], $signData['money']);
$log['content']['signData'] = $signData;
if ($token != $signData['app_token']) {
throw new Exception('token错误');
}
// 获取商品信息
/*$orderModel = DeviceBuy::get(function ($query) use($signData) {
$query->where('id', $signData['id']);
});*/
$orderModel = DeviceBuy::where('id', $signData['id'])->find();
if (!in_array($orderModel->getData('status'), [0, 1])) {
throw new Exception('错误_非待支付');
}
$payment_account = '';
//获取医生信息
// $diagDoctorWechatModel = ScanDoctorWechat::where('scan_doctor_id', $orderModel['scan_doctor_id'])->find();
$diagDoctorModel = ScanDoctor::where('id', $orderModel['scan_doctor_id'])->find();
if ($diagDoctorModel) {
$payment_account = $diagDoctorModel['name'];
}
$payment_flow = '';
$out_trade_no = '';
$content = '';
if ($signData['type'] == 'alipay') {
$payment_flow = input('trade_no');
$out_trade_no = input('out_trade_no');
$content = json_encode($_REQUEST);
$orderModel->pay_type = 2;
$orderModel->payment_flow = input('trade_no');
// $alipayRes = $orderModel->save();
// $log['content']['alipayRes'] = $alipayRes;
}else{
//微信支付,
$input_value = !empty( file_get_contents('php://input') ) ? file_get_contents('php://input') : '';
$curlData = simplexml_load_string($input_value, 'SimpleXMLElement', LIBXML_NOCDATA);
$curlData = json_decode(json_encode($curlData), true);
$log['content']['input'] = $curlData;
// $curlData['wxBackData']['transaction_id'];
if( !empty($curlData) ){
$payment_flow = $curlData['transaction_id'];
$out_trade_no = $curlData['out_trade_no'];
$content = json_encode($curlData);
$orderModel->payment_flow = $payment_flow;
}
}
//支付信息记录表 关联DeviceBuy
if( !empty($payment_flow) ){
$payment_lsit = PaymentList::where('data_id', $signData['id'])->where('out_trade_no', $out_trade_no)->find();
if( !$payment_lsit ){
$payment_lsit = new PaymentList;
//数据库不存在的情况新增数据
$payment_lsit->out_trade_no = $out_trade_no;
$payment_lsit->payment_flow = $payment_flow;
$payment_lsit->data_id = $signData['id'];
$payment_lsit->content = $content;
$payment_lsit->type = 1;
$payment_lsit->save();
}
}
$orderModel->payment_account = $payment_account;
/*$orderData = DeviceBuy::where('id', $orderModel['id'])->find();
if ($orderData) {
$orderData->payment_account = $payment_account;
$orderData->save();
}*/
if ($orderModel->scale == 0) {
// 不分期
$orderModel->money = $signData['money'];
$orderModel->pay = $signData['money'];
$orderModel->status = 2;
} else {
if ($orderModel->getData('status') == 0) {
// 付第一期
$orderModel->money = $signData['money'];
$orderModel->pay = $signData['money'];
$orderModel->status = 1;
} else {
// 付第二期
if ( empty( $signData['erqi'] ) || $signData['erqi'] != true) {
throw new Exception('非二期请求');
}
$orderModel->money += $signData['money'];
$orderModel->pay += $signData['money'];
$orderModel->status = 2;
}
}
$log['content']['DeviceBuyStatus'] = $orderModel->status;
$deviceBuyRes = $orderModel->save();
$log['content']['deviceBuyRes'] = $deviceBuyRes;
$streamModel = new DeviceStream();
$streamModel->scan_doctor_id = $orderModel->scan_doctor_id;
$streamModel->device_buy_id = $orderModel->id;
$streamModel->type = 0;
$streamModel->money = $signData['money'];
$streamModel->content = '购买设备';
$deviceStreamRes = $streamModel->save();
$log['content']['money'] = $signData['money'];
$log['content']['deviceStreamRes'] = $deviceStreamRes;
//$checkStatusRes = Check::where('order_id',$orderModel->id)->update(['status' => 1]);
//$log['content']['check_status_res'] = $checkStatusRes;
$log['content']['msg'] = 'success';
LogModel::add($log);
$response = \wxpay\Wxpay::success();
return $response;
} catch (Exception $e) {
$log['content']['msg'] = $e->getMessage();
LogModel::add($log);
return errorResponse($e->getMessage());
}
}
// 生成充值token
protected function makeToken($uid, $money)
{
$k = $uid . md5($money) . $uid;
$k = md5(sha1($k));
return $k;
}