午夜91福利视频,午夜成人在线观看,午夜在线视频免费观看,午夜福利短视频,精品午夜成人免费视频APP

小程序模板網

微信支付服務商接入指引

發布(bu)時間:2018-08-29 08:53 所屬欄目:小程序開發教程

微信支付服務商接入指引

本文主(zhu)要針對(dui)服務商(shang)下(xia)特約商(shang)戶的小程序(xu)支(zhi)付(fu)(fu)進行講解。(掃碼支(zhi)付(fu)(fu), h5支(zhi)付(fu)(fu)大(da)致流程都差不多(duo),了解了小程序(xu)支(zhi)付(fu)(fu)能夠很快接入其他(ta)支(zhi)付(fu)(fu)類型)

說(shuo)明:本文中的支付都(dou)是指在服務(wu)商模式下

支付主體

  • 服務商:擁有支付開發能力的第三方提供商
  • 普通商戶: 擁有開發能力的商戶
  • 特約商戶:服務商下的商戶

 一(yi)個商(shang)(shang)家主體可以(yi)在(zai)不同(tong)服務(wu)(wu)商(shang)(shang)下申請特(te)約商(shang)(shang)戶(hu),每個服務(wu)(wu)商(shang)(shang)都會給(gei)商(shang)(shang)家主體在(zai)此(ci)服務(wu)(wu)商(shang)(shang)下一(yi)個特(te)約商(shang)(shang)戶(hu)號(hao)。

普通商戶申請需要花費大約(yue)(yue)300RMB,服務商申請特約(yue)(yue)商戶不(bu)需要費用。

一個商(shang)(shang)(shang)家主體可(ke)以申(shen)(shen)請 普通(tong)(tong)商(shang)(shang)(shang)戶(hu)(hu)(hu)(hu),特(te)約商(shang)(shang)(shang)戶(hu)(hu)(hu)(hu)。同一個商(shang)(shang)(shang)戶(hu)(hu)(hu)(hu)主體申(shen)(shen)請的普通(tong)(tong)商(shang)(shang)(shang)戶(hu)(hu)(hu)(hu)與在服務商(shang)(shang)(shang)下申(shen)(shen)請的特(te)約商(shang)(shang)(shang)戶(hu)(hu)(hu)(hu)號是獨(du)立的。

服務商

服(fu)務(wu)商下的特(te)(te)(te)約商戶(hu)的資(zi)金(jin)流轉不會直接(jie)(jie)經過服(fu)務(wu)商的支付賬戶(hu),最(zui)終(zhong)消費者(zhe)的資(zi)金(jin)直接(jie)(jie)和服(fu)務(wu)商下的特(te)(te)(te)約商戶(hu)進行(xing)來往,但是服(fu)務(wu)商可以查(cha)看(kan)自己(ji)下的特(te)(te)(te)約商戶(hu)資(zi)金(jin)流水。

服(fu)務(wu)商小程序(xu)開發文(wen)檔

開發支付

開發之前

申請注冊服務商,通過之后登錄微信商戶平臺,進入菜單: 服務商功能 --> 特約商戶管理 -->新增商戶(也就是申請服務商下的特約商戶)
申請如果沒有問題會在三到五天通過,之后可以在特約商戶管理
下看到(dao)服務(wu)商(shang)自己(ji)的特(te)約(yue)商(shang)戶(hu)(hu),我(wo)們在開發中需要 服務(wu)商(shang)商(shang)戶(hu)(hu)號(hao)及這里的商(shang)戶(hu)(hu)號(hao)(特(te)約(yue)商(shang)戶(hu)(hu)號(hao))

支付需要接口:微信統一下單,及提供給微信的回調接口

微信官(guan)方(fang)給的業(ye)務流程圖:

可以很清晰的理解業務(wu)流程走向。

統一下單接口

微信統一下單請求參數

統一下單請求參數封裝為(wei)我們可以處理的對象(xiang):

此處我的命(ming)名是: WechatUnifiedorderRequest

以(yi)下是我開發中(zhong)遇(yu)到一些坑,主要是由于微信(xin)官方的(de)文檔給的(de)參數很(hen)模糊,特別是小程序支付。

 


