小程序支付
<?php
/**
* Created by PhpStorm.
* User: zb
* Date: 17-10-9
* Time: 下午7:15
*/
class PaysAction extends CommonAction
{
public function _initialize(){
parent::_initialize();
}
public function pay(){
$openid = trim($_POST['openid']);
$total_price = (float)$_POST['total_price'] * 100;//~~~~
$coupon_id = (int)$_POST['coupon_id'];
$coupon_price = (float)$_POST['coupon_price'] * 100;
$order_remark = trim($_POST['order_remark']);
$old_order_num = trim($_POST['order_num']);//有order_num,再来一单购买
if ($old_order_num == 'undefined'){
$old_order_num = '';
}
$product_id = (int)$_POST['product_id'];//有product_id,立即购买~~~~NaN,undefined在int转化后都为0;
if (!$openid){
$this->json->setErr(10000,'缺少参数');
$this->json->Send();
}
$user = M('user');
$tel_flag = $user->where(array('openid'=>$openid))->find();
if (!$tel_flag || !$tel_flag['id']){
$this->json->setErr(10001,'未绑定手机号');
$this->json->Send();
}
$uid = $tel_flag['id'];
if ($total_price <= 0){
$this->json->setErr(10002,'支付金额不可为0或负数');
$this->json->Send();
}
$order_info = $this->makeorder($old_order_num,$product_id,$openid,$uid,$total_price,$coupon_id,$coupon_price,$order_remark);
$order_num = $order_info['order_num'];
$products_name = $order_info['products_name'];
$unifiedorder = $this->unifiedorder($openid,$order_num,$total_price,$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;
$this->json->setAttr('data',$data);
$this->json->Send();
}
/*** 生成订单 优惠券处理
* @param $openid
* @param $uid
* @param $total_price
* @param $coupon_id user_coupon中的id字段,而非coupon_id字段
* @param $coupon_price 用户实际获取优惠额度,而非一定是表格中的price字段;
* @param $order_remark 用户提交订单的备注信息;
* @param $old_order_num 如有此参数,再来一单购买
* @param $product_id 立即购买方式
* @param order表格中的status字段 1未支付;2已支付;3已申请退款;4已退款;5已完成
* @return string
*/
private function makeorder($old_order_num='',$product_id=0,$openid,$uid,$total_price,$coupon_id,$coupon_price,$order_remark){
$order = M('order');
$now = time();
if ($old_order_num && !$product_id){
$order_num = 'os'.$uid.substr($now,3).rand(1000,9999); //生成12位以上订单号~~~~如果开头有os,表示从order_shoppingcar转变而来
$shoppingcar = M('order_shoppingcar');//~~~~
}elseif($product_id && !$old_order_num){
$order_num = 'qs'.$uid.substr($now,3).rand(1000,9999); //生成12位以上订单号~~~~如果开头有qs,表示从quickbuy_shoppingcar转变而来
$shoppingcar = M('quickbuy_shoppingcar');//~~~~
}else{
$order_num = $uid.substr($now,3).rand(1000,9999); //生成12位以上订单号
$shoppingcar = M('shoppingcar');//~~~~
}
$order_add_data = [
'order_num' => $order_num,
'uid' => $uid,
'coupon_id' => $coupon_id,
'coupon_price' => $coupon_price,
'total_price' => $total_price,//订单价格
'status' => 1,
'addtime' => $now,//订单生成时间
'remark' => $order_remark
];
$order_add_flag = $order->add($order_add_data);
// $sql = $order->getLastSql();
// $this->json->setAttr('sql',$sql);
// $this->json->Send();
if (!$order_add_flag){
$this->json->setErr(10003,'生成订单失败');
$this->json->Send();
}
$return_data['order_num'] = $order_num;
$map = array(
'openid' => $openid,
'pnum' => array('gt',0)
);
$shoppingcar_flag = $shoppingcar->where($map)->field('pid,pnum')->order('updatetime desc')->select();
$shoppingcar_count = count($shoppingcar_flag);
$product = M('product');
$order_product = M('order_product');
$products_name = '';
for ($i=0;$i<$shoppingcar_count;$i++){
$product_flag = $product->where(array('id'=>$shoppingcar_flag[$i]['pid']))->find();
//如果该产品已下架或删除,购物车数据中该产品要剔除
if ($product_flag['status'] == '0' || ($product_flag['is_del'] == '1')){
unset($shoppingcar_flag[$i]);
continue;
}
if (!$products_name){
$products_name .= $product_flag['title'];
}else{
$products_name .= '-'.$product_flag['title'];
}
$product_add_data = [
'order_id' => $order_add_flag,
'uid' => $uid,
'pid' => $shoppingcar_flag[$i]['pid'],
'pnum' => $shoppingcar_flag[$i]['pnum'],
'p_name' => $product_flag['title'],
'p_price' => $product_flag['price'],
'addtime' => $now
];
$product_add_flag = $order_product->add($product_add_data);
if (!$product_add_flag){
$this->json->setErr(10004,'订单产品数据添加失败');
$this->json->Send();
}
}
$return_data['products_name'] = $products_name;
return $return_data;
}
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;
}
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' => '****-附加数据',
//'detail' => '*****线上销售',
'out_trade_no' => $trade_no, //订单号
'fee_type' => 'CNY',
'total_fee' => $total_fee, //$total_fee, for test~~~
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
// 'time_start' => $this->getMillisecond(),
'goods_tag' => '******-商品标记',
'notify_url' => 'https://**************/api.php/Pays/order_notice',
'trade_type' => 'JSAPI',
'openid' => $openid
];
$sign = $this->MakeSign($data);
$data['sign'] = $sign;
$xml = $this->ToXml($data);
vendor('Func.Http');
$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);
$this->values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $this->values;
}
private function getMillisecond()
{
//获取毫秒的时间戳
$time = explode ( " ", microtime () );
$time = $time[1] . ($time[0] * 1000);
$time2 = explode( ".", $time );
$time = $time2[0];
return $time;
}
public function getSign(){
$appid = C('APPID');
$nocestr = $this->createNonceStr();
$timeStamp = time();
}
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 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'];
// 这句file_put_contents是用来查看服务器返回的XML数据 测试完可以删除了~~for test
// vendor('Func.Func');
// $hostname = 'http://'.Func::getHostName();
// $path = $hostname.'/static/log2.txt';
// file_put_contents($path,$xml);
//将服务器返回的XML数据转化为数组
//$data = self::xml2array($xml);
$data = $this->FromXml($xml);
// 保存微信服务器返回的签名sign
$data_sign = $data['sign'];
// sign不参与签名算法
unset($data['sign']);
//$sign = self::makeSign($data);
$sign = $this->makeSign($data);
// 判断签名是否正确 判断支付状态
if ( ($sign===$data_sign) && ($data['return_code']=='SUCCESS') && ($data['result_code']=='SUCCESS') ) {
$result = $data;
//获取服务器返回的数据
$order_num = $data['out_trade_no']; //订单单号
$openid = $data['openid']; //付款人openID
$total_fee = $data['total_fee']; //付款金额
$transaction_id = $data['transaction_id']; //微信支付流水号
$user = M('user');
$user_flag = $user->where(array('openid'=>$openid))->field('id')->find();
$uid = $user_flag['id'];
$save_data = array(
'total_payed_price' => $total_fee, //实际到帐金额
'transaction_id' => $transaction_id,
'paytime' => time(),
'status' => 2 //1未支付;2已支付;3已申请退款;4已退款;5已完成
);
$order = M('order');
$order_save_flag = $order->where(array('order_num'=>$order_num,'uid'=>$uid))->save($save_data);
//优惠券信息处理~~~~~发起订单还未必就支付~~~~~支付成功才处理
$order_coupon_flag = $order->where(array('order_num'=>$order_num,'uid'=>$uid))->field('coupon_id,id')->find();
$coupon_id = $order_coupon_flag['coupon_id'];
if ($coupon_id){
$user_coupon = M('user_coupon');
$coupon_save_data = array(
'is_use' => 1,
'oid' => $order_coupon_flag['id'], //~~~~order订单的id
'update_time' => time()
);
$user_coupon_save_flag = $user_coupon->where(array('id'=>$coupon_id))->save($coupon_save_data);
$user_coupon_find_flag = $user_coupon->where(array('id'=>$coupon_id))->field('coupon_id')->find();
if ($user_coupon_save_flag){
$coupon = M('coupon');
$coupon->where(array('id'=>$user_coupon_find_flag['coupon_id']))->setInc('used_number','+1');
}
}
//购物车信息清理
// 1.订单号数字开头,立即购买方式,清空shoppingcar;
// 2.订单号开头有sn,再来一单购买方式,清空order_shoppingcar(进入我的订单会清理),一定不要清理了shoppingcar
// 2.订单号开头有qn,立即购买方式,清空quickbuy_shoppingcar(立即购买触发时间前会清理),一定不要清理了shoppingcar
if (preg_match('/^(os)/',$order_num)){
$shoppingcar = M('order_shoppingcar');
}elseif(preg_match('/^(qs)/',$order_num)){
$shoppingcar = M('quickbuy_shoppingcar');
}else{
$shoppingcar = M('shoppingcar');
}
$clear_data['pnum'] = 0;
$shoppingcar->where(array('openid'=>$openid))->save($clear_data);
}else{
$result = false;
}
// 返回状态给微信服务器
if ($result) {
$str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
}else{
$str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>';
}
echo $str;
return $result;
}
}
go_to_pay: function (e) {
var that = this;
var coupon_id = parseInt(e.currentTarget.dataset.coupon_id);//user_coupon的id
var coupon_price = e.currentTarget.dataset.coupon_price;//实际优惠价格
var total_price = e.currentTarget.dataset.total_price;
var products_name = e.currentTarget.dataset.products_name;
var order_num = e.currentTarget.dataset.order_num;//可以'',undefined
var product_id = parseInt(e.currentTarget.dataset.product_id);//undefined转化int->NaN
var input_order_remark = that.data.input_order_remark;
wx.request({
url: 'https://**************.net/api.php/Pays/pay',
header: { 'content-type': 'application/x-www-form-urlencoded' },
data: {
openid: app.globalData.open_id,
total_price: total_price,
order_num: order_num,
product_id: product_id,
coupon_id: coupon_id,
coupon_price: coupon_price,
order_remark: input_order_remark,
},
method: 'POST', //注意header
success: function (res) {
if (res.errno) {
wx.showToast(res.errdesc);
return;
}
var datas = res.data;
//console.log(typeof datas.data.timeStamp);
wx.requestPayment({
'timeStamp': datas.data.timeStamp.toString(),
'nonceStr': datas.data.nonceStr,
'package': datas.data.package,
'signType': 'MD5',
'paySign': datas.data.sign,
'success': function (res) {
console.log('支付成功');
console.log(res);
//return;
},
'fail': function (res) {
console.log('支付失败');
//console.log(res);
return;
},
'complete': function (res) {
console.log('支付完成');
console.log(res);
if (res.errMsg == 'requestPayment:ok') {
wx.navigateTo({
url: '/pages/pay/pay_success?products_name=' + products_name
})
}
return;
}
});
// console.log(res.data);
}
})
},
相信坚持的力量,日复一日的习惯.

浙公网安备 33010602011771号