摘要:背景事先準(zhǔn)備工作申請一個小程序,并開通微信支付,詳細(xì)見微信小程序支付業(yè)務(wù)說明仔細(xì)查閱微信支付官方文檔,詳細(xì)見微信支付開發(fā)者文檔仔細(xì)閱讀微信支付統(tǒng)一下單接口仔細(xì)閱讀支付結(jié)果通知接口整理并在商戶平臺設(shè)置好相應(yīng)的回掉地址,比如服務(wù)端編寫兩個接口微
背景 事先準(zhǔn)備工作
申請一個小程序,并開通微信支付,詳細(xì)見:微信小程序支付業(yè)務(wù)說明
仔細(xì)查閱微信支付官方文檔,詳細(xì)見: 微信支付開發(fā)者文檔
仔細(xì)閱讀 微信支付統(tǒng)一下單接口
仔細(xì)閱讀 支付結(jié)果通知接口
整理并在商戶平臺設(shè)置好相應(yīng)的回掉地址,比如http://test.dev.com/wechat/pa...
服務(wù)端編寫兩個接口
1) 微信預(yù)支付接口,http://test.dev.com/wechat/pr... , 以商品訂單為例,此接口接受兩個參數(shù),goods_id 和 uid ,goods_id表示商品編號,uid表示用戶編號,返回參數(shù)如下
{ errcode: 200, msg: "SUCCESS", data: { status: 1, //狀態(tài),為1表示成功,其他的表示失敗 result: "success", data: { appId: "xxx", //小程序的appid timeStamp: 1545909092, //時間戳 nonceStr: "vuryhptlafvpee92pxhji6zs5jl2n0gu", //隨機(jī)串 package: "prepay_id=wx27191130962951f060bfa1323531879649", //支付的包參數(shù) signType: "MD5", //簽名方式 paySign: "B04272BB9BBDB1F52863D3B0EF580BE8" //支付簽名 } } }
2) 微信支付回調(diào)接口,http://test.dev.com/wechat/pa... ,此接口最好是get和post都設(shè)置,因?yàn)? 微信在進(jìn)行回調(diào)的時候會以post的形式進(jìn)行請求
5.建表
1) 商品訂單表(shop_goods_order),其中重要的字段有out_trade_no,out_trade_no傳遞給微信支付的支付訂單號,也是我們自己的系統(tǒng)與微信對接的訂單唯一標(biāo)識;bill_no表示微信支付的交易訂單號,這個字段只有在訂單支付成功之后進(jìn)行更新,該字段也是查詢位置支付訂單的唯一標(biāo)識,詳細(xì)的表結(jié)構(gòu)如下
CREATE TABLE `shop_goods_order` ( `id` int(10) NOT NULL AUTO_INCREMENT, `uid` int(10) DEFAULT "0" COMMENT "用戶編號", `goods_id` int(10) DEFAULT "0" COMMENT "商品編號", `out_trade_no` varchar(30) DEFAULT "" COMMENT "訂單序列號", `bill_no` varchar(30) DEFAULT "" COMMENT "支付方返回的交易訂單號", `paid_money` int(10) DEFAULT "0" COMMENT "支付的金額", `paid_integral` int(10) DEFAULT "0" COMMENT "支付的健康幣", `paid_type` varchar(15) DEFAULT "WXPAY" COMMENT "支付類型,有WXPAY和INTEGRAL等值", `paid_status` varchar(10) DEFAULT "CHECKED" COMMENT "支付狀態(tài),CHECKED表示初始狀態(tài),SUCC表示支付成功,F(xiàn)AILED表示支付失敗,REFUND表示已退款", `add_time` int(10) DEFAULT "0" COMMENT "添加時間", `paid_time` int(10) DEFAULT "0" COMMENT "支付時間", `update_time` int(10) DEFAULT "0" COMMENT "更新時間", PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;
2) 商品信息表(shop_goods_info),字段如下
CREATE TABLE `shop_goods_info` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT "主鍵", `name` varchar(100) DEFAULT "" COMMENT "商品名稱", `note` varchar(300) DEFAULT "" COMMENT "商品描述", `market_price` int(10) DEFAULT "0" COMMENT "原價", `sale_price` int(10) DEFAULT "0" COMMENT "售價", `integral` int(8) DEFAULT "0" COMMENT "健康幣", `main_thumbnail` varchar(40) DEFAULT "" COMMENT "主圖", `thumbnail1` varchar(40) DEFAULT "" COMMENT "縮略圖1", `thumbnail2` varchar(40) DEFAULT "" COMMENT "縮略圖2", `thumbnail3` varchar(40) DEFAULT "" COMMENT "縮略圖3", `thumbnail4` varchar(40) DEFAULT "" COMMENT "縮略圖4", `thumbnail5` varchar(40) DEFAULT "" COMMENT "縮略圖5", `content` text COMMENT "詳細(xì)介紹", `add_time` int(10) DEFAULT "0" COMMENT "添加時間", `update_time` int(10) DEFAULT "0" COMMENT "更新時間", `is_online` tinyint(1) DEFAULT "1" COMMENT "商品是否上線", `sort` int(4) DEFAULT "0" COMMENT "排序值,越大越靠前", PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;實(shí)現(xiàn)步驟 業(yè)務(wù)實(shí)現(xiàn)時序圖 實(shí)現(xiàn)步驟說明 客戶端
客戶端調(diào)用 微信預(yù)支付接口 獲取對應(yīng)的微信支付參數(shù)
獲取基礎(chǔ)的支付參數(shù)后,調(diào)用wx.requetPayment接口調(diào)起微信支付
用戶輸入密碼完成支付
服務(wù)端客戶端在發(fā)起支付前先往商品訂單表里面創(chuàng)建一條訂單,并生成對應(yīng)的out_trade_no參數(shù)
調(diào)用微信支付的統(tǒng)一下單接口https://api.mch.weixin.qq.com...,向微信發(fā)起支付訂單請求,統(tǒng)一下單接口文檔地址,見微信支付統(tǒng)一下單接口
支付請求結(jié)束后微信將支付結(jié)果返回給 微信支付回調(diào)接口
若支付成功,服務(wù)端將訂單的paid_status字段設(shè)置succ ,并將bill_no、paid_time、update_time更新,bill_no的值為微信支付的transaction_id;若支付失敗,將paid_status字段更新為failed,并更新update_time字段
關(guān)鍵代碼 客戶端 發(fā)起微信支付wxPay:function () { var that = this var params = { goods_id: that.data.goods_id, uid: that.data.uid, paid_type: "WXPAY" } var param = JSON.stringify(params) console.log(param) param = app.Encrypt(param) var url = app.data.API_DOMAIN + "/wechat/prepay?param=" + param wx.showModal({ title: "提示", content: "確定要微信支付購買此系列課嗎?", success(res) { if (res.confirm) { if (that.data.iswxpay == 0) { that.setData({ iswxpay: 1 }) app.httpRequest(that.data.uid, url, function (response) { var payinfo = response.data.data.data wx.requestPayment({ timeStamp: payinfo.timeStamp.toString(), nonceStr: payinfo.nonceStr, package: payinfo.package, signType: "MD5", paySign: payinfo.paySign, success(res) { wx.showToast({ title: "購買成功", icon: "success" }) that.setData({ is_paid: 1 }) that.getSeminarInfo(that.data.sid, that.data.uid) }, fail(res) { that.setData({ iswxpay: 0 }) wx.showToast({ title: "購買失敗", icon: "none" }) } }) console.log(response.data.data.data) }, function (f_res) { }, function (f_res) { }) } } else { that.setData({ iswxpay: 0 }) console.log("取消微信支付") } } }) },服務(wù)端 預(yù)支付接口關(guān)鍵代碼
1、入口方法:orderPay
/** * 微信支付的獲取支付參數(shù)的接口 * 1.先要用戶編號和支付方式獲取對應(yīng)的訂單,如果存在則取存在的,若不存在則創(chuàng)建,一種支付類型的訂單值存在一條記錄 * 2.創(chuàng)建訂單后根據(jù)out_trade_no來調(diào)用微信支付的統(tǒng)一下單接口得到微信支付的支付參數(shù) * 3.將參數(shù)返回給前端進(jìn)行支付 * 4.支付成功之后進(jìn)行回掉 */ public function orderPay($uid, $goodsId, $paidType){ $result = []; $lockKey = BusinessHelper::getPayOrderLockRedisKey(); //枷鎖是為了防止并發(fā) $this->doWithLock(function()use(&$result,$uid,$goodsId,$paidType){ error_log("$paidType ================>".$paidType); switch ($paidType){ case Constant::PAID_TYPE_MIXED : error_log("doIntegralPay ================>"); $result = $this->doMixedPay($uid,$goodsId,$paidType); error_log("integral pay result ================>".json_encode($result)); break; case Constant::PAID_TYPE_WXPAY : $result = $this->doWxaPay($uid,$goodsId,$paidType); error_log("wx pay result ================>".json_encode($result)); break; } },$lockKey,5); error_log("result ================>".json_encode($result)); return $result; }
2、微信核心支付方法:doWxaPay
/** * 通過小程序支付的邏輯 * @param $uid 用戶編號 * @param $goodsId 系列課編號 * @param $paidType 支付類型,有INTEGRAL和WXPAY兩種 * @return array */ public function doWxaPay($uid, $goodsId, $paidType){ $goodsInfo = ShopGoodsInfoService::getById($goodsId); if(!$goodsInfo){ return [ "status" => -1, "result" => "商品已經(jīng)下架或者不存在" ]; } $config = BusinessHelper::getWechatPayConfig(); $payHelper = new WechatPayHelper($config); $payContent = $this->getWxaPrepayContent($uid,$paidType,$goodsId); $params = $payHelper->prepay($payContent); error_log("param ==============>".json_encode($params)); return $params; }
3、創(chuàng)建訂單方法:createOrder
這個方法是為了建立訂單,為了保證表示每一次支付都建立一個訂單,我這邊做兩重的訂單復(fù)用,先根據(jù)訂單狀態(tài)去查詢是否有待支付的訂單,如果有在判斷這個訂單的差功能鍵時間是否已經(jīng)超過7天,如果超過七天則另外創(chuàng)建新的訂單,盡最大的進(jìn)行數(shù)據(jù)復(fù)用
/** * 創(chuàng)建和驗(yàn)證訂單,接口方法 * @param $uid 用戶編號 * @param $paidType 支付類型 * @param $goodsId 系列課編號 * @return array */ protected function createOrder($uid, $paidType, $goodsId){ $existOrder = $this->getUserGoodsOrderWithPaidType($uid,$paidType,$goodsId); if(!$existOrder){ return $this->generateOrder($uid,$paidType,$goodsId); } //驗(yàn)證7天之類訂單有效 $createTime = date("Y-m-d",$existOrder["add_time"]); $today = date("Y-m-d"); $diff = TimeHelper::getDiffBetweenTwoDays($today,$createTime); if($diff > 7){ return $this->generateOrder($uid,$paidType,$goodsId); } return $existOrder; }
4、訂單查重方法:getUserGoodsOrderWithPaidType
/** * 根據(jù)支付類型獲取用戶對應(yīng)的商品的訂單 */ public function getUserGoodsOrderWithPaidType($uid, $paidType, $goodsId){ $order = BeanHelper::convertStdClsToArr( ShopGoodsOrder::where("uid", $uid) ->where("goods_id",$goodsId) ->where("paid_type",$paidType) ->whereIn("paid_status",[Constant::PAID_STATUS_CHECKED]) ->orderBy("add_time","desc") ->first() ); return $order; }
5、生成訂單方法:
/** * 生成訂單,輔助方法 * @param $uid 用戶編號 * @param $paidType 支付類型 * @param $goodsId 系列課編號 * @return array */ public function generateOrder($uid, $paidType, $goodsId){ $goodsInfo = ShopGoodsInfoService::getById($goodsId); $priceKey = $paidType == Constant::PAID_TYPE_WXPAY ? "market_price" : "sale_price"; $price = formatArrValue($goodsInfo,$priceKey,0); $integral = $paidType == Constant::PAID_TYPE_WXPAY ? 0 : formatArrValue($goodsInfo,"integral",0); $baseMeasureUnit = 100; $insertOrderData = [ "uid" => $uid, "goods_id" => $goodsId, "out_trade_no" => BusinessHelper::generateOutTradeNo(Constant::PAID_SCENE_SHOP_GOODS_ORDER), "paid_money" => $price * $baseMeasureUnit, "paid_integral" => $integral, "paid_type" => $paidType, "paid_status" => Constant::PAID_STATUS_CHECKED, "add_time" => time(), "update_time" => time(), ]; $existOrder = BeanHelper::convertStdClsToArr($this->store($insertOrderData)); return $existOrder; }
6、生成outTradeNo方法
這個方法中的getPaidSceneMapping方法返回的是一個數(shù)組,out_trade_no方法有3個部分組成,分別是當(dāng)前時間,場景值(這個是為了保證不同的支付場景對應(yīng)的不同的業(yè)務(wù)代碼)以及10位隨機(jī)數(shù)字組成
/** * 生成第三方支付的外部訂單號 */ public static function generateOutTradeNo($paidScene = Constant::PAID_SCENE_SEMINAR_ORDER){ $prefix = date("YmdHis"); $paidSceneMap = self::getPaidSceneMapping(); $scene = formatArrValue($paidSceneMap,$paidScene,"0001"); $suffix = generateRandomNum(10); return $prefix.$scene.$suffix; } /** * 獲取支付場景的map,這個是為了區(qū)分不同的支付場景時候更新不同的業(yè)務(wù)字段,為了拓展進(jìn)行的預(yù)留 */ public static function getPaidSceneMapping(){ return [ Constant::PAID_SCENE_SEMINAR_ORDER => "0001", Constant::PAID_SCENE_SHOP_GOODS_ORDER => "0002" ]; }支付回調(diào)接口關(guān)鍵代碼
入口方法:payNotify
/** * 支付的回掉 */ public function payNotify(Request $request){ error_log("notify request param ========>"); $config = BusinessHelper::getWechatPayConfig(); $helper = new WechatPayHelper($config); $result = $helper->notify($request); return $result; }微信支付幫助類
config = $config; } /** * 預(yù)支付請求接口(POST) * 返回json的數(shù)據(jù) */ public function prepay($payContent) { $config = $this->config; $unifiedorder = [ "appid" =>$config["appid"], "mch_id" =>$config["mchid"], "nonce_str" =>self::getNonceStr(), "body" =>$payContent["body"], "out_trade_no" =>$payContent["out_trade_no"], "total_fee" =>$payContent["fee"], "spbill_create_ip"=>$_SERVER["REMOTE_ADDR"], "notify_url" =>$config["notify_url"], "trade_type" =>"JSAPI", "openid" =>$payContent["openid"] ]; error_log("config ===============>".json_encode($config)); $unifiedorder["sign"] = $this->makeSign($unifiedorder); error_log("unifine order param ===============>".json_encode($unifiedorder)); //請求數(shù)據(jù) $xmldata = $this->array2xml($unifiedorder); $url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $res = $this->request($url, $xmldata); if(!$res){ return $this->errorResult("Can"t connect the server"); } $content = $this->xml2array($res); error_log("unifine order result ===============>".json_encode($content)); if(strval($content["result_code"]) == "FAIL"){ return $this->errorResult(strval($content["return_msg"])); } if(strval($content["return_code"]) == "FAIL"){ return $this->errorResult(strval($content["return_msg"])); } //拼接小程序的接口數(shù)據(jù) $resData = [ "appId" => strval($content["appid"]), "timeStamp" => time(), "nonceStr" => $this->getNonceStr(), "package" => "prepay_id=".strval($content["prepay_id"]), "signType" => "MD5" ]; //加密簽名 $resData["paySign"] = $this->makeSign($resData); return $this->successResult($resData); } /** * @return array|bool * 微信支付回調(diào)驗(yàn)證 * 返回?cái)?shù)據(jù) */ public function notify(){ //$xml = $GLOBALS["HTTP_RAW_POST_DATA"]; error_log("wechat pay notify message ============>"); $xml = file_get_contents("php://input"); //將服務(wù)器返回的XML數(shù)據(jù)轉(zhuǎn)化為數(shù)組 $data = $this->xml2array($xml); // 保存微信服務(wù)器返回的簽名sign $dataSign = $data["sign"]; // sign不參與簽名算法 unset($data["sign"]); $sign = $this->makeSign($data); // 判斷簽名是否正確 判斷支付狀態(tài) $result = false; error_log("return data ============>".json_encode($data)); //驗(yàn)證訂單是否已經(jīng)支付,調(diào)用訂單查詢接口 $isPayment = $this->verifyPament($data); error_log("isPayment ============>".$isPayment); if($isPayment && ($data["return_code"]=="SUCCESS") && ($data["result_code"]=="SUCCESS")) { error_log("isPayment success============>"); $outTradeNo = $data["out_trade_no"]; $concurrentTime = 30; $lockKey = getCacheKey("redis_key.cache_key.zset_list.lock") . $outTradeNo; //采用并發(fā)鎖控制并發(fā) SeminarOrderService::doWithLock(function()use(&$result , $data){ $result = $data; $this->setPaidSuccess($data); },$lockKey,$concurrentTime); }else{ error_log("isPayment failed============>"); $this->setPaidFail($data); } // 返回狀態(tài)給微信服務(wù)器 if($result){ $str="踩坑點(diǎn)"; }else { $str=" "; } return $str; } /** * 支付成功 */ public function setPaidSuccess($data){ error_log("current paid data =============>".json_encode($data)); $paidType = substr($data["out_trade_no"], 14, 4); error_log("current paid type is =============>".$paidType); switch ($paidType){ case "0001" : SeminarOrderService::setOrderPaid($data); break; case "0002": ShopGoodsOrderService::setOrderPaid($data); break; } } /** * 支付失敗 */ public function setPaidFail($data){ $paidType = intval(substr($data["out_trade_no"], 14, 4)); LogHelper::info("current paid type is =============>".$paidType); switch ($paidType){ case "0001" : SeminarOrderService::setOrderPaidFailed($data); break; case "0002": ShopGoodsOrderService::setOrderPaidFailed($data); break; } } /** * 驗(yàn)證支付的問題 */ public function verifyPament($wxPayResp){ error_log("verify paymnent method=======>".json_encode($wxPayResp)); $url = "https://api.mch.weixin.qq.com/pay/orderquery"; //檢測必填參數(shù) if(!$wxPayResp["transaction_id"] && !$wxPayResp["out_trade_no"]) { error_log("訂單查詢接口中,out_trade_no、transaction_id至少填一個!"); return false; } error_log("開始查詢==============》接口"); $config = BusinessHelper::getWechatPayConfig(); error_log("post config ==============》".json_encode($config)); error_log("transaction is===============>".$wxPayResp["transaction_id"]); error_log("appid is===============>".$config["appid"]); error_log("transaction is===============>".$config["mchid"]); error_log("nonce_string is===============>".$this->getNonceStr()); $params = [ "appid" => $config["appid"], "mch_id" => $config["mchid"], "nonce_str" => $this->getNonceStr(), "transaction_id" => $wxPayResp["transaction_id"] ]; error_log("post PARAM without sign==============》"); $params["sign"] = $this->makeSign($params); error_log("post PARAM0 with sign ==============》"); $xmlData = $this->array2xml($params); $response = $this->request($url,$xmlData); if(!$response){ error_log("接口請求錯誤:"); return false; } $result = $this->xml2array($response); error_log("查詢訂單接口返回結(jié)果:".json_encode($result)); if(array_key_exists("return_code", $result) && array_key_exists("trade_state", $result) && $result["return_code"] == "SUCCESS" && $result["trade_state"] == "SUCCESS"){ return true; } return false; } //---------------------------------------------------------------用到的函數(shù)------------------------------------------------------------ /** * 錯誤返回提示 * @param string $errMsg 錯誤信息 * @param string $status 錯誤碼 * @return array json的數(shù)據(jù) */ protected function errorResult($errMsg = "error", $status = Constant::PAID_RESULT_FAILED) { return [ "status"=>$status, "result"=>"fail", "data"=>$errMsg ]; } /** * 正確返回 * @param array $data 要返回的數(shù)組 * @return array json的數(shù)據(jù) */ protected function successResult($data=[]){ return [ "status"=> Constant::PAID_RESULT_SUCCESS, "result"=>"success", "data"=>$data ]; } /** * 將一個數(shù)組轉(zhuǎn)換為 XML 結(jié)構(gòu)的字符串 * @param array $arr 要轉(zhuǎn)換的數(shù)組 * @param int $level 節(jié)點(diǎn)層級, 1 為 Root. * @return string XML 結(jié)構(gòu)的字符串 */ protected function array2xml($arr, $level = 1){ $s = $level == 1 ? " " : ""; foreach($arr as $tagname => $value) { if (is_numeric($tagname)) { $tagname = $value["TagName"]; unset($value["TagName"]); } if(!is_array($value)) { $s .= "<{$tagname}>".(!is_numeric($value) ? "" : "")."{$tagname}>"; }else { $s .= "<{$tagname}>" . $this->array2xml($value, $level + 1)."{$tagname}>"; } } $s = preg_replace("/([x01-x08x0b-x0cx0e-x1f])+/", " ", $s); return $level == 1 ? $s." " : $s; } /** * 將xml轉(zhuǎn)為array * @param string $xml xml字符串 * @return array 轉(zhuǎn)換得到的數(shù)組 */ protected function xml2array($xml) { //禁止引用外部xml實(shí)體 libxml_disable_entity_loader(true); $result= json_decode(json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA)), true); return $result; } /** * * 產(chǎn)生隨機(jī)字符串,不長于32位 * @param int $length * @return 產(chǎn)生的隨機(jī)字符串 */ protected function getNonceStr($length = 32){ $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; $str =""; for ( $i = 0; $i < $length; $i++ ) { $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1); } return $str; } /** * 生成簽名 * @return 簽名 */ protected function makeSign($data){ //獲取微信支付秘鑰 $key = $this->config["mch_secret"]; //去空 $data = array_filter($data); //簽名步驟一:按字典序排序參數(shù) ksort($data); $signParam = http_build_query($data); $signParam = urldecode($signParam); //簽名步驟二:在string后加入KEY $signContent = $signParam."&key=".$key; //簽名步驟三:MD5加密 $sign = md5($signContent); // 簽名步驟四:所有字符轉(zhuǎn)為大寫 $result=strtoupper($sign); return $result; } /** * 微信支付發(fā)起請求 */ protected function request($url, $xmldata, $second=30, $aHeader=array()){ $ch = curl_init(); //超時時間 curl_setopt($ch,CURLOPT_TIMEOUT,$second); curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1); //這里設(shè)置代理,如果有的話 //curl_setopt($ch,CURLOPT_PROXY, "10.206.30.98"); //curl_setopt($ch,CURLOPT_PROXYPORT, 8080); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false); if( count($aHeader) >= 1 ){ curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader); } curl_setopt($ch,CURLOPT_POST, 1); curl_setopt($ch,CURLOPT_POSTFIELDS,$xmldata); $data = curl_exec($ch); if($data){ curl_close($ch); return $data; } else { $error = curl_errno($ch); echo "call faild, errorCode:$error "; curl_close($ch); return false; } } }
1、支付回調(diào)接口http://test.dev.com/wechat/pa... 一定要設(shè)置成get、post都能訪問,我當(dāng)初只設(shè)置了get請求可以訪問,浪費(fèi)了好多時間進(jìn)行排查,而微信回調(diào)的數(shù)據(jù)基本都是以post形式進(jìn)行調(diào)用的
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/29871.html
摘要:目前支持哪些平臺的搬家目前對外開放版本釋放了微信小程序轉(zhuǎn)支付寶小程序的功能,這也是我們在調(diào)研中發(fā)現(xiàn)需求最多的。從筆者的了解來看,微信小程序框架原理更接近于,而支付寶小程序更接近于。 原文地址: https://ant-move.github.io/we... 螞蟻搬家工具(Antmove)是一個小程序開發(fā)輔助工具,致力于解決小程序跨平臺開發(fā)的難題,借助于 Antmove,你只需要編寫...
摘要:背景最近項(xiàng)目需要上線支付寶小程序,同時需要走用戶的授權(quán)流程完成用戶信息的存儲,以前做過微信小程序的開發(fā),本以為實(shí)現(xiàn)授權(quán)的過程是很簡單的事情,但是再實(shí)現(xiàn)的過程中還是遇到了不少的坑,因此記錄一下實(shí)現(xiàn)的過程學(xué)到的知識支付寶開放接口的調(diào)用模式以及實(shí) 背景 最近項(xiàng)目需要上線支付寶小程序,同時需要走用戶的授權(quán)流程完成用戶信息的存儲,以前做過微信小程序的開發(fā),本以為實(shí)現(xiàn)授權(quán)的過程是很簡單的事情,但是...
摘要:按著我的步驟一步一步操作,你就可以成功的到這個微信支付技能包。原文鏈接手把手教你實(shí)現(xiàn)小程序微信支付由于自己本身就是開發(fā)的,所以只涉及到微信支付的開發(fā)。我將會一步一步的記錄如何實(shí)現(xiàn)微信支付的。第一步先上微信支付開發(fā)文檔境內(nèi)普通商戶里面下載與。 這是我自己研究了兩天的微信支付整理得的開發(fā)筆記,然后在這里分享給大家,讓大家快速上手微信支付。 按著我的步驟一步一步操作,你就可以成功的get到這...
摘要:這幾天在做小程序的支付,沒有用官方的,這里就純用官方的文檔搞一發(fā)。 這幾天在做小程序的支付,沒有用官方的SDK,這里就純用官方的文檔搞一發(fā)。 * 注作者使用的PHP,不過支付流程都是這樣 開發(fā)前必讀 主要流程 小程序前端發(fā)送求參請求 接受請求封裝 統(tǒng)一下單 獲取package 小程序接受 統(tǒng)一下單 獲取的package值帶入wx.requestPayment發(fā)起支付請求 準(zhǔn)備...
閱讀 1378·2021-11-24 09:38
閱讀 2086·2021-09-22 15:17
閱讀 2340·2021-09-04 16:41
閱讀 3452·2019-08-30 15:56
閱讀 3511·2019-08-29 17:19
閱讀 1939·2019-08-28 18:09
閱讀 1249·2019-08-26 13:35
閱讀 1711·2019-08-23 17:52