在填充好了WechatUnifiedorderRequest對象后對我們填充的值按照字典排序,連接key進行簽名,以xml格式字符向微信發起請求

  1. 我們需要(yao)對對象按(an)照字典(dian)序排(pai)序

    第一步,設所有發送或者接收到的數據為集合M,將集合M內非空參數值的參數按照參數名ASCII碼從小到大排序(字典序),使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
  2. 字典排序后的字符連接key(需要在微信商戶平臺進行配置建議使用UUID生成32位)
  3. MD5加密簽名,得到sign填充WechatUnifiedorderRequest對象
  4. WechatUnifiedorderRequest轉換為微信需要的xml類型
  5. 發起請求
  6. 得到微信統一下單的響應(是xml字符格式),解析為對象(對返回的響應封裝對象進行處理WechatUnifiedorderResponse),
  7. 對返回的對象進行驗證,通過驗證返回給小程序 需要的參數及簽名 小程序調起支付API
  8. 小程序支付成功,微信開始回調在統一下單傳給微信的回調地址
獲取下單用戶的真實IP
 /**
     * 獲取用戶真實IP
     * 如果有代理,獲取真實客戶端IP
     * @param request
     * @return
     */
    public  static  String getRealId(HttpServletRequest request){

        String xForwardedForHeader= request.getHeader("X-Forwarded-For");
        if(xForwardedForHeader == null){
            return  request.getRemoteAddr();

        }else {
            return  new StringTokenizer(xForwardedForHeader, ",").nextToken().trim();
        }

    }
按照字典序排序
 
/**
     * 使用java反射機制,動態獲取對象的屬性和參數值,排除值為null的情況,并按字典序排序
     * @param object
     * @return
     */
    public static   String getSortMap(Object object) throws  Exception{
        //1.得到屬性的名稱及值 如果為null不存入map
        Field [] fields = object.getClass().getDeclaredFields();
        Map<String,String> map = new HashMap<>();
        for(Field field : fields){
            String name = field.getName();
            /*String methodName = "get"+name.replaceFirst(name.substring(0, 1), name.substring(0, 1)
                    .toUpperCase());*/
            //通過get方法直接獲取屬性值
            field.setAccessible(true);
            Object value = field.get(object);
            if (value != null){
                map.put(name, value.toString());
            }


        }
        //排序
        Map<String, String> sortMap = new TreeMap<String,String>(
                new Comparator<String>() {

                    @Override
                    public int compare(String arg0, String arg1) {

                        return arg0.compareTo(arg1);
                    }
                });
        sortMap.putAll(map);


        StringBuilder sortFeil = new StringBuilder();
        //得到鍵值對的格式(即key1=value1&key2=value2…
        sortMap.forEach((k,v)-> {
            sortFeil.append(k+"="+v+"&");
        });
        //移除最后一個 &
        sortFeil.deleteCharAt(sortFeil.length()-1);
        return sortFeil.toString();

    }

使用字(zi)典序返回的字(zi)符連(lian)接key,使用MD5進行加密,得到sign

WechatUnifiedorderRequest轉換為微信需要的xml類型

在WechatUnifiedorderRequest對象上使用注(zhu)解

  • @xmlAccessorType @xmlAccessorType(XmlAccessType.FIELD)
  • @xmlRootElement @xmlRootElement(name ="xml") ( name = "xml : "WechatUnifiedorderReques對象轉換為xml的根名稱)
/**
 * 微信統一下單請求對象
 *
 * @Author xuelongjiang
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "xml")//xml的根元素
public class WechatUnifiedorderRequest  implements Serializable{
}
對象轉換為xml字符
引入包:import javax.xml.bind.JAXBContext

 /**
     * 對象轉換為xml
     * @param object
     * @return
     */
    public static  String objectToXml(Object object){

        StringWriter sw = new StringWriter();
        try {

            JAXBContext context = JAXBContext.newInstance(object.getClass());
            Marshaller marshaller =  context.createMarshaller();
            marshaller.marshal(object,sw);

        }catch (Exception e){
            e.printStackTrace();
            logger.error("對象解析xml出現異常,對象為"+object.toString());
        }

        return sw.toString();
    }
得到微信統一下單的響應(是xml字符格式),解析為對象

封裝對象:WechatUnifiedorderResponse 表示微(wei)信統一下單響應的對象。

請(qing)求微(wei)信統(tong)一下(xia)單(dan)返回示例(li):

