后台代码:
<?php
/**
* 小程序支付接口
* User: Administrator
* Date: 2018/6/15 0015
* Time: 14:42
*/
class Shop_pay_mini extends Controllers
{
private $data = array(
'appid'=>'xxxx',
'mch_id'=>'xxxx',
'nonce_str'=>'',
'sign'=>'',
'body'=>'xxxx',
'out_trade_no'=>'',
'total_fee'=>'',
'spbill_create_ip'=>'',
'time_start'=>'',
'time_expire'=>'',
'notify_url'=>'http://xxx/phone/pay/Wxpay/api/notify.php',
'trade_type'=>'JSAPI',
'openid'=>''
);
private $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
private $key = '';
private $xmlData = '';
private $app_secret = '';
private $_new_notify_url = '';
private $_random_str = '';
private $session_key = '';
public $openId = '';
public $total_fee='';
public $pay_sn='';
public $user_id='';
public $nonce_str='';
public $random_str='';
public function __construct()
{
}
public function shop_pay(){
define('IS_MINI',1);
//记录表中
$random_str = get_random_str();
$pay_client=1;
$yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
$number=$yCode[intval(date('Y')) - 2018] . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
$data = [
'pay_sn'=>$this->pay_sn,
'add_time'=>time(),
'random_char'=>$random_str,
'pay_client'=>$pay_client,
'money_account'=>$this->total_fee,
'ip_address'=>$_SERVER['REMOTE_ADDR'],
'is_pay'=>0,
'user_id'=>$this->user_id
];
$option = [
'table'=>'assist_pay'
];
$list=M()->insert($data,$option);
unset($this->nonce_str,$this->random_str);
$this->nonce_str=$this->nonce_str();
$this->random_str=$random_str;
//生成订单
$this->data['time_start'] = date('YmdHis',time());
$this->data['notify_url'] = $this->_new_notify_url;
$this->data['out_trade_no'] =$this->random_str;
$this->data['total_fee'] = $this->total_fee;
$this->data['notify_url'] = 'http://www.e-hl.cc/phone/pay/Wxpay/api/notify_mini.php';
$this->data['nonce_str'] = $this->nonce_str;
$this->data['openid'] = $this->openId;
$this->data['sign'] = $this->_get_sign();
$this->xmlData = $this->_get_xml();
$this->_curl();
}
/**
* 小程序获取openid
*/
public function get_wx_openid(){
$this->user_id=$this->is_index();
$code = isset($_GET['code'])?$_GET['code']:$_POST['code'];
$this->pay_sn = isset($_GET['pay_sn'])?$_GET['pay_sn']:$_POST['pay_sn'];
$this->total_fee=isset($_POST['money'])?$_POST['money']*100:$_GET['money']*100;
$urls = 'https://api.weixin.qq.com/sns/jscode2session?appid=wx3670f6b94f08b57e&secret=dd8357c95ef1c8d1c5c7068eda56112e&js_code='.$code.'&grant_type=authorization_code';
$this->curl = new Lib\Curl();
$this->curl->setUrl($urls);
$return = $this->curl->execute(true);
$this->session_key = $return->session_key;
$this->openId = $return->openid;
$this->shop_pay();
}
private function _curl(){
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $this->url); //定义表单提交地址
curl_setopt($curl, CURLOPT_POST, 1); //定义提交类型 1:POST ;0:GET
curl_setopt($curl, CURLOPT_HEADER, 0); //定义是否显示状态头 1:显示 ; 0:不显示
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);//定义是否直接输出返回流
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_HTTPHEADER, 'Content-type: text/xml');
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_POSTFIELDS, $this->xmlData); //定义提交的数据,这里是XML文件
$returnData = curl_exec($curl);
curl_close($curl);
$returnData = $this->xmlstr_to_array($returnData);
if(!empty($returnData['err_code_des'])){
output_error('请按首次操作微信支付');
}
if($returnData['return_code'] == 'SUCCESS' && $returnData['result_code'] == 'SUCCESS'){
$time = time();
$tmp='';//临时数组用于签名
$tmp['appId'] = 'xxxx';
$tmp['nonceStr'] = $this->nonce_str;
$tmp['package'] = 'prepay_id='.$returnData['prepay_id'];
$tmp['signType'] = 'MD5';
$tmp['timeStamp'] = "$time";
$data['test']=$returnData;
$data['state'] = 200;
$data['timeStamp'] = "$time";//时间戳
$data['nonceStr'] = $this->nonce_str;//随机字符串
$data['signType'] = 'MD5';//签名算法,暂支持 MD5
$data['package'] = 'prepay_id='.$returnData['prepay_id'];//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
$data['paySign'] = $this->sign($tmp);//签名,具体签名方案参见微信公众号支付帮助文档;
$data['out_trade_no'] = $this->random_str;
}else{
$data['state'] = 0;
$data['text'] = "错误";
$data['RETURN_CODE'] = $returnData['RETURN_CODE'];
$data['RETURN_MSG'] = $returnData['RETURN_MSG'];
}
echo json_encode($data);
}
private function _get_xml(){
$xml = '<xml>';
foreach ($this->data as $key=>$val){
if (is_numeric($val)){
$xml.="<".$key.">".$val."</".$key.">";
}else{
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
}
$xml .= '</xml>';
return $xml;
}
private function xmlstr_to_array($xmlstr) {
$doc = new DOMDocument();
$doc->loadXML($xmlstr);
return $this->domnode_to_array($doc->documentElement);
}
private function domnode_to_array($node) {
$output = array();
switch ($node->nodeType) {
case XML_CDATA_SECTION_NODE:
case XML_TEXT_NODE:
$output = trim($node->textContent);
break;
case XML_ELEMENT_NODE:
for ($i=0, $m=$node->childNodes->length; $i<$m; $i++) {
$child = $node->childNodes->item($i);
$v = $this->domnode_to_array($child);
if(isset($child->tagName)) {
$t = $child->tagName;
if(!isset($output[$t])) {
$output[$t] = array();
}
$output[$t][] = $v;
}
elseif($v) {
$output = (string) $v;
}
}
if(is_array($output)) {
if($node->attributes->length) {
$a = array();
foreach($node->attributes as $attrName => $attrNode) {
$a[$attrName] = (string) $attrNode->value;
}
$output['@attributes'] = $a;
}
foreach ($output as $t => $v) {
if(is_array($v) && count($v)==1 && $t!='@attributes') {
$output[$t] = $v[0];
}
}
}
break;
}
return $output;
}
private function _get_sign(){
$temArr = array();
ksort($this->data);
foreach ($this->data as $k=>$v){
if(!empty($v)){
$temArr[] = $k.'='.$v;
}
}
$str = implode('&',$temArr).'&key='.$this->key;
return strtoupper(md5($str));
}
//随机32位字符串
private function nonce_str(){
$result = '';
$str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
for ($i=0;$i<32;$i++){
$result .= $str[rand(0,48)];
}
return $result;
}
//签名 $data要先排好顺序
private function sign($data){
$stringA = '';
foreach ($data as $key=>$value){
if(!$value) continue;
if($stringA) $stringA .= '&'.$key."=".$value;
else $stringA = $key."=".$value;
}
$wx_key = 'YinWenTao118YinWenTao118YinWenTa';//申请支付后有给予一个商户账号和密码,登陆后自己设置的key
$stringSignTemp = $stringA.'&key='.$wx_key;
return strtoupper(md5($stringSignTemp));
}
}
小程序js:
//下单成功,开始支付
// var code='';
// 登录
wx.login({
success: res => {
// code=res.code;
var that = this
com.POST({
url: 'Shop_pay_mini/get_wx_openid',
data: {
key: com.key,
code: res.code,
pay_sn: msg.data.datas.pay_sn,
money: msg.data.datas.end_price
},
success: function (msg) {
var paySign = msg.data.paySign;
var pack = msg.data.package;
var timeStamp = msg.data.timeStamp;
var nonceStr = msg.data.nonceStr;
wx.requestPayment({
'timeStamp': timeStamp ,
'nonceStr': nonceStr,
'package': pack ,
'signType': 'MD5',
'paySign': paySign,
'success': function (res) {
console.log(res);
},
'fail': function (res) {
console.log(res);
},
})
}
})
// 发送 res.code 到后台换取 openId, sessionKey, unionId
}
})
APP支付
//下单支付 private function _curl($url) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); //定义表单提交地址 curl_setopt($curl, CURLOPT_POST, 1); //定义提交类型 1:POST ;0:GET curl_setopt($curl, CURLOPT_HEADER, 0); //定义是否显示状态头 1:显示 ; 0:不显示 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);//定义是否直接输出返回流 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_HTTPHEADER, 'Content-type: text/xml'); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl, CURLOPT_POSTFIELDS, $this->xmlData); //定义提交的数据,这里是XML文件 $returnData = curl_exec($curl); curl_close($curl); $returnData = $this->xmlstr_to_array($returnData); if (!empty($returnData['err_code_des'])) { output_error('请按首次操作微信支付'); } $nonce = $this->nonce_str(); if ($returnData['return_code'] == 'SUCCESS' && $returnData['result_code'] == 'SUCCESS') { $time = time(); $tmp = [];//临时数组用于签名 $tmp['appid'] = $this->appid; $tmp['partnerid'] = $this->mch_id; $tmp['prepayid'] = $returnData['prepay_id']; $tmp['noncestr'] = $nonce; $tmp['package'] = 'Sign=WXPay'; $tmp['timestamp'] = "$time"; // $data['test'] = $returnData; $data['state'] = 200; $data['appid'] = $this->appid; $data['partnerid'] = $this->mch_id; $data['prepayid'] = $returnData['prepay_id']; $data['noncestr'] = $nonce;//随机字符串 $data['packages'] = 'Sign=WXPay';//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=* $data['timestamp'] = "$time";//时间戳 $data['sign'] = $this->_get_sign($tmp);//签名,具体签名方案参见微信公众号支付帮助文档; output_data($data); } else { $data['state'] = 0; $data['text'] = "错误"; $data['RETURN_CODE'] = $returnData['RETURN_CODE']; $data['RETURN_MSG'] = $returnData['RETURN_MSG']; output_errors($data); } }