• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

封装微信小程序支付

原作者: [db:作者] 来自: [db:来源] 收藏 邀请
<?php

/**
 * User: Eden
 * Date: 2019/3/21
 * 共有内容
 */
namespace Common\Service;
use Think\Exception;
use Vendor\Func\Http;

class WxPayService extends CommonService {
    public static function unifiedOrder($openid,$order_num,$total_fee,$products_name,$notify_url = \'\'){
        $trade_no = $order_num;
        $url = \'https://api.mch.weixin.qq.com/pay/unifiedorder\';
        $data = [
            \'appid\'             => C(\'APPID\'),
            \'mch_id\'            => C(\'MCHID\'),
            \'nonce_str\'         => self::createNonceStr(),
            \'sign_type\'         => \'MD5\',
            \'body\'              => $products_name,  //商品名称组合
            \'attach\'            => C(\'APP_NAME\').\'-附加信息\',
            \'out_trade_no\'      => $trade_no,       //订单号
            \'fee_type\'          => \'CNY\',
            \'total_fee\'         => $total_fee,
            \'spbill_create_ip\'  => $_SERVER[\'REMOTE_ADDR\'],
            \'goods_tag\'         => C(\'APP_NAME\').\'-商品标记\',
            \'notify_url\'        => $notify_url ?:C(\'NOTIFY_URL\'),
            \'trade_type\'        => \'JSAPI\',
            \'openid\'            => $openid
        ];

        $sign = self::MakeSign($data);
        $data[\'sign\'] = $sign;
        $xml = self::ToXml($data);
        $result = self::FromXml(Http::postXmlCurl($url,$xml));

        // 加工数据
        $data = [
            \'appId\' => $result[\'appid\'] ?: C(\'APPID\'),
            \'timeStamp\' => time(),
            \'nonceStr\' => self::createNonceStr(),
            \'package\' => \'prepay_id=\' . $result[\'prepay_id\'],
            \'signType\' => \'MD5\'
        ];
        $sign = self::MakeSign($data);
        $data[\'sign\'] = $sign;
        return $data;
    }


    public static function FromXml($xml)
    {
        if(!$xml){
            throw new Exception("xml数据异常!");
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $values = json_decode(json_encode(simplexml_load_string($xml, \'SimpleXMLElement\', LIBXML_NOCDATA)), true);
        return $values;
    }

    public static function ToXml($array){
        if(!is_array($array)|| count($array) <= 0){
            return ;
        }
        $xml = \'<xml version="1.0">\';
        foreach ($array as $key=>$val){
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
    }

    public static function createNonceStr($length = 16) {
        $chars = \'abcdefghijklmnopqrstuvwxyz0123456789\';
        $str = \'\';
        for ( $i = 0; $i < $length; $i++ )  {
            $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }

    public static function MakeSign($data)
    {
        //签名步骤一:按字典序排序参数
        ksort($data);
        $string = self::ToUrlParams($data);
        //签名步骤二:在string后加入KEY
        $string = $string . "&key=".C(\'WEIXIN_PAY_KEY\');
        //签名步骤三:MD5加密
        $string = md5($string);
        //签名步骤四:所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    public static function ToUrlParams($array)
    {
        $buff = "";
        foreach ($array as $k => $v)
        {
            if($k != "sign" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff;
    }
}
/***
 * 发起捐赠
 */
public function pay()
{
    if (!$openid = trim($_POST[\'openid\'])) {
        $this->json->setErr(10001, \'缺少参数\');
        $this->json->Send();
    }
    if (!$donate_id = $_POST[\'donate_id\']) {
        $this->json->setErr(10001, \'缺少参数donate_id\');
        $this->json->Send();
    }
    $amount = (float)$_POST[\'amount\']; // 实际支付金额
    if ($amount <= 0) {
        $this->json->setErr(10002, \'支付金额不可为0或负数\');
        $this->json->Send();
    }
    $donate = M(\'donate\');
    $donate_info = $donate->where(array(\'id\' => $donate_id, \'status\' => 1, \'is_show\' => 1))->find();
    if (!$donate_info) {
        $this->json->setErr(10002, \'捐赠内容不存在\');
        $this->json->Send();
    }

    // 判断当前是否可以捐赠
    $now = time();
    if ($now < (int)$donate_info[\'start_time\']) {
        $this->json->setErr(10003, \'捐赠未开始\');
        $this->json->Send();
    }

    if ($now > (int)$donate_info[\'end_time\']) {
        $this->json->setErr(10004, \'捐赠已结束\');
        $this->json->Send();
    }

    $money = $donate_info[\'money\']; // 已有捐赠金额
    $user = M(\'user\');
    $user_info = $user->where(array(\'openid\' => $openid))->find();
    if (!$user_info) {
        $this->json->setErr(10001, \'用户信息不存在\');
        $this->json->Send();
    }
    $uid = $user_info[\'id\'];

    // step1 生成订单
    $order_info = $this->makeOrder($uid, $donate_id, $amount, $money);
    $order_num = $order_info[\'order_num\'];
    $products_name = $order_info[\'products_name\'];

    // step2  unifiedOrder
    $unifiedorder = WxPayService::unifiedOrder($openid, $order_num, $amount * 100, $products_name);

    // step3 将数据package下放到小程序中
    $this->json->setAttr(\'data\', $unifiedorder);
    $this->json->Send();
}


/***
 * 生成捐赠订单
 * @param $uid
 * @param $donate_id
 * @param $amount
 * @param $money
 * @return mixed
 */
private function makeOrder($uid, $donate_id, $amount, $money)
{
    $donate_order = M(\'donate_order\');
    $now = time();
    $order_num = \'do\' . $uid . substr($now, 3) . rand(1000, 9999);
    $order_add_data = [
        \'donate_id\' => $donate_id,
        \'order_num\' => $order_num,
        \'amount\' => $amount,    //订单价格
        \'money\' => $money + $amount,
        \'uid\' => $uid,
        \'status\' => 1,               //未到账
        \'create_time\' => $now,            //订单生成时间
    ];
    $order_add_flag = $donate_order->add($order_add_data);
    if (!$order_add_flag) {
        $this->json->setErr(10003, \'生成订单失败\');
        $this->json->Send();
    }
    $return_data[\'order_num\'] = $order_num;
    $return_data[\'products_name\'] = \'捐赠\';
    return $return_data;
}


//微信支付回调
public function order_notice()
{
    $xml = $GLOBALS[\'HTTP_RAW_POST_DATA\'];
    $data = WxPayService::FromXml($xml);
    // 保存微信服务器返回的签名sign
    $data_sign = $data[\'sign\'];
    // sign不参与签名算法
    unset($data[\'sign\']);
    $sign = WxPayService::MakeSign($data);
    Clog::setLog($data, \'order_notice 回调数据\');
    // 判断签名是否正确  判断支付状态
    if (($sign === $data_sign) && ($data[\'return_code\'] == \'SUCCESS\') && ($data[\'result_code\'] == \'SUCCESS\')) {
        //获取服务器返回的数据
        $order_num = $data[\'out_trade_no\'];         //订单单号
        $openid = $data[\'openid\'];                  //付款人openID
        $total_fee = $data[\'total_fee\'];            //付款金额
        $transaction_id = $data[\'transaction_id\'];  //微信支付流水号
        $user = M(\'user\');
        $user_info = $user->where(array(\'openid\' => $openid))->find();
        $total_payed_price = $total_fee / 100;
        $save_data = array(
            \'total_payed_price\' => $total_payed_price,     //实际到帐金额
            \'transaction_id\' => $transaction_id,
            \'pay_time\' => time(),
            \'status\' => 2,
        );

        // 开启事务
        M()->startTrans();
        $error_count = 0;

        // step 1 修改充值订单数据
        $donate_order = M(\'donate_order\');
        $donate_order_info = $donate_order->where(array(\'order_num\' => $order_num, \'uid\' => $user_info[\'id\']))->find();
        $donate_amount = $donate_order_info[\'amount\'];
        $save_flag = $donate_order->where(array(\'order_num\' => $order_num, \'uid\' => $user_info[\'id\']))->save($save_data);
        if (!$save_flag) {
            $error_count++;
            Clog::setLog(\'修改订单失败\', \'order_notice 订单数据\');
        }

        // step 2 修改捐赠总数
        $donate = M(\'donate\');
        $donate_info = $donate->where([\'id\' => $donate_order_info[\'donate_id\']])->find();
        $save_donate_data = [
            \'money\' => $donate_info[\'money\'] + $donate_amount
        ];
        $money_save_flag = $donate->where([\'id\' => $donate_order_info[\'donate_id\']])->save($save_donate_data);
        if (!$money_save_flag) {
            $error_count++;
            Clog::setLog(\'修改捐赠总数失败\', \'order_notice 捐款数据\');
        }

        // step 3 处理configs中的统计信息
        $configService = new ConfigService();
        $key = [\'key\' => [\'in\', [\'total_donate\', \'total_help\', \'total_join\']]];
        $total_data = $configService->queryKey($key);
        $edit_donate = $configService->updateOneKey(\'total_donate\',$total_data[\'total_donate\']+$total_payed_price);
        if (!$edit_donate && $edit_donate !== 0) {
            $error_count ++;
        }
        if ((float)$donate_info[\'money\'] === 0.00) {
            // 第一次被帮助
            $edit_help = $configService->updateOneKey(\'total_help\',$total_data[\'total_help\']+1);
            if (!$edit_help && $edit_help !== 0) {
                $error_count ++;
            }
        }

        $save_join = $configService->updateOneKey(\'total_join\',$total_data[\'total_join\']+1);
        if (!$save_join && $save_join !== 0) {
            $error_count ++;
        }

        if ($error_count > 0) {
            Clog::setLog(\'回滚了\', \'order_notice\');
            M()->rollback();
            $result = -2;
        } else {
            Clog::setLog(\'commit了\', \'order_notice\');
            M()->commit();
            $result = 0;
        }
    } else {
        Clog::setLog(\'签名有误\', \'order_notice\');
        $result = -1;
    }
    Clog::setLog($result, \'order_notice\');
    // 返回状态给微信服务器
    $str = \'\';
    if ($result === 0) { // 成功之后不会再回调
        $str = \'<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>\';
    } elseif ($result === -1) { // 失败后会继续发送几次回调
        $str = \'<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>\';
    } elseif ($result === -2) { // 失败后会继续发送几次回调
        $str = \'<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[操作失败]]></return_msg></xml>\';
    }
    exit($str);
}

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
微信小程序家庭记账本开发进度七发布时间:2022-07-18
下一篇:
微信小程序遍历wx:for,wx:for-item,wx:key发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap