微信支付
app\common\service\WxPay.php
<?php /** * Created by PhpStorm. * Date: 2020/6/17 * Time: 0:01 */ namespace app\common\service; use app\common\model\LogModel; class Wxpay extends WxpayCommon { protected $log; /** * desc:测试app支付 */ public function test(){ $params['appid'] = 'wx85ad1ecf7ebce37a'; $params['attach'] = 'test'; $params['body'] = 'test2'; $params['mch_id'] = '1587922861'; $params['notify_url'] = '2323'; $params['out_trade_no'] = time(); $params['total_fee'] = 100; $response = $this->appPay($params); echo json_encode($response); } /** * desc:APP支付 */ public function appPay($config) { $this->log=[]; $this->log['title']='微信APP支付'; $this->log['content']['config']= $config; $params = []; $params['appid'] = $config['appid']; $params['attach'] = $config['attach']; $params['body'] = $config['body']; $params['mch_id'] = $config['mch_id']; $params['nonce_str'] = $this->getNonceStr(); $params['notify_url'] = $config['notify_url']; $params['out_trade_no'] = $config['out_trade_no']; $params['spbill_create_ip'] = $_SERVER['SERVER_ADDR']; $params['total_fee'] = $config['total_fee']; $params['trade_type'] = "APP"; $this->log['flag'] = $config['out_trade_no']; $this->log['content']['params']= $params; //获取签名 $sign = $this->makeSign($params); $this->log['content']['sign']= $sign; $params['sign'] = $sign; $xml = $this->ToXml($params); $api = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $curlData = $this->curlXml($api, $xml); $this->log['content']['curlDataXML']= $curlData; $curlData = simplexml_load_string($curlData, 'SimpleXMLElement', LIBXML_NOCDATA); $curlData = json_decode(json_encode($curlData), true); $this->log['content']['curlData']= $curlData; //返回 $response=[]; $response['appid'] = !empty($curlData['appid'])?$curlData['appid']:''; $response['partnerid'] = !empty($curlData['mch_id'])?$curlData['mch_id']:''; $response['prepayid'] = !empty($curlData['prepay_id'])?$curlData['prepay_id']:''; $response['package'] = 'Sign=WXPay'; $response['noncestr'] = $this->getNonceStr(); $response['timestamp'] = time(); $sign2 = $this->makeSign($response); $response['sign'] = $sign2; $this->log['content']['response']= $response; LogModel::add($this->log); return $response; } }
app\common\service\WxpayCommon.php
<?php /** * Created by PhpStorm. * Date: 2020/6/17 * Time: 0:01 */ namespace app\common\service; use think\Config; use think\Controller; class WxpayCommon extends Controller { protected $log; /** * desc:测试签名,与https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=20_1进行对比 */ public function testSign(){ $response=[]; $response['appid'] = 'wx85ad1ecf7ebce37a'; $response['partnerid'] = '1587922861'; $response['prepayid'] = 'wx2318424232767470837925821975240400'; $response['package'] ='Sign=WXPay'; $response['noncestr'] = 't0ym9r9qjoji6b8r9yloksymxxzcge5q'; $response['timestamp'] = 1592908962; $sign = $this->makeSign($response); echo $sign; } /** * desc:推送xml */ public function curlXml($api,$xml){ $header[] = "Content-type: text/xml"; //定义content-type为xml,注意是数组 $ch = curl_init ($api); curl_setopt($ch, CURLOPT_URL, $api); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); $response = curl_exec($ch); if(curl_errno($ch)){ print curl_error($ch); exit(); } curl_close($ch); return $response; } /** * auth:chenliang * desc:获取签名 */ public function makeSign($params){ //第一步 ksort($params); $str = $this->ToUrlParams($params); //第二部 $str.="&key=".Config::get("wxapp.key"); //第三步 $sign= strtoupper(MD5($str)); return $sign; } /** * desc:字符串拼接 */ public function ToUrlParams($params) { $buff = ""; foreach ($params as $k => $v) { if($k != "sign" && $v != "" && !is_array($v)){ $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; } /** * desc:数组转成xml */ public function ToXml($values) { if(!is_array($values) || count($values) <= 0) { throw new WxPayException("数组数据异常!"); } $xml = "<xml>"; foreach ($values as $key=>$val) { if (is_numeric($val)){ $xml.="<".$key.">".$val."</".$key.">"; }else{ $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } } $xml.="</xml>"; return $xml; } /** * desc:生成随机字符串 */ public function getNonceStr($length = 32) { $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; $str =""; for ( $i = 0; $i < $length; $i++ ) { $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1); } return $str; } }
控制器方法
protected function makeToken($uid, $money)
{
$k = $uid . md5($money) . $uid;
$k = md5(sha1($k));
return $k;
}
function num_random($length = 6) {
$pool = '0123456789';
return substr(str_shuffle(str_repeat($pool, 5)), 0, $length);
}
$token = $this->makeToken($model->id, $money);
$data = ['id' => $model->id, 'money' => $money, 'app_token' => $token, 'notify_type' => 'device_notify'];
$data['type'] = 'appwx';
$wxset = config('wxapp');
$sign = base64_encode(json_encode($data));
$order = ['out_trade_no' => $user_info['id'] . time() . num_random(4),
'body' => '商品支付',
'total_fee' => $money * 100,
'notify_url' => $app_host . 'scan_doctor_app/notify_service/device_notify/' . $sign,
'appid' => $wxset['appid'],
'mch_id' => $wxset['mch_id'],
'attach' => '商品支付'
];
$Wxpay = new Wxpay();
$pay = $Wxpay->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; }