按照微信支付的流程来进行:
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);