网站首页 文章专栏 微信支付流程(H5);退款

微信支付流程(H5);退款

编辑时间:2018-04-19 16:07:28 作者:苹果 浏览量:3302


    前言:引入微信SDK web端支付唤醒微信APP支付接口;微信退款接口 特别注意:同步和异步的返回均要验证数据库信息是否更改,避免重复处理操作


以下是几年前写的,原生写法,现已改进,融合了微信和支付宝的各种支付方式,调用方便。详见:《常用微信和支付宝支付方法》


function wxpayfromh5($name, $orderNo, $money) {

     $ip = '用户IP';//真实IP

     $nonce_str = $this->makePassword(32);//随机数

     $return_url = '同步回调地址';

     $notify_url = '异步回调地址';

     $scene_info = array(

     'h5_info' => array(

     'type' => 'Wap',

     'wap_url' => $_SERVER['HTTP_REFERER'],

     'wap_name' => $name,//描述

     ),

     );

     $arr = array(

     'nonce_str' => $nonce_str,

     'out_trade_no' => $orderNo,//订单号,微信的订单号只能一次性使用,不管支付成功与否均不允许第二次支付,建议每次生成新的订单号

     'total_fee' => $money,//支付金额,单位分

     'body' => $name,

     'ip' => $ip,

     'notify_url' => $notify_url,

     'trade_type' => 'MWEB',

     'scene_info' => json_encode($scene_info),

     );

     vendor('WxPay.WxPay#Api');

     vendor('WxPay.WxPay#NativePay');

    

     $notify = new \WxPayApi();

     $input = new \WxPayUnifiedOrder();

     $input->SetNonce_str($nonce_str); //随机字符串,不长于32位

     $input->SetBody($name); //设置商品或支付单简要描述

     $input->SetOut_trade_no($orderNo); //设置商户系统内部的订单号,32个字符内、可包含字母,

     $input->SetTotal_fee($money); //设置订单总金额,只能为整数,单位为分

     $input->SetSpbill_create_ip($ip); //必须传正确的用户端IP

     $input->SetNotify_url($notify_url); //设置接收微信支付异步通知回调地址

     $input->SetTrade_type("MWEB"); //设置trade_type H5支付的交易类型为MWEB

     $input->SetScene_info(json_encode($scene_info)); //场景信息

     $input->SetSign($arr); //签名

     $result = $notify->unifiedOrder($input);

     $this->siteLogsPay('微信H5支付处理结果:' . $orderNo . ':' . json_encode($result, JSON_UNESCAPED_UNICODE), date('Ymd', strtotime('now')), 'wxpay');//建议记录日志

     if ($result['result_code'] == 'SUCCESS') {

     //成功处理

     $url = $result['mweb_url'] . '&redirect_url=' . urldecode($return_url . '?token=' . $token);

     $this->assign('url', $url);

     $this->display('wxpayfromh5');//微信H5不会自动唤醒微信APP,需要用户前台确认,用返回的$result['mweb_url']去唤醒

     } else {

     //失败

     echo $result['err_code_des'];

     return false;

     }

}


wxpayfromh5 页面如下:

<a href="{$url}" class="btn btn-black-b">打开微信支付</a>


/**

* h5微信支付完成页面 同步返回不会显示支付的交易单号,需要用户前台确认,用订单号去查询交易信息

*/

 function h5wxreturn() {

$token = I('get.token', '');//token是中间参数,一般加密传递一些交易信息

if (!$token) {

return false;

}

$this->assign('token', $token);

$this->display('h5wxreturn');

}

h5wxreturn 页面如下:

<a href="支付成功地址h5wxsuccess.cgi?token={$token}">支付完成</a>

<br>

<a href="再次支付地址h5payagain.cgi?token={$token}">支付遇到问题,重新支付</a>


/**

* H5微信支付完成   微信H5支付完毕不会返回任何的支付信息,需要重新用订单号去查,而且还必须是前台提交

*/

function h5wxsuccess() {

     $token = I('get.token', '');

     $info = $token;//从token中解密出交易信息

     $orderno = $info['orderno'];

     if (!$orderno) {

     return false;

     }

     $old_orderno = $this->redis->get('wxoldorderno_' . trim($orderno));//从缓存中取出老的订单号 这步可省略(建议保留新老订单号数据)

     $this->h5wxorderquery($orderno, $old_orderno);//用订单号查询微信支付状态   $old_orderno可省略 建议将老订单号能够回传

}

/**

* h5微信查询  提供所有微信支付订单的查询

*/

private function h5wxorderquery($orderNo, $old_orderno = '') {

     $nonce_str = $this->makePassword(32);

    

     $arr = array(

     'nonce_str' => $nonce_str,

     'out_trade_no' => $orderNo,

     );

     vendor('WxPay.WxPay#Api');

     vendor('WxPay.WxPay#NativePay');

    

     $notify = new \WxPayApi();

     $input = new \WxPayOrderQuery();

     $input->SetNonce_str($nonce_str); //随机字符串,不长于32位

     $input->SetOut_trade_no($orderNo); //设置商户系统内部的订单号,32个字符内、可包含字母,

     $input->SetSign($arr); //签名

     $result = $notify->orderQuery($input);

     $this->siteLogsPay('微信H5支付查询结果:' . $orderNo . ':' . json_encode($result, JSON_UNESCAPED_UNICODE), date('Ymd', strtotime('now')), 'wxpay');//建议记录日志

     if ($result['result_code'] == 'SUCCESS' && $result['trade_state'] == 'SUCCESS') {

    //确认支付成功处理 可直接处理,建议将数据传到其他地方处理保证方法的可利用性

     $this->redis->rm('wxoldorderno_' . trim($orderNo));

     header("Location:" . $backurl .= "?token=" . $token);//

     } else {

     return false;

     }

}