<xml>
   <return_code><![CDATA[SUCCESS]]></return_code>
   <return_msg><![CDATA[OK]]></return_msg>
   <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
   <sub_appid><![CDATA[wx2421b1c4370ec11b]]></sub_appid>
   <mch_id><![CDATA[10000100]]></mch_id>
   <sub_mch_id>![CDATA[10000101]]></appid>
   <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
   <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
   <result_code><![CDATA[SUCCESS]]></result_code>
   <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
   <trade_type><![CDATA[JSAPI]]></trade_type>
</xml>

參數值用XML轉義即可,CDATA標簽用于說明數據不被XML解析器解析,在轉為對象的時候我們需要解析
<![CDATA[]]>

WechatUnifiedorderResponse對象使用注解

    • @XmlAccessorType(XmlAccessType.FIELD)
  • @XmlRootElement(name = "xml")//解析xml的根元素

以(yi)上(shang)的和WechatUnifiedorderRequest是(shi)一樣,但是(shi)由于需要解析<![CDATA[]]>,我們(men)創建CDataAdapter繼承XmlAdapter ,使用注解@XmlJavaTypeAdapter來處理(li),在WechatUnifiedorderResponse需要處理(li)<![CDATA[]]>的域上(shang)使用注解

如下:

 @XmlJavaTypeAdapter(CDataAdapter.class)// 解析<![CDATA[]]>
    private String return_code; //返回狀態碼
CDataAdapter解析<![CDATA[]]>


/**
 *
 * 注解使用, 對象與xml轉換的字段需要有 <![CDATA[]]>
 *
 * @Author xuelongjiang
 */
public class CDataAdapter extends XmlAdapter<String,String> {

    private static Logger logger = LoggerFactory.getLogger(CDataAdapter.class);

    /**
     * Do-nothing constructor for the derived classes.
     */
    protected CDataAdapter() {
        super();
    }

    /**
     * Convert a value type to a bound type.
     *
     * @param v The value to be converted. Can be null.
     * @throws Exception if there's an error during the conversion. The caller is responsible for
     *                   reporting the error to the user through {@link ValidationEventHandler}.
     */
    @Override
    public String unmarshal(String v) throws Exception {

      if("<![CDATA[]]>".equals(v)){
          return "";
      }
      String v1 = null;
      String v2 = null;

      String subStart = "<![CDATA[";
      int a = v.indexOf(subStart);
      if(a>= 0){
          v1 = v.substring(subStart.length(),v.length());

      }else {
          return v;
      }
      String subEnd = "]]>";
      int b = v1.indexOf(subEnd);
      if(b>= 0){
          v2 = v1.substring(0,b);
      }
      return v2;

    }

    /**
     * Convert a bound type to a value type.
     *
     * @param v The value to be convereted. Can be null.
     * @throws Exception if there's an error during the conversion. The caller is responsible for
     *                   reporting the error to the user through {@link ValidationEventHandler}.
     */
    @Override
    public String marshal(String v) throws Exception {

        logger.info("對象轉換xml:"+"<![CDATA["+ v +"]]>");
        return "<![CDATA["+ v +"]]>";
    }
}

到此為止,我們已經得到微(wei)信(xin)統一下單的(de)響應值了,后續的(de)處理不(bu)(bu)是很復雜。按照文檔不(bu)(bu)會(hui)有(you)很大的(de)坑。

在(zai)(zai)做微信支付的(de)(de)時候,難點(dian)是以上的(de)(de):請求參數說明(ming)模糊,在(zai)(zai)經歷幾次的(de)(de)傳(chuan)參試驗及百度谷(gu)歌之(zhi)后,才(cai)明(ming)白了參數的(de)(de)具體的(de)(de)使用,其(qi)實(shi)后續在(zai)(zai)做掃碼支付的(de)(de)時候,發現掃碼支付解釋的(de)(de)比(bi)較清楚,小程序的(de)(de)文檔確實(shi)比(bi)較坑。



易優小程序(企業(ye)版)+靈活api+前(qian)后(hou)代(dai)碼開源 碼(ma)云倉庫:
本文地址://www.jinyoudianli.com/wxmini/doc/course/24735.html 復制鏈接 如需(xu)定制請聯系易優(you)客服咨詢:

工作日 8:30-12:00 14:30-18:00
周六及(ji)部分節假(jia)日(ri)提(ti)供值(zhi)班服務(wu)

易小優
轉人工 ×