java-微信小程式支付程式碼分享
按照微信支付的流程來進行:
1.小程式呼叫後臺介面生成預支付訂單:
package com.stonedt.controller; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.alibaba.fastjson.JSON; import com.stonedt.entity.HosOrder; import com.stonedt.util.DateKit; import com.stonedt.util.HttpClientsKit; import com.stonedt.util.ResultUtil; import com.stonedt.util.WxUtils; public class Test { // 小程式appid public static final String appid = ""; // app 金鑰 public static final String secret = ""; // 微信支付的商戶id public static final String mch_id = ""; // 微信支付的商戶金鑰 public static final String key = ""; // 支付成功後的伺服器回撥url public static final String notify_url = ""; // 簽名方式,固定值 public static final String SIGNTYPE = "MD5"; // 交易型別,小程式支付的固定值為JSAPI public static final String trade_type = "JSAPI"; // 微信統一下單介面地址 public static final String pay_url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; // 微信統一下單介面地址 public static final String body = ""; // 交易型別 : 這裡是微信小程式支付 public static final String JSAPI = "JSAPI"; /** * 支付介面 * * @param openid 使用者唯一標識 * @return */ @RequestMapping(value = "pay", produces = "text/json;charset=UTF-8") @ResponseBody public String pay(HttpServletRequest request,String openid) { // 商戶訂單號--->訂單號唯一 //這裡用時間戳模擬 商戶訂單號 String out_trade_no = System.currentTimeMillis()+""; // 生成商戶訂單類 預支付資訊組裝 用於存入資料庫 /** * 這裡省略 ....個人生成自己的 訂單類存入資料 */ // 生成隨機串 String nonce_str = WxUtils.getRandomStringByLength(32); // 獲取使用者後臺IP地址(即使用微信小程式的手機IP) String spbill_create_ip = WxUtils.getIpAddr(request); // 組裝引數,使用者生成統一下單介面的簽名 Map<String, String> preParams = new HashMap<String, String>(); //attach可以儲存你想要在回撥中獲取的資料 String attach = out_trade_no; preParams.put("appid", appid); preParams.put("attach", attach); preParams.put("mch_id", mch_id); preParams.put("nonce_str", nonce_str); preParams.put("body", body); preParams.put("out_trade_no", out_trade_no); preParams.put("total_fee", "1");// hospital.getHosPrice() preParams.put("spbill_create_ip", spbill_create_ip);// 使用者ip preParams.put("notify_url", notify_url); preParams.put("trade_type", trade_type); preParams.put("openid", openid); // 引數按照引數名ASCII碼從小到大排序拼接 (即key1=value1&key2=value2…) Map<String, String> cleanSignArray = WxUtils.cleanSignArray(preParams); String preSign = WxUtils.createLinkString(cleanSignArray); System.out.println(preSign); // MD5運算生成簽名,這裡是第一次簽名,用於呼叫統一下單介面 --簽名時 需要全部轉換編碼 System.out.println(WxUtils.sign(preSign, key, "utf-8")); String fistSign = WxUtils.sign(preSign, key, "utf-8").toUpperCase(); // 問題商戶金鑰 // 拼接統一下單介面使用的xml資料,和params儲存的資料一樣,並且排列順序安裝a.b.c.d...的從小到大順序排列 要將上一步生成的簽名fistSign一起拼接進去 String xml = "<xml>" + "<appid><![CDATA[" + appid + "]]></appid>" + "<attach><![CDATA[" + attach + "]]></attach>" + "<body><![CDATA[" + body + "]]></body>" + "<mch_id><![CDATA[" + mch_id + "]]></mch_id>" + "<nonce_str><![CDATA[" + nonce_str + "]]></nonce_str>" + "<notify_url><![CDATA[" + notify_url + "]]></notify_url>" + "<openid><![CDATA[" + openid + "]]></openid>" + "<out_trade_no><![CDATA[" + out_trade_no + "]]></out_trade_no>" + "<spbill_create_ip><![CDATA[" + spbill_create_ip + "]]></spbill_create_ip>" + "<total_fee><![CDATA[1]]></total_fee>" + "<trade_type><![CDATA[" + JSAPI + "]]></trade_type>" + "<sign><![CDATA[" + fistSign + "]]></sign>" + "</xml>"; System.out.println("除錯模式_統一下單介面 請求XML資料:" + xml); // 呼叫統一下單介面,並接受返回的結果 ---》傳送請求時 引數需要轉換統一編碼 String result = HttpClientsKit.httpRequest(pay_url, "POST", xml); System.out.println("除錯模式_統一下單介面 返回XML資料:" + result); // 這裡解析的是xml資料 Map returnMap = WxUtils.doXMLParse(result); // 返回狀態碼 String return_code = (String) returnMap.get("return_code"); System.out.println("返回狀態碼" + return_code); // 返回給小程式端的結果 Map<String, Object> respone = new HashMap<String, Object>(); // 返回給小程式端需要的引數 Map<String, String> data = new HashMap<String, String>(); // 有返回結果 if (return_code.equals("SUCCESS")) { // 業務結果 String result_code = (String) returnMap.get("result_code"); if (!"SUCCESS".equals(result_code)) { //業務結果為fail respone.put("code", 1); String err_code_des = (String) returnMap.get("err_code_des"); respone.put("msg", err_code_des); } String prepay_id = (String) returnMap.get("prepay_id"); data.put("appId", appid); data.put("timeStamp", System.currentTimeMillis() + ""); data.put("nonceStr", "m9fil9bt27e49ag1jz54vtxffwci7e08"); data.put("package", "prepay_id=" + prepay_id); data.put("signType", "MD5"); // 拼接簽名需要的引數 // 引數按照引數名ASCII碼從小到大排序拼接 (即key1=value1&key2=value2…) Map<String, String> signTemp = WxUtils.cleanSignArray(data); // 生成簽名字串 String tempSign = WxUtils.createLinkString(signTemp); // 再次簽名,這個簽名用於小程式端呼叫wx.requesetPayment方法 String resSign = WxUtils.sign(tempSign, key, "utf-8"); data.put("paySign", resSign); respone.put("data", data); respone.put("code", 0); respone.put("msg", "success"); } else { //返回結果失敗 respone.put("code", 1); String return_msg = (String) returnMap.get("return_msg"); respone.put("msg", return_msg); } //返回的資料用於小 程式 調起支付 或 展示 錯誤資訊 return JSON.toJSONString(respone); } }
2.小程式根據後臺介面生成預支付訂單後返回的資料生成預支付訂單:
wx.requestPayment({ timeStamp: e.data.data.timeStamp, nonceStr: e.data.data.nonceStr, package: e.data.data.package, signType: 'MD5', paySign: e.data.data.paySign, success: function (event) { // success console.log(event); wx.showToast({ title: '支付成功', icon: 'success', duration: 2000 }); //處理 業務邏輯 }, fail: function (error) { // fail console.log("支付失敗") wx.showToast({ title: '支付失敗', icon: 'none', duration: 2000 }); } })
3.後臺的支付回撥:
/** * 微信通知後臺的介面 * * @param request * @return */ @RequestMapping(value = "notifi") @ResponseBody public void notifi(HttpServletRequest request, HttpServletResponse response) { /** * 當收到通知進行處理時,應檢查對應業務資料的狀態,判斷該通知是否已經處理過 * 涉及查詢資料庫 這裡省略 * 直接預設未處理 */ String resXml = ""; try { // 通過ServletInputStream讀取http請求傳入的資料 BufferedReader br = new BufferedReader( new InputStreamReader((ServletInputStream) request.getInputStream())); String temp = null; // 獲取微信返回的xml StringBuffer wxRes = new StringBuffer(); while ((temp = br.readLine()) != null) { wxRes.append(temp); } br.close(); // 處理微信返回的xml資料 String notityXml = wxRes.toString(); System.out.println("接收到微信的返回值(notityXml):" + notityXml); Map map = WxUtils.doXMLParse(notityXml); // 判斷返回結果 String returnCode = (String) map.get("return_code"); System.out.println("微信返回結果returnCode:" + returnCode); if ("SUCCESS".equals(returnCode)) { // 判斷result_code--->交易是否成功需要檢視result_code來判斷 String result_code = (String) map.get("result_code"); System.out.println("微信業務返回結果result_code:" + result_code); if ("SUCCESS".equals(result_code)) { // 成功 // 獲取簽名 String notitySign = (String) map.get("sign"); // 去除原sign map.remove("sign"); // 對微信傳回的資料進行2次簽名驗證 if (WxUtils.verify(WxUtils.createLinkString(map), notitySign, key, "utf-8")) { // 修改訂單資訊 --根據訂單號order_id /** * 修改 根據out_trade_no(我們自己的訂單號-->從微信返回的XML中獲取 然後修改資料庫的訂單記錄下面三項作為舉例) * * 支付時間(pay_time) * 支付狀態(order_status=1,支付成功) * 微信流水號(wexin_serial_num) * */ // 獲取引數 // 微信支付訂單號 String wxOrderId = (String) map.get("transaction_id"); // 商戶訂單號(我們自己的訂單號) String out_trade_no = (String) map.get("out_trade_no"); // 支付時間 String payTime = (String) map.get("time_end"); // 生成order類 HosOrder order = new HosOrder(); order.setOrderId(out_trade_no); order.setPayTime(DateKit.localDateTime2Date(payTime)); order.setOrderStatus(1); order.setWexinSerialNum(wxOrderId); // 修改訂單資訊 /** * 根據serviceImpl 修改 對應訂單資料 */ // 通知微信伺服器已經處理成功 resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> "; } else { //簽名2次驗證失敗 System.out.println("微信簽名驗證失敗------"); resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[簽名驗證失敗!]]></return_msg>" + "</xml> "; } } else { //微信業務結果失敗 String err_code_des = (String) map.get("err_code_des"); System.out.println("微信業務結果失敗,錯誤資訊err_code_des:" + err_code_des); resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[" + err_code_des + "]]></return_msg>" + "</xml> "; } } System.out.println("微信支付回撥資料結束resXml:" + resXml); // 返回結果 BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream()); out.write(resXml.getBytes()); out.flush(); out.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
4.微信小程式支付涉及工具類:
package com.stonedt.util;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Security;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
/**
* 微信支付工具類
* @author spring
*
*/
public class WxUtils {
/**
* 把字串最後拼接上 key ,再進行MD5運算,再將得到的字串所有字元轉換為大寫,得到sign
* @param text 需要簽名的字串
* @param key 金鑰
* @param inpit_charset 編碼格式
* @return
*/
public static String sign(String text,String key,String inpit_charset) {
String sign=text+"&key="+key;
return DigestUtils.md5Hex(getContentBytes(sign, inpit_charset));
}
/**
* 驗證簽名是否正確
* @param text 需要簽名的字串
* @param sign 微信的簽名結果
* @param key 金鑰
* @param input_charset 編碼格式
* @return 驗證結果
*/
public static boolean verify(String text, String sign, String key, String input_charset){
if(null==text||null==sign||null==key) {
return false;
}else {
text = text +"&key="+ key;
String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset)).toUpperCase();
System.out.println("列印微信返回的資料組裝的新的sign--mysign:"+mysign);
if (mysign.equals(sign)) {
return true;
} else {
return false;
}
}
}
/**
* 把字串按照一點編碼格式轉成位元組陣列
* @param content 字串
* @param charset 編碼方式
* @return
*/
public static byte[] getContentBytes(String content, String charset) {
if (charset == null || "".equals(charset)) {
return content.getBytes();
}
try {
return content.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("MD5簽名過程中出現錯誤,指定的編碼集不對,您目前指定的編碼集是:" + charset);
}
}
/**
* 除去陣列中的空值和簽名引數
* @param sArray 簽名引數組
* @return 去掉空值與簽名引數後的新簽名引數組
*/
public static Map<String, String> cleanSignArray(Map<String, String> signArray) {
Map<String, String> result = new HashMap<String, String>();
if (signArray == null || signArray.size() <= 0) {
return result;
}
for (String key : signArray.keySet()) {
String value = signArray.get(key);
if (value == null || value.equals("")) {
continue;
}
result.put(key, value);
}
return result;
}
/**
* 把陣列所有元素排序,並按照“引數=引數值”的模式用“&”字元拼接成字串
* @param params 需要排序並參與字元拼接的引數組
* @return 拼接後字串
*/
public static String createLinkString(Map<String, String> params) {
List<String> keys = new ArrayList<String>(params.keySet());
//Collections是一個工具類,sort是其中的靜態方法,是用來對List型別進行排序,規則是從小到大
Collections.sort(keys);
String prestr = "";
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key);
if (i == keys.size() - 1) {// 拼接時,不包括最後一個&字元
prestr = prestr + key + "=" + value;
} else {
prestr = prestr + key + "=" + value + "&";
}
}
return prestr;
}
/**
* 解析xml,返回第一級元素鍵值對。如果第一級元素有子節點,則此節點的值是子節點的xml資料。
* @param strxml
* @return
* @throws JDOMException
* @throws IOException
*/
public static Map doXMLParse(String strxml){
Map m = new HashMap();
try {
if(null == strxml || "".equals(strxml)) {
return null;
}
InputStream in = String2Inputstream(strxml);
SAXBuilder builder = new SAXBuilder();
Document doc;
doc = builder.build(in);
Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if(children.isEmpty()) {
v = e.getTextNormalize();
} else {
v = getChildrenText(children);
}
m.put(k, v);
}
//關閉流
in.close();
} catch (JDOMException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return m;
}
/**
* 獲取子結點的xml
* @param children
* @return String
*/
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if(!children.isEmpty()) {
Iterator it = children.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if(!list.isEmpty()) {
sb.append(getChildrenText(list));
}
sb.append(value);
sb.append("</" + name + ">");
}
}
return sb.toString();
}
public static InputStream String2Inputstream(String str) {
return new ByteArrayInputStream(str.getBytes());
}
/**
* 獲取真實的ip地址
* @param request
* @return
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
//多次反向代理後會有多個ip值,第一個ip才是真實ip
int index = ip.indexOf(",");
if(index != -1){
return ip.substring(0,index);
}else{
return ip;
}
}
ip = request.getHeader("X-Real-IP");
if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
return ip;
}
return request.getRemoteAddr();
}
/**
* 獲取一定長度的隨機字串,範圍0-9,a-z
* @param length:指定字串長度
* @return 一定長度的隨機字串
*/
public static String getRandomStringByLength(int length) {
String base = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
////////////////下面是解密手機號的方法
// 演算法名
public static final String KEY_NAME = "AES";
// 加解密演算法/模式/填充方式
// ECB模式只用金鑰即可對資料進行加密解密,CBC模式需要新增一個iv
public static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";
/**
* 微信 資料解密<br/>
* 對稱解密使用的演算法為 AES-128-CBC,資料採用PKCS#7填充
* 對稱解密的目標密文:encrypted=Base64_Decode(encryptData)
* 對稱解密祕鑰:key = Base64_Decode(session_key),aeskey是16位元組
* 對稱解密演算法初始向量:iv = Base64_Decode(iv),同樣是16位元組
*
* @param encrypted 目標密文
* @param session_key 會話ID
* @param iv 加密演算法的初始向量
*/
public static String wxDecrypt(String encrypted, String session_key, String iv) {
String json = null;
byte[] encrypted64 = Base64.decodeBase64(encrypted);
byte[] key64 = Base64.decodeBase64(session_key);
byte[] iv64 = Base64.decodeBase64(iv);
byte[] data;
try {
init();
json = new String(decrypt(encrypted64, key64, generateIV(iv64)));
} catch (Exception e) {
e.printStackTrace();
}
return json;
}
/**
* 初始化金鑰
*/
public static void init() throws Exception {
Security.addProvider(new BouncyCastleProvider());
KeyGenerator.getInstance(KEY_NAME).init(128);
}
/**
* 生成iv
*/
public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
// iv 為一個 16 位元組的陣列,這裡採用和 iOS 端一樣的構造方法,資料全為0
// Arrays.fill(iv, (byte) 0x00);
AlgorithmParameters params = AlgorithmParameters.getInstance(KEY_NAME);
params.init(new IvParameterSpec(iv));
return params;
}
/**
* 生成解密
*/
public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes, AlgorithmParameters iv)
throws Exception {
Key key = new SecretKeySpec(keyBytes, KEY_NAME);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 設定為解密模式
cipher.init(Cipher.DECRYPT_MODE, key, iv);
return cipher.doFinal(encryptedData);
}
}
微信返回的時間的格式問題(yyyyMMddHHmmss型別)
/**
* yyyyMMddHHmmss 轉換為Date
* @param localDateTime
*/
public static Date localDateTime2Date( String datetime){
//先把符合格式的字串時間 轉換成LocalDateTime
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
LocalDateTime ldt = LocalDateTime.parse(datetime,dtf);
//把LocalDateTime 轉換成Date
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = ldt.atZone(zoneId);//Combines this date-time with a time-zone to create a ZonedDateTime.
Date date = Date.from(zdt.toInstant());
return date;
}
傳送和接收 統一下單介面內容
/**
*
* @param requestUrl 請求地址
* @param requestMethod 請求方法
* @param outputStr 引數
*/
public static String httpRequest(String requestUrl,String requestMethod,String outputStr){
StringBuffer buffer = null;
try{
URL url = new URL(requestUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(requestMethod);
conn.setRequestProperty("Content-Type","text/xml;charset=UTF-8");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.connect();
//往伺服器端寫內容
if(null !=outputStr){
OutputStream os=conn.getOutputStream();
os.write(outputStr.getBytes("utf-8"));
os.close();
}
// 讀取伺服器端返回的內容
InputStream is = conn.getInputStream();
InputStreamReader isr = new InputStreamReader(is, "utf-8");
BufferedReader br = new BufferedReader(isr);
buffer = new StringBuffer();
String line = null;
while ((line = br.readLine()) != null) {
buffer.append(line);
}
br.close();
}catch(Exception e){
e.printStackTrace();
}
return buffer.toString();
}
最後感覺一位博主:https://blog.csdn.net/zhourenfei17/article/details/77765585
借鑑了不少,雖然有些地方出現了問題。。。。感謝!相關推薦
java-微信小程式支付程式碼分享
按照微信支付的流程來進行:1.小程式呼叫後臺介面生成預支付訂單:package com.stonedt.controller; import java.io.BufferedOutputStream; import java.io.BufferedReader; impo
java微信小程式支付完整流程
用到的jar包就不貼了 1、小程式內呼叫登入介面,獲取到使用者的openid,api參見公共api【小程式登入API】 public String getOpenId(String code) throws BusinessException { try
完整微信小程式支付程式碼+支付工具
package api.iruhua.controller; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.UnsupportedEncodi
java微信小程式支付,退款,回撥函式
package com.pay;import java.util.Date;import java.util.Map;public class test { /** * 生成統一下單 * @throws Exception */public s
java服務端微信小程式支付demo
一丶項目錄結構 demo下載地址 小程式支付demo下載 二丶實現步驟 1.在小程式中獲取使用者的登入資訊,成功後可以獲取到使用者的程式碼值 2.在使用者自己的服務端請求微信獲取使用者的OpenID介面,成功後可以電子雜誌使用者的OpenID的值 微信
微信小程式支付功能,完成整個交易的思路和程式碼
開發工具:微信開發者工具,Intellij idea 2018 框架:spring boot 交易流程圖: 下面直接上程式碼: 1.在wxml新增一個支付按鈕,點選監聽payMethod方法 <view><button bindtap='pa
JAVA之微信小程式支付退款(PKCS12證書設定與SSL請求封裝)
問題背景 話說有小程式支付就有小程式退款,退款和支付是對應的,不能憑空退。 解決方案 解決方案有點長,我們分兩個部分,一個是業務引數拼接與Sign簽名,一個是https請求/ssl請求與pkcs12證書,用到的包org.apache.httpcomponents/httpcl
微信小程式支付JAVA後臺邏輯
① 小程式前端會通過呼叫wx.login介面獲取得到登陸憑據code。這個code獲取之後5分鐘內如果再次呼叫wx.login獲取code並傳遞給②就會報錯,code非法,這個需要注意下。② 小程式將code登陸憑據和orderId訂單編號穿給後臺服務端,服務端呼叫https
【明天的地平線】專注Java相關技術:SpringBoot、Spr ingCloud、MyBatis、Docker、微服務、叢集、分散式、 Linux、Jenkins、Netty、Angular 5 、Vue 2、微信小程式、程式碼生成器等的技術研究和乾貨分
專注Java相關技術:SpringBoot、Spr ingCloud、MyBatis、Docker、微服務、叢集、分散式、 Linux、Jenkins、Netty、Angular 5 、Vue 2、微...
微信小程式支付 java
話不多說,直接開擼。 支付流程步驟: 1)首先呼叫wx.login方法獲取code,通過code獲取openid; 2)java後臺呼叫統一下單支付介面(這裡會進行第一次簽名),用來獲取prepay_id; 3)java後臺再次呼叫簽名(這裡會進行第二次簽名),並返回
微信小程式支付(Java)
相信進行過微信公眾號支付的同學對於微信小程式支付的開發上手很快,如下是微信官方對三種接入方式的對比注意坑一:發起支付必須是HTTPS流程然後我們整理下發起訂單的思路。如下是官方給的流程圖,發起支付已經做了標註。由此可見,伺服器端發起訂單需要以下五小步,我們來各個擊破。第一步:
微信小程式支付原始碼 Demo 後臺服務端程式碼
微信小程式支付繞坑指南 步驟 A:小程式向服務端傳送商品詳情、金額、openid B:服務端向微信統一下單 C:伺服器收到返回資訊二次簽名發回給小程式 D:小程式發起支付 E:服務端收到回撥 首先準備以一下資訊 小程式傳送小程式向服務端傳送商品詳情、金額、openid
java微信小程式呼叫支付介面
簡介:微信小程式支付這裡的坑還是有的,所以提醒各位在編寫的一定要注意!!! 1.首先呢,你需要準備openid,appid,還有申請微信支付後要設定一個32位的金鑰,需要先生成一個sign,得到prepay_id,然後再得到一個paySign,總之就是很墨跡,
微信小程式支付 php後臺對接完整程式碼
這個程式碼全是乾貨呀,拿過來可以直接使用。小程式在調起微信支付之前需要5個引數,這時候就需要攜帶code向後臺請求,然後後臺根據code獲取openid 再進行伺服器之間的。。。。 一、準備工作 1、小程式註冊,要以公司的以身份去註冊一個小程式,才有微信支付許可權;
微信小程式自定義分享彈窗
效果圖: 多種觸發條件使用同一個彈窗: *.js觸發處: this.setData({ isWrong:true, wrongtap:1, dialogWord:"wrong", wrongDec:"答案錯誤,是否向好友求助?" })
mqtt協議實現即時通訊-activemq nginx.支援JS,JAVA,微信小程式
MQTT協議通訊 簡述: 使用MQTT協議實現後臺推送、及時通訊等功能。本案例實現了web-js端、微信小程式端、Java client端、Java serv
微信小程式 支付
var app = getApp(); Page({ data: {}, onLoad: function (options) { // 頁面初始化 options為頁面跳轉所帶來的引數 var that = this //登陸獲取code wx.
微信小程式支付流程
使用者在微信端使用小程式,發起微信支付;(使用者) 小程式呼叫微信api(wx.login()),獲取到使用者登入憑證code(五分鐘內有效),小程式將code、需要支付的商品資訊等一起傳送給自己的商戶系統後臺;(小程式端) a、商戶系統後臺獲取到小程式傳遞過來
php微信小程式支付
<?php class WxpayModel { //介面API URL字首 const API_URL_PREFIX = 'https://api.mch.weixin.qq.com'; //下單地址URL const UN
微信小程式支付全問題解決
這幾天在做小程式的支付,沒有用官方的SDK,這裡就純用官方的文件搞一發。 * 注作者使用的PHP,不過支付流程都是這樣 開發前必讀 主要流程 小程式前端傳送求參請求 接受請求封裝 “統一下單” 獲取package 小程式接受 “統一下單” 獲取的package值帶入wx.reque