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;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注