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的操作。
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 = ''; foreach ($array as $key=>$val){ if (is_numeric($val)){ $xml.="<".$key.">".$val." "; }else{ $xml.="<".$key."> "; } } $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=''; } elseif ($result === -1){ // 失败后会继续发送几次回调 $str=' '; } elseif ($result === -2) { // 失败后会继续发送几次回调 $str=' '; } exit($str); }}