支付前准备工作:
* 申请小程序开发者账号 APP_ID
* 申请支付商户号 MCH_ID
* 获取商户秘钥 MCH_KEY
公共配置文件中,配置好参数值:
自定义统一下单方法:
/** * 首先在服务器端调用微信【统一下单】接口 * 返回prepay_id和sign签名等信息给前端,前端调用微信支付接口 * @param [type] $payFee 支付金额 * @param [type] $openid OPENID * @param [type] $orderNo 订单编号 * @author 凉笙墨染 2019-04-23 */ public function pay($payFee, $openid, $orderNo){ $appId = config('WX_APP_ID'); $mchId = config('MCH_ID'); $mchKey = config('MCH_KEY'); if ( empty($mchId) ) return [[], 0, '请配置微信支付商户号']; if ( empty($mchKey) ) return [[], 0, '请配置微信支付商户秘钥']; $nonceStr = pay_nonce_str(); $signParam = [ 'appid' => $appId, 'mch_id' => $mchId, 'nonce_str' => $nonceStr, 'body' => '小程序支付订单', 'out_trade_no' => $orderNo, 'total_fee' => intval($payFee), 'spbill_create_ip' => $_SERVER['SERVER_ADDR'], 'notify_url' => $this->request->domain().'/wxpaynotify', 'trade_type' => 'JSAPI', 'openid' => $openid, ]; // 获取支付签名 $signStr = pay_sign($signParam, $mchKey); $signParam['sign'] = $signStr; $xml = array_to_xml($signParam); /** * POST 发起请求 统一下单接口prepay_id * @var string * <xml> * <return_code><![CDATA[SUCCESS]]></return_code> * <return_msg><![CDATA[OK]]></return_msg> * <appid><![CDATA[wxb894baf67da7b043]]></appid> * <mch_id><![CDATA[1517273941]]></mch_id> * <nonce_str><![CDATA[MtwS7SGqRIBat6yT]]></nonce_str> * <sign><![CDATA[BA27C3FA17ED3BFCC2CFEA0CAC418F73]]></sign> * <result_code><![CDATA[SUCCESS]]></result_code> * <prepay_id><![CDATA[wx25162041735041e7f92689191844942960]]></prepay_id> * <trade_type><![CDATA[JSAPI]]></trade_type> * </xml> */ $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; $ret = curl_request($url, $xml); /** * { * APPID:"wxb894baf67da7b043", * MCH_ID: 1517273941, * NONCE_STR: "MtwS7SGqRIBat6yT", * PREPAY_ID: "wx25162041735041e7f92689191844942960", * RESULT_CODE:"SUCCESS", * RETRUN_CODE:"SUCCESS", * RETURN_MSG:"OK", * SIGN:"243872A3A46265CE6704879B203CE58A", * TRADE_TYPE:"JSAPI" * } */ $res = xml_to_array($ret); if ($res['RETURN_CODE'] == 'SUCCESS' && $res['RESULT_CODE'] == 'SUCCESS') { // 支付成功 $timeStamp = time(); // 参与签名参数: appId, nonceStr, package, signType, timeStamp $data = [ 'appId' => $res['APPID'], 'nonceStr' => $res['NONCE_STR'], 'package' => 'prepay_id='.$res['PREPAY_ID'], 'signType' => 'MD5', 'timeStamp' => $timeStamp ]; $res['TIMESTAMP']= (string)$timeStamp; // must be string $res['PACKAGE'] = 'prepay_id='.$res['PREPAY_ID']; $res['SIGNTYPE'] = 'MD5'; $res['PAYSIGN'] = pay_sign($data, $mchKey); // 其他参数 $res['ORDERNO']= $orderNo; } else { $res['CODE'] = 0; $res['RETURN_CODE'] = $res['RETURN_CODE']; $res['RETURN_MSG'] = $res['RETURN_MSG']; } return $res; }
公共函数:
① pay_nonce_str()
② pay_sign()
③ array_to_xml()
④ xml_to_array() 注:③④请查看PHP实现JSON字符串、数组和XML互相转换示例,解决小程序支付签名问题
⑤ curl_request() 注:请查看万能的CURL发起HTTP(GET/POST)请求
① 获取签名随机字符串:
/** * 为支付签名产生随机字符串 * @return [type] [description] * @author 凉笙墨染 2019-04-20 */ function pay_nonce_str(){ $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; $noceStr = ""; for($i = 0; $i < 32; $i++){ $noceStr .= $chars[ mt_rand(0, strlen($chars) - 1) ]; } return $noceStr; }
② 获取签名函数:
/** * 生成支付签名 * @param [type] $params 参数按照key=value的格式 并按照参数名ASCII字典序排序 * @param [type] $key 商户平台设置的密钥key * @author 凉笙墨染 2019-04-20 */ function pay_sign($params, $key){ //签名步骤一:按字典序排序数组参数 ksort($params); //签名步骤二:在string后加入KEY $params['key'] = $key; $string = ''; $array = array(); foreach( $params as $key => $value ){ $array[] = $key.'='.$value; } $string = implode("&",$array); //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $string = strtoupper($string); return $string; }
文章评论 (0)