一、遇到的問題
-
商戶號該產(chǎn)品權(quán)限未開通,請前往商戶平臺>產(chǎn)品中心檢查后重試
2.簽名錯誤
3.已經(jīng)調(diào)起微信統(tǒng)一下單接口,可以拿到預(yù)支付ID,但是前端支付的時候出現(xiàn) 支付驗(yàn)證簽名失敗
網(wǎng)上的問題基本上就是這三類下面說解決方案。
第一個問題:商戶號的問題,微信app支付與微信小程序支付的商戶號不同,微信app內(nèi)支付與微信開放平臺內(nèi)的商戶號綁定,微信小程序支付是與微信公眾平臺內(nèi)的商戶號綁定。
第二個問題:簽名錯誤, 第一次簽名需要的appid mchid key 分別對應(yīng)的是小程序的appid、微信公眾平臺綁定的商戶號、以及商戶平臺的密鑰(重要的事情說三遍:商戶平臺的!商戶平臺的!商戶平臺的!)。
這里重點(diǎn)說下商戶平臺的密鑰(當(dāng)時就是因?yàn)槊荑€的問題耽誤了不少時間):具體請看圖(商戶平臺--->賬戶中心--->API安全---->設(shè)置密鑰)
第三個問題:支付驗(yàn)證簽名失敗 這個就得需要嚴(yán)格執(zhí)行小程序支付文檔中的生成簽名的規(guī)則。參數(shù)字段大小寫、順序一定要對(切記,切記,切記)
如果能把以上都注意到了,那基本上沒什么問題了。下面是我自己寫的demo供大家參考,有什么問題可以留言。
二、demo 事例
1.下載商戶的證書(在問題2的截圖中已經(jīng)展示下載的位置)放在resources下的cert目錄下(cert目錄需要自己手動建)
2.實(shí)現(xiàn)微信的 WXPayConfig接口
-
1 package com.ieou.franky.payCenter.common; 2 3 import com.github.wxpay.sdk.WXPayConfig; 4 import org.apache.commons.io.IOUtils; 5 6 import java.io.ByteArrayInputStream; 7 import java.io.InputStream; 8 9 public class MiniprogramConfig implements WXPayConfig{ 10 11 private byte[] certData; 12 13 public MiniprogramConfig() throws Exception { 14 InputStream certStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("cert/miniProgram/apiclient_cert.p12"); 15 this.certData = IOUtils.toByteArray(certStream); 16 certStream.close(); 17 } 18 19 @Override 20 public String getAppID() { 21 return "wx6db448a73f8a6666"; 22 } //小程序appid 23 24 @Override 25 public String getMchID() { 26 return "1500669999"; 27 } //商戶號 28 29 /** 商戶平臺-賬戶中心-API安全中的密鑰 */ 30 @Override 31 public String getKey() { 32 return "1add1a30ac87aa77yyy2db72f57a237577777"; 33 } 34 35 @Override 36 public InputStream getCertStream() { 37 return new ByteArrayInputStream(this.certData); 38 } 39 40 @Override 41 public int getHttpConnectTimeoutMs() { 42 return 0; 43 } 44 45 @Override 46 public int getHttpReadTimeoutMs() { 47 return 0; 48 } 49 }
3.調(diào)用微信統(tǒng)一下單接口并且實(shí)現(xiàn)簽名
-
1 private Map<String, String> createMiniProgramTradePay(WxpayTradeAppPayModel model,String notifyUrl) throws Exception { 2 MiniprogramConfig config = new MiniprogramConfig(); 3 4 WXPay wxpay = new WXPay(config); 5 6 Map<String, String> data = new HashMap<>(); 7 data.put("appid",config.getAppID()); 8 data.put("mch_id",config.getMchID()); 9 data.put("body",model.getBody()); 10 data.put("out_trade_no", model.getOutTradeNo()); 11 data.put("device_info", ""); 12 data.put("fee_type", "CNY"); 13 data.put("total_fee", model.getTotalFee()); 14 data.put("spbill_create_ip", "127.0.0.1"); 15 data.put("notify_url", notifyUrl); 16 data.put("trade_type", "JSAPI"); 17 data.put("openid",model.getOpenId()); 18 // data.put("nonce_str","1add1a30ac87aa2db72f57a2375d8fec"); 19 String sign = WXPayUtil.generateSignature(data, config.getKey()); 20 data.put("sign",sign); 21 22 Map<String, String> resp = wxpay.unifiedOrder(data); 23 if ("SUCCESS".equals(resp.get("return_code"))) { 24 //再次簽名 25 /** 重要的事情說三遍 小程序支付 所有的字段必須大寫 駝峰模式 嚴(yán)格按照小程序支付文檔 26 *https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=3# 27 * ******* 我當(dāng)初就因?yàn)閠imeStamp中S沒大寫弄了3個小時 ********** 28 * */ 29 Map<String, String> reData = new HashMap<>(); 30 reData.put("appId", config.getAppID()); 31 reData.put("nonceStr", resp.get("nonce_str")); 32 String newPackage = "prepay_id=" + resp.get("prepay_id"); 33 reData.put("package", newPackage); 34 reData.put("signType","MD5"); 35 reData.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); 36 37 String newSign = WXPayUtil.generateSignature(reData, config.getKey()); 38 resp.put("paySign",newSign); 39 resp.put("timeStamp", reData.get("timeStamp")); 40 return resp; 41 } else { 42 throw new FrankyErrorException(resp.get("return_msg")); 43 } 44 45 }
說明:這里只是說明小程序支付與微信app內(nèi)支付的不同和遇到的問題,有關(guān)里面用到微信的SDK,請看上一篇文章。
到這一步j(luò)ava 后端代碼就差不多了,前端拿到返回的字段調(diào)起支付接口。