/**

* H5微信再次提交

*/

public function h5payagain() {

     $token = I('get.token', '');

     $info =$token;//从token中解密出交易信息

     $orderno = $info['orderno'];

     $old_orderno = $this->redis->get('data_pay_wxoldorderno_' . trim($orderno));

     if (!$old_orderno) {

     return false;

     }

     $this->wxpayfromh5($info['name'], $orderno, $info['money']);//再次去支付

}


/**

*微信异步

*/

public function h5wxnotify() {

     ob_clean();

     $data = @file_get_contents('php://input');

     if ($data) {

     $data = $this->_xmldataparse($data);

     }

     $old_orderno = $this->redis->get('wxoldorderno_' . trim($data['out_trade_no']));

     $backurl = $this->redis->get('backurl_' . $old_orderno);

     if ($data['return_code'] == "SUCCESS" && $data['result_code'] == "SUCCESS") {

    //支付成功处理  建议在其他地方处理 如下,也可在这里直接处理

     $this->siteLogsPay('微信H5支付成功异步参数:' . json_encode($d, JSON_UNESCAPED_UNICODE), date('Ymd', strtotime('now')), 'wxpay');

     $d['selling'] = $data['total_fee'] / 100;

     $d['payno'] = $data['transaction_id'];

     $d['orderno'] = $data['out_trade_no'];

     $d['old_orderno'] = $old_orderno;

     //将接收到的数据加密token

     $url = $backurl . "?token=" . $token;

     $result = curlPost($url, $d);//建议在其他地方处理

     $status = json_decode($result)->status;//处理完毕后的响应

     if ($status != 200) {

     $return['return_code'] = "FAIL";

     } else {

     $return['return_code'] = "SUCCESS";

     $return['return_msg'] = "OK";

     $this->redis->rm('wxoldorderno_' . trim($data['out_trade_no']));

     }

     } else {

        //支付失败处理

     $this->siteLogsPay('微信回调支付失败!!', date('Ymd', strtotime('now')), 'wxpay');

     $return['return_code'] = "FAIL";

     }

     echo $this->ToXml($return);

}

//xml格式数据解析函数

private function _xmldataparse($data) {

     $msg = array();

     $msg = (array) simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);

     return $msg;

}


/**

*随机字符串

*/

private function makePassword($length = 32) {


     // 密码字符集,可任意添加你需要的字符

     $chars = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '@', '*');

    

     // 在 $chars 中随机取 $length 个数组元素键名

     $keys = array_rand($chars, $length);

     $password = '';

     for ($i = 0; $i < $length; $i++) {

     // 将 $length 个数组元素连接成字符串

     $password .= $chars[$keys[$i]];

     }

     return $password;

}

特别注意:同步和异步的返回均要验证数据库信息是否更改,避免重复处理操作



/**

*微信退款

*/

private function wxrefund($orderNo, $refund_no, $money, $refund_money) {

     $nonce_str = $this->makePassword(32);

     $arr = array(

     'nonce_str' => $nonce_str,

     'out_trade_no' => $orderNo,

     'out_refund_no' => $refund_no,

     'total_fee' => $money,

     'refund_fee' => $refund_money,

     );

    

     vendor('WxPay.WxPay#Api');

     vendor('WxPay.WxPay#NativePay');

     Vendor('phpqrcode.phpqrcode');

     //vendor('WxPay.WxPay#WxPay#Config');

     $notify = new \WxPayApi();

     $input = new \WxPayRefund();

     $input->SetOut_trade_no($orderNo); //设置商户系统内部的订单号,32个字符内、可包含字母,

     $input->SetTotal_fee($money); //设置订单总金额,只能为整数,单位为分

     $input->SetNonce_str($nonce_str); //随机字符串,不长于32位

     $input->SetOut_refund_no($refund_no); //商户退款单号

     $input->SetRefund_fee($refund_money); //退款总金额,订单总金额,单位为分,只能为整数

     $input->SetSign($arr);

     $input->SetOp_user_id('微信授权ID');

     $result = $notify->refund($input);

     $this->siteLogsPay('微信退款处理结果:' . $orderNo . ':' . json_encode($result, JSON_UNESCAPED_UNICODE), date('Ymd', strtotime('now')), 'userrefund');

     if ($result['result_code'] == 'SUCCESS') {

     $this->ajaxReturn(array('status' => 200));

     } else {

     $this->ajaxReturn(array('status' => -200));

     }


}



    出自:何冰华个人网站

    地址:https://www.hebinghua.com/

    转载请注明出处


来说两句吧
最新评论