下单
public function unifyPay(){
$param = (I('get.'));
if(!$param['member_id'] || !$param['order_sn']){
return json_encode(['code'=>201,'message'=>'缺少参数']);
}
$data = [];
$paydata = [];
$unifydata = [];
$orderinfo = Db::name('order')->where(['order_sn'=>$param['order_sn'],'user_id'=>$param['member_id']])->find();
if(empty($orderinfo)){
return json_encode(['code'=>201,'message'=>'订单不存在']);
}
$userinfo = Db::name('users')->where(['user_id'=>$param['member_id']])->find();
if(empty($userinfo)){
return json_encode(['code'=>201,'message'=>'用户不存在']);
}
$config = Db::name('config')->where('name','site_url')->find();
$wechatconf = config('wechat');
//这个数组里所有的数据都是必填的
$unifydata = [
'appid' => $wechatconf['appid'],//appid
'mch_id' => $wechatconf['mchid'],//商户id
'nonce_str' => md5(rand(100000,999999)),//随机字符串
'body' => '商品',
'out_trade_no' => $param['order_sn'],//订单号
// 'total_fee' => bcmul((string)$orderinfo['order_amount'], '100',0),
'total_fee' => bcmul(0.01, '100',0),//金额
'spbill_create_ip' => $_SERVER["REMOTE_ADDR"],
'notify_url' => $config['value'].'/index.php/mobile/Pay/notify',//回调地址
'trade_type' => 'JSAPI',
'openid' => $userinfo['openid'],
];
$this->closeorder($unifydata);//关闭以前的订单,当前项目需要,可以不加
// 'total_fee' => bcmul((string)$orderinfo['order_amount'], '100'),
// 'key' => $wechatconf['pay_key'], // API 密钥
// 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
// 'cert_path' => '', // XXX: 绝对路径!!!!
// 'key_path' => '', // XXX: 绝对路径!!!!
$this->pay_key = $wechatconf['sign'];//32位签名
$orderResult = $this->create_pay_order($unifydata);创建订单
$timeStamp = time();
$paydata = [
'appId' => $wechatconf['appid'],
'timeStamp' => "$timeStamp",
'nonceStr' => md5(rand(100000,999999)),
'package' => 'prepay_id=' . $orderResult['prepay_id'],
'signType' => 'MD5'
];
$sign = $this->getSign($paydata);//给小程序生成验证签名
$paydata['paySign'] = $sign;
$data = ['code'=>0,'message'=>'统一下单成功','data'=>$paydata];
return json_encode($data);
}
POST 调用API
public function post_data($url,$data=[]){
$ch = curl_init ();
// print_r($ch);
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_POST, 1 );
curl_setopt ( $ch, CURLOPT_HEADER, 0 );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data );
$return = curl_exec ( $ch );
curl_close ( $ch );
return $return;
}
获取签名
protected function getSign($data) {
ksort($data);
$tmpstr = $this->arrToTempStr($data);
$tmpSign = $tmpstr . '&key=' . $this->pay_key;
$sign = strtoupper(md5($tmpSign));
return $sign;
}
数组转签名字符串
private function arrToTempStr($arr) {
$str = '';
foreach ($arr as $key => $value) {
$str .= $key . '=' . $value . '&';
}
return substr($str,0,-1);
}
数组转微信XML
protected function arrayToXml($arr) {
$xml = "<xml>";
foreach ($arr as $key=>$val) {
if ($key == 'detail') {
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
} else {
$xml.="<".$key.">".$val."</".$key.">";
}
}
$xml.="</xml>";
return $xml;
}
解析XML
protected function analyze_xml($xml) {
$dom = new DOMDocument();
$dom->loadXML($xml);
$node = $dom->documentElement;
$array = $this->getArray($node);
return $array;
}
解析XML 转数组
private function getArray($node) {
$array = false;
if ($node->hasAttributes()) {
foreach ($node->attributes as $attr) {
$array[$attr->nodeName] = $attr->nodeValue;
}
}
if ($node->hasChildNodes()) {
if ($node->childNodes->length == 1) {
$array[$node->firstChild->nodeName] = $this->getArray($node->firstChild);
} else {
foreach ($node->childNodes as $childNode) {
if ($childNode->nodeType != XML_TEXT_NODE) {
$array[$childNode->nodeName][] = $this->getArray($childNode);
}
}
}
} else {
return $node->nodeValue;
}
return $array;
}
关闭订单
public function closeorder($order){
$apiparams=[
'appid'=>$order['appid'],
'mch_id'=>$order['mch_id'],
'out_trade_no'=>$order['out_trade_no'],
'nonce_str'=>$order['nonce_str'],
];
$apiparams['sign']=$this->getSign($apiparams);
$apiparams = $this->arrayToXml($apiparams);
$this->post_data('https://api.mch.weixin.qq.com/pay/closeorder',$apiparams);
return true;
}
封装微信支付订单 下单数据
private function create_pay_order($inputData) {
$return = array();
$inputData['sign'] = $this->getSign($inputData);
$inputData = $this->arrayToXml($inputData);
$result = $this->post_data('https://api.mch.weixin.qq.com/pay/unifiedorder',$inputData);
$result = $this->analyze_xml($result);
$return['return_code'] = isset($result['return_code']['0']['#cdata-section'])?$result['return_code']['0']['#cdata-section']:'';
$return['return_msg'] = isset($result['return_msg']['0']['#cdata-section'])?$result['return_msg']['0']['#cdata-section']:'';
$return['appid'] = isset($result['app_id']['0']['#cdata-section'])?$result['app_id']['0']['#cdata-section']:'';
$return['mchid'] = isset($result['mch_id']['0']['#cdata-section'])?$result['mch_id']['0']['#cdata-section']:'';
$return['nonce_str'] = isset($result['nonce_str']['0']['#cdata-section'])?$result['nonce_str']['0']['#cdata-section']:'';
$return['sign'] = isset($result['sign']['0']['#cdata-section'])?$result['sign']['0']['#cdata-section']:'';
$return['result_code'] = isset($result['result_code']['0']['#cdata-section'])?$result['result_code']['0']['#cdata-section']:'';
$return['prepay_id'] = isset($result['prepay_id']['0']['#cdata-section'])?$result['prepay_id']['0']['#cdata-section']:'';
$return['trade_type'] = isset($result['trade_type']['0']['#cdata-section'])?$result['trade_type']['0']['#cdata-section']:'';;
return $return;
}
支付回调
public function notify(){
$testxml = file_get_contents("php://input");
$jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA));
$result = json_decode($jsonxml, true);//转成数组,
$wechatconf = config('wechat');
if($result){
//如果成功返回了
if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){
if($result['sign'] == $wechatconf['sign'] && $result['appid'] == $wechatconf['appid']){
Db::name('service_order')->where('orderno',$result['out_trade_no'])->update([
'pay_state'=>1,
'trade_no'=>$result['transaction_id'],
'pay_time'=>time()
]);
}
}
}
}