jiqing9006
add_balance: function() {
  var that = this;
  var total_payed_price = this.data.recharge;
  var rc_id = this.data.rc_id;
  getData.getData(\'rechargePay\', {
    openid: app.globalData.openid,
    total_payed_price: total_payed_price,
    rc_id: rc_id,
    method: \'POST\'
  }, function(res) {
    if (res.errno) {
      wx.showToast({
        title: res.errdesc
      });
      return;
    }
    var data = res.data;
    wx.requestPayment({
      \'timeStamp\': data.timeStamp.toString(),
      \'nonceStr\': data.nonceStr,
      \'package\': data.package,
      \'signType\': \'MD5\',
      \'paySign\': data.sign,
      \'success\': function(res) {
        console.log(\'支付成功\');
      },
      \'fail\': function(res) {
        console.log(\'支付失败\');
        return;
      },
      \'complete\': function(res) {
        console.log(\'支付完成\');
        console.log(res);
        var url = that.data.url;
        console.log(\'get url\', url);
        if (res.errMsg == \'requestPayment:ok\') {
          wx.showModal({
            title: \'提示\',
            content: \'充值成功\'
          });
          if (url) {
            setTimeout(function() {
              // 直接跳转,当前页面出栈
              wx.redirectTo({
                url: \'/pages\' + url
              });
            }, 2000)
          } else {
            setTimeout(() => {
              wx.navigateBack()
            }, 2000)
          }
        }
        return;
      }
    });

  })
}

上述是小程序端的操作。

下面是php的操作。

<?php

namespace Api\Action;


use Vendor\Func\Http;

/**
 * 充值相关接口
 */
class RechargeAction extends CommonAction
{
    /**
     * 获取充值项
     */
    public function get_recharge_config(){
        $recharge_config = M(\'recharge_config\');
        $recharge_config_list = $recharge_config->where(array(\'status\'=>1,\'is_show\'=>1))->field(\'id,recharge,amount\')->select();

        $this->json->setAttr(\'data\',$recharge_config_list);
        $this->json->Send();
    }

    /***
     * 余额充值微信支付
     */
    public function pay(){
        if (!$openid = trim($_POST[\'openid\'])){
            $this->json->setErr(10001,\'缺少参数\');
            $this->json->Send();
        }
        if(!$rc_id = $_POST[\'rc_id\']){
            $this->json->setErr(10001,\'没有余额充值id\');
            $this->json->Send();
        }
        $total_payed_price = (float)$_POST[\'total_payed_price\']; // 实际支付金额
        if ($total_payed_price <= 0){
            $this->json->setErr(10002,\'支付金额不可为0或负数\');
            $this->json->Send();
        }
        $recharge_config = M(\'recharge_config\');
        $recharge_flag = $recharge_config->where(array(\'id\'=>$rc_id,\'status\'=>1,\'is_show\'=>1))->find();
        if (!$recharge_config) {
            $this->json->setErr(10002,\'充值项不存在\');
            $this->json->Send();
        }

        $money_amount = $recharge_flag[\'amount\']; // 应到账金额
        $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\'];

        $user_balance = $user_info[\'balance\'];
        // step1 生成订单
        $order_info = $this->makeorder($uid,$total_payed_price,$money_amount,$user_balance);
        $order_num = $order_info[\'order_num\'];
        $products_name = $order_info[\'products_name\'];

        // step2  unifiedorder
        $unifiedorder = $this->unifiedorder($openid,$order_num,$total_payed_price*100,$products_name);
        $data = [
            \'appId\'     => C(\'APPID\'),
            \'timeStamp\' => time(),
            \'nonceStr\'  => $this->createNonceStr(),
            \'package\'   => \'prepay_id=\'.$unifiedorder[\'prepay_id\'],
            \'signType\'  => \'MD5\'
        ];
        $sign = $this->MakeSign($data);
        $data[\'sign\'] = $sign;

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


    /***
     * 生成充值订单
     */
    private function makeorder($uid,$total_payed_price,$money_amount,$user_balance){
        $recharge_order = M(\'recharge_order\');
        $now = time();
        $order_num = \'cz\'.$uid.substr($now,3).rand(1000,9999);
        $order_add_data = [
            \'order_num\'          =>  $order_num,
            \'amount\'             =>  $money_amount,    //订单价格
            \'balance\'            =>  ($user_balance+$money_amount),
            \'uid\'                =>  $uid,
            \'status\'             =>  1,               //未到账
            \'total_payed_price\'  =>  $total_payed_price,
            \'create_time\'        =>  $now,            //订单生成时间
        ];
        $order_add_flag = $recharge_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 unifiedorder($openid,$order_num,$total_fee,$products_name){
        $trade_no = $order_num;
        $url = \'https://api.mch.weixin.qq.com/pay/unifiedorder\';
        $data = [
            \'appid\'             => C(\'APPID\'),
            \'mch_id\'            => C(\'MCHID\'),
            \'nonce_str\'         => $this->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\'        => C(\'RECHARGE_URL\'),
            \'trade_type\'        => \'JSAPI\',
            \'openid\'            => $openid
        ];


        $sign = $this->MakeSign($data);
        $data[\'sign\'] = $sign;
        $xml = $this->ToXml($data);
        $result = $this->FromXml(Http::postXmlCurl($url,$xml));
        return $result;
    }

    public function FromXml($xml)
    {
        if(!$xml){
            throw new WxPayException("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 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;
    }

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

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

    private 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 order_notice(){
        $xml = $GLOBALS[\'HTTP_RAW_POST_DATA\'];
        $data = $this->FromXml($xml);
        // 保存微信服务器返回的签名sign
        $data_sign = $data[\'sign\'];
        // sign不参与签名算法
        unset($data[\'sign\']);
        $sign = $this->MakeSign($data);
        // 判断签名是否正确  判断支付状态
        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();
            $save_data = array(
                \'total_payed_price\' =>  $total_fee/100,     //实际到帐金额
                \'transaction_id\'    =>  $transaction_id,
                \'pay_time\'          =>  time(),
                \'status\'            =>  2,
            );

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

            // step 1 修改充值订单数据
            $recharge_order = M(\'recharge_order\');
            $recharge_order_info = $recharge_order->where(array(\'order_num\'=>$order_num,\'uid\'=>$user_info[\'id\']))->find();
            $recharge_amount= $recharge_order_info[\'amount\'];
            $recharge_save_flag = $recharge_order->where(array(\'order_num\'=>$order_num,\'uid\'=>$user_info[\'id\']))->save($save_data);
            if(!$recharge_save_flag){
                $error_count++;
            }

            // step 2 修改充值订单数据
            $save_balance = $user_info[\'balance\']+$recharge_amount;
            $balance_save_flag = $user->where(array(\'openid\'=>$openid))->save([\'balance\'=>$save_balance]);
            if (!$balance_save_flag) {
                $error_count++;
            }

            // step 3 增加充值记录
            $balance_record = M(\'balance_record\');
            $balance_record_data = [
                \'uid\' => $user_info[\'id\'],
                \'amount\' => $recharge_amount,
                \'balance\' => $save_balance,
                \'type\' => 1, // 增加
                \'from\' => 1, // 充值
                \'remark\' => \'余额充值\', // 充值
                \'create_time\' => time(),
            ];

            $add_flag = $balance_record->add($balance_record_data);
            if (!$add_flag) {
                $error_count ++;
            }

            if ($error_count > 0) {
                M()->rollback();
                $result = -2;
            } else {
                M()->commit();
                $result = 0;
            }
        }else{
            $result = -1;
        }
        // 返回状态给微信服务器
        $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);
    }


}

分类:

技术点:

相关文章: