小程序開(kāi)發(fā)調(diào)用微信支付以及微信回調(diào)地址配置
首先觀看微信提供的文檔
https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1
清楚調(diào)用微信支付必須傳遞的參數(shù)
因?yàn)槲⑿盘峁┝诵〕绦騿酒鹞⑿胖Ц兜姆椒ǎ蠖酥恍枰獋鬟f對(duì)應(yīng)的參數(shù)給前端即可
首先在程序中配置申請(qǐng)的固定參數(shù)
wx.open.app_id=用戶的appid wx.open.app_secret=這是做登陸用的 weixin.pay.partner=商戶號(hào) wexxin.pay.partenerkey=商戶號(hào)秘鑰
編寫工具類實(shí)現(xiàn)對(duì)固定值的讀取
@Component //@PropertySource("classpath:application.properties") public class ConstantPropertiesUtil implements InitializingBean { //讀取配置文件并賦值 @Value("${wx.open.app_id}") private String appId; @Value("${wx.open.app_secret}") private String appSecret; @Value("{weixin.pay.partner}") private String partner; @Value("{wexxin.pay.partenerkey}") private String partenerkey; public static String WX_OPEN_APP_ID; public static String WX_OPEN_APP_SECRET; public static String PARTNER; public static String PARTNERKET; @Override public void afterPropertiesSet() throws Exception { WX_OPEN_APP_ID = appId; WX_OPEN_APP_SECRET = appSecret; PARTNER = partner; PARTNERKET = partenerkey; } }
當(dāng)用戶點(diǎn)擊購(gòu)買會(huì)生成訂單,這里代碼省略
點(diǎn)擊登陸時(shí)調(diào)用后端傳給前端需要的值
對(duì)應(yīng)微信文檔https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
可以看到,除了一些固定值,需要我們自己處理的有
簽名:根據(jù)文檔可以發(fā)現(xiàn)簽名是有一定要求的
簡(jiǎn)單來(lái)說(shuō)就將其他傳入固定值字段進(jìn)行排序拼接,在根據(jù)商家號(hào)的key進(jìn)行加密處理。
支付接口
@Autowired private WXService wxService; @GetMapping("pay") public R creatNative(Integer orderid){ try { Map map = wxService.payment(orderid); return R.ok().data(map); } catch (UnsupportedEncodingException e) { return R.error().message("支付失敗"); } }
編寫service邏輯,根據(jù)文檔進(jìn)行傳值
@Service public class WXServiceImpl implements WXService { @Autowired private OrderService orderService; @Override public Map payment(Integer orderid) throws UnsupportedEncodingException { //封裝傳遞微信地址參數(shù) Map paramMap = new HashMap(); paramMap.put("appid", ConstantPropertiesUtil.WX_OPEN_APP_ID); //公眾號(hào)id paramMap.put("mch_id", ConstantPropertiesUtil.PARTNER); //商戶號(hào) paramMap.put("nonce_str", WXPayUtil.generateNonceStr()); //隨機(jī)字符串,調(diào)用工具類 paramMap.put("out_trade_no", orderid); //訂單流水號(hào) Order order = orderService.getById(orderid); paramMap.put("total_fee", order.getPayment()); //金額 paramMap.put("spbill_create_ip", "127.0.0.1"); //終端ip paramMap.put("notify_url", "http://XXXXX/weixin/callBack");//回調(diào)地址 paramMap.put("body",order.getProductname()); //商品名稱 paramMap.put("timeStamp", WXUtil.getCurrentTimestamp()+"");//獲取當(dāng)前時(shí)間戳,單位秒 String sign = WXUtil.genSignature(ConstantPropertiesUtil.PARTNERKET,paramMap); //sing paramMap.put("sign", sign); //簽名 return paramMap; } }
簽名工具類,以及時(shí)間戳方法
public class WXUtil { public static String genSignature(String secretKey, Map<String, String> params) throws UnsupportedEncodingException { if (secretKey == null || params == null || params.size() == 0) { return ""; } // 1. 參數(shù)名按照ASCII碼表升序排序 String[] keys = params.keySet().toArray(new String[0]); Arrays.sort(keys); // 2. 按照排序拼接參數(shù)名與參數(shù)值 StringBuffer paramBuffer = new StringBuffer(); for (String key : keys) { paramBuffer.append("&"+key).append(params.get(key) == null ? "" : "="+params.get(key)); } // 3. 將secretKey拼接到最后 paramBuffer=paramBuffer.append("&key="+secretKey); String pa =paramBuffer.substring(1); // 4. MD5是128位長(zhǎng)度的摘要算法,用16進(jìn)制表示,一個(gè)十六進(jìn)制的字符能表示4個(gè)位,所以簽名后的字符串長(zhǎng)度固定為32個(gè)十六進(jìn)制字符。 return DigestUtils.md5Hex(pa.getBytes("UTF-8")).toUpperCase(); } /** * 獲取當(dāng)前時(shí)間戳,單位秒 * @return */ public static long getCurrentTimestamp() { return System.currentTimeMillis()/1000; } /** * 獲取當(dāng)前時(shí)間戳,單位毫秒 * @return */ public static long getCurrentTimestampMs() { return System.currentTimeMillis(); } }
此時(shí)即可完成支付,微信支付后,微信會(huì)給我們回調(diào)地址進(jìn)行發(fā)送信息,由此我們可以判斷支付狀態(tài)以及獲取微信支付返回的參數(shù)
回調(diào)接口
//回調(diào)接口 @RequestMapping("callBack") public String callBack(HttpServletRequest request, HttpServletResponse response) throws Exception{ System.out.println("接口已被調(diào)用"); ServletInputStream inputStream = request.getInputStream(); String notifyXml = StreamUtils.inputStream2String(inputStream, "utf-8"); System.out.println(notifyXml); // 解析返回結(jié)果 Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyXml); // 判斷支付是否成功 if ("SUCCESS".equals(notifyMap.get("result_code"))) { //編寫自己的實(shí)現(xiàn)邏輯 // 支付成功:給微信發(fā)送我已接收通知的響應(yīng) // 創(chuàng)建響應(yīng)對(duì)象 Map<String, String> returnMap = new HashMap<>(); returnMap.put("return_code", "SUCCESS"); returnMap.put("return_msg", "OK"); String returnXml = WXPayUtil.mapToXml(returnMap); response.setContentType("text/xml"); System.out.println("支付成功"); return returnXml; } } // 創(chuàng)建響應(yīng)對(duì)象:微信接收到校驗(yàn)失敗的結(jié)果后,會(huì)反復(fù)的調(diào)用當(dāng)前回調(diào)函數(shù) Map<String, String> returnMap = new HashMap<>(); returnMap.put("return_code", "FAIL"); returnMap.put("return_msg", ""); String returnXml = WXPayUtil.mapToXml(returnMap); response.setContentType("text/xml"); System.out.println("校驗(yàn)失敗"); return returnXml; }
接收輸入流轉(zhuǎn)換工具類
public class StreamUtils { private static int _buffer_size = 1024; /** * InputStream流轉(zhuǎn)換成String字符串 * @param inStream InputStream流 * @param encoding 編碼格式 * @return String字符串 */ public static String inputStream2String(InputStream inStream, String encoding){ String result = null; ByteArrayOutputStream outStream = null; try { if(inStream != null){ outStream = new ByteArrayOutputStream(); byte[] tempBytes = new byte[_buffer_size]; int count = -1; while((count = inStream.read(tempBytes, 0, _buffer_size)) != -1){ outStream.write(tempBytes, 0, count); } tempBytes = null; outStream.flush(); result = new String(outStream.toByteArray(), encoding); outStream.close(); } } catch (Exception e) { result = null; } finally { try { if(inStream != null) { inStream.close(); inStream = null; } if(outStream != null) { outStream.close(); outStream = null; } } catch (IOException e) { e.printStackTrace(); } } return result; } }
到此這篇關(guān)于小程序開(kāi)發(fā)調(diào)用微信支付以及微信回調(diào)地址配置的文章就介紹到這了,更多相關(guān)小程序 調(diào)用微信支付以及微信回調(diào)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript實(shí)現(xiàn)相同事件名稱,不同命名空間的調(diào)用方法
這篇文章主要介紹了javascript實(shí)現(xiàn)相同事件名稱,不同命名空間的調(diào)用方法,涉及javascript命名空間及事件調(diào)用的技巧,需要的朋友可以參考下2015-06-06如何利用js實(shí)時(shí)監(jiān)聽(tīng)input輸入框值的變化
在做web開(kāi)發(fā)時(shí)候很多時(shí)候都需要即時(shí)監(jiān)聽(tīng)輸入框值的變化,以便作出即時(shí)動(dòng)作去引導(dǎo)瀏覽者增強(qiáng)網(wǎng)站的用戶體驗(yàn)感,這篇文章主要給大家介紹了關(guān)于如何利用js實(shí)時(shí)監(jiān)聽(tīng)input輸入框值的變化,需要的朋友可以參考下2024-02-02javascript 響應(yīng)鍵盤特定按鍵(只響應(yīng)數(shù)字鍵)
響應(yīng)鍵盤特定按鍵(只響應(yīng)數(shù)字鍵),大家可以看看思路。2009-03-03layui 動(dòng)態(tài)設(shè)置checbox 選中狀態(tài)的例子
今天小編就為大家分享一篇layui 動(dòng)態(tài)設(shè)置checbox 選中狀態(tài)的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09微信小程序云函數(shù)添加數(shù)據(jù)到數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了微信小程序云函數(shù)添加數(shù)據(jù)到數(shù)據(jù)庫(kù)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03深入webpack打包原理及l(fā)oader和plugin的實(shí)現(xiàn)
這篇文章主要介紹了深入webpack打包原理及l(fā)oader和plugin的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05js/jquery遍歷對(duì)象和數(shù)組的方法分析【forEach,map與each方法】
這篇文章主要介紹了js/jquery遍歷對(duì)象和數(shù)組的方法,結(jié)合實(shí)例形式分析了數(shù)組遍歷的forEach,map與each方法常見(jiàn)使用技巧,需要的朋友可以參考下2019-02-02js如何準(zhǔn)確獲取當(dāng)前頁(yè)面url網(wǎng)址信息
這篇文章主要為大家介紹了js準(zhǔn)確獲取當(dāng)前頁(yè)面url網(wǎng)址信息的多種方法,包括正則法、split拆分法等,需要的朋友可以參考下2016-04-04