1、服务器端使用TP3.2处理(随便写在一个Controller里面)

/* 小程序报名,生成订单 */
public function make_order(){
if(IS_POST){
$data['openid'] = I('POST.openid');
$data_total = I('POST.data_total');
$data['crsNo'] = 'W'.date('YmdHis',time()).'-'.randomkeys(2);
$insertId = M('home_order','xxf_witkey_')->add($data);
if($insertId){
$this->insertID = $insertId;
$this->data_total = $data_total*100; //订单总金额,单位分
/* 调用微信【统一下单】 */
$this->pay($data_total*100,$data['openid'],$data['crsNo']);
}else{
echo $insertId;
}
//echo json_encode($re);
}
}
/* 首先在服务器端调用微信【统一下单】接口,返回prepay_id和sign签名等信息给前端,前端调用微信支付接口 */
private function Pay($total_fee,$openid,$order_id){
if(empty($total_fee)){
echo json_encode(array('state'=>0,'Msg'=>'金额有误'));exit;
}
if(empty($openid)){
echo json_encode(array('state'=>0,'Msg'=>'登录失效,请重新登录(openid参数有误)'));exit;
}
if(empty($order_id)){
echo json_encode(array('state'=>0,'Msg'=>'自定义订单有误'));exit;
}
$appid = '小程序appid';//如果是公众号 就是公众号的appid;小程序就是小程序的appid
$body = '自己填';
$mch_id = '商户账号';
$KEY = '你申请微信支付的key';
$nonce_str = randomkeys(32);//随机字符串
$notify_url = 'https://m.******.com/index.php/Home/Xiaoxxf/xiao_notify_url'; //支付完成回调地址url,不能带参数
$out_trade_no = $order_id;//商户订单号
$spbill_create_ip = $_SERVER['SERVER_ADDR'];
$trade_type = 'JSAPI';//交易类型 默认JSAPI //这里是按照顺序的 因为下面的签名是按照(字典序)顺序 排序错误 肯定出错
$post['appid'] = $appid;
$post['body'] = $body;
$post['mch_id'] = $mch_id;
$post['nonce_str'] = $nonce_str;//随机字符串
$post['notify_url'] = $notify_url;
$post['openid'] = $openid;
$post['out_trade_no'] = $out_trade_no;
$post['spbill_create_ip'] = $spbill_create_ip;//服务器终端的ip
$post['total_fee'] = intval($total_fee); //总金额 最低为一分钱 必须是整数
$post['trade_type'] = $trade_type;
$sign = $this->MakeSign($post,$KEY); //签名
$this->sign = $sign; $post_xml = '<xml>
<appid>'.$appid.'</appid>
<body>'.$body.'</body>
<mch_id>'.$mch_id.'</mch_id>
<nonce_str>'.$nonce_str.'</nonce_str>
<notify_url>'.$notify_url.'</notify_url>
<openid>'.$openid.'</openid>
<out_trade_no>'.$out_trade_no.'</out_trade_no>
<spbill_create_ip>'.$spbill_create_ip.'</spbill_create_ip>
<total_fee>'.$total_fee.'</total_fee>
<trade_type>'.$trade_type.'</trade_type>
<sign>'.$sign.'</sign>
</xml> '; //统一下单接口prepay_id
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$xml = $this->http_request($url,$post_xml); //POST方式请求http
$array = $this->xml2array($xml); //将【统一下单】api返回xml数据转换成数组,全要大写
if($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS'){
$time = time();
$tmp=''; //临时数组用于签名
$tmp['appId'] = $appid;
$tmp['nonceStr'] = $nonce_str;
$tmp['package'] = 'prepay_id='.$array['PREPAY_ID'];
$tmp['signType'] = 'MD5';
$tmp['timeStamp'] = "$time"; $data['state'] = 1;
$data['timeStamp'] = "$time"; //时间戳
$data['nonceStr'] = $nonce_str; //随机字符串
$data['signType'] = 'MD5'; //签名算法,暂支持 MD5
$data['package'] = 'prepay_id='.$array['PREPAY_ID']; //统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
$data['paySign'] = $this->MakeSign($tmp,$KEY); //签名,具体签名方案参见微信公众号支付帮助文档;
$data['out_trade_no'] = $out_trade_no; }else{
$data['state'] = 0;
$data['text'] = "错误";
$data['RETURN_CODE'] = $array['RETURN_CODE'];
$data['RETURN_MSG'] = $array['RETURN_MSG'];
}
echo json_encode($data);
} /**
* 生成签名, $KEY就是支付key
* @return 签名
*/
public function MakeSign( $params,$KEY){
//签名步骤一:按字典序排序数组参数
ksort($params);
$string = $this->ToUrlParams($params); //参数进行拼接key=value&k=v
//签名步骤二:在string后加入KEY
$string = $string . "&key=".$KEY;
//签名步骤三:MD5加密
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
}
/**
* 将参数拼接为url: key=value&key=value
* @param $params
* @return string
*/
public function ToUrlParams( $params ){
$string = '';
if( !empty($params) ){
$array = array();
foreach( $params as $key => $value ){
$array[] = $key.'='.$value;
}
$string = implode("&",$array);
}
return $string;
}
/**
* 调用接口, $data是数组参数
* @return 签名
*/
public function http_request($url,$data = null,$headers=array())
{
$curl = curl_init();
if( count($headers) >= 1 ){
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
}
curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); if (!empty($data)){
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
//获取xml里面数据,转换成array
private function xml2array($xml){
$p = xml_parser_create();
xml_parse_into_struct($p, $xml, $vals, $index);
xml_parser_free($p);
$data = "";
foreach ($index as $key=>$value) {
if($key == 'xml' || $key == 'XML') continue;
$tag = $vals[$value[0]]['tag'];
$value = $vals[$value[0]]['value'];
$data[$tag] = $value;
}
return $data;
}

/**
* 将xml转为array
* @param string $xml
* return array
*/
public function xml_to_array($xml){
if(!$xml){
return false;
}
//将XML转为array
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $data;
}

//还有就是,微信要求支付后处理微信发送的回调内容,就是告诉商户,订单交易成功了,你要发送‘我知道了’给微信。

//还有一点就是:这里就是回调url,你预支付填写的notify_url地址。废话不多说,看下面

    /* 微信支付完成,回调地址url方法  xiao_notify_url() */
public function xiao_notify_url(){
$post = post_data(); //接受POST数据XML个数
/*

function post_data(){
$receipt = $_REQUEST;
if($receipt==null){
$receipt = file_get_contents("php://input");
if($receipt == null){
$receipt = $GLOBALS['HTTP_RAW_POST_DATA'];
}
}
return $receipt;
}

*/
$post_data = $this->xml_to_array($post); //微信支付成功,返回回调地址url的数据:XML转数组Array
$postSign = $post_data['sign'];
unset($post_data['sign']); /* 微信官方提醒:
* 商户系统对于支付结果通知的内容一定要做【签名验证】,
* 并校验返回的【订单金额是否与商户侧的订单金额】一致,
* 防止数据泄漏导致出现“假通知”,造成资金损失。
*/
ksort($post_data);// 对数据进行排序
$str = $this->ToUrlParams($post_data);//对数组数据拼接成key=value字符串
$user_sign = strtoupper(md5($post_data)); //再次生成签名,与$postSign比较 $where['crsNo'] = $post_data['out_trade_no'];
$order_status = M('home_order','xxf_witkey_')->where($where)->find(); if($post_data['return_code']=='SUCCESS'&&$postSign){
/*
* 首先判断,订单是否已经更新为ok,因为微信会总共发送8次回调确认
* 其次,订单已经为ok的,直接返回SUCCESS
* 最后,订单没有为ok的,更新状态为ok,返回SUCCESS
*/
if($order_status['order_status']=='ok'){
$this->return_success();
}else{
$updata['order_status'] = 'ok';
if(M('home_order','xxf_witkey_')->where($where)->save($updata)){
$this->return_success();
}
}
}else{
echo '微信支付失败';
}
} /*
* 给微信发送确认订单金额和签名正确,SUCCESS信息 -xzz0521
*/
private function return_success(){
$return['return_code'] = 'SUCCESS';
$return['return_msg'] = 'OK';
$xml_post = '<xml>
<return_code>'.$return['return_code'].'</return_code>
<return_msg>'.$return['return_msg'].'</return_msg>
</xml>';
echo $xml_post;exit;
}

2、小程序端发起下单和支付请求:

/**
* 自定义方法,校验form数据
*/
submitForm: function (e) {    //这里是小程序wxml提交form
var that = this;
//#code ,注意这里的form数据你要校验哦。
wx.request({ url: 'https://m.******.com/index.php/Home/Xiaoxxf/make_order', header: { "Content-Type": "application/x-www-form-urlencoded" }, method: "POST", data: { openid: wx.getStorageSync('openid'), data_name: e.detail.value.data_name, data_phone: e.detail.value.data_phone, data_IDcard: e.detail.value.data_IDcard, data_num: e.detail.value.data_num, data_addr: e.detail.value.data_addr, data_remark: e.detail.value.data_remark, data_total: e.detail.value.data_num * that.data.unitPrice,a_id:that.data.a_id}, success: function (res) {
if (res.data.state==1) {
// --------- 订单生成成功,发起支付请求 ------------------
wx.requestPayment({
timeStamp: res.data.timeStamp,
nonceStr: res.data.nonceStr, //字符串随机数
package: res.data.package,
signType: res.data.signType,
paySign: res.data.paySign,
'success': function (res) {
console.log(res.errMsg); //requestPayment:ok==>调用支付成功
wx.showToast({
title: '报名成功',//这里打印出报名成功
icon: 'success',
duration: 1000
})
},
'fail': function (res) {
console.log(res.errMsg);
},
'complete': function (res) {
console.log(res.errMsg);
}
})
} else if (res.data.state == 0){
wx.showToast({
title: res.data.Msg,
icon: 'fail',
duration: 1000
})
}else{
wx.showToast({
title: '系统繁忙,请稍后重试~',
icon: 'fail',
duration: 1000
})
}
} })
}

原创:微信小程序调用【统一下单】、【支付】、【支付回调】api并处理请求的更多相关文章

  1. 微信小程序--使用云开发完成支付闭环

    微信小程序--使用云开发完成支付闭环 1.流程介绍 2. 代码实现和逻辑思想描述 云函数统一下单 对应云函数 unipay [CloudPay.unifiedOrder] 函数思路 : 调用云函数封装 ...

  2. 图解微信小程序---调用API操作步骤

    图解微信小程序---调用API操作步骤 什么是API API(Application Programming Interface,应用程序编程接口:是一些预先定义的函数,目的是提供应用程序与开发人员基 ...

  3. 微信小程序把玩(三十三)Record API

    原文:微信小程序把玩(三十三)Record API 其实这个API也挺奇葩的,录音结束后success不走,complete不走,fail也不走, 不知道是不是因为电脑测试的原因,只能等公测或者等他们 ...

  4. 微信小程序把玩(四十)animation API

    原文:微信小程序把玩(四十)animation API 动画水还是比较深的,这里只是简单介绍下小程序中动画的一些属性和注意事项,做动画前一定要整理好思路将动画一步步分解,再进行组合!这里只做引入. w ...

  5. 微信小程序把玩(四十一)canvas API

    原文:微信小程序把玩(四十一)canvas API 绘图是每个移动应用必备的技术,基本上和Android,IOS,等移动开发都是相同的,创建个上下文,给你个画布再上画,官网给的小例子都比较全了自己去看 ...

  6. 微信小程序把玩(三十七)location API

    原文:微信小程序把玩(三十七)location API location API也就分这里分两种wx.getLocation(object)获取当前位置和wx.openLocation(object) ...

  7. PHP:微信小程序调用【统一下单】【微信支付】【支付回调】API;XML转Array,Array转XML方法(通用)

    1.微信公众号.微信小程序开发过程中,第三方服务器与微信服务器数据交互,需要进行数据转换,必须用到这两个函数: 分别是xml_to_array.array_to_xml ; /** * 输出xml字符 ...

  8. java微信小程序调用支付接口(转)

    简介:微信小程序支付这里的坑还是有的,所以提醒各位在编写的一定要注意!!! 1.首先呢,你需要准备openid,appid,还有申请微信支付后要设置一个32位的密钥,需要先生成一个sign,得到pre ...

  9. java微信小程序调用支付接口

    简介:微信小程序支付这里的坑还是有的,所以提醒各位在编写的一定要注意!!! 1.首先呢,你需要准备openid,appid,还有申请微信支付后要设置一个32位的密钥,需要先生成一个sign,得到pre ...

随机推荐

  1. .net上开发winform

    c++用WinForm做界面的实现 因为笔者是以前是做C#的,对Winform情有独钟,最近想转C++,想把以前的一些Delphi转成c++,MFC我不熟而且用起来相当烦效果又丑,GTK图形库用起来太 ...

  2. JAVA nio 2 和 Path 类简介

    想要初步了解 NIO.2 API,也就是通常所说的“JSR203: More New I/O APIs for the Java Platform”,最好的切入点就是新的抽象类 java.nio.fi ...

  3. JAVA常见算法题(三十四)---计算加密之后的电话号码

    某个公司采用公用电话传递数据,数据是四位的整数,在传递过程中是加密的, 加密规则如下: 每位数字都加上5,然后用和除以10的余数代替该数字, 再将第一位和第四位交换,第二位和第三位交换. 求加密之后的 ...

  4. [JQuery] jQuery选择器ID、CLASS、标签获取对象值、属性、设置css样式

    reference : http://www.suyunyou.com/aid1657.html jQuery是继prototype之后又一个优秀的Javascrīpt框架.它是轻量级的js库(压缩后 ...

  5. 如何解决Maven速度慢

    注:oschina已失效 Maven 远程仓库 <mirror> <id>ui</id> <mirrorOf>central</mirrorOf& ...

  6. Miscellaneos:版本控制、SVN、VSS

    ylbtech-Miscellaneos:版本控制.SVN.VSS 版本控制.SVN.VSS 1.A,版本控制返回顶部 1, 版本控制(Revision control)是一种软体工程技巧,籍以在开发 ...

  7. Strings of Power

    B. Strings of Power Volodya likes listening to heavy metal and (occasionally) reading. No wonder Vol ...

  8. 第三章 JVM内存回收区域+对象存活的判断+引用类型+垃圾回收线程

    注意:本文主要参考自<深入理解Java虚拟机(第二版)> 说明:查看本文之前,推荐先知道JVM内存结构,见<第一章 JVM内存结构> 1.内存回收的区域 堆:这是GC的主要区域 ...

  9. 第一章 Java常用的并发类

    注:本系列博客主要参考于<分布式Java应用:基础与实践>,林昊 著 1.常用的并发集合类 ConcurrentHashMap:线程安全的HashMap的实现 CopyOnWriteArr ...

  10. 第一章 HttpClient的使用

    1.http协议(这一块儿有时间的话会做记录) 2.常用的两种RPC方式 基于http协议:HttpClient和JDK自己的Http操作类 基于TCP或UDP协议:mina2和netty(这一部分以 ...