在开发之中经常会使用到支付的功能,现在常用的两种支付方式是支付宝和微信。相对而言,支付宝的文档较为健全,并且配置和调用方式方式比较简单,这里就不过多的描述。
首先去微信官网网站下去下载服务端的demo:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
这里虽然是官网提供的公众号支付的demo,虽然微信支付的预下单等都可以在前端进行实现,不过官方还是建议在服务端进行处理。下载后,将其中的demo引入你的项目就好,注意的是如果是公众号的支付用到的类文件WxPay.JsApiPay.php在文件中example目录下。
接下来我们就可以进行引用了并实现。以thinkphp框架下进行调用为例(以下案例包括移动端以及公众号支付以及公众号获取openid等功能)。以下代码为了能够更容易理解,将一些类中的方法提取了出来,写的有点乱,请见谅。
/* 微信APP下支付预下单 */ public function wxAppOrder(){ //TODO:首先获取订单详情,例如传递过来订单号或订单id,获取订单的详情信息,例如将取出的数据存放入$user_order_info数组,订单中包含的商品在$user_order_product_info之中。 /* 向微信发起请求 */ vendor(\'WxpayAPI.lib.WxPay\',\'\',\'.Api.php\'); vendor(\'WxpayAPI.lib.WxPay\',\'\',\'.Data.php\');//生成数据 //统一下单输入对象 $order_info= new WxPayUnifiedOrder(); $order_info->SetOut_trade_no($user_order_info[\'orderNo\']);//商品订单号 $body=$user_order_product_info[\'productName\']; // $body=iconv(\'UTF-8\', \'ISO-8859-1\', $user_order_product_info[\'productName\']); $order_info->SetBody($body);//商品描述 $order_info->SetTrade_type(\'CNY\');//人民币 $order_info->SetTotal_fee(intval($user_order_info[\'sumPrice\']*100));//总金额,以分为单位 $order_info->SetTrade_type(\'APP\');//交易类型 $order_info->SetAppid(C(\'wxAPPID\')); $order_info->SetMch_id(C(\'wxMCHID\')); $order_info->SetNotify_url(\'你的回调地址\'); $order_info->SetSign(); //进行统一支付 $wxpay=new WxPayApi(); $order_result=$wxpay->unifiedOrder($order_info);//统一下单 if ($order_result[\'return_code\']==\'FAIL\') { $arr=array( \'resultCode\'=>\'99\', \'resultDesc\'=>$order_result[\'return_msg\'], \'resultObj\'=>array(\'\'=>\'\'), ); echo JSON($arr); exit(); } if ($order_result[\'result_code\']==\'SUCCESS\') { //预下单成功后,重新签名返回给移动端 $wxpay_result=new WxPayResults(); $timestamp=time(); $wxpay_result->SetData(\'appid\', $order_result[\'appid\']); $wxpay_result->SetData(\'partnerid\', $order_result[\'mch_id\']); $wxpay_result->SetData(\'prepayid\', $order_result[\'prepay_id\']); $wxpay_result->SetData(\'timestamp\', $timestamp); $wxpay_result->SetData(\'noncestr\', $order_result[\'nonce_str\']); $wxpay_result->SetData(\'package\', \'Sign=WXPay\'); // $wxpay_result->SetData(\'key\', C(\'wxKEY\')); //上方注释的代码是再签名中必要的一步,只是这个包含在了微信demo的类中,如果像该项目中既有app支付,又有公众号支付,最好是注释类中代码,并自己写入 $resign_result=$wxpay_result->SetSign(); //处理返回数据 $result=array( \'appid\'=>$order_result[\'appid\'],//appid \'partnerid\'=>$order_result[\'mch_id\'],//商户号 \'prepayid\'=>$order_result[\'prepay_id\'],//与支付id \'package\'=>\'Sign=WXPay\', \'noncestr\'=>$order_result[\'nonce_str\'], \'timestamp\'=>$timestamp, \'sign\'=>$resign_result, ); $arr=array( \'resultCode\'=>\'00\', \'resultDesc\'=>\'成功\', \'resultObj\'=>$result, ); echo JSON($arr); exit(); }else{ $arr=array( \'resultCode\'=>\'99\', \'resultDesc\'=>\'失败\', \'resultObj\'=>$order_result, ); echo JSON($arr); exit(); } } /* 微信支付回调函数 */ public function wxpayNotify(){ vendor(\'WxpayAPI.lib.Logwx\',\'\',\'.Log.php\');//在回调中最好是引入日志进行记录,在这里因为Log类与thinkphp中的log类重复,需要进行处理 $handle=new CLogFileHandler(\'./Public/wxlog.txt\'); $log=Logwx::Init($handle); $xml = $GLOBALS[\'HTTP_RAW_POST_DATA\'];//获取数据 vendor(\'WxpayAPI.lib.WxPay\',\'\',\'.Api.php\'); vendor(\'WxpayAPI.lib.WxPay\',\'\',\'.Data.php\'); $wxpay=new WxPayApi(); $notify=new WxPayNotifyReply(); $result=WxPayResults::Init($xml);//获取数据并转换为数组 if ($result[\'return_code\']==\'SUCCESS\' && $result[\'result_code\']==\'SUCCESS\') {//此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断 //TODO:进行数据库操作的业务逻辑处理,假设其成功与否的数据为$res if ($res) { $log->INFO(\'订单:\'.$result[\'out_trade_no\'].\'支付成功\'); $notify->SetReturn_code(\'SUCCESS\'); $notify->SetReturn_msg(\'OK\'); $notify->SetSign(); }else{ $log->ERROR(\'微信支付失败\'); $notify->SetReturn_code(\'FAIL\'); $notify->SetReturn_msg(\'客户服务器错误\'); } }else{ $log->ERROR(\'微信回调返回错误\'); $notify->SetReturn_code(\'FAIL\'); $notify->SetReturn_msg(\'微信支付失败\'); } //返回微信端 $wxpay->replyNotify($notify->ToXml()); } /* 微信公众账号下单 * 获取code等信息 * 跳转至获取信息 * */ public function wxPubOrder(){ //此流程中 $orderId=$_GET[\'orderId\']; //注意:此处如果想要回调成功,需要在微信公众平台设置回调域名 // print_r(\'Location:https://open.weixin.qq.com/connect/oauth2/authorize?appid=\'.C(\'wxAPPID\').\'&redirect_uri=\'.\'http://你的域名/Pay/getOpenid/orderId/\'.$orderId.\'&response_type=code&scope=snsapi_base&state=123#wechat_redirect\'); // exit(); header(\'Location:https://open.weixin.qq.com/connect/oauth2/authorize?appid=\'.\'*******\'.\'&redirect_uri=\'.urlencode(\'http://*****/Pay/getOpenid/orderId/\'.$orderId).\'&response_type=code&scope=snsapi_base&state=123#wechat_redirect\'); exit(); } /* 微信获取openid,跳转到微信同意下单接口 */ public function getOpenid(){ //code $code=$_GET[\'code\']; $state=$_GET[\'state\']; $orderId=$_GET[\'orderId\']; $appid=\'******\'; $appsecret=\'******\'; //获取openid $get_token_url = \'https://api.weixin.qq.com/sns/oauth2/access_token?appid=\'.$appid.\'&secret=\'.$appsecret.\'&code=\'.$code.\'&grant_type=authorization_code\'; $ch = curl_init(); curl_setopt($ch,CURLOPT_URL,$get_token_url); curl_setopt($ch,CURLOPT_HEADER,0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); $res = curl_exec($ch); curl_close($ch); $json_obj = json_decode($res,true); $openId=$json_obj[\'openid\']; // 跳转到预下单 // echo $openId;exit(); $url=\'http://******/html5/#/pay/\'.$orderId.\'openid=\'.$openId; header(\'Location:\'.$url); } /* 微信公众账号统一下单 */ public function wxOrder(){ $orderId=$_GET[\'orderId\']; $openId=$_GET[\'openId\']; if (empty($orderId)||empty($openId)) { $arr=array( \'resultCode\'=>\'66\', \'resultDesc\'=>\'缺少参数\', \'resultObj\'=>array(), ); echo JSON($arr); exit(); } //TODO:获取订单和订单商品信息,分别存储在$user_order_info中和$user_order_good_info中 if (empty($user_order_info)) { $arr=array( \'resultCode\'=>\'99\', \'resultDesc\'=>\'不存在该订单\', \'resultObj\'=>array(), ); echo JSON($arr); exit(); } /* 向微信发起请求 */ vendor(\'WxpayAPI.lib.WxPay\',\'\',\'.Api.php\'); vendor(\'WxpayAPI.lib.WxPay\',\'\',\'.Data.php\');//生成数据 // vendor(\'WxpayAPI.lib.WxPay\',\'\',\'.JsApiPay.php\'); //统一下单输入对象 $order_info= new WxPayUnifiedOrder(); $wxpay=new WxPayApi(); $order_info->SetMch_id(\'***\');//商户号 $order_info->SetAppid(\'****\');//微信号APPID//wx70a40dfa2711c4fe $order_info->SetOut_trade_no($user_order_info[\'orderNo\']);//商品订单号 $order_info->SetBody($user_order_good_info[\'productName\']);//商品描述 $order_info->SetTrade_type(\'CNY\');//人民币 $order_info->SetTotal_fee(intval($user_order_info[\'sumPrice\']*100));//总金额,以分为单位 $order_info->SetTrade_type(\'JSAPI\');//交易类型 $order_info->SetNonce_str($wxpay->getNonceStr(32)); $order_info->SetSpbill_create_ip(\'1.1.1.1\'); // $order_info->SetOpenid($user_info[\'openId\']); $order_info->SetOpenid($openId); //TODO: $order_info->SetNotify_url(\'http://****/Pay/wxpayNotify\'); $order_info->SetSign();//设置签名 //进行统一支付 $order_result=$wxpay->unifiedOrder($order_info);//统一下单 //同意下单后再加 if ($order_result[\'return_code\']==\'FAIL\') { $arr=array( \'resultCode\'=>\'99\', \'resultDesc\'=>$order_result[\'return_code\'].\':\'.$order_result[\'return_msg\'], \'resultObj\'=>array(), ); echo JSON($arr); exit(); } if ($order_result[\'result_code\']==\'SUCCESS\') { $jsapi = new WxPayJsApiPay(); $jsapi->SetAppid($order_result[\"appid\"]); $timeStamp = time(); $jsapi->SetTimeStamp(\"$timeStamp\"); $jsapi->SetNonceStr(WxPayApi::getNonceStr()); $jsapi->SetPackage(\"prepay_id=\" . $order_result[\'prepay_id\']); $jsapi->SetSignType(\"MD5\"); $jsapi->SetPaySign($jsapi->MakeSign()); $order_result = $jsapi->GetValues(); // print_r($order_result);exit(); $arr=array( \'resultCode\'=>\'00\', \'resultDesc\'=>\'成功\', \'resultObj\'=>$order_result, ); echo JSON($arr); exit(); }else{ $arr=array( \'resultCode\'=>\'99\', \'resultDesc\'=>\'失败\', \'resultObj\'=>$order_result, ); echo JSON($arr); exit(); } }
这就是一个支付的流程,在这之中会遇到很多问题,在此给出一个大多数会遇到的问题的解决方法的大概思路:
1、APP统一下单后数据返回给前端,前端调用报签名错误:首先验证自己的秘钥信息是否正确,要注意移动端和公众号的是不同的,而类拿着key又去重新签名,可以将微信官方提供的demo中的直接内部调用配置文件那里注释掉
2、在公众号获取openid的时候,显示跨域:这个解决参考YII2框架中对于\\yii::$app->response->header,中的remove方法,将报头去掉即可。
3、对于微信支付的配置,包括公众号支付配置白名单、测试目录啥的就不过多说了,请自行搜索资料
过程中肯定还遇到很多问题,这里不一一写了,如果还有问题可以在评论中留言,大家一起讨论学习,共同进步。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对免费资源网的支持。如果你想了解更多相关内容请查看下面相关链接
暂无评论内容