一:小程序充值列表wxml代码
<view class="charge_rule_list fl {{current_id==item.id?'active':''}}" wx:for="{{charge_rules}}" wx:for-item="item" data-id="{{item.id}}" data-coin="{{item.coin}}" data-money="{{item.money}}" data-give="{{item.give}}" bindtap="selectItem">
<view class="charge_rule_center">
<view class="coin">{{item.coin}}
<image src="../image/coin.png"></image>
</view>
<view class="money">¥{{item.money}}</view>
</view>
<view class="give" wx:if="{{item.give>0}}">
赠送{{item.give}}{{name_coin}}
<image src="../image/my/wallet/give.png"></image>
</view>
</view>
二:小程序点击充值金额请求接口生成支付订单js代码
//选择充值类别
selectItem:function(options){
var _this = this;
var app=getApp();
var id = options.currentTarget.dataset.id;
if(id==_this.data.current_id){
return;
}
var coin=options.currentTarget.dataset.coin;
var money=options.currentTarget.dataset.money;
//设置当前样式
_this.setData({
'current_id': id
});
//获取缓存里的openid
var openid=wx.getStorageSync("openid");
if(!openid){
//调用微信登录获取openid(因为小程序支付openid为必传值)
wx.login({
success(res){
var code=res.code;
//console.log("code:"+code);
var methodName='Login.getUnionid';
var data={"code":code};
util.requestData(methodName,data,function(code,msg,info){
//console.log(info);
openid=info[0].openid;
app.globalData.openid=info[0].openid;
//将openid存入缓存
wx.setStorageSync('openid',openid);
_this.wxMiniPay(id,coin,money,openid);
});
}
})
}else{
_this.wxMiniPay(id,coin,money,openid);
}
},
//微信小程序支付
wxMiniPay:function(chargeid,coin,money,openid){
//调用接口生成微信小程序订单
var _this=this;
var methodName="Charge.getWxMiniOrder"; //接口名称
var app=getApp();
var userinfo=app.globalData.userinfo;
var data={
"uid":userinfo.id,
"chargeid":chargeid,
"coin":coin,
"money":money,
"openid":openid
};
util.requestData(methodName,data,function(code,msg,info){
//console.log(info);
var timeStamp=info[0].timeStamp.toString(); //注意要转为字符串,不然程序报错
var nonceStr=info[0].nonceStr;
var package_str=info[0].package;
var signType=info[0].signType;
var paySign=info[0].sign;
//小程序调起支付API
wx.requestPayment(
{
'timeStamp': timeStamp,
'nonceStr': nonceStr,
'package': package_str,
'signType': signType,
'paySign': paySign,
'success':function(res){
//console.log("支付成功");
setTimeout(function(){
_this.setData({
'current_id':0
});
_this.reLoad();
},2000);
},
'fail':function(res){
// console.log("支付失败");
// console.log(res);
wx.showToast({
title: "发起支付失败",
icon: 'none',
duration: 2000
});
},
'complete':function(res){
}
});
});
},
三:接口【php代码】:
//获取微信小程序登录用的unionid接口的参数列表及说明
'getUnionid' => array(
'code' => array('name' => 'code', 'type' => 'string','desc' => '微信code'),
),
/**
* 获取微信登录unionid
* @desc 用于获取微信登录unionid
* @return int code 操作码,0表示成功,2发送失败
* @return array info
* @return string info[0].unionid 微信unionid
* @return string msg 提示信息
*/
public function getUnionid(){
$rs = array('code' => 0, 'msg' => '', 'info' => array());
$code=$this->code;
if($code==''){
$rs['code']=1001;
$rs['msg']='参数错误';
return $rs;
}
$AppID = ''; //替换为自己的微信小程序appid
$AppSecret = ''; //替换为自己的微信小程序secret
/* 获取token */
//$url="https://api.weixin.qq.com/sns/oauth2/access_token?appid={$AppID}&secret={$AppSecret}&code={$code}&grant_type=authorization_code";
$url="https://api.weixin.qq.com/sns/jscode2session?appid={$AppID}&secret={$AppSecret}&js_code={$code}&grant_type=authorization_code";
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_URL, $url);
$json = curl_exec($ch);
curl_close($ch);
$arr=json_decode($json,1);
//file_put_contents('./getUnionid.txt',date('Y-m-d H:i:s').' 提交参数信息 code:'.json_encode($code)."\r\n",FILE_APPEND);
//file_put_contents('./getUnionid.txt',date('Y-m-d H:i:s').' 提交参数信息 arr:'.json_encode($arr)."\r\n",FILE_APPEND);
if($arr['errcode']){
$rs['code']=1003;
$rs['msg']='配置错误';
//file_put_contents('./getUnionid.txt',date('Y-m-d H:i:s').' 提交参数信息 arr:'.json_encode($arr)."\r\n",FILE_APPEND);
return $rs;
}
/* 小程序 绑定到 开放平台 才有 unionid 否则 用 openid */
$unionid=$arr['unionid'];
if(!$unionid){
//$rs['code']=1002;
//$rs['msg']='公众号未绑定到开放平台';
//return $rs;
$unionid=$arr['openid'];
}
$rs['info'][0]['unionid'] = $unionid;
$rs['info'][0]['openid'] = $arr['openid'];
return $rs;
}
//生成微信小程序支付的订单接口参数列表及说明
'getWxMiniOrder' => array(
'uid' => array('name' => 'uid', 'type' => 'int', 'min' => 1, 'require' => true, 'desc' => '用户ID'),
'chargeid' => array('name' => 'chargeid', 'type' => 'string', 'require' => true, 'desc' => '充值规则ID'),
'coin' => array('name' => 'coin', 'type' => 'string', 'require' => true, 'desc' => '钻石'),
'money' => array('name' => 'money', 'type' => 'string', 'require' => true, 'desc' => '充值金额'),
'openid' => array('name' => 'openid', 'type' => 'string', 'require' => true, 'desc' => '用户在商户appid下的唯一标识'),
),
/**
* 微信小程序支付生成支付订单并获取订单号
* @desc 用于 微信小程序支付 获取订单号
* @return int code 操作码,0表示成功
* @return array info
* @return string info[0] 支付信息
* @return string msg 提示信息
*/
public function getWxMiniOrder() {
$rs = array('code' => 0, 'msg' => '', 'info' => array());
$uid = $this->uid;
$chargeid = $this->chargeid;
$coin = $this->coin;
$money = $this->money;
$openid = $this->openid;
$orderid=$this->getOrderid($uid);
$type=4;
if($coin==0){
$rs['code']=1002;
$rs['msg']='信息错误';
return $rs;
}
$wx_mini_appid = ''; //填写自己的微信小程序appid
$wx_mini_mchid = ''; //微信小程序绑定的商户号
$wx_mini_key = ''; //微信小程序支付密钥
//配置参数检测
if($wx_mini_appid== "" || $wx_mini_mchid== "" || $wx_mini_key== ""){
$rs['code'] = 1002;
$rs['msg'] = '微信小程序支付未配置';
return $rs;
}
if(!$openid){
$rs['code'] = 1002;
$rs['msg'] = '缺少必要参数openid';
return $rs;
}
$orderinfo=array(
"uid" => $uid,
"touid" => $uid,
"money" => $money,
"coin" => $coin,
"orderno"=> $orderid,
"type" => $type,
"status" => 0,
"addtime"=> time()
);
$info = $this->getOrderId($chargeid,$orderinfo);
if($info==1003){
$rs['code']=1003;
$rs['msg']='订单信息有误,请重新提交';
return $rs;
}else if(!$info){
$rs['code']=1001;
$rs['msg']='订单生成失败';
return $rs;
}
$noceStr = md5(rand(100,1000).time());//获取随机字符串
$time = time();
$paramarr = array(
"appid" => $wx_mini_appid,
"body" => "充值虚拟币",
"mch_id" => $wx_mini_mchid,
"nonce_str" => $noceStr,
"notify_url" => '域名/IP'.'/Appapi/pay/notify_wx_mini',
"openid" => $openid,
"out_trade_no" => $orderid,
"spbill_create_ip"=> $_SERVER["REMOTE_ADDR"],
"total_fee" => $money*100,
"trade_type" => "JSAPI"
);
$sign = $this -> sign($paramarr,$wx_mini_key);//生成签名
$paramarr['sign'] = $sign;
$paramXml = "<xml>";
foreach($paramarr as $k => $v){
$paramXml .= "<" . $k . ">" . $v . "</" . $k . ">";
}
$paramXml .= "</xml>";
$ch = curl_init ();
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //跳过证书检查
@curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true); //从证书中检查SSL加密算法是否存在
@curl_setopt($ch, CURLOPT_URL, "https://api.mch.weixin.qq.com/pay/unifiedorder");
@curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@curl_setopt($ch, CURLOPT_POST, 1);
@curl_setopt($ch, CURLOPT_POSTFIELDS, $paramXml);
@$resultXmlStr = curl_exec($ch);
if(curl_errno($ch)){
//print curl_error($ch);
file_put_contents('./wx_mini_pay.txt',date('y-m-d H:i:s').' 提交参数信息 ch:'.json_encode(curl_error($ch))."\r\n",FILE_APPEND);
}
curl_close($ch);
$result2 = $this->xmlToArray($resultXmlStr);
if($result2['return_code']=='FAIL'){
$rs['code']=1005;
$rs['msg']=$result2['return_msg'];
return $rs;
}
$time2 = time();
$prepayid = $result2['prepay_id'];
$sign = "";
$noceStr = md5(rand(100,1000).time());//获取随机字符串
//注意参数大小写
$paramarr2 = array(
"appId" => $wx_mini_appid,
"timeStamp" => $time2,
"nonceStr" => $noceStr,
"package" => "prepay_id=".$prepayid,
"signType" => "MD5"
);
$paramarr2["sign"] = $this -> sign($paramarr2,$wx_mini_key);//生成签名
$rs['info'][0]=$paramarr2;
return $rs;
}
//生成订单编号
public function getOrderId($changeid,$orderinfo) {
$charge=DI()->notorm->charge_rules->select('*')->where('id=?',$changeid)->fetchOne();
if(!$charge || $charge['money']!=$orderinfo['money'] || ($charge['coin']!=$orderinfo['coin'] && $charge['coin_ios']!=$orderinfo['coin'] )){
return 1003;
}
$orderinfo['coin_give']=$charge['give'];
$result= DI()->notorm->charge_user->insert($orderinfo);
return $result;
}
/**
* sign拼装获取
*/
protected function sign($param,$key){
$sign = "";
ksort($param);
foreach($param as $k => $v){
$sign .= $k."=".$v."&";
}
$sign .= "key=".$key;
$sign = strtoupper(md5($sign));
return $sign;
}
四:异步回调地址【php】
//微信小程序支付异步回调
private $wxMiniDate = null;
public function notify_wx_mini(){
$xmlInfo=file_get_contents("php://input");
//解析xml
$arrayInfo = $this -> xmlToArray($xmlInfo);
$this -> wxMiniDate = $arrayInfo;
$this -> logwx_mini("wxmini_data:".json_encode($arrayInfo));//log打印保存
if($arrayInfo['return_code'] == "SUCCESS"){
$wxSign = $arrayInfo['sign']; //支付返回的签名
unset($arrayInfo['sign']);
$arrayInfo['appid'] = ''; //替换为自己的微信小程序appid
$arrayInfo['mch_id'] = ''; //替换为自己的微信小程序绑定的商户号
$key = $config['wx_mini_key'];
ksort($arrayInfo);//按照字典排序参数数组
$sign = $this -> sign($arrayInfo,$key);//生成签名
$this -> logwx_mini("数据打印对比签名signmy:".$sign.":::微信sign:".$wxSign);//log打印保存
if($this -> checkSign($wxSign,$sign)){
echo $this -> returnInfo("SUCCESS","OK");
$this -> logwx_mini("签名验证结果成功:".$sign);//log打印保存
$this -> wxMiniOrderServer();//微信小程序订单处理业务逻辑
exit;
}else{
echo $this -> returnInfo("FAIL","签名失败");
$this -> logwx_mini("签名验证结果失败:本地加密:".$sign.':::::三方加密'.$wxSign);//log打印保存
exit;
}
}else{
echo $this -> returnInfo("FAIL","签名失败");
$this -> logwx_mini($arrayInfo['return_code']);//log打印保存
exit;
}
}
/* 微信小程序订单查询加值业务处理
* @param orderNum 订单号
*/
private function wxMiniOrderServer(){
$info = $this -> wxMiniDate;
$this->logwx_mini("wxMiniOrderServer info:".json_encode($info));
$out_trade_no=$info['out_trade_no'];
$where['orderno']=$info['out_trade_no'];
$where['type']=4;
$trade_no=$info['transaction_id']; //微信支付订单号
$data=[
'trade_no'=>$trade_no
];
$this->logwx_mini("where:".json_encode($where));
$res=handelCharge($where,$data);
if($res==0){
$this->logwx_mini("orderno:".$out_trade_no.' 订单信息不存在');
return false;
}
$this->logwx_mini("成功");
return true;
}
/* 打印log */
public function logwx_mini($msg){
file_put_contents(CMF_ROOT.'data/paylog/logwx_mini_'.date('Y-m-d').'.txt',date('Y-m-d H:i:s').' msg:'.$msg."\r\n",FILE_APPEND);
}
/* 处理支付订单 */
function handelCharge($where,$data=[]){
$orderinfo=Db::name("charge_user")->where($where)->find();
if(!$orderinfo){
return 0;
}
if($orderinfo['status']!=0){
return 1;
}
/* 更新会员虚拟币 */
$coin=$orderinfo['coin']+$orderinfo['coin_give'];
Db::name("user")->where("id='{$orderinfo['touid']}'")->setInc("coin",$coin);
/* 更新 订单状态 */
$data['status']=1;
Db::name("charge_user")->where("id='{$orderinfo['id']}'")->update($data);
return 2;